diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index f2bc2b49151d17f13ebb88284f7051f9a5397e20..e35640e39c6d3b637d446bd47499d79df4ad4ea5 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -474,6 +474,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 	struct sctp_sack_block_list *sack_block_list;
 	struct sctp_forward_tsn_ids_list *forward_tsn_ids_list;
 	struct sctp_forward_tsn_ids_list_item  *forward_tsn_ids_list_item;
+	struct sctp_i_forward_tsn_ids_list *i_forward_tsn_ids_list;
+	struct sctp_i_forward_tsn_ids_list_item  *i_forward_tsn_ids_list_item;
 	struct sctp_address_type_list_item *address_type_list_item;
 	struct sctp_address_type_list *address_type_list;
 	struct sctp_parameter_type_list_item *parameter_type_list_item;
@@ -521,7 +523,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %token <reserved> SPINFO_MTU GAUTH_ASSOC_ID GAUTH_NUMBER_OF_CHUNKS GAUTH_CHUNKS
 %token <reserved> CHUNK DATA INIT INIT_ACK HEARTBEAT HEARTBEAT_ACK ABORT
 %token <reserved> SHUTDOWN SHUTDOWN_ACK ERROR COOKIE_ECHO COOKIE_ACK ECNE CWR
-%token <reserved> SHUTDOWN_COMPLETE I_DATA PAD RECONFIG FORWARD_TSN
+%token <reserved> SHUTDOWN_COMPLETE I_DATA PAD RECONFIG FORWARD_TSN I_FORWARD_TSN
 %token <reserved> TYPE FLAGS LEN
 %token <reserved> TAG A_RWND OS IS TSN SID SSN MID PPID FSN CUM_TSN GAPS NR_GAPS DUPS
 %token <reserved> PARAMETER HEARTBEAT_INFORMATION IPV4_ADDRESS IPV6_ADDRESS
@@ -677,7 +679,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %type <chunk_list_item> sctp_shutdown_complete_chunk_spec
 %type <chunk_list_item> sctp_i_data_chunk_spec
 %type <chunk_list_item> sctp_pad_chunk_spec sctp_reconfig_chunk_spec
-%type <chunk_list_item> sctp_forward_tsn_spec
+%type <chunk_list_item> sctp_forward_tsn_spec sctp_i_forward_tsn_spec
 %type <parameter_list> opt_parameter_list_spec sctp_parameter_list_spec
 %type <parameter_list_item> sctp_parameter_spec
 %type <parameter_list_item> sctp_generic_parameter_spec
@@ -726,8 +728,10 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %type <u16_item> u16_item
 %type <sack_block_list> opt_gaps opt_nr_gaps gap_list opt_dups dup_list
 %type <sack_block_list_item> gap dup
-%type <forward_tsn_ids_list> opt_stream_identifier ids_list
+%type <forward_tsn_ids_list> opt_stream_identifier  ids_list
 %type <forward_tsn_ids_list_item> id
+%type <i_forward_tsn_ids_list> opt_i_forward_tsn_stream_identifier i_forward_tsn_ids_list
+%type <i_forward_tsn_ids_list_item> i_forward_tsn_id
 %type <address_type_list> address_types_list
 %type <address_type_list_item> address_type
 %type <parameter_type_list> parameter_types_list
@@ -1061,6 +1065,7 @@ sctp_chunk_spec
 | sctp_pad_chunk_spec               { $$ = $1; }
 | sctp_reconfig_chunk_spec          { $$ = $1; }
 | sctp_forward_tsn_spec             { $$ = $1; }
+| sctp_i_forward_tsn_spec           { $$ = $1; }
 ;
 
 chunk_type
@@ -1610,6 +1615,36 @@ id
 }
 ;
 
+opt_i_forward_tsn_stream_identifier
+: IDS '=' ELLIPSIS         { $$ = NULL; }
+| IDS '=' '[' ELLIPSIS ']' { $$ = NULL; }
+| IDS '=' '[' i_forward_tsn_ids_list ']' { $$ = $4; }
+;
+
+i_forward_tsn_ids_list
+:                  { $$ = sctp_i_forward_tsn_ids_list_new(); }
+| i_forward_tsn_id { $$ =sctp_i_forward_tsn_ids_list_new();
+                     sctp_i_forward_tsn_ids_list_append($$, $1); }
+| i_forward_tsn_ids_list ',' i_forward_tsn_id { $$ = $1;
+                     sctp_i_forward_tsn_ids_list_append($1, $3); }
+;
+
+i_forward_tsn_id
+: '{' WORD ',' INTEGER ',' INTEGER '}' {
+	char *c = $2;
+	if (*c != 'O' || *c != 'U') {
+		semantic_error("either O for ordered or U for unordered must be specified");
+	}
+	if (!is_valid_u16($4)) {
+		semantic_error("stream identifier out of range");
+	}
+	if (!is_valid_u16($6)) {
+		semantic_error("stream sequence number out of range");
+	}
+	$$ = sctp_i_forward_tsn_ids_list_item_new(*c, $4, $6);
+}
+;
+
 sctp_generic_chunk_spec
 : CHUNK '[' opt_chunk_type ',' opt_flags ',' opt_len ',' opt_val ']' {
 	if (($7 != -1) &&
@@ -1752,6 +1787,11 @@ sctp_forward_tsn_spec
     $$ = sctp_forward_tsn_chunk_new($3, $5);
 }
 
+sctp_i_forward_tsn_spec
+: I_FORWARD_TSN '[' opt_cum_tsn ',' opt_i_forward_tsn_stream_identifier']' {
+    $$ = sctp_i_forward_tsn_chunk_new($3, $5);
+}
+
 opt_req_sn
 : REQ_SN '=' INTEGER {
 	if (!is_valid_u32($3)) {
diff --git a/gtests/net/packetdrill/sctp.h b/gtests/net/packetdrill/sctp.h
index 6a17a416edbba0903362c603adca544e56c051c4..e8d0650b5cdd220bb22306feecd143fc7bde5a64 100644
--- a/gtests/net/packetdrill/sctp.h
+++ b/gtests/net/packetdrill/sctp.h
@@ -57,6 +57,8 @@ struct sctp_common_header {
 #define SCTP_RECONFIG_CHUNK_TYPE			0x82
 #define SCTP_PAD_CHUNK_TYPE				0x84
 #define SCTP_FORWARD_TSN_CHUNK_TYPE                     0xc0
+#define SCTP_I_FORWARD_TSN_CHUNK_TYPE                   0xc2
+
 
 #define MAX_SCTP_CHUNK_BYTES	0xffff
 
@@ -281,6 +283,20 @@ struct sctp_forward_tsn_chunk {
 	struct sctp_stream_identifier_block stream_identifier_blocks[];
 } __packed;
 
+struct sctp_i_forward_tsn_identifier_block {
+	__u16 stream_identifier;
+	__u16 reserved;
+	__u32 message_identifier;
+};
+
+struct sctp_i_forward_tsn_chunk {
+	__u8 type;
+	__u8 flags;
+	__be16 length;
+	__be32 cum_tsn;
+	struct sctp_i_forward_tsn_identifier_block stream_identifier_blocks[];
+} __packed;
+
 #define SCTP_HEARTBEAT_INFORMATION_PARAMETER_TYPE	0x0001
 #define SCTP_IPV4_ADDRESS_PARAMETER_TYPE		0x0005
 #define SCTP_IPV6_ADDRESS_PARAMETER_TYPE		0x0006
diff --git a/gtests/net/packetdrill/sctp_packet.c b/gtests/net/packetdrill/sctp_packet.c
index ad7048918e205345628b099d9d2390e607a1a85d..866abba6a3b91d8462031d2a65fa2c04adce101e 100644
--- a/gtests/net/packetdrill/sctp_packet.c
+++ b/gtests/net/packetdrill/sctp_packet.c
@@ -293,6 +293,66 @@ sctp_forward_tsn_ids_list_item_new(u16 stream_identifier, u16 stream_sequence_nu
 	return item;
 }
 
+struct sctp_i_forward_tsn_ids_list *
+sctp_i_forward_tsn_ids_list_new () {
+	struct sctp_i_forward_tsn_ids_list *list;
+
+	list = malloc(sizeof(struct sctp_i_forward_tsn_ids_list));
+	assert(list != NULL);
+	list->first = NULL;
+	list->last = NULL;
+	list->nr_entries = 0;
+	return list;
+}
+
+void
+sctp_i_forward_tsn_ids_list_append(struct sctp_i_forward_tsn_ids_list *list,
+			          struct sctp_i_forward_tsn_ids_list_item *item) {
+	assert(item->next == NULL);
+	if (list->last == NULL) {
+		assert(list->first == NULL);
+		assert(list->nr_entries == 0);
+		list->first = item;
+	} else {
+		assert(list->first != NULL);
+		list->last->next = item;
+	}
+	list->last = item;
+	list->nr_entries++;
+}
+
+void sctp_i_forward_tsn_ids_list_free (struct sctp_i_forward_tsn_ids_list *list) {
+	struct sctp_i_forward_tsn_ids_list_item *current_item, *next_item;
+
+	if (list == NULL) {
+		return;
+	}
+	current_item = list->first;
+	while (current_item != NULL) {
+		assert(list->nr_entries > 0);
+		next_item = current_item->next;
+		assert(next_item != NULL || current_item == list->last);
+		free(current_item);
+		current_item = next_item;
+		list->nr_entries--;
+	}
+	assert(list->nr_entries == 0);
+	free(list);
+}
+
+struct sctp_i_forward_tsn_ids_list_item *
+sctp_i_forward_tsn_ids_list_item_new(char u_bit_set, u16 stream_identifier, u32 message_identifier) {
+	struct sctp_i_forward_tsn_ids_list_item *item;
+
+	item = malloc(sizeof(struct sctp_i_forward_tsn_ids_list_item));
+	assert(item != NULL);
+	item->next = NULL;
+	item->stream_identifier = stream_identifier;
+	item->u_bit_set = u_bit_set;
+	item->message_identifier = message_identifier;
+	return item;
+}
+
 struct sctp_address_type_list *
 sctp_address_type_list_new(void)
 {
@@ -1495,6 +1555,70 @@ sctp_forward_tsn_chunk_new(u32 cum_tsn, struct sctp_forward_tsn_ids_list *sids)
 	                                sctp_cause_list_new());
 }
 
+struct sctp_chunk_list_item *
+sctp_i_forward_tsn_chunk_new(u32 cum_tsn, struct sctp_i_forward_tsn_ids_list *ids_list) {
+	struct sctp_i_forward_tsn_chunk *chunk;
+	struct sctp_i_forward_tsn_ids_list_item *item;
+	
+	DEBUGP("sctp_i_forward_tsn_chunk_new called with cum_tsn = %d and sids_list = %p", cum_tsn, ids_list);
+	
+	u32 flags;
+	u32 length;
+	u16 i, nr_ids;
+
+	flags = 0;
+	length = sizeof(struct sctp_i_forward_tsn_chunk);
+	if (ids_list == NULL) {
+		nr_ids = 0;
+		flags |= FLAG_CHUNK_LENGTH_NOCHECK;
+		flags |= FLAG_I_FORWARD_TSN_CHUNK_IDS_NOCHECK;
+	} else {
+		nr_ids = ids_list->nr_entries;
+		length += nr_ids * sizeof(struct sctp_i_forward_tsn_identifier_block);
+	}
+	
+	assert(is_valid_u16(length));
+	assert(length % 4 == 0);
+	chunk = malloc(length);
+	assert(chunk != NULL);
+	chunk->type = SCTP_I_FORWARD_TSN_CHUNK_TYPE;
+	chunk->flags = 0;
+	chunk->length = htons(length);
+	if (cum_tsn == -1) {
+		chunk->cum_tsn = htonl(0);
+		flags |= FLAG_I_FORWARD_TSN_CHUNK_CUM_TSN_NOCHECK;
+	} else {
+		chunk->cum_tsn = htonl((u32)cum_tsn);
+	}
+	
+	if (nr_ids == 0 || ids_list == NULL) {
+		flags |= FLAG_I_FORWARD_TSN_CHUNK_IDS_NOCHECK;
+	}
+
+	if (ids_list != NULL) {
+		for (i = 0, item = ids_list->first;
+		     (i < nr_ids) && (item != NULL);
+		     i++, item = item->next) {
+			chunk->stream_identifier_blocks[i].stream_identifier= htons(item->stream_identifier);
+			if (item->u_bit_set == 'U') {
+				//TODO: htons required here?
+				chunk->stream_identifier_blocks[i].reserved = htons(0x01); 
+			}
+			else if (item->u_bit_set == 'O') {
+				chunk->stream_identifier_blocks[i].reserved = 0;
+			}
+			
+			chunk->stream_identifier_blocks[i].message_identifier = htonl(item->message_identifier);
+		}
+		
+		assert((i == nr_ids) && (item == NULL));
+	}
+	return sctp_chunk_list_item_new((struct sctp_chunk *)chunk,
+	                                length, flags,
+	                                sctp_parameter_list_new(),
+	                                sctp_cause_list_new());
+}
+
 struct sctp_chunk_list_item *
 sctp_reconfig_chunk_new(s64 flgs, struct sctp_parameter_list *parameters)
 {
diff --git a/gtests/net/packetdrill/sctp_packet.h b/gtests/net/packetdrill/sctp_packet.h
index f41521fd274e2ddf4f8d12a56443eaff59e9e68e..ea7ddecefdda5688e672c6309b5f37be048d2435 100644
--- a/gtests/net/packetdrill/sctp_packet.h
+++ b/gtests/net/packetdrill/sctp_packet.h
@@ -130,6 +130,31 @@ struct sctp_forward_tsn_ids_list_item *
 sctp_forward_tsn_ids_list_item_new(u16 stream_identifier, u16 stream_sequence_number);
 
 
+struct sctp_i_forward_tsn_ids_list_item {
+	struct sctp_i_forward_tsn_ids_list_item *next;
+	char u_bit_set;
+	u16 stream_identifier;
+	u32 message_identifier;
+}; 
+
+struct sctp_i_forward_tsn_ids_list {
+	struct sctp_i_forward_tsn_ids_list_item *first;
+	struct sctp_i_forward_tsn_ids_list_item *last;
+	u16 nr_entries;
+};
+
+struct sctp_i_forward_tsn_ids_list *
+sctp_i_forward_tsn_ids_list_new ();
+
+void
+sctp_i_forward_tsn_ids_list_append(struct sctp_i_forward_tsn_ids_list *list,
+			          struct sctp_i_forward_tsn_ids_list_item *item);
+
+void sctp_i_forward_tsn_ids_list_free (struct sctp_i_forward_tsn_ids_list *list);
+
+struct sctp_i_forward_tsn_ids_list_item *
+sctp_i_forward_tsn_ids_list_item_new(char u_bit_set, u16 stream_identifier, u32 message_identifier);
+
 struct sctp_address_type_list_item {
 	struct sctp_address_type_list_item *next;
 	u16 address_type;
@@ -357,6 +382,12 @@ sctp_pad_chunk_new(s64 flgs, s64 len, u8* padding);
 struct sctp_chunk_list_item *
 sctp_forward_tsn_chunk_new(u32 cum_tsn, struct sctp_forward_tsn_ids_list *sids_list);
 
+#define FLAG_I_FORWARD_TSN_CHUNK_CUM_TSN_NOCHECK  0x00000100
+#define FLAG_I_FORWARD_TSN_CHUNK_IDS_NOCHECK      0x00000200
+
+struct sctp_chunk_list_item *
+sctp_i_forward_tsn_chunk_new(u32 cum_tsn, struct sctp_i_forward_tsn_ids_list *ids_list);
+
 struct sctp_chunk_list_item *
 sctp_reconfig_chunk_new(s64 flgs, struct sctp_parameter_list *parameters);