From b06cbd41813edeab47c6164bd5f121b51f479338 Mon Sep 17 00:00:00 2001
From: Hoelscher <jens.hoelscher@fh-muenster.de>
Date: Mon, 7 Mar 2016 16:09:19 +0100
Subject: [PATCH] add support for sctp_add_streams

---
 gtests/net/packetdrill/lexer.l           |  3 +
 gtests/net/packetdrill/parser.y          | 35 +++++++++
 gtests/net/packetdrill/run_system_call.c | 21 ++++++
 gtests/net/packetdrill/script.c          | 95 +++++++++++++++++-------
 gtests/net/packetdrill/script.h          |  9 +++
 5 files changed, 136 insertions(+), 27 deletions(-)

diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l
index aa5af067..9521fed2 100644
--- a/gtests/net/packetdrill/lexer.l
+++ b/gtests/net/packetdrill/lexer.l
@@ -510,6 +510,9 @@ srs_assoc_id			return SRS_ASSOC_ID;
 srs_flags			return SRS_FLAGS;
 srs_number_streams		return SRS_NUMBER_STREAMS;
 srs_stream_list			return SRS_STREAM_LIST;
+sas_assoc_id			return SAS_ASSOC_ID;
+sas_instrms			return SAS_INSTRMS;
+sas_outstrms			return SAS_OUTSTRMS;
 CHUNK				return CHUNK;
 DATA				return DATA;
 INIT				return INIT;
diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index 775094cc..c4af6bf1 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -568,6 +568,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %token <reserved> SN_TYPE SN_FLAGS SN_LENGTH SAUTH_CHUNK
 %token <reserved> SCA_ASSOC_ID SCA_KEYNUMBER SCA_KEYLENGTH SCA_KEY
 %token <reserved> SRS_ASSOC_ID SRS_FLAGS SRS_NUMBER_STREAMS SRS_STREAM_LIST
+%token <reserved> SAS_ASSOC_ID SAS_INSTRMS SAS_OUTSTRMS
 %token <floating> FLOAT
 %token <integer> INTEGER HEX_INTEGER
 %token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR
@@ -642,6 +643,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %type <expression> sctp_tlv sn_type sn_flags sn_length sctp_assoc_ids gaids_number_of_ids
 %type <expression> sctp_setpeerprim sctp_authchunk sctp_authkey
 %type <expression> sctp_reset_streams srs_flags
+%type <expression> sctp_add_streams
 %type <errno_info> opt_errno
 %type <chunk_list> sctp_chunk_list_spec
 %type <chunk_list_item> sctp_chunk_spec
@@ -2637,6 +2639,9 @@ expression
 | sctp_reset_streams{
 	$$ = $1;
 }
+| sctp_add_streams  {
+	$$ = $1;
+}
 | null              {
 	$$ = $1;
 }
@@ -4988,6 +4993,36 @@ sctp_reset_streams
 	$$->value.sctp_reset_streams->srs_stream_list = $10;
 }
 ;
+
+sctp_add_streams
+: '{' SAS_ASSOC_ID '=' sctp_assoc_id ',' SAS_INSTRMS '=' INTEGER ',' SAS_OUTSTRMS '=' INTEGER '}' {
+	$$ = new_expression(EXPR_SCTP_ADD_STREAMS);
+	$$->value.sctp_add_streams = calloc(1, sizeof(struct sctp_add_streams_expr));
+	$$->value.sctp_add_streams->sas_assoc_id = $4;
+	if (!is_valid_u16($8)) {
+		semantic_error("sas_instrms out of range");
+	}
+	$$->value.sctp_add_streams->sas_instrms = new_integer_expression($8, "%hu");
+	if (!is_valid_u16($12)) {
+		semantic_error("sas_outstrms out of range");
+	}
+	$$->value.sctp_add_streams->sas_outstrms = new_integer_expression($12, "%hu");
+}
+| '{' SAS_INSTRMS '=' INTEGER ',' SAS_OUTSTRMS '=' INTEGER '}' {
+	$$ = new_expression(EXPR_SCTP_ADD_STREAMS);
+	$$->value.sctp_add_streams = calloc(1, sizeof(struct sctp_add_streams_expr));
+	$$->value.sctp_add_streams->sas_assoc_id = new_expression(EXPR_ELLIPSIS);
+	if (!is_valid_u16($4)) {
+		semantic_error("sas_instrms out of range");
+	}
+	$$->value.sctp_add_streams->sas_instrms = new_integer_expression($4, "%hu");
+	if (!is_valid_u16($8)) {
+		semantic_error("sas_outstrms out of range");
+	}
+	$$->value.sctp_add_streams->sas_outstrms = new_integer_expression($8, "%hu");
+}
+;
+
 opt_errno
 :                   { $$ = NULL; }
 | WORD note         {
diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c
index 8caeff04..ab467780 100644
--- a/gtests/net/packetdrill/run_system_call.c
+++ b/gtests/net/packetdrill/run_system_call.c
@@ -3518,6 +3518,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 	u32 spp_ipv6_flowlabel;
 	u8 spp_dscp;
 #endif
+#endif
+#ifdef SCTP_ADD_STREAMS
+	struct sctp_add_streams add_streams;
 #endif
 	if (check_arg_count(args, 5, error))
 		return STATUS_ERR;
@@ -4017,6 +4020,24 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 		optval = &reset_streams;
 		break;
 	}
+#endif
+#ifdef SCTP_ADD_STREAMS
+	case EXPR_SCTP_ADD_STREAMS:
+		if (get_sctp_assoc_t(val_expression->value.sctp_add_streams->sas_assoc_id,
+				     &add_streams.sas_assoc_id, error)) {
+			return STATUS_ERR;
+		}
+		if (get_u16(val_expression->value.sctp_add_streams->sas_instrms,
+			    &add_streams.sas_instrms, error)) {
+			return STATUS_ERR;
+		}
+		if (get_u16(val_expression->value.sctp_add_streams->sas_outstrms,
+			    &add_streams.sas_outstrms, error)) {
+			return STATUS_ERR;
+		}
+
+		optval = &add_streams;
+		break;
 #endif
 	default:
 		asprintf(error, "unsupported value type: %s",
diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c
index f0e94f1a..8200496b 100644
--- a/gtests/net/packetdrill/script.c
+++ b/gtests/net/packetdrill/script.c
@@ -108,7 +108,8 @@ struct expression_type_entry expression_type_table[] = {
 	{ EXPR_SCTP_SETPEERPRIM,     "sctp_setpeerprim"},
 	{ EXPR_SCTP_AUTHCHUNK,       "sctp_authchunk"  },
 	{ EXPR_SCTP_AUTHKEY,         "sctp_authkey"    },
-	{ EXPR_SCTP_RESET_STREAM,    "sctp_reset_stream"},
+	{ EXPR_SCTP_RESET_STREAMS,   "sctp_reset_streams"},
+	{ EXPR_SCTP_ADD_STREAMS,     "sctp_add_streams"},
 	{ NUM_EXPR_TYPES,            NULL}
 };
 
@@ -608,11 +609,16 @@ void free_expression(struct expression *expression)
 		free_expression(expression->value.sctp_authkey->sca_keylength);
 		free_expression(expression->value.sctp_authkey->sca_key);
 		break;
-	case EXPR_SCTP_RESET_STREAM:
-		free_expression(expression->value.sctp_reset_stream->srs_assoc_id);
-		free_expression(expression->value.sctp_reset_stream->srs_flags);
-		free_expression(expression->value.sctp_reset_stream->srs_number_streams);
-		free_expression(expression->value.sctp_reset_stream->srs_stream_list);
+	case EXPR_SCTP_RESET_STREAMS:
+		free_expression(expression->value.sctp_reset_streams->srs_assoc_id);
+		free_expression(expression->value.sctp_reset_streams->srs_flags);
+		free_expression(expression->value.sctp_reset_streams->srs_number_streams);
+		free_expression(expression->value.sctp_reset_streams->srs_stream_list);
+		break;
+	case EXPR_SCTP_ADD_STREAMS:
+		free_expression(expression->value.sctp_add_streams->sas_assoc_id);
+		free_expression(expression->value.sctp_add_streams->sas_instrms);
+		free_expression(expression->value.sctp_add_streams->sas_outstrms);
 		break;
 	case EXPR_WORD:
 		assert(expression->value.string);
@@ -2425,36 +2431,68 @@ static int evaluate_sctp_authkey_expression(struct expression *in,
 	return STATUS_OK;
 }
 
-static int evaluate_sctp_reset_stream_expression(struct expression *in,
-						 struct expression *out,
-						 char **error)
+static int evaluate_sctp_reset_streams_expression(struct expression *in,
+						  struct expression *out,
+						  char **error)
 {
-	struct sctp_reset_stream_expr *in_reset_stream;
-	struct sctp_reset_stream_expr *out_reset_stream;
+	struct sctp_reset_streams_expr *in_reset_streams;
+	struct sctp_reset_streams_expr *out_reset_streams;
 
-	assert(in->type == EXPR_SCTP_RESET_STREAM);
-	assert(in->value.sctp_reset_stream);
-	assert(out->type == EXPR_SCTP_RESET_STREAM);
+	assert(in->type == EXPR_SCTP_RESET_STREAMS);
+	assert(in->value.sctp_reset_streams);
+	assert(out->type == EXPR_SCTP_RESET_STREAMS);
 
-	out->value.sctp_reset_stream = calloc(1, sizeof(struct sctp_reset_stream_expr));
+	out->value.sctp_reset_streams = calloc(1, sizeof(struct sctp_reset_streams_expr));
 
-	in_reset_stream = in->value.sctp_reset_stream;
-	out_reset_stream = out->value.sctp_reset_stream;
+	in_reset_streams = in->value.sctp_reset_streams;
+	out_reset_streams = out->value.sctp_reset_streams;
 
-	if (evaluate(in_reset_stream->srs_assoc_id,
-		     &out_reset_stream->srs_assoc_id,
+	if (evaluate(in_reset_streams->srs_assoc_id,
+		     &out_reset_streams->srs_assoc_id,
 		     error))
 		return STATUS_ERR;
-	if (evaluate(in_reset_stream->srs_flags,
-		     &out_reset_stream->srs_flags,
+	if (evaluate(in_reset_streams->srs_flags,
+		     &out_reset_streams->srs_flags,
 		     error))
 		return STATUS_ERR;
-	if (evaluate(in_reset_stream->srs_number_streams,
-		     &out_reset_stream->srs_number_streams,
+	if (evaluate(in_reset_streams->srs_number_streams,
+		     &out_reset_streams->srs_number_streams,
 		     error))
 		return STATUS_ERR;
-	if (evaluate(in_reset_stream->srs_stream_list,
-		     &out_reset_stream->srs_stream_list,
+	if (evaluate(in_reset_streams->srs_stream_list,
+		     &out_reset_streams->srs_stream_list,
+		     error))
+		return STATUS_ERR;
+
+	return STATUS_OK;
+}
+
+static int evaluate_sctp_add_streams_expression(struct expression *in,
+						struct expression *out,
+						char **error)
+{
+	struct sctp_add_streams_expr *in_add_streams;
+	struct sctp_add_streams_expr *out_add_streams;
+
+	assert(in->type == EXPR_SCTP_ADD_STREAMS);
+	assert(in->value.sctp_add_streams);
+	assert(out->type == EXPR_SCTP_ADD_STREAMS);
+
+	out->value.sctp_add_streams = calloc(1, sizeof(struct sctp_add_streams_expr));
+
+	in_add_streams = in->value.sctp_add_streams;
+	out_add_streams = out->value.sctp_add_streams;
+
+	if (evaluate(in_add_streams->sas_assoc_id,
+		     &out_add_streams->sas_assoc_id,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_add_streams->sas_instrms,
+		     &out_add_streams->sas_instrms,
+		     error))
+		return STATUS_ERR;
+	if (evaluate(in_add_streams->sas_outstrms,
+		     &out_add_streams->sas_outstrms,
 		     error))
 		return STATUS_ERR;
 
@@ -2609,8 +2647,11 @@ static int evaluate(struct expression *in,
 	case EXPR_SCTP_AUTHKEY:
 		result = evaluate_sctp_authkey_expression(in, out, error);
 		break;
-	case EXPR_SCTP_RESET_STREAM:
-		result = evaluate_sctp_reset_stream_expression(in, out, error);
+	case EXPR_SCTP_RESET_STREAMS:
+		result = evaluate_sctp_reset_streams_expression(in, out, error);
+		break;
+	case EXPR_SCTP_ADD_STREAMS:
+		result = evaluate_sctp_add_streams_expression(in, out, error);
 		break;
 	case EXPR_WORD:
 		out->type = EXPR_INTEGER;
diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h
index 3967c12b..97a9ce4d 100644
--- a/gtests/net/packetdrill/script.h
+++ b/gtests/net/packetdrill/script.h
@@ -89,6 +89,7 @@ enum expression_t {
 	EXPR_SCTP_AUTHCHUNK,      /* expression tree for sctp_authchunk struct for setsockopt */
 	EXPR_SCTP_AUTHKEY,        /* expression tree for sctp_authkey struct for setsockopt */
 	EXPR_SCTP_RESET_STREAMS,  /* expression tree for sctp_reset_stream struct for [gs]etsockopt */
+	EXPR_SCTP_ADD_STREAMS,    /* expression tree for sctp_add_streams struct for [gs]etsockopt */
 	NUM_EXPR_TYPES,
 };
 /* Convert an expression type to a human-readable string */
@@ -151,6 +152,7 @@ struct expression {
 		struct sctp_authchunk_expr *sctp_authchunk;
 		struct sctp_authkey_expr *sctp_authkey;
 		struct sctp_reset_streams_expr *sctp_reset_streams;
+		struct sctp_add_streams_expr *sctp_add_streams;
 	} value;
 	const char *format;	/* the printf format for printing the value */
 };
@@ -575,6 +577,13 @@ struct sctp_reset_streams_expr {
 	struct expression *srs_stream_list;
 };
 
+/* Parse tree for sctp_add_stream struct for setsockopt. */
+struct sctp_add_streams_expr {
+	struct expression *sas_assoc_id;
+	struct expression *sas_instrms;
+	struct expression *sas_outstrms;
+};
+
 /* The errno-related info from strace to summarize a system call error */
 struct errno_spec {
 	const char *errno_macro;	/* errno symbol (C macro name) */
-- 
GitLab