summaryrefslogtreecommitdiffstats
path: root/net/mptcp/subflow.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2020-05-15 12:30:13 -0700
committerDavid S. Miller <davem@davemloft.net>2020-05-15 12:30:13 -0700
commit93d43e58683efd958a0421b932a273df74e0e008 (patch)
treedd27101a3b5e26414458c2d0e9180a30d66025bd /net/mptcp/subflow.c
parentca1c933bcee9393d8a83c6be1093471e0c3b655d (diff)
parent729cd6436f359b6e618c2f14836d419f40444503 (diff)
downloadlinux-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.c18
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;