[PATCH mptcp-next RFC 2/3] mptcp: reject MP_JOIN earlier
"Matthieu Baerts (NGI0)" <[email protected]>
| Newsgroups | dev.linux.lists.mptcp |
|---|---|
| Message-ID | <[email protected]> |
When a SYN + MP_JOIN is received, it is good to check directly if the MP_JOIN is allowed, then checking that later at the establishment of the new subflow. This avoids situations where the 3WHS is done, then the joined subflow is rejected. This changes the behaviour, and the new behaviour is tracked with the MPJoinDisallow MIB counter. TODO: adapt the selftests to be able to run on older kernels: if the new counter is not available, increment syn_ack and syn_rej instead. Signed-off-by: Matthieu Baerts (NGI0) <[email protected]> --- net/mptcp/mib.c | 1 + net/mptcp/mib.h | 1 + net/mptcp/subflow.c | 19 ++++++++++++++++--- tools/testing/selftests/net/mptcp/mptcp_join.sh | 25 +++++++++++++++++-------- 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/net/mptcp/mib.c b/net/mptcp/mib.c index 608cb568897c..988755b41a5a 100644 --- a/net/mptcp/mib.c +++ b/net/mptcp/mib.c @@ -34,6 +34,7 @@ static const struct snmp_mib mptcp_snmp_list[] = { SNMP_MIB_ITEM("MPJoinAckNoCtx", MPTCP_MIB_MPJOINACKNOCTX), SNMP_MIB_ITEM("MPJoinRejected", MPTCP_MIB_JOINREJECTED), SNMP_MIB_ITEM("MPJoinNotEstablished", MPTCP_MIB_MPJOINNOTESTABLISHED), + SNMP_MIB_ITEM("MPJoinDisallow", MPTCP_MIB_MPJOINDISALLOWED), SNMP_MIB_ITEM("MPJoinSynTx", MPTCP_MIB_JOINSYNTX), SNMP_MIB_ITEM("MPJoinSynTxCreatSkErr", MPTCP_MIB_JOINSYNTXCREATSKERR), SNMP_MIB_ITEM("MPJoinSynTxBindErr", MPTCP_MIB_JOINSYNTXBINDERR), diff --git a/net/mptcp/mib.h b/net/mptcp/mib.h index 1ebdb55e9534..e97ee2d952a7 100644 --- a/net/mptcp/mib.h +++ b/net/mptcp/mib.h @@ -29,6 +29,7 @@ enum linux_mptcp_mib_field { MPTCP_MIB_MPJOINACKNOCTX, /* MP_RST: no subflow context on ACK */ MPTCP_MIB_JOINREJECTED, /* The PM rejected the JOIN request */ MPTCP_MIB_MPJOINNOTESTABLISHED, /* MP_RST: JOIN on not-fully-established msk */ + MPTCP_MIB_MPJOINDISALLOWED, /* RST JOIN early if disallowed: fallback/PM */ MPTCP_MIB_JOINSYNTX, /* Sending a SYN + MP_JOIN */ MPTCP_MIB_JOINSYNTXCREATSKERR, /* Not able to create a socket when sending a SYN + MP_JOIN */ MPTCP_MIB_JOINSYNTXBINDERR, /* Not able to bind() the address when sending a SYN + MP_JOIN */ diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index af81ad5e699d..7552abf4c333 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -82,7 +82,8 @@ static void subflow_req_create_thmac(struct mptcp_subflow_request_sock *subflow_ subflow_req->thmac = get_unaligned_be64(hmac); } -static struct mptcp_sock *subflow_token_join_request(struct request_sock *req) +static struct mptcp_sock *subflow_token_join_request(struct request_sock *req, + u8 *reason) { struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req); struct mptcp_sock *msk; @@ -91,12 +92,22 @@ static struct mptcp_sock *subflow_token_join_request(struct request_sock *req) msk = mptcp_token_get_sock(sock_net(req_to_sk(req)), subflow_req->token); if (!msk) { SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINNOTOKEN); + *reason = MPTCP_RST_EMPTCP; + return NULL; + } + + /* Stop it early if the subflow cannot be accepted */ + if (!mptcp_can_accept_new_subflow(msk)) { + SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MPJOINDISALLOWED); + *reason = MPTCP_RST_EPROHIBIT; + sock_put((struct sock *)msk); return NULL; } local_id = mptcp_pm_get_local_id(msk, (struct sock_common *)req); if (local_id < 0) { SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MPJOINNOIDFOUND); + *reason = MPTCP_RST_EMPTCP; sock_put((struct sock *)msk); return NULL; } @@ -217,17 +228,19 @@ static int subflow_check_req(struct request_sock *req, SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_TOKENFALLBACKINIT); } else if (opt_mp_join && listener->request_mptcp) { + u8 reason; + subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq; subflow_req->mp_join = 1; subflow_req->backup = mp_opt.backup; subflow_req->remote_id = mp_opt.join_id; subflow_req->token = mp_opt.token; subflow_req->remote_nonce = mp_opt.nonce; - subflow_req->msk = subflow_token_join_request(req); + subflow_req->msk = subflow_token_join_request(req, &reason); /* Can't fall back to TCP in this case. */ if (!subflow_req->msk) { - subflow_add_reset_reason(skb, MPTCP_RST_EMPTCP); + subflow_add_reset_reason(skb, reason); return -EPERM; } diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh index 18ce7136a2b0..1924ff488c8d 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_join.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh @@ -80,6 +80,7 @@ unset join_ack_no_mpjoin unset join_ack_no_ctx unset join_not_established unset join_no_id_found +unset join_disallowed unset rst_md5sig unset rst_dss @@ -1617,6 +1618,7 @@ chk_join_nr() local ack_no_ctx=${join_ack_no_ctx:-0} local not_established=${join_not_established:-0} local no_id_found=${join_no_id_found:-0} + local disallowed=${join_disallowed:-0} local rc=${KSFT_PASS} local count local with_cookie @@ -1723,6 +1725,13 @@ chk_join_nr() fail_test "got $count JOIN[s] no id found expected $no_id_found" fi + count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinDisallowed") + if [ -n "$count" ] && [ "$count" != "$disallowed" ]; then + rc=${KSFT_FAIL} + print_check "join disallowed" + fail_test "got $count JOIN[s] disallowed expected $disallowed" + fi + print_results "join Rx" ${rc} join_syn_tx="${join_syn_tx:-${syn_nr}}" \ @@ -2202,8 +2211,8 @@ subflows_tests() pm_nl_set_limits $ns2 0 1 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow run_tests $ns1 $ns2 10.0.1.1 - join_syn_rej=1 \ - chk_join_nr 1 1 0 + join_disallowed=1 \ + chk_join_nr 1 0 0 fi # subflow @@ -2232,8 +2241,8 @@ subflows_tests() pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow run_tests $ns1 $ns2 10.0.1.1 - join_syn_rej=1 \ - chk_join_nr 2 2 1 + join_disallowed=1 \ + chk_join_nr 2 1 1 fi # single subflow, dev @@ -4114,8 +4123,8 @@ userspace_tests() pm_nl_set_limits $ns2 1 1 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow run_tests $ns1 $ns2 10.0.1.1 - join_syn_rej=1 \ - chk_join_nr 1 1 0 + join_disallowed=1 \ + chk_join_nr 1 0 0 fi # userspace pm type does not send join @@ -4138,8 +4147,8 @@ userspace_tests() pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow sflags=backup speed=slow \ run_tests $ns1 $ns2 10.0.1.1 - join_syn_rej=1 \ - chk_join_nr 1 1 0 + join_disallowed=1 \ + chk_join_nr 1 0 0 chk_prio_nr 0 0 0 0 fi -- 2.53.0