diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l index e6decf23b0f988713b3971300bc291d100bd4d5c..17e8f55ed446fab88020a5a1db974f5ecf1dc07f 100644 --- a/gtests/net/packetdrill/lexer.l +++ b/gtests/net/packetdrill/lexer.l @@ -567,11 +567,14 @@ gaps return GAPS; dups return DUPS; adaptation_code_point return ADAPTATION_CODE_POINT; OUTGOING_SSN_RESET return OUTGOING_SSN_RESET; +RECONFIG_RESPONSE return RECONFIG_RESPONSE; req_sn return REQ_SN; resp_sn return RESP_SN; last_tsn return LAST_TSN; -result return RESULT; sids return SIDS; +result return RESULT; +sender_next_tsn return SENDER_NEXT_TSN; +receiver_next_tsn return RECEIVER_NEXT_TSN; 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 eaa91c2526af86eb76f027e015e9c7be23448219..a9051530391985a7354fa41ea1883065d4ca212d 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -525,7 +525,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %token <reserved> STATE_COOKIE UNRECOGNIZED_PARAMETER COOKIE_PRESERVATIVE %token <reserved> HOSTNAME_ADDRESS SUPPORTED_ADDRESS_TYPES ECN_CAPABLE %token <reserved> SUPPORTED_EXTENSIONS ADAPTATION_CODE_POINT ADAPTATION_INDICATION -%token <reserved> OUTGOING_SSN_RESET REQ_SN RESP_SN LAST_TSN SIDS RESULT +%token <reserved> OUTGOING_SSN_RESET REQ_SN RESP_SN LAST_TSN SIDS +%token <reserved> RECONFIG_RESPONSE RESULT SENDER_NEXT_TSN RECEIVER_NEXT_TSN %token <reserved> ADDR INCR TYPES PARAMS %token <reserved> IPV4_TYPE IPV6_TYPE HOSTNAME_TYPE %token <reserved> CAUSE @@ -686,6 +687,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <parameter_list_item> sctp_supported_extensions_parameter_spec %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 reconfig_response %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 @@ -707,8 +709,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <integer> opt_shutdown_complete_flags opt_i_data_flags opt_len %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 -%type <integer> opt_req_sn opt_resp_sn opt_last_tsn +%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 <byte_list> opt_val opt_info byte_list chunk_types_list %type <byte_list_item> byte %type <u16_list> u16_list @@ -1690,7 +1692,7 @@ sctp_pad_chunk_spec opt_req_sn : REQ_SN '=' INTEGER { - if (!is_valid_u16($3)) { + if (!is_valid_u32($3)) { semantic_error("req_sn out of range"); } $$ = $3; @@ -1700,7 +1702,7 @@ opt_req_sn opt_resp_sn : RESP_SN '=' INTEGER { - if (!is_valid_u16($3)) { + if (!is_valid_u32($3)) { semantic_error("resp_sn out of range"); } $$ = $3; @@ -1710,7 +1712,7 @@ opt_resp_sn opt_last_tsn : LAST_TSN '=' INTEGER { - if (!is_valid_u16($3)) { + if (!is_valid_u32($3)) { semantic_error("last_tsn out of range"); } $$ = $3; @@ -1718,6 +1720,16 @@ opt_last_tsn | LAST_TSN '=' ELLIPSIS { $$ = -1; } ; +opt_result +: RESULT '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("result out of range"); + } + $$ = $3; +} +| RESULT '=' ELLIPSIS { $$ = -1; } +; + sctp_reconfig_parameter_list_spec : sctp_reconfig_parameter_spec { $$ = sctp_parameter_list_new(); @@ -1730,7 +1742,31 @@ sctp_reconfig_parameter_list_spec ; sctp_reconfig_parameter_spec -: OUTGOING_SSN_RESET '[' opt_req_sn ',' opt_resp_sn ',' opt_last_tsn ']' { +:outgoing_ssn_reset_request { $$ = $1; } +|reconfig_response { $$ = $1; } +; +opt_sender_next_tsn +: SENDER_NEXT_TSN '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("sender_next_tsn out of range"); + } + $$ = $3; +} +| SENDER_NEXT_TSN '=' ELLIPSIS { $$ = -1; } +; + +opt_receiver_next_tsn +: RECEIVER_NEXT_TSN '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("receiver_next_tsn out of range"); + } + $$ = $3; +} +| RECEIVER_NEXT_TSN '=' 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); } | OUTGOING_SSN_RESET '[' opt_req_sn ',' opt_resp_sn ',' opt_last_tsn ',' SIDS '=' '[' u16_list ']' ']' { @@ -1738,6 +1774,15 @@ sctp_reconfig_parameter_spec } ; +reconfig_response +:RECONFIG_RESPONSE '[' opt_resp_sn ',' opt_result ']' { + $$ = sctp_reconfig_response_new($3, $5, -2, -2); +} +|RECONFIG_RESPONSE '[' opt_resp_sn ',' opt_result ',' opt_sender_next_tsn ',' opt_receiver_next_tsn']' { + $$ = sctp_reconfig_response_new($3, $5, $7, $9); +} +; + 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 190de08ea3116d8d4ef1980260a32d0429cb59e4..79953ee8fa8578fb1c57f0e4f1f4adf2de692159 100644 --- a/gtests/net/packetdrill/run_packet.c +++ b/gtests/net/packetdrill/run_packet.c @@ -758,6 +758,16 @@ static int map_inbound_sctp_packet( reset->last_tsn = htonl(ntohl(reset->last_tsn) + remote_diff); break; } + case SCTP_RECONFIG_RESPONSE_PARAMETER_TYPE: { + struct sctp_reconfig_response_parameter *response; + response = (struct sctp_reconfig_response_parameter *)parameter; + response->respsn = htonl(htonl(response->respsn) + local_diff); + if (response->length == sizeof(struct sctp_reconfig_response_parameter)) { + response->receiver_next_tsn = htonl(htonl(response->receiver_next_tsn) + local_diff); + response->sender_next_tsn = htonl(htonl(response->sender_next_tsn) + remote_diff); + } + break; + } default: //do nothing break; @@ -979,6 +989,16 @@ static int map_outbound_live_sctp_packet( reset->last_tsn = htonl(ntohl(reset->last_tsn) + local_diff); break; } + case SCTP_RECONFIG_RESPONSE_PARAMETER_TYPE: { + struct sctp_reconfig_response_parameter *response; + response = (struct sctp_reconfig_response_parameter *)parameter; + response->respsn = htonl(htonl(response->respsn) + remote_diff); + if (response->length == sizeof(struct sctp_reconfig_response_parameter)) { + response->receiver_next_tsn = htonl(htonl(response->receiver_next_tsn) + local_diff); + response->sender_next_tsn = htonl(htonl(response->sender_next_tsn) + remote_diff); + } + break; + } default: //do nothing break; diff --git a/gtests/net/packetdrill/sctp.h b/gtests/net/packetdrill/sctp.h index 6a85c2cf7fa512d0cae7c0b9129acbdf1e9cc6c0..84bdeff7d467b4dc6ce1e643369ce145405c6ae5 100644 --- a/gtests/net/packetdrill/sctp.h +++ b/gtests/net/packetdrill/sctp.h @@ -249,6 +249,7 @@ struct sctp_reconfig_chunk { #define SCTP_HOSTNAME_ADDRESS_PARAMETER_TYPE 0x000b #define SCTP_SUPPORTED_ADDRESS_TYPES_PARAMETER_TYPE 0x000c #define SCTP_OUTGOING_SSN_RESET_REQUEST_PARAMETER_TYPE 0x000d +#define SCTP_RECONFIG_RESPONSE_PARAMETER_TYPE 0x0010 #define SCTP_ECN_CAPABLE_PARAMETER_TYPE 0x8000 #define SCTP_SUPPORTED_EXTENSIONS_PARAMETER_TYPE 0x8008 #define SCTP_PAD_PARAMETER_TYPE 0x8005 @@ -342,6 +343,15 @@ struct sctp_outgoing_ssn_reset_request_parameter { __be16 sids[]; } __packed; +struct sctp_reconfig_response_parameter { + __be16 type; + __be16 length; + __be32 respsn; + __be32 result; + __be32 sender_next_tsn; + __be32 receiver_next_tsn; +} __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 4f30526276162ea9273ab19b385ac4b51c4859be..c3634c5425410595a62e90cc4c7e757bee6d72dd 100644 --- a/gtests/net/packetdrill/sctp_chunk_to_string.c +++ b/gtests/net/packetdrill/sctp_chunk_to_string.c @@ -348,6 +348,31 @@ static int sctp_outgoing_ssn_reset_request_parameter_to_string( return STATUS_OK; } +static int sctp_reconfig_response_parameter_to_string( + FILE *s, + struct sctp_reconfig_response_parameter *parameter, + char **error) +{ + u16 length; + u32 respsn; + u32 sender_next_tsn; + u32 receiver_next_tsn; + + length = ntohs(parameter->length); + respsn = ntohl(parameter->respsn); + fputs("RECONFIG_RESPONSE[", s); + fprintf(s, "len=%hu, ", length); + fprintf(s, "resp_sn=%u", respsn); + if (length == sizeof(struct sctp_reconfig_response_parameter)){ + sender_next_tsn = ntohl(parameter->sender_next_tsn); + receiver_next_tsn = ntohl(parameter->receiver_next_tsn); + fprintf(s, ", sender_next_tsn=%u, ", sender_next_tsn); + fprintf(s, "receiver_next_tsn=%u", receiver_next_tsn); + } + fputs("]", s); + return STATUS_OK; +} + static int sctp_unknown_parameter_to_string( FILE *s, struct sctp_parameter *parameter, @@ -457,7 +482,11 @@ static int sctp_parameter_to_string(FILE *s, case SCTP_OUTGOING_SSN_RESET_REQUEST_PARAMETER_TYPE: result = sctp_outgoing_ssn_reset_request_parameter_to_string(s, (struct sctp_outgoing_ssn_reset_request_parameter *)parameter, error); - break; + break; + case SCTP_RECONFIG_RESPONSE_PARAMETER_TYPE: + result = sctp_reconfig_response_parameter_to_string(s, + (struct sctp_reconfig_response_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 ff1df004f4330820e3b14143ccc95521df49d870..126d1f5166d8eef7e0451b9f526e9727f34decfb 100644 --- a/gtests/net/packetdrill/sctp_packet.c +++ b/gtests/net/packetdrill/sctp_packet.c @@ -1795,7 +1795,7 @@ sctp_pad_parameter_new(s64 len, u8 *padding) } struct sctp_parameter_list_item * -sctp_outgoing_ssn_reset_request_parameter_new(u32 reqsn, u32 respsn, u32 last_tsn, struct sctp_u16_list *sids) +sctp_outgoing_ssn_reset_request_parameter_new(s64 reqsn, s64 respsn, s64 last_tsn, struct sctp_u16_list *sids) { struct sctp_outgoing_ssn_reset_request_parameter *parameter; u32 flags = 0; @@ -1813,9 +1813,24 @@ sctp_outgoing_ssn_reset_request_parameter_new(u32 reqsn, u32 respsn, u32 last_ts parameter->type = htons(SCTP_OUTGOING_SSN_RESET_REQUEST_PARAMETER_TYPE); parameter->length = htons(parameter_length); - parameter->reqsn = htonl(reqsn); - parameter->respsn = htonl(respsn); - parameter->last_tsn = htonl(last_tsn); + if (reqsn == -1) { + flags |= FLAG_RECONFIG_REQ_SN_NOCHECK; + parameter->reqsn = 0; + } else { + parameter->reqsn = htonl((u32)reqsn); + } + if (respsn == -1) { + flags |= FLAG_RECONFIG_RESP_SN_NOCHECK; + parameter->respsn = 0; + } else { + parameter->respsn = htonl((u32)respsn); + } + if (last_tsn == -1) { + flags |= FLAG_RECONFIG_LAST_TSN_NOCHECK; + parameter->last_tsn = 0; + } else { + parameter->last_tsn = htonl((u32)last_tsn); + } if (sids != NULL) { struct sctp_u16_list_item *item; for (item = sids->first; item != NULL; item = item->next) { @@ -1827,6 +1842,54 @@ sctp_outgoing_ssn_reset_request_parameter_new(u32 reqsn, u32 respsn, u32 last_ts parameter_length, flags); } +struct sctp_parameter_list_item * +sctp_reconfig_response_new(s64 respsn, s64 result, s64 sender_next_tsn, s64 receiver_next_tsn) +{ + struct sctp_reconfig_response_parameter *parameter; + u32 flags = 0; + u16 parameter_length; + + parameter_length = sizeof(struct sctp_reconfig_response_parameter); + if (receiver_next_tsn == -2 && sender_next_tsn == -2) { + parameter_length -=sizeof(u32); + parameter_length -=sizeof(u32); + } + parameter = malloc(parameter_length); + assert(parameter != NULL); + + parameter->type = htons(SCTP_RECONFIG_RESPONSE_PARAMETER_TYPE); + parameter->length = htons(parameter_length); + + if (respsn == -1) { + flags |= FLAG_RECONFIG_RESP_SN_NOCHECK; + parameter->respsn = 0; + } else { + parameter->respsn = htonl((u32)respsn); + } + if (result == -1) { + flags |= FLAG_RECONFIG_RESULT_NOCHECK; + parameter->result = 0; + } else { + parameter->result = htonl((u32)result); + } + if (receiver_next_tsn != -2 && sender_next_tsn != -2) { + if (sender_next_tsn == -1) { + flags |= FLAG_RECONFIG_SENDER_NEXT_TSN_NOCHECK; + parameter->sender_next_tsn = 0; + } else { + parameter->sender_next_tsn = htonl((u32)sender_next_tsn); + } + if (receiver_next_tsn == -1) { + flags |= FLAG_RECONFIG_RECEIVER_NEXT_TSN_NOCHECK; + parameter->receiver_next_tsn = 0; + } else { + parameter->receiver_next_tsn = htonl((u32)receiver_next_tsn); + } + } + return sctp_parameter_list_item_new((struct sctp_parameter *)parameter, + parameter_length, flags); +} + struct sctp_parameter_list_item * sctp_ecn_capable_parameter_new(void) { diff --git a/gtests/net/packetdrill/sctp_packet.h b/gtests/net/packetdrill/sctp_packet.h index 50d3bb8a79956900bd112a82a0864322aa2c5fe3..530530e9ef0f1a332f996ba2b880de5fb7194c8c 100644 --- a/gtests/net/packetdrill/sctp_packet.h +++ b/gtests/net/packetdrill/sctp_packet.h @@ -376,8 +376,18 @@ sctp_supported_extensions_parameter_new(struct sctp_byte_list *list); struct sctp_parameter_list_item * sctp_pad_parameter_new(s64 len, u8 *padding); +#define FLAG_RECONFIG_REQ_SN_NOCHECK 0x00000001 +#define FLAG_RECONFIG_RESP_SN_NOCHECK 0x00000002 +#define FLAG_RECONFIG_LAST_TSN_NOCHECK 0x00000004 + +struct sctp_parameter_list_item * +sctp_outgoing_ssn_reset_request_parameter_new(s64 reqsn, s64 respsn, s64 last_tsn, struct sctp_u16_list *sids); + +#define FLAG_RECONFIG_RESULT_NOCHECK 0x00000001 +#define FLAG_RECONFIG_SENDER_NEXT_TSN_NOCHECK 0x00000004 +#define FLAG_RECONFIG_RECEIVER_NEXT_TSN_NOCHECK 0x00000008 struct sctp_parameter_list_item * -sctp_outgoing_ssn_reset_request_parameter_new(u32 reqsn, u32 respsn, u32 last_tsn, struct sctp_u16_list *sids); +sctp_reconfig_response_new(s64 respsn, s64 result, s64 sender_next_tsn, s64 receiver_next_tsn); struct sctp_parameter_list * sctp_parameter_list_new(void); diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/reset_outgoing_ssn.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/reset_outgoing_ssn.pkt index 5424fcf0f405e7607f503a1ee7e6d2361d837dd7..21c179cb224a9f5c82e224845825ff42e2d7f1cf 100644 --- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/reset_outgoing_ssn.pkt +++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/reset_outgoing_ssn.pkt @@ -32,6 +32,6 @@ srs_number_streams=2, srs_stream_list=[0, 1]}, 12) = 0 +0.0 > sctp: RECONFIG[flgs=0, OUTGOING_SSN_RESET[req_sn=1, resp_sn=0, last_tsn=2, sids=[]]] -+0.0 < sctp: RECONFIG[flgs=0, RECONFIG_RESPONSE[resp_sn=0, result=1]] ++0.0 < sctp: RECONFIG[flgs=0, RECONFIG_RESPONSE[resp_sn=1, result=1]] +1.0 close(3) = 0 diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/reset_outgoing_ssn_passiv.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/reset_outgoing_ssn_passiv.pkt index 56d50dc0749b3716b185f4567cc203f727b94c71..45f0576e1ec4c64b4c1b0b267741aab5a2301318 100644 --- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/reset_outgoing_ssn_passiv.pkt +++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/reset_outgoing_ssn_passiv.pkt @@ -35,4 +35,4 @@ +0.0 read(4, ..., 1000) = 1000 +0.0 < sctp: RECONFIG[flgs=0, OUTGOING_SSN_RESET[req_sn=0, resp_sn=10, last_tsn=2, sids=[0]]] -+0.0 > sctp: RECONFIG[flgs=0, RECONFIG_RESPONSE[resp_sn=10, result=0]] ++0.0 > sctp: RECONFIG[flgs=0, RECONFIG_RESPONSE[resp_sn=0, result=0]]