summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Abeni <pabeni@redhat.com>2020-05-15 19:22:17 +0200
committerDavid S. Miller <davem@davemloft.net>2020-05-15 12:30:13 -0700
commit729cd6436f359b6e618c2f14836d419f40444503 (patch)
treedd27101a3b5e26414458c2d0e9180a30d66025bd
parent2f8a397d0a54b59c05e481523ab2a88a63d82d18 (diff)
mptcp: cope better with MP_JOIN failure
Currently, on MP_JOIN failure we reset the child socket, but leave the request socket untouched. tcp_check_req will deal with it according to the 'tcp_abort_on_overflow' sysctl value - by default the req socket will stay alive. The above leads to inconsistent behavior on MP JOIN failure, and bad listener overflow accounting. This patch addresses the issue leveraging the infrastructure just introduced to ask the TCP stack to drop the req on failure. The child socket is not freed anymore by subflow_syn_recv_sock(), instead it's moved to a dead state and will be disposed by the next sock_put done by the TCP stack, so that listener overflow accounting is not affected by MP JOIN failure. Signed-off-by: Paolo Abeni <pabeni@redhat.com> Reviewed-by: Christoph Paasch <cpaasch@apple.com> Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/mptcp/subflow.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 5e03ed8ae899..3cf2eeea9d80 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -478,7 +478,7 @@ create_child:
*/
if (!ctx || fallback) {
if (fallback_is_fatal)
- goto close_child;
+ goto dispose_child;
if (ctx) {
subflow_ulp_fallback(child, ctx);
@@ -507,11 +507,11 @@ 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;
@@ -531,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;