diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l index 0e4bb734030b51512df8d8d119ef1bcd9c2f2779..92a6d22940649be7a0d5ba870c63e2876fd54c77 100644 --- a/gtests/net/packetdrill/lexer.l +++ b/gtests/net/packetdrill/lexer.l @@ -240,6 +240,8 @@ spp_pathmtu return SPP_PATHMTU; spp_flags return SPP_FLAGS; spp_ipv6_flowlabel return SPP_IPV6_FLOWLABEL_; /* avoid name clash */ spp_dscp return SPP_DSCP_; /* avoid name clash */ +se_type return SE_TYPE; +se_on return SE_ON; CHUNK return CHUNK; DATA return DATA; INIT return INIT; diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index aff97c189b49cf1b02a773521c1ecbcc2f3846fd..151546a15dc31ab66f4fff5c7939310b89d94ad3 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -536,7 +536,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %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 <reserved> SASOC_LOCAL_RWND SASOC_COOKIE_LIFE SE_TYPE SE_ON %token <floating> FLOAT %token <integer> INTEGER HEX_INTEGER %token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR @@ -584,7 +584,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <expression> spp_flags spp_ipv6_flowlabel spp_dscp %type <expression> spinfo_address 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 <expression> sasoc_local_rwnd sasoc_cookie_life sctp_assocparams +%type <expression> sctp_event se_type se_on %type <errno_info> opt_errno %type <chunk_list> sctp_chunk_list_spec %type <chunk_list_item> sctp_chunk_spec @@ -2367,7 +2368,10 @@ expression | sctp_paddrparams { $$ = $1; } -| sctp_assocparams { +| sctp_assocparams { + $$ = $1; +} +| sctp_event { $$ = $1; } ; @@ -2965,6 +2969,42 @@ sctp_assocparams } ; +se_type +: SE_TYPE '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("se_type out of range"); + } + $$ = new_integer_expression($3, "%hu"); +} +| SE_TYPE '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +; + +se_on +: SE_ON '=' INTEGER { + if (!is_valid_u8($3)) { + semantic_error("se_on out of range"); + } + $$ = new_integer_expression($3, "%hhu"); +} +| SE_ON '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +sctp_event +: '{' se_type ',' se_on '}' { +#ifdef SCTP_EVENT + $$ = new_expression(EXPR_SCTP_EVENT); + $$->value.sctp_event = calloc(1, sizeof(struct sctp_event_expr)); + $$->value.sctp_event->se_type = $2; + $$->value.sctp_event->se_on = $4; +#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 15fe76adfc7a1e059f622b4610bcb011ceea27c1..c550a868867f3699b26365948dbc578b238e83fd 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -2224,6 +2224,39 @@ static int check_sctp_assocparams(struct sctp_assocparams_expr *expr, } #endif +#ifdef SCTP_EVENT +static int check_sctp_event(struct sctp_event_expr *expr, + struct sctp_event *sctp_event, + char **error) +{ + if (expr->se_type->type != EXPR_ELLIPSIS) { + u16 se_type; + + if (get_u16(expr->se_type, &se_type, error)) { + return STATUS_ERR; + } + if (sctp_event->se_type != se_type) { + asprintf(error, "Bad getsockopt sctp_event.se_type: expected: %hu actual: %hu", + se_type, sctp_event->se_type); + return STATUS_ERR; + } + } + if (expr->se_on->type != EXPR_ELLIPSIS) { + u8 se_on; + + if (get_u8(expr->se_on, &se_on, error)) { + return STATUS_ERR; + } + if (sctp_event->se_on != se_on) { + asprintf(error, "Bad getsockopt sctp_event.se_on: expected: %hhu actual: %hhu", + se_on, sctp_event->se_on); + return STATUS_ERR; + } + } + return STATUS_OK; +} +#endif + static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, struct expression_list *args, char **error) { @@ -2349,6 +2382,18 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, free(live_optval); return STATUS_ERR; } +#endif +#ifdef SCTP_EVENT + } else if (val_expression->type == EXPR_SCTP_EVENT) { + live_optval = malloc(sizeof(struct sctp_event)); + live_optlen = sizeof(struct sctp_event); + ((struct sctp_event *)live_optval)->se_assoc_id = 0; + if (get_u16(val_expression->value.sctp_event->se_type, + &((struct sctp_event *)live_optval)->se_type, + error)) { + free(live_optval); + return STATUS_ERR; + } #endif } else { s32_bracketed_arg(args, 3, &script_optval, error); @@ -2437,6 +2482,13 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, free(live_optval); return STATUS_ERR; } +#endif +#ifdef SCTP_EVENT + } else if (val_expression->type == EXPR_SCTP_EVENT) { + if (check_sctp_event(val_expression->value.sctp_event, live_optval, error)) { + free(live_optval); + return STATUS_ERR; + } #endif } else { if (*(int*)live_optval != script_optval) { @@ -2481,6 +2533,9 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, #if defined(SCTP_SS_VALUE) struct sctp_stream_value stream_value; #endif +#ifdef SCTP_EVENT + struct sctp_event event; +#endif #ifdef SCTP_PEER_ADDR_PARAMS struct sctp_paddrparams paddrparams; #ifdef linux @@ -2656,6 +2711,20 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, optval = &paddrinfo; break; #endif +#ifdef SCTP_EVENT + case EXPR_SCTP_EVENT: + event.se_assoc_id = 0; + if (get_u16(val_expression->value.sctp_event->se_type, + &event.se_type, error)) { + return STATUS_ERR; + } + if (get_u8(val_expression->value.sctp_event->se_on, + &event.se_on, error)) { + return STATUS_ERR; + } + optval = &event; + break; +#endif #ifdef SCTP_PEER_ADDR_PARAMS case EXPR_SCTP_PEER_ADDR_PARAMS: paddrparams.spp_assoc_id = 0; diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c index 3f2d056b2505a7c3e3745e5ce549db0a7e9aeee1..729475dbc498e2c35715bc25b304cccbe3ae39e0 100644 --- a/gtests/net/packetdrill/script.c +++ b/gtests/net/packetdrill/script.c @@ -89,6 +89,9 @@ struct expression_type_entry expression_type_table[] = { #endif #ifdef SCTP_ASSOCINFO { EXPR_SCTP_ASSOCPARAMS, "sctp_assocparams"}, +#endif +#ifdef SCTP_EVENT + { EXPR_SCTP_EVENT, "sctp_event" }, #endif { NUM_EXPR_TYPES, NULL} }; @@ -380,6 +383,12 @@ void free_expression(struct expression *expression) free_expression(expression->value.sctp_assocparams->sasoc_local_rwnd); free_expression(expression->value.sctp_assocparams->sasoc_cookie_life); break; +#endif +#ifdef SCTP_EVENT + case EXPR_SCTP_EVENT: + free_expression(expression->value.sctp_event->se_type); + free_expression(expression->value.sctp_event->se_on); + break; #endif case EXPR_WORD: assert(expression->value.string); @@ -869,6 +878,36 @@ static int evaluate_sctp_stream_value_expression(struct expression *in, } #endif +#ifdef SCTP_EVENT +static int evaluate_sctp_event_expression(struct expression *in, + struct expression *out, + char **error) +{ + struct sctp_event_expr *in_event; + struct sctp_event_expr *out_event; + + assert(in->type == EXPR_SCTP_EVENT); + assert(in->value.sctp_event); + assert(out->type == EXPR_SCTP_EVENT); + + out->value.sctp_event = calloc(1, sizeof(struct sctp_event_expr)); + + in_event = in->value.sctp_event; + out_event = out->value.sctp_event; + + if (evaluate(in_event->se_type, + &out_event->se_type, + error)) + return STATUS_ERR; + if (evaluate(in_event->se_on, + &out_event->se_on, + error)) + return STATUS_ERR; + + return STATUS_OK; +} +#endif + #ifdef SCTP_ASSOCINFO static int evaluate_sctp_accocparams_expression(struct expression *in, struct expression *out, @@ -976,6 +1015,11 @@ static int evaluate(struct expression *in, case EXPR_SCTP_STREAM_VALUE: evaluate_sctp_stream_value_expression(in, out, error); break; +#endif +#ifdef SCTP_EVENT + case EXPR_SCTP_EVENT: + result = evaluate_sctp_event_expression(in, out, error); + break; #endif case EXPR_WORD: out->type = EXPR_INTEGER; diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h index 037a3720cc0b2262614b8ce56da041b880ca2b6f..647155410aa1546803a380771d95800603369f59 100644 --- a/gtests/net/packetdrill/script.h +++ b/gtests/net/packetdrill/script.h @@ -66,10 +66,13 @@ enum expression_t { EXPR_SCTP_STREAM_VALUE, /* struct sctp_stream_value for SCTP_SS_VALUE */ #endif #ifdef SCTP_PEER_ADDR_PARAMS - EXPR_SCTP_PEER_ADDR_PARAMS, /* struct for sctp_paddrparams for 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 +#ifdef SCTP_EVENT + EXPR_SCTP_EVENT, /* struct sctp_event to for SCTP_EVENT */ #endif NUM_EXPR_TYPES, }; @@ -114,6 +117,9 @@ struct expression { #endif #ifdef SCTP_ASSOCINFO struct sctp_assocparams_expr *sctp_assocparams; +#endif +#ifdef SCTP_EVENT + struct sctp_event_expr *sctp_event; #endif } value; const char *format; /* the printf format for printing the value */ @@ -248,6 +254,14 @@ struct sctp_assocparams_expr { }; #endif +#ifdef SCTP_EVENT +/* Parse tree for sctp_enevt struct in [gs]etsockopt syscall. */ +struct sctp_event_expr { + struct expression *se_type; + struct expression *se_on; +}; +#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 79511960ade2bd1ba7bb9a87a0a67b54c3664e76..6576badbd3944cb5f44a30a2ac65e3d51ac8b7d1 100644 --- a/gtests/net/packetdrill/symbols_freebsd.c +++ b/gtests/net/packetdrill/symbols_freebsd.c @@ -87,6 +87,7 @@ struct int_symbol platform_symbols_table[] = { { SCTP_DELAYED_SACK, "SCTP_DELAYED_SACK" }, { SCTP_MAX_BURST, "SCTP_MAX_BURST" }, { SCTP_PEER_ADDR_PARAMS, "SCTP_PEER_ADDR_PARAMS" }, + { SCTP_EVENT, "SCTP_EVENT" }, { SCTP_STATUS, "SCTP_STATUS" }, { SCTP_GET_PEER_ADDR_INFO, "SCTP_GET_PEER_ADDR_INFO" }, { SCTP_FRAGMENT_INTERLEAVE, "SCTP_FRAGMENT_INTERLEAVE" }, @@ -160,7 +161,21 @@ struct int_symbol platform_symbols_table[] = { { SPP_PMTUD_DISABLE, "SPP_PMTUD_DISABLE" }, { SPP_IPV6_FLOWLABEL, "SPP_IPV6_FLOWLABEL" }, { SPP_DSCP, "SPP_DSCP" }, - + { SCTP_ASSOC_CHANGE, "SCTP_ASSOC_CHANGE" }, + { SCTP_PEER_ADDR_CHANGE, "SCTP_PEER_ADDR_CHANGE" }, + { SCTP_REMOTE_ERROR, "SCTP_REMOTE_ERROR" }, + { SCTP_SEND_FAILED, "SCTP_SEND_FAILED" }, + { SCTP_SHUTDOWN_EVENT, "SCTP_SHUTDOWN_EVENT" }, + { SCTP_ADAPTATION_INDICATION, "SCTP_ADAPTATION_INDICATION" }, + { SCTP_ADAPTION_INDICATION, "SCTP_ADAPTION_INDICATION" }, + { SCTP_PARTIAL_DELIVERY_EVENT, "SCTP_PARTIAL_DELIVERY_EVENT" }, + { SCTP_AUTHENTICATION_EVENT, "SCTP_AUTHENTICATION_EVENT" }, + { SCTP_STREAM_RESET_EVENT, "SCTP_STREAM_RESET_EVENT" }, + { SCTP_SENDER_DRY_EVENT, "SCTP_SENDER_DRY_EVENT" }, + { SCTP_NOTIFICATIONS_STOPPED_EVENT, "SCTP_NOTIFICATIONS_STOPPED_EVENT"}, + { SCTP_ASSOC_RESET_EVENT, "SCTP_ASSOC_RESET_EVENT" }, + { SCTP_STREAM_CHANGE_EVENT, "SCTP_STREAM_CHANGE_EVENT" }, + { SCTP_SEND_FAILED_EVENT, "SCTP_SEND_FAILED_EVENT" }, /* /usr/include/netinet/tcp.h */ { TCP_NODELAY, "TCP_NODELAY" }, { TCP_MAXSEG, "TCP_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 382334acdf79156a54437136cefce6dd77732e38..cf8dda781a11e14006c2d17d1802f7644ccd239f 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 @@ -107,4 +107,7 @@ spp_hbinterval=300, spp_pathmaxrxt=..., spp_pathmtu=1468, spp_flags=521, spp_ipv +0 getsockopt(3, IPPROTO_SCTP, SCTP_DELAYED_SACK, {sack_delay=..., sack_freq=1}, [12]) = 0 +0 getsockopt(3, IPPROTO_SCTP, SCTP_DELAYED_SACK, {sack_delay=250, sack_freq=...}, [12]) = 0 ++0 setsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_SHUTDOWN_EVENT, se_on=1}, 8) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_SHUTDOWN_EVENT, se_on=1}, [8]) = 0 + +0 close(3) = 0