From nobody Sun Feb 8 19:02:53 2026 Delivered-To: wpasupplicant.patchew@gmail.com Received: by 2002:a05:6638:38c:0:0:0:0 with SMTP id y12csp1899547jap; Thu, 6 Jan 2022 16:20:52 -0800 (PST) X-Google-Smtp-Source: ABdhPJxOCsKQ+PT4itLVkZqzsYPnsxiQbyj8RYBdhXBKs5WCBq09pLEbWfLa7riLp1hVapZJPahS X-Received: by 2002:a05:6a00:1485:b0:4bb:317a:a909 with SMTP id v5-20020a056a00148500b004bb317aa909mr63081907pfu.29.1641514852467; Thu, 06 Jan 2022 16:20:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1641514852; cv=none; d=google.com; s=arc-20160816; b=DIQh0l7s4rQgM0vAVF52qQCyJpy9a6PWSiSPnXCX6Ra7s1sNQ13Jf7MbX3mTOwsBr/ arxC0Ak+AGxGtSsxQXCHbliEdj4LC1eRvxac/07Qg8heWc7uqEl35gp3nzfAiQpl4I/h hEpApItnXxQv0eV+cLj9vnyowtC+f6pMvzuAHI5yQOh6a/9jhGN1VF5UkyvXZCkuk4WP YWvsBifSzb20Y6DMrW4kPV2jRQvVoLLVRzmq+L58BjusjIQ8i2wON1AemaiiOjANZyuZ xJm/Hg6meNGSyfnwr9dIxAmaImqPirmgZ1CKfYSAM+tOyUX/H/qp9YDwqTMoSsSvK1ht TqYA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=T7TgEQ0YNB09ccyXaEYJONuPhBngJiHX1DigYQ4WCJw=; b=W8d7jnenZwVemCDuz50Su211UvNUESlTWQURovwAOtDgLnLF46R7ZBGAM+5sfurlLR iH75NeonFYEgPakXHrUx5vTztHNoZFj2jstJbJsiI7tCKcEy0uD0rMyke4BdjHAQY95r zNvu2InTpLl8UkxTkKPB3HyIv0DBmrGvIVw7txej1BMH8polCUyQo+gBzZmRqp6qYtVK xGJONHCvESWCx7yFz5w2CFM+LWl6Syq3eqhWcaEROVCb2DgRuCTAIm6kaV9cLVK2aLvE hoxWXZLmNBOgxTypmUEgJX2asWlOrqRDITdveRxWdbYflgeNalU/hX203yBzDxNE7Wn8 xEag== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=Yo7P3Av5; spf=pass (google.com: domain of mptcp+bounces-2946-wpasupplicant.patchew=gmail.com@lists.linux.dev designates 147.75.69.165 as permitted sender) smtp.mailfrom="mptcp+bounces-2946-wpasupplicant.patchew=gmail.com@lists.linux.dev"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from sjc.edge.kernel.org (sjc.edge.kernel.org. [147.75.69.165]) by mx.google.com with ESMTPS id v71si3324745pgd.176.2022.01.06.16.20.52 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 06 Jan 2022 16:20:52 -0800 (PST) Received-SPF: pass (google.com: domain of mptcp+bounces-2946-wpasupplicant.patchew=gmail.com@lists.linux.dev designates 147.75.69.165 as permitted sender) client-ip=147.75.69.165; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=Yo7P3Av5; spf=pass (google.com: domain of mptcp+bounces-2946-wpasupplicant.patchew=gmail.com@lists.linux.dev designates 147.75.69.165 as permitted sender) smtp.mailfrom="mptcp+bounces-2946-wpasupplicant.patchew=gmail.com@lists.linux.dev"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sjc.edge.kernel.org (Postfix) with ESMTPS id 06F4C3E0F05 for ; Fri, 7 Jan 2022 00:20:52 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 3C3F42CAC; Fri, 7 Jan 2022 00:20:50 +0000 (UTC) X-Original-To: mptcp@lists.linux.dev Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6059B2C9C for ; Fri, 7 Jan 2022 00:20:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1641514848; x=1673050848; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=pqOieQkFJK/df3FIuxP2JeoTUef4jBU5My1op3wP8ds=; b=Yo7P3Av5Z0zzyI+tXUBahUzbdZYgSM4lNVPoNOlgWs9Mcox22g4QUWn5 SbVYPsU/MkvCFKd1gSyBTnO7QMMBREGFNs4mFOQXmjtqKEEcW4i7hMoEv 1UoKfUQVokDZ2ZN7RwgE7IdJHN0EhC0euKQ3FW1bwPvTM+S9Wuz0IFMXb 76cJLNrDlYEHI30Rl4/79uwnGPkoayZCC1KK5APNFTwZZ/JahQa2+gW1W XEq6k+6UjlB344PMrbJvoLbl2N1E43IBG5tAyUP8lqWIaeom82TZHI1gs rpsncdDP8LKbooyFWwLXe5FxOIHA8It7cr2DcVhWTp5bqP/72ClmjqQHn g==; X-IronPort-AV: E=McAfee;i="6200,9189,10217"; a="329111026" X-IronPort-AV: E=Sophos;i="5.88,268,1635231600"; d="scan'208";a="329111026" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jan 2022 16:20:34 -0800 X-IronPort-AV: E=Sophos;i="5.88,268,1635231600"; d="scan'208";a="618508497" Received: from mjmartin-desk2.amr.corp.intel.com (HELO mjmartin-desk2.intel.com) ([10.209.94.200]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jan 2022 16:20:34 -0800 From: Mat Martineau To: netdev@vger.kernel.org Cc: Paolo Abeni , davem@davemloft.net, kuba@kernel.org, matthieu.baerts@tessares.net, mptcp@lists.linux.dev, Mat Martineau Subject: [PATCH net-next 03/13] mptcp: full disconnect implementation Date: Thu, 6 Jan 2022 16:20:16 -0800 Message-Id: <20220107002026.375427-4-mathew.j.martineau@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220107002026.375427-1-mathew.j.martineau@linux.intel.com> References: <20220107002026.375427-1-mathew.j.martineau@linux.intel.com> Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Paolo Abeni The current mptcp_disconnect() implementation lacks several steps, we additionally need to reset the msk socket state and flush the subflow list. Factor out the needed helper to avoid code duplication. Additionally ensure that the initial subflow is disposed only after mptcp_close(), just reset it at disconnect time. Signed-off-by: Paolo Abeni Signed-off-by: Mat Martineau --- net/mptcp/pm.c | 10 +++-- net/mptcp/protocol.c | 101 ++++++++++++++++++++++++++++++++----------- net/mptcp/protocol.h | 14 ++++++ net/mptcp/token.c | 1 + 4 files changed, 98 insertions(+), 28 deletions(-) diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c index 6ab386ff3294..6b2bfe89d445 100644 --- a/net/mptcp/pm.c +++ b/net/mptcp/pm.c @@ -356,7 +356,7 @@ void mptcp_pm_subflow_chk_stale(const struct mptcp_sock= *msk, struct sock *ssk) } } =20 -void mptcp_pm_data_init(struct mptcp_sock *msk) +void mptcp_pm_data_reset(struct mptcp_sock *msk) { msk->pm.add_addr_signaled =3D 0; msk->pm.add_addr_accepted =3D 0; @@ -371,10 +371,14 @@ void mptcp_pm_data_init(struct mptcp_sock *msk) WRITE_ONCE(msk->pm.remote_deny_join_id0, false); msk->pm.status =3D 0; =20 + mptcp_pm_nl_data_init(msk); +} + +void mptcp_pm_data_init(struct mptcp_sock *msk) +{ spin_lock_init(&msk->pm.lock); INIT_LIST_HEAD(&msk->pm.anno_list); - - mptcp_pm_nl_data_init(msk); + mptcp_pm_data_reset(msk); } =20 void __init mptcp_pm_init(void) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index f6fc0f0f66f0..83f6d6c3e3eb 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -2253,6 +2253,10 @@ bool __mptcp_retransmit_pending_data(struct sock *sk) return true; } =20 +/* flags for __mptcp_close_ssk() */ +#define MPTCP_CF_PUSH BIT(1) +#define MPTCP_CF_FASTCLOSE BIT(2) + /* subflow sockets can be either outgoing (connect) or incoming * (accept). * @@ -2262,22 +2266,37 @@ bool __mptcp_retransmit_pending_data(struct sock *s= k) * parent socket. */ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk, - struct mptcp_subflow_context *subflow) + struct mptcp_subflow_context *subflow, + unsigned int flags) { struct mptcp_sock *msk =3D mptcp_sk(sk); - bool need_push; + bool need_push, dispose_it; =20 - list_del(&subflow->node); + dispose_it =3D !msk->subflow || ssk !=3D msk->subflow->sk; + if (dispose_it) + list_del(&subflow->node); =20 lock_sock_nested(ssk, SINGLE_DEPTH_NESTING); =20 + if (flags & MPTCP_CF_FASTCLOSE) + subflow->send_fastclose =3D 1; + + need_push =3D (flags & MPTCP_CF_PUSH) && __mptcp_retransmit_pending_data(= sk); + if (!dispose_it) { + tcp_disconnect(ssk, 0); + msk->subflow->state =3D SS_UNCONNECTED; + mptcp_subflow_ctx_reset(subflow); + release_sock(ssk); + + goto out; + } + /* if we are invoked by the msk cleanup code, the subflow is * already orphaned */ if (ssk->sk_socket) sock_orphan(ssk); =20 - need_push =3D __mptcp_retransmit_pending_data(sk); subflow->disposable =3D 1; =20 /* if ssk hit tcp_done(), tcp_cleanup_ulp() cleared the related ops @@ -2297,14 +2316,12 @@ static void __mptcp_close_ssk(struct sock *sk, stru= ct sock *ssk, =20 sock_put(ssk); =20 - if (ssk =3D=3D msk->last_snd) - msk->last_snd =3D NULL; - if (ssk =3D=3D msk->first) msk->first =3D NULL; =20 - if (msk->subflow && ssk =3D=3D msk->subflow->sk) - mptcp_dispose_initial_subflow(msk); +out: + if (ssk =3D=3D msk->last_snd) + msk->last_snd =3D NULL; =20 if (need_push) __mptcp_push_pending(sk, 0); @@ -2315,7 +2332,7 @@ void mptcp_close_ssk(struct sock *sk, struct sock *ss= k, { if (sk->sk_state =3D=3D TCP_ESTABLISHED) mptcp_event(MPTCP_EVENT_SUB_CLOSED, mptcp_sk(sk), ssk, GFP_KERNEL); - __mptcp_close_ssk(sk, ssk, subflow); + __mptcp_close_ssk(sk, ssk, subflow, MPTCP_CF_PUSH); } =20 static unsigned int mptcp_sync_mss(struct sock *sk, u32 pmtu) @@ -2533,9 +2550,20 @@ static int __mptcp_init_sock(struct sock *sk) return 0; } =20 -static int mptcp_init_sock(struct sock *sk) +static void mptcp_ca_reset(struct sock *sk) { struct inet_connection_sock *icsk =3D inet_csk(sk); + + tcp_assign_congestion_control(sk); + strcpy(mptcp_sk(sk)->ca_name, icsk->icsk_ca_ops->name); + + /* no need to keep a reference to the ops, the name will suffice */ + tcp_cleanup_congestion_control(sk); + icsk->icsk_ca_ops =3D NULL; +} + +static int mptcp_init_sock(struct sock *sk) +{ struct net *net =3D sock_net(sk); int ret; =20 @@ -2556,12 +2584,7 @@ static int mptcp_init_sock(struct sock *sk) /* fetch the ca name; do it outside __mptcp_init_sock(), so that clone wi= ll * propagate the correct value */ - tcp_assign_congestion_control(sk); - strcpy(mptcp_sk(sk)->ca_name, icsk->icsk_ca_ops->name); - - /* no need to keep a reference to the ops, the name will suffice */ - tcp_cleanup_congestion_control(sk); - icsk->icsk_ca_ops =3D NULL; + mptcp_ca_reset(sk); =20 sk_sockets_allocated_inc(sk); sk->sk_rcvbuf =3D sock_net(sk)->ipv4.sysctl_tcp_rmem[1]; @@ -2720,9 +2743,13 @@ static void __mptcp_destroy_sock(struct sock *sk) sk_stop_timer(sk, &sk->sk_timer); msk->pm.status =3D 0; =20 + /* clears msk->subflow, allowing the following loop to close + * even the initial subflow + */ + mptcp_dispose_initial_subflow(msk); list_for_each_entry_safe(subflow, tmp, &conn_list, node) { struct sock *ssk =3D mptcp_subflow_tcp_sock(subflow); - __mptcp_close_ssk(sk, ssk, subflow); + __mptcp_close_ssk(sk, ssk, subflow, 0); } =20 sk->sk_prot->destroy(sk); @@ -2733,7 +2760,6 @@ static void __mptcp_destroy_sock(struct sock *sk) xfrm_sk_free_policy(sk); =20 sk_refcnt_debug_release(sk); - mptcp_dispose_initial_subflow(msk); sock_put(sk); } =20 @@ -2769,6 +2795,9 @@ static void mptcp_close(struct sock *sk, long timeout) =20 sock_hold(sk); pr_debug("msk=3D%p state=3D%d", sk, sk->sk_state); + if (mptcp_sk(sk)->token) + mptcp_event(MPTCP_EVENT_CLOSED, mptcp_sk(sk), NULL, GFP_KERNEL); + if (sk->sk_state =3D=3D TCP_CLOSE) { __mptcp_destroy_sock(sk); do_cancel_work =3D true; @@ -2779,9 +2808,6 @@ static void mptcp_close(struct sock *sk, long timeout) if (do_cancel_work) mptcp_cancel_work(sk); =20 - if (mptcp_sk(sk)->token) - mptcp_event(MPTCP_EVENT_CLOSED, mptcp_sk(sk), NULL, GFP_KERNEL); - sock_put(sk); } =20 @@ -2815,13 +2841,36 @@ static int mptcp_disconnect(struct sock *sk, int fl= ags) =20 mptcp_do_flush_join_list(msk); =20 + inet_sk_state_store(sk, TCP_CLOSE); + mptcp_for_each_subflow(msk, subflow) { struct sock *ssk =3D mptcp_subflow_tcp_sock(subflow); =20 - lock_sock(ssk); - tcp_disconnect(ssk, flags); - release_sock(ssk); + __mptcp_close_ssk(sk, ssk, subflow, MPTCP_CF_FASTCLOSE); } + + sk_stop_timer(sk, &msk->sk.icsk_retransmit_timer); + sk_stop_timer(sk, &sk->sk_timer); + + if (mptcp_sk(sk)->token) + mptcp_event(MPTCP_EVENT_CLOSED, mptcp_sk(sk), NULL, GFP_KERNEL); + + mptcp_destroy_common(msk); + msk->last_snd =3D NULL; + msk->flags =3D 0; + msk->recovery =3D false; + msk->can_ack =3D false; + msk->fully_established =3D false; + msk->rcv_data_fin =3D false; + msk->snd_data_fin_enable =3D false; + msk->rcv_fastclose =3D false; + msk->use_64bit_ack =3D false; + WRITE_ONCE(msk->csum_enabled, mptcp_is_checksum_enabled(sock_net(sk))); + mptcp_pm_data_reset(msk); + mptcp_ca_reset(sk); + + sk->sk_shutdown =3D 0; + sk_error_report(sk); return 0; } =20 @@ -2961,9 +3010,11 @@ void mptcp_destroy_common(struct mptcp_sock *msk) __mptcp_clear_xmit(sk); =20 /* move to sk_receive_queue, sk_stream_kill_queues will purge it */ + mptcp_data_lock(sk); skb_queue_splice_tail_init(&msk->receive_queue, &sk->sk_receive_queue); __skb_queue_purge(&sk->sk_receive_queue); skb_rbtree_purge(&msk->out_of_order_queue); + mptcp_data_unlock(sk); =20 /* move all the rx fwd alloc into the sk_mem_reclaim_final in * inet_sock_destruct() will dispose it diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index f177936ff67d..1a4ca5a202c8 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -395,6 +395,9 @@ DECLARE_PER_CPU(struct mptcp_delegated_action, mptcp_de= legated_actions); /* MPTCP subflow context */ struct mptcp_subflow_context { struct list_head node;/* conn_list of subflows */ + + char reset_start[0]; + unsigned long avg_pacing_rate; /* protected by msk socket lock */ u64 local_key; u64 remote_key; @@ -442,6 +445,9 @@ struct mptcp_subflow_context { u8 stale_count; =20 long delegated_status; + + char reset_end[0]; + struct list_head delegated_node; /* link into delegated_action, protect= ed by local BH */ =20 u32 setsockopt_seq; @@ -473,6 +479,13 @@ mptcp_subflow_tcp_sock(const struct mptcp_subflow_cont= ext *subflow) return subflow->tcp_sock; } =20 +static inline void +mptcp_subflow_ctx_reset(struct mptcp_subflow_context *subflow) +{ + memset(subflow->reset_start, 0, subflow->reset_end - subflow->reset_start= ); + subflow->request_mptcp =3D 1; +} + static inline u64 mptcp_subflow_get_map_offset(const struct mptcp_subflow_context *subflow) { @@ -713,6 +726,7 @@ void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u8 *msg,= int len, void *hmac); =20 void __init mptcp_pm_init(void); void mptcp_pm_data_init(struct mptcp_sock *msk); +void mptcp_pm_data_reset(struct mptcp_sock *msk); void mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struct sock = *ssk); void mptcp_pm_nl_subflow_chk_stale(const struct mptcp_sock *msk, struct so= ck *ssk); void mptcp_pm_new_connection(struct mptcp_sock *msk, const struct sock *ss= k, int server_side); diff --git a/net/mptcp/token.c b/net/mptcp/token.c index e581b341c5be..f52ee7b26aed 100644 --- a/net/mptcp/token.c +++ b/net/mptcp/token.c @@ -384,6 +384,7 @@ void mptcp_token_destroy(struct mptcp_sock *msk) bucket->chain_len--; } spin_unlock_bh(&bucket->lock); + WRITE_ONCE(msk->token, 0); } =20 void __init mptcp_token_init(void) --=20 2.34.1