From 45a9a85ad4a8297f633a6ef4199a1a5cbd16788e Mon Sep 17 00:00:00 2001 From: hoelscher <jens.hoelscher@fh-muenster.de> Date: Tue, 27 Oct 2015 18:28:44 +0100 Subject: [PATCH] add support for sctp_notifications_stopped_event --- gtests/net/packetdrill/lexer.l | 3 ++ gtests/net/packetdrill/parser.y | 47 +++++++++++++++++++ gtests/net/packetdrill/run_system_call.c | 24 +++++++++- gtests/net/packetdrill/script.c | 40 ++++++++++++++++ gtests/net/packetdrill/script.h | 9 ++++ .../sctp_notifications_stopped_event.pkt | 17 +++++++ 6 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_notifications_stopped_event.pkt diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l index 4d92cdb9..4cadbae7 100644 --- a/gtests/net/packetdrill/lexer.l +++ b/gtests/net/packetdrill/lexer.l @@ -348,6 +348,9 @@ sai_length return SAI_LENGTH; sai_flags return SAI_FLAGS; sai_adaptation_ind return SAI_ADAPTATION_IND; sai_assoc_id return SAI_ASSOC_ID; +sn_type return SN_TYPE; +sn_length return SN_LENGTH; +sn_flags return SN_FLAGS; CHUNK return CHUNK; DATA return DATA; INIT return INIT; diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index 7771e687..f2d3fc5d 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -562,6 +562,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %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 <reserved> SAI_TYPE SAI_FLAGS SAI_LENGTH SAI_ADAPTATION_IND SAI_ASSOC_ID +%token <reserved> SN_TYPE SN_FLAGS SN_LENGTH %token <floating> FLOAT %token <integer> INTEGER HEX_INTEGER %token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR @@ -629,6 +630,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %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 <expression> sctp_adaptation_event sai_type sai_flags sai_length sai_adaptation_ind sai_assoc_id +%type <expression> sctp_tlv sn_type sn_flags sn_length %type <errno_info> opt_errno %type <chunk_list> sctp_chunk_list_spec %type <chunk_list_item> sctp_chunk_spec @@ -2613,6 +2615,7 @@ data | sctp_sender_dry_event { $$ = $1; } | sctp_send_failed_event { $$ = $1; } | sctp_authkey_event { $$ = $1; } +| sctp_tlv { $$ = $1; } ; msghdr @@ -4324,6 +4327,50 @@ sctp_adaptation_event } ; +sn_type +: SN_TYPE '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("sn_type out of range"); + } + $$ = new_integer_expression($3, "%hu"); +} +| SN_TYPE '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +| SN_TYPE '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +sn_flags +: SN_FLAGS '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("sn_flags out of range"); + } + $$ = new_integer_expression($3, "%hu"); +} +| SN_FLAGS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +sn_length +: SN_LENGTH '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("sn_length out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| SN_LENGTH '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +sctp_tlv +: '{' sn_type ',' sn_flags ',' sn_length '}' { + $$ = new_expression(EXPR_SCTP_TLV); + $$->value.sctp_tlv = calloc(1, sizeof(struct sctp_tlv_expr)); + $$->value.sctp_tlv->sn_type = $2; + $$->value.sctp_tlv->sn_flags = $4; + $$->value.sctp_tlv->sn_length = $6; +} +; + opt_errno : { $$ = NULL; } | WORD note { diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c index 4ede3caf..c54a41b5 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -576,7 +576,8 @@ static int iovec_new(struct expression *expression, iov_expr->iov_base->type == EXPR_SCTP_PDAPI_EVENT || iov_expr->iov_base->type == EXPR_SCTP_AUTHKEY_EVENT || iov_expr->iov_base->type == EXPR_SCTP_SENDER_DRY_EVENT || - iov_expr->iov_base->type == EXPR_SCTP_SEND_FAILED_EVENT); + iov_expr->iov_base->type == EXPR_SCTP_SEND_FAILED_EVENT || + iov_expr->iov_base->type == EXPR_SCTP_TLV); assert(iov_expr->iov_len->type == EXPR_INTEGER); len = iov_expr->iov_len->value.num; @@ -3682,6 +3683,21 @@ static int check_sctp_send_failed_event(struct sctp_send_failed_event_expr *expr } #endif +#if defined(__FreeBSD__) || defined(linux) +static int check_sctp_tlv(struct sctp_tlv_expr *expr, struct sctp_tlv *sctp_tlv, char **error) { + if (check_u16_expr(expr->sn_type, sctp_tlv->sn_type, + "sctp_tlv.sn_type", error)) + return STATUS_ERR; + if (check_u16_expr(expr->sn_flags, sctp_tlv->sn_flags, + "sctp_tlv.sn_flags", error)) + return STATUS_ERR; + if (check_u32_expr(expr->sn_length, sctp_tlv->sn_length, + "sctp_tlv.sn_length", error)) + return STATUS_ERR; + return STATUS_OK; +} +#endif + #if defined(__FreeBSD__) || defined(linux) static int check_sctp_notification(struct iovec *iov, struct expression *iovec_expr, @@ -3762,6 +3778,12 @@ static int check_sctp_notification(struct iovec *iov, return STATUS_ERR; break; #endif + case EXPR_SCTP_TLV: + if (check_sctp_tlv(script_iov_base->value.sctp_tlv, + (struct sctp_tlv *) iov[i].iov_base, + error)) + return STATUS_ERR; + break; case EXPR_ELLIPSIS: printf("check Ellipsis\n"); break; diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c index f119c512..33637435 100644 --- a/gtests/net/packetdrill/script.c +++ b/gtests/net/packetdrill/script.c @@ -96,6 +96,7 @@ struct expression_type_entry expression_type_table[] = { { EXPR_SCTP_AUTHKEY_EVENT, "sctp_authkey_event"}, { EXPR_SCTP_SENDER_DRY_EVENT,"sctp_sender_dry_event"}, { EXPR_SCTP_SEND_FAILED_EVENT,"sctp_send_failed_event"}, + { EXPR_SCTP_TLV, "sctp_tlv" }, { NUM_EXPR_TYPES, NULL} }; @@ -520,6 +521,11 @@ void free_expression(struct expression *expression) free_expression(expression->value.sctp_send_failed_event->ssfe_assoc_id); free_expression(expression->value.sctp_send_failed_event->ssfe_data); break; + case EXPR_SCTP_TLV: + free_expression(expression->value.sctp_tlv->sn_type); + free_expression(expression->value.sctp_tlv->sn_flags); + free_expression(expression->value.sctp_tlv->sn_length); + break; case EXPR_WORD: assert(expression->value.string); free(expression->value.string); @@ -1874,6 +1880,37 @@ static int evaluate_sctp_send_failed_event_expression(struct expression *in, return STATUS_OK; } +static int evaluate_sctp_tlv_expression(struct expression *in, + struct expression *out, + char **error) +{ + struct sctp_tlv_expr *in_tlv; + struct sctp_tlv_expr *out_tlv; + + assert(in->type == EXPR_SCTP_TLV); + assert(in->value.sctp_tlv); + assert(out->type == EXPR_SCTP_TLV); + + out->value.sctp_tlv = calloc(1, sizeof(struct sctp_tlv_expr)); + + in_tlv = in->value.sctp_tlv; + out_tlv = out->value.sctp_tlv; + + if (evaluate(in_tlv->sn_type, + &out_tlv->sn_type, + error)) + return STATUS_ERR; + if (evaluate(in_tlv->sn_flags, + &out_tlv->sn_flags, + error)) + return STATUS_ERR; + if (evaluate(in_tlv->sn_length, + &out_tlv->sn_length, + error)) + return STATUS_ERR; + return STATUS_OK; +} + static int evaluate(struct expression *in, struct expression **out_ptr, char **error) { @@ -1989,6 +2026,9 @@ static int evaluate(struct expression *in, case EXPR_SCTP_SEND_FAILED_EVENT: result = evaluate_sctp_send_failed_event_expression(in, out, error); break; + case EXPR_SCTP_TLV: + result = evaluate_sctp_tlv_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 26264d74..bb60524f 100644 --- a/gtests/net/packetdrill/script.h +++ b/gtests/net/packetdrill/script.h @@ -76,6 +76,7 @@ enum expression_t { EXPR_SCTP_AUTHKEY_EVENT, /* expression tree for sctp_authentication_event */ EXPR_SCTP_SENDER_DRY_EVENT, /* expression tree for sctp_sender_dry_event */ EXPR_SCTP_SEND_FAILED_EVENT, /* expression tree for sctp_send_failed_event */ + EXPR_SCTP_TLV, /* expression tree for sctp_notifications_stopped_event */ NUM_EXPR_TYPES, }; /* Convert an expression type to a human-readable string */ @@ -125,6 +126,7 @@ struct expression { struct sctp_authkey_event_expr *sctp_authkey_event; struct sctp_sender_dry_event_expr *sctp_sender_dry_event; struct sctp_send_failed_event_expr *sctp_send_failed_event; + struct sctp_tlv_expr *sctp_tlv; } value; const char *format; /* the printf format for printing the value */ }; @@ -436,6 +438,13 @@ struct sctp_send_failed_event_expr { struct expression *ssfe_data; }; +/* Parse tree for sctp_tlv for notifications. */ +struct sctp_tlv_expr { + struct expression *sn_type; + struct expression *sn_flags; + struct expression *sn_length; +}; + /* 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/tests/bsd/sctp/notifications/sctp_notifications_stopped_event.pkt b/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_notifications_stopped_event.pkt new file mode 100644 index 00000000..6adecb8f --- /dev/null +++ b/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_notifications_stopped_event.pkt @@ -0,0 +1,17 @@ ++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 setsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_ADAPTATION_INDICATION, se_on=1}, 8) = 0 ++0.0 getsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_ADAPTATION_INDICATION, se_on=1}, [8]) = 0 ++0.0 setsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_NOTIFICATIONS_STOPPED_EVENT, se_on=1}, 8) = 0 + ++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] +// No implementation provides this messages, so it can't be tested +// as discribed in rfc, create an notification storm so that the implementation disable notifications ++0.0 sctp_recvv(3, [{iov_base={sn_type=SCTP_NOTIFICATIONS_STOPPED_EVENT, sn_flags=0, sn_length=8}, iov_len=1000}], 1, +..., 20, NULL, [0], [SCTP_RECVV_NOINFO],[MSG_NOTIFICATION|MSG_EOR]) = 21 -- GitLab