diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l index 9521fed2eddd06237cbe92a334e2d3969122dae7..f54f7a597db864f2b2ea752f2b9dc01d9271a932 100644 --- a/gtests/net/packetdrill/lexer.l +++ b/gtests/net/packetdrill/lexer.l @@ -513,6 +513,23 @@ srs_stream_list return SRS_STREAM_LIST; sas_assoc_id return SAS_ASSOC_ID; sas_instrms return SAS_INSTRMS; sas_outstrms return SAS_OUTSTRMS; +strreset_type return STRRESET_TYPE; +strreset_flags return STRRESET_FLAGS; +strreset_length return STRRESET_LENGTH; +strreset_assoc_id return STRRESET_ASSOC_ID; +strreset_stream_list return STRRESET_STREAM_LIST; +assocreset_type return ASSOCRESET_TYPE; +assocreset_flags return ASSOCRESET_FLAGS; +assocreset_length return ASSOCRESET_LENGTH; +assocreset_assoc_id return ASSOCRESET_ASSOC_ID; +assocreset_local_tsn return ASSOCRESET_LOCAL_TSN; +assocreset_remote_tsn return ASSOCRESET_REMOTE_TSN; +strchange_type return STRCHANGE_TYPE; +strchange_flags return STRCHANGE_FLAGS; +strchange_length return STRCHANGE_LENGTH; +strchange_assoc_id return STRCHANGE_ASSOC_ID; +strchange_instrms return STRCHANGE_INSTRMS; +strchange_outstrms return STRCHANGE_OUTSTRMS; CHUNK return CHUNK; DATA return DATA; INIT return INIT; diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index c4af6bf1fef35e7d91ba00e71fe706dc24cf9f9a..3ac46b6497d1788cc9038a3c95d4fa4a51b99567 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -569,6 +569,9 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %token <reserved> SCA_ASSOC_ID SCA_KEYNUMBER SCA_KEYLENGTH SCA_KEY %token <reserved> SRS_ASSOC_ID SRS_FLAGS SRS_NUMBER_STREAMS SRS_STREAM_LIST %token <reserved> SAS_ASSOC_ID SAS_INSTRMS SAS_OUTSTRMS +%token <reserved> STRRESET_TYPE STRRESET_FLAGS STRRESET_LENGTH STRRESET_ASSOC_ID STRRESET_STREAM_LIST +%token <reserved> ASSOCRESET_TYPE ASSOCRESET_FLAGS ASSOCRESET_LENGTH ASSOCRESET_ASSOC_ID ASSOCRESET_LOCAL_TSN ASSOCRESET_REMOTE_TSN +%token <reserved> STRCHANGE_TYPE STRCHANGE_FLAGS STRCHANGE_LENGTH STRCHANGE_ASSOC_ID STRCHANGE_INSTRMS STRCHANGE_OUTSTRMS %token <floating> FLOAT %token <integer> INTEGER HEX_INTEGER %token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR @@ -643,6 +646,10 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <expression> sctp_tlv sn_type sn_flags sn_length sctp_assoc_ids gaids_number_of_ids %type <expression> sctp_setpeerprim sctp_authchunk sctp_authkey %type <expression> sctp_reset_streams srs_flags +%type <expression> sctp_stream_reset_event strreset_type strreset_flags strreset_length +%type <expression> sctp_assoc_reset_event assocreset_type assocreset_flags assocreset_length +%type <expression> assocreset_local_tsn assocreset_remote_tsn +%type <expression> sctp_stream_change_event strchange_type strchange_flags strchange_length strchange_instrms strchange_outstrms %type <expression> sctp_add_streams %type <errno_info> opt_errno %type <chunk_list> sctp_chunk_list_spec @@ -2740,6 +2747,9 @@ data | sctp_send_failed_event { $$ = $1; } | sctp_authkey_event { $$ = $1; } | sctp_tlv { $$ = $1; } +| sctp_stream_reset_event { $$ = $1; } +| sctp_assoc_reset_event { $$ = $1; } +| sctp_stream_change_event { $$ = $1; } ; msghdr @@ -5023,6 +5033,203 @@ sctp_add_streams } ; +strreset_type +: STRRESET_TYPE '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("strreset_type out of range"); + } + $$ = new_integer_expression($3, "%hu"); +} +| STRRESET_TYPE '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +| STRRESET_TYPE '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +strreset_flags +: STRRESET_FLAGS '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("strreset_flags out of range"); + } + $$ = new_integer_expression($3, "%hu"); +} +| STRRESET_FLAGS '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +| STRRESET_FLAGS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +| STRRESET_FLAGS '=' binary_expression { $$ = $3; } +; + +strreset_length +: STRRESET_LENGTH '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("strreset_length out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| STRRESET_LENGTH '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +sctp_stream_reset_event +: '{' strreset_type ',' strreset_flags ',' strreset_length ',' STRRESET_ASSOC_ID '=' sctp_assoc_id ',' STRRESET_STREAM_LIST '=' array '}' { + $$ = new_expression(EXPR_SCTP_STREAM_RESET_EVENT); + $$->value.sctp_stream_reset_event = calloc(1, sizeof(struct sctp_stream_reset_event_expr)); + $$->value.sctp_stream_reset_event->strreset_type = $2; + $$->value.sctp_stream_reset_event->strreset_flags = $4; + $$->value.sctp_stream_reset_event->strreset_length = $6; + $$->value.sctp_stream_reset_event->strreset_assoc_id = $10; + $$->value.sctp_stream_reset_event->strreset_stream_list = $14; +} +; + +assocreset_type +: ASSOCRESET_TYPE '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("assocreset_type out of range"); + } + $$ = new_integer_expression($3, "%hu"); +} +| ASSOCRESET_TYPE '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +| ASSOCRESET_TYPE '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +assocreset_flags +: ASSOCRESET_FLAGS '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("assocreset_flags out of range"); + } + $$ = new_integer_expression($3, "%hu"); +} +| ASSOCRESET_FLAGS '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +| ASSOCRESET_FLAGS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +| ASSOCRESET_FLAGS '=' binary_expression { $$ = $3; } +; + +assocreset_length +: ASSOCRESET_LENGTH '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("assocreset_length out of range"); + } + $$ = new_integer_expression($3, "%hu"); +} +| ASSOCRESET_LENGTH '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +assocreset_local_tsn +: ASSOCRESET_LOCAL_TSN '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("assocreset_local_tsn out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| ASSOCRESET_LOCAL_TSN '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +assocreset_remote_tsn +: ASSOCRESET_REMOTE_TSN '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("assocreset_remote_tsn out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| ASSOCRESET_REMOTE_TSN '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +sctp_assoc_reset_event +: '{' assocreset_type ',' assocreset_flags ',' assocreset_length ',' ASSOCRESET_ASSOC_ID '=' sctp_assoc_id ',' + assocreset_local_tsn ',' assocreset_remote_tsn '}' { + $$ = new_expression(EXPR_SCTP_ASSOC_RESET_EVENT); + $$->value.sctp_assoc_reset_event = calloc(1, sizeof(struct sctp_assoc_reset_event_expr)); + $$->value.sctp_assoc_reset_event->assocreset_type = $2; + $$->value.sctp_assoc_reset_event->assocreset_flags = $4; + $$->value.sctp_assoc_reset_event->assocreset_length = $6; + $$->value.sctp_assoc_reset_event->assocreset_assoc_id = $10; + $$->value.sctp_assoc_reset_event->assocreset_local_tsn = $12; + $$->value.sctp_assoc_reset_event->assocreset_remote_tsn = $14; +} +; + +strchange_type +: STRCHANGE_TYPE '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("strchange_type out of range"); + } + $$ = new_integer_expression($3, "%hu"); +} +| STRCHANGE_TYPE '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +| STRCHANGE_TYPE '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +strchange_flags +: STRCHANGE_FLAGS '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("strchange_flags out of range"); + } + $$ = new_integer_expression($3, "%hu"); +} +| STRCHANGE_FLAGS '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +| STRCHANGE_FLAGS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +| STRCHANGE_FLAGS '=' binary_expression { $$ = $3; } +; + +strchange_length +: STRCHANGE_LENGTH '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("strchange_length out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| STRCHANGE_LENGTH '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +strchange_instrms +: STRCHANGE_INSTRMS '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("strchange_instrms out of range"); + } + $$ = new_integer_expression($3, "%hu"); +} +| STRCHANGE_INSTRMS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +strchange_outstrms +: STRCHANGE_OUTSTRMS '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("strchange_outstrms out of range"); + } + $$ = new_integer_expression($3, "%hu"); +} +| STRCHANGE_OUTSTRMS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +sctp_stream_change_event +: '{' strchange_type ',' strchange_flags ',' strchange_length ',' STRCHANGE_ASSOC_ID '=' sctp_assoc_id ',' strchange_instrms ',' strchange_outstrms '}' { + $$ = new_expression(EXPR_SCTP_STREAM_CHANGE_EVENT); + $$->value.sctp_stream_change_event = calloc(1, sizeof(struct sctp_stream_change_event_expr)); + $$->value.sctp_stream_change_event->strchange_type = $2; + $$->value.sctp_stream_change_event->strchange_flags = $4; + $$->value.sctp_stream_change_event->strchange_length = $6; + $$->value.sctp_stream_change_event->strchange_assoc_id = $10; + $$->value.sctp_stream_change_event->strchange_instrms = $12; + $$->value.sctp_stream_change_event->strchange_outstrms = $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 f0b4fb30164982eb8791a3056792fd1aeb7348cd..d3f1332a97fa70fda29566355308fca35b4466fb 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -853,7 +853,10 @@ static int iovec_new(struct expression *expression, 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_TLV); + iov_expr->iov_base->type == EXPR_SCTP_TLV || + iov_expr->iov_base->type == EXPR_SCTP_STREAM_RESET_EVENT || + iov_expr->iov_base->type == EXPR_SCTP_ASSOC_RESET_EVENT || + iov_expr->iov_base->type == EXPR_SCTP_STREAM_CHANGE_EVENT); assert(iov_expr->iov_len->type == EXPR_INTEGER); len = iov_expr->iov_len->value.num; @@ -4018,7 +4021,7 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, get_u16(expr, &(reset_streams->srs_stream_list[i]), error); } - optval = &reset_streams; + optval = reset_streams; break; } #endif @@ -5237,6 +5240,85 @@ static int check_sctp_tlv(struct sctp_tlv_expr *expr, struct sctp_tlv *sctp_tlv, } #endif +#if defined(__FreeBSD__) +static int check_sctp_stream_reset_event(struct sctp_stream_reset_event_expr *expr, + struct sctp_stream_reset_event *sctp_stream_reset_event, + char **error) { + if (check_u16_expr(expr->strreset_type, sctp_stream_reset_event->strreset_type, + "sctp_stream_reset_event.strreset_type", error)) + return STATUS_ERR; + if (check_u16_expr(expr->strreset_flags, sctp_stream_reset_event->strreset_flags, + "sctp_stream_reset_event.strreset_flags", error)) + return STATUS_ERR; + if (check_u32_expr(expr->strreset_length, sctp_stream_reset_event->strreset_length, + "sctp_stream_reset_event.strreset_length", error)) + return STATUS_ERR; + if (check_sctp_assoc_t_expr(expr->strreset_assoc_id, sctp_stream_reset_event->strreset_assoc_id, + "sctp_stream_reset_event.strreset_assoc_id", error)) + return STATUS_ERR; + if (check_u16array_expr(expr->strreset_stream_list, sctp_stream_reset_event->strreset_stream_list, + sctp_stream_reset_event->strreset_length - sizeof(u16) - sizeof(u16) - sizeof(u32) - sizeof(sctp_assoc_t), + "sctp_stream_reset_event.strreset_stream_list", error)) + return STATUS_ERR; + + return STATUS_OK; +} +#endif + +#if defined(__FreeBSD__) +static int check_sctp_assoc_reset_event(struct sctp_assoc_reset_event_expr *expr, + struct sctp_assoc_reset_event *sctp_assoc_reset_event, + char **error) { + if (check_u16_expr(expr->assocreset_type, sctp_assoc_reset_event->assocreset_type, + "sctp_assoc_reset_event.assocreset_type", error)) + return STATUS_ERR; + if (check_u16_expr(expr->assocreset_flags, sctp_assoc_reset_event->assocreset_flags, + "sctp_assoc_reset_event.assocreset_flags", error)) + return STATUS_ERR; + if (check_u32_expr(expr->assocreset_length, sctp_assoc_reset_event->assocreset_length, + "sctp_assoc_reset_event.assocreset_length", error)) + return STATUS_ERR; + if (check_sctp_assoc_t_expr(expr->assocreset_assoc_id, sctp_assoc_reset_event->assocreset_assoc_id, + "sctp_assoc_reset_event.assocreset_assoc_id", error)) + return STATUS_ERR; + if (check_u32_expr(expr->assocreset_local_tsn, sctp_assoc_reset_event->assocreset_local_tsn, + "sctp_assoc_reset_event.assocreset_local_tsn", error)) + return STATUS_ERR; + if (check_u32_expr(expr->assocreset_remote_tsn, sctp_assoc_reset_event->assocreset_remote_tsn, + "sctp_assoc_reset_event.assocreset_remote_tsn", error)) + return STATUS_ERR; + + return STATUS_OK; +} +#endif + +#if defined(__FreeBSD__) +static int check_sctp_stream_change_event(struct sctp_stream_change_event_expr *expr, + struct sctp_stream_change_event *sctp_stream_change_event, + char **error) { + if (check_u16_expr(expr->strchange_type, sctp_stream_change_event->strchange_type, + "sctp_stream_change_event.strchange_type", error)) + return STATUS_ERR; + if (check_u16_expr(expr->strchange_flags, sctp_stream_change_event->strchange_flags, + "sctp_stream_change_event.strchange_flags", error)) + return STATUS_ERR; + if (check_u32_expr(expr->strchange_length, sctp_stream_change_event->strchange_length, + "sctp_stream_change_event.strchange_length", error)) + return STATUS_ERR; + if (check_sctp_assoc_t_expr(expr->strchange_assoc_id, sctp_stream_change_event->strchange_assoc_id, + "sctp_stream_change_event.strchange_assoc_id", error)) + return STATUS_ERR; + if (check_u16_expr(expr->strchange_instrms, sctp_stream_change_event->strchange_instrms, + "sctp_stream_change_event.strchange_instrms", error)) + return STATUS_ERR; + if (check_u16_expr(expr->strchange_outstrms, sctp_stream_change_event->strchange_outstrms, + "sctp_stream_change_event.strchange_outstrms", 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, @@ -5323,6 +5405,30 @@ static int check_sctp_notification(struct iovec *iov, error)) return STATUS_ERR; break; +#if defined(__FreeBSD__) + case EXPR_SCTP_STREAM_RESET_EVENT: + if (check_sctp_stream_reset_event(script_iov_base->value.sctp_stream_reset_event, + (struct sctp_stream_reset_event *) iov[i].iov_base, + error)) + return STATUS_ERR; + break; +#endif +#if defined(__FreeBSD__) + case EXPR_SCTP_ASSOC_RESET_EVENT: + if (check_sctp_assoc_reset_event(script_iov_base->value.sctp_assoc_reset_event, + (struct sctp_assoc_reset_event *) iov[i].iov_base, + error)) + return STATUS_ERR; + break; +#endif +#if defined(__FreeBSD__) + case EXPR_SCTP_STREAM_CHANGE_EVENT: + if (check_sctp_stream_change_event(script_iov_base->value.sctp_stream_change_event, + (struct sctp_stream_change_event *) iov[i].iov_base, + error)) + return STATUS_ERR; + break; +#endif case EXPR_ELLIPSIS: break; default: diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c index 8200496b47fb85664e5bf03586e296c9d56c228f..250dcd4c6531cb2e9006460a0b53eb3464dea65f 100644 --- a/gtests/net/packetdrill/script.c +++ b/gtests/net/packetdrill/script.c @@ -110,6 +110,9 @@ struct expression_type_entry expression_type_table[] = { { EXPR_SCTP_AUTHKEY, "sctp_authkey" }, { EXPR_SCTP_RESET_STREAMS, "sctp_reset_streams"}, { EXPR_SCTP_ADD_STREAMS, "sctp_add_streams"}, + { EXPR_SCTP_STREAM_RESET_EVENT, "sctp_stream_reset_event"}, + { EXPR_SCTP_ASSOC_RESET_EVENT, "sctp_assoc_reset_event"}, + { EXPR_SCTP_STREAM_CHANGE_EVENT, "sctp_stream_change_event"}, { NUM_EXPR_TYPES, NULL} }; @@ -620,6 +623,29 @@ void free_expression(struct expression *expression) free_expression(expression->value.sctp_add_streams->sas_instrms); free_expression(expression->value.sctp_add_streams->sas_outstrms); break; + case EXPR_SCTP_STREAM_RESET_EVENT: + free_expression(expression->value.sctp_stream_reset_event->strreset_type); + free_expression(expression->value.sctp_stream_reset_event->strreset_flags); + free_expression(expression->value.sctp_stream_reset_event->strreset_length); + free_expression(expression->value.sctp_stream_reset_event->strreset_assoc_id); + free_expression(expression->value.sctp_stream_reset_event->strreset_stream_list); + break; + case EXPR_SCTP_ASSOC_RESET_EVENT: + free_expression(expression->value.sctp_assoc_reset_event->assocreset_type); + free_expression(expression->value.sctp_assoc_reset_event->assocreset_flags); + free_expression(expression->value.sctp_assoc_reset_event->assocreset_length); + free_expression(expression->value.sctp_assoc_reset_event->assocreset_assoc_id); + free_expression(expression->value.sctp_assoc_reset_event->assocreset_local_tsn); + free_expression(expression->value.sctp_assoc_reset_event->assocreset_remote_tsn); + break; + case EXPR_SCTP_STREAM_CHANGE_EVENT: + free_expression(expression->value.sctp_stream_change_event->strchange_type); + free_expression(expression->value.sctp_stream_change_event->strchange_flags); + free_expression(expression->value.sctp_stream_change_event->strchange_length); + free_expression(expression->value.sctp_stream_change_event->strchange_assoc_id); + free_expression(expression->value.sctp_stream_change_event->strchange_instrms); + free_expression(expression->value.sctp_stream_change_event->strchange_outstrms); + break; case EXPR_WORD: assert(expression->value.string); free(expression->value.string); @@ -2499,6 +2525,134 @@ static int evaluate_sctp_add_streams_expression(struct expression *in, return STATUS_OK; } +static int evaluate_sctp_stream_reset_event_expression(struct expression *in, + struct expression *out, + char **error) +{ + struct sctp_stream_reset_event_expr *in_event; + struct sctp_stream_reset_event_expr *out_event; + + assert(in->type == EXPR_SCTP_STREAM_RESET_EVENT); + assert(in->value.sctp_stream_reset_event); + assert(out->type == EXPR_SCTP_STREAM_RESET_EVENT); + + out->value.sctp_stream_reset_event = calloc(1, sizeof(struct sctp_stream_reset_event_expr)); + + in_event = in->value.sctp_stream_reset_event; + out_event = out->value.sctp_stream_reset_event; + + if (evaluate(in_event->strreset_type, + &out_event->strreset_type, + error)) + return STATUS_ERR; + if (evaluate(in_event->strreset_flags, + &out_event->strreset_flags, + error)) + return STATUS_ERR; + if (evaluate(in_event->strreset_length, + &out_event->strreset_length, + error)) + return STATUS_ERR; + if (evaluate(in_event->strreset_assoc_id, + &out_event->strreset_assoc_id, + error)) + return STATUS_ERR; + if (evaluate(in_event->strreset_stream_list, + &out_event->strreset_stream_list, + error)) + return STATUS_ERR; + + return STATUS_OK; +} + +static int evaluate_sctp_assoc_reset_event_expression(struct expression *in, + struct expression *out, + char **error) +{ + struct sctp_assoc_reset_event_expr *in_event; + struct sctp_assoc_reset_event_expr *out_event; + + assert(in->type == EXPR_SCTP_ASSOC_RESET_EVENT); + assert(in->value.sctp_assoc_reset_event); + assert(out->type == EXPR_SCTP_ASSOC_RESET_EVENT); + + out->value.sctp_assoc_reset_event = calloc(1, sizeof(struct sctp_assoc_reset_event_expr)); + + in_event = in->value.sctp_assoc_reset_event; + out_event = out->value.sctp_assoc_reset_event; + + if (evaluate(in_event->assocreset_type, + &out_event->assocreset_type, + error)) + return STATUS_ERR; + if (evaluate(in_event->assocreset_flags, + &out_event->assocreset_flags, + error)) + return STATUS_ERR; + if (evaluate(in_event->assocreset_length, + &out_event->assocreset_length, + error)) + return STATUS_ERR; + if (evaluate(in_event->assocreset_assoc_id, + &out_event->assocreset_assoc_id, + error)) + return STATUS_ERR; + if (evaluate(in_event->assocreset_local_tsn, + &out_event->assocreset_local_tsn, + error)) + return STATUS_ERR; + if (evaluate(in_event->assocreset_remote_tsn, + &out_event->assocreset_remote_tsn, + error)) + return STATUS_ERR; + + return STATUS_OK; +} + +static int evaluate_sctp_stream_change_event_expression(struct expression *in, + struct expression *out, + char **error) +{ + struct sctp_stream_change_event_expr *in_event; + struct sctp_stream_change_event_expr *out_event; + + assert(in->type == EXPR_SCTP_STREAM_CHANGE_EVENT); + assert(in->value.sctp_stream_change_event); + assert(out->type == EXPR_SCTP_STREAM_CHANGE_EVENT); + + out->value.sctp_stream_change_event = calloc(1, sizeof(struct sctp_stream_change_event_expr)); + + in_event = in->value.sctp_stream_change_event; + out_event = out->value.sctp_stream_change_event; + + if (evaluate(in_event->strchange_type, + &out_event->strchange_type, + error)) + return STATUS_ERR; + if (evaluate(in_event->strchange_flags, + &out_event->strchange_flags, + error)) + return STATUS_ERR; + if (evaluate(in_event->strchange_length, + &out_event->strchange_length, + error)) + return STATUS_ERR; + if (evaluate(in_event->strchange_assoc_id, + &out_event->strchange_assoc_id, + error)) + return STATUS_ERR; + if (evaluate(in_event->strchange_instrms, + &out_event->strchange_instrms, + error)) + return STATUS_ERR; + if (evaluate(in_event->strchange_outstrms, + &out_event->strchange_outstrms, + error)) + return STATUS_ERR; + + return STATUS_OK; +} + static int evaluate(struct expression *in, struct expression **out_ptr, char **error) { @@ -2653,6 +2807,15 @@ static int evaluate(struct expression *in, case EXPR_SCTP_ADD_STREAMS: result = evaluate_sctp_add_streams_expression(in, out, error); break; + case EXPR_SCTP_STREAM_RESET_EVENT: + result = evaluate_sctp_stream_reset_event_expression(in, out, error); + break; + case EXPR_SCTP_ASSOC_RESET_EVENT: + result = evaluate_sctp_assoc_reset_event_expression(in, out, error); + break; + case EXPR_SCTP_STREAM_CHANGE_EVENT: + result = evaluate_sctp_stream_change_event_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 97a9ce4deb124616c6e7de387a971dca8e0c4e47..0dc20025819b2e04ea482756465c7096ec542f21 100644 --- a/gtests/net/packetdrill/script.h +++ b/gtests/net/packetdrill/script.h @@ -90,6 +90,9 @@ enum expression_t { EXPR_SCTP_AUTHKEY, /* expression tree for sctp_authkey struct for setsockopt */ EXPR_SCTP_RESET_STREAMS, /* expression tree for sctp_reset_stream struct for [gs]etsockopt */ EXPR_SCTP_ADD_STREAMS, /* expression tree for sctp_add_streams struct for [gs]etsockopt */ + EXPR_SCTP_STREAM_RESET_EVENT, /* expression tree for sctp_stream_reset_event struct for sctp notifications */ + EXPR_SCTP_ASSOC_RESET_EVENT, /* expression tree for sctp_assoc_reset_event struct for sctp notifications */ + EXPR_SCTP_STREAM_CHANGE_EVENT, /* expression tree for sctp_stream_change_event struct for sctp notifications */ NUM_EXPR_TYPES, }; /* Convert an expression type to a human-readable string */ @@ -153,6 +156,9 @@ struct expression { struct sctp_authkey_expr *sctp_authkey; struct sctp_reset_streams_expr *sctp_reset_streams; struct sctp_add_streams_expr *sctp_add_streams; + struct sctp_stream_reset_event_expr *sctp_stream_reset_event; + struct sctp_assoc_reset_event_expr *sctp_assoc_reset_event; + struct sctp_stream_change_event_expr *sctp_stream_change_event; } value; const char *format; /* the printf format for printing the value */ }; @@ -584,6 +590,35 @@ struct sctp_add_streams_expr { struct expression *sas_outstrms; }; +/* Parse tree for sctp_stream_reset_event struct for sctp notifications. */ +struct sctp_stream_reset_event_expr { + struct expression *strreset_type; + struct expression *strreset_flags; + struct expression *strreset_length; + struct expression *strreset_assoc_id; + struct expression *strreset_stream_list; +}; + +/* Parse tree for sctp_assoc_reset_event struct for sctp notifications. */ +struct sctp_assoc_reset_event_expr { + struct expression *assocreset_type; + struct expression *assocreset_flags; + struct expression *assocreset_length; + struct expression *assocreset_assoc_id; + struct expression *assocreset_local_tsn; + struct expression *assocreset_remote_tsn; +}; + +/* Parse tree for sctp_stream_change_event struct for sctp notifications. */ +struct sctp_stream_change_event_expr { + struct expression *strchange_type; + struct expression *strchange_flags; + struct expression *strchange_length; + struct expression *strchange_assoc_id; + struct expression *strchange_instrms; + struct expression *strchange_outstrms; +}; + /* 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 a84937712785cdc4a75d2af91122aceb74917fcf..6cf0971c4c3748355bb2bbb1bcdf8dbcc8c8e420 100644 --- a/gtests/net/packetdrill/symbols_freebsd.c +++ b/gtests/net/packetdrill/symbols_freebsd.c @@ -199,10 +199,7 @@ struct int_symbol platform_symbols_table[] = { { 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_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" }, { SCTP_UNORDERED, "SCTP_UNORDERED" }, { SCTP_COMPLETE, "SCTP_COMPLETE" }, @@ -275,6 +272,17 @@ struct int_symbol platform_symbols_table[] = { { SCTP_STREAM_RESET_OUTGOING, "SCTP_STREAM_RESET_OUTGOING" }, { SCTP_RESET_ASSOC, "SCTP_RESET_ASSOC" }, { SCTP_ADD_STREAMS, "SCTP_ADD_STREAMS" }, + { SCTP_STREAM_RESET_EVENT, "SCTP_STREAM_RESET_EVENT" }, + { SCTP_STREAM_RESET_INCOMING_SSN, "SCTP_STREAM_RESET_INCOMING_SSN" }, + { SCTP_STREAM_RESET_OUTGOING_SSN, "SCTP_STREAM_RESET_OUTGOING_SSN" }, + { SCTP_STREAM_RESET_DENIED, "SCTP_STREAM_RESET_DENIED" }, + { SCTP_STREAM_RESET_FAILED, "SCTP_STREAM_RESET_FAILED" }, + { SCTP_ASSOC_RESET_EVENT, "SCTP_ASSOC_RESET_EVENT" }, + { SCTP_ASSOC_RESET_DENIED, "SCTP_ASSOC_RESET_DENIED" }, + { SCTP_ASSOC_RESET_FAILED, "SCTP_ASSOC_RESET_FAILED" }, + { SCTP_STREAM_CHANGE_EVENT, "SCTP_STREAM_CHANGE_EVENT" }, + { SCTP_STREAM_CHANGE_DENIED, "SCTP_STREAM_CHANGE_DENIED" }, + { SCTP_STREAM_CHANGE_FAILED, "SCTP_STREAM_CHANGE_FAILED" }, /* /usr/include/netinet/tcp.h */ { TCP_NODELAY, "TCP_NODELAY" }, diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/sctp_add_streams.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/sctp_add_streams.pkt index 1f7a50af99366ce8936f34a439d1b17b17d79f48..88fdd7cc9608f823bbd1f0e93f1ad87a9876b5d0 100644 --- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/sctp_add_streams.pkt +++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/sctp_add_streams.pkt @@ -1,20 +1,40 @@ --tolerance_usecs=100000 - 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 ++0.0 socket(..., SOCK_STREAM, IPPROTO_SCTP) = 3 + ++0.0 setsockopt(3, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET, {assoc_id=0, assoc_value=SCTP_ENABLE_RESET_STREAM_REQ}, 8) = 0 + +0.0 bind(3, ..., ...) = 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=16, is=16, 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 listen(3, 1) = 0 ++0.0 < sctp: INIT[flgs=0, tag=1, a_rwnd=1500, os=1, is=1, tsn=1, + ECN_CAPABLE[], + SUPPORTED_EXTENSIONS[types=[0x82]], + COOKIE_PRESERVATIVE[incr=12345], + SUPPORTED_ADDRESS_TYPES[types=[IPv4]]] ++0.0 > sctp: INIT_ACK[flgs=0, tag=2, a_rwnd=..., os=..., is=..., tsn=10, ...] ++0.1 < sctp: COOKIE_ECHO[flgs=0, len=..., val=...] ++0.0 > sctp: COOKIE_ACK[flgs=0] + ++0.0 accept(3, ..., ...) = 4 + ++1.0 write(4, ..., 1000) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=10, sid=0, ssn=0, ppid=0] ++0.1 < sctp: SACK[flgs=0, cum_tsn=10, a_rwnd=1500, gaps=[], dups=[]] + ++1.0 write(4, ..., 1000) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=11, sid=0, ssn=1, ppid=0] ++0.0 < sctp: SACK[flgs=0, cum_tsn=11, a_rwnd=1500, gaps=[], dups=[]] + ++0.1 < sctp: DATA[flgs=BE, len=1016, tsn=1, sid=0, ssn=0, ppid=0] +* > sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=..., gaps=[], dups=[]] ++0.0 read(4, ..., 1000) = 1000 -+0 setsockopt(3, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET, {assoc_id=0, assoc_value=SCTP_ENABLE_RESET_STREAM_REQ}, 8) = 0 ++0.1 < sctp: DATA[flgs=BE, len=1016, tsn=2, sid=0, ssn=1, ppid=0] +* > sctp: SACK[flgs=0, cum_tsn=2, a_rwnd=..., gaps=[], dups=[]] ++0.0 read(4, ..., 1000) = 1000 -+0 setsockopt(3, IPPROTO_SCTP, SCTP_ADD_STREAMS, {sas_instrms=20, ++0 setsockopt(4, IPPROTO_SCTP, SCTP_ADD_STREAMS, {sas_instrms=20, sas_outstrms=20}, 8) = 0 +0 close(3) = 0 ++0 close(4) = 0 diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/sctp_reset_assoc.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/sctp_reset_assoc.pkt index e5081031c5f958664afc9b60c7e594d931f4a321..26b66e02e7425618bc864c82060022168d6b71ce 100644 --- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/sctp_reset_assoc.pkt +++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/sctp_reset_assoc.pkt @@ -1,57 +1,39 @@ --tolerance_usecs=100000 - 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 ++0.0 socket(..., SOCK_STREAM, IPPROTO_SCTP) = 3 + ++0.0 setsockopt(3, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET, {assoc_id=0, assoc_value=SCTP_ENABLE_RESET_STREAM_REQ}, 8) = 0 + +0.0 bind(3, ..., ...) = 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=16, is=16, 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 setsockopt(3, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET, {assoc_id=0, assoc_value=SCTP_ENABLE_RESET_ASSOC_REQ}, 8) = 0 - -+0.0 sctp_sendx(3, ..., 1000, ..., 1, {sinfo_stream=3, - sinfo_ssn=3, - sinfo_flags=0, - sinfo_ppid=htonl(1234), - sinfo_context=0, - sinfo_timetolive=0, - sinfo_tsn=2, - sinfo_cumtsn=2, - sinfo_assoc_id=3}, 0) = 1000 -* > sctp: DATA[flgs=BE, len=1016, tsn=1, sid=3, ssn=0, ppid=1234] -+0.0 < sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=1500, gaps=[], dups=[]] - - -+0.0 sctp_sendx(3, ..., 1000, ..., 1, {sinfo_stream=3, - sinfo_ssn=3, - sinfo_flags=0, - sinfo_ppid=htonl(7), - sinfo_context=0, - sinfo_timetolive=0, - sinfo_tsn=1, - sinfo_cumtsn=6, - sinfo_assoc_id=3}, 0) = 1000 -* > sctp: DATA[flgs=BE, len=1016, tsn=2, sid=3, ssn=1, ppid=7] -+0.0 < sctp: SACK[flgs=0, cum_tsn=2, a_rwnd=1500, gaps=[], dups=[]] - -+0.0 sctp_sendx(3, ..., 1000, ..., 1, - {sinfo_stream=3, - sinfo_ssn=3, - sinfo_flags=0, - sinfo_ppid=htonl(7), - sinfo_context=0, - sinfo_timetolive=0, - sinfo_tsn=1, - sinfo_cumtsn=6, - sinfo_assoc_id=3}, 0) = 1000 -* > sctp: DATA[flgs=BE, len=1016, tsn=3, sid=3, ssn=2, ppid=7] -+0.0 < sctp: SACK[flgs=0, cum_tsn=3, a_rwnd=1500, gaps=[], dups=[]] - -+0 setsockopt(3, IPPROTO_SCTP, SCTP_RESET_ASSOC, [0], 4) = 0 ++0.0 listen(3, 1) = 0 ++0.0 < sctp: INIT[flgs=0, tag=1, a_rwnd=1500, os=1, is=1, tsn=1, + ECN_CAPABLE[], + SUPPORTED_EXTENSIONS[types=[0x82]], + COOKIE_PRESERVATIVE[incr=12345], + SUPPORTED_ADDRESS_TYPES[types=[IPv4]]] ++0.0 > sctp: INIT_ACK[flgs=0, tag=2, a_rwnd=..., os=..., is=..., tsn=10, ...] ++0.1 < sctp: COOKIE_ECHO[flgs=0, len=..., val=...] ++0.0 > sctp: COOKIE_ACK[flgs=0] + ++0.0 accept(3, ..., ...) = 4 + ++1.0 write(4, ..., 1000) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=10, sid=0, ssn=0, ppid=0] ++0.1 < sctp: SACK[flgs=0, cum_tsn=10, a_rwnd=1500, gaps=[], dups=[]] + ++1.0 write(4, ..., 1000) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=11, sid=0, ssn=1, ppid=0] ++0.0 < sctp: SACK[flgs=0, cum_tsn=11, a_rwnd=1500, gaps=[], dups=[]] + ++0.1 < sctp: DATA[flgs=BE, len=1016, tsn=1, sid=0, ssn=0, ppid=0] +* > sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=..., gaps=[], dups=[]] ++0.0 read(4, ..., 1000) = 1000 + ++0.1 < sctp: DATA[flgs=BE, len=1016, tsn=2, sid=0, ssn=1, ppid=0] +* > sctp: SACK[flgs=0, cum_tsn=2, a_rwnd=..., gaps=[], dups=[]] ++0.0 read(4, ..., 1000) = 1000 + ++0 setsockopt(4, IPPROTO_SCTP, SCTP_RESET_ASSOC, [0], 4) = 0 +0 close(3) = 0 ++0 close(4) = 0 diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/sctp_reset_streams.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/sctp_reset_streams.pkt index 1e6e1969ac3939a4179facc91b64da9e24d439c1..effc8b65aead031c9632d619d39444a71cebf3b6 100644 --- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/sctp_reset_streams.pkt +++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_reconfig/sctp_reset_streams.pkt @@ -1,59 +1,38 @@ --tolerance_usecs=100000 - 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 ++0.0 socket(..., SOCK_STREAM, IPPROTO_SCTP) = 3 + ++0.0 setsockopt(3, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET, {assoc_id=0, assoc_value=SCTP_ENABLE_RESET_STREAM_REQ}, 8) = 0 + +0.0 bind(3, ..., ...) = 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=16, is=16, 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 setsockopt(3, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET, {assoc_id=0, assoc_value=SCTP_ENABLE_RESET_STREAM_REQ}, 8) = 0 - -+0.0 sctp_sendx(3, ..., 1000, ..., 1, {sinfo_stream=3, - sinfo_ssn=3, - sinfo_flags=0, - sinfo_ppid=htonl(1234), - sinfo_context=0, - sinfo_timetolive=0, - sinfo_tsn=2, - sinfo_cumtsn=2, - sinfo_assoc_id=3}, 0) = 1000 -* > sctp: DATA[flgs=BE, len=1016, tsn=1, sid=3, ssn=0, ppid=1234] -+0.0 < sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=1500, gaps=[], dups=[]] - - -+0.0 sctp_sendx(3, ..., 1000, ..., 1, {sinfo_stream=3, - sinfo_ssn=3, - sinfo_flags=0, - sinfo_ppid=htonl(7), - sinfo_context=0, - sinfo_timetolive=0, - sinfo_tsn=1, - sinfo_cumtsn=6, - sinfo_assoc_id=3}, 0) = 1000 -* > sctp: DATA[flgs=BE, len=1016, tsn=2, sid=3, ssn=1, ppid=7] -+0.0 < sctp: SACK[flgs=0, cum_tsn=2, a_rwnd=1500, gaps=[], dups=[]] - -+0.0 sctp_sendx(3, ..., 1000, ..., 1, - {sinfo_stream=3, - sinfo_ssn=3, - sinfo_flags=0, - sinfo_ppid=htonl(7), - sinfo_context=0, - sinfo_timetolive=0, - sinfo_tsn=1, - sinfo_cumtsn=6, - sinfo_assoc_id=3}, 0) = 1000 -* > sctp: DATA[flgs=BE, len=1016, tsn=3, sid=3, ssn=2, ppid=7] -+0.0 < sctp: SACK[flgs=0, cum_tsn=3, a_rwnd=1500, gaps=[], dups=[]] - -+0 setsockopt(3, IPPROTO_SCTP, SCTP_RESET_STREAMS, {srs_flags=SCTP_STREAM_RESET_OUTGOING, - srs_number_streams=1, - srs_stream_list=[0]}, 10) = 0 - -+0 close(3) = 0 ++0.0 listen(3, 1) = 0 ++0.0 < sctp: INIT[flgs=0, tag=1, a_rwnd=1500, os=1, is=1, tsn=1, + ECN_CAPABLE[], + SUPPORTED_EXTENSIONS[types=[0x82]], + COOKIE_PRESERVATIVE[incr=12345], + SUPPORTED_ADDRESS_TYPES[types=[IPv4]]] ++0.0 > sctp: INIT_ACK[flgs=0, tag=2, a_rwnd=..., os=..., is=..., tsn=10, ...] ++0.1 < sctp: COOKIE_ECHO[flgs=0, len=..., val=...] ++0.0 > sctp: COOKIE_ACK[flgs=0] + ++0.0 accept(3, ..., ...) = 4 + ++1.0 write(4, ..., 1000) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=10, sid=0, ssn=0, ppid=0] ++0.1 < sctp: SACK[flgs=0, cum_tsn=10, a_rwnd=1500, gaps=[], dups=[]] + ++1.0 write(4, ..., 1000) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=11, sid=0, ssn=1, ppid=0] ++0.0 < sctp: SACK[flgs=0, cum_tsn=11, a_rwnd=1500, gaps=[], dups=[]] + ++0.1 < sctp: DATA[flgs=BE, len=1016, tsn=1, sid=0, ssn=0, ppid=0] +* > sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=..., gaps=[], dups=[]] ++0.0 read(4, ..., 1000) = 1000 + ++0.1 < sctp: DATA[flgs=BE, len=1016, tsn=2, sid=0, ssn=1, ppid=0] +* > sctp: SACK[flgs=0, cum_tsn=2, a_rwnd=..., gaps=[], dups=[]] ++0.0 read(4, ..., 1000) = 1000 + ++0.0 setsockopt(4, IPPROTO_SCTP, SCTP_RESET_STREAMS, {srs_flags=SCTP_STREAM_RESET_OUTGOING, + srs_number_streams=1, + srs_stream_list=[0]}, 10) = 0