diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l
index 4d92cdb9bc9baf1b66338f8573ccd5315471b719..4cadbae7f5436d244f6479e5fb95c64902e1a442 100644
--- a/gtests/net/packetdrill/lexer.l
+++ b/gtests/net/packetdrill/lexer.l
@@ -348,6 +348,9 @@ sai_length                      return SAI_LENGTH;
 sai_flags                       return SAI_FLAGS;
 sai_adaptation_ind              return SAI_ADAPTATION_IND;
 sai_assoc_id                    return SAI_ASSOC_ID;
+sn_type                         return SN_TYPE;
+sn_length                       return SN_LENGTH;
+sn_flags                        return SN_FLAGS;
 CHUNK				return CHUNK;
 DATA				return DATA;
 INIT				return INIT;
diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index 7771e687b4ad8912c937c719e66c555ad3aaa66d..f2d3fc5deb09b0981ccb4f69fdd185ebae8b92f3 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -562,6 +562,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %token <reserved> SPC_TYPE SPC_FLAGS SPC_LENGTH SPC_AADDR SPC_STATE SPC_ERROR SPC_ASSOC_ID
 %token <reserved> SSF_TYPE SSF_LENGTH SSF_FLAGS SSF_ERROR SSF_INFO SSF_ASSOC_ID SSF_DATA
 %token <reserved> SAI_TYPE SAI_FLAGS SAI_LENGTH SAI_ADAPTATION_IND SAI_ASSOC_ID
+%token <reserved> SN_TYPE SN_FLAGS SN_LENGTH
 %token <floating> FLOAT
 %token <integer> INTEGER HEX_INTEGER
 %token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR
@@ -629,6 +630,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %type <expression> sctp_paddr_change spc_type spc_flags spc_length spc_aaddr spc_error spc_state spc_assoc_id
 %type <expression> sctp_send_failed ssf_type ssf_length ssf_flags ssf_error ssf_info ssf_assoc_id ssf_data
 %type <expression> sctp_adaptation_event sai_type sai_flags sai_length sai_adaptation_ind sai_assoc_id
+%type <expression> sctp_tlv sn_type sn_flags sn_length
 %type <errno_info> opt_errno
 %type <chunk_list> sctp_chunk_list_spec
 %type <chunk_list_item> sctp_chunk_spec
@@ -2613,6 +2615,7 @@ data
 | sctp_sender_dry_event     { $$ = $1; }
 | sctp_send_failed_event    { $$ = $1; }
 | sctp_authkey_event        { $$ = $1; }
+| sctp_tlv                  { $$ = $1; }
 ;
 
 msghdr
@@ -4324,6 +4327,50 @@ sctp_adaptation_event
 }
 ;
 
+sn_type
+: SN_TYPE '=' INTEGER {
+	if (!is_valid_u16($3)) {
+		semantic_error("sn_type out of range");
+	}
+	$$ = new_integer_expression($3, "%hu");
+}
+| SN_TYPE '=' WORD {
+	$$ = new_expression(EXPR_WORD);
+	$$->value.string = $3;
+}
+| SN_TYPE '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sn_flags
+: SN_FLAGS '=' INTEGER {
+	if (!is_valid_u16($3)) {
+		semantic_error("sn_flags out of range");
+	}
+	$$ = new_integer_expression($3, "%hu");
+}
+| SN_FLAGS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sn_length
+: SN_LENGTH '=' INTEGER {
+	if (!is_valid_u32($3)) {
+		semantic_error("sn_length out of range");
+	}
+	$$ = new_integer_expression($3, "%u");
+}
+| SN_LENGTH '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sctp_tlv
+: '{' sn_type ',' sn_flags ',' sn_length '}' {
+	$$ = new_expression(EXPR_SCTP_TLV);
+	$$->value.sctp_tlv = calloc(1, sizeof(struct sctp_tlv_expr));
+	$$->value.sctp_tlv->sn_type = $2;
+	$$->value.sctp_tlv->sn_flags = $4;
+	$$->value.sctp_tlv->sn_length = $6;
+}
+;
+
 opt_errno
 :                   { $$ = NULL; }
 | WORD note         {
diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c
index 4ede3caf0ec065069829089a711cde58e4f98748..c54a41b58000e0059c0ac12304c4d3a2d1a19a40 100644
--- a/gtests/net/packetdrill/run_system_call.c
+++ b/gtests/net/packetdrill/run_system_call.c
@@ -576,7 +576,8 @@ static int iovec_new(struct expression *expression,
 		       iov_expr->iov_base->type == EXPR_SCTP_PDAPI_EVENT ||
 		       iov_expr->iov_base->type == EXPR_SCTP_AUTHKEY_EVENT ||
 		       iov_expr->iov_base->type == EXPR_SCTP_SENDER_DRY_EVENT ||
-		       iov_expr->iov_base->type == EXPR_SCTP_SEND_FAILED_EVENT);
+		       iov_expr->iov_base->type == EXPR_SCTP_SEND_FAILED_EVENT ||
+		       iov_expr->iov_base->type == EXPR_SCTP_TLV);
 		assert(iov_expr->iov_len->type == EXPR_INTEGER);
 
 		len = iov_expr->iov_len->value.num;
