diff options
author | David S. Miller <davem@davemloft.net> | 2020-05-15 12:30:13 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-05-15 12:30:13 -0700 |
commit | 93d43e58683efd958a0421b932a273df74e0e008 (patch) | |
tree | dd27101a3b5e26414458c2d0e9180a30d66025bd /net/mptcp/subflow.c | |
parent | ca1c933bcee9393d8a83c6be1093471e0c3b655d (diff) | |
parent | 729cd6436f359b6e618c2f14836d419f40444503 (diff) | |
download | linux-93d43e58683efd958a0421b932a273df74e0e008.tar.gz linux-93d43e58683efd958a0421b932a273df74e0e008.tar.bz2 linux-93d43e58683efd958a0421b932a273df74e0e008.zip |
Merge branch 'mptcp-fix-MP_JOIN-failure-handling'
Paolo Abeni says:
====================
mptcp: fix MP_JOIN failure handling
Currently if we hit an MP_JOIN failure on the third ack, the child socket is
closed with reset, but the request socket is not deleted, causing weird
behaviors.
The main problem is that MPTCP's MP_JOIN code needs to plug it's own
'valid 3rd ack' checks and the current TCP callbacks do not allow that.
This series tries to address the above shortcoming introducing a new MPTCP
specific bit in a 'struct tcp_request_sock' hole, and leveraging that to allow
tcp_check_req releasing the request socket when needed.
The above allows cleaning-up a bit current MPTCP hooking in tcp_check_req().
An alternative solution, possibly cleaner but more invasive, would be
changing the 'bool *own_req' syn_recv_sock() argument into 'int *req_status'
and let MPTCP set it to 'REQ_DROP'.
v1 -> v2:
- be more conservative about drop_req initialization
RFC -> v1:
- move the drop_req bit inside tcp_request_sock (Eric)
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/mptcp/subflow.c')
-rw-r--r-- | net/mptcp/subflow.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 009d5c478062..3cf2eeea9d80 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -470,13 +470,15 @@ create_child: if (child && *own_req) { struct mptcp_subflow_context *ctx = mptcp_subflow_ctx(child); + tcp_rsk(req)->drop_req = false; + /* we need to fallback on ctx allocation failure and on pre-reqs * checking above. In the latter scenario we additionally need * to reset the context to non MPTCP status. */ if (!ctx || fallback) { if (fallback_is_fatal) - goto close_child; + goto dispose_child; if (ctx) { subflow_ulp_fallback(child, ctx); @@ -505,13 +507,14 @@ create_child: owner = mptcp_token_get_sock(ctx->token); if (!owner) - goto close_child; + goto dispose_child; ctx->conn = (struct sock *)owner; if (!mptcp_finish_join(child)) - goto close_child; + goto dispose_child; SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKRX); + tcp_rsk(req)->drop_req = true; } } @@ -528,11 +531,14 @@ out: !mptcp_subflow_ctx(child)->conn)); return child; -close_child: +dispose_child: + tcp_rsk(req)->drop_req = true; tcp_send_active_reset(child, GFP_ATOMIC); - inet_csk_prepare_forced_close(child); + inet_csk_prepare_for_destroy_sock(child); tcp_done(child); - return NULL; + + /* The last child reference will be released by the caller */ + return child; } static struct inet_connection_sock_af_ops subflow_specific; |