diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index a443838695b6f5e0e772fb9c5a57bea52e1b0e12..88deb4f9a8029964404f6f9d2c2a3e99dcd28985 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -565,9 +565,10 @@ 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_status sctp_initmsg sctp_sackinfo
+%type <expression> sctp_assoc_value
 %type <expression> sctp_rtoinfo srto_initial srto_max srto_min
 %type <errno_info> opt_errno
 %type <chunk_list> sctp_chunk_list_spec
@@ -2333,7 +2334,7 @@ expression
 | sctp_initmsg      {
 	$$ = $1;
 }
-| sctp_assocval     {
+| sctp_assoc_value  {
 	$$ = $1;
 }
 | sctp_sackinfo     {
@@ -2461,18 +2462,18 @@ 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");
 	}
@@ -2560,14 +2561,12 @@ sctp_initmsg
 }
 ;
 
-sctp_assocval
-: '{' ASSOC_VALUE '=' INTEGER '}' {
+sctp_assoc_value
+: '{' ASSOC_VALUE '=' expression '}' {
 #if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED)
-	$$ = new_expression(EXPR_SCTP_ASSOCVAL);
-	if (!is_valid_u32($4)) {
-		semantic_error("assoc_value out of range");
-	}
-	$$->value.sctp_assoc_value.assoc_value = $4;
+	$$ = new_expression(EXPR_SCTP_ASSOC_VALUE);
+	$$->value.sctp_assoc_value = calloc(1, sizeof(struct sctp_assoc_value_expr));
+	$$->value.sctp_assoc_value->assoc_value = $4;
 #else
 	$$ = NULL;
 #endif
diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c
index bd09377eed6615b7395514a003950c6f39757dc2..a130404fbec2a5c375d436217e152360c7cccba4 100644
--- a/gtests/net/packetdrill/run_system_call.c
+++ b/gtests/net/packetdrill/run_system_call.c
@@ -180,6 +180,26 @@ static int check_type(struct expression *expression,
 	}
 }
 
+/* Sets the value from the expression argument, checking that it is a
+ * valid u32, and matches the expected type. Returns STATUS_OK on
+ * success; on failure returns STATUS_ERR and sets error message.
+ */
+static int get_u32(struct expression *expression,
+		   u32 *value, char **error)
+{
+	if (check_type(expression, EXPR_INTEGER, error))
+		return STATUS_ERR;
+	if ((expression->value.num > UINT32_MAX) ||
+	    (expression->value.num < 0)) {
+		asprintf(error,
+			 "Value out of range for 32-bit unsigned 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 s32 or u32, and matches the expected type. Returns STATUS_OK on
  * success; on failure returns STATUS_ERR and sets error message.
@@ -1578,6 +1598,7 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 	void *live_optval;
 	socklen_t live_optlen;
 	struct expression *val_expression;
+
 	if (check_arg_count(args, 5, error))
 		return STATUS_ERR;
 	if (s32_arg(args, 0, &script_fd, error))
@@ -1609,6 +1630,12 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 		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;
+#endif
+#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED)
+	} else if (val_expression->type == EXPR_SCTP_ASSOC_VALUE) {
+		live_optval = malloc(sizeof(struct sctp_assoc_value));
+		live_optlen = (socklen_t)sizeof(struct sctp_assoc_value);
+		((struct sctp_assoc_value *) live_optval)->assoc_id = 0;
 #endif
 	} else {
 		s32_bracketed_arg(args, 3, &script_optval, error);
@@ -1633,7 +1660,7 @@ 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; 
+		int val_onoff = 0;
 		if (l_onoff->type == EXPR_INTEGER) {
 			if (get_s32(l_onoff, &val_onoff, error)) {
 				free(live_optval);
@@ -1742,6 +1769,25 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 			free(live_optval);
 			return STATUS_ERR;
 		}
+#endif
+#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED)
+	} else if (val_expression->type == EXPR_SCTP_ASSOC_VALUE) {
+		struct expression *assoc_value = val_expression->value.sctp_assoc_value->assoc_value;
+		struct sctp_assoc_value *sctp_assoc_value = live_optval;
+		u32 value;
+
+		if (assoc_value->type != EXPR_ELLIPSIS) {
+			if (get_u32(assoc_value, &value, error)) {
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			if (sctp_assoc_value->assoc_value != value) {
+				asprintf(error, "Bad getsockopt sctp_assoc_value.assoc_value: expected: %u actual: %u",
+					 value, sctp_assoc_value->assoc_value);
+				free(live_optval);
+				return STATUS_ERR;
+			}
+		}
 #endif
 	} else {
 		if (*(int*)live_optval != script_optval) {
@@ -1761,6 +1807,7 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 	int script_fd, live_fd, level, optname, optval_s32, optlen, result;
 	void *optval = NULL;
 	struct expression *val_expression;
+	struct sctp_assoc_value assoc_value;
 
 	if (check_arg_count(args, 5, error))
 		return STATUS_ERR;
@@ -1780,7 +1827,7 @@ 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);
@@ -1796,7 +1843,7 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 		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) { 
+			expr_rtoinfo->srto_min->type != EXPR_INTEGER) {
 			asprintf(error, "Bad setsockopt, bad inputtype for rtoinfo");
 			return STATUS_ERR;
 		}
@@ -1812,8 +1859,13 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 		optval = &val_expression->value.sctp_initmsg;
 #endif
 #if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED)
-	} else if (val_expression->type == EXPR_SCTP_ASSOCVAL) {
-		optval = &val_expression->value.sctp_assoc_value;
+	} else if (val_expression->type == EXPR_SCTP_ASSOC_VALUE) {
+		assoc_value.assoc_id = 0;
+		if (get_u32(val_expression->value.sctp_assoc_value->assoc_value,
+		            &assoc_value.assoc_value, error)) {
+			return STATUS_ERR;
+		}
+		optval = &assoc_value;
 #endif
 #ifdef SCTP_DELAYED_SACK
 	} else if (val_expression->type == EXPR_SCTP_SACKINFO) {
diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c
index d6d774ade62503dc457114f7262b15dd0fcb388c..3592bd39e73511ddc1e1bc4eb8fa567ff400a300 100644
--- a/gtests/net/packetdrill/script.c
+++ b/gtests/net/packetdrill/script.c
@@ -72,7 +72,7 @@ struct expression_type_entry expression_type_table[] = {
 	{ EXPR_SCTP_INITMSG,         "sctp_initmsg"},
 #endif
 #if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED)
-	{ EXPR_SCTP_ASSOCVAL,        "sctp_assocvalue"},
+	{ EXPR_SCTP_ASSOC_VALUE,     "sctp_assoc_value"},
 #endif
 #ifdef SCTP_DELAYED_SACK
 	{ EXPR_SCTP_SACKINFO,        "sctp_sackinfo"},
@@ -297,12 +297,14 @@ void free_expression(struct expression *expression)
 		free(expression->value.sctp_rtoinfo->srto_min);
 		break;
 #endif
+#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED)
+	case EXPR_SCTP_ASSOC_VALUE:
+		free(expression->value.sctp_assoc_value->assoc_value);
+		break;
+#endif
 #ifdef SCTP_INITMSG
 	case EXPR_SCTP_INITMSG:
 #endif
-#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED)
-	case EXPR_SCTP_ASSOCVAL:
-#endif
 #ifdef SCTP_DELAYED_SACK
 	case EXPR_SCTP_SACKINFO:
 #endif
@@ -495,6 +497,30 @@ static int evaluate_pollfd_expression(struct expression *in,
 	return STATUS_OK;
 }
 
+#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED)
+static int evaluate_sctp_assoc_value_expression(struct expression *in,
+						struct expression *out,
+						char **error)
+{
+	struct sctp_assoc_value_expr *in_value;
+	struct sctp_assoc_value_expr *out_value;
+
+	assert(in->type == EXPR_SCTP_ASSOC_VALUE);
+	assert(in->value.sctp_assoc_value);
+	assert(out->type == EXPR_SCTP_ASSOC_VALUE);
+
+	out->value.sctp_assoc_value = calloc(1, sizeof(struct sctp_assoc_value_expr));
+
+	in_value = in->value.sctp_assoc_value;
+	out_value = out->value.sctp_assoc_value;
+
+	if (evaluate(in_value->assoc_value, &out_value->assoc_value, error))
+		return STATUS_ERR;
+
+	return STATUS_OK;
+}
+#endif
+
 static int evaluate(struct expression *in,
 		    struct expression **out_ptr, char **error)
 {
@@ -531,10 +557,8 @@ static int evaluate(struct expression *in,
 		break;
 #endif
 #if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED)
-	case EXPR_SCTP_ASSOCVAL:	/* copy as-is */
-		memcpy(&out->value.sctp_assoc_value,
-		       &in->value.sctp_assoc_value,
-		       sizeof(in->value.sctp_assoc_value));
+	case EXPR_SCTP_ASSOC_VALUE:	/* copy as-is */
+		evaluate_sctp_assoc_value_expression(in, out, error);
 		break;
 #endif
 #ifdef SCTP_DELAYED_SACK
diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h
index aff29336e071fa858a1d3db160a32acdf3abcc0f..3fc9ca95b3b3766de85e675e4300891b9b029c65 100644
--- a/gtests/net/packetdrill/script.h
+++ b/gtests/net/packetdrill/script.h
@@ -52,7 +52,7 @@ enum expression_t {
 	EXPR_SCTP_INITMSG,	  /* struct sctp_initmsg for SCTP_INITMSG */
 #endif
 #if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED)
-	EXPR_SCTP_ASSOCVAL,	  /* struct sctp_assoc_value */
+	EXPR_SCTP_ASSOC_VALUE,	  /* struct sctp_assoc_value */
 #endif
 #ifdef SCTP_DELAYED_SACK
 	EXPR_SCTP_SACKINFO,	  /* struct sctp_sack_info for
@@ -87,7 +87,7 @@ struct expression {
 		struct sctp_initmsg sctp_initmsg;
 #endif
 #if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED)
-		struct sctp_assoc_value sctp_assoc_value;
+		struct sctp_assoc_value_expr *sctp_assoc_value;
 #endif
 #ifdef SCTP_DELAYED_SACK
 		struct sctp_sack_info sctp_sack_info;
@@ -150,6 +150,13 @@ struct sctp_rtoinfo_expr {
 };
 #endif
 
+#if defined(SCTP_MAXSEG) || defined(SCTP_MAX_BURST) || defined(SCTP_INTERLEAVING_SUPPORTED)
+/* Parse tree for a sctp_assoc_value struct in a [gs]etsockopt syscall. */
+struct sctp_assoc_value_expr {
+	struct expression *assoc_value;
+};
+#endif
+
 /* 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/tests/bsd/sctp/sctp_get_socket_options.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt
index 8374c2c9fb78140ccaaeeeefef61792e53cb6ef0..c433529aa6cc2691bcd7356498a82916c17c5332 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
@@ -24,6 +24,6 @@
 +0 getsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=..., srto_max=200, srto_min=50}, [16]) = 0
 +0 getsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=100, srto_max=..., srto_min=50}, [16]) = 0
 +0 getsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=100, srto_max=200, srto_min=...}, [16]) = 0
-
++0 getsockopt(3, IPPROTO_SCTP, SCTP_MAXSEG, {assoc_value=1452}, [8]) = 0
 +0 close(3) = 0