@@ -3682,6 +3683,21 @@ static int check_sctp_send_failed_event(struct sctp_send_failed_event_expr *expr
 }
 #endif
 
+#if defined(__FreeBSD__) || defined(linux)
+static int check_sctp_tlv(struct sctp_tlv_expr *expr, struct sctp_tlv *sctp_tlv, char **error) {
+	if (check_u16_expr(expr->sn_type, sctp_tlv->sn_type,
+			   "sctp_tlv.sn_type", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sn_flags, sctp_tlv->sn_flags,
+			   "sctp_tlv.sn_flags", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->sn_length, sctp_tlv->sn_length,
+			   "sctp_tlv.sn_length", error))
+		return STATUS_ERR;
+	return STATUS_OK;
+}
+#endif
+
 #if defined(__FreeBSD__) || defined(linux)
 static int check_sctp_notification(struct iovec *iov,
 				   struct expression *iovec_expr,
@@ -3762,6 +3778,12 @@ static int check_sctp_notification(struct iovec *iov,
 				return STATUS_ERR;
 			break;
 #endif
+		case EXPR_SCTP_TLV:
+			if (check_sctp_tlv(script_iov_base->value.sctp_tlv,
+					   (struct sctp_tlv *) iov[i].iov_base,
+					    error))
+				return STATUS_ERR;
+			break;
 		case EXPR_ELLIPSIS:
 			printf("check Ellipsis\n");
 			break;
diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c
index f119c512f6ec384f53e54c2a1b291a1f00303e84..336374356ad389bd00034b6d481c417767d348d8 100644
--- a/gtests/net/packetdrill/script.c
+++ b/gtests/net/packetdrill/script.c
@@ -96,6 +96,7 @@ struct expression_type_entry expression_type_table[] = {
 	{ EXPR_SCTP_AUTHKEY_EVENT,   "sctp_authkey_event"},
 	{ EXPR_SCTP_SENDER_DRY_EVENT,"sctp_sender_dry_event"},
 	{ EXPR_SCTP_SEND_FAILED_EVENT,"sctp_send_failed_event"},
+	{ EXPR_SCTP_TLV,             "sctp_tlv"        },
 	{ NUM_EXPR_TYPES,            NULL}
 };
 
@@ -520,6 +521,11 @@ void free_expression(struct expression *expression)
 		free_expression(expression->value.sctp_send_failed_event->ssfe_assoc_id);
 		free_expression(expression->value.sctp_send_failed_event->ssfe_data);
 		break;
+	case EXPR_SCTP_TLV:
+		free_expression(expression->value.sctp_tlv->sn_type);
+		free_expression(expression->value.sctp_tlv->sn_flags);
+		free_expression(expression->value.sctp_tlv->sn_length);
+		break;
 	case EXPR_WORD:
 		assert(expression->value.string);
 		free(expression->value.string);
@@ -1874,6 +1880,37 @@ static int evaluate_sctp_send_failed_event_expression(struct expression *in,
 	return STATUS_OK;
 }
 
+static int evaluate_sctp_tlv_expression(struct expression *in,
+					struct expression *out,
+					char **error)
+{
+	struct sctp_tlv_expr *in_tlv;
+	struct sctp_tlv_expr *out_tlv;
+
+	assert(in->type == EXPR_SCTP_TLV);
+	assert(in->value.sctp_tlv);
+	assert(out->type == EXPR_SCTP_TLV);
+
+	out->value.sctp_tlv = calloc(1, sizeof(struct sctp_tlv_expr));
+
+	in_tlv = in->value.sctp_tlv;
+	out_tlv = out->value.sctp_tlv;
+
+	if (evaluate(in_tlv->sn_type,
+		     &out_tlv->sn_type,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_tlv->sn_flags,
+		     &out_tlv->sn_flags,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_tlv->sn_length,
+		     &out_tlv->sn_length,
+		     error))
+		return STATUS_ERR;
+	return STATUS_OK;
+}
+
 static int evaluate(struct expression *in,
 		    struct expression **out_ptr, char **error)
 {
@@ -1989,6 +2026,9 @@ static int evaluate(struct expression *in,
 	case EXPR_SCTP_SEND_FAILED_EVENT:
 		result = evaluate_sctp_send_failed_event_expression(in, out, error);
 		break;
+	case EXPR_SCTP_TLV:
+		result = evaluate_sctp_tlv_expression(in, out, error);
+		break;
 	case EXPR_WORD:
 		out->type = EXPR_INTEGER;
 		if (symbol_to_int(in->value.string,
diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h
index 26264d74a26dbce9db32e946e147ed09e4856865..bb60524ff45952a372108df958fdfbef5f63567a 100644
--- a/gtests/net/packetdrill/script.h
+++ b/gtests/net/packetdrill/script.h
@@ -76,6 +76,7 @@ enum expression_t {
 	EXPR_SCTP_AUTHKEY_EVENT,  /* expression tree for sctp_authentication_event */
 	EXPR_SCTP_SENDER_DRY_EVENT, /* expression tree for sctp_sender_dry_event */
 	EXPR_SCTP_SEND_FAILED_EVENT, /* expression tree for sctp_send_failed_event */
+	EXPR_SCTP_TLV,            /* expression tree for sctp_notifications_stopped_event */
 	NUM_EXPR_TYPES,
 };
 /* Convert an expression type to a human-readable string */
@@ -125,6 +126,7 @@ struct expression {
 		struct sctp_authkey_event_expr *sctp_authkey_event;
 		struct sctp_sender_dry_event_expr *sctp_sender_dry_event;
 		struct sctp_send_failed_event_expr *sctp_send_failed_event;
+		struct sctp_tlv_expr *sctp_tlv;
 	} value;
 	const char *format;	/* the printf format for printing the value */
 };
@@ -436,6 +438,13 @@ struct sctp_send_failed_event_expr {
 	struct expression *ssfe_data;
 };
 
+/* Parse tree for sctp_tlv for notifications. */
+struct sctp_tlv_expr {
+	struct expression *sn_type;
+	struct expression *sn_flags;
+	struct expression *sn_length;
+};
+
 /* 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/notifications/sctp_notifications_stopped_event.pkt b/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_notifications_stopped_event.pkt
new file mode 100644
index 0000000000000000000000000000000000000000..6adecb8f05d09a6964e5db5d966391bbfe01e71b
--- /dev/null
+++ b/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_notifications_stopped_event.pkt
@@ -0,0 +1,17 @@
++0.0 socket(..., SOCK_STREAM, IPPROTO_SCTP) = 3
++0.0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
++0.0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+// Check the handshake with an empty(!) cookie
++0.1 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress)
++0.0 setsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_ADAPTATION_INDICATION, se_on=1}, 8) = 0
++0.0 getsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_ADAPTATION_INDICATION, se_on=1}, [8]) = 0
++0.0 setsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_NOTIFICATIONS_STOPPED_EVENT, se_on=1}, 8) = 0
+
++0.0 > sctp: INIT[flgs=0, tag=1, a_rwnd=..., os=..., is=..., tsn=1, ...]
++0.1 < sctp: INIT_ACK[flgs=0, tag=2, a_rwnd=1500, os=1, is=1, tsn=1, STATE_COOKIE[len=4, val=...]]
++0.0 > sctp: COOKIE_ECHO[flgs=0, len=4, val=...]
++0.1 < sctp: COOKIE_ACK[flgs=0]
+// No implementation provides this messages, so it can't be tested
+// as discribed in rfc, create an notification storm so that the implementation disable notifications
++0.0 sctp_recvv(3, [{iov_base={sn_type=SCTP_NOTIFICATIONS_STOPPED_EVENT, sn_flags=0, sn_length=8}, iov_len=1000}], 1,
+..., 20, NULL, [0], [SCTP_RECVV_NOINFO],[MSG_NOTIFICATION|MSG_EOR]) = 21