diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index 7a91d334f8891059d78aef1adfd1f0eccbef401e..da6c940c9cc0da85e00d891a0a031a89aa47e8fc 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -951,7 +951,8 @@ opt_shutdown_complete_flags
 ;
 
 opt_tag
-: TAG '=' INTEGER {
+: TAG '=' ELLIPSIS { $$ = -1; }
+| TAG '=' INTEGER  {
 	if (!is_valid_u32($3)) {
 		semantic_error("tag value out of range");
 	}
@@ -1098,23 +1099,11 @@ sctp_data_chunk_spec
 
 sctp_init_chunk_spec
 : INIT '[' opt_flags ',' opt_tag ',' opt_a_rwnd ',' opt_os ',' opt_is ',' opt_tsn opt_parameter_list_spec ']' {
-	if ($5 == -1) {
-		semantic_error("tag value must be specified");
-	}
-	if ($13 == -1) {
-		semantic_error("tsn value must be specified");
-	}
 	$$ = sctp_init_chunk_new($3, $5, $7, $9, $11, $13, $14);
 }
 
 sctp_init_ack_chunk_spec
 : INIT_ACK '[' opt_flags ',' opt_tag ',' opt_a_rwnd ',' opt_os ',' opt_is ',' opt_tsn opt_parameter_list_spec ']' {
-	if ($5 == -1) {
-		semantic_error("tag value must be specified");
-	}
-	if ($13 == -1) {
-		semantic_error("tsn value must be specified");
-	}
 	$$ = sctp_init_ack_chunk_new($3, $5, $7, $9, $11, $13, $14);
 }
 
diff --git a/gtests/net/packetdrill/run_packet.c b/gtests/net/packetdrill/run_packet.c
index fb8a0c736d7428b358416d6bf359e079ae1a39ba..303f2f53b16779f1da5a630a2ab8cc545481460a 100644
--- a/gtests/net/packetdrill/run_packet.c
+++ b/gtests/net/packetdrill/run_packet.c
@@ -1153,10 +1153,11 @@ static int verify_init_chunk(struct sctp_init_chunk *actual_chunk,
 
 	assert(ntohs(actual_chunk->length) >= sizeof(struct sctp_init_chunk));
 	parameters_length = ntohs(actual_chunk->length) - sizeof(struct sctp_init_chunk);
-	if (check_field("sctp_init_chunk_tag",
-		        ntohl(script_chunk->initiate_tag),
-		        ntohl(actual_chunk->initiate_tag),
-		        error) ||
+	if ((flags & FLAG_INIT_CHUNK_TAG_NOCHECK ? STATUS_OK :
+	        check_field("sctp_init_chunk_tag",
+		            ntohl(script_chunk->initiate_tag),
+		            ntohl(actual_chunk->initiate_tag),
+		            error)) ||
 	    (flags & FLAG_INIT_CHUNK_A_RWND_NOCHECK ? STATUS_OK :
 	        check_field("sctp_init_chunk_a_rwnd",
 		            ntohl(script_chunk->a_rwnd),
@@ -1172,10 +1173,11 @@ static int verify_init_chunk(struct sctp_init_chunk *actual_chunk,
 		            ntohs(script_chunk->is),
 		            ntohs(actual_chunk->is),
 		            error)) ||
-	    check_field("sctp_init_chunk_tsn",
-		        ntohl(script_chunk->initial_tsn),
-		        ntohl(actual_chunk->initial_tsn),
-		        error) ||
+	    (flags & FLAG_INIT_CHUNK_TSN_NOCHECK? STATUS_OK :
+		check_field("sctp_init_chunk_tsn",
+		            ntohl(script_chunk->initial_tsn),
+		            ntohl(actual_chunk->initial_tsn),
+		            error)) ||
 	    (flags & FLAG_INIT_CHUNK_OPT_PARAM_NOCHECK? STATUS_OK :
 	        verify_sctp_parameters(actual_chunk->parameter,
 	                               parameters_length,
@@ -1190,10 +1192,11 @@ static int verify_init_ack_chunk(struct sctp_init_ack_chunk *actual_chunk,
                                  struct sctp_init_ack_chunk *script_chunk,
                                  u32 flags, char **error)
 {
-	if (check_field("sctp_init_ack_chunk_tag",
-		        ntohl(script_chunk->initiate_tag),
-		        ntohl(actual_chunk->initiate_tag),
-		        error) ||
+	if ((flags & FLAG_INIT_ACK_CHUNK_TAG_NOCHECK ? STATUS_OK :
+	        check_field("sctp_init_ack_chunk_tag",
+		            ntohl(script_chunk->initiate_tag),
+		            ntohl(actual_chunk->initiate_tag),
+		            error)) ||
 	    (flags & FLAG_INIT_ACK_CHUNK_A_RWND_NOCHECK ? STATUS_OK :
 	        check_field("sctp_init_ack_chunk_a_rwnd",
 		            ntohl(script_chunk->a_rwnd),
@@ -1209,10 +1212,11 @@ static int verify_init_ack_chunk(struct sctp_init_ack_chunk *actual_chunk,
 		            ntohs(script_chunk->is),
 		            ntohs(actual_chunk->is),
 		            error)) ||
-	    check_field("sctp_init_ack_chunk_tsn",
-		        ntohl(script_chunk->initial_tsn),
-		        ntohl(actual_chunk->initial_tsn),
-		        error)) {
+	    (flags & FLAG_INIT_ACK_CHUNK_TSN_NOCHECK? STATUS_OK :
+		check_field("sctp_init_ack_chunk_tsn",
+		            ntohl(script_chunk->initial_tsn),
+		            ntohl(actual_chunk->initial_tsn),
+		            error))) {
 		return STATUS_ERR;
 	}
 	/* FIXME: Validate parameters */
diff --git a/gtests/net/packetdrill/sctp_packet.c b/gtests/net/packetdrill/sctp_packet.c
index b190289e9727dff88c7f6b542fd5a6560703a3cc..f3eec362655eafa63504e269afc32c5fb498f740 100644
--- a/gtests/net/packetdrill/sctp_packet.c
+++ b/gtests/net/packetdrill/sctp_packet.c
@@ -282,7 +282,12 @@ sctp_init_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn,
 		chunk->flags = (u8)flgs;
 	}
 	chunk->length = htons(chunk_length);
-	chunk->initiate_tag = htonl((u32)tag);
+	if (tag == -1) {
+		chunk->initiate_tag = htonl(0);
+		flags |= FLAG_INIT_CHUNK_TAG_NOCHECK;
+	} else {
+		chunk->initiate_tag = htonl((u32)tag);
+	}
 	if (a_rwnd == -1) {
 		chunk->a_rwnd = htonl(0);
 		flags |= FLAG_INIT_CHUNK_A_RWND_NOCHECK;
@@ -301,7 +306,12 @@ sctp_init_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn,
 	} else {
 		chunk->is = htons((u16)is);
 	}
-	chunk->initial_tsn = htonl((u32)tsn);
+	if (tsn == -1) {
+		chunk->initial_tsn = htonl(0);
+		flags |= FLAG_INIT_CHUNK_TSN_NOCHECK;
+	} else {
+		chunk->initial_tsn = htonl((u32)tsn);
+	}
 	offset = 0;
 	for (item = list->first; item != NULL; item = item->next) {
 		parameter_padding_length = item->length % 4;
@@ -355,26 +365,36 @@ sctp_init_ack_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn,
 		chunk->flags = (u8)flgs;
 	}
 	chunk->length = htons(chunk_length);
-	chunk->initiate_tag = htonl((u32)tag);
+	if (tag == -1) {
+		chunk->initiate_tag = htonl(0);
+		flags |= FLAG_INIT_ACK_CHUNK_TAG_NOCHECK;
+	} else {
+		chunk->initiate_tag = htonl((u32)tag);
+	}
 	if (a_rwnd == -1) {
 		chunk->a_rwnd = htonl(0);
-		flags |= FLAG_INIT_CHUNK_A_RWND_NOCHECK;
+		flags |= FLAG_INIT_ACK_CHUNK_A_RWND_NOCHECK;
 	} else {
 		chunk->a_rwnd = htonl((u32)a_rwnd);
 	}
 	if (os == -1) {
 		chunk->os = htons(0);
-		flags |= FLAG_INIT_CHUNK_OS_NOCHECK;
+		flags |= FLAG_INIT_ACK_CHUNK_OS_NOCHECK;
 	} else {
 		chunk->os = htons((u16)os);
 	}
 	if (is == -1) {
 		chunk->is = htons(0);
-		flags |= FLAG_INIT_CHUNK_IS_NOCHECK;
+		flags |= FLAG_INIT_ACK_CHUNK_IS_NOCHECK;
 	} else {
 		chunk->is = htons((u16)is);
 	}
-	chunk->initial_tsn = htonl((u32)tsn);
+	if (tsn == -1) {
+		chunk->initial_tsn = htonl(0);
+		flags |= FLAG_INIT_ACK_CHUNK_TSN_NOCHECK;
+	} else {
+		chunk->initial_tsn = htonl((u32)tsn);
+	}
 	offset = 0;
 	for (item = list->first; item != NULL; item = item->next) {
 		parameter_padding_length = item->length % 4;
@@ -1379,6 +1399,11 @@ new_sctp_packet(int address_family,
 				}
 				break;
 			case SCTP_INIT_CHUNK_TYPE:
+				if (chunk_item->flags & FLAG_INIT_CHUNK_TAG_NOCHECK) {
+					asprintf(error,
+						 "TAG must be specified for inbound packets");
+					return NULL;
+				}
 				if (chunk_item->flags & FLAG_INIT_CHUNK_A_RWND_NOCHECK) {
 					asprintf(error,
 						 "A_RWND must be specified for inbound packets");
@@ -1401,6 +1426,11 @@ new_sctp_packet(int address_family,
 				}
 				break;
 			case SCTP_INIT_ACK_CHUNK_TYPE:
+				if (chunk_item->flags & FLAG_INIT_ACK_CHUNK_TAG_NOCHECK) {
+					asprintf(error,
+						 "TAG must be specified for inbound packets");
+					return NULL;
+				}
 				if (chunk_item->flags & FLAG_INIT_ACK_CHUNK_A_RWND_NOCHECK) {
 					asprintf(error,
 						 "A_RWND must be specified for inbound packets");
diff --git a/gtests/net/packetdrill/sctp_packet.h b/gtests/net/packetdrill/sctp_packet.h
index 36df5f54589908fcc9c0aeea8d7f38f0f3bdb90c..51b0bcc9e15e270ee3cfa31ee62d8d9a44907ade 100644
--- a/gtests/net/packetdrill/sctp_packet.h
+++ b/gtests/net/packetdrill/sctp_packet.h
@@ -130,19 +130,23 @@ 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 len, s64 tsn, s64 sid, s64 ssn, s64 ppid);
 
-#define FLAG_INIT_CHUNK_A_RWND_NOCHECK          0x00000100
-#define FLAG_INIT_CHUNK_OS_NOCHECK              0x00000200
-#define FLAG_INIT_CHUNK_IS_NOCHECK              0x00000400
-#define FLAG_INIT_CHUNK_OPT_PARAM_NOCHECK       0x00000800
+#define FLAG_INIT_CHUNK_TAG_NOCHECK             0x00000100
+#define FLAG_INIT_CHUNK_A_RWND_NOCHECK          0x00000200
+#define FLAG_INIT_CHUNK_OS_NOCHECK              0x00000400
+#define FLAG_INIT_CHUNK_IS_NOCHECK              0x00000800
+#define FLAG_INIT_CHUNK_TSN_NOCHECK             0x00001000
+#define FLAG_INIT_CHUNK_OPT_PARAM_NOCHECK       0x00002000
 
 struct sctp_chunk_list_item *
 sctp_init_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn,
                     struct sctp_parameter_list *parameters);
 
-#define FLAG_INIT_ACK_CHUNK_A_RWND_NOCHECK      0x00000100
-#define FLAG_INIT_ACK_CHUNK_OS_NOCHECK          0x00000200
-#define FLAG_INIT_ACK_CHUNK_IS_NOCHECK          0x00000400
-#define FLAG_INIT_ACK_CHUNK_OPT_PARAM_NOCHECK   0x00000800
+#define FLAG_INIT_ACK_CHUNK_TAG_NOCHECK         0x00000100
+#define FLAG_INIT_ACK_CHUNK_A_RWND_NOCHECK      0x00000200
+#define FLAG_INIT_ACK_CHUNK_OS_NOCHECK          0x00000400
+#define FLAG_INIT_ACK_CHUNK_IS_NOCHECK          0x00000800
+#define FLAG_INIT_ACK_CHUNK_TSN_NOCHECK         0x00001000
+#define FLAG_INIT_ACK_CHUNK_OPT_PARAM_NOCHECK   0x00002000
 
 struct sctp_chunk_list_item *
 sctp_init_ack_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn,