diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l index 26d04437c01b4d235a13dd6092c48e2ae8adc321..8f9aaa8c75c131253d4050bce16c2ee778b757a7 100644 --- a/gtests/net/packetdrill/lexer.l +++ b/gtests/net/packetdrill/lexer.l @@ -329,6 +329,13 @@ pdapi_indication return PDAPI_INDICATION; pdapi_stream return PDAPI_STREAM; pdapi_seq return PDAPI_SEQ; pdapi_assoc_id return PDAPI_ASSOC_ID; +spc_type return SPC_TYPE; +spc_length return SPC_LENGTH; +spc_flags return SPC_FLAGS; +spc_aaddr return SPC_AADDR; +spc_state return SPC_STATE; +spc_error return SPC_ERROR; +spc_assoc_id return SPC_ASSOC_ID; CHUNK return CHUNK; DATA return DATA; INIT return INIT; diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index 448638be8cb202fde0d4b306713924f330698bf0..6134be3af2ead53ae3dca9fecd7490373ea2e881 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -559,6 +559,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %token <reserved> AUTH_TYPE AUTH_FLAGS AUTH_LENGTH AUTH_INDICATION AUTH_ASSOC_ID %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 <floating> FLOAT %token <integer> INTEGER HEX_INTEGER %token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR @@ -623,6 +624,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <expression> sctp_authkey_event auth_type auth_flags auth_length auth_keynumber auth_indication auth_assoc_id %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 <errno_info> opt_errno %type <chunk_list> sctp_chunk_list_spec %type <chunk_list_item> sctp_chunk_spec @@ -2598,6 +2600,7 @@ sockaddr data : ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } | sctp_assoc_change { $$ = $1; } +| sctp_paddr_change { $$ = $1; } | sctp_remote_error { $$ = $1; } | sctp_shutdown_event { $$ = $1; } | sctp_pdapi_event { $$ = $1; } @@ -4073,6 +4076,97 @@ sctp_remote_error } ; +spc_type +: SPC_TYPE '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("spc_type out of range"); + } + $$ = new_integer_expression($3, "%hu"); +} +| SPC_TYPE '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +| SPC_TYPE '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +spc_flags +: SPC_FLAGS '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("spc_flags out of range"); + } + $$ = new_integer_expression($3, "%hu"); +} +| SPC_FLAGS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +spc_length +: SPC_LENGTH '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("spc_length out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| SPC_LENGTH '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +spc_aaddr +: SPC_AADDR '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +| SPC_AADDR '=' sockaddr { $$ = $3; } +; + +spc_state +: SPC_STATE '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("spc_state out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| SPC_STATE '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +| SPC_STATE '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +spc_error +: SPC_ERROR '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("spc_error out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| SPC_ERROR '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +| SPC_ERROR '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +spc_assoc_id +: SPC_ASSOC_ID '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("spc_assoc_id out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| SPC_ASSOC_ID '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +sctp_paddr_change +: '{' spc_type ',' spc_flags ',' spc_length ',' spc_aaddr ',' spc_state ',' spc_error ',' spc_assoc_id '}' { + $$ = new_expression(EXPR_SCTP_PADDR_CHANGE); + $$->value.sctp_paddr_change = calloc(1, sizeof(struct sctp_paddr_change_expr)); + $$->value.sctp_paddr_change->spc_type = $2; + $$->value.sctp_paddr_change->spc_length = $4; + $$->value.sctp_paddr_change->spc_flags = $6; + $$->value.sctp_paddr_change->spc_aaddr = $8; + $$->value.sctp_paddr_change->spc_state = $10; + $$->value.sctp_paddr_change->spc_error = $12; + $$->value.sctp_paddr_change->spc_assoc_id = $14; +} +; + opt_errno : { $$ = NULL; } | WORD note { diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c index b5fc2103bf33917c52697f61736f4297c828f5a4..7a0a66134718838cc8f72e79ed8027e7fca14d64 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -569,6 +569,7 @@ static int iovec_new(struct expression *expression, assert(iov_expr->iov_base->type == EXPR_ELLIPSIS || 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_SHUTDOWN_EVENT || iov_expr->iov_base->type == EXPR_SCTP_PDAPI_EVENT || @@ -3419,6 +3420,36 @@ static int check_sctp_assoc_change(struct sctp_assoc_change_expr *expr, } #endif +#if defined(__FreeBSD__) || defined(linux) +static int check_sctp_paddr_change(struct sctp_paddr_change_expr *expr, + struct sctp_paddr_change *sctp_event, + char **error) { + if (check_u16_expr(expr->spc_type, sctp_event->spc_type, + "sctp_paddr_change.spc_type", error)) + return STATUS_ERR; + if (check_u16_expr(expr->spc_flags, sctp_event->spc_flags, + "sctp_paddr_change.spc_flags", error)) + return STATUS_ERR; + if (check_u32_expr(expr->spc_length, sctp_event->spc_length, + "sctp_paddr_change.spc_length", error)) + return STATUS_ERR; + if (check_sockaddr(expr->spc_aaddr, + (struct sockaddr *)&sctp_event->spc_aaddr, error)) + return STATUS_ERR; + if (check_u32_expr(expr->spc_state, sctp_event->spc_state, + "sctp_paddr_change.spc_state", error)) + return STATUS_ERR; + if (check_u32_expr(expr->spc_error, sctp_event->spc_error, + "sctp_paddr_change.spc_error", error)) + return STATUS_ERR; + if (check_u32_expr(expr->spc_assoc_id, sctp_event->spc_assoc_id, + "sctp_paddr_change.spc_assoc_id", error)) + return STATUS_ERR; + + return STATUS_OK; +} +#endif + #if defined(__FreeBSD__) || defined(linux) static int check_sctp_remote_error(struct sctp_remote_error_expr *expr, struct sctp_remote_error *sctp_event, @@ -3602,6 +3633,12 @@ static int check_sctp_notification(struct iovec *iov, error)) return STATUS_ERR; break; + case EXPR_SCTP_PADDR_CHANGE: + if (check_sctp_paddr_change(script_iov_base->value.sctp_paddr_change, + (struct sctp_paddr_change *) iov[i].iov_base, + error)) + return STATUS_ERR; + break; case EXPR_SCTP_REMOTE_ERROR: if (check_sctp_remote_error(script_iov_base->value.sctp_remote_error, (struct sctp_remote_error *) iov[i].iov_base, diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c index a48423c5d0d37e1ac821b7f01655a60313e10384..35979f33210cdd52722d924542fad048a3080ad4 100644 --- a/gtests/net/packetdrill/script.c +++ b/gtests/net/packetdrill/script.c @@ -87,6 +87,7 @@ struct expression_type_entry expression_type_table[] = { { EXPR_SCTP_NXTINFO, "sctp_nxtinfo" }, { EXPR_SCTP_RECVV_RN, "sctp_recvv_rn " }, { EXPR_SCTP_ASSOC_CHANGE, "sctp_assoc_change"}, + { EXPR_SCTP_PADDR_CHANGE, "sctp_paddr_change"}, { EXPR_SCTP_REMOTE_ERROR, "sctp_remote_error"}, { EXPR_SCTP_SHUTDOWN_EVENT, "sctp_shutdown_event"}, { EXPR_SCTP_PDAPI_EVENT, "sctp_pdapi_event"}, @@ -447,6 +448,15 @@ void free_expression(struct expression *expression) free_expression(expression->value.sctp_assoc_change->sac_assoc_id); free_expression(expression->value.sctp_assoc_change->sac_info); break; + case EXPR_SCTP_PADDR_CHANGE: + free_expression(expression->value.sctp_paddr_change->spc_type); + free_expression(expression->value.sctp_paddr_change->spc_flags); + free_expression(expression->value.sctp_paddr_change->spc_length); + free_expression(expression->value.sctp_paddr_change->spc_aaddr); + free_expression(expression->value.sctp_paddr_change->spc_state); + free_expression(expression->value.sctp_paddr_change->spc_error); + free_expression(expression->value.sctp_paddr_change->spc_assoc_id); + break; case EXPR_SCTP_REMOTE_ERROR: free_expression(expression->value.sctp_remote_error->sre_type); free_expression(expression->value.sctp_remote_error->sre_flags); @@ -1458,6 +1468,54 @@ static int evaluate_sctp_assoc_change_expression(struct expression *in, return STATUS_OK; } +static int evaluate_sctp_paddr_change_expression(struct expression *in, + struct expression *out, + char **error) +{ + struct sctp_paddr_change_expr *in_event; + struct sctp_paddr_change_expr *out_event; + + assert(in->type == EXPR_SCTP_PADDR_CHANGE); + assert(in->value.sctp_paddr_change); + assert(out->type == EXPR_SCTP_PADDR_CHANGE); + + out->value.sctp_paddr_change = calloc(1, sizeof(struct sctp_paddr_change_expr)); + + in_event = in->value.sctp_paddr_change; + out_event = out->value.sctp_paddr_change; + + if (evaluate(in_event->spc_type, + &out_event->spc_type, + error)) + return STATUS_ERR; + if (evaluate(in_event->spc_flags, + &out_event->spc_flags, + error)) + return STATUS_ERR; + if (evaluate(in_event->spc_length, + &out_event->spc_length, + error)) + return STATUS_ERR; + if (evaluate(in_event->spc_aaddr, + &out_event->spc_aaddr, + error)) + return STATUS_ERR; + if (evaluate(in_event->spc_state, + &out_event->spc_state, + error)) + return STATUS_ERR; + if (evaluate(in_event->spc_error, + &out_event->spc_error, + error)) + return STATUS_ERR; + if (evaluate(in_event->spc_assoc_id, + &out_event->spc_assoc_id, + error)) + return STATUS_ERR; + + return STATUS_OK; +} + static int evaluate_sctp_remote_error_expression(struct expression *in, struct expression *out, char **error) @@ -1798,6 +1856,9 @@ static int evaluate(struct expression *in, case EXPR_SCTP_ASSOC_CHANGE: result = evaluate_sctp_assoc_change_expression(in, out, error); break; + case EXPR_SCTP_PADDR_CHANGE: + result = evaluate_sctp_paddr_change_expression(in, out, error); + break; case EXPR_SCTP_REMOTE_ERROR: result = evaluate_sctp_remote_error_expression(in, out, error); break; diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h index c88287efca23aa6a352b3c96034c7fd5a77f7d45..f6f444dff3e042bd6283f44c24fde2b535a515a2 100644 --- a/gtests/net/packetdrill/script.h +++ b/gtests/net/packetdrill/script.h @@ -67,6 +67,7 @@ enum expression_t { EXPR_SCTP_NXTINFO, /* struct sctp_nxtinfo for syscall sctp_recvv */ EXPR_SCTP_RECVV_RN, /* struct sctp_recvv_rn for syscall sctp_recvv */ 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_SHUTDOWN_EVENT, /* expression tree for sctp_shutdown_event */ EXPR_SCTP_PDAPI_EVENT, /* expression tree for sctp_partial_delivery_event */ @@ -113,6 +114,7 @@ struct expression { struct sctp_nxtinfo_expr *sctp_nxtinfo; struct sctp_recvv_rn_expr *sctp_recvv_rn; 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_shutdown_event_expr *sctp_shutdown_event; struct sctp_pdapi_event_expr *sctp_pdapi_event; @@ -342,7 +344,18 @@ struct sctp_assoc_change_expr { struct expression *sac_info; }; -/* Parse tree for sctp_assoc_change for notifications. */ +/* Parse tree for sctp_paddr_change for notifications. */ +struct sctp_paddr_change_expr { + struct expression *spc_type; + struct expression *spc_flags; + struct expression *spc_length; + struct expression *spc_aaddr; + struct expression *spc_state; + struct expression *spc_error; + struct expression *spc_assoc_id; +}; + +/* Parse tree for sctp_remote_error_event for notifications. */ struct sctp_remote_error_expr { struct expression *sre_type; struct expression *sre_flags; diff --git a/gtests/net/packetdrill/symbols_freebsd.c b/gtests/net/packetdrill/symbols_freebsd.c index 7437cd1290ef19fafc7577bcc28083f60abeef04..9b0bc90bc370a39d4290c88fcd923801218762ad 100644 --- a/gtests/net/packetdrill/symbols_freebsd.c +++ b/gtests/net/packetdrill/symbols_freebsd.c @@ -217,7 +217,10 @@ struct int_symbol platform_symbols_table[] = { { SCTP_ASSOC_SUPPORTS_ASCONF, "SCTP_ASSOC_SUPPORTS_ASCONF" }, { SCTP_ASSOC_SUPPORTS_MULTIBUF, "SCTP_ASSOC_SUPPORTS_MULTIBUF" }, { SCTP_PARTIAL_DELIVERY_ABORTED, "SCTP_PARTIAL_DELIVERY_ABORTED" }, - + { SCTP_ADDR_AVAILABLE, "SCTP_ADDR_AVAILABLE" }, + { SCTP_ADDR_UNREACHABLE, "SCTP_ADDR_UNREACHABLE" }, + { SCTP_ADDR_REMOVED, "SCTP_ADDR_REMOVED" }, + { SCTP_ADDR_MADE_PRIM, "SCTP_ADDR_MADE_PRIM" }, /* /usr/include/netinet/tcp.h */ { TCP_NODELAY, "TCP_NODELAY" }, { TCP_MAXSEG, "TCP_MAXSEG" }, diff --git a/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_partial_delivery_event.pkt b/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_partial_delivery_event.pkt index 566aeecaf7d29a4a5a53cff4eabdca6c2fd23650..b1c619e8dfcb773fed123181ce3e1774165ebdba 100644 --- a/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_partial_delivery_event.pkt +++ b/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_partial_delivery_event.pkt @@ -9,13 +9,12 @@ +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 write(3, ..., 3000) = 3000 -* > sctp: DATA[flgs=B, len=1468, tsn=1, sid=0, ssn=0, ppid=0] -+0.0 < sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=1500, gaps=[], dups=[]] -* > sctp: DATA[flgs=0, len=1468, tsn=2, sid=0, ssn=0, ppid=0] -//+0.0 < sctp: ABORT[flgs=0, USER_INITIATED_ABORT[info="Testing"]] - -+0.0 sctp_recvv(3, [{iov_base=..., iov_len=1000}, {iov_base={pdapi_type=SCTP_PARTIAL_DELIVERY_EVENT, pdapi_flags=0,pdapi_length=24, ++0.0 < sctp: DATA[flgs=B, len=300, tsn=1, sid=0, ssn=0, ppid=0] ++0.0 > sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=..., gaps=[], dups=[]] ++0.0 < sctp: DATA[flgs=0, len=300, tsn=2, sid=0, ssn=0, ppid=0] +* > sctp: SACK[flgs=0, cum_tsn=2, a_rwnd=..., gaps=[], dups=[]] ++0.0 < sctp: ABORT[flgs=0] ++1.5 sctp_recvv(3, [{iov_base=..., iov_len=1000}, {iov_base={pdapi_type=SCTP_PARTIAL_DELIVERY_EVENT, pdapi_flags=0,pdapi_length=24, pdapi_indication=SCTP_PARTIAL_DELIVERY_ABORTED, pdapi_stream=0, pdapi_seq=0, pdapi_assoc_id=3 }, iov_len=1000}], 2, ..., 20, NULL, [0], [SCTP_RECVV_NOINFO], [MSG_NOTIFICATION|MSG_EOR]) = 21 diff --git a/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_peer_addr_change.pkt b/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_peer_addr_change.pkt new file mode 100644 index 0000000000000000000000000000000000000000..0c7069b8fde395b9a07152d48f6333b0b0ce8ccf --- /dev/null +++ b/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_peer_addr_change.pkt @@ -0,0 +1,15 @@ ++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_PEER_ADDR_CHANGE, se_on=1}, 8) = 0 ++0.0 getsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_PEER_ADDR_CHANGE, 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] + ++0.0 sctp_recvv(3, [{iov_base={spc_type=SCTP_PEER_ADDR_CHANGE, spc_flags=0, spc_length=21, spc_aaddr=..., spc_state=SCTP_ADDR_MADE_PRIM, spc_error=0, + spc_assoc_id=3}, iov_len=1000}], 1, ..., 20, NULL, [0], [SCTP_RECVV_NOINFO], +[MSG_NOTIFICATION|MSG_EOR]) = 21