diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l
index cc958793bbee6e63a645444cdec2d2300a85e9e2..61af210e8a20b634a729ac250b0cea29b7a93e14 100644
--- a/gtests/net/packetdrill/lexer.l
+++ b/gtests/net/packetdrill/lexer.l
@@ -291,6 +291,15 @@ recvv_nxtinfo                   return RECVV_NXTINFO;
 sse_type                        return SSE_TYPE;
 sse_flags                       return SSE_FLAGS;
 sse_length                      return SSE_LENGTH;
+sac_type                        return SAC_TYPE;
+sac_flags                       return SAC_FLAGS;
+sac_length                      return SAC_LENGTH;
+sac_state                       return SAC_STATE;
+sac_error                       return SAC_ERROR;
+sac_outbound_streams            return SAC_OUTBOUND_STREAMS;
+sac_inbound_streams             return SAC_INBOUND_STREAMS;
+sac_assoc_id                    return SAC_ASSOC_ID;
+sac_info                        return SAC_INFO;
 sender_dry_type                 return SENDER_DRY_TYPE;
 sender_dry_flags                return SENDER_DRY_FLAGS;
 sender_dry_length               return SENDER_DRY_LENGTH;
diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index 2f413edc0b8fc5f310c5244117b30deae8432d22..a8e49b87bdeea6603ce9ae65ef3a0c13d9756a89 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -553,6 +553,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %token <reserved> _SCTP_SEND_FAILURE_EVENT_ _SCTP_PEER_ERROR_EVENT_ _SCTP_SHUTDOWN_EVENT_
 %token <reserved> _SCTP_PARTIAL_DELIVERY_EVENT_ _SCTP_ADAPTATION_LAYER_EVENT_
 %token <reserved> _SCTP_AUTHENTICATION_EVENT_ _SCTP_SENDER_DRY_EVENT_
+%token <reserved> SAC_TYPE SAC_FLAGS SAC_LENGTH SAC_STATE SAC_ERROR SAC_OUTBOUND_STREAMS
+%token <reserved> SAC_INBOUND_STREAMS SAC_ASSOC_ID SAC_INFO
 %token <floating> FLOAT
 %token <integer> INTEGER HEX_INTEGER
 %token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR
@@ -611,6 +613,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %type <expression> sctp_shutdown_event sse_type sse_flags sse_length
 %type <expression> sctp_sender_dry_event sender_dry_type sender_dry_flags sender_dry_length sender_dry_assoc_id
 %type <expression> sctp_event_subscribe
+%type <expression> sctp_assoc_change_event sac_type sac_flags sac_length sac_state sac_error sac_outbound_streams
+%type <expression> sac_inbound_streams sac_assoc_id
 %type <errno_info> opt_errno
 %type <chunk_list> sctp_chunk_list_spec
 %type <chunk_list_item> sctp_chunk_spec
@@ -2585,6 +2589,7 @@ sockaddr
 
 data
 : ELLIPSIS { new_expression(EXPR_ELLIPSIS); }
+| sctp_assoc_change_event { $$ = $1; }
 | sctp_shutdown_event { $$ = $1; }
 | sctp_sender_dry_event { $$ = $1; }
 ;
@@ -3627,6 +3632,111 @@ sctp_sender_dry_event
 }
 ;
 
