diff --git a/gtests/net/packetdrill/contrib/packetdrill.el b/gtests/net/packetdrill/contrib/packetdrill.el
index 7aa999eefd58a9f20c1144b8f2b36627e58b9b13..ba735c72923e7352964e0ce0d00274cb69ee1741 100644
--- a/gtests/net/packetdrill/contrib/packetdrill.el
+++ b/gtests/net/packetdrill/contrib/packetdrill.el
@@ -1,4 +1,4 @@
-(setq packetdrill-keywords '("sa_family" "sin_port" "sin_addr" "msg_name" "msg_iov" "msg_flags" "fd" "events" "revents" "htons" "icmp" "sctp" "udp" "udplite" "inet_addr" "ack" "eol" "ecr" "mss" "mtu" "nop" "sack" "sackOK" "TS" "FO" "LS" "gcn" "minRTO" "val" "win" "wscale" "ect01" "ect0" "ect1" "noecn" "ce" "pro" "onoff" "linger" "srto_initial" "srto_max" "srto_min" "sinit_num_ostreams" "sinit_max_instreams" "sinit_max_attempts" "sinit_max_init_timeo" "assoc_value" "sack_delay" "sack_freq" "sstat_state" "sstat_rwnd" "sstat_unackdata" "sstat_penddata" "sstat_instrms" "sstat_outstrms" "sstat_fragmentation_point" "sstat_primary"))
+(setq packetdrill-keywords '("sa_family" "sin_port" "sin_addr" "msg_name" "msg_iov" "msg_flags" "fd" "events" "revents" "htons" "icmp" "sctp" "udp" "udplite" "inet_addr" "ack" "eol" "ecr" "mss" "mtu" "nop" "sack" "sackOK" "TS" "FO" "LS" "gcn" "minRTO" "val" "win" "wscale" "ect01" "ect0" "ect1" "noecn" "ce" "pro" "onoff" "linger" "srto_initial" "srto_max" "srto_min" "sinit_num_ostreams" "sinit_max_instreams" "sinit_max_attempts" "sinit_max_init_timeo" "assoc_value" "sack_delay" "sack_freq" "sstat_state" "sstat_rwnd" "sstat_unackdata" "sstat_penddata" "sstat_instrms" "sstat_outstrms" "sstat_fragmentation_point" "sstat_primary" "spp_address" "spp_hbinterval" "spp_pathmaxrxt" "spp_pathmtu" "spinfo_state" "spinfo_cwnd" "spinfo_srtt" "spinfo_rto" "spinfo_mtu"))
 
 (setq packetdrill-constants '("AF_INET" "AF_INET6" "PF_INET" "PF_INET6" "SOCK_STREAM" "SOCK_DGRAM" "IPPROTO_IP" "IPPROTO_IPV6" "IPPROTO_ICMP" "IPPROTO_SCTP" "IPPROTO_TCP" "IPPROTO_UDP" "IPPROTO_UDPLITE" "SOL_SOCKET" "SOL_IP" "SOL_IPV6" "SOL_SCTP" "SOL_TCP" "SOL_UDP" "SO_ACCEPTCONN" "SO_ATTACH_FILTER" "SO_BINDTODEVICE" "SO_BROADCAST" "SO_BSDCOMPAT" "SO_DEBUG" "SO_DETACH_FILTER" "SO_DONTROUTE" "SO_ERROR" "SO_KEEPALIVE" "SO_LINGER" "SO_NO_CHECK" "SO_OOBINLINE" "SO_PASSCRED" "SO_PEERCRED" "SO_PEERNAME" "SO_PEERSEC" "SO_PRIORITY" "SO_RCVBUF" "SO_RCVLOWAT" "SO_RCVTIMEO" "SO_REUSEADDR" "SO_REUSEPORT" "SO_SECURITY_AUTHENTICATION" "SO_SECURITY_ENCRYPTION_NETWORK" "SO_SECURITY_ENCRYPTION_TRANSPORT" "SO_SNDBUF" "SO_SNDLOWAT" "SO_SNDTIMEO" "SO_TIMESTAMP" "SO_TYPE" "IP_TOS" "IP_MTU_DISCOVER" "IP_PMTUDISC_WANT" "IP_PMTUDISC_DONT" "IP_PMTUDISC_DO" "IP_PMTUDISC_PROBE" "IP_MTU" "IPV6_MTU" "SCTP_RTOINFO" "SCTP_INITMSG" "SCTP_NODELAY" "SCTP_MAXSEG" "SCTP_DELAYED_SACK" "SCTP_MAX_BURST" "TCP_NODELAY" "TCP_MAXSEG" "TCP_CORK" "TCP_KEEPIDLE" "TCP_KEEPINTVL" "TCP_KEEPCNT" "TCP_SYNCNT" "TCP_LINGER2" "TCP_DEFER_ACCEPT" "TCP_WINDOW_CLAMP" "TCP_INFO" "TCP_QUICKACK" "TCP_CONGESTION" "TCP_MD5SIG" "TCP_COOKIE_TRANSACTIONS" "TCP_THIN_LINEAR_TIMEOUTS" "TCP_THIN_DUPACK" "TCP_USER_TIMEOUT" "TCP_MIN_RTO" "TCP_INFO_EXT" "TCP_CWND" "TCP_XMIT_COMPL_SEQ" "TCP_CWND_CLAMP" "TCP_SAVE_SYN" "TCP_SAVED_SYN" "TCP_FASTOPEN" "TCP_MULTIPLE_CONNECTIONS" "UDPLITE_RECV_CSCOV" "UDPLITE_SEND_CSCOV" "O_RDONLY" "O_WRONLY" "O_RDWR" "O_ACCMODE" "O_CREAT" "O_EXCL" "O_NOCTTY" "O_TRUNC" "O_APPEND" "O_NONBLOCK" "F_DUPFD" "F_GETFD" "F_SETFD" "F_GETFL" "F_SETFL" "F_GETLK" "F_SETLK" "F_SETLKW" "F_GETOWN" "F_SETOWN" "F_SETSIG" "F_GETSIG" "F_GETOWN" "F_SETOWN" "F_SETLK" "F_SETLKW" "F_GETLK" "F_SETLK64" "F_SETLKW64" "F_GETLK64" "F_SETLEASE" "F_GETLEASE" "F_NOTIFY" "F_DUPFD_CLOEXEC" "FD_CLOEXEC" "LOCK_SH" "LOCK_EX" "LOCK_NB" "LOCK_UN" "F_RDLCK" "F_WRLCK" "F_UNLCK" "F_EXLCK" "F_SHLCK" "SEEK_SET" "SEEK_CUR" "SEEK_END" "MSG_OOB" "MSG_DONTROUTE" "MSG_PEEK" "MSG_CTRUNC" "MSG_PROXY" "MSG_EOR" "MSG_WAITALL" "MSG_TRUNC" "MSG_CTRUNC" "MSG_ERRQUEUE" "MSG_DONTWAIT" "MSG_CONFIRM" "MSG_FIN" "MSG_SYN" "MSG_RST" "MSG_NOSIGNAL" "MSG_MORE" "MSG_CMSG_CLOEXEC" "MSG_FASTOPEN" "SIOCINQ" "FIONREAD" "POLLIN" "POLLPRI" "POLLOUT" "POLLRDNORM" "POLLRDBAND" "POLLWRNORM" "POLLWRBAND" "POLLMSG" "POLLREMOVE" "POLLRDHUP" "POLLERR" "POLLHUP" "POLLNVAL" "EPERM" "ENOENT" "ESRCH" "EINTR" "EIO" "ENXIO" "E2BIG" "ENOEXEC" "EBADF" "ECHILD" "EAGAIN" "ENOMEM" "EACCES" "EFAULT" "ENOTBLK" "EBUSY" "EEXIST" "EXDEV" "ENODEV" "ENOTDIR" "EISDIR" "EINVAL" "ENFILE" "EMFILE" "ENOTTY" "ETXTBSY" "EFBIG" "ENOSPC" "ESPIPE" "EROFS" "EMLINK" "EPIPE" "EDOM" "ERANGE" "EDEADLK" "ENAMETOOLONG" "ENOLCK" "ENOSYS" "ENOTEMPTY" "ELOOP" "EWOULDBLOCK" "ENOMSG" "EIDRM" "ECHRNG" "EL2NSYNC" "EL3HLT" "EL3RST" "ELNRNG" "EUNATCH" "ENOCSI" "EL2HLT" "EBADE" "EBADR" "EXFULL" "ENOANO" "EBADRQC" "EBADSLT" "EDEADLOCK" "EBFONT" "ENOSTR" "ENODATA" "ETIME" "ENOSR" "ENONET" "ENOPKG" "EREMOTE" "ENOLINK" "EADV" "ESRMNT" "ECOMM" "EPROTO" "EMULTIHOP" "EDOTDOT" "EBADMSG" "EOVERFLOW" "ENOTUNIQ" "EBADFD" "EREMCHG" "ELIBACC" "ELIBBAD" "ELIBSCN" "ELIBMAX" "ELIBEXEC" "EILSEQ" "ERESTART" "ESTRPIPE" "EUSERS" "ENOTSOCK" "EDESTADDRREQ" "EMSGSIZE" "EPROTOTYPE" "ENOPROTOOPT" "EPROTONOSUPPORT" "ESOCKTNOSUPPORT" "EOPNOTSUPP" "EPFNOSUPPORT" "EAFNOSUPPORT" "EADDRINUSE" "EADDRNOTAVAIL" "ENETDOWN" "ENETUNREACH" "ENETRESET" "ECONNABORTED" "ECONNRESET" "ENOBUFS" "EISCONN" "ENOTCONN" "ESHUTDOWN" "ETOOMANYREFS" "ETIMEDOUT" "ECONNREFUSED" "EHOSTDOWN" "EHOSTUNREACH" "EALREADY" "EINPROGRESS" "ESTALE" "EUCLEAN" "ENOTNAM" "ENAVAIL" "EISNAM" "EREMOTEIO" "EDQUOT" "ENOMEDIUM" "EMEDIUMTYPE" "ECANCELED" "ENOKEY" "EKEYEXPIRED" "EKEYREVOKED" "EKEYREJECTED" "EOWNERDEAD" "ENOTRECOVERABLE" "ERFKILL" "POLLIN" "POLLPRI" "POLLOUT" "POLLRDNORM" "POLLRDBAND" "POLLWRNORM" "POLLWRBAND" "POLLMSG" "POLLREMOVE" "POLLRDHUP" "POLLERR" "POLLHUP" "POLLNVAL"))
 
diff --git a/gtests/net/packetdrill/contrib/packetdrill.plist b/gtests/net/packetdrill/contrib/packetdrill.plist
index 978645f5e4749df1b8ccd89313b401f5d4fcabae..59a083bd6204ce63bed7d2bcda0aef49a7e5300e 100644
--- a/gtests/net/packetdrill/contrib/packetdrill.plist
+++ b/gtests/net/packetdrill/contrib/packetdrill.plist
@@ -80,6 +80,14 @@
 		<string>sstat_outstrms</string>
 		<string>sstat_fragmentation_point</string>
 		<string>sstat_primary</string>
+		<string>spinfo_state</string>
+		<string>spinfo_cwnd</string>
+		<string>spinfo_srtt</string>
+		<string>spinfo_rto</string>
+		<string>spinfo_mtu</string>
+		<string>spp_address</string>
+		<string>spp_hbinterval</string>
+		<string>spp_pathmaxrxt</string>
 	</array>
 	<key>BBLMPredefinedNameList</key>
 	<array>
diff --git a/gtests/net/packetdrill/contrib/packetdrill.vim b/gtests/net/packetdrill/contrib/packetdrill.vim
index 7401ffd4f038f6a98f2b6499feba12ddc879ac61..6c51f243f9094267c0e3373d25d88f7dab55226c 100644
--- a/gtests/net/packetdrill/contrib/packetdrill.vim
+++ b/gtests/net/packetdrill/contrib/packetdrill.vim
@@ -11,7 +11,7 @@ endif
 let s:cpo_save = &cpo
 set cpo&vim
 
-syn keyword     pKeyword        sa_family sin_port sin_addr msg_name msg_iov msg_flags fd events revents htons icmp sctp udp udplite inet_addr ack eol ecr mss mtu nop sack sackOK TS FO LS gcn minRTO val win wscale ect01 ect0 ect1 noecn ce pro onoff linger srto_initial srto_max srto_min sinit_num_ostreams sinit_max_instreams sinit_max_attempts sinit_max_init_timeo assoc_value sack_delay sack_freq sstat_state sstat_rwnd sstat_unackdata sstat_penddata sstat_instrms sstat_outstrms sstat_fragmentation_point sstat_primary
+syn keyword     pKeyword        sa_family sin_port sin_addr msg_name msg_iov msg_flags fd events revents htons icmp sctp udp udplite inet_addr ack eol ecr mss mtu nop sack sackOK TS FO LS gcn minRTO val win wscale ect01 ect0 ect1 noecn ce pro onoff linger srto_initial srto_max srto_min sinit_num_ostreams sinit_max_instreams sinit_max_attempts sinit_max_init_timeo assoc_value sack_delay sack_freq sstat_state sstat_rwnd sstat_unackdata sstat_penddata sstat_instrms sstat_outstrms sstat_fragmentation_point sstat_primary spp_address spp_hbinterval spp_pathmaxrxt spinfo_state spinfo_cwnd spinfo_srtt spinfo_rto spinfo_mtu spp_pathmtu
 syn keyword     pConstant       AF_INET AF_INET6 PF_INET PF_INET6 SOCK_STREAM SOCK_DGRAM IPPROTO_IP IPPROTO_IPV6 IPPROTO_ICMP IPPROTO_SCTP IPPROTO_TCP IPPROTO_UDP IPPROTO_UDPLITE SOL_SOCKET SOL_IP SOL_IPV6 SOL_SCTP SOL_TCP SOL_UDP SOL_UDPLITE SO_ACCEPTCONN SO_ATTACH_FILTER SO_BINDTODEVICE SO_BROADCAST SO_BSDCOMPAT SO_DEBUG SO_DETACH_FILTER SO_DONTROUTE SO_ERROR SO_KEEPALIVE SO_LINGER SO_NO_CHECK SO_OOBINLINE SO_PASSCRED SO_PEERCRED SO_PEERNAME SO_PEERSEC SO_PRIORITY SO_RCVBUF SO_RCVLOWAT SO_RCVTIMEO SO_REUSEADDR SO_REUSEPORT SO_SECURITY_AUTHENTICATION SO_SECURITY_ENCRYPTION_NETWORK SO_SECURITY_ENCRYPTION_TRANSPORT SO_SNDBUF SO_SNDLOWAT SO_SNDTIMEO SO_TIMESTAMP SO_TYPE IP_TOS IP_MTU_DISCOVER IP_PMTUDISC_WANT IP_PMTUDISC_DONT IP_PMTUDISC_DO IP_PMTUDISC_PROBE IP_MTU IPV6_MTU SCTP_RTOINFO SCTP_INITMSG SCTP_NODELAY SCTP_MAXSEG SCTP_DELAYED_SACK SCTP_MAX_BURST TCP_NODELAY TCP_MAXSEG TCP_CORK TCP_KEEPIDLE TCP_KEEPINTVL TCP_KEEPCNT TCP_SYNCNT TCP_LINGER2 TCP_DEFER_ACCEPT TCP_WINDOW_CLAMP TCP_INFO TCP_QUICKACK TCP_CONGESTION TCP_MD5SIG TCP_COOKIE_TRANSACTIONS TCP_THIN_LINEAR_TIMEOUTS TCP_THIN_DUPACK TCP_USER_TIMEOUT TCP_MIN_RTO TCP_INFO_EXT TCP_CWND TCP_XMIT_COMPL_SEQ TCP_CWND_CLAMP TCP_SAVE_SYN TCP_SAVED_SYN TCP_FASTOPEN TCP_MULTIPLE_CONNECTIONS UDPLITE_RECV_CSCOV UDPLITE_SEND_CSCOV
 syn keyword     pConstant       O_RDONLY O_WRONLY O_RDWR O_ACCMODE O_CREAT O_EXCL O_NOCTTY O_TRUNC O_APPEND O_NONBLOCK F_DUPFD F_GETFD F_SETFD F_GETFL F_SETFL F_GETLK F_SETLK F_SETLKW F_GETOWN F_SETOWN F_SETSIG F_GETSIG F_GETOWN F_SETOWN F_SETLK F_SETLKW F_GETLK F_SETLK64 F_SETLKW64 F_GETLK64 F_SETLEASE F_GETLEASE F_NOTIFY F_DUPFD_CLOEXEC FD_CLOEXEC LOCK_SH LOCK_EX LOCK_NB LOCK_UN F_RDLCK F_WRLCK F_UNLCK F_EXLCK F_SHLCK SEEK_SET SEEK_CUR SEEK_END MSG_OOB MSG_DONTROUTE MSG_PEEK MSG_CTRUNC MSG_PROXY MSG_EOR MSG_WAITALL MSG_TRUNC MSG_CTRUNC MSG_ERRQUEUE MSG_DONTWAIT MSG_CONFIRM MSG_FIN MSG_SYN MSG_RST MSG_NOSIGNAL MSG_MORE MSG_CMSG_CLOEXEC MSG_FASTOPEN SIOCINQ FIONREAD POLLIN POLLPRI POLLOUT POLLRDNORM POLLRDBAND POLLWRNORM POLLWRBAND POLLMSG POLLREMOVE POLLRDHUP POLLERR POLLHUP POLLNVAL EPERM ENOENT ESRCH EINTR EIO ENXIO E2BIG ENOEXEC EBADF ECHILD EAGAIN ENOMEM EACCES EFAULT ENOTBLK EBUSY EEXIST EXDEV ENODEV ENOTDIR EISDIR EINVAL ENFILE EMFILE ENOTTY ETXTBSY EFBIG ENOSPC ESPIPE EROFS EMLINK EPIPE EDOM ERANGE EDEADLK ENAMETOOLONG ENOLCK ENOSYS ENOTEMPTY ELOOP EWOULDBLOCK ENOMSG EIDRM ECHRNG EL2NSYNC EL3HLT EL3RST ELNRNG EUNATCH ENOCSI EL2HLT EBADE EBADR EXFULL ENOANO EBADRQC EBADSLT EDEADLOCK EBFONT ENOSTR ENODATA ETIME ENOSR ENONET ENOPKG EREMOTE ENOLINK EADV ESRMNT ECOMM EPROTO EMULTIHOP EDOTDOT EBADMSG EOVERFLOW ENOTUNIQ EBADFD EREMCHG ELIBACC ELIBBAD ELIBSCN ELIBMAX ELIBEXEC EILSEQ ERESTART ESTRPIPE EUSERS ENOTSOCK EDESTADDRREQ EMSGSIZE EPROTOTYPE ENOPROTOOPT EPROTONOSUPPORT ESOCKTNOSUPPORT EOPNOTSUPP EPFNOSUPPORT EAFNOSUPPORT EADDRINUSE EADDRNOTAVAIL ENETDOWN ENETUNREACH ENETRESET ECONNABORTED ECONNRESET ENOBUFS EISCONN ENOTCONN ESHUTDOWN ETOOMANYREFS ETIMEDOUT ECONNREFUSED EHOSTDOWN EHOSTUNREACH EALREADY EINPROGRESS ESTALE EUCLEAN ENOTNAM ENAVAIL EISNAM EREMOTEIO EDQUOT ENOMEDIUM EMEDIUMTYPE ECANCELED ENOKEY EKEYEXPIRED EKEYREVOKED EKEYREJECTED EOWNERDEAD ENOTRECOVERABLE ERFKILL POLLIN POLLPRI POLLOUT POLLRDNORM POLLRDBAND POLLWRNORM POLLWRBAND POLLMSG POLLREMOVE POLLRDHUP POLLERR POLLHUP POLLNVAL
 syn keyword	pSyscall        accept bind close connect fcntl getsockopt ioctl listen poll read readv recv recvfrom recvmsg send sendmsg sendto setsockopt shutdown socket write writev
diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l
index 95cb894ce1fd22bbf9a4d5e5d8afccc97bc9b866..71f72a1dbc26ff52e53e0e4c81d940a4c17963fa 100644
--- a/gtests/net/packetdrill/lexer.l
+++ b/gtests/net/packetdrill/lexer.l
@@ -220,6 +220,18 @@ sstat_instrms			return SSTAT_INSTRMS;
 sstat_outstrms			return SSTAT_OUTSTRMS;
 sstat_fragmentation_point	return SSTAT_FRAGMENTATION_POINT;
 sstat_primary			return SSTAT_PRIMARY;
+spinfo_state			return SPINFO_STATE;
+spinfo_cwnd			return SPINFO_CWND;
+spinfo_srtt			return SPINFO_SRTT;
+spinfo_rto			return SPINFO_RTO;
+spinfo_mtu			return SPINFO_MTU;
+spp_address			return SPP_ADDRESS;
+spp_hbinterval			return SPP_HBINTERVAL;
+spp_pathmaxrxt			return SPP_PATHMAXRXT;
+spp_pathmtu			return SPP_PATHMTU;
+spp_flags			return SPP_FLAGS;
+spp_ipv6_flowlabel		return SPPIPV6FLOWLABEL;
+spp_dscp			return SPPDSCP;
 CHUNK				return CHUNK;
 DATA				return DATA;
 INIT				return INIT;
diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index 8f353410b201060a80ebbcd1c7cfa2262974a2f4..330562dc751db025514d78c0619bad9831cc5246 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -509,7 +509,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %token <reserved> SACK_DELAY SACK_FREQ
 %token <reserved> SSTAT_STATE SSTAT_RWND SSTAT_UNACKDATA SSTAT_PENDDATA
 %token <reserved> SSTAT_INSTRMS SSTAT_OUTSTRMS SSTAT_FRAGMENTATION_POINT
-%token <reserved> SSTAT_PRIMARY;
+%token <reserved> SSTAT_PRIMARY
+%token <reserved> SPINFO_STATE SPINFO_CWND SPINFO_SRTT SPINFO_RTO SPINFO_MTU
 %token <reserved> CHUNK DATA INIT INIT_ACK HEARTBEAT HEARTBEAT_ACK ABORT
 %token <reserved> SHUTDOWN SHUTDOWN_ACK ERROR COOKIE_ECHO COOKIE_ACK ECNE CWR
 %token <reserved> SHUTDOWN_COMPLETE PAD
@@ -529,6 +530,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %token <reserved> COOKIE_RECEIVED_WHILE_SHUTDOWN RESTART_WITH_NEW_ADDRESSES
 %token <reserved> USER_INITIATED_ABORT PROTOCOL_VIOLATION
 %token <reserved> STALENESS CHK PARAM UNRECOGNIZED_PARAMETERS
+%token <reserved> SPP_ADDRESS SPP_HBINTERVAL SPP_PATHMAXRXT SPP_PATHMTU
+%token <reserved> SPP_FLAGS SPPIPV6FLOWLABEL SPPDSCP 
 %token <floating> FLOAT
 %token <integer> INTEGER HEX_INTEGER
 %token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR
@@ -564,11 +567,16 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %type <expression_list> expression_list function_arguments
 %type <expression> expression binary_expression array
 %type <expression> decimal_integer hex_integer
-%type <expression> inaddr sockaddr msghdr iovec pollfd opt_revents 
+%type <expression> inaddr sockaddr msghdr iovec pollfd opt_revents
 %type <expression> linger l_onoff l_linger
-%type <expression> sctp_status sctp_initmsg sctp_assocval sctp_sackinfo
-%type <expression> sctp_rtoinfo srto_initial srto_max srto_min
-%type <errno_info> opt_errno
+%type <expression> sctp_status sstat_state sstat_rwnd sstat_unackdata sstat_penddata
+%type <expression> sstat_instrms sstat_outstrms sstat_fragmentation_point sstat_primary
+%type <expression> sctp_initmsg sctp_assocval sctp_sackinfo
+%type <expression> sctp_rtoinfo srto_initial srto_max srto_min sctp_paddrinfo
+%type <expression> sctp_paddrparams spp_address spp_hbinterval spp_pathmtu spp_pathmaxrxt
+%type <expression> spp_flags spp_ipv6_flowlabel spp_dscp
+%type <expression> spinfo_state spinfo_cwnd spinfo_srtt spinfo_rto spinfo_mtu
+%type <errno_info> opt_errno 
 %type <chunk_list> sctp_chunk_list_spec
 %type <chunk_list_item> sctp_chunk_spec
 %type <chunk_list_item> sctp_generic_chunk_spec
@@ -2163,6 +2171,12 @@ expression
 | sctp_status       {
 	$$ = $1;
 }
+| sctp_paddrinfo    {
+	$$ = $1;
+}
+| sctp_paddrparams  {
+	$$ = $1;
+}
 ;
 
 decimal_integer
@@ -2282,18 +2296,17 @@ opt_revents
 ;
 
 l_onoff
-: ONOFF '=' INTEGER { 
+: ONOFF '=' INTEGER {
 	if (!is_valid_s32($3)) {
 		semantic_error("linger onoff out of range");
-	} else {
-		$$ = new_integer_expression($3, "%ld"); 
-	}	
+	}
+	$$ = new_integer_expression($3, "%ld");
 }
 | ONOFF '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
 ;
 
 l_linger
-: LINGER '=' INTEGER { 
+: LINGER '=' INTEGER {
 	if (!is_valid_s32($3)) {
 		semantic_error("linger out of range");
 	}
@@ -2413,42 +2426,230 @@ sctp_sackinfo
 }
 ;
 
-sctp_status
-: '{' SSTAT_STATE '=' INTEGER ',' SSTAT_RWND '=' INTEGER ',' SSTAT_UNACKDATA '=' INTEGER ',' SSTAT_PENDDATA '=' INTEGER ',' SSTAT_INSTRMS '=' INTEGER ',' SSTAT_OUTSTRMS '=' INTEGER ',' SSTAT_FRAGMENTATION_POINT '=' INTEGER ',' SSTAT_PRIMARY '=' ELLIPSIS '}' {
-#ifdef SCTP_INITMSG
-	$$ = new_expression(EXPR_SCTP_STATUS);
-	if (!is_valid_s32($4)) {
-		semantic_error("sstat_state out of range");
-	}
-	$$->value.sctp_status.sstat_state = $4;
-	if (!is_valid_u32($8)) {
+sstat_state
+: SSTAT_STATE '=' expression { $$ = $3; }
+;
+
+sstat_rwnd
+: SSTAT_RWND '=' INTEGER {
+	if (!is_valid_u32($3)) {
 		semantic_error("sstat_rwnd out of range");
 	}
-	$$->value.sctp_status.sstat_rwnd = $8;
-	if (!is_valid_u16($12)) {
+	$$ = new_integer_expression($3, "%u");
+}
+| SSTAT_RWND '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sstat_unackdata
+: SSTAT_UNACKDATA '=' INTEGER {
+	if (!is_valid_u16($3)) {
 		semantic_error("sstat_unackdata out of range");
 	}
-	$$->value.sctp_status.sstat_unackdata = $12;
-	if (!is_valid_u16($16)) {
+	$$ = new_integer_expression($3, "%hu");
+}
+| SSTAT_UNACKDATA '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sstat_penddata
+: SSTAT_PENDDATA '=' INTEGER {
+	if (!is_valid_u16($3)) {
 		semantic_error("sstat_penddata out of range");
 	}
-	$$->value.sctp_status.sstat_penddata = $16;
-	if (!is_valid_u16($20)) {
+	$$ = new_integer_expression($3, "%hu");
+}
+| SSTAT_PENDDATA '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sstat_instrms
+: SSTAT_INSTRMS '=' INTEGER {
+	if (!is_valid_u16($3)) {
 		semantic_error("sstat_instrms out of range");
 	}
-	$$->value.sctp_status.sstat_instrms = $20;
-	if (!is_valid_u16($24)) {
+	$$ = new_integer_expression($3, "%hu");
+}
+| SSTAT_INSTRMS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sstat_outstrms
+: SSTAT_OUTSTRMS '=' INTEGER {
+	if (!is_valid_u16($3)) {
 		semantic_error("sstat_outstrms out of range");
 	}
-	$$->value.sctp_status.sstat_outstrms = $24;
-	if (!is_valid_u32($28)) {
+	$$ = new_integer_expression($3, "%hu");
+}
+| SSTAT_OUTSTRMS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sstat_fragmentation_point
+: SSTAT_FRAGMENTATION_POINT '=' INTEGER {
+	if (!is_valid_u32($3)) {
 		semantic_error("sstat_fragmentation_point out of range");
 	}
-	$$->value.sctp_status.sstat_fragmentation_point = $28;
-#else
-	$$ = NULL;
-#endif
+	$$ = new_integer_expression($3, "%u");
 }
+| SSTAT_FRAGMENTATION_POINT '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sstat_primary
+: SSTAT_PRIMARY '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+| SSTAT_PRIMARY '=' sctp_paddrinfo  { $$ = $3; }
+;
+
+spinfo_state
+: SPINFO_STATE '=' INTEGER { 
+	if (!is_valid_s32($3)) {
+		semantic_error("spinfo_state out of range");
+	}
+	$$ = new_integer_expression($3, "%d"); 
+}
+| SPINFO_STATE '=' WORD { 
+	$$ = new_expression(EXPR_WORD); 
+	$$->value.string = $3; 
+}
+| SPINFO_STATE '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+spinfo_cwnd
+: SPINFO_CWND '=' INTEGER {
+	if (!is_valid_u32($3)) {
+		semantic_error("spinfo_cwnd out of range");
+	}
+	$$ = new_integer_expression($3, "%u");
+}
+| SPINFO_CWND '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+spinfo_srtt
+: SPINFO_SRTT '=' INTEGER {
+	if (!is_valid_u32($3)) {
+		semantic_error("spinfo_srtt out of range");
+	}
+	$$ = new_integer_expression($3, "%u");
+}
+| SPINFO_SRTT '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+spinfo_rto
+: SPINFO_RTO '=' INTEGER {
+	if (!is_valid_u32($3)) {
+		semantic_error("spinfo_rto out of range");	
+	}
+	$$ = new_integer_expression($3, "%u");
+}
+| SPINFO_RTO '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+spinfo_mtu
+: SPINFO_MTU '=' INTEGER {
+	if (!is_valid_u32($3)) {
+		semantic_error("spinfo_mtu out of range");
+	}
+	$$ = new_integer_expression($3, "%u");
+}
+| SPINFO_MTU '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sctp_paddrinfo
+: '{' spinfo_state ',' spinfo_cwnd ',' spinfo_srtt ',' spinfo_rto ',' spinfo_mtu '}' {
+	$$ = new_expression(EXPR_SCTP_PADDRINFO);
+	$$->value.sctp_paddrinfo = (struct sctp_paddrinfo_expr*) calloc(1, sizeof(struct sctp_paddrinfo_expr));
+	$$->value.sctp_paddrinfo->spinfo_state = $2;
+	$$->value.sctp_paddrinfo->spinfo_cwnd = $4;
+	$$->value.sctp_paddrinfo->spinfo_srtt = $6;
+	$$->value.sctp_paddrinfo->spinfo_rto = $8;
+	$$->value.sctp_paddrinfo->spinfo_mtu = $10;
+}
+;
+
+sctp_status
+: '{' sstat_state ',' sstat_rwnd ',' sstat_unackdata ',' sstat_penddata ',' sstat_instrms ',' sstat_outstrms ','
+	sstat_fragmentation_point ',' sstat_primary  '}' {
+	$$ = new_expression(EXPR_SCTP_STATUS);
+	$$->value.sctp_status = (struct sctp_status_expr*) calloc(1, sizeof(struct sctp_status_expr));
+	$$->value.sctp_status->sstat_state = $2;
+	$$->value.sctp_status->sstat_rwnd = $4;
+	$$->value.sctp_status->sstat_unackdata = $6;
+	$$->value.sctp_status->sstat_penddata = $8;
+	$$->value.sctp_status->sstat_instrms = $10;
+	$$->value.sctp_status->sstat_outstrms = $12;
+	$$->value.sctp_status->sstat_fragmentation_point = $14;
+	$$->value.sctp_status->sstat_primary = $16;
+}
+;
+
+spp_address
+: SPP_ADDRESS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+| SPP_ADDRESS '=' sockaddr { $$ = $3; }
+;
+
+spp_hbinterval
+: SPP_HBINTERVAL '=' INTEGER { 
+	if (!is_valid_u32($3)) {
+		semantic_error("spp_hbinterval out of range");
+	}
+	$$ = new_integer_expression($3, "%u");
+}
+| SPP_HBINTERVAL '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+spp_pathmtu
+: SPP_PATHMTU '=' INTEGER {
+	if (!is_valid_u32($3)) {
+		semantic_error("spp_pathmtu out of range");
+	}
+	$$ = new_integer_expression($3, "%u");
+}
+| SPP_PATHMTU '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+spp_pathmaxrxt
+: SPP_PATHMAXRXT '=' INTEGER {
+	if (!is_valid_u16($3)) {
+		semantic_error("spp_pathmaxrxt out of range");
+	}
+	$$ = new_integer_expression($3, "%hu");
+}
+| SPP_PATHMAXRXT '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+spp_flags
+: SPP_FLAGS '=' expression { $$ = $3; }
+;
+
+spp_ipv6_flowlabel
+: SPPIPV6FLOWLABEL '=' INTEGER {
+	if (!is_valid_u32($3)) {
+		semantic_error("spp_ipv6_flowlabel out of range");
+	}
+	$$ = new_integer_expression($3, "%u");
+}
+| SPPIPV6FLOWLABEL '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+spp_dscp
+: SPPDSCP '=' INTEGER {
+	if (!is_valid_u8($3)) {
+		semantic_error("spp_dscp out of range");
+	}
+	$$ = new_integer_expression($3, "%hhu");
+}
+| SPPDSCP '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sctp_paddrparams
+: '{' spp_address ',' spp_hbinterval ',' spp_pathmtu ',' spp_pathmaxrxt ',' spp_flags 
+	',' spp_ipv6_flowlabel ',' spp_dscp'}' {
+	$$ = new_expression(EXPR_SCTP_PEER_ADDR_PARAMS);
+	$$->value.sctp_paddrparams = (struct sctp_paddrparams_expr*) calloc(1, sizeof(struct sctp_paddrparams_expr));
+	$$->value.sctp_paddrparams->spp_address = $2;
+	$$->value.sctp_paddrparams->spp_hbinterval = $4;
+	$$->value.sctp_paddrparams->spp_pathmtu = $6;
+	$$->value.sctp_paddrparams->spp_pathmaxrxt = $8;
+	$$->value.sctp_paddrparams->spp_flags = $10;
+	$$->value.sctp_paddrparams->spp_ipv6_flowlabel = $12;
+	$$->value.sctp_paddrparams->spp_dscp = $14;
+}
+;
 
 opt_errno
 :                   { $$ = NULL; }
diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c
index 85cb8a15782462f931fad9aaf1ba00cfc23fdd2e..72ea542661e460baec74c4c5a3819c1fc3b49852 100644
--- a/gtests/net/packetdrill/run_system_call.c
+++ b/gtests/net/packetdrill/run_system_call.c
@@ -200,6 +200,46 @@ static int get_s32(struct expression *expression,
 	return STATUS_OK;
 }
 
+/* Sets the value from the expression argument, checking that it is a
+ * valid s16 or u16, and matches the expected type. Returns STATUS_OK on
+ * success; on failure returns STATUS_ERR and sets error message.
+ */
+static int get_s16(struct expression *expression,
+		s16 *value, char **error)
+{
+	if (check_type(expression, EXPR_INTEGER, error))
+		return STATUS_ERR;
+	if ((expression->value.num > USHRT_MAX) ||
+		(expression->value.num < SHRT_MIN)) {
+		asprintf(error,
+			"Value out of range for 16-bit integer: %lld",
+			expression->value.num);
+		return STATUS_ERR;
+	}
+	*value = expression->value.num;
+	return STATUS_OK;
+}
+
+/* Sets the value from the expression argument, checking that it is a
+ * valid s8 or u8, and matches the expected type. Returns STATUS_OK on
+ * success; on failure returns STATUS_ERR and sets error message.
+ */
+static int get_s8(struct expression *expression,
+                s8 *value, char **error)
+{
+        if (check_type(expression, EXPR_INTEGER, error))
+                return STATUS_ERR;
+        if ((expression->value.num > UCHAR_MAX) ||
+                (expression->value.num < SCHAR_MIN)) {
+                asprintf(error,
+                        "Value out of range for 8-bit integer: %lld",
+                        expression->value.num);
+                return STATUS_ERR;
+        }
+        *value = expression->value.num;
+        return STATUS_OK;
+}
+
 /* Return the value of the argument with the given index, and verify
  * that it has the expected type.
  */
@@ -538,7 +578,7 @@ static int end_syscall(struct state *state, struct syscall_spec *syscall,
 	if (mode == CHECK_NON_NEGATIVE) {
 		if (actual < 0) {
 			asprintf(error,
-				 "Expected non-negative result but got %d "
+				 "Expected non-negative result but got %d"
 				 "with errno %d (%s)",
 				 actual, actual_errno, strerror(actual_errno));
 			return STATUS_ERR;
@@ -1606,9 +1646,33 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 #endif
 #ifdef SCTP_STATUS
 	} else if (val_expression->type == EXPR_SCTP_STATUS) {
-		live_optval = malloc(sizeof(val_expression->value.sctp_status));
-		live_optlen = (socklen_t)sizeof(val_expression->value.sctp_status);
-		((struct sctp_status*) live_optval)->sstat_assoc_id = val_expression->value.sctp_status.sstat_assoc_id;
+		live_optval = malloc(sizeof(struct sctp_status));
+		live_optlen = (socklen_t)sizeof(struct sctp_status);
+		((struct sctp_status*) live_optval)->sstat_assoc_id = 0;
+#endif
+#ifdef SCTP_PEER_ADDR_PARAMS
+	} else if (val_expression->type == EXPR_SCTP_PEER_ADDR_PARAMS) {
+		struct sctp_paddrparams_expr *expr_params = val_expression->value.sctp_paddrparams;
+		struct sctp_paddrparams *live_params = malloc(sizeof(struct sctp_paddrparams));
+		live_optlen = sizeof(struct sctp_paddrparams);
+		if (expr_params->spp_address->type == EXPR_ELLIPSIS) {
+			socklen_t len_addr = sizeof(live_params->spp_address);
+			if (getpeername(live_fd, (struct sockaddr*) &live_params->spp_address, &len_addr)) {
+				asprintf(error, "Bad setsockopt, bad get primary peer address");
+				free(live_params);
+				return STATUS_ERR;
+			}
+		} else if (expr_params->spp_address->type == EXPR_SOCKET_ADDRESS_IPV4) {
+			memcpy(&live_params->spp_address, expr_params->spp_address->value.socket_address_ipv4, sizeof(struct sockaddr_in));
+		} else if (expr_params->spp_address->type == EXPR_SOCKET_ADDRESS_IPV6) {
+			memcpy(&live_params->spp_address, expr_params->spp_address->value.socket_address_ipv6, sizeof(struct sockaddr_in6));
+		} else {
+			asprintf(error, "Bad setsockopt, bad get input for spp_address");
+			free(live_params);
+			return STATUS_ERR;
+		}
+		live_params->spp_assoc_id = 0;
+		live_optval = live_params;
 #endif
 	} else {
 		s32_bracketed_arg(args, 3, &script_optval, error);
@@ -1633,28 +1697,28 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 		struct expression *l_onoff = val_expression->value.linger->l_onoff;
 		struct expression *l_linger = val_expression->value.linger->l_linger;
 		struct linger *ling = live_optval;
-		int val_onoff = 0; 
-		if (l_onoff->type == EXPR_INTEGER) {
+		int val_onoff = 0;
+		if (l_onoff->type != EXPR_ELLIPSIS) {
 			if (get_s32(l_onoff, &val_onoff, error)) {
 				free(live_optval);
 				return STATUS_ERR;
 			}
 			if (val_onoff != ling->l_onoff) {
 				asprintf(error, "Bad getsockopt Linger onoff: expected: %d actual: %d",
-			         	(int) val_onoff, ling->l_onoff);
+					val_onoff, ling->l_onoff);
 				free(live_optval);
 				return STATUS_ERR;
 			}
 		}
 		int val_linger = 0;
-		if (l_linger->type == EXPR_INTEGER) {
+		if (l_linger->type != EXPR_ELLIPSIS) {
 			if (get_s32(l_linger, &val_linger, error)) {
 				free(live_optval);
 				return STATUS_ERR;
 			}
 			if (ling->l_linger != val_linger) {
 				asprintf(error, "Bad getsockopt Linger Value: expected: %d actual: %d",
-			        	 val_linger, ling->l_linger);
+					val_linger, ling->l_linger);
 				free(live_optval);
 				return STATUS_ERR;
 			}
@@ -1667,7 +1731,7 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 		struct expression *srto_min = val_expression->value.sctp_rtoinfo->srto_min;
 		struct sctp_rtoinfo *rtoinfo = live_optval;
 		int initial=0, max=0, min=0;
-		if (srto_initial->type == EXPR_INTEGER) {
+		if (srto_initial->type != EXPR_ELLIPSIS) {
 			if (get_s32(srto_initial, &initial, error)) {
 				free(live_optval);
 				return STATUS_ERR;
@@ -1678,7 +1742,7 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 				free(live_optval);
 				return STATUS_ERR;
 			}
-		} else if (srto_max->type == EXPR_INTEGER) {
+		} else if (srto_max->type != EXPR_ELLIPSIS) {
 			if (get_s32(srto_max, &max, error)) {
 				free(live_optval);
 				return STATUS_ERR;
@@ -1689,7 +1753,7 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 				free(live_optval);
 				return STATUS_ERR;
 			}
-		} else if (srto_min->type == EXPR_INTEGER) {
+		} else if (srto_min->type != EXPR_ELLIPSIS) {
 			if (get_s32(srto_min, &min, error)) {
 				free(live_optval);
 				return STATUS_ERR;
@@ -1704,49 +1768,260 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 #endif
 #ifdef SCTP_STATUS
 	} else if (val_expression->type == EXPR_SCTP_STATUS) {
-		struct sctp_status *live_val = live_optval;
-		struct sctp_status *expected_val = &(val_expression->value.sctp_status);
-		if (live_val->sstat_state != expected_val->sstat_state) {
-			asprintf(error, "Bad getsockopt SCTP_STATUS state: expected: %d actual: %d ",
-			         expected_val->sstat_state, live_val->sstat_state);
-			free(live_optval);
-			return STATUS_ERR;
-		} else if (live_val->sstat_rwnd != expected_val->sstat_rwnd) {
-			asprintf(error, "Bad getsockopt SCTP_STATUS rwnd: expected: %u actual: %u ",
-			         expected_val->sstat_rwnd, live_val->sstat_rwnd);
-			free(live_optval);
-			return STATUS_ERR;
-		} else if (live_val->sstat_unackdata != expected_val->sstat_unackdata) {
-			asprintf(error, "Bad getsockopt SCTP_STATUS unackdata: expected: %u actual: %u",
-			         expected_val->sstat_unackdata, live_val->sstat_unackdata);
-			free(live_optval);
-			return STATUS_ERR;
-		} else if (live_val->sstat_penddata != expected_val->sstat_penddata) {
-			asprintf(error, "Bad getsockopt SCTP_STATUS penddata: expected: %u actual: %u",
-			         expected_val->sstat_penddata, live_val->sstat_penddata);
-			free(live_optval);
-			return STATUS_ERR;
-		} else if (live_val->sstat_instrms != expected_val->sstat_instrms) {
-			asprintf(error, "Bad getsockopt SCTP_STATUS instreams: expected: %u actual: %u",
-			         expected_val->sstat_instrms, live_val->sstat_instrms);
-			free(live_optval);
-			return STATUS_ERR;
-		} else if (live_val->sstat_outstrms != expected_val->sstat_outstrms) {
-			asprintf(error, "Bad getsockopt SCTP_STATUS outstreams: expected: %u actual: %u",
-			         expected_val->sstat_outstrms, live_val->sstat_outstrms);
-			free(live_optval);
-			return STATUS_ERR;
-		} else if (live_val->sstat_fragmentation_point != expected_val->sstat_fragmentation_point){
-			asprintf(error, "Bad getsockopt SCTP_STATUS fragmentation point: expected: %u actual: %u",
-			         expected_val->sstat_fragmentation_point, live_val->sstat_fragmentation_point);
-			free(live_optval);
-			return STATUS_ERR;
+		struct expression *sstat_state = val_expression->value.sctp_status->sstat_state;
+		struct expression *sstat_rwnd = val_expression->value.sctp_status->sstat_rwnd;
+		struct expression *sstat_unackdata = val_expression->value.sctp_status->sstat_unackdata;
+		struct expression *sstat_penddata = val_expression->value.sctp_status->sstat_penddata;
+		struct expression *sstat_instrms = val_expression->value.sctp_status->sstat_instrms;
+		struct expression *sstat_outstrms = val_expression->value.sctp_status->sstat_outstrms;
+		struct expression *sstat_fragmentation_point = val_expression->value.sctp_status->sstat_fragmentation_point;
+		struct expression *sstat_primary = val_expression->value.sctp_status->sstat_primary;
+		struct sctp_status *live_status = live_optval;
+		int state, rwnd, fragmentation_point;
+		short unackdata, penddata, instrms, outstrms;
+		if (sstat_state->type != EXPR_ELLIPSIS) {
+			if (get_s32(sstat_state, &state, error)) {
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			if (live_status->sstat_state != state) {
+				asprintf(error, "Bad getsockopt SCTP_STATUS state: expected: %d actual: %d",
+					state, live_status->sstat_state);
+				free(live_optval);
+				return STATUS_ERR;
+			}
+		}
+		if (sstat_rwnd->type != EXPR_ELLIPSIS) {
+			if (get_s32(sstat_rwnd, &rwnd, error)) {
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			if (live_status->sstat_rwnd != rwnd) {
+				asprintf(error, "Bad getsockopt SCTP_STATUS rwnd: expected: %u actual: %u",
+					rwnd, live_status->sstat_rwnd);
+				free(live_optval);
+				return STATUS_ERR;
+			}
+		}
+		if (sstat_unackdata->type != EXPR_ELLIPSIS) {
+			if (get_s16(sstat_unackdata, &unackdata, error)) {
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			if (live_status->sstat_unackdata != unackdata) {
+				asprintf(error, "Bad getsockopt SCTP_STATUS unackdata: expected: %hu actual: %hu",
+					unackdata, live_status->sstat_unackdata);
+				free(live_optval);
+				return STATUS_ERR;
+			}
+		}
+		if (sstat_penddata->type != EXPR_ELLIPSIS) {
+			if (get_s16(sstat_penddata, &penddata, error)) {
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			if (live_status->sstat_penddata != penddata) {
+				asprintf(error, "Bad getsockopt SCTP_STATUS penddata: expected: %hu actual: %hu",
+					penddata, live_status->sstat_penddata);
+				free(live_optval);
+				return STATUS_ERR;
+			}
+		}
+		if (sstat_instrms->type != EXPR_ELLIPSIS) {
+			if (get_s16(sstat_instrms, &instrms, error)) {
+				free(live_optval);
+				return STATUS_ERR;	
+			}
+			if (live_status->sstat_instrms != instrms) {
+				asprintf(error, "Bad getsockopt SCTP_STATUS instreams: expected: %hu actual: %hu",
+					instrms, live_status->sstat_instrms);
+				free(live_optval);
+				return STATUS_ERR;
+			}
+		}
+		if (sstat_outstrms->type != EXPR_ELLIPSIS) {
+			if (get_s16(sstat_outstrms, &outstrms, error)) {
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			if (live_status->sstat_outstrms != outstrms) {
+				asprintf(error, "Bad getsockopt SCTP_STATUS outstreams: expected: %hu actual: %hu",
+					outstrms, live_status->sstat_outstrms);
+				free(live_optval);
+				return STATUS_ERR;
+			}
+		}
+		if (sstat_fragmentation_point->type != EXPR_ELLIPSIS) {
+			if (get_s32(sstat_fragmentation_point, &fragmentation_point, error)) {
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			if (live_status->sstat_fragmentation_point != fragmentation_point) {
+				asprintf(error, "Bad getsockopt SCTP_STATUS fragmentation point: expected: %u actual: %u",
+					fragmentation_point, live_status->sstat_fragmentation_point);
+				free(live_optval);
+				return STATUS_ERR;
+			}
+		}
+		if (sstat_primary->type != EXPR_ELLIPSIS) {
+			struct sctp_paddrinfo_expr *paddrinfo_expr = sstat_primary->value.sctp_paddrinfo;
+			struct sctp_paddrinfo live_paddrinfo = live_status->sstat_primary;
+			int state, cwnd, srtt, rto, mtu;
+			if (paddrinfo_expr->spinfo_state->type != EXPR_ELLIPSIS) {
+				if (get_s32(paddrinfo_expr->spinfo_state, &state, error)) {
+					free(live_optval);
+					return STATUS_ERR;
+				}
+				if (live_paddrinfo.spinfo_state != state) {
+					asprintf(error, "Bad getsockopt SCTP_STATUS Primary state: expected: %u actual: %u",
+						state, live_paddrinfo.spinfo_state);
+					free(live_optval);
+					return STATUS_ERR;
+				}
+			}
+			if (paddrinfo_expr->spinfo_cwnd->type != EXPR_ELLIPSIS) {
+				if (get_s32(paddrinfo_expr->spinfo_cwnd, &cwnd, error)) {
+					free(live_optval);
+					return STATUS_ERR;
+				}
+				if (live_paddrinfo.spinfo_cwnd != cwnd) {
+					asprintf(error, "Bad getsockopt SCTP_STATUS Primary cwnd: expected: %u actual: %u",
+						cwnd, live_paddrinfo.spinfo_cwnd);
+					free(live_optval);
+					return STATUS_ERR;				
+				}
+			}
+			if (paddrinfo_expr->spinfo_srtt->type != EXPR_ELLIPSIS) {
+				if (get_s32(paddrinfo_expr->spinfo_srtt, &srtt, error)) {
+					free(live_optval);
+					return STATUS_ERR;
+				}
+				if (live_paddrinfo.spinfo_srtt != srtt) {
+					asprintf(error, "Bad getsockopt SCTP_STATUS Primary srtt: expected: %u actual: %u",
+						srtt, live_paddrinfo.spinfo_srtt);
+					free(live_optval);
+					return STATUS_ERR;
+				}
+			}
+			if (paddrinfo_expr->spinfo_rto->type != EXPR_ELLIPSIS) {
+				if (get_s32(paddrinfo_expr->spinfo_rto, &rto, error)) {
+					free(live_optval);
+					return STATUS_ERR;
+				}
+				if (live_paddrinfo.spinfo_rto != rto) {
+					asprintf(error, "Bad getsockopt SCTP_STATUS Primary rto: expected: %u actual: %u",
+						rto, live_paddrinfo.spinfo_rto);
+					free(live_optval);
+					return STATUS_ERR;
+				}
+			}
+			if (paddrinfo_expr->spinfo_mtu->type != EXPR_ELLIPSIS) {
+				if (get_s32(paddrinfo_expr->spinfo_mtu, &mtu, error)) {
+					free(live_optval);
+					return STATUS_ERR;
+				}
+				if (live_paddrinfo.spinfo_mtu != mtu) {
+					asprintf(error, "Bad getsockopt SCTP_STATUS Primary mtu: expected: %u actual: %u",
+						mtu, live_paddrinfo.spinfo_mtu);
+					free(live_optval);
+					return STATUS_ERR;					
+				}
+			}
+		}
+#endif
+#ifdef SCTP_PEER_ADDR_PARAMS
+	} else if (val_expression->type == EXPR_SCTP_PEER_ADDR_PARAMS) {
+		struct expression *spp_hbinterval = val_expression->value.sctp_paddrparams->spp_hbinterval;
+		struct expression *spp_pathmaxrxt = val_expression->value.sctp_paddrparams->spp_pathmaxrxt;
+		struct expression *spp_pathmtu = val_expression->value.sctp_paddrparams->spp_pathmtu;
+		struct expression *spp_flags = val_expression->value.sctp_paddrparams->spp_flags;
+		struct expression *spp_ipv6_flowlabel = val_expression->value.sctp_paddrparams->spp_ipv6_flowlabel;
+		struct expression *spp_dscp = val_expression->value.sctp_paddrparams->spp_dscp;
+		struct sctp_paddrparams *live_params = live_optval;
+		int hbinterval, pathmtu, flags, ipv6_flowlabel;
+		short pathmaxrxt;
+		s8 dscp;
+		if (spp_hbinterval->type != EXPR_ELLIPSIS) {
+			if (get_s32(spp_hbinterval, &hbinterval, error)) {
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			if (live_params->spp_hbinterval != hbinterval) {
+				asprintf(error, "Bad getsockopt SCTP_PARAMS hbinterval: expected: %u actual: %u",
+					hbinterval, live_params->spp_hbinterval);
+				free(live_optval);
+				return STATUS_ERR;
+			}
+		}
+		if (spp_pathmaxrxt->type != EXPR_ELLIPSIS) {
+			if (get_s16(spp_pathmaxrxt, &pathmaxrxt, error)) {
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			if (live_params->spp_pathmaxrxt != pathmaxrxt) {
+				asprintf(error, "Bad getsockopt SCTP_PARAMS pathmaxrxt: expected: %hu actual: %hu",
+					pathmaxrxt, live_params->spp_pathmaxrxt);
+				free(live_optval);
+				return STATUS_ERR;
+			}
+		}
+		if (spp_pathmtu->type != EXPR_ELLIPSIS) {
+			if (get_s32(spp_pathmtu, &pathmtu, error)) {
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			if (live_params->spp_pathmtu != pathmtu) {
+				asprintf(error, "Bad getsockopt SCTP_PARAMS pathmtu: expected: %u actual: %u",
+					pathmtu, live_params->spp_pathmtu);
+				free(live_optval);
+				return STATUS_ERR;
+			}
+		}
+		if (spp_flags->type != EXPR_ELLIPSIS) {
+			if (get_s32(spp_flags, &flags, error)) {
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			if (live_params->spp_flags != flags) {
+				asprintf(error, "Bad getsockopt SCTP_PARAMS flags: expected: %u actual: %u",
+					flags, live_params->spp_flags);
+				free(live_optval);
+				return STATUS_ERR;
+			}
+		}
+#ifdef SPP_IPV6_FLOWLABEL
+		if (spp_ipv6_flowlabel->type != EXPR_ELLIPSIS) {
+			if (get_s32(spp_ipv6_flowlabel, &ipv6_flowlabel, error)) {
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			if (live_params->spp_ipv6_flowlabel != ipv6_flowlabel) {
+				asprintf(error, "Bad getsockopt SCTP_PARAMS ipv6_flowlabel: expected: %u actual: %u",
+					ipv6_flowlabel, live_params->spp_ipv6_flowlabel);
+				free(live_optval);
+				return STATUS_ERR;
+			}
+		}
+#endif
+#ifdef SPP_DSCP
+		if (spp_dscp->type != EXPR_ELLIPSIS) {
+			if (get_s8(spp_dscp, &dscp, error)) {
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			if (live_params->spp_dscp != dscp) {
+				asprintf(error, "Bad getsockopt SCTP_PARAMS dscp: expected: %hhu actual: %hhu",
+					dscp, live_params->spp_dscp);
+				free(live_optval);
+				return STATUS_ERR;
+			}
 		}
+#endif
 #endif
 	} else {
 		if (*(int*)live_optval != script_optval) {
 			asprintf(error, "Bad getsockopt optval: expected: %d actual: %d",
-			         (int)script_optval, *(int*)live_optval);
+				(int)script_optval, *(int*)live_optval);
 			free(live_optval);
 			return STATUS_ERR;
 		}
@@ -1756,7 +2031,7 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 }
 
 static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
-			      struct expression_list *args, char **error)
+			struct expression_list *args, char **error)
 {
 	int script_fd, live_fd, level, optname, optval_s32, optlen, result;
 	void *optval = NULL;
@@ -1780,10 +2055,10 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 		return STATUS_ERR;
 	if (val_expression->type == EXPR_LINGER) {
 		optval = malloc(sizeof(struct linger));
-		get_s32(val_expression->value.linger->l_onoff, 
+		get_s32(val_expression->value.linger->l_onoff,
 			&(((struct linger*) optval)->l_onoff), error);
 		get_s32(val_expression->value.linger->l_linger,
-                        &(((struct linger*) optval)->l_linger), error);
+			&(((struct linger*) optval)->l_linger), error);
 	} else if (val_expression->type == EXPR_STRING) {
 		optval = val_expression->value.string;
 	} else if (val_expression->type == EXPR_LIST) {
@@ -1794,17 +2069,24 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 	} else if (val_expression->type == EXPR_SCTP_RTOINFO) {
 		struct sctp_rtoinfo *rtoinfo;
 		struct sctp_rtoinfo_expr *expr_rtoinfo  = val_expression->value.sctp_rtoinfo;
-		if (expr_rtoinfo->srto_initial->type != EXPR_INTEGER ||
-			expr_rtoinfo->srto_max->type != EXPR_INTEGER ||
-			expr_rtoinfo->srto_min->type != EXPR_INTEGER) { 
-			asprintf(error, "Bad setsockopt, bad inputtype for rtoinfo");
-			return STATUS_ERR;
-		}
+		socklen_t live_optlen = sizeof(struct sctp_paddrparams);
 		rtoinfo = malloc(sizeof(struct sctp_rtoinfo));
-		rtoinfo->srto_initial = expr_rtoinfo->srto_initial->value.num;
-		rtoinfo->srto_max = expr_rtoinfo->srto_max->value.num;
-		rtoinfo->srto_min = expr_rtoinfo->srto_min->value.num;
+		memset(rtoinfo, 0, sizeof(struct sctp_rtoinfo));
 		rtoinfo->srto_assoc_id = 0;
+		if (getsockopt(live_fd, level, optname, rtoinfo, &live_optlen) == -1) {
+			asprintf(error, "Bad setsockopt, bad get actuall values");
+			free(rtoinfo);
+			return STATUS_ERR;
+		}
+		if (expr_rtoinfo->srto_initial->type != EXPR_ELLIPSIS) {
+			rtoinfo->srto_initial = expr_rtoinfo->srto_initial->value.num;	
+		}
+		if (expr_rtoinfo->srto_max->type != EXPR_ELLIPSIS) {
+			rtoinfo->srto_max = expr_rtoinfo->srto_max->value.num;		
+		}
+		if (expr_rtoinfo->srto_min->type != EXPR_ELLIPSIS) {
+			rtoinfo->srto_min = expr_rtoinfo->srto_min->value.num;
+		}
 		optval = rtoinfo;
 #endif
 #ifdef SCTP_INITMSG
@@ -1821,7 +2103,91 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 #endif
 #ifdef SCTP_STATUS
 	} else if (val_expression->type == EXPR_SCTP_STATUS) {
-		optval = &val_expression->value.sctp_status;
+		struct sctp_status *status = malloc(sizeof(struct sctp_status));
+		status->sstat_assoc_id = 0;
+		optval = status;
+#endif
+#ifdef SCTP_PEER_ADDR_PARAMS
+	} else if (val_expression->type == EXPR_SCTP_PEER_ADDR_PARAMS) {
+		struct sctp_paddrparams_expr *expr_params = val_expression->value.sctp_paddrparams;
+		struct sctp_paddrparams *params = malloc(sizeof(struct sctp_paddrparams));
+		memset(params, 0, sizeof(struct sctp_paddrparams));
+		socklen_t live_optlen = sizeof(struct sctp_paddrparams);
+		if (expr_params->spp_address->type == EXPR_SOCKET_ADDRESS_IPV4) {
+			memcpy(&params->spp_address, expr_params->spp_address->value.socket_address_ipv4, sizeof(struct sockaddr_in));
+		} else if (expr_params->spp_address->type == EXPR_SOCKET_ADDRESS_IPV6) {
+			memcpy(&params->spp_address, expr_params->spp_address->value.socket_address_ipv6, sizeof(struct sockaddr_in6));
+		} else if (expr_params->spp_address->type == EXPR_ELLIPSIS) {
+			socklen_t len_addr = sizeof(params->spp_address);
+			if (getpeername(live_fd, (struct sockaddr*) &params->spp_address, &len_addr)) {
+				asprintf(error, "Bad setsockopt, bad get primary peer address");
+				free(params);
+				return STATUS_ERR;
+			}
+		} else {
+			asprintf(error, "Bad setsockopt, bad input for spp_address for socketoption SCTP_PADDRPARAMS");
+			free(params);
+			return STATUS_ERR;
+		}
+		params->spp_assoc_id = 0;
+		if (getsockopt(live_fd, level, optname, params, &live_optlen) == -1) {
+			asprintf(error, "Bad setsockopt, bad get actuall values");
+			free(params);
+			return STATUS_ERR;
+		}
+		if (expr_params->spp_hbinterval->type != EXPR_ELLIPSIS) {
+			int hbinterval;
+			if (get_s32(expr_params->spp_hbinterval, &hbinterval, error)) {
+				free(params);
+				return STATUS_ERR;
+			}
+			params->spp_hbinterval = hbinterval;
+		}
+		if (expr_params->spp_pathmaxrxt->type != EXPR_ELLIPSIS) {
+			short maxrxt;
+			if (get_s16(expr_params->spp_pathmaxrxt, &maxrxt, error)) {
+				free(params);
+				return STATUS_ERR;
+			}
+			params->spp_pathmaxrxt = maxrxt;
+		}
+		if (expr_params->spp_pathmtu->type != EXPR_ELLIPSIS) {
+			int mtu;
+			if (get_s32(expr_params->spp_pathmtu, &mtu, error)) {
+				free(params);
+				return STATUS_ERR;
+			}
+			params->spp_pathmtu = mtu;
+		}
+		if (expr_params->spp_flags->type != EXPR_ELLIPSIS) {
+			int flags;
+			if (get_s32(expr_params->spp_flags, &flags, error)) {
+				free(params);
+				return STATUS_ERR;
+			}
+			params->spp_flags = flags;
+		}
+#ifdef SPP_IPV6_FLOWLABEL
+		if (expr_params->spp_ipv6_flowlabel->type != EXPR_ELLIPSIS) {
+			int flowlabel; 
+			if (get_s32(expr_params->spp_ipv6_flowlabel, &flowlabel, error)) {
+				free(params);
+				return STATUS_ERR;
+			}
+			params->spp_ipv6_flowlabel = flowlabel;
+		}
+#endif
+#ifdef SPP_DSCP
+		if (expr_params->spp_dscp->type != EXPR_ELLIPSIS) {
+			s8 dscp;
+			if (get_s8(expr_params->spp_dscp, &dscp, error)) {
+				free(params);
+				return STATUS_ERR;
+			}
+			params->spp_dscp = dscp;
+		}
+#endif
+		optval = params;
 #endif
 	} else {
 		asprintf(error, "unsupported setsockopt value type: %s",
@@ -1829,7 +2195,6 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 				 val_expression->type));
 		return STATUS_ERR;
 	}
-
 	begin_syscall(state, syscall);
 
 	result = setsockopt(live_fd, level, optname, optval, optlen);
diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c
index 7b7d656577e63322f865f600d38a354e1280bd73..2490e907d6dbcb42a5d7e02eefb8ce6d277c6024 100644
--- a/gtests/net/packetdrill/script.c
+++ b/gtests/net/packetdrill/script.c
@@ -78,7 +78,11 @@ struct expression_type_entry expression_type_table[] = {
 	{ EXPR_SCTP_SACKINFO,        "sctp_sackinfo"},
 #endif
 #ifdef SCTP_STATUS
-	{ EXPR_SCTP_STATUS,           "sctp_status"},
+	{ EXPR_SCTP_STATUS,          "sctp_status"},
+	{ EXPR_SCTP_PADDRINFO,	     "sctp_paddrinfo"},
+#endif
+#ifdef SCTP_PEER_ADDR_PARAMS
+	{ EXPR_SCTP_PEER_ADDR_PARAMS,	"sctp_peer_addr_params"},
 #endif
 	{ NUM_EXPR_TYPES,            NULL}
 };
@@ -306,10 +310,37 @@ void free_expression(struct expression *expression)
 #ifdef SCTP_DELAYED_SACK
 	case EXPR_SCTP_SACKINFO:
 #endif
+		break;
 #ifdef SCTP_STATUS
+	case EXPR_SCTP_PADDRINFO:
+		free(expression->value.sctp_paddrinfo->spinfo_state);
+		free(expression->value.sctp_paddrinfo->spinfo_cwnd);
+		free(expression->value.sctp_paddrinfo->spinfo_srtt);
+		free(expression->value.sctp_paddrinfo->spinfo_rto);
+		free(expression->value.sctp_paddrinfo->spinfo_mtu);
+		break;
 	case EXPR_SCTP_STATUS:
+		free(expression->value.sctp_status->sstat_state);
+		free(expression->value.sctp_status->sstat_rwnd);
+		free(expression->value.sctp_status->sstat_unackdata);
+		free(expression->value.sctp_status->sstat_penddata);
+		free(expression->value.sctp_status->sstat_instrms);
+		free(expression->value.sctp_status->sstat_outstrms);
+		free(expression->value.sctp_status->sstat_fragmentation_point);
+		free(expression->value.sctp_status->sstat_primary);
+		break;
 #endif
+#ifdef SCTP_PEER_ADDR_PARAMS
+	case EXPR_SCTP_PEER_ADDR_PARAMS:
+		free(expression->value.sctp_paddrparams->spp_address);
+		free(expression->value.sctp_paddrparams->spp_hbinterval);
+		free(expression->value.sctp_paddrparams->spp_pathmaxrxt);
+		free(expression->value.sctp_paddrparams->spp_pathmtu);
+		free(expression->value.sctp_paddrparams->spp_flags);
+		free(expression->value.sctp_paddrparams->spp_ipv6_flowlabel);
+		free(expression->value.sctp_paddrparams->spp_dscp);
 		break;
+#endif
 	case EXPR_WORD:
 		assert(expression->value.string);
 		free(expression->value.string);
@@ -470,6 +501,57 @@ static int evaluate_msghdr_expression(struct expression *in,
 	return STATUS_OK;
 }
 
+#ifdef SCTP_STATUS
+static int evaluate_sctp_status_expression(struct expression *in,
+						struct expression *out, char **error)
+{
+	struct sctp_status_expr *in_status;
+	struct sctp_status_expr *out_status;
+
+	assert(in->type == EXPR_SCTP_STATUS);
+	assert(in->value.sctp_status);
+	assert(out->type == EXPR_SCTP_STATUS);
+
+	out->value.sctp_status = calloc(1, sizeof(struct sctp_status_expr));
+
+	in_status = in->value.sctp_status;
+	out_status = out->value.sctp_status;
+	
+	if (evaluate(in_status->sstat_state,
+			&out_status->sstat_state,
+			error))
+		return STATUS_ERR;
+	if (evaluate(in_status->sstat_rwnd,
+			&out_status->sstat_rwnd,
+			error))
+		return STATUS_ERR;
+	if (evaluate(in_status->sstat_unackdata,
+			&out_status->sstat_unackdata,
+			error))
+		return STATUS_ERR;
+	if (evaluate(in_status->sstat_penddata,
+			&out_status->sstat_penddata,
+			error))
+		return STATUS_ERR;
+	if (evaluate(in_status->sstat_instrms,
+			&out_status->sstat_instrms,
+			error))
+		return STATUS_ERR;
+	if (evaluate(in_status->sstat_outstrms,
+			&out_status->sstat_outstrms,
+			error))
+		return STATUS_ERR;
+	if (evaluate(in_status->sstat_fragmentation_point,
+			&out_status->sstat_fragmentation_point,
+			error))
+		return STATUS_ERR;
+	if (evaluate(in_status->sstat_primary,
+			&out_status->sstat_primary,
+			error))
+			return STATUS_ERR;
+	return STATUS_OK;
+}
+#endif
 static int evaluate_pollfd_expression(struct expression *in,
 				      struct expression *out, char **error)
 {
@@ -544,9 +626,26 @@ static int evaluate(struct expression *in,
 		break;
 #endif
 #ifdef SCTP_STATUS
+	case EXPR_SCTP_PADDRINFO:
+		memcpy(&out->value.sctp_paddrinfo, &in->value.sctp_paddrinfo,
+		       sizeof(in->value.sctp_paddrinfo));
+		if (evaluate(in->value.sctp_paddrinfo->spinfo_state,
+				&out->value.sctp_paddrinfo->spinfo_state,
+				error))
+			return STATUS_ERR;
+		break;
 	case EXPR_SCTP_STATUS:	/* copy as-is */
-		memcpy(&out->value.sctp_status, &in->value.sctp_status,
-		       sizeof(in->value.sctp_status));
+		result = evaluate_sctp_status_expression(in, out, error);
+		break;
+#endif
+#ifdef SCTP_PEER_ADDR_PARAMS
+	case EXPR_SCTP_PEER_ADDR_PARAMS:
+		memcpy(&out->value.sctp_paddrparams, &in->value.sctp_paddrparams, 
+			sizeof(in->value.sctp_paddrparams));
+		if (evaluate(in->value.sctp_paddrparams->spp_flags,
+				&out->value.sctp_paddrparams->spp_flags,
+				error))
+			return STATUS_ERR;		
 		break;
 #endif
 	case EXPR_WORD:
diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h
index cba02337b50e441dd038f2b8a4e5f6fcc50a81cc..e604d910f73f4d921cb1d693435c06cca6b1677b 100644
--- a/gtests/net/packetdrill/script.h
+++ b/gtests/net/packetdrill/script.h
@@ -60,7 +60,9 @@ enum expression_t {
 #endif
 #ifdef SCTP_STATUS
 	EXPR_SCTP_STATUS,	  /* struct sctp_status for SCTP_STATUS */
+	EXPR_SCTP_PADDRINFO,
 #endif
+	EXPR_SCTP_PEER_ADDR_PARAMS,	 /* struct for sctp_paddrparams for SCTP_PEER_ADDR_PARAMS*/
 	NUM_EXPR_TYPES,
 };
 /* Convert an expression type to a human-readable string */
@@ -93,7 +95,11 @@ struct expression {
 		struct sctp_sack_info sctp_sack_info;
 #endif
 #ifdef SCTP_STATUS
-		struct sctp_status sctp_status;
+		struct sctp_status_expr *sctp_status;
+		struct sctp_paddrinfo_expr *sctp_paddrinfo;
+#endif
+#ifdef SCTP_PEER_ADDR_PARAMS
+		struct sctp_paddrparams_expr *sctp_paddrparams; 
 #endif
 	} value;
 	const char *format;	/* the printf format for printing the value */
@@ -150,6 +156,39 @@ struct sctp_rtoinfo_expr {
 };
 #endif
 
+/* Parse tree for syscall getsockopt for sctp_status*/
+#ifdef SCTP_STATUS
+struct sctp_status_expr {
+	struct expression *sstat_state;
+	struct expression *sstat_rwnd;
+	struct expression *sstat_unackdata;
+	struct expression *sstat_penddata;
+	struct expression *sstat_instrms;
+	struct expression *sstat_outstrms;
+	struct expression *sstat_fragmentation_point;
+	struct expression *sstat_primary;
+};
+
+struct sctp_paddrinfo_expr {
+	struct expression *spinfo_state;
+	struct expression *spinfo_cwnd;
+	struct expression *spinfo_srtt;
+	struct expression *spinfo_rto;
+	struct expression *spinfo_mtu;
+};
+#endif
+
+/* Parse tree for syscall set/getsockopt for SCTP_PEER_ADDR_PARAMS*/
+struct sctp_paddrparams_expr {
+	struct expression *spp_address;
+	struct expression *spp_hbinterval;
+	struct expression *spp_pathmaxrxt;
+	struct expression *spp_pathmtu;
+	struct expression *spp_flags;
+	struct expression *spp_ipv6_flowlabel;
+	struct expression *spp_dscp;
+};
+
 /* The errno-related info from strace to summarize a system call error */
 struct errno_spec {
 	const char *errno_macro;	/* errno symbol (C macro name) */
diff --git a/gtests/net/packetdrill/symbols_freebsd.c b/gtests/net/packetdrill/symbols_freebsd.c
index 9e4e8093f921b7f5c5722b2c44f81dad7d5dec78..14eda9cf01e377000c9e3fcc118df62461ea40d3 100644
--- a/gtests/net/packetdrill/symbols_freebsd.c
+++ b/gtests/net/packetdrill/symbols_freebsd.c
@@ -85,6 +85,7 @@ struct int_symbol platform_symbols_table[] = {
 	{ SCTP_MAXSEG,                      "SCTP_MAXSEG"                     },
 	{ SCTP_DELAYED_SACK,                "SCTP_DELAYED_SACK"               },
 	{ SCTP_MAX_BURST,                   "SCTP_MAX_BURST"                  },
+	{ SCTP_PEER_ADDR_PARAMS,            "SCTP_PEER_ADDR_PARAMS"           },
 	{ SCTP_STATUS,                      "SCTP_STATUS"                     },
 	{ SCTP_CLOSED,                      "SCTP_CLOSED"                     },
 	{ SCTP_BOUND,                       "SCTP_BOUND"                      },
@@ -97,6 +98,20 @@ struct int_symbol platform_symbols_table[] = {
 	{ SCTP_SHUTDOWN_ACK_SENT,           "SCTP_SHUTDOWN_ACK_SENT"          },
 	{ SCTP_SHUTDOWN_PENDING,            "SCTP_SHUTDOWN_PENDING"           },
 
+	/* /usr/include/netinet/sctp_uio.h */
+	{ SCTP_UNCONFIRMED,                 "SCTP_UNCONFIRMED"                },
+	{ SCTP_ACTIVE,                      "SCTP_ACTIVE"                     },
+	{ SCTP_INACTIVE,                    "SCTP_INACTIVE"                   },
+	{ SPP_HB_ENABLE,                    "SPP_HB_ENABLE"                   },
+	{ SPP_HB_DISABLE,                   "SPP_HB_DISABLE"                  },
+	{ SPP_HB_DEMAND,                    "SPP_HB_DEMAND"                   },
+	{ SPP_PMTUD_ENABLE,                 "SPP_PMTUD_ENABLE"                },
+	{ SPP_PMTUD_DISABLE,                "SPP_PMTUD_DISABLE"               },
+	{ SPP_HB_TIME_IS_ZERO,              "SPP_HB_TIME_IS_ZERO"             },
+	{ SPP_IPV6_FLOWLABEL,               "SPP_IPV6_FLOWLABEL"              },
+	{ SPP_DSCP,                         "SPP_DSCP"                        },
+	{ SPP_IPV4_TOS,                     "SPP_IPV4_TOS"                    },
+ 
 	/* /usr/include/netinet/tcp.h */
 	{ TCP_NODELAY,                      "TCP_NODELAY"                     },
 	{ TCP_MAXSEG,                       "TCP_MAXSEG"                      },
diff --git a/gtests/net/packetdrill/symbols_linux.c b/gtests/net/packetdrill/symbols_linux.c
index 33b7797c7bf6479b3640bb45c911bdd78b784b5d..db4e25599a982a3bdfbd95aa9d4f02da43ee2b88 100644
--- a/gtests/net/packetdrill/symbols_linux.c
+++ b/gtests/net/packetdrill/symbols_linux.c
@@ -118,6 +118,9 @@ struct int_symbol platform_symbols_table[] = {
 #ifdef SCTP_MAX_BURST
 	{ SCTP_MAX_BURST,                   "SCTP_MAX_BURST"                  },
 #endif
+#ifdef SCTP_PEER_ADDR_PARAMS
+	{ SCTP_PEER_ADDR_PARAMS,            "SCTP_PEER_ADDR_PARAMS"           },
+#endif
 #ifdef SCTP_STATUS
 	{ SCTP_STATUS,                      "SCTP_STATUS"                     },
 #endif
@@ -133,7 +136,36 @@ struct int_symbol platform_symbols_table[] = {
 	{ SCTP_SHUTDOWN_RECEIVED,           "SCTP_SHUTDOWN_RECEIVED"          },
 	{ SCTP_SHUTDOWN_ACK_SENT,           "SCTP_SHUTDOWN_ACK_SENT"          },
 	{ SCTP_SHUTDOWN_PENDING,            "SCTP_SHUTDOWN_PENDING"           },
-
+        { SCTP_UNCONFIRMED,                 "SCTP_UNCONFIRMED"                },
+        { SCTP_ACTIVE,                      "SCTP_ACTIVE"                     },
+        { SCTP_INACTIVE,                    "SCTP_INACTIVE"                   },
+#ifdef SPP_HB_ENABLE
+        { SPP_HB_ENABLE,                    "SPP_HB_ENABLE"                   },
+#endif
+#ifdef SPP_HB_DISABLE
+        { SPP_HB_DISABLE,                    "SPP_HB_DISABLE"                 },
+#endif
+#ifdef SPP_HB_DEMAND
+        { SPP_HB_DEMAND,                    "SPP_HB_DEMAND"                   },
+#endif
+#ifdef SPP_PMTUD_ENABLE
+        { SPP_PMTUD_ENABLE,                 "SPP_PMTUD_ENABLE"                },
+#endif
+#ifdef SPP_PMTUD_DISABLE
+	{ SPP_PMTUD_DISABLE,                "SPP_PMTUD_DISABLE"               },
+#endif
+#ifdef SPP_HB_TIME_IS_ZERO
+	{ SPP_HB_TIME_IS_ZERO,              "SPP_HB_TIME_IS_ZERO"             },
+#endif
+#ifdef SPP_IPV6_FLOWLABEL
+	{ SPP_IPV6_FLOWLABEL,               "SPP_IPV6_FLOWLABEL"              },
+#endif
+#ifdef SPP_DSCP
+	{ SPP_DSCP,                         "SPP_DSCP"                        },
+#endif
+#ifdef SPP_IPV4_TOS
+	{ SPP_IPV4_TOS,                     "SPP_IPV4_TOS"                    },
+#endif
 	{ TCP_NODELAY,                      "TCP_NODELAY"                     },
 	{ TCP_MAXSEG,                       "TCP_MAXSEG"                      },
 	{ TCP_CORK,                         "TCP_CORK"                        },
diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt
index 8374c2c9fb78140ccaaeeeefef61792e53cb6ef0..4b619548f3647f87e74a8a4f2e1b533a2e0b44bc 100644
--- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt
+++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt
@@ -8,10 +8,57 @@
 +0.0 > sctp: COOKIE_ECHO[flgs=0, len=4, val=...]
 +0.1 < sctp: COOKIE_ACK[flgs=0]
 
-+0.0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
+//+0.0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
 
-+0 getsockopt(3, IPPROTO_SCTP, SCTP_STATUS, {sstat_state=8, sstat_rwnd=1500, sstat_unackdata=0, sstat_penddata=0, sstat_instrms=1, sstat_outstrms=1, 
- 		sstat_fragmentation_point=1452, sstat_primary=...}, [176])= 0
++0 setsockopt(3, IPPROTO_SCTP, SCTP_STATUS, {sstat_state=..., sstat_rwnd=..., sstat_unackdata=..., sstat_penddata=...,
+sstat_instrms=..., sstat_outstrms=..., sstat_fragmentation_point=..., sstat_primary=...}, 176) = -1
+
++0 getsockopt(3, IPPROTO_SCTP, SCTP_STATUS, {sstat_state=SCTP_ESTABLISHED, sstat_rwnd=1500, 
+sstat_unackdata=0, sstat_penddata=0, sstat_instrms=1, sstat_outstrms=1, sstat_fragmentation_point=1452, sstat_primary=...}, [176]) = 0
+
++0 getsockopt(3, IPPROTO_SCTP, SCTP_STATUS, {sstat_state=..., sstat_rwnd=1500, sstat_unackdata=0, 
+sstat_penddata=0, sstat_instrms=1, sstat_outstrms=1, sstat_fragmentation_point=1452, sstat_primary=...}, [176]) = 0
+
++0 getsockopt(3, IPPROTO_SCTP, SCTP_STATUS, {sstat_state=8, sstat_rwnd=..., sstat_unackdata=0, 
+sstat_penddata=0, sstat_instrms=1, sstat_outstrms=1, sstat_fragmentation_point=1452, sstat_primary=...}, [176]) = 0
+
++0 getsockopt(3, IPPROTO_SCTP, SCTP_STATUS, {sstat_state=8, sstat_rwnd=1500, sstat_unackdata=..., 
+sstat_penddata=0, sstat_instrms=1, sstat_outstrms=1, sstat_fragmentation_point=1452, sstat_primary=...}, [176]) = 0
+
++0 getsockopt(3, IPPROTO_SCTP, SCTP_STATUS, {sstat_state=8, sstat_rwnd=1500, sstat_unackdata=0, 
+sstat_penddata=..., sstat_instrms=1, sstat_outstrms=1, sstat_fragmentation_point=1452, sstat_primary=...}, [176]) = 0
+
++0 getsockopt(3, IPPROTO_SCTP, SCTP_STATUS, {sstat_state=8, sstat_rwnd=1500, sstat_unackdata=0, 
+sstat_penddata=0, sstat_instrms=..., sstat_outstrms=1, sstat_fragmentation_point=1452, sstat_primary=...}, [176]) = 0
+
++0 getsockopt(3, IPPROTO_SCTP, SCTP_STATUS, {sstat_state=8, sstat_rwnd=1500, sstat_unackdata=0, 
+sstat_penddata=0, sstat_instrms=1, sstat_outstrms=..., sstat_fragmentation_point=1452, sstat_primary=...}, [176]) = 0
+
++0 getsockopt(3, IPPROTO_SCTP, SCTP_STATUS, {sstat_state=8, sstat_rwnd=1500, sstat_unackdata=0, 
+sstat_penddata=0, sstat_instrms=1, sstat_outstrms=1, sstat_fragmentation_point=..., sstat_primary=...}, [176]) = 0
+
++0 getsockopt(3, IPPROTO_SCTP, SCTP_STATUS, {sstat_state=SCTP_ESTABLISHED, sstat_rwnd=1500, sstat_unackdata=0, sstat_penddata=0,
+sstat_instrms=1, sstat_outstrms=1, sstat_fragmentation_point=..., 
+sstat_primary={ spinfo_state=SCTP_ACTIVE, spinfo_cwnd=4464, spinfo_srtt=..., spinfo_rto=1000, spinfo_mtu=1468} }, [176]) = 0
+
+
++0 setsockopt(3, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, {spp_address={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")},
+spp_hbinterval=300, spp_pathmtu=1468, spp_pathmaxrxt=..., spp_flags=SPP_DSCP|SPP_HB_ENABLE, spp_ipv6_flowlabel=0, spp_dscp=0}, 152) = 0
+
++0 getsockopt(3, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, {spp_address={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")},
+spp_hbinterval=300, spp_pathmtu=1468, spp_pathmaxrxt=..., spp_flags=SPP_DSCP|SPP_HB_ENABLE|SPP_PMTUD_ENABLE, spp_ipv6_flowlabel=0, spp_dscp=0}, [152]) = 0
+
++0 getsockopt(3, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, {spp_address={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")},
+spp_hbinterval=..., spp_pathmtu=1468, spp_pathmaxrxt=..., spp_flags=..., spp_ipv6_flowlabel=0, spp_dscp=0}, [152]) = 0
+
++0 getsockopt(3, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, {spp_address={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")},
+spp_hbinterval=300, spp_pathmtu=..., spp_pathmaxrxt=..., spp_flags=521, spp_ipv6_flowlabel=0, spp_dscp=0}, [152]) = 0
+
++0 getsockopt(3, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, {spp_address={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")},
+spp_hbinterval=300, spp_pathmtu=1468, spp_pathmaxrxt=..., spp_flags=521, spp_ipv6_flowlabel=..., spp_dscp=0}, [152]) = 0
+
++0 getsockopt(3, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, {spp_address={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")},
+spp_hbinterval=300, spp_pathmtu=1468, spp_pathmaxrxt=..., spp_flags=521, spp_ipv6_flowlabel=0, spp_dscp=...}, [152]) = 0
 
 +0 setsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=1, linger=30}, 8) = 0
 +0 getsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=128, linger=30}, [8]) = 0
@@ -26,4 +73,3 @@
 +0 getsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=100, srto_max=200, srto_min=...}, [16]) = 0
 
 +0 close(3) = 0
-
diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_socket_options.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_socket_options.pkt
index ea2f192f00fc4cd73c9c63edf654961ad595f34d..c6ba3996e650b05f17fd958de0e7a9403c874217 100644
--- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_socket_options.pkt
+++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_socket_options.pkt
@@ -5,7 +5,7 @@
 +0 setsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=200, srto_max=200, srto_min=50}, 16) = 0
 +0 setsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=50, srto_max=50, srto_min=50}, 16) = 0
 +0 setsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=100, srto_max=200, srto_min=50}, 17) = 0 
-+0 setsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=100, srto_max=200, srto_min=50}, 15) = -1 EINVAL (Invalid argument)
++0 setsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=..., srto_max=200, srto_min=50}, 15) = -1 EINVAL (Invalid argument)
 +0 setsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=25, srto_max=200, srto_min=50}, 16) = -1 EINVAL (Invalid argument)
 +0 setsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=225, srto_max=200, srto_min=50}, 16) = -1 EINVAL (Invalid argument)
 +0 setsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=50, srto_max=50, srto_min=200}, 16) = -1 EINVAL (Invalid argument)
@@ -42,5 +42,7 @@
 +0 setsockopt(3, IPPROTO_SCTP, SCTP_MAX_BURST, {assoc_value=1}, 9) = 0
 +0 setsockopt(3, IPPROTO_SCTP, SCTP_MAX_BURST, {assoc_value=1}, 7) = -1 (Invalid argument)
 
-+0 close(3) = 0
++0 setsockopt(3, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, {spp_address={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")},
+spp_hbinterval=30000, spp_pathmtu=1468, spp_pathmaxrxt=100, spp_flags=0, spp_ipv6_flowlabel=0, spp_dscp=0}, 152) = 0
 
++0 close(3) = 0