diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l
index 3fcb49a0f77bbdf4b4fe84ad51da51e8cca11f33..36fa98fd3991fba1dc7426388cbfc21483e1a65a 100644
--- a/gtests/net/packetdrill/lexer.l
+++ b/gtests/net/packetdrill/lexer.l
@@ -228,6 +228,7 @@ ECNE			return ECNE;
 CWR			return CWR;
 SHUTDOWN_COMPLETE	return SHUTDOWN_COMPLETE;
 flgs			return FLAGS;
+len			return LEN;
 tag			return TAG;
 a_rwnd			return A_RWND;
 is			return IS;
diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index 6dbdf550a2965976c5ebc4f445a1f981eb22ea35..9608afcd7e898601c8e2b32c8de1fa21f592b0ec 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -499,7 +499,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %token <reserved> DATA INIT INIT_ACK HEARTBEAT HEARTBEAT_ACK ABORT
 %token <reserved> SHUTDOWN SHUTDOWN_ACK ERROR COOKIE_ECHO COOKIE_ACK ECNE CWR
 %token <reserved> SHUTDOWN_COMPLETE
-%token <reserved> FLAGS TAG A_RWND OS IS TSN SID SSN PPID GAPS DUPS
+%token <reserved> FLAGS LEN TAG A_RWND OS IS TSN SID SSN PPID GAPS DUPS
 %token <floating> FLOAT
 %token <integer> INTEGER HEX_INTEGER
 %token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR
@@ -551,7 +551,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %type <chunk_list_item> sctp_cookie_echo_chunk_spec sctp_cookie_ack_chunk_spec
 %type <chunk_list_item> sctp_ecne_chunk_spec sctp_cwr_chunk_spec
 %type <chunk_list_item> sctp_shutdown_complete_chunk_spec
-%type <integer> opt_flags
+%type <integer> opt_flags opt_data_chunk_len
 %type <integer> opt_a_rwnd opt_os opt_is opt_tsn opt_sid opt_ssn opt_ppid
 %type <sack_block_list> opt_gaps gap_list opt_dups dup_list
 %type <sack_block_list_item> gap dup
@@ -763,13 +763,22 @@ sctp_chunk_spec
 | sctp_shutdown_complete_chunk_spec { $$ = $1; }
 ;
 
+opt_data_chunk_len
+:                  { $$ = -1; }
+| LEN '=' INTEGER  {if (!is_valid_u16($3) ||
+                        $3 < sizeof(struct sctp_data_chunk)) {
+                      semantic_error("length value out of range");
+                    }
+                    $$ = $3;
+}
+
 opt_flags
 :                        { $$ = -1; }
 | FLAGS '=' HEX_INTEGER  {if (!is_valid_u8($3)) {
                             semantic_error("flags value out of range");
                           }
-                          $$ = $3;}
-;
+                          $$ = $3;
+}
 
 opt_a_rwnd
 :		{ $$ = -1; }
@@ -878,8 +887,8 @@ dup
 ;
 
 sctp_data_chunk_spec
-: DATA '[' opt_flags opt_tsn opt_sid opt_ssn opt_ppid ']' {
-	$$ = sctp_data_chunk_new($3, $4, $5, $6, $7);
+: DATA '[' opt_flags opt_data_chunk_len opt_tsn opt_sid opt_ssn opt_ppid ']' {
+	$$ = sctp_data_chunk_new($3, $4, $5, $6, $7, $8);
 }
 
 sctp_init_chunk_spec
diff --git a/gtests/net/packetdrill/sctp_packet.c b/gtests/net/packetdrill/sctp_packet.c
index 7731e80f39bf8a6967f8b2eee5891e0b22ffa396..8b7817bb31366f5c97401b8ab205a7af9dc9505e 100644
--- a/gtests/net/packetdrill/sctp_packet.c
+++ b/gtests/net/packetdrill/sctp_packet.c
@@ -126,23 +126,36 @@ sctp_chunk_list_item_new(struct sctp_chunk *chunk, u32 length, u32 flags)
 }
 
 struct sctp_chunk_list_item *
-sctp_data_chunk_new(s64 flgs, s64 tsn, s64 sid, s64 ssn, s64 ppid)
+sctp_data_chunk_new(s64 flgs, s64 len, s64 tsn, s64 sid, s64 ssn, s64 ppid)
 {
 	struct sctp_data_chunk *chunk;
 	u32 flags;
-	u16 payload_len = 1000;
+	u16 length, padding_length;
 
 	flags = 0;
-	chunk = malloc(sizeof(struct sctp_data_chunk) + payload_len);
+	if (len == -1) {
+		length = (u16)sizeof(struct sctp_data_chunk);
+	} else {
+		length = (u16)len;
+	}
+	padding_length = length % 4;
+	if (padding_length > 0) {
+		padding_length = 4 - padding_length;
+	}
+	chunk = malloc(length + padding_length);
 	assert(chunk != NULL);
 	chunk->type = SCTP_DATA_CHUNK_TYPE;
 	if (flgs == -1) {
 		chunk->flags = 0;
 		flags |= FLAG_CHUNK_FLAGS_NOCHECK;
 	} else {
-		chunk->flags = (u8)flgs;
+		 chunk->flags = (u8)flgs;
+	}
+	chunk->length = htons(length);
+	if (len == -1) {
+		flags |= FLAG_CHUNK_LENGTH_NOCHECK;
+		flags |= FLAG_CHUNK_VALUE_NOCHECK;
 	}
-	chunk->length = htons(sizeof(struct sctp_data_chunk) + payload_len);
 	if (tsn == -1) {
 		chunk->tsn = htonl(0);
 		flags |= FLAG_DATA_CHUNK_TSN_NOCHECK;
@@ -167,10 +180,10 @@ sctp_data_chunk_new(s64 flgs, s64 tsn, s64 sid, s64 ssn, s64 ppid)
 	} else {
 		chunk->ppid = htons((u32)ppid);
 	}
-	memset(chunk->data, 0, payload_len);
+	memset(chunk->data, 0,
+	       length + padding_length - sizeof(struct sctp_data_chunk));
 	return sctp_chunk_list_item_new((struct sctp_chunk *)chunk,
-	                                (u32)sizeof(struct sctp_data_chunk) + payload_len,
-	                                flags);
+	                                length, flags);
 }
 
 struct sctp_chunk_list_item *
diff --git a/gtests/net/packetdrill/sctp_packet.h b/gtests/net/packetdrill/sctp_packet.h
index 6f03fc71360e8baf7567931ae913e7078cc94407..6ac35603d36b5fb834fbb36b8865984ce96020bb 100644
--- a/gtests/net/packetdrill/sctp_packet.h
+++ b/gtests/net/packetdrill/sctp_packet.h
@@ -86,7 +86,7 @@ sctp_chunk_list_item_new(struct sctp_chunk *chunk, u32 length, u32 flags);
 #define FLAG_DATA_CHUNK_PPID_NOCHECK            0x00000800
 
 struct sctp_chunk_list_item *
-sctp_data_chunk_new(s64 flgs, s64 tsn, s64 sid, s64 ssn, s64 ppid);
+sctp_data_chunk_new(s64 flgs, s64 len, s64 tsn, s64 sid, s64 ssn, s64 ppid);
 
 #define FLAG_INIT_CHUNK_A_RWND_NOCHECK          0x00000100
 #define FLAG_INIT_CHUNK_OS_NOCHECK              0x00000200
diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_active.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_active.pkt
index 5b348acaf98ec1cc42ca21bfb6776aa19806a095..c08bb3dffa370a57b44dbafb692fac3dc2d59225 100644
--- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_active.pkt
+++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_active.pkt
@@ -13,15 +13,15 @@
 +0.0 > sctp: DATA[tsn=0 sid=0 ssn=0 ppid=0]
 +0.1 < sctp: SACK[tsn=0 a_rwnd=1500 gaps=[] dups=[]]
 // Receive some data
-+1.0 < sctp: DATA[flgs=0x3 tsn=3 sid=0 ssn=0 ppid=0] // How to handle
++1.0 < sctp: DATA[flgs=0x3 len=1016 tsn=3 sid=0 ssn=0 ppid=0] // How to handle
 +0.0 read(3, ..., 2000) = 1000
 +0.0 > sctp: SACK[tsn=3]
 // Receive more data, observe delayed SACK
-+1.0 < sctp: DATA[flgs=0x0b tsn=4 sid=0 ssn=1 ppid=0]
++1.0 < sctp: DATA[flgs=0x0b len=1016 tsn=4 sid=0 ssn=1 ppid=0]
 +0.0 read(3, ..., 2000) = 1000
 +0.0 > sctp: SACK[tsn=4]
 // Tear down the association
 +0.0 close(3) = 0
 +0.0 > sctp: SHUTDOWN[tsn=4]
 +0.1 < sctp: SHUTDOWN_ACK[]
-+0.0 > sctp: SHUTDOWN_COMPLETE[flgs=0x01]
++0.0 > sctp: SHUTDOWN_COMPLETE[]
diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_passive.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_passive.pkt
index 716c4c4e7be1f0da1536535c1d5e44301b3a3e32..b6b5c711b0fb2a3d5ee56db5f1922864ebcb8e3a 100644
--- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_passive.pkt
+++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_passive.pkt
@@ -4,7 +4,7 @@
 +0.0 listen(3, 1) = 0
 +0.0 < sctp: INIT[tag=1 a_rwnd=1500 os=1 is=1 tsn=0]
 +0.0 > sctp: INIT_ACK[tag=2 tsn=10] // faked cookie
-+0.1 < sctp: COOKIE_ECHO[]; DATA[tsn=0 sid=0 ssn=0 ppid=0]// syntax not clear
++0.1 < sctp: COOKIE_ECHO[]; DATA[flgs=0x03 len=1016 tsn=0 sid=0 ssn=0 ppid=0]// syntax not clear
 +0.0 > sctp: COOKIE_ACK[]; SACK[tsn=0]
 +0.0 accept(3, ..., ...) = 4
 +0.0 read(4, ..., 1000) = 1000
@@ -13,11 +13,11 @@
 +0.0 > sctp: DATA[tsn=10 sid=0 ssn=0 ppid=0]
 +0.1 < sctp: SACK[tsn=10 a_rwnd=1500 gaps=[] dups=[]]
 // Receive some data
-+1.0 < sctp: DATA[tsn=1 sid=0 ssn=1 ppid=0] // How to handle payload?
++1.0 < sctp: DATA[flgs=0x03 len=1016 tsn=1 sid=0 ssn=1 ppid=0] // How to handle payload?
 +0.0 read(4, ..., 2000) = 1000
 +0.2 > sctp: SACK[tsn=1]
 // Receive more data, observe delayed SACKi
-+1.0 < sctp: DATA[tsn=2 sid=0 ssn=2 ppid=0]
++1.0 < sctp: DATA[flgs=0x03 len=1016 tsn=2 sid=0 ssn=2 ppid=0]
 +0.0 read(4, ..., 2000) = 1000
 +0.2 > sctp: SACK[tsn=2]
 // Tear down the association