From fcd4baf13a35ef95992d5a915d8df4f4749ecc77 Mon Sep 17 00:00:00 2001 From: hoelscher <jens.hoelscher@fh-muenster.de> Date: Tue, 27 Oct 2015 15:10:23 +0100 Subject: [PATCH] add support for sctp_send_failed event --- gtests/net/packetdrill/lexer.l | 7 ++ gtests/net/packetdrill/parser.y | 88 +++++++++++++++++++ gtests/net/packetdrill/run_system_call.c | 38 ++++++++ gtests/net/packetdrill/script.c | 61 +++++++++++++ gtests/net/packetdrill/script.h | 14 +++ .../sctp/notifications/sctp_send_failed.pkt | 30 +++++++ 6 files changed, 238 insertions(+) create mode 100644 gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_send_failed.pkt diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l index 8f9aaa8c..53effec3 100644 --- a/gtests/net/packetdrill/lexer.l +++ b/gtests/net/packetdrill/lexer.l @@ -336,6 +336,13 @@ spc_aaddr return SPC_AADDR; spc_state return SPC_STATE; spc_error return SPC_ERROR; spc_assoc_id return SPC_ASSOC_ID; +ssf_type return SSF_TYPE; +ssf_length return SSF_LENGTH; +ssf_flags return SSF_FLAGS; +ssf_error return SSF_ERROR; +ssf_info return SSF_INFO; +ssf_assoc_id return SSF_ASSOC_ID; +ssf_data return SSF_DATA; CHUNK return CHUNK; DATA return DATA; INIT return INIT; diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index e3cb12a1..320d694c 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -560,6 +560,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %token <reserved> SRE_TYPE SRE_FLAGS SRE_LENGTH SRE_ERROR SRE_ASSOC_ID SRE_DATA PDAPI_ASSOC_ID %token <reserved> PDAPI_TYPE PDAPI_FLAGS PDAPI_LENGTH PDAPI_INDICATION PDAPI_STREAM PDAPI_SEQ %token <reserved> SPC_TYPE SPC_FLAGS SPC_LENGTH SPC_AADDR SPC_STATE SPC_ERROR SPC_ASSOC_ID +%token <reserved> SSF_TYPE SSF_LENGTH SSF_FLAGS SSF_ERROR SSF_INFO SSF_ASSOC_ID SSF_DATA %token <floating> FLOAT %token <integer> INTEGER HEX_INTEGER %token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR @@ -625,6 +626,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <expression> sctp_remote_error sre_type sre_flags sre_length sre_error sre_assoc_id sre_data %type <expression> sctp_pdapi_event pdapi_type pdapi_flags pdapi_length pdapi_indication pdapi_stream pdapi_seq pdapi_assoc_id %type <expression> sctp_paddr_change spc_type spc_flags spc_length spc_aaddr spc_error spc_state spc_assoc_id +%type <expression> sctp_send_failed ssf_type ssf_length ssf_flags ssf_error ssf_info ssf_assoc_id ssf_data %type <errno_info> opt_errno %type <chunk_list> sctp_chunk_list_spec %type <chunk_list_item> sctp_chunk_spec @@ -2602,6 +2604,7 @@ data | sctp_assoc_change { $$ = $1; } | sctp_paddr_change { $$ = $1; } | sctp_remote_error { $$ = $1; } +| sctp_send_failed { $$ = $1; } | sctp_shutdown_event { $$ = $1; } | sctp_pdapi_event { $$ = $1; } | sctp_sender_dry_event { $$ = $1; } @@ -4166,6 +4169,91 @@ sctp_paddr_change $$->value.sctp_paddr_change->spc_assoc_id = $14; } ; +ssf_type +: SSF_TYPE '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("ssf_type out of range"); + } + $$ = new_integer_expression($3, "%hu"); +} +| SSF_TYPE '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +| SSF_TYPE '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +ssf_length +: SSF_LENGTH '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("ssf_length out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| SSF_LENGTH '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +ssf_flags +: SSF_FLAGS '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("ssf_flags out of range"); + } + $$ = new_integer_expression($3, "%hu"); +} +| SSF_FLAGS '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +| SSF_FLAGS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +ssf_error +: SSF_ERROR '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("ssf_error out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| SSF_ERROR '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +| SSF_ERROR '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +ssf_info +: SSF_INFO '=' sctp_sndrcvinfo { $$ = $3; } +| SSF_INFO '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +ssf_assoc_id +: SSF_ASSOC_ID '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("ssf_assoc_id out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| SSF_ASSOC_ID '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +ssf_data +: SSF_DATA '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +| SSF_DATA '=' array { $$ = $3; } +; + +sctp_send_failed +: '{' ssf_type ',' ssf_flags ',' ssf_length ',' ssf_error ',' ssf_info ',' ssf_assoc_id ',' ssf_data '}' { + $$ = new_expression(EXPR_SCTP_SEND_FAILED); + $$->value.sctp_send_failed = calloc(1, sizeof(struct sctp_send_failed_expr)); + $$->value.sctp_send_failed->ssf_type = $2; + $$->value.sctp_send_failed->ssf_flags = $4; + $$->value.sctp_send_failed->ssf_length = $6; + $$->value.sctp_send_failed->ssf_error = $8; + $$->value.sctp_send_failed->ssf_info = $10; + $$->value.sctp_send_failed->ssf_assoc_id = $12; + $$->value.sctp_send_failed->ssf_data = $14; +} +; opt_errno : { $$ = NULL; } diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c index 7a0a6613..57013b82 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -571,6 +571,7 @@ static int iovec_new(struct expression *expression, iov_expr->iov_base->type == EXPR_SCTP_ASSOC_CHANGE || iov_expr->iov_base->type == EXPR_SCTP_PADDR_CHANGE || iov_expr->iov_base->type == EXPR_SCTP_REMOTE_ERROR || + iov_expr->iov_base->type == EXPR_SCTP_SEND_FAILED || iov_expr->iov_base->type == EXPR_SCTP_SHUTDOWN_EVENT || iov_expr->iov_base->type == EXPR_SCTP_PDAPI_EVENT || iov_expr->iov_base->type == EXPR_SCTP_AUTHKEY_EVENT || @@ -3477,6 +3478,37 @@ static int check_sctp_remote_error(struct sctp_remote_error_expr *expr, } #endif +#if defined(__FreeBSD__) || defined(linux) +static int check_sctp_send_failed(struct sctp_send_failed_expr *expr, + struct sctp_send_failed *sctp_event, + char **error) { + + if (check_u16_expr(expr->ssf_type, sctp_event->ssf_type, + "sctp_send_failed.ssf_type", error)) + return STATUS_ERR; + if (check_u16_expr(expr->ssf_flags, sctp_event->ssf_flags, + "sctp_send_failed.ssf_flags", error)) + return STATUS_ERR; + if (check_u32_expr(expr->ssf_length, sctp_event->ssf_length, + "sctp_send_failed.ssf_length", error)) + return STATUS_ERR; + if (check_u32_expr(expr->ssf_error, sctp_event->ssf_error, + "sctp_send_failed.ssf_error", error)) + return STATUS_ERR; + if (check_sctp_sndrcvinfo(expr->ssf_info->value.sctp_sndrcvinfo, + &sctp_event->ssf_info, error)) + return STATUS_ERR; + if (check_u32_expr(expr->ssf_assoc_id, sctp_event->ssf_assoc_id, + "sctp_send_failed.ssf_assoc_id", error)) + return STATUS_ERR; + if (check_u8array_expr(expr->ssf_data, sctp_event->ssf_data, sctp_event->ssf_length - sizeof(struct sctp_send_failed), + "sctp_send_failed.ssf_data", error)) + return STATUS_ERR; + + return STATUS_OK; +} +#endif + #if defined(__FreeBSD__) || defined(linux) static int check_sctp_shutdown_event(struct sctp_shutdown_event_expr *expr, struct sctp_shutdown_event *sctp_event, @@ -3645,6 +3677,12 @@ static int check_sctp_notification(struct iovec *iov, error)) return STATUS_ERR; break; + case EXPR_SCTP_SEND_FAILED: + if (check_sctp_send_failed(script_iov_base->value.sctp_send_failed, + (struct sctp_send_failed *) iov[i].iov_base, + error)) + return STATUS_ERR; + break; case EXPR_SCTP_SHUTDOWN_EVENT: if (check_sctp_shutdown_event(script_iov_base->value.sctp_shutdown_event, (struct sctp_shutdown_event *) iov[i].iov_base, diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c index 35979f33..53b30e85 100644 --- a/gtests/net/packetdrill/script.c +++ b/gtests/net/packetdrill/script.c @@ -89,6 +89,7 @@ struct expression_type_entry expression_type_table[] = { { EXPR_SCTP_ASSOC_CHANGE, "sctp_assoc_change"}, { EXPR_SCTP_PADDR_CHANGE, "sctp_paddr_change"}, { EXPR_SCTP_REMOTE_ERROR, "sctp_remote_error"}, + { EXPR_SCTP_SEND_FAILED, "sctp_send_failed"}, { EXPR_SCTP_SHUTDOWN_EVENT, "sctp_shutdown_event"}, { EXPR_SCTP_PDAPI_EVENT, "sctp_pdapi_event"}, { EXPR_SCTP_AUTHKEY_EVENT, "sctp_authkey_event"}, @@ -465,6 +466,15 @@ void free_expression(struct expression *expression) free_expression(expression->value.sctp_remote_error->sre_assoc_id); free_expression(expression->value.sctp_remote_error->sre_data); break; + case EXPR_SCTP_SEND_FAILED: + free_expression(expression->value.sctp_send_failed->ssf_type); + free_expression(expression->value.sctp_send_failed->ssf_flags); + free_expression(expression->value.sctp_send_failed->ssf_length); + free_expression(expression->value.sctp_send_failed->ssf_error); + free_expression(expression->value.sctp_send_failed->ssf_info); + free_expression(expression->value.sctp_send_failed->ssf_assoc_id); + free_expression(expression->value.sctp_send_failed->ssf_data); + break; case EXPR_SCTP_SHUTDOWN_EVENT: free_expression(expression->value.sctp_shutdown_event->sse_type); free_expression(expression->value.sctp_shutdown_event->sse_flags); @@ -1560,6 +1570,54 @@ static int evaluate_sctp_remote_error_expression(struct expression *in, return STATUS_OK; } +static int evaluate_sctp_send_failed_expression(struct expression *in, + struct expression *out, + char **error) +{ + struct sctp_send_failed_expr *in_event; + struct sctp_send_failed_expr *out_event; + + assert(in->type == EXPR_SCTP_SEND_FAILED); + assert(in->value.sctp_send_failed); + assert(out->type == EXPR_SCTP_SEND_FAILED); + + out->value.sctp_send_failed = calloc(1, sizeof(struct sctp_send_failed_expr)); + + in_event = in->value.sctp_send_failed; + out_event = out->value.sctp_send_failed; + + if (evaluate(in_event->ssf_type, + &out_event->ssf_type, + error)) + return STATUS_ERR; + if (evaluate(in_event->ssf_flags, + &out_event->ssf_flags, + error)) + return STATUS_ERR; + if (evaluate(in_event->ssf_length, + &out_event->ssf_length, + error)) + return STATUS_ERR; + if (evaluate(in_event->ssf_error, + &out_event->ssf_error, + error)) + return STATUS_ERR; + if (evaluate(in_event->ssf_info, + &out_event->ssf_info, + error)) + return STATUS_ERR; + if (evaluate(in_event->ssf_assoc_id, + &out_event->ssf_assoc_id, + error)) + return STATUS_ERR; + if (evaluate(in_event->ssf_data, + &out_event->ssf_data, + error)) + return STATUS_ERR; + + return STATUS_OK; +} + static int evaluate_sctp_shutdown_event_expression(struct expression *in, struct expression *out, char **error) @@ -1862,6 +1920,9 @@ static int evaluate(struct expression *in, case EXPR_SCTP_REMOTE_ERROR: result = evaluate_sctp_remote_error_expression(in, out, error); break; + case EXPR_SCTP_SEND_FAILED: + result = evaluate_sctp_send_failed_expression(in, out, error); + break; case EXPR_SCTP_SHUTDOWN_EVENT: result = evaluate_sctp_shutdown_event_expression(in, out, error); break; diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h index f6f444df..dc755dbb 100644 --- a/gtests/net/packetdrill/script.h +++ b/gtests/net/packetdrill/script.h @@ -69,6 +69,7 @@ enum expression_t { EXPR_SCTP_ASSOC_CHANGE, /* expression tree for sctp_assoc_change_event */ EXPR_SCTP_PADDR_CHANGE, /* expression tree for sctp_peer_addr_change */ EXPR_SCTP_REMOTE_ERROR, /* expression tree for sctp_remote_error_event */ + EXPR_SCTP_SEND_FAILED, /* expression tree for sctp_send_failed event (DEPRICATED) */ EXPR_SCTP_SHUTDOWN_EVENT, /* expression tree for sctp_shutdown_event */ EXPR_SCTP_PDAPI_EVENT, /* expression tree for sctp_partial_delivery_event */ EXPR_SCTP_AUTHKEY_EVENT, /* expression tree for sctp_authentication_event */ @@ -116,6 +117,7 @@ struct expression { struct sctp_assoc_change_expr *sctp_assoc_change; struct sctp_paddr_change_expr *sctp_paddr_change; struct sctp_remote_error_expr *sctp_remote_error; + struct sctp_send_failed_expr *sctp_send_failed; struct sctp_shutdown_event_expr *sctp_shutdown_event; struct sctp_pdapi_event_expr *sctp_pdapi_event; struct sctp_authkey_event_expr *sctp_authkey_event; @@ -364,6 +366,18 @@ struct sctp_remote_error_expr { struct expression *sre_assoc_id; struct expression *sre_data; }; + +/* Parse tree for sctp_shutdown_event for notifications. */ +struct sctp_send_failed_expr { + struct expression *ssf_type; + struct expression *ssf_flags; + struct expression *ssf_length; + struct expression *ssf_error; + struct expression *ssf_info; + struct expression *ssf_assoc_id; + struct expression *ssf_data; +}; + /* Parse tree for sctp_shutdown_event for notifications. */ struct sctp_shutdown_event_expr { struct expression *sse_type; diff --git a/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_send_failed.pkt b/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_send_failed.pkt new file mode 100644 index 00000000..6a55b3dc --- /dev/null +++ b/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_send_failed.pkt @@ -0,0 +1,30 @@ ++0.0 socket(..., SOCK_STREAM, IPPROTO_SCTP) = 3 ++0.0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR) ++0.0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 +// Check the handshake with an empty(!) cookie ++0.1 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress) ++0.0 > sctp: INIT[flgs=0, tag=1, a_rwnd=..., os=..., is=..., tsn=1, ...] ++0.1 < sctp: INIT_ACK[flgs=0, tag=2, a_rwnd=1500, os=1, is=1, tsn=1, STATE_COOKIE[len=4, val=...]] ++0.0 > sctp: COOKIE_ECHO[flgs=0, len=4, val=...] ++0.1 < sctp: COOKIE_ACK[flgs=0] ++0.0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0 + ++0.0 setsockopt(3, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, {spp_address=..., spp_hbinterval=0, spp_pathmaxrxt=100, spp_pathmtu=1468, spp_flags=SPP_HB_DISABLE, +spp_ipv6_flowlabel=0, spp_dscp=0}, 152) = 0 + +//test for SEND_FAILED_EVENT ++0.0 setsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_SEND_FAILED, se_on=1}, 8) = 0 ++0.0 setsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=100, srto_max=150, srto_min=50}, 16) = 0 ++0.0 write(3, ..., 1000) = 1000 ++0.0 > sctp: DATA[flgs=BE, len=1016, tsn=1, sid=0, ssn=0, ppid=0] +* > sctp: DATA[flgs=BE, len=1016, tsn=1, sid=0, ssn=0, ppid=0] +* > sctp: DATA[flgs=BE, len=1016, tsn=1, sid=0, ssn=0, ppid=0] +* > sctp: DATA[flgs=BE, len=1016, tsn=1, sid=0, ssn=0, ppid=0] +* > sctp: DATA[flgs=BE, len=1016, tsn=1, sid=0, ssn=0, ppid=0] +* > sctp: DATA[flgs=BE, len=1016, tsn=1, sid=0, ssn=0, ppid=0] +* > sctp: DATA[flgs=BE, len=1016, tsn=1, sid=0, ssn=0, ppid=0] +* > sctp: DATA[flgs=BE, len=1016, tsn=1, sid=0, ssn=0, ppid=0] ++1.0 sctp_recvv(3, [{iov_base={ssf_type=SCTP_SEND_FAILED, ssf_flags=SCTP_DATA_SENT, ssf_length=1144, ssf_error=0, +ssf_info={sinfo_stream=0, sinfo_ssn=0, sinfo_flags=3, sinfo_ppid=htonl(0), sinfo_context=0, sinfo_timetolive=0, sinfo_tsn=0, sinfo_cumtsn=0}, +ssf_assoc_id=3, ssf_data=...}, iov_len=1000}], +1, ..., 20, NULL, [0], [SCTP_RECVV_NOINFO], [MSG_NOTIFICATION]) = 1000 -- GitLab