+sac_type
+: SAC_TYPE '=' INTEGER {
+	if (!is_valid_u16($3)) {
+		semantic_error("sac_type out of range");
+	}
+	$$ = new_integer_expression($3, "%hu");
+}
+| SAC_TYPE '=' WORD {
+	$$ = new_expression(EXPR_WORD);
+	$$->value.string = $3;
+}
+| SAC_TYPE '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sac_flags
+: SAC_FLAGS '=' INTEGER {
+	if (!is_valid_u16($3)) {
+		semantic_error("sac_flags out of range");
+	}
+	$$ = new_integer_expression($3, "%hu");
+}
+| SAC_FLAGS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sac_length
+: SAC_LENGTH '=' INTEGER {
+	if (!is_valid_u16($3)) {
+		semantic_error("sac_length out of range");
+	}
+	$$ = new_integer_expression($3, "%hu");
+}
+| SAC_LENGTH '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sac_state
+: SAC_STATE '=' INTEGER {
+	if (!is_valid_u16($3)) {
+		semantic_error("sac_state out of range");
+	}
+	$$ = new_integer_expression($3, "%hu");
+}
+| SAC_STATE '=' WORD {
+	$$ = new_expression(EXPR_WORD);
+	$$->value.string = $3;
+}
+| SAC_STATE '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sac_error
+: SAC_ERROR '=' INTEGER {
+	if (!is_valid_u16($3)) {
+		semantic_error("sac_error out of range");
+	}
+	$$ = new_integer_expression($3, "%hu");
+}
+| SAC_ERROR '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sac_outbound_streams
+: SAC_OUTBOUND_STREAMS '=' INTEGER {
+	if (!is_valid_u16($3)) {
+		semantic_error("sac_outbound_streams out of range");
+	}
+	$$ = new_integer_expression($3, "%hu");
+}
+| SAC_OUTBOUND_STREAMS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sac_inbound_streams
+: SAC_INBOUND_STREAMS '=' INTEGER {
+	if (!is_valid_u16($3)) {
+		semantic_error("sac_inbound_streams out of range");
+	}
+	$$ = new_integer_expression($3, "%hu");
+}
+| SAC_INBOUND_STREAMS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sac_assoc_id
+: SAC_ASSOC_ID '=' INTEGER {
+	if (!is_valid_u32($3)) {
+		semantic_error("sac_assoc_id out of range");
+	}
+	$$ = new_integer_expression($3, "%u");
+}
+| SAC_ASSOC_ID '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sctp_assoc_change_event
+: '{' sac_type ',' sac_flags ',' sac_length ',' sac_state ',' sac_error ',' sac_outbound_streams ','
+sac_inbound_streams ',' sac_assoc_id ',' SAC_INFO '=' ELLIPSIS '}' {
+	$$ = new_expression(EXPR_SCTP_ASSOC_CHANGE_EVENT);
+	$$->value.sctp_assoc_change_event = calloc(1, sizeof(struct sctp_assoc_change_event_expr));
+	$$->value.sctp_assoc_change_event->sac_type = $2;
+	$$->value.sctp_assoc_change_event->sac_flags = $4;
+	$$->value.sctp_assoc_change_event->sac_length = $6;
+	$$->value.sctp_assoc_change_event->sac_state = $8;
+	$$->value.sctp_assoc_change_event->sac_error = $10;
+	$$->value.sctp_assoc_change_event->sac_outbound_streams = $12;
+	$$->value.sctp_assoc_change_event->sac_inbound_streams = $14;
+	$$->value.sctp_assoc_change_event->sac_assoc_id = $16;
+	$$->value.sctp_assoc_change_event->sac_info = new_expression(EXPR_ELLIPSIS);
+}
+;
+
 opt_errno
 :                   { $$ = NULL; }
 | WORD note         {
diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c
index d81e4e5b992944c68c32cf08db96ee094222c5d3..121d47ede6545ded9cb3c76baaa0d508b5ac713b 100644
--- a/gtests/net/packetdrill/script.c
+++ b/gtests/net/packetdrill/script.c
@@ -86,6 +86,7 @@ struct expression_type_entry expression_type_table[] = {
 	{ EXPR_SCTP_RCVINFO,         "sctp_rcvinfo"    },
 	{ EXPR_SCTP_NXTINFO,         "sctp_nxtinfo"    },
 	{ EXPR_SCTP_RECVV_RN,        "sctp_recvv_rn "  },
+	{ EXPR_SCTP_ASSOC_CHANGE_EVENT,"sctp_assoc_change_event"},
 	{ EXPR_SCTP_SHUTDOWN_EVENT,  "sctp_shutdown_event"},
 	{ EXPR_SCTP_SENDER_DRY_EVENT,"sctp_sender_dry_event"},
 	{ NUM_EXPR_TYPES,            NULL}
@@ -431,6 +432,17 @@ void free_expression(struct expression *expression)
 		free_expression(expression->value.sctp_recvv_rn->recvv_rcvinfo);
 		free_expression(expression->value.sctp_recvv_rn->recvv_nxtinfo);
 		break;
+	case EXPR_SCTP_ASSOC_CHANGE_EVENT:
+		free_expression(expression->value.sctp_assoc_change_event->sac_type);
+		free_expression(expression->value.sctp_assoc_change_event->sac_flags);
+		free_expression(expression->value.sctp_assoc_change_event->sac_length);
+		free_expression(expression->value.sctp_assoc_change_event->sac_state);
+		free_expression(expression->value.sctp_assoc_change_event->sac_error);
+		free_expression(expression->value.sctp_assoc_change_event->sac_outbound_streams);
+		free_expression(expression->value.sctp_assoc_change_event->sac_inbound_streams);
+		free_expression(expression->value.sctp_assoc_change_event->sac_assoc_id);
+		free_expression(expression->value.sctp_assoc_change_event->sac_info);
+		break;
 	case EXPR_SCTP_SHUTDOWN_EVENT:
 		free_expression(expression->value.sctp_shutdown_event->sse_type);
 		free_expression(expression->value.sctp_shutdown_event->sse_flags);
@@ -1353,6 +1365,62 @@ static int evaluate_sctp_recvv_rn_expression(struct expression *in,
 	return STATUS_OK;
 }
 
+static int evaluate_sctp_assoc_change_event_expression(struct expression *in,
+						       struct expression *out,
+						       char **error)
+{
+	struct sctp_assoc_change_event_expr *in_event;
+	struct sctp_assoc_change_event_expr *out_event;
+
+	assert(in->type == EXPR_SCTP_ASSOC_CHANGE_EVENT);
+	assert(in->value.sctp_assoc_change_event);
+	assert(out->type == EXPR_SCTP_ASSOC_CHANGE_EVENT);
+
+	out->value.sctp_assoc_change_event = calloc(1, sizeof(struct sctp_assoc_change_event_expr));
+
+	in_event = in->value.sctp_assoc_change_event;
+	out_event = out->value.sctp_assoc_change_event;
+
+	if (evaluate(in_event->sac_type,
+		     &out_event->sac_type,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_event->sac_flags,
+		     &out_event->sac_flags,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_event->sac_length,
+		     &out_event->sac_length,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_event->sac_state,
+		     &out_event->sac_state,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_event->sac_error,
+		     &out_event->sac_error,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_event->sac_outbound_streams,
+		     &out_event->sac_outbound_streams,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_event->sac_inbound_streams,
+		     &out_event->sac_inbound_streams,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_event->sac_assoc_id,
+		     &out_event->sac_assoc_id,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_event->sac_info,
+		     &out_event->sac_info,
+		     error))
+		return STATUS_ERR;
+
+	return STATUS_OK;
+}
+
 static int evaluate_sctp_shutdown_event_expression(struct expression *in,
 						   struct expression *out,
 						   char **error)
@@ -1506,6 +1574,9 @@ static int evaluate(struct expression *in,
 	case EXPR_SCTP_RECVV_RN:
 		result = evaluate_sctp_recvv_rn_expression(in, out, error);
 		break;
+	case EXPR_SCTP_ASSOC_CHANGE_EVENT:
+		result = evaluate_sctp_assoc_change_event_expression(in, out, error);
+		break;
 	case EXPR_SCTP_SHUTDOWN_EVENT:
 		result = evaluate_sctp_shutdown_event_expression(in, out, error);
 		break;
diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h
index fbcf3009cdb2b57fd4b28b860359005638fa742d..40a96b42dfd7763bbee3ffec425ac9aba13f0dbd 100644
--- a/gtests/net/packetdrill/script.h
+++ b/gtests/net/packetdrill/script.h
@@ -66,6 +66,7 @@ enum expression_t {
 	EXPR_SCTP_RCVINFO,        /* struct sctp_rcvinfo for syscall sctp_recvv */
 	EXPR_SCTP_NXTINFO,        /* struct sctp_nxtinfo for syscall sctp_recvv */
 	EXPR_SCTP_RECVV_RN,       /* struct sctp_recvv_rn for syscall sctp_recvv */
+	EXPR_SCTP_ASSOC_CHANGE_EVENT, /* expression tree for sctp_assoc_change_event */
 	EXPR_SCTP_SHUTDOWN_EVENT, /* expression tree for sctp_shutdown_event */
 	EXPR_SCTP_SENDER_DRY_EVENT, /* expression tree for sctp_sender_dry_event */
 	NUM_EXPR_TYPES,
@@ -107,6 +108,7 @@ struct expression {
 		struct sctp_rcvinfo_expr *sctp_rcvinfo;
 		struct sctp_nxtinfo_expr *sctp_nxtinfo;
 		struct sctp_recvv_rn_expr *sctp_recvv_rn;
+		struct sctp_assoc_change_event_expr *sctp_assoc_change_event;
 		struct sctp_shutdown_event_expr *sctp_shutdown_event;
 		struct sctp_sender_dry_event_expr *sctp_sender_dry_event;
 	} value;
@@ -319,6 +321,19 @@ struct sctp_recvv_rn_expr {
 	struct expression *recvv_nxtinfo;
 };
 
+/* Parse tree for sctp_assoc_change_event for notifications. */
+struct sctp_assoc_change_event_expr {
+	struct expression *sac_type;
+	struct expression *sac_flags;
+	struct expression *sac_length;
+	struct expression *sac_state;
+	struct expression *sac_error;
+	struct expression *sac_outbound_streams;
+	struct expression *sac_inbound_streams;
+	struct expression *sac_assoc_id;
+	struct expression *sac_info;
+};
+
 /* Parse tree for sctp_shutdown_event for notifications. */
 struct sctp_shutdown_event_expr {
 	struct expression *sse_type;