diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l index c889f1b0026b5f7fed00bc70dc4921b626e8b98a..5ecfac2619ffe2cb967b143c0d1b6a5f84a88621 100644 --- a/gtests/net/packetdrill/lexer.l +++ b/gtests/net/packetdrill/lexer.l @@ -570,6 +570,7 @@ OUTGOING_SSN_RESET return OUTGOING_SSN_RESET; INCOMING_SSN_RESET return INCOMING_SSN_RESET; SSN_TSN_RESET return SSN_TSN_RESET; RECONFIG_RESPONSE return RECONFIG_RESPONSE; +ADD_INCOMING_STREAMS return ADD_INCOMING_STREAMS; req_sn return REQ_SN; resp_sn return RESP_SN; last_tsn return LAST_TSN; @@ -577,6 +578,7 @@ sids return SIDS; result return RESULT; sender_next_tsn return SENDER_NEXT_TSN; receiver_next_tsn return RECEIVER_NEXT_TSN; +number_of_new_streams return NUMBER_OF_NEW_STREAMS; PARAMETER return PARAMETER; HEARTBEAT_INFORMATION return HEARTBEAT_INFORMATION; IPV4_ADDRESS return IPV4_ADDRESS; diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index f3befd608b0d2bca130ba87312119b7815d9fcb8..776a238f41700936a5b56cd245fc4b1a1fe88655 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -527,7 +527,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %token <reserved> SUPPORTED_EXTENSIONS ADAPTATION_CODE_POINT ADAPTATION_INDICATION %token <reserved> OUTGOING_SSN_RESET REQ_SN RESP_SN LAST_TSN SIDS INCOMING_SSN_RESET %token <reserved> RECONFIG_RESPONSE RESULT SENDER_NEXT_TSN RECEIVER_NEXT_TSN -%token <reserved> SSN_TSN_RESET +%token <reserved> SSN_TSN_RESET ADD_INCOMING_STREAMS NUMBER_OF_NEW_STREAMS %token <reserved> ADDR INCR TYPES PARAMS %token <reserved> IPV4_TYPE IPV6_TYPE HOSTNAME_TYPE %token <reserved> CAUSE @@ -689,7 +689,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <parameter_list_item> sctp_adaptation_indication_parameter_spec %type <parameter_list_item> sctp_pad_parameter_spec sctp_reconfig_parameter_spec %type <parameter_list_item> outgoing_ssn_reset_request incoming_ssn_reset_request -%type <parameter_list_item> reconfig_response ssn_tsn_reset_request +%type <parameter_list_item> reconfig_response ssn_tsn_reset_request add_incoming_streams_request %type <cause_list> opt_cause_list_spec sctp_cause_list_spec %type <cause_list_item> sctp_cause_spec %type <cause_list_item> sctp_generic_cause_spec @@ -712,7 +712,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <integer> opt_tag opt_a_rwnd opt_os opt_is opt_tsn opt_sid opt_ssn %type <integer> opt_mid opt_fsn %type <integer> opt_cum_tsn opt_ppid opt_sender_next_tsn opt_receiver_next_tsn -%type <integer> opt_req_sn opt_resp_sn opt_last_tsn opt_result +%type <integer> opt_req_sn opt_resp_sn opt_last_tsn opt_result opt_number_of_new_streams %type <byte_list> opt_val opt_info byte_list chunk_types_list %type <byte_list_item> byte %type <u16_list> u16_list @@ -1748,6 +1748,7 @@ sctp_reconfig_parameter_spec | incoming_ssn_reset_request { $$ = $1; } | ssn_tsn_reset_request { $$ = $1; } | reconfig_response { $$ = $1; } +| add_incoming_streams_request { $$ = $1; } ; opt_sender_next_tsn @@ -1770,6 +1771,16 @@ opt_receiver_next_tsn | RECEIVER_NEXT_TSN '=' ELLIPSIS { $$ = -1; } ; +opt_number_of_new_streams +: NUMBER_OF_NEW_STREAMS '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("number_of_new_streams out of range"); + } + $$ = $3; +} +| NUMBER_OF_NEW_STREAMS '=' ELLIPSIS { $$ = -1; } +; + outgoing_ssn_reset_request : OUTGOING_SSN_RESET '[' opt_req_sn ',' opt_resp_sn ',' opt_last_tsn ']' { $$ = sctp_outgoing_ssn_reset_request_parameter_new($3, $5, $7, NULL); @@ -1803,6 +1814,12 @@ reconfig_response } ; +add_incoming_streams_request +: ADD_INCOMING_STREAMS '[' opt_req_sn ',' opt_number_of_new_streams ']' { + $$ = sctp_add_incoming_streams_request_parameter_new($3, $5); +} +; + sctp_reconfig_chunk_spec : RECONFIG '[' opt_flags ',' sctp_reconfig_parameter_list_spec ']' { $$ = sctp_reconfig_chunk_new($3, $5); diff --git a/gtests/net/packetdrill/run_packet.c b/gtests/net/packetdrill/run_packet.c index 6b48611dc796d3ba1bc4c27a6edb0ad318813ac3..2e91a37c69850cb8e775bcb2d290fb71fcbec0a0 100644 --- a/gtests/net/packetdrill/run_packet.c +++ b/gtests/net/packetdrill/run_packet.c @@ -780,6 +780,12 @@ static int map_inbound_sctp_packet( } break; } + case SCTP_ADD_INCOMING_STREAMS_REQUEST_PARAMETER_TYPE: { + struct sctp_add_incoming_streams_request_parameter *request; + request = (struct sctp_add_incoming_streams_request_parameter *)parameter; + request->reqsn = htonl(htonl(request->reqsn) + remote_diff); + break; + } default: //do nothing break; @@ -1023,6 +1029,12 @@ static int map_outbound_live_sctp_packet( } break; } + case SCTP_ADD_INCOMING_STREAMS_REQUEST_PARAMETER_TYPE: { + struct sctp_add_incoming_streams_request_parameter *request; + request = (struct sctp_add_incoming_streams_request_parameter *)parameter; + request->reqsn = htonl(htonl(request->reqsn) + local_diff); + break; + } default: //do nothing break; diff --git a/gtests/net/packetdrill/sctp.h b/gtests/net/packetdrill/sctp.h index 58a9f252d3829688d6747c934a5363f3a0a469ae..bd590b52d0e400d87fc783a74d489b485409a5db 100644 --- a/gtests/net/packetdrill/sctp.h +++ b/gtests/net/packetdrill/sctp.h @@ -252,6 +252,7 @@ struct sctp_reconfig_chunk { #define SCTP_INCOMING_SSN_RESET_REQUEST_PARAMETER_TYPE 0x000e #define SCTP_SSN_TSN_RESET_REQUEST_PARAMETER_TYPE 0x000f #define SCTP_RECONFIG_RESPONSE_PARAMETER_TYPE 0x0010 +#define SCTP_ADD_INCOMING_STREAMS_REQUEST_PARAMETER_TYPE 0x0012 #define SCTP_ECN_CAPABLE_PARAMETER_TYPE 0x8000 #define SCTP_SUPPORTED_EXTENSIONS_PARAMETER_TYPE 0x8008 #define SCTP_PAD_PARAMETER_TYPE 0x8005 @@ -367,6 +368,14 @@ struct sctp_reconfig_response_parameter { __be32 receiver_next_tsn; } __packed; +struct sctp_add_incoming_streams_request_parameter { + __be16 type; + __be16 length; + __be32 reqsn; + __be16 number_of_new_streams; + __be16 reserved; +} __packed; + #define SCTP_INVALID_STREAM_IDENTIFIER_CAUSE_CODE 0x0001 #define SCTP_MISSING_MANDATORY_PARAMETER_CAUSE_CODE 0x0002 #define SCTP_STALE_COOKIE_ERROR_CAUSE_CODE 0x0003 diff --git a/gtests/net/packetdrill/sctp_chunk_to_string.c b/gtests/net/packetdrill/sctp_chunk_to_string.c index 0f73312ac7122611891566eee8c82d37600d3647..d4124883c2916bcfb05fe04b98fd0764e3fe0978 100644 --- a/gtests/net/packetdrill/sctp_chunk_to_string.c +++ b/gtests/net/packetdrill/sctp_chunk_to_string.c @@ -421,6 +421,27 @@ static int sctp_reconfig_response_parameter_to_string( return STATUS_OK; } +static int sctp_add_incoming_streams_request_parameter_to_string( + FILE *s, + struct sctp_add_incoming_streams_request_parameter *parameter, + char **error) +{ + u16 length; + u32 reqsn; + u16 number_of_new_streams; + + length = ntohs(parameter->length); + reqsn = ntohl(parameter->reqsn); + number_of_new_streams = ntohs(parameter->number_of_new_streams); + + fputs("ADD_INCOMING_STREAMS[", s); + fprintf(s, "len=%hu, ", length); + fprintf(s, "req_sn=%u, ", reqsn); + fprintf(s, "number_of_new_streams=%hu", number_of_new_streams); + fputs("]", s); + return STATUS_OK; +} + static int sctp_unknown_parameter_to_string( FILE *s, struct sctp_parameter *parameter, @@ -543,6 +564,10 @@ static int sctp_parameter_to_string(FILE *s, result = sctp_reconfig_response_parameter_to_string(s, (struct sctp_reconfig_response_parameter *)parameter, error); break; + case SCTP_ADD_INCOMING_STREAMS_REQUEST_PARAMETER_TYPE: + result = sctp_add_incoming_streams_request_parameter_to_string(s, + (struct sctp_add_incoming_streams_request_parameter *)parameter, error); + break; default: result = sctp_unknown_parameter_to_string(s, parameter, error); break; diff --git a/gtests/net/packetdrill/sctp_packet.c b/gtests/net/packetdrill/sctp_packet.c index fd49921ebfaaa1e0df3871aca0408c52c83b1f70..5a30c97d68f9c3735767cf6d99fcf86d14649f8d 100644 --- a/gtests/net/packetdrill/sctp_packet.c +++ b/gtests/net/packetdrill/sctp_packet.c @@ -1951,6 +1951,39 @@ sctp_ssn_tsn_reset_request_parameter_new(s64 reqsn) parameter_length, flags); } +struct sctp_parameter_list_item * +sctp_add_incoming_streams_request_parameter_new(s64 reqsn, s32 number_of_new_streams) +{ + struct sctp_add_incoming_streams_request_parameter *parameter; + u32 flags = 0; + u16 parameter_length; + + parameter_length = sizeof(struct sctp_add_incoming_streams_request_parameter); + + parameter = malloc(parameter_length); + assert(parameter != NULL); + + parameter->type = htons(SCTP_ADD_INCOMING_STREAMS_REQUEST_PARAMETER_TYPE); + parameter->length = htons(parameter_length); + parameter->reserved = 0; + + if (reqsn == -1) { + flags |= FLAG_RECONFIG_REQ_SN_NOCHECK; + parameter->reqsn = 0; + } else { + parameter->reqsn = htonl((u32)reqsn); + } + if (reqsn == -1) { + flags |= FLAG_RECONFIG_NUMBER_OF_NEW_STREAMS_NOCHECK; + parameter->number_of_new_streams = 0; + } else { + parameter->number_of_new_streams = htons((u16)number_of_new_streams); + } + + return sctp_parameter_list_item_new((struct sctp_parameter *)parameter, + parameter_length, flags); +} + struct sctp_parameter_list_item * sctp_ecn_capable_parameter_new(void) { @@ -2636,6 +2669,17 @@ new_sctp_packet(int address_family, return NULL; } break; + case SCTP_ADD_INCOMING_STREAMS_REQUEST_PARAMETER_TYPE: + if (parameter_item->flags & FLAG_RECONFIG_REQ_SN_NOCHECK) { + asprintf(error, + "reqsn value must be specified for inbound packets"); + return NULL; + } + if (parameter_item->flags & FLAG_RECONFIG_NUMBER_OF_NEW_STREAMS_NOCHECK) { + asprintf(error, + "number_of_new_streams value must be specified for inbound packets"); + return NULL; + } default: break; } diff --git a/gtests/net/packetdrill/sctp_packet.h b/gtests/net/packetdrill/sctp_packet.h index 515901b08a83cf47855b61669adf4f7f5969c377..e468018c68e75b3b0a14bd526d881f23a05fca28 100644 --- a/gtests/net/packetdrill/sctp_packet.h +++ b/gtests/net/packetdrill/sctp_packet.h @@ -392,9 +392,15 @@ sctp_ssn_tsn_reset_request_parameter_new(s64 reqsn); #define FLAG_RECONFIG_RESULT_NOCHECK 0x00000010 #define FLAG_RECONFIG_SENDER_NEXT_TSN_NOCHECK 0x00000040 #define FLAG_RECONFIG_RECEIVER_NEXT_TSN_NOCHECK 0x00000080 + struct sctp_parameter_list_item * sctp_reconfig_response_parameter_new(s64 respsn, s64 result, s64 sender_next_tsn, s64 receiver_next_tsn); +#define FLAG_RECONFIG_NUMBER_OF_NEW_STREAMS_NOCHECK 0x00000080 + +struct sctp_parameter_list_item * +sctp_add_incoming_streams_request_parameter_new(s64 reqsn, s32 number_of_new_streams); + struct sctp_parameter_list * sctp_parameter_list_new(void);