diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l index 4478ed2e8e8772fd2ca5606c8c4bbfd834d6da5d..4f8b391f11fb09ce9859c30e84e788e9fc2033c5 100644 --- a/gtests/net/packetdrill/lexer.l +++ b/gtests/net/packetdrill/lexer.l @@ -210,6 +210,11 @@ sack_freq return SACK_FREQ; srto_initial return SRTO_INITIAL; srto_max return SRTO_MAX; srto_min return SRTO_MIN; +sasoc_asocmaxrxt return SASOC_ASOCMAXRXT; +sasoc_number_peer_destinations return SASOC_NUMBER_PEER_DESTINATIONS; +sasoc_peer_rwnd return SASOC_PEER_RWND; +sasoc_local_rwnd return SASOC_LOCAL_RWND; +sasoc_cookie_life return SASOC_COOKIE_LIFE; sinit_num_ostreams return SINIT_NUM_OSTREAMS; sinit_max_instreams return SINIT_MAX_INSTREAMS; sinit_max_attempts return SINIT_MAX_ATTEMPTS; diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index 14a3a50f246a98964b4a0f5940685329564552ae..d01b6e32009cdce8f5abbdf609df9e128dbe24fb 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -534,6 +534,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %token <reserved> STALENESS CHK PARAM UNRECOGNIZED_PARAMETERS %token <reserved> SPP_ADDRESS SPP_HBINTERVAL SPP_PATHMAXRXT SPP_PATHMTU %token <reserved> SPP_FLAGS SPP_IPV6_FLOWLABEL_ SPP_DSCP_ +%token <reserved> SASOC_ASOCMAXRXT SASOC_NUMBER_PEER_DESTINATIONS SASOC_PEER_RWND +%token <reserved> SASOC_LOCAL_RWND SASOC_COOKIE_LIFE %token <floating> FLOAT %token <integer> INTEGER HEX_INTEGER %token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR @@ -579,6 +581,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <expression> sctp_paddrparams spp_address spp_hbinterval spp_pathmtu spp_pathmaxrxt %type <expression> spp_flags spp_ipv6_flowlabel spp_dscp %type <expression> spinfo_state spinfo_cwnd spinfo_srtt spinfo_rto spinfo_mtu +%type <expression> sasoc_asocmaxrxt sasoc_number_peer_destinations sasoc_peer_rwnd +%type <expression> sasoc_local_rwnd sasoc_cookie_life sctp_assocparams %type <errno_info> opt_errno %type <chunk_list> sctp_chunk_list_spec %type <chunk_list_item> sctp_chunk_spec @@ -2361,6 +2365,9 @@ expression | sctp_paddrparams { $$ = $1; } +| sctp_assocparams { + $$ = $1; +} ; decimal_integer @@ -2871,6 +2878,72 @@ sctp_paddrparams } ; +sasoc_asocmaxrxt +: SASOC_ASOCMAXRXT '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("sasoc_asocmaxrxt out of range"); + } + $$ = new_integer_expression($3, "%hu"); +} +| SASOC_ASOCMAXRXT '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +sasoc_number_peer_destinations +: SASOC_NUMBER_PEER_DESTINATIONS '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("sasoc_number_peer_destinations out of range"); + } + $$ = new_integer_expression($3, "%hu"); +} +| SASOC_NUMBER_PEER_DESTINATIONS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +sasoc_peer_rwnd +: SASOC_PEER_RWND '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("sasoc_peer_rwnd out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| SASOC_PEER_RWND '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +sasoc_local_rwnd +: SASOC_LOCAL_RWND '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("sasoc_local_rwnd out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| SASOC_LOCAL_RWND '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +sasoc_cookie_life +: SASOC_COOKIE_LIFE '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("sasoc_cookie_life out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| SASOC_COOKIE_LIFE '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +sctp_assocparams +: '{' sasoc_asocmaxrxt ',' sasoc_number_peer_destinations ',' sasoc_peer_rwnd ',' sasoc_local_rwnd ',' sasoc_cookie_life '}' { +#ifdef SCTP_ASSOCINFO + $$ = new_expression(EXPR_SCTP_ASSOCPARAMS); + $$->value.sctp_assocparams = calloc(1, sizeof(struct sctp_assocparams_expr)); + $$->value.sctp_assocparams->sasoc_asocmaxrxt = $2; + $$->value.sctp_assocparams->sasoc_number_peer_destinations = $4; + $$->value.sctp_assocparams->sasoc_peer_rwnd = $6; + $$->value.sctp_assocparams->sasoc_local_rwnd = $8; + $$->value.sctp_assocparams->sasoc_cookie_life = $10; +#elif + $$ = NULL; +#endif +} +; + opt_errno : { $$ = NULL; } | WORD note { diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c index aee26de078065370c20fe72ac3f66bc9e8182eb1..a95bfd33f0bde225455b8968abb8a5356920a21a 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -2121,6 +2121,76 @@ static int check_sctp_stream_value(struct sctp_stream_value_expr *expr, } #endif +#ifdef SCTP_ASSOCINFO +static int check_sctp_assocparams(struct sctp_assocparams_expr *expr, + struct sctp_assocparams *sctp_assocparams, + char **error) +{ + if (expr->sasoc_asocmaxrxt->type != EXPR_ELLIPSIS) { + u16 sasoc_asocmaxrxt; + + if (get_u16(expr->sasoc_asocmaxrxt, &sasoc_asocmaxrxt, error)) { + return STATUS_ERR; + } + if (sctp_assocparams->sasoc_asocmaxrxt != sasoc_asocmaxrxt) { + asprintf(error, "Bad getsockopt sctp_assocparams.sasoc_asocmaxrxt: expected: %hu actual: %hu", + sasoc_asocmaxrxt, sctp_assocparams->sasoc_asocmaxrxt); + return STATUS_ERR; + } + } + if (expr->sasoc_number_peer_destinations->type != EXPR_ELLIPSIS) { + u16 sasoc_number_peer_destinations; + + if (get_u16(expr->sasoc_number_peer_destinations, &sasoc_number_peer_destinations, error)) { + return STATUS_ERR; + } + if (sctp_assocparams->sasoc_number_peer_destinations != sasoc_number_peer_destinations) { + asprintf(error, "Bad getsockopt sctp_assocparams.sasoc_number_peer_destinations: expected: %hu actual: %hu", + sasoc_number_peer_destinations, sctp_assocparams->sasoc_number_peer_destinations); + return STATUS_ERR; + } + } + if (expr->sasoc_peer_rwnd->type != EXPR_ELLIPSIS) { + u32 sasoc_peer_rwnd; + + if (get_u32(expr->sasoc_peer_rwnd, &sasoc_peer_rwnd, error)) { + return STATUS_ERR; + } + if (sctp_assocparams->sasoc_peer_rwnd != sasoc_peer_rwnd) { + asprintf(error, "Bad getsockopt sctp_assocparams.sasoc_peer_rwnd: expected: %u actual: %u", + sasoc_peer_rwnd, sctp_assocparams->sasoc_peer_rwnd); + return STATUS_ERR; + } + } + if (expr->sasoc_local_rwnd->type != EXPR_ELLIPSIS) { + u32 sasoc_local_rwnd; + + if (get_u32(expr->sasoc_local_rwnd, &sasoc_local_rwnd, error)) { + return STATUS_ERR; + } + if (sctp_assocparams->sasoc_local_rwnd != sasoc_local_rwnd) { + asprintf(error, "Bad getsockopt sctp_assocparams.sasoc_local_rwnd: expected: %u actual: %u", + sasoc_local_rwnd, sctp_assocparams->sasoc_local_rwnd); + return STATUS_ERR; + } + } + if (expr->sasoc_cookie_life->type != EXPR_ELLIPSIS) { + u32 sasoc_cookie_life; + + if (get_u32(expr->sasoc_cookie_life, &sasoc_cookie_life, error)) { + return STATUS_ERR; + } + if (sctp_assocparams->sasoc_cookie_life != sasoc_cookie_life) { + asprintf(error, "Bad getsockopt sctp_assocparams.sasoc_cookie_life: expected: %u actual: %u", + sasoc_cookie_life, sctp_assocparams->sasoc_cookie_life); + return STATUS_ERR; + } + } + + return STATUS_OK; +} +#endif + static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, struct expression_list *args, char **error) { @@ -2156,6 +2226,12 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, live_optlen = (socklen_t)sizeof(struct sctp_rtoinfo); ((struct sctp_rtoinfo*)live_optval)->srto_assoc_id = 0; #endif +#ifdef SCTP_ASSOCINFO + } else if (val_expression->type == EXPR_SCTP_ASSOCPARAMS) { + live_optval = malloc(sizeof(struct sctp_assocparams)); + live_optlen = (socklen_t)sizeof(struct sctp_assocparams); + ((struct sctp_assocparams*) live_optval)->sasoc_assoc_id = 0; +#endif #ifdef SCTP_INITMSG } else if (val_expression->type == EXPR_SCTP_INITMSG) { live_optval = malloc(sizeof(struct sctp_initmsg)); @@ -2175,7 +2251,7 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, if (expr_params->spp_address->type == EXPR_ELLIPSIS) { socklen_t len_addr = sizeof(live_params->spp_address); if (getpeername(live_fd, (struct sockaddr*) &live_params->spp_address, &len_addr)) { - asprintf(error, "Bad setsockopt, bad get primary peer address"); + asprintf(error, "Bad getsockopt, bad get primary peer address"); free(live_params); return STATUS_ERR; } @@ -2184,7 +2260,7 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, } else if (expr_params->spp_address->type == EXPR_SOCKET_ADDRESS_IPV6) { memcpy(&live_params->spp_address, expr_params->spp_address->value.socket_address_ipv6, sizeof(struct sockaddr_in6)); } else { - asprintf(error, "Bad setsockopt, bad get input for spp_address"); + asprintf(error, "Bad getsockopt, bad get input for spp_address"); free(live_params); return STATUS_ERR; } @@ -2241,6 +2317,13 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, return STATUS_ERR; } #endif +#ifdef SCTP_ASSOCINFO + } else if (val_expression->type == EXPR_SCTP_ASSOCPARAMS) { + if (check_sctp_assocparams(val_expression->value.sctp_assocparams, live_optval, error)) { + free(live_optval); + return STATUS_ERR; + } +#endif #ifdef SCTP_INITMSG } else if (val_expression->type == EXPR_SCTP_INITMSG) { if (check_sctp_initmsg(val_expression->value.sctp_initmsg, live_optval, error)) { @@ -2298,6 +2381,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, #ifdef SCTP_RTOINFO struct sctp_rtoinfo rtoinfo; #endif +#ifdef SCTP_ASSOCINFO + struct sctp_assocparams assocparams; +#endif #ifdef SCTP_INITMSG struct sctp_initmsg initmsg; #endif @@ -2368,6 +2454,32 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, optval = &rtoinfo; break; #endif +#ifdef SCTP_ASSOCINFO + case EXPR_SCTP_ASSOCPARAMS: + assocparams.sasoc_assoc_id = 0; + if (get_u16(val_expression->value.sctp_assocparams->sasoc_asocmaxrxt, + &assocparams.sasoc_asocmaxrxt, error)) { + return STATUS_ERR; + } + if (get_u16(val_expression->value.sctp_assocparams->sasoc_number_peer_destinations, + &assocparams.sasoc_number_peer_destinations, error)) { + return STATUS_ERR; + } + if (get_u32(val_expression->value.sctp_assocparams->sasoc_peer_rwnd, + &assocparams.sasoc_peer_rwnd, error)) { + return STATUS_ERR; + } + if (get_u32(val_expression->value.sctp_assocparams->sasoc_local_rwnd, + &assocparams.sasoc_local_rwnd, error)) { + return STATUS_ERR; + } + if (get_u32(val_expression->value.sctp_assocparams->sasoc_cookie_life, + &assocparams.sasoc_cookie_life, error)) { + return STATUS_ERR; + } + optval = &assocparams; + break; +#endif #ifdef SCTP_INITMSG case EXPR_SCTP_INITMSG: if (get_u16(val_expression->value.sctp_initmsg->sinit_num_ostreams, diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c index 6088b01fc4ad757018e05891deff74d569044270..502038607e7f85078422e3ea37072f2fa5ee7f08 100644 --- a/gtests/net/packetdrill/script.c +++ b/gtests/net/packetdrill/script.c @@ -85,7 +85,10 @@ struct expression_type_entry expression_type_table[] = { { EXPR_SCTP_PEER_ADDR_PARAMS, "sctp_peer_addr_params"}, #endif #ifdef SCTP_SS_VALUE - { EXPR_SCTP_STREAM_VALUE, "sctp_stream_value"}, + { EXPR_SCTP_STREAM_VALUE, "sctp_stream_value"}, +#endif +#ifdef SCTP_ASSOCINFO + { EXPR_SCTP_ASSOCPARAMS, "sctp_assocparams"}, #endif { NUM_EXPR_TYPES, NULL} }; @@ -367,6 +370,15 @@ void free_expression(struct expression *expression) free_expression(expression->value.sctp_stream_value->stream_id); free_expression(expression->value.sctp_stream_value->stream_value); break; +#endif +#ifdef SCTP_ASSOCINFO + case EXPR_SCTP_ASSOCPARAMS: + free_expression(expression->value.sctp_assocparams->sasoc_asocmaxrxt); + free_expression(expression->value.sctp_assocparams->sasoc_number_peer_destinations); + free_expression(expression->value.sctp_assocparams->sasoc_peer_rwnd); + free_expression(expression->value.sctp_assocparams->sasoc_local_rwnd); + free_expression(expression->value.sctp_assocparams->sasoc_cookie_life); + break; #endif case EXPR_WORD: assert(expression->value.string); @@ -828,6 +840,48 @@ static int evaluate_sctp_stream_value_expression(struct expression *in, } #endif +#ifdef SCTP_ASSOCINFO +static int evaluate_sctp_accocparams_expression(struct expression *in, + struct expression *out, + char **error) +{ + struct sctp_assocparams_expr *in_params; + struct sctp_assocparams_expr *out_params; + + assert(in->type == EXPR_SCTP_ASSOCPARAMS); + assert(in->value.sctp_assocparams); + assert(out->type == EXPR_SCTP_ASSOCPARAMS); + + out->value.sctp_assocparams = calloc(1, sizeof(struct sctp_assocparams_expr)); + + in_params = in->value.sctp_assocparams; + out_params = out->value.sctp_assocparams; + + if (evaluate(in_params->sasoc_asocmaxrxt, + &out_params->sasoc_asocmaxrxt, + error)) + return STATUS_ERR; + if (evaluate(in_params->sasoc_number_peer_destinations, + &out_params->sasoc_number_peer_destinations, + error)) + return STATUS_ERR; + if (evaluate(in_params->sasoc_peer_rwnd, + &out_params->sasoc_peer_rwnd, + error)) + return STATUS_ERR; + if (evaluate(in_params->sasoc_local_rwnd, + &out_params->sasoc_local_rwnd, + error)) + return STATUS_ERR; + if (evaluate(in_params->sasoc_cookie_life, + &out_params->sasoc_cookie_life, + error)) + return STATUS_ERR; + + return STATUS_OK; +} +#endif + static int evaluate(struct expression *in, struct expression **out_ptr, char **error) { @@ -856,6 +910,11 @@ static int evaluate(struct expression *in, evaluate_sctp_rtoinfo_expression(in, out, error); break; #endif +#ifdef SCTP_ASSOCINFO + case EXPR_SCTP_ASSOCPARAMS: + evaluate_sctp_accocparams_expression(in, out, error); + break; +#endif #ifdef SCTP_INITMSG case EXPR_SCTP_INITMSG: evaluate_sctp_initmsg_expression(in, out, error); diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h index 1410b7dd89e75fa4dae7ab6573164fa89d713e61..5f8bb99b1c7598139dcaca5b0e587a9a95260dbe 100644 --- a/gtests/net/packetdrill/script.h +++ b/gtests/net/packetdrill/script.h @@ -67,6 +67,9 @@ enum expression_t { #endif #ifdef SCTP_PEER_ADDR_PARAMS EXPR_SCTP_PEER_ADDR_PARAMS, /* struct for sctp_paddrparams for SCTP_PEER_ADDR_PARAMS*/ +#endif +#ifdef SCTP_ASSOCINFO + EXPR_SCTP_ASSOCPARAMS, /* struct sctp_assocparams for SCTP_ASSOCINFO */ #endif NUM_EXPR_TYPES, }; @@ -108,6 +111,9 @@ struct expression { #endif #ifdef SCTP_SS_VALUE struct sctp_stream_value_expr *sctp_stream_value; +#endif +#ifdef SCTP_ASSOCINFO + struct sctp_assocparams_expr *sctp_assocparams; #endif } value; const char *format; /* the printf format for printing the value */ @@ -164,7 +170,6 @@ struct sctp_rtoinfo_expr { }; #endif - #ifdef SCTP_INITMSG /* Parse tree for a sctp_initmsg struct in a [gs]etsockopt syscall. */ struct sctp_initmsg_expr { @@ -224,6 +229,17 @@ struct sctp_paddrparams_expr { struct expression *spp_dscp; }; +#ifdef SCTP_ASSOCINFO +/* Parse tree for sctp_assocparams struct in [gs]etsockopt syscall. */ +struct sctp_assocparams_expr { + struct expression *sasoc_asocmaxrxt; + struct expression *sasoc_number_peer_destinations; + struct expression *sasoc_peer_rwnd; + struct expression *sasoc_local_rwnd; + struct expression *sasoc_cookie_life; +}; +#endif + /* 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 80811b847226e5249b6830d7fbd3c110800a9215..5932f39f591020104a01f0d6aec4e482797a34a8 100644 --- a/gtests/net/packetdrill/symbols_freebsd.c +++ b/gtests/net/packetdrill/symbols_freebsd.c @@ -80,6 +80,7 @@ struct int_symbol platform_symbols_table[] = { /* /usr/include/netinet/sctp.h and /usr/include/netinet/sctp_uio.h */ { SCTP_RTOINFO, "SCTP_RTOINFO" }, + { SCTP_ASSOCINFO, "SCTP_ASSOCINFO" }, { SCTP_INITMSG, "SCTP_INITMSG" }, { SCTP_NODELAY, "SCTP_NODELAY" }, { SCTP_MAXSEG, "SCTP_MAXSEG" }, diff --git a/gtests/net/packetdrill/symbols_linux.c b/gtests/net/packetdrill/symbols_linux.c index d175d6a8486561862e37cea376b73fda0e5a8c69..9116c17e9f15ff9fbb06b51c79e2c2dd95c3f1e3 100644 --- a/gtests/net/packetdrill/symbols_linux.c +++ b/gtests/net/packetdrill/symbols_linux.c @@ -101,6 +101,7 @@ struct int_symbol platform_symbols_table[] = { #endif { SCTP_RTOINFO, "SCTP_RTOINFO" }, + { SCTP_ASSOCINFO, "SCTP_ASSOCINFO" }, { SCTP_INITMSG, "SCTP_INITMSG" }, { SCTP_NODELAY, "SCTP_NODELAY" }, { SCTP_MAXSEG, "SCTP_MAXSEG" }, diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt index a2ec201acded1bd0da5a27c7f3419a827ed6b4d6..26ebc401be66fa3f8324d44a418e4e4320992f21 100644 --- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt +++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt @@ -78,4 +78,11 @@ spp_hbinterval=300, spp_pathmaxrxt=..., spp_pathmtu=1468, spp_flags=521, spp_ipv +0 getsockopt(3, IPPROTO_SCTP, SCTP_INITMSG, {sinit_num_ostreams=..., sinit_max_instreams=2, sinit_max_attempts=2, sinit_max_init_timeo=30}, [8]) = 0 +0 getsockopt(3, IPPROTO_SCTP, SCTP_INITMSG, {sinit_num_ostreams=2, sinit_max_instreams=..., sinit_max_attempts=2, sinit_max_init_timeo=30}, [8]) = 0 +0 getsockopt(3, IPPROTO_SCTP, SCTP_INITMSG, {sinit_num_ostreams=2, sinit_max_instreams=2, sinit_max_attempts=..., sinit_max_init_timeo=30}, [8]) = 0 + ++0 setsockopt(3, IPPROTO_SCTP, SCTP_ASSOCINFO, {sasoc_asocmaxrxt=5, sasoc_number_peer_destinations=3, sasoc_peer_rwnd=1800, sasoc_local_rwnd=2000, sasoc_cookie_life=40000}, 20) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_ASSOCINFO, {sasoc_asocmaxrxt=5, sasoc_number_peer_destinations=1, sasoc_peer_rwnd=1500, sasoc_local_rwnd=1864135, sasoc_cookie_life=40000}, [20]) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_ASSOCINFO, {sasoc_asocmaxrxt=..., sasoc_number_peer_destinations=..., sasoc_peer_rwnd=..., sasoc_local_rwnd=..., sasoc_cookie_life=40000}, [20]) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_ASSOCINFO, {sasoc_asocmaxrxt=5, sasoc_number_peer_destinations=..., sasoc_peer_rwnd=..., sasoc_local_rwnd=..., sasoc_cookie_life=40000}, [20]) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_ASSOCINFO, {sasoc_asocmaxrxt=5, sasoc_number_peer_destinations=..., sasoc_peer_rwnd=..., sasoc_local_rwnd=..., sasoc_cookie_life=...}, [20]) = 0 + +0 close(3) = 0