diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l
index f31c6d0f86ef82262248c2a6a45e444fd29b03c4..cc94918d6ffe3730631e20d34a9f0f903caf2fcb 100644
--- a/gtests/net/packetdrill/lexer.l
+++ b/gtests/net/packetdrill/lexer.l
@@ -306,6 +306,12 @@ 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;
+sre_type                        return SRE_TYPE;
+sre_flags                       return SRE_FLAGS;
+sre_length                      return SRE_LENGTH;
+sre_error                       return SRE_ERROR;
+sre_assoc_id                    return SRE_ASSOC_ID;
+sre_data                        return SRE_DATA;
 auth_type                       return AUTH_TYPE;
 auth_flags                      return AUTH_FLAGS;
 auth_length                     return AUTH_LENGTH;
diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index 14838d613145e41603fb7db3acbd9eb70e1bbf58..f88812d586196682fed3cc2258085091542d4f76 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -557,6 +557,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %token <reserved> SAC_INBOUND_STREAMS SAC_ASSOC_ID SAC_INFO
 %token <reserved> SSFE_TYPE SSFE_FLAGS SSFE_LENGTH SSFE_ERROR SSFE_INFO SSFE_ASSOC_ID SSFE_DATA
 %token <reserved> AUTH_TYPE AUTH_FLAGS AUTH_LENGTH AUTH_INDICATION AUTH_ASSOC_ID
+%token <reserved> SRE_TYPE SRE_FLAGS SRE_LENGTH SRE_ERROR SRE_ASSOC_ID SRE_DATA
 %token <floating> FLOAT
 %token <integer> INTEGER HEX_INTEGER
 %token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR
@@ -619,6 +620,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %type <expression> sac_inbound_streams sac_assoc_id sac_info
 %type <expression> sctp_send_failed_event ssfe_type ssfe_flags ssfe_length ssfe_error ssfe_assoc_id
 %type <expression> sctp_authkey_event auth_type auth_flags auth_length auth_keynumber auth_indication auth_assoc_id
+%type <expression> sctp_remote_error sre_type sre_flags sre_length sre_error sre_assoc_id sre_data
 %type <errno_info> opt_errno
 %type <chunk_list> sctp_chunk_list_spec
 %type <chunk_list_item> sctp_chunk_spec
@@ -2594,6 +2596,7 @@ sockaddr
 data
 : ELLIPSIS { new_expression(EXPR_ELLIPSIS); }
 | sctp_assoc_change         { $$ = $1; }
+| sctp_remote_error         { $$ = $1; }
 | sctp_shutdown_event       { $$ = $1; }
 | sctp_sender_dry_event     { $$ = $1; }
 | sctp_send_failed_event    { $$ = $1; }
@@ -3899,6 +3902,78 @@ sac_inbound_streams ',' sac_assoc_id ',' sac_info '}' {
 }
 ;
 
+sre_type
+: SRE_TYPE '=' INTEGER {
+	if (!is_valid_u16($3)) {
+		semantic_error("sre_type out of range");
+	}
+	$$ = new_integer_expression($3, "%hu");
+}
+| SRE_TYPE '=' WORD {
+	$$ = new_expression(EXPR_WORD);
+	$$->value.string = $3;
+}
+| SRE_TYPE '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sre_flags
+: SRE_FLAGS '=' INTEGER {
+	if (!is_valid_u16($3)) {
+		semantic_error("sre_flags out of range");
+	}
+	$$ = new_integer_expression($3, "%hu");
+}
+| SRE_FLAGS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sre_length
+: SRE_LENGTH '=' INTEGER {
+	if (!is_valid_u32($3)) {
+		semantic_error("sre_length out of range");
+	}
+	$$ = new_integer_expression($3, "%u");
+}
+| SRE_LENGTH '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sre_error
+: SRE_ERROR '=' INTEGER {
+	if (!is_valid_u16($3)) {
+		semantic_error("sre_error out of range");
+	}
+	$$ = new_integer_expression($3, "%hu");
+}
+| SRE_ERROR '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sre_assoc_id
+: SRE_ASSOC_ID '=' INTEGER {
+	if (!is_valid_u32($3)) {
+		semantic_error("sre_assoc_id out of range");
+	}
+	$$ = new_integer_expression($3, "%u");
+}
+| SRE_ASSOC_ID '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+;
+
+sre_data
+: SRE_DATA '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); }
+| SRE_DATA '=' array { $$ = $3; }
+;
+
+sctp_remote_error
+: '{' sre_type ',' sre_flags ',' sre_length ',' sre_error ',' sre_assoc_id ',' sre_data '}' {
+	$$ = new_expression(EXPR_SCTP_REMOTE_ERROR);
+	$$->value.sctp_remote_error = calloc(1, sizeof(struct sctp_remote_error_expr));
+	$$->value.sctp_remote_error->sre_type = $2;
+	$$->value.sctp_remote_error->sre_flags = $4;
+	$$->value.sctp_remote_error->sre_length = $6;
+	$$->value.sctp_remote_error->sre_error = $8;
+	$$->value.sctp_remote_error->sre_assoc_id = $10;
+	$$->value.sctp_remote_error->sre_data = $12;
+}
+;
+
 opt_errno
 :                   { $$ = NULL; }
 | WORD note         {
diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c
index b26843f797aff42dae5ca68a39799e9d4fdf11ce..fe1c166e48be4a9d8f400438ba56648ac8e73d23 100644
--- a/gtests/net/packetdrill/run_system_call.c
+++ b/gtests/net/packetdrill/run_system_call.c
@@ -527,6 +527,7 @@ static int iovec_new(struct expression *expression,
 
 		assert(iov_expr->iov_base->type == EXPR_ELLIPSIS ||
 		       iov_expr->iov_base->type == EXPR_SCTP_ASSOC_CHANGE ||
+		       iov_expr->iov_base->type == EXPR_SCTP_REMOTE_ERROR ||
 		       iov_expr->iov_base->type == EXPR_SCTP_SHUTDOWN_EVENT ||
 		       iov_expr->iov_base->type == EXPR_SCTP_AUTHKEY_EVENT ||
 		       iov_expr->iov_base->type == EXPR_SCTP_SENDER_DRY_EVENT ||
@@ -3339,6 +3340,46 @@ static int check_sctp_nxtinfo(struct sctp_nxtinfo_expr *expr,
 }
 #endif
 
+static int check_u8array_expr(struct expression *expr_list, u8 *data, size_t data_len, char *val_name, char **error) {
+	if ( expr_list->type != EXPR_ELLIPSIS) {
+		struct expression *expr = NULL;
+		unsigned int i;
+
+		switch(expr_list->type) {
+		case EXPR_LIST:
+			if (data_len != expression_list_length(expr_list->value.list)) {
+				asprintf(error, "%s length: expected: %u actual %zu",
+					 val_name, expression_list_length(expr_list->value.list), data_len);
+				return STATUS_ERR;
+			}
+			for (i = 0; i < data_len; i++) {
+				expr = get_arg(expr_list->value.list, i, error);
+				if (expr->type != EXPR_ELLIPSIS) {
+					u8 script_val;
+
+					if (get_u8(expr, &script_val, error)) {
+						return STATUS_ERR;
+					}
+					if (script_val != data[i]) {
+						asprintf(error, "%s[%d]: expected: %hhu actual: %hhu",
+							val_name, i, script_val, data[i]);
+						return STATUS_ERR;
+					}
+				}
+			}
+			break;
+		case EXPR_NULL:
+			if (data != NULL)
+				return STATUS_ERR;
+			break;
+		default: asprintf(error, "Bad expressiontype for sac_info");
+			return STATUS_ERR;
+			break;
+		}
+	}
+	return STATUS_OK;
+}
+
 #if defined(__FreeBSD__) || defined(linux)
 static int check_sctp_assoc_change(struct sctp_assoc_change_expr *expr,
 				   struct sctp_assoc_change *sctp_event,
@@ -3367,40 +3408,36 @@ static int check_sctp_assoc_change(struct sctp_assoc_change_expr *expr,
 	if (check_u32_expr(expr->sac_assoc_id, sctp_event->sac_assoc_id,
 			   "sctp_assoc_change.sac_assoc_id", error))
 		return STATUS_ERR;
-	if ( expr->sac_info->type != EXPR_ELLIPSIS) {
-		size_t infolen;
-		struct expression *info_expr = NULL;
-		unsigned int i;
-
-		infolen = sctp_event->sac_length - sizeof(struct sctp_assoc_change);
-		switch(expr->sac_info->type) {
-		case EXPR_LIST:
-			if (infolen != expression_list_length(expr->sac_info->value.list)) {
-				asprintf(error, "sctp_assoc_change.sac_info length: expected: %u actual %zu",
-					 expression_list_length(expr->sac_info->value.list), infolen);
-				return STATUS_ERR;
-			}
-			for (i = 0; i < infolen; i++) {
-				info_expr = get_arg(expr->sac_info->value.list, i, error);
-				if (info_expr->type != EXPR_ELLIPSIS) {
-					u8 script_val;
+	if (check_u8array_expr(expr->sac_info, sctp_event->sac_info, sctp_event->sac_length - sizeof(struct sctp_assoc_change),
+			       "sctp_assoc_change.sac_info", error))
+			return STATUS_ERR;
+	return STATUS_OK;
+}
+#endif
 
-					if (get_u8(info_expr, &script_val, error)) {
-						return STATUS_ERR;
-					}
-					if (script_val != sctp_event->sac_info[i]) {
-						asprintf(error, "sctp_assoc_change.sac_info[%d]: expected: %hhu actual: %hhu",
-							i, script_val, sctp_event->sac_info[i]);
-						return STATUS_ERR;
-					}
-				}
-			}
-			break;
-		default: asprintf(error, "Bad expressiontype for sac_info");
+#if defined(__FreeBSD__) || defined(linux)
+static int check_sctp_remote_error(struct sctp_remote_error_expr *expr,
+				   struct sctp_remote_error *sctp_event,
+				   char **error) {
+	if (check_u16_expr(expr->sre_type, sctp_event->sre_type,
+			   "sctp_remote_error.sre_type", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sre_flags, sctp_event->sre_flags,
+			   "sctp_remote_error.sre_flags", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->sre_length, sctp_event->sre_length,
+			   "sctp_remote_error.sre_length", error))
+		return STATUS_ERR;
+	if (check_u16_expr(expr->sre_error, sctp_event->sre_error,
+			   "sctp_remote_error.sre_error", error))
+		return STATUS_ERR;
+	if (check_u32_expr(expr->sre_assoc_id, sctp_event->sre_assoc_id,
+			   "sctp_remote_error.sre_assoc_id", error))
+		return STATUS_ERR;
+	if (check_u8array_expr(expr->sre_data, sctp_event->sre_data, sctp_event->sre_length - sizeof(struct sctp_remote_error),
+			       "sctp_remote_error.sre_data", error))
 			return STATUS_ERR;
-			break;
-		}
-	}
+
 	return STATUS_OK;
 }
 #endif
@@ -3526,6 +3563,12 @@ static int check_sctp_notification(struct iovec *iov,
 						    error))
 				return STATUS_ERR;
 			break;
+		case EXPR_SCTP_REMOTE_ERROR:
+			if (check_sctp_remote_error(script_iov_base->value.sctp_remote_error,
+						    (struct sctp_remote_error *) iov->iov_base,
+						    error))
+				return STATUS_ERR;
+			break;
 		case EXPR_SCTP_SHUTDOWN_EVENT:
 			if (check_sctp_shutdown_event(script_iov_base->value.sctp_shutdown_event,
 						      (struct sctp_shutdown_event *) iov->iov_base,
diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c
index a20c7f14d4f2eda680fd327bcff566a2bf3c610a..0ed1f1e636c5bf5c0eec13b11fca5826caa4754e 100644
--- a/gtests/net/packetdrill/script.c
+++ b/gtests/net/packetdrill/script.c
@@ -87,6 +87,7 @@ struct expression_type_entry expression_type_table[] = {
 	{ EXPR_SCTP_NXTINFO,         "sctp_nxtinfo"    },
 	{ EXPR_SCTP_RECVV_RN,        "sctp_recvv_rn "  },
 	{ EXPR_SCTP_ASSOC_CHANGE,    "sctp_assoc_change"},
+	{ EXPR_SCTP_REMOTE_ERROR,    "sctp_remote_error"},
 	{ EXPR_SCTP_SHUTDOWN_EVENT,  "sctp_shutdown_event"},
 	{ EXPR_SCTP_AUTHKEY_EVENT,   "sctp_authkey_event"},
 	{ EXPR_SCTP_SENDER_DRY_EVENT,"sctp_sender_dry_event"},
@@ -445,6 +446,14 @@ void free_expression(struct expression *expression)
 		free_expression(expression->value.sctp_assoc_change->sac_assoc_id);
 		free_expression(expression->value.sctp_assoc_change->sac_info);
 		break;
+	case EXPR_SCTP_REMOTE_ERROR:
+		free_expression(expression->value.sctp_remote_error->sre_type);
+		free_expression(expression->value.sctp_remote_error->sre_flags);
+		free_expression(expression->value.sctp_remote_error->sre_length);
+		free_expression(expression->value.sctp_remote_error->sre_error);
+		free_expression(expression->value.sctp_remote_error->sre_assoc_id);
+		free_expression(expression->value.sctp_remote_error->sre_data);
+		break;
 	case EXPR_SCTP_SHUTDOWN_EVENT:
 		free_expression(expression->value.sctp_shutdown_event->sse_type);
 		free_expression(expression->value.sctp_shutdown_event->sse_flags);
@@ -1384,8 +1393,8 @@ static int evaluate_sctp_recvv_rn_expression(struct expression *in,
 }
 
 static int evaluate_sctp_assoc_change_expression(struct expression *in,
-						       struct expression *out,
-						       char **error)
+					         struct expression *out,
+					         char **error)
 {
 	struct sctp_assoc_change_expr *in_event;
 	struct sctp_assoc_change_expr *out_event;
@@ -1439,6 +1448,50 @@ static int evaluate_sctp_assoc_change_expression(struct expression *in,
 	return STATUS_OK;
 }
 
+static int evaluate_sctp_remote_error_expression(struct expression *in,
+					         struct expression *out,
+						 char **error)
+{
+	struct sctp_remote_error_expr *in_event;
+	struct sctp_remote_error_expr *out_event;
+
+	assert(in->type == EXPR_SCTP_REMOTE_ERROR);
+	assert(in->value.sctp_remote_error);
+	assert(out->type == EXPR_SCTP_REMOTE_ERROR);
+
+	out->value.sctp_remote_error = calloc(1, sizeof(struct sctp_remote_error_expr));
+
+	in_event = in->value.sctp_remote_error;
+	out_event = out->value.sctp_remote_error;
+
+	if (evaluate(in_event->sre_type,
+		     &out_event->sre_type,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_event->sre_flags,
+		     &out_event->sre_flags,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_event->sre_length,
+		     &out_event->sre_length,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_event->sre_error,
+		     &out_event->sre_error,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_event->sre_assoc_id,
+		     &out_event->sre_assoc_id,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_event->sre_data,
+		     &out_event->sre_data,
+		     error))
+		return STATUS_ERR;
+
+	return STATUS_OK;
+}
+
 static int evaluate_sctp_shutdown_event_expression(struct expression *in,
 						   struct expression *out,
 						   char **error)
@@ -1687,6 +1740,9 @@ static int evaluate(struct expression *in,
 	case EXPR_SCTP_ASSOC_CHANGE:
 		result = evaluate_sctp_assoc_change_expression(in, out, error);
 		break;
+	case EXPR_SCTP_REMOTE_ERROR:
+		result = evaluate_sctp_remote_error_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 fdf4a7f148ccec9a679fadae22391a240a8c1667..82e269719df2aa46cb264ef5b702f7af173e2003 100644
--- a/gtests/net/packetdrill/script.h
+++ b/gtests/net/packetdrill/script.h
@@ -67,6 +67,7 @@ enum expression_t {
 	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,   /* expression tree for sctp_assoc_change_event */
+	EXPR_SCTP_REMOTE_ERROR,   /* expression tree for sctp_remote_error_event */
 	EXPR_SCTP_SHUTDOWN_EVENT, /* expression tree for sctp_shutdown_event */
 	EXPR_SCTP_AUTHKEY_EVENT,  /* expression tree for sctp_authentication_event */
 	EXPR_SCTP_SENDER_DRY_EVENT, /* expression tree for sctp_sender_dry_event */
@@ -111,6 +112,7 @@ struct expression {
 		struct sctp_nxtinfo_expr *sctp_nxtinfo;
 		struct sctp_recvv_rn_expr *sctp_recvv_rn;
 		struct sctp_assoc_change_expr *sctp_assoc_change;
+		struct sctp_remote_error_expr *sctp_remote_error;
 		struct sctp_shutdown_event_expr *sctp_shutdown_event;
 		struct sctp_authkey_event_expr *sctp_authkey_event;
 		struct sctp_sender_dry_event_expr *sctp_sender_dry_event;
@@ -338,6 +340,15 @@ struct sctp_assoc_change_expr {
 	struct expression *sac_info;
 };
 
+/* Parse tree for sctp_assoc_change for notifications. */
+struct sctp_remote_error_expr {
+	struct expression *sre_type;
+	struct expression *sre_flags;
+	struct expression *sre_length;
+	struct expression *sre_error;
+	struct expression *sre_assoc_id;
+	struct expression *sre_data;
+};
 /* Parse tree for sctp_shutdown_event for notifications. */
 struct sctp_shutdown_event_expr {
 	struct expression *sse_type;
diff --git a/gtests/net/packetdrill/symbols_freebsd.c b/gtests/net/packetdrill/symbols_freebsd.c
index d4ee1bef97420a83a94e6778e7aee9e60b66946c..5a54612f9c633b4af06d72afaa28fa6a2cca1504 100644
--- a/gtests/net/packetdrill/symbols_freebsd.c
+++ b/gtests/net/packetdrill/symbols_freebsd.c
@@ -168,7 +168,6 @@ struct int_symbol platform_symbols_table[] = {
 	{ SCTP_PEER_ADDR_CHANGE,            "SCTP_PEER_ADDR_CHANGE"           },
 	{ SCTP_REMOTE_ERROR,                "SCTP_REMOTE_ERROR"               },
 	{ SCTP_SEND_FAILED,                 "SCTP_SEND_FAILED"                },
-	{ SCTP_ASSOC_CHANGE,                "SCTP_ASSOC_CHANGE"               },
 	{ SCTP_SHUTDOWN_EVENT,              "SCTP_SHUTDOWN_EVENT"             },
 	{ SCTP_SENDER_DRY_EVENT,            "SCTP_SENDER_DRY_EVENT"           },
 	{ SCTP_SEND_FAILED_EVENT,           "SCTP_SEND_FAILED_EVENT"          },
@@ -177,7 +176,6 @@ struct int_symbol platform_symbols_table[] = {
 	{ SCTP_PARTIAL_DELIVERY_EVENT,      "SCTP_PARTIAL_DELIVERY_EVENT"     },
 	{ SCTP_AUTHENTICATION_EVENT,        "SCTP_AUTHENTICATION_EVENT"       },
 	{ SCTP_STREAM_RESET_EVENT,          "SCTP_STREAM_RESET_EVENT"         },
-	{ SCTP_SENDER_DRY_EVENT,            "SCTP_SENDER_DRY_EVENT"           },
 	{ SCTP_NOTIFICATIONS_STOPPED_EVENT, "SCTP_NOTIFICATIONS_STOPPED_EVENT"},
 	{ SCTP_ASSOC_RESET_EVENT,           "SCTP_ASSOC_RESET_EVENT"          },
 	{ SCTP_STREAM_CHANGE_EVENT,         "SCTP_STREAM_CHANGE_EVENT"        },
diff --git a/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_remote_error.pkt b/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_remote_error.pkt
new file mode 100644
index 0000000000000000000000000000000000000000..4d245235197b7f22585e70aa63536206b03cb82d
--- /dev/null
+++ b/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_remote_error.pkt
@@ -0,0 +1,19 @@
++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_REMOTE_ERROR, se_on=1}, 8) = 0
++0.0 getsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_REMOTE_ERROR, 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]
+
++0.0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
+
++0.0 < sctp: ERROR[flgs=0, INVALID_STREAM_IDENTIFIER[sid=1]]
+
++0.0 sctp_recvv(3, [{iov_base={sre_type=SCTP_REMOTE_ERROR, sre_flags=0, sre_length=32, sre_error=1,
+sre_assoc_id=..., sre_data=[0x09, 0x00, 0x00 , 0x0C, 0x00, 0x01, 0x00 , 0x08, 0x00, 0x01, 0x00 , 0x00]}, iov_len=1000}], 1, ..., 20, NULL, [0], [SCTP_RECVV_NOINFO],
+[MSG_NOTIFICATION|MSG_EOR]) = 32