diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l index 1244636e640f55631833deeaf5e96884b3785888..aa5af067e61d313ce6eb43d81b0506073734fa00 100644 --- a/gtests/net/packetdrill/lexer.l +++ b/gtests/net/packetdrill/lexer.l @@ -506,6 +506,10 @@ sca_assoc_id return SCA_ASSOC_ID; sca_keynumber return SCA_KEYNUMBER; sca_keylength return SCA_KEYLENGTH; sca_key return SCA_KEY; +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; CHUNK return CHUNK; DATA return DATA; INIT return INIT; diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index f5c85b66fe083778b3a6556f247c61649b1f9dae..775094cc029ed06fce576cbe11e5ad6e3d13622c 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -567,6 +567,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %token <reserved> GAIDS_NUMBER_OF_IDS GAIDS_ASSOC_ID SSPP_ASSOC_ID SSPP_ADDR %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 <floating> FLOAT %token <integer> INTEGER HEX_INTEGER %token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR @@ -640,6 +641,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <expression> sctp_adaptation_event sai_type sai_flags sai_length sai_adaptation_ind %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 <errno_info> opt_errno %type <chunk_list> sctp_chunk_list_spec %type <chunk_list_item> sctp_chunk_spec @@ -2632,6 +2634,9 @@ expression | sctp_authkey { $$ = $1; } +| sctp_reset_streams{ + $$ = $1; +} | null { $$ = $1; } @@ -4946,6 +4951,43 @@ sctp_authkey $$->value.sctp_authkey->sca_key = $12; }; +srs_flags +: SRS_FLAGS '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("srs_flags out of range"); + } + $$ = new_integer_expression($3, "%hu"); +} +| SRS_FLAGS '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +; + +sctp_reset_streams +: '{' SRS_ASSOC_ID '=' sctp_assoc_id ',' srs_flags ',' SRS_NUMBER_STREAMS '=' INTEGER ',' SRS_STREAM_LIST '=' array '}' { + $$ = new_expression(EXPR_SCTP_RESET_STREAMS); + $$->value.sctp_reset_streams = calloc(1, sizeof(struct sctp_reset_streams_expr)); + $$->value.sctp_reset_streams->srs_assoc_id = $4; + $$->value.sctp_reset_streams->srs_flags = $6; + if (!is_valid_u16($10)) { + semantic_error("srs_number_streams out of range"); + } + $$->value.sctp_reset_streams->srs_number_streams = new_integer_expression($10, "%hu"); + $$->value.sctp_reset_streams->srs_stream_list = $14; +} +| '{' srs_flags ',' SRS_NUMBER_STREAMS '=' INTEGER ',' SRS_STREAM_LIST '=' array '}' { + $$ = new_expression(EXPR_SCTP_RESET_STREAMS); + $$->value.sctp_reset_streams = calloc(1, sizeof(struct sctp_reset_streams_expr)); + $$->value.sctp_reset_streams->srs_assoc_id = new_expression(EXPR_ELLIPSIS); + $$->value.sctp_reset_streams->srs_flags = $2; + if (!is_valid_u16($6)) { + semantic_error("srs_number_streams out of range"); + } + $$->value.sctp_reset_streams->srs_number_streams = new_integer_expression($6, "%hu"); + $$->value.sctp_reset_streams->srs_stream_list = $10; +} +; opt_errno : { $$ = NULL; } | WORD note { diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c index 4a9798f87287b917f9422df31375c4b03e78a1ae..a3c9823ef89b7ad06341ed8e33194b19c27a18cd 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -3981,6 +3981,47 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, #endif optval = &paddrparams; break; +#endif +#ifdef SCTP_RESET_STREAMS + case EXPR_SCTP_RESET_STREAMS: { + struct sctp_reset_streams *reset_streams; + struct expression_list *list; + int len = 0, i = 0; + + if (check_type(val_expression->value.sctp_reset_streams->srs_stream_list, EXPR_LIST, error)) { + return STATUS_ERR; + } + list = val_expression->value.sctp_reset_streams->srs_stream_list->value.list; + len = expression_list_length(list); + reset_streams = malloc(sizeof(u32) + sizeof(u16) + sizeof(u16) + (sizeof(u16) * len)); + + if (get_sctp_assoc_t(val_expression->value.sctp_reset_streams->srs_assoc_id, + &reset_streams->srs_assoc_id, error)) { + return STATUS_ERR; + } + if (get_u16(val_expression->value.sctp_reset_streams->srs_flags, + &reset_streams->srs_flags, error)) { + return STATUS_ERR; + } + if (get_u16(val_expression->value.sctp_reset_streams->srs_number_streams, + &reset_streams->srs_number_streams, error)) { + return STATUS_ERR; + } + + for (i = 0; i < len; i++) { + struct expression *expr; + expr = get_arg(list, i, error); + get_u16(expr, &(reset_streams->srs_stream_list[i]), error); + } + + printf("SCTP_RESET_STREAMS\n"); + printf("flags: %hu\n", reset_streams->srs_flags); + printf("number_of-streams: %hu\n", reset_streams->srs_number_streams); + printf("size: %d\n", len); + + optval = &reset_streams; + break; + } #endif default: asprintf(error, "unsupported value type: %s", @@ -3993,7 +4034,7 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, result = setsockopt(live_fd, level, optname, optval, optlen); return end_syscall(state, syscall, CHECK_EXACT, result, error); -#if defined(SCTP_HMAC_IDENT) || defined(SCTP_AUTH_KEY) +#if defined(SCTP_HMAC_IDENT) || defined(SCTP_AUTH_KEY) || defined(SCTP_RESET_STREAMS) free(optval); #endif } diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c index 1b78fccfec74215093642b6e0833afbbf83e1a41..f0e94f1aff7087184816b1a953fef07b6fb2fcd4 100644 --- a/gtests/net/packetdrill/script.c +++ b/gtests/net/packetdrill/script.c @@ -108,6 +108,7 @@ 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"}, { NUM_EXPR_TYPES, NULL} }; @@ -607,6 +608,12 @@ 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); + break; case EXPR_WORD: assert(expression->value.string); free(expression->value.string); @@ -2418,6 +2425,42 @@ 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) +{ + struct sctp_reset_stream_expr *in_reset_stream; + struct sctp_reset_stream_expr *out_reset_stream; + + assert(in->type == EXPR_SCTP_RESET_STREAM); + assert(in->value.sctp_reset_stream); + assert(out->type == EXPR_SCTP_RESET_STREAM); + + out->value.sctp_reset_stream = calloc(1, sizeof(struct sctp_reset_stream_expr)); + + in_reset_stream = in->value.sctp_reset_stream; + out_reset_stream = out->value.sctp_reset_stream; + + if (evaluate(in_reset_stream->srs_assoc_id, + &out_reset_stream->srs_assoc_id, + error)) + return STATUS_ERR; + if (evaluate(in_reset_stream->srs_flags, + &out_reset_stream->srs_flags, + error)) + return STATUS_ERR; + if (evaluate(in_reset_stream->srs_number_streams, + &out_reset_stream->srs_number_streams, + error)) + return STATUS_ERR; + if (evaluate(in_reset_stream->srs_stream_list, + &out_reset_stream->srs_stream_list, + error)) + return STATUS_ERR; + + return STATUS_OK; +} + static int evaluate(struct expression *in, struct expression **out_ptr, char **error) { @@ -2566,6 +2609,9 @@ 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); + break; case EXPR_WORD: out->type = EXPR_INTEGER; if (symbol_to_int(in->value.string, diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h index 6769d095c235523409f84915806502704ee57d23..3967c12bb142596962a89bb4237b03dfef0e98f5 100644 --- a/gtests/net/packetdrill/script.h +++ b/gtests/net/packetdrill/script.h @@ -88,6 +88,7 @@ enum expression_t { EXPR_SCTP_SETPEERPRIM, /* expression tree for sctp_setpeerprim struct for [gs]etsockopt */ 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 */ NUM_EXPR_TYPES, }; /* Convert an expression type to a human-readable string */ @@ -149,6 +150,7 @@ struct expression { struct sctp_setpeerprim_expr *sctp_setpeerprim; struct sctp_authchunk_expr *sctp_authchunk; struct sctp_authkey_expr *sctp_authkey; + struct sctp_reset_streams_expr *sctp_reset_streams; } value; const char *format; /* the printf format for printing the value */ }; @@ -565,6 +567,14 @@ struct sctp_authkey_expr { struct expression *sca_key; }; +/* Parse tree for sctp_reset_stream struct for setsockopt. */ +struct sctp_reset_streams_expr { + struct expression *srs_assoc_id; + struct expression *srs_flags; + struct expression *srs_number_streams; + struct expression *srs_stream_list; +}; + /* The errno-related info from strace to summarize a system call error */ struct errno_spec { const char *errno_macro; /* errno symbol (C macro name) */ diff --git a/gtests/net/packetdrill/symbols_freebsd.c b/gtests/net/packetdrill/symbols_freebsd.c index 2716450bec02eeb3a1f6b7e0e2b992aa98a93f90..5798d69a244db5204b9155c2c21b2cad962b25f2 100644 --- a/gtests/net/packetdrill/symbols_freebsd.c +++ b/gtests/net/packetdrill/symbols_freebsd.c @@ -264,6 +264,7 @@ struct int_symbol platform_symbols_table[] = { { SCTP_USE_EXT_RCVINFO, "SCTP_USE_EXT_RCVINFO" }, { SCTP_AUTH_HMAC_ID_SHA1, "SCTP_AUTH_HMAC_ID_SHA1" }, { SCTP_AUTH_HMAC_ID_SHA256, "SCTP_AUTH_HMAC_ID_SHA256" }, + /* sctp stream reconfiguration */ { SCTP_ENABLE_STREAM_RESET, "SCTP_ENABLE_STREAM_RESET" }, { SCTP_ENABLE_RESET_STREAM_REQ, "SCTP_ENABLE_RESET_STREAM_REQ" },