From 21c2710176c31a2ec4a4f5b80cffc74546946160 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 10 Nov 2020 17:54:38 +0100 Subject: [PATCH] mptcp: add MPTCP_TCPRST support This adds the 'mp_reset' keyword to allow sending packets with TCPRST suboption. Examples: 1.0 R. 1:1(0) ack 1001 win 264 1.0 R. 1:1(0) ack 1001 win 264 Signed-off-by: Florian Westphal --- gtests/net/packetdrill/lexer.l | 2 ++ gtests/net/packetdrill/mptcp.h | 5 +++ gtests/net/packetdrill/parser.y | 34 ++++++++++++++++++- gtests/net/packetdrill/run_packet.c | 8 +++++ gtests/net/packetdrill/tcp_options.h | 19 +++++++++++ .../net/packetdrill/tcp_options_to_string.c | 5 +++ 6 files changed, 72 insertions(+), 1 deletion(-) diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l index e274bc4b..0556e9ea 100644 --- a/gtests/net/packetdrill/lexer.l +++ b/gtests/net/packetdrill/lexer.l @@ -246,6 +246,7 @@ flag_e return FLAG_E; flag_f return FLAG_F; flag_g return FLAG_G; flag_h return FLAG_H; +flag_t return FLAG_T; no_flags return NO_FLAGS; nokey return NOKEY; mp_join_syn return MP_JOIN_SYN; @@ -261,6 +262,7 @@ list_id return LIST_ID; mp_prio return MP_PRIO; mp_fail return MP_FAIL; mp_fastclose return MP_FASTCLOSE; +mp_reset return MP_TCPRST; rand return RAND; sender_hmac return SENDER_HMAC; hmac return ADD_ADDR_HMAC; diff --git a/gtests/net/packetdrill/mptcp.h b/gtests/net/packetdrill/mptcp.h index 483ebf23..02a3e1a8 100644 --- a/gtests/net/packetdrill/mptcp.h +++ b/gtests/net/packetdrill/mptcp.h @@ -40,6 +40,7 @@ #define MP_PRIO_SUBTYPE 5 // TODO, Change Subflow Priority #define MP_FAIL_SUBTYPE 6 // TODO #define MP_FASTCLOSE_SUBTYPE 7 // TODO => enhancement +#define MP_TCPRST_SUBTYPE 8 /* MPTCP options subtypes length */ @@ -86,6 +87,8 @@ #define TCPOLEN_MP_FAIL 12 // MP_FASTCLOSE #define TCPOLEN_MP_FASTCLOSE 12 +// MP_RESET +#define TCPOLEN_MP_TCPRST 4 // MPTCP Flags #define MP_CAPABLE_FLAGS 1 #define MP_CAPABLE_FLAGS_CS 129 //With checksum @@ -107,6 +110,8 @@ #define MPTCP_VER_DEFAULT MPTCPV1 +#define MP_TCPRST_FLAG_T 1 + //SUBFLOW states #define ESTABLISHED 1 //for Subflow state #define PRE_ESTABLISHED 0 //Subflow state diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index 66ae0b61..da7ee908 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -845,7 +845,7 @@ struct tcp_option *dss_do_dsn_dack( int dack_type, int dack_val, %token U32 U64 PTR %token ACK ECR EOL MSS NOP SACK SACKOK TIMESTAMP VAL WIN WSCALE %token URG MD5 FAST_OPEN FAST_OPEN_EXP -%token MP_CAPABLE MP_CAPABLE_NO_CS MP_FASTCLOSE FLAG_A FLAG_B FLAG_C FLAG_D FLAG_E FLAG_F FLAG_G FLAG_H NO_FLAGS +%token MP_CAPABLE MP_CAPABLE_NO_CS MP_FASTCLOSE FLAG_A FLAG_B FLAG_C FLAG_D FLAG_E FLAG_F FLAG_G FLAG_H FLAG_T NO_FLAGS %token MPCAPABLE V0 V1 NOKEY MPCDATALEN %token MP_JOIN_SYN MP_JOIN_ACK MP_JOIN_SYN_ACK %token DSS DACK4 DSN4 DACK8 DSN8 FIN SSN DLL NOCS CKSUM ADDR ADDRESS_ID BACKUP TOKEN AUTO RAND @@ -854,6 +854,7 @@ struct tcp_option *dss_do_dsn_dack( int dack_type, int dack_val, %token ADD_ADDRESS ADD_ADDR_IPV4 ADD_ADDR_IPV6 PORT MP_FAIL %token REMOVE_ADDRESS ADDRESSES_ID LIST_ID %token MP_PRIO +%token MP_TCPRST %token TOS FLAGS FLOWLABEL %token ECT0 ECT1 CE ECT01 NO_ECN %token IPV4 IPV6 ICMP UDP RAW GRE MTU ID @@ -883,6 +884,8 @@ struct tcp_option *dss_do_dsn_dack( int dack_type, int dack_val, %type opt_mpls_stack_bottom %type opt_icmp_mtu fin ssn dll dss_checksum %type mp_capable_no_cs is_backup address_id rand port +%type mptcprst_reason mptcprst_flags_list mptcprst_flags mptcprst_flag + %type flag_a flag_b flag_c flag_d flag_e flag_f flag_g flag_h no_flags %type mpc_ver mpc_flags_list mpc_flags mpc_flag mpc_keys mpc_data %type gre_flags_list gre_flags gre_flag @@ -2048,6 +2051,27 @@ mpc_data } ; +mptcprst_reason +: INTEGER { + if(!is_valid_u8($1)) + semantic_error("mp_reset: reason code should be a 8 bits unsigned integer."); + $$ = $1; +} + +mptcprst_flags_list +: FLAGS '[' mptcprst_flags ']' { $$ = $3; } +| { $$ = 0; } +; + +mptcprst_flags +: mptcprst_flag { $$ = $1; } +; + +mptcprst_flag +: NO_FLAGS { $$ = 0; } +| FLAG_T { $$ = MP_TCPRST_FLAG_T; } +; + tcp_option : NOP { $$ = tcp_option_new(TCPOPT_NOP, 1); } | EOL { $$ = tcp_option_new(TCPOPT_EOL, 1); } @@ -2302,6 +2326,14 @@ tcp_option $$->data.mp_prio.flags = $2; $$->data.mp_capable.subtype = MP_PRIO_SUBTYPE; } +| MP_TCPRST mptcprst_reason mptcprst_flags_list { + $$ = tcp_option_new(TCPOPT_MPTCP, TCPOLEN_MP_TCPRST); + $$->data.mp_tcprst.reason = $2; + $$->data.mp_tcprst.flag_transient = ($3 & MP_TCPRST_FLAG_T); + $$->data.mp_tcprst.reserved_bits = ZERO_RESERVED; + + $$->data.mp_capable.subtype = MP_TCPRST_SUBTYPE; +} | MP_FAIL dsn { if($2.type == 4) semantic_error("Value assigned to a MP_FAIL option is not a valid unsigned 64 bits number."); diff --git a/gtests/net/packetdrill/run_packet.c b/gtests/net/packetdrill/run_packet.c index d2b916a3..67fde65d 100644 --- a/gtests/net/packetdrill/run_packet.c +++ b/gtests/net/packetdrill/run_packet.c @@ -1237,6 +1237,14 @@ bool same_mptcp_opt(struct tcp_option *opt_a, struct tcp_option *opt_b, struct p if(opt_a->data.mp_fastclose.receiver_key != opt_b->data.mp_fastclose.receiver_key) return false; break; + case MP_TCPRST_SUBTYPE: + if(opt_a->data.mp_tcprst.reason != opt_b->data.mp_tcprst.reason) + return false; + if(opt_a->data.mp_tcprst.flag_transient != opt_b->data.mp_tcprst.flag_transient) + return false; + if(opt_a->data.mp_tcprst.reserved_bits != opt_b->data.mp_tcprst.reserved_bits) + return false; + break; default: return false; } diff --git a/gtests/net/packetdrill/tcp_options.h b/gtests/net/packetdrill/tcp_options.h index e82e3d0c..ba8d8755 100644 --- a/gtests/net/packetdrill/tcp_options.h +++ b/gtests/net/packetdrill/tcp_options.h @@ -376,6 +376,25 @@ struct tcp_option { +---------------------------------------------------------------+ */ } __packed mp_fastclose; + struct { + #if __BYTE_ORDER == __LITTLE_ENDIAN + __u8 flag_transient:1, reserved_bits:3; + __u8 subtype:4; + __u8 reason; + #elif __BYTE_ORDER == __BIG_ENDIAN + __u8 subtype:4; + __u8 reserved_bits:3, flag_transient:1; + __u8 reason; + #else + #error "Adjust your defines" + #endif + /* + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +---------------+---------------+-------+-----------------------+ + | Kind | Length |Subtype|U V W T| Reason | + +---------------+---------------+-------+-----------------------+ + */ + } __packed mp_tcprst; /*******END MPTCP options*********/ } data; } __packed; diff --git a/gtests/net/packetdrill/tcp_options_to_string.c b/gtests/net/packetdrill/tcp_options_to_string.c index d8d772c4..716497a9 100644 --- a/gtests/net/packetdrill/tcp_options_to_string.c +++ b/gtests/net/packetdrill/tcp_options_to_string.c @@ -473,6 +473,11 @@ int tcp_options_to_string(struct packet *packet, fprintf(s, "mp_fastclose receiver key: %lu", (unsigned long)option->data.mp_fastclose.receiver_key); break; + case MP_TCPRST_SUBTYPE: + fprintf(s, "mp_reset %u", option->data.mp_tcprst.reason); + if (option->data.mp_tcprst.flag_transient) + fprintf(s, "flags [ flag_t ]"); + break; default: fprintf(s, "unknown MPTCP subtype"); break;