From a6210cd183febeb3fde672d4acf9977d6dcf3d49 Mon Sep 17 00:00:00 2001
From: Michael Tuexen <tuexen@fh-muenster.de>
Date: Mon, 4 May 2015 08:33:34 +0200
Subject: [PATCH] Allow the DATA chunk flags to be specified as IUBE and the
 ABORT and SHUTDOWN_COMPLETE chunk flags using T. This finally fixes
 https://github.com/nplab/packetdrill/issues/2

---
 gtests/net/packetdrill/parser.y               | 126 +++++++++++++++++-
 .../tests/bsd/sctp/sctp_active.pkt            |   4 +-
 .../tests/bsd/sctp/sctp_passive.pkt           |   4 +-
 3 files changed, 126 insertions(+), 8 deletions(-)

diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index 9608afcd..f3f8f328 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -551,7 +551,8 @@ 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 opt_data_chunk_len
+%type <integer> opt_flags opt_data_flags opt_abort_flags
+%type <integer> opt_shutdown_complete_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
@@ -780,6 +781,123 @@ opt_flags
                           $$ = $3;
 }
 
+opt_data_flags
+:                       {
+	$$ = -1;
+}
+| FLAGS '=' HEX_INTEGER {
+	if (!is_valid_u8($3)) {
+		semantic_error("flags value out of range");
+	}
+	$$ = $3;
+}
+| FLAGS '=' WORD        {
+	u64 flags;
+	char *c;
+
+	flags = 0;
+	for (c = $3; *c != '\0'; c++) {
+		switch (*c) {
+		case 'I':
+			if (flags & SCTP_DATA_CHUNK_I_BIT) {
+				semantic_error("Specifying the I-bit multiple times");
+			} else {
+				flags |= SCTP_DATA_CHUNK_I_BIT;
+			}
+			break;
+		case 'U':
+			if (flags & SCTP_DATA_CHUNK_U_BIT) {
+				semantic_error("Specifying the U-bit multiple times");
+			} else {
+				flags |= SCTP_DATA_CHUNK_U_BIT;
+			}
+			break;
+		case 'B':
+			if (flags & SCTP_DATA_CHUNK_B_BIT) {
+				semantic_error("Specifying the B-bit multiple times");
+			} else {
+				flags |= SCTP_DATA_CHUNK_B_BIT;
+			}
+			break;
+		case 'E':
+			if (flags & SCTP_DATA_CHUNK_E_BIT) {
+				semantic_error("Specifying the E-bit multiple times");
+			} else {
+				flags |= SCTP_DATA_CHUNK_E_BIT;
+			}
+			break;
+		default:
+			semantic_error("Only expecting IUBE as flags");
+			break;
+		}
+	}
+	$$ = flags;
+}
+
+opt_abort_flags
+:                       {
+	$$ = -1;
+}
+| FLAGS '=' HEX_INTEGER {
+	if (!is_valid_u8($3)) {
+		semantic_error("flags value out of range");
+	}
+	$$ = $3;
+}
+| FLAGS '=' WORD        {
+	u64 flags;
+	char *c;
+
+	flags = 0;
+	for (c = $3; *c != '\0'; c++) {
+		switch (*c) {
+		case 'T':
+			if (flags & SCTP_ABORT_CHUNK_T_BIT) {
+				semantic_error("Specifying the T-bit multiple times");
+			} else {
+				flags |= SCTP_ABORT_CHUNK_T_BIT;
+			}
+			break;
+		default:
+			semantic_error("Only expecting T as flags");
+			break;
+		}
+	}
+	$$ = flags;
+}
+
+opt_shutdown_complete_flags
+:                       {
+	$$ = -1;
+}
+| FLAGS '=' HEX_INTEGER {
+	if (!is_valid_u8($3)) {
+		semantic_error("flags value out of range");
+	}
+	$$ = $3;
+}
+| FLAGS '=' WORD        {
+	u64 flags;
+	char *c;
+
+	flags = 0;
+	for (c = $3; *c != '\0'; c++) {
+		switch (*c) {
+		case 'T':
+			if (flags & SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT) {
+				semantic_error("Specifying the T-bit multiple times");
+			} else {
+				flags |= SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT;
+			}
+			break;
+		default:
+			semantic_error("Only expecting T as flags");
+			break;
+		}
+	}
+	$$ = flags;
+}
+
 opt_a_rwnd
 :		{ $$ = -1; }
 | A_RWND '=' INTEGER	{
@@ -887,7 +1005,7 @@ dup
 ;
 
 sctp_data_chunk_spec
-: DATA '[' opt_flags opt_data_chunk_len opt_tsn opt_sid opt_ssn opt_ppid ']' {
+: DATA '[' opt_data_flags opt_data_chunk_len opt_tsn opt_sid opt_ssn opt_ppid ']' {
 	$$ = sctp_data_chunk_new($3, $4, $5, $6, $7, $8);
 }
 
@@ -929,7 +1047,7 @@ sctp_heartbeat_ack_chunk_spec
 }
 
 sctp_abort_chunk_spec
-: ABORT '[' opt_flags ']' {
+: ABORT '[' opt_abort_flags ']' {
 	$$ = sctp_abort_chunk_new($3);
 }
 
@@ -969,7 +1087,7 @@ sctp_cwr_chunk_spec
 }
 
 sctp_shutdown_complete_chunk_spec
-: SHUTDOWN_COMPLETE '[' opt_flags ']' {
+: SHUTDOWN_COMPLETE '[' opt_shutdown_complete_flags ']' {
 	$$ = sctp_shutdown_complete_chunk_new($3);
 }
 
diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_active.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_active.pkt
index c08bb3df..64a442fc 100644
--- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_active.pkt
+++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_active.pkt
@@ -13,11 +13,11 @@
 +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 len=1016 tsn=3 sid=0 ssn=0 ppid=0] // How to handle
++1.0 < sctp: DATA[flgs=BE len=1016 tsn=3 sid=0 ssn=0 ppid=0]
 +0.0 read(3, ..., 2000) = 1000
 +0.0 > sctp: SACK[tsn=3]
 // Receive more data, observe delayed SACK
-+1.0 < sctp: DATA[flgs=0x0b len=1016 tsn=4 sid=0 ssn=1 ppid=0]
++1.0 < sctp: DATA[flgs=IBE 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
diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_passive.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_passive.pkt
index b6b5c711..71358130 100644
--- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_passive.pkt
+++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_passive.pkt
@@ -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[flgs=0x03 len=1016 tsn=1 sid=0 ssn=1 ppid=0] // How to handle payload?
++1.0 < sctp: DATA[flgs=BE len=1016 tsn=1 sid=0 ssn=1 ppid=0] 
 +0.0 read(4, ..., 2000) = 1000
 +0.2 > sctp: SACK[tsn=1]
 // Receive more data, observe delayed SACKi
-+1.0 < sctp: DATA[flgs=0x03 len=1016 tsn=2 sid=0 ssn=2 ppid=0]
++1.0 < sctp: DATA[flgs=BE 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
-- 
GitLab