diff --git a/gtests/net/packetdrill/packet.h b/gtests/net/packetdrill/packet.h
index 832f6125665a1dcdcfd3abeb58d5c1a1a285da64..8e931ec28528670813bf29749eb3f205f0d84528 100644
--- a/gtests/net/packetdrill/packet.h
+++ b/gtests/net/packetdrill/packet.h
@@ -109,6 +109,7 @@ struct packet {
 #define FLAG_WIN_NOCHECK	0x1  /* don't check TCP receive window */
 #define FLAG_OPTIONS_NOCHECK	0x2  /* don't check TCP options */
 #define FLAGS_SCTP_BAD_CRC32C   0x4  /* compute bad CRC32C for SCTP packets */
+#define FLAGS_SCTP_EXPLICIT_TAG 0x8  /* verification tag specified */
 
 	enum ip_ecn_t ecn;	/* IPv4/IPv6 ECN treatment for packet */
 
diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index bb2fb56b5a72dc63bcf7b54f14b2fa6e5b0f2e2b..7df5a63877e4b8201eb6d4025f494e8d2f58dac9 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -821,7 +821,7 @@ sctp_packet_spec
 	enum direction_t direction = outer->direction;
 
 	inner = new_sctp_packet(in_config->wire_protocol, direction, $2,
-	                        false, $5, &error);
+	                        -1, false, $5, &error);
 	if (inner == NULL) {
 		assert(error != NULL);
 		semantic_error(error);
@@ -836,7 +836,43 @@ sctp_packet_spec
 	enum direction_t direction = outer->direction;
 
 	inner = new_sctp_packet(in_config->wire_protocol, direction, $2,
-	                        true, $8, &error);
+	                        -1, true, $8, &error);
+	if (inner == NULL) {
+		assert(error != NULL);
+		semantic_error(error);
+		free(error);
+	}
+
+	$$ = packet_encapsulate_and_free(outer, inner);
+}
+| packet_prefix opt_ip_info SCTP '(' TAG '=' INTEGER ')' ':' sctp_chunk_list_spec {
+	char *error = NULL;
+	struct packet *outer = $1, *inner = NULL;
+	enum direction_t direction = outer->direction;
+
+	if (!is_valid_u32($7)) {
+		semantic_error("tag value out of range");
+	}
+	inner = new_sctp_packet(in_config->wire_protocol, direction, $2,
+	                        $7, false, $10, &error);
+	if (inner == NULL) {
+		assert(error != NULL);
+		semantic_error(error);
+		free(error);
+	}
+
+	$$ = packet_encapsulate_and_free(outer, inner);
+}
+| packet_prefix opt_ip_info SCTP '(' BAD_CRC32C ',' TAG '=' INTEGER ')' ':' sctp_chunk_list_spec {
+	char *error = NULL;
+	struct packet *outer = $1, *inner = NULL;
+	enum direction_t direction = outer->direction;
+
+	if (!is_valid_u32($9)) {
+		semantic_error("tag value out of range");
+	}
+	inner = new_sctp_packet(in_config->wire_protocol, direction, $2,
+	                        $9, true, $12, &error);
 	if (inner == NULL) {
 		assert(error != NULL);
 		semantic_error(error);
diff --git a/gtests/net/packetdrill/run_packet.c b/gtests/net/packetdrill/run_packet.c
index 45d44a1cc63ff4b83f0db828fb6509fbc00bcffb..7dc504fd8cf7f52c589863bee6387ac0283f6f1a 100644
--- a/gtests/net/packetdrill/run_packet.c
+++ b/gtests/net/packetdrill/run_packet.c
@@ -2695,7 +2695,7 @@ int abort_association(struct state *state, struct socket *socket)
 	chunk_list = sctp_chunk_list_new();
 	sctp_chunk_list_append(chunk_list, sctp_abort_chunk_new(flgs, cause_list));
 	packet = new_sctp_packet(socket->address_family,
-				 DIRECTION_INBOUND, ECN_NONE, false,
+				 DIRECTION_INBOUND, ECN_NONE, -1, false,
 				 chunk_list, &error);
 	if (packet == NULL)
 		die("%s", error);
diff --git a/gtests/net/packetdrill/sctp_packet.c b/gtests/net/packetdrill/sctp_packet.c
index 2658b47d4554a868f7cda2cda85c324ce3a627a3..48416d3b0c43233012bd302ca09075cf9a9c57cf 100644
--- a/gtests/net/packetdrill/sctp_packet.c
+++ b/gtests/net/packetdrill/sctp_packet.c
@@ -2242,6 +2242,7 @@ struct packet *
 new_sctp_packet(int address_family,
                 enum direction_t direction,
                 enum ip_ecn_t ecn,
+                s64 tag,
                 bool bad_crc32c,
                 struct sctp_chunk_list *list,
                 char **error)
@@ -2512,6 +2513,9 @@ new_sctp_packet(int address_family,
 	if (bad_crc32c) {
 		packet->flags |= FLAGS_SCTP_BAD_CRC32C;
 	}
+	if (tag != -1) {
+		packet->flags |= FLAGS_SCTP_EXPLICIT_TAG;
+	}
 	packet->ecn = ecn;
 
 	/* Set IP header fields */
@@ -2528,7 +2532,7 @@ new_sctp_packet(int address_family,
 	/* Set SCTP header fields */
 	packet->sctp->src_port = htons(0);
 	packet->sctp->dst_port = htons(0);
-	packet->sctp->v_tag = htonl(0);
+	packet->sctp->v_tag = htonl((u32)tag);
 	packet->sctp->crc32c = htonl(0);
 
 	for (chunk_item = list->first;
diff --git a/gtests/net/packetdrill/sctp_packet.h b/gtests/net/packetdrill/sctp_packet.h
index ca0256b107fb8a0ffb0e418a7c502f10a616c97d..c32e8d9d6878ed480890735478ec254c21483741 100644
--- a/gtests/net/packetdrill/sctp_packet.h
+++ b/gtests/net/packetdrill/sctp_packet.h
@@ -423,6 +423,7 @@ sctp_cause_list_free(struct sctp_cause_list *list);
 extern struct packet *new_sctp_packet(int address_family,
 				      enum direction_t direction,
 				      enum ip_ecn_t ecn,
+				      s64 tag,
 				      bool bad_crc32c,
 				      struct sctp_chunk_list *chunk_list,
 				      char **error);