From nobody Thu Nov 5 07:28:35 2026 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1792720745; b=soDLKPb6sUwYLjsg/KahHygR0wp76qA+Mcdgmvs5UFyngzpozXmRNkWbMWLcNxrHifAA /V9/Z+Ejbec+jN87fgFqJYYo2bnPgdCJtE0gje8kOKSD2lpJZgbyHISS54oVydNh8JkkX 61R0Bp/C9kzYHW3D6xV/3W9aa7W5uV3Ufap/5SbvMcODlrUHZVMjQcDsPIl0o/TyDzh9E Gb9tDSYaT/cbpkkpeadTgjmnYInDfDeYQWQYuWO1tOQGhuIM+3F7zT0MVBlTZkbMFzF2u 2yYvOGgXyW4fbFOmnO1SDxBDt69vOFvER2nEZm2aUJUnaL7osBJXixg0li63LxZBqeQ== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1792720745; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=1J8C7pphSK2zVga48ZXLypGHUwLsv9JZ0n5GsGZOvyg=; b=ldUU/2d1kGYJ1zchG/3WShgY1Q3vguhVD7pOJuWecK7JYLm/aDbqH6+Hh3p1WH49fleh aFmeg//c9CEq2jg+C1yCQfq1dE7n8baBeZ1sgamXq/2S6JHNpzvjxm20HAMZASGJzJS8O la+yxjvUbZAera7FdrVG0gQSIxXptUQpCigYOM8HsqlOEcyg3KKmeW+OVxrt+TugOG+8n 5qDSNkZ6yspHxwXNcpQWODEiXwIag9QpbddrMi5ySF64b+hfTPXA8+QeZPfps3v3UHtH9 qMouvgxAAS555D91k6ILpqTH6HKb56drewVwTrJEjpytk/PYBpJdYvf1sPKhCLQqVzQ== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=OmNADHpy; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 45968606A319 for ; Fri, 23 Oct 2026 01:59:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=OmNADHpy Received: by smtp.kernel.org (Postfix) with ESMTPSA id C38E41F01828; Fri, 23 Oct 2026 01:59:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1792720744; bh=1J8C7pphSK2zVga48ZXLypGHUwLsv9JZ0n5GsGZOvyg=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=OmNADHpyh7o8D3pZ3lhMcOTCt2b6YibxPI81BQ1N4gJhUSnfd/HOabTh7merUzZ8M QbEyP2RTojWBiVAfl25LeDeq9e/kZ0Cz2sNa3oeSQ1kj9GaYbJqEJmKby6hPOWlKKW BFlU0RLHNAk7T1KkJBYqwFWs8+23Ov09dEo/Dm3TEKpC2vixKanmCjik0JNVGeYtSW Ij5TZgp9CDJ63l+qOcBrdMDfFmjs/fxArwLUqrRosRTMOqI5kTL/TlUgw7qliGalri lMYmWSpfyEyt7NfihbTkKlCtX7qTitnJ0r8A0xr14NRSJ1uN498DMtNcLH9h2PORkD jkw7YYxLKUYIw== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Paolo Abeni , Geliang Tang Subject: [PATCH mptcp-next v15 01/11] mptcp: drop the mptcp_ooo_try_coalesce() helper Date: Fri, 23 Oct 2026 09:58:42 +0800 Message-ID: <77f2a6bc17dd336ab7c06d3be1bdc67d148bb530.1792718041.git.tanggeliang@kylinos.cn> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Paolo Abeni It's used to save an additional comparison for in-order skbs, but is also a barrier to remove CB offset. Remove the helper, let __mptcp_try_coalesce() always perform the sequence check and remove duplicate checks from the callers. Co-developed-by: Geliang Tang Signed-off-by: Geliang Tang Signed-off-by: Paolo Abeni --- net/mptcp/protocol.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 02a4f479d9d8..528a72da646c 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -167,7 +167,8 @@ static bool __mptcp_try_coalesce(struct sock *sk, struc= t sk_buff *to, { int limit =3D READ_ONCE(sk->sk_rcvbuf); =20 - if (unlikely(MPTCP_SKB_CB(to)->cant_coalesce) || + if (MPTCP_SKB_CB(from)->map_seq !=3D MPTCP_SKB_CB(to)->end_seq || + unlikely(MPTCP_SKB_CB(to)->cant_coalesce) || MPTCP_SKB_CB(from)->offset || ((to->len + from->len) > (limit >> 3)) || !skb_try_coalesce(to, from, fragstolen, delta)) @@ -200,15 +201,6 @@ static bool mptcp_try_coalesce(struct sock *sk, struct= sk_buff *to, return true; } =20 -static bool mptcp_ooo_try_coalesce(struct mptcp_sock *msk, struct sk_buff = *to, - struct sk_buff *from) -{ - if (MPTCP_SKB_CB(from)->map_seq !=3D MPTCP_SKB_CB(to)->end_seq) - return false; - - return mptcp_try_coalesce((struct sock *)msk, to, from); -} - /* "inspired" by tcp_rcvbuf_grow(), main difference: * - mptcp does not maintain a msk-level window clamp * - returns true when the receive buffer is actually updated @@ -348,7 +340,7 @@ static void mptcp_data_queue_ofo(struct mptcp_sock *msk= , struct sk_buff *skb) /* with 2 subflows, adding at end of ooo queue is quite likely * Use of ooo_last_skb avoids the O(Log(N)) rbtree lookup. */ - if (mptcp_ooo_try_coalesce(msk, msk->ooo_last_skb, skb)) { + if (mptcp_try_coalesce(sk, msk->ooo_last_skb, skb)) { MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_OFOMERGE); MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_OFOQUEUETAIL); return; @@ -394,7 +386,7 @@ static void mptcp_data_queue_ofo(struct mptcp_sock *msk= , struct sk_buff *skb) MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DUPDATA); goto merge_right; } - } else if (mptcp_ooo_try_coalesce(msk, skb1, skb)) { + } else if (mptcp_try_coalesce(sk, skb1, skb)) { MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_OFOMERGE); return; } @@ -777,8 +769,7 @@ static void __mptcp_add_backlog(struct sock *sk, if (!list_empty(&msk->backlog_list)) tail =3D list_last_entry(&msk->backlog_list, struct sk_buff, list); =20 - if (tail && MPTCP_SKB_CB(skb)->map_seq =3D=3D MPTCP_SKB_CB(tail)->end_seq= && - ssk =3D=3D tail->sk && + if (tail && ssk =3D=3D tail->sk && __mptcp_try_coalesce(sk, tail, skb, &fragstolen, &delta)) { skb->truesize -=3D delta; kfree_skb_partial(skb, fragstolen); @@ -902,7 +893,7 @@ static bool __mptcp_ofo_queue(struct mptcp_sock *msk) =20 end_seq =3D MPTCP_SKB_CB(skb)->end_seq; tail =3D skb_peek_tail(&sk->sk_receive_queue); - if (!tail || !mptcp_ooo_try_coalesce(msk, tail, skb)) { + if (!tail || !mptcp_try_coalesce(sk, tail, skb)) { int delta =3D msk->ack_seq - MPTCP_SKB_CB(skb)->map_seq; =20 /* skip overlapping data, if any */ --=20 2.55.0 From nobody Thu Nov 5 07:28:35 2026 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1792720747; b=ncPuHQmNGiaXUeLfWb79SE79bZTfdqrxWaXOFwt5z0fjkvGFtTkOR5pKkcZS8ULdiybj 2lgZ6JT/CoxU10VHezOkY4OWI8YyyLS1EXjIjNh+nqV1CBzIgBNBJCnNb4s/8YNTseHVn W4FDe/jPfzAUIVLxDh562jqLxTHa7brRjB3FrmOEmQXcXDTirDWbrIPi5F5lKRD5uXkeG kotsvj33f8S+kk0qgybAernEIEiNQ9hG3l6D9aop6uXXldsinjV3sLeBWKiWjic+una+v hvK2QLgLw5rRxS+v6A485ilMcBDhfMG+I7XArvOsZEWDVdjtUmYq0nDHgK60ajc7Rrw== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1792720747; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=Azi9DImrTKo7o5xlUMXNYmvJJm4gGEk66EwLDxIxeKg=; b=nZYjU53qAo3j5HQcjDCc3TOsUDdZlh1/taRsDVs+aK1KMLgfygP3BSfVr6IifGzfYI3q vO3iPPR9RH29CqPJjE1w1GSTZqfGJ9fDMTcorGrmm3BVeGu2iOW6EIb1TzuE6ICN9phDl cMJbzxO7ZTljaOqxlMqDUO6RdZEaU+CFetO3PBfr/mWNRhkq/SHDcxSPzeHgoCMd52uio bwOY/C6Dobu7NnqgJYBkzrepvLt9ia4lYWLeJ8MpevB6di5rZmhbY0iI+VGdacaG7krVn ESS7A8FZuP6jinXALl10kPtDF7D7ooyhlLpPaz9Dbnhf5XYWkztujgoZ4u1tDDuSJ9Q== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=Q4NYug0E; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D3383606A31E for ; Fri, 23 Oct 2026 01:59:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=Q4NYug0E Received: by smtp.kernel.org (Postfix) with ESMTPSA id 622011F031E0; Fri, 23 Oct 2026 01:59:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1792720746; bh=Azi9DImrTKo7o5xlUMXNYmvJJm4gGEk66EwLDxIxeKg=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Q4NYug0E4aN6CRdnBAYxy+Mog7GcRqYnIIo1UoaUhKqn0SqqMyYR0S/3Qij8zd7dl Rr55e/QOFI2lmC6OpISGryy7ce/JnkCcof9kZa9aKDsCGaEAAyhRch2b0mDbs8We31 JsXMNCY7cq3xTjbFCYhGWiV0Gdxkf/S63X3myemNmtCigQ5Oo4rwiQBucEL2F8AqDb YzqnaQ7P32Y1g8y9lcNedTPs8+6F0IwLVPHGV8X/+rLSnSVHb6RgFnXS89RfbcwVg7 FxeyyOeN/beQqan7XjP77beTG0ESCmv5GNFDj7Ir3pKviRA1cgQQBkpa31Gh3KK9u6 aN3681TBxu98w== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Paolo Abeni , Geliang Tang Subject: [PATCH mptcp-next v15 02/11] mptcp: drop the cant_coalesce CB field Date: Fri, 23 Oct 2026 09:58:43 +0800 Message-ID: <25f42bae1af43649a5c89ca10cfe0d962941c6f7.1792718041.git.tanggeliang@kylinos.cn> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Paolo Abeni Such field is used to ensure in-sequence processing in case of fastopen. Instead let's perform synchronization of the fastopen skb sequence when the IASN becomes available with the 3rd ack. When the `cant_coalesce` field has been introduced, commit f03afb3aeb9d ("mptcp: drop __mptcp_fastopen_gen_msk_ackseq()") noted that updating the already queued skb for passive fastopen socket at 3rd ack time would be difficult and race prone. The main point is that such update don't need to be synchronously performed at 3rd ack time, but is sufficient to perform it before the next segment is introduced into the msk. To such extent, add an explicit test in __mptcp_move_skb(). Performance wise this trades a conditional in the fast path - in __mptcp_try_coalesce() - with a similar one in __mptcp_move_skb() and a couple more in slow paths. After this change the user-space will always observe consistent sequence numbers in the receive queue, even in the TFO dummy mapping case. Co-developed-by: Geliang Tang Signed-off-by: Geliang Tang Signed-off-by: Paolo Abeni --- net/mptcp/fastopen.c | 6 ++++-- net/mptcp/protocol.c | 46 +++++++++++++++++++++++++++++++++++++++++--- net/mptcp/protocol.h | 4 +++- net/mptcp/subflow.c | 10 ++++++++++ 4 files changed, 60 insertions(+), 6 deletions(-) diff --git a/net/mptcp/fastopen.c b/net/mptcp/fastopen.c index f717750906ff..e18b31028e7e 100644 --- a/net/mptcp/fastopen.c +++ b/net/mptcp/fastopen.c @@ -9,6 +9,7 @@ void mptcp_fastopen_subflow_synack_set_params(struct mptcp_subflow_context= *subflow, struct request_sock *req) { + struct mptcp_sock *msk; struct sock *sk, *ssk; struct sk_buff *skb; struct tcp_sock *tp; @@ -49,15 +50,16 @@ void mptcp_fastopen_subflow_synack_set_params(struct mp= tcp_subflow_context *subf MPTCP_SKB_CB(skb)->end_seq =3D 0; MPTCP_SKB_CB(skb)->offset =3D 0; MPTCP_SKB_CB(skb)->has_rxtstamp =3D has_rxtstamp; - MPTCP_SKB_CB(skb)->cant_coalesce =3D 1; =20 mptcp_data_lock(sk); DEBUG_NET_WARN_ON_ONCE(sock_owned_by_user_nocheck(sk)); =20 + msk =3D mptcp_sk(sk); + msk->rcvd_dummy_seq =3D true; mptcp_borrow_fwdmem(sk, skb); skb_set_owner_r(skb, sk); __skb_queue_tail(&sk->sk_receive_queue, skb); - mptcp_sk(sk)->bytes_received +=3D skb->len; + msk->bytes_received +=3D skb->len; =20 sk->sk_data_ready(sk); =20 diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 528a72da646c..96deaed109a2 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -168,7 +168,6 @@ static bool __mptcp_try_coalesce(struct sock *sk, struc= t sk_buff *to, int limit =3D READ_ONCE(sk->sk_rcvbuf); =20 if (MPTCP_SKB_CB(from)->map_seq !=3D MPTCP_SKB_CB(to)->end_seq || - unlikely(MPTCP_SKB_CB(to)->cant_coalesce) || MPTCP_SKB_CB(from)->offset || ((to->len + from->len) > (limit >> 3)) || !skb_try_coalesce(to, from, fragstolen, delta)) @@ -430,7 +429,6 @@ static void mptcp_init_skb(struct sock *ssk, struct sk_= buff *skb, int offset, MPTCP_SKB_CB(skb)->end_seq =3D MPTCP_SKB_CB(skb)->map_seq + copy_len; MPTCP_SKB_CB(skb)->offset =3D offset; MPTCP_SKB_CB(skb)->has_rxtstamp =3D has_rxtstamp; - MPTCP_SKB_CB(skb)->cant_coalesce =3D 0; =20 __skb_unlink(skb, &ssk->sk_receive_queue); =20 @@ -438,6 +436,27 @@ static void mptcp_init_skb(struct sock *ssk, struct sk= _buff *skb, int offset, skb_dst_drop(skb); } =20 +/* Caller must hold the msk data lock */ +void __mptcp_sync_rcv_sequence(struct sock *sk) +{ + struct mptcp_sock *msk =3D mptcp_sk(sk); + struct sk_buff *skb; + u32 offset; + + if (likely(!msk->rcvd_dummy_seq)) + return; + + /* User space can have already received the TFO skb. */ + msk->rcvd_dummy_seq =3D false; + skb =3D skb_peek_tail(&sk->sk_receive_queue); + if (!skb) + return; + + offset =3D MPTCP_SKB_CB(skb)->offset; + MPTCP_SKB_CB(skb)->map_seq =3D msk->ack_seq - skb->len + offset; + MPTCP_SKB_CB(skb)->end_seq =3D msk->ack_seq; +} + static bool __mptcp_move_skb(struct sock *sk, struct sk_buff *skb) { u64 copy_len =3D MPTCP_SKB_CB(skb)->end_seq - MPTCP_SKB_CB(skb)->map_seq; @@ -446,6 +465,17 @@ static bool __mptcp_move_skb(struct sock *sk, struct s= k_buff *skb) =20 mptcp_borrow_fwdmem(sk, skb); =20 + if (test_and_clear_bit(MPTCP_SYNC_SEQ, &msk->cb_flags)) { + /* Ensure we see the updated ack_seq after seeing the flag */ + smp_rmb(); + + /* Be sure to sync the eventual fastopen dummy mapping before + * any other skb lands into the msk. + */ + if (unlikely(msk->rcvd_dummy_seq)) + __mptcp_sync_rcv_sequence(sk); + } + if (MPTCP_SKB_CB(skb)->map_seq =3D=3D msk->ack_seq) { /* in sequence */ insert: @@ -2394,11 +2424,14 @@ static unsigned int mptcp_inq_hint(const struct soc= k *sk) { const struct mptcp_sock *msk =3D mptcp_sk(sk); const struct sk_buff *skb; + u64 hint_val; =20 skb =3D skb_peek(&sk->sk_receive_queue); if (skb) { - u64 hint_val =3D READ_ONCE(msk->ack_seq) - MPTCP_SKB_CB(skb)->map_seq; + if (test_bit(MPTCP_SYNC_SEQ, &msk->cb_flags)) + return skb->len - MPTCP_SKB_CB(skb)->offset; =20 + hint_val =3D READ_ONCE(msk->ack_seq) - MPTCP_SKB_CB(skb)->map_seq; if (hint_val >=3D INT_MAX) return INT_MAX; =20 @@ -3930,6 +3963,13 @@ static void mptcp_release_cb(struct sock *sk) __mptcp_error_report(sk); if (__test_and_clear_bit(MPTCP_SYNC_SNDBUF, &msk->cb_flags)) __mptcp_sync_sndbuf(sk); + if (__test_and_clear_bit(MPTCP_SYNC_SEQ, &msk->cb_flags)) { + /* Ensure we see the updated ack_seq after seeing + * the flag + */ + smp_rmb(); + __mptcp_sync_rcv_sequence(sk); + } } } =20 diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 3be60da12924..609b572f8eb0 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -126,13 +126,13 @@ #define MPTCP_FLUSH_JOIN_LIST 5 #define MPTCP_SYNC_STATE 6 #define MPTCP_SYNC_SNDBUF 7 +#define MPTCP_SYNC_SEQ 8 =20 struct mptcp_skb_cb { u64 map_seq; u64 end_seq; u32 offset; u8 has_rxtstamp; - u8 cant_coalesce; }; =20 #define MPTCP_SKB_CB(__skb) ((struct mptcp_skb_cb *)&((__skb)->cb[0])) @@ -327,6 +327,7 @@ struct mptcp_sock { u32 token; unsigned long flags; unsigned long cb_flags; + bool rcvd_dummy_seq; bool recovery; /* closing subflow write queue reinjected */ bool can_ack; bool fully_established; @@ -1193,6 +1194,7 @@ void mptcp_event_pm_listener(const struct sock *ssk, enum mptcp_event_type event); bool mptcp_userspace_pm_active(const struct mptcp_sock *msk); =20 +void __mptcp_sync_rcv_sequence(struct sock *sk); void mptcp_fastopen_subflow_synack_set_params(struct mptcp_subflow_context= *subflow, struct request_sock *req); int mptcp_pm_genl_fill_addr(struct sk_buff *msg, diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 78e886b20258..bf6ba235c268 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -515,6 +515,8 @@ static void subflow_set_remote_key(struct mptcp_sock *m= sk, struct mptcp_subflow_context *subflow, const struct mptcp_options_received *mp_opt) { + struct sock *sk =3D (struct sock *)msk; + /* active MPC subflow will reach here multiple times: * at subflow_finish_connect() time and at 4th ack time */ @@ -533,6 +535,14 @@ static void subflow_set_remote_key(struct mptcp_sock *= msk, WRITE_ONCE(msk->ack_seq, subflow->iasn); WRITE_ONCE(msk->can_ack, true); atomic64_set(&msk->rcv_wnd_sent, subflow->iasn); + + if (!sock_owned_by_user(sk)) { + __mptcp_sync_rcv_sequence(sk); + } else { + /* Ensure ack_seq is visible before setting the flag */ + smp_wmb(); + set_bit(MPTCP_SYNC_SEQ, &msk->cb_flags); + } } =20 static void mptcp_propagate_state(struct sock *sk, struct sock *ssk, --=20 2.55.0 From nobody Thu Nov 5 07:28:35 2026 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1792720749; b=iEUzWHh1m7P7babQLkJeWdBjJr/5rpYNluiAjhQhqjDjIDIFGJDTPi/WK4Q55EFRI+dd Ndv9BFgHeEm72m0FEgvGpnUcQbKi0FGHY0qSlf1JqNmS6Ro87CfHBdd5hLMEBiTiPkvam A7JZtpbaDPZKNCs8fGU32ullP3ZTzdhevnqhyKfeISi0rXVVmhc4eCAqtul+wit4cLU1b CUEr8e/k3BUqca2UukAYrk/gUTRhJBk5o+wnf6Q0+5a4nzOO3Dh90pqvtRk2PNslXEkqm 5ml9u9HD6JWobSveK7nQwAw4gQrnTppI7YevOdjG6SXQsjke/gPgMW52wkzJVpTAMBg== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1792720749; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=0h5dLs/38+krHQ/Y0ZIpvbWilzTpEbQRt6e3N63d6ks=; b=4zrix9rPVbyjX+1o4O7BeCgd9smC9RpSH6gNr5h+pCVQYS32IIQ+TRg8lGdZ/5f6r8yy VK7Zgny7dHh5a9UaTVWoemp5MXJCq8YnpgvCrqsV3sHOwT8pYXCc5LFdKwscuCLQwR/AG gs7YcpSwAQshDLYxQ8zG+r/1xxaqngHetZ/UDrNuG2zk6M4K99z3tqF6Ds1Ttykztc0ih zIm8fRTdrq594n+cwEUQlm1kMIsZBwxDn1R8qk/s+dl973Bzbss4h/jS43nxrkfRNZP4G XIBKNauSVoePdYbCWldKOK0RLr5S0Wra/8p8lnH2QQCRX0OzHTpLbjIzT6TVjRMr0XQ== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=RClYpzqC; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AA4E2606A31D for ; Fri, 23 Oct 2026 01:59:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=RClYpzqC Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2E6FE1F01828; Fri, 23 Oct 2026 01:59:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1792720748; bh=0h5dLs/38+krHQ/Y0ZIpvbWilzTpEbQRt6e3N63d6ks=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=RClYpzqCtgknlPbfEA/pA26qzD52iYWi49nTGbjbogh+06b/oSw9Q0X4/qaUQepk9 Nma+wESQsVYc4hA7/GOJMxi/EqcYae6aHA2QBFtMV7IhZbdJjnPkI930OsvBeCSTnB 9sf5WKhm3PsAKWc1rB+PQhIJr1Hbj2VXpNSOPnxV22bUwv1BGQLmgyg315upIi2EiJ bnfpTSzsxW5YEXaw0vBzOlxHK0yS1iUPVbEOvThDo+KNa8KmfR3hS6Zx8dHDirfa27 F8u/BodtAN2/s+f/dMtTcYhFRbO7PiTR63a4i64ZoFuCl+K2D9ydd+DkTco8m4xEdz 2hO/4Oe8yNZlQ== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Paolo Abeni , Geliang Tang Subject: [PATCH mptcp-next v15 03/11] mptcp: remove CB offset field Date: Fri, 23 Oct 2026 09:58:44 +0800 Message-ID: <8f0a05ab4c45b9ff763ac81eaf85b2eb8148d2cb.1792718041.git.tanggeliang@kylinos.cn> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Paolo Abeni Instead, use a new msk-level field to track the bytes already consumed inside each skb, carrying the amount of bytes already copied to user-space, alike what TCP is already doing. The newly introduce `copied_seq` field is always accessed under the msk socket lock, delegating the synchronization with IASN to the msk release CB, when the socket is owned by the user-space at remote key reception time. Such synchronization preserves any partial progress (copy) made on the TFO packet. Note that the explicit synchronization in __mptcp_move_skb() is needed to ensure that the TFO skb in the receive queue got its map_seq synched before the next skb lands into the receive queue when spooling the backlog at mptcp_release_cb() time, as the release CB synchronization will happen later. Prior to this patch, the TFO skb dummy mapping (map_seq =3D -(u32)skb->len, zero-extended to u64) caused mptcp_inq_hint() to compute a wrapped ack_seq - map_seq, so SIOCINQ and TCP_CM_INQ returned INT_MAX before the MPC ACK. This patch fixes that behaviour through both the -(u64)skb->len sign fix and the new ack_seq - copied_seq hint. Overall this simplifies a bit the __mptcp_recvmsg_mskq(), mptcp_inq_hint() and the __mptcp_move_skb() code and will also make possible the next patch. Initialize MPTCP sequence space to 0 in mptcp_propagate_state() when mp_opt is NULL, ensuring SKB's map_seq starts from 0 to match msk->copied_seq and prevent offset calculation underflow in fallback mode. The writes are safe without sock_owned_by_user() deferral because mptcp_propagate_state() already holds mptcp_data_lock(). Note: mptcp_iasn() assumes ack_seq and bytes_received advance in lockstep. If mptcp_check_data_fin() increments ack_seq for a DATA_FIN before the deferred SYNC_SEQ sync runs, copied_seq ends up one byte past the real IASN. In practice this requires a DATA_FIN to arrive before the MPC third ACK on a passive TFO socket, which cannot happen because the connection is not yet established. Co-developed-by: Geliang Tang Signed-off-by: Geliang Tang Signed-off-by: Paolo Abeni --- net/mptcp/fastopen.c | 9 ++-- net/mptcp/protocol.c | 107 +++++++++++++++++++------------------------ net/mptcp/protocol.h | 8 +++- net/mptcp/subflow.c | 13 ++++++ 4 files changed, 74 insertions(+), 63 deletions(-) diff --git a/net/mptcp/fastopen.c b/net/mptcp/fastopen.c index e18b31028e7e..421a50a85547 100644 --- a/net/mptcp/fastopen.c +++ b/net/mptcp/fastopen.c @@ -45,10 +45,11 @@ void mptcp_fastopen_subflow_synack_set_params(struct mp= tcp_subflow_context *subf subflow->ssn_offset +=3D skb->len; has_rxtstamp =3D TCP_SKB_CB(skb)->has_rxtstamp; =20 - /* Only the sequence delta is relevant */ - MPTCP_SKB_CB(skb)->map_seq =3D -skb->len; + /* The TFO segment data sits before the IASN; before receiving + * the remote key, IASN is assumed being 0. + */ + MPTCP_SKB_CB(skb)->map_seq =3D -(u64)skb->len; MPTCP_SKB_CB(skb)->end_seq =3D 0; - MPTCP_SKB_CB(skb)->offset =3D 0; MPTCP_SKB_CB(skb)->has_rxtstamp =3D has_rxtstamp; =20 mptcp_data_lock(sk); @@ -56,6 +57,8 @@ void mptcp_fastopen_subflow_synack_set_params(struct mptc= p_subflow_context *subf =20 msk =3D mptcp_sk(sk); msk->rcvd_dummy_seq =3D true; + msk->copied_seq =3D MPTCP_SKB_CB(skb)->map_seq; + msk->tfo_skb_len =3D skb->len; mptcp_borrow_fwdmem(sk, skb); skb_set_owner_r(skb, sk); __skb_queue_tail(&sk->sk_receive_queue, skb); diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 96deaed109a2..f2840c8d9c82 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -168,7 +168,6 @@ static bool __mptcp_try_coalesce(struct sock *sk, struc= t sk_buff *to, int limit =3D READ_ONCE(sk->sk_rcvbuf); =20 if (MPTCP_SKB_CB(from)->map_seq !=3D MPTCP_SKB_CB(to)->end_seq || - MPTCP_SKB_CB(from)->offset || ((to->len + from->len) > (limit >> 3)) || !skb_try_coalesce(to, from, fragstolen, delta)) return false; @@ -415,8 +414,7 @@ static void mptcp_data_queue_ofo(struct mptcp_sock *msk= , struct sk_buff *skb) skb_set_owner_r(skb, sk); } =20 -static void mptcp_init_skb(struct sock *ssk, struct sk_buff *skb, int offs= et, - int copy_len) +static void mptcp_init_skb(struct sock *ssk, struct sk_buff *skb, int offs= et) { struct mptcp_subflow_context *subflow =3D mptcp_subflow_ctx(ssk); bool has_rxtstamp =3D TCP_SKB_CB(skb)->has_rxtstamp; @@ -425,9 +423,9 @@ static void mptcp_init_skb(struct sock *ssk, struct sk_= buff *skb, int offset, * mptcp_subflow_get_mapped_dsn() is based on the current tp->copied_seq * value */ - MPTCP_SKB_CB(skb)->map_seq =3D mptcp_subflow_get_mapped_dsn(subflow); - MPTCP_SKB_CB(skb)->end_seq =3D MPTCP_SKB_CB(skb)->map_seq + copy_len; - MPTCP_SKB_CB(skb)->offset =3D offset; + MPTCP_SKB_CB(skb)->map_seq =3D mptcp_subflow_get_mapped_dsn(subflow) - + offset; + MPTCP_SKB_CB(skb)->end_seq =3D MPTCP_SKB_CB(skb)->map_seq + skb->len; MPTCP_SKB_CB(skb)->has_rxtstamp =3D has_rxtstamp; =20 __skb_unlink(skb, &ssk->sk_receive_queue); @@ -441,7 +439,6 @@ void __mptcp_sync_rcv_sequence(struct sock *sk) { struct mptcp_sock *msk =3D mptcp_sk(sk); struct sk_buff *skb; - u32 offset; =20 if (likely(!msk->rcvd_dummy_seq)) return; @@ -452,9 +449,8 @@ void __mptcp_sync_rcv_sequence(struct sock *sk) if (!skb) return; =20 - offset =3D MPTCP_SKB_CB(skb)->offset; - MPTCP_SKB_CB(skb)->map_seq =3D msk->ack_seq - skb->len + offset; - MPTCP_SKB_CB(skb)->end_seq =3D msk->ack_seq; + MPTCP_SKB_CB(skb)->map_seq =3D mptcp_iasn(msk) - skb->len; + MPTCP_SKB_CB(skb)->end_seq =3D MPTCP_SKB_CB(skb)->map_seq + skb->len; } =20 static bool __mptcp_move_skb(struct sock *sk, struct sk_buff *skb) @@ -468,6 +464,7 @@ static bool __mptcp_move_skb(struct sock *sk, struct sk= _buff *skb) if (test_and_clear_bit(MPTCP_SYNC_SEQ, &msk->cb_flags)) { /* Ensure we see the updated ack_seq after seeing the flag */ smp_rmb(); + msk->copied_seq +=3D mptcp_iasn(msk); =20 /* Be sure to sync the eventual fastopen dummy mapping before * any other skb lands into the msk. @@ -502,10 +499,6 @@ static bool __mptcp_move_skb(struct sock *sk, struct s= k_buff *skb) /* Partial packet */ if (after64(MPTCP_SKB_CB(skb)->end_seq, msk->ack_seq)) { copy_len =3D MPTCP_SKB_CB(skb)->end_seq - msk->ack_seq; - MPTCP_SKB_CB(skb)->offset +=3D msk->ack_seq - - MPTCP_SKB_CB(skb)->map_seq; - MPTCP_SKB_CB(skb)->map_seq +=3D msk->ack_seq - - MPTCP_SKB_CB(skb)->map_seq; goto insert; } =20 @@ -863,7 +856,7 @@ static bool __mptcp_move_skbs_from_subflow(struct mptcp= _sock *msk, if (offset < skb->len) { size_t len =3D skb->len - offset; =20 - mptcp_init_skb(ssk, skb, offset, len); + mptcp_init_skb(ssk, skb, offset); =20 if (own_msk) { mptcp_subflow_lend_fwdmem(subflow, skb); @@ -924,14 +917,9 @@ static bool __mptcp_ofo_queue(struct mptcp_sock *msk) end_seq =3D MPTCP_SKB_CB(skb)->end_seq; tail =3D skb_peek_tail(&sk->sk_receive_queue); if (!tail || !mptcp_try_coalesce(sk, tail, skb)) { - int delta =3D msk->ack_seq - MPTCP_SKB_CB(skb)->map_seq; - - /* skip overlapping data, if any */ pr_debug("uncoalesced seq=3D%llx ack seq=3D%llx delta=3D%d\n", MPTCP_SKB_CB(skb)->map_seq, msk->ack_seq, - delta); - MPTCP_SKB_CB(skb)->offset +=3D delta; - MPTCP_SKB_CB(skb)->map_seq +=3D delta; + (int)(msk->ack_seq - MPTCP_SKB_CB(skb)->map_seq)); __skb_queue_tail(&sk->sk_receive_queue, skb); } msk->bytes_received +=3D end_seq - msk->ack_seq; @@ -2215,33 +2203,24 @@ static void mptcp_eat_recv_skb(struct sock *sk, str= uct sk_buff *skb) } =20 static int __mptcp_recvmsg_mskq(struct sock *sk, struct msghdr *msg, - size_t len, int flags, int copied_total, + size_t len, int flags, u64 *seq, struct scm_timestamping_internal *tss, int *cmsg_flags, struct sk_buff **last) { struct mptcp_sock *msk =3D mptcp_sk(sk); struct sk_buff *skb, *tmp; - int total_data_len =3D 0; int copied =3D 0; =20 skb_queue_walk_safe(&sk->sk_receive_queue, skb, tmp) { - u32 delta, offset =3D MPTCP_SKB_CB(skb)->offset; + u64 offset =3D *seq - MPTCP_SKB_CB(skb)->map_seq; u32 data_len =3D skb->len - offset; u32 count; int err; =20 - if (flags & MSG_PEEK) { - /* skip already peeked skbs */ - if (total_data_len + data_len <=3D copied_total) { - total_data_len +=3D data_len; - *last =3D skb; - continue; - } - - /* skip the already peeked data in the current skb */ - delta =3D copied_total - total_data_len; - offset +=3D delta; - data_len -=3D delta; + /* Skip the already peeked data. */ + if (offset >=3D skb->len) { + *last =3D skb; + continue; } =20 count =3D min_t(size_t, len - copied, data_len); @@ -2260,14 +2239,12 @@ static int __mptcp_recvmsg_mskq(struct sock *sk, st= ruct msghdr *msg, } =20 copied +=3D count; + *seq +=3D count; =20 if (!(flags & MSG_PEEK)) { msk->bytes_consumed +=3D count; - if (count < data_len) { - MPTCP_SKB_CB(skb)->offset +=3D count; - MPTCP_SKB_CB(skb)->map_seq +=3D count; + if (count < data_len) break; - } =20 mptcp_eat_recv_skb(sk, skb); } else { @@ -2426,22 +2403,20 @@ static unsigned int mptcp_inq_hint(const struct soc= k *sk) const struct sk_buff *skb; u64 hint_val; =20 - skb =3D skb_peek(&sk->sk_receive_queue); - if (skb) { - if (test_bit(MPTCP_SYNC_SEQ, &msk->cb_flags)) - return skb->len - MPTCP_SKB_CB(skb)->offset; - - hint_val =3D READ_ONCE(msk->ack_seq) - MPTCP_SKB_CB(skb)->map_seq; - if (hint_val >=3D INT_MAX) - return INT_MAX; - - return (unsigned int)hint_val; + if (test_bit(MPTCP_SYNC_SEQ, &msk->cb_flags)) { + skb =3D skb_peek(&sk->sk_receive_queue); + return skb ? skb->len : 0; } =20 - if (sk->sk_state =3D=3D TCP_CLOSE || (sk->sk_shutdown & RCV_SHUTDOWN)) + hint_val =3D READ_ONCE(msk->ack_seq) - msk->copied_seq; + if (hint_val >=3D INT_MAX) + return INT_MAX; + + if (!hint_val && + (sk->sk_state =3D=3D TCP_CLOSE || (sk->sk_shutdown & RCV_SHUTDOWN))) return 1; =20 - return 0; + return (unsigned int)hint_val; } =20 static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, @@ -2450,6 +2425,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msgh= dr *msg, size_t len, struct mptcp_sock *msk =3D mptcp_sk(sk); struct scm_timestamping_internal tss; int copied =3D 0, cmsg_flags =3D 0; + u64 peek_seq, *seq; int target; long timeo; =20 @@ -2468,6 +2444,11 @@ static int mptcp_recvmsg(struct sock *sk, struct msg= hdr *msg, size_t len, =20 len =3D min_t(size_t, len, INT_MAX); target =3D sock_rcvlowat(sk, flags & MSG_WAITALL, len); + seq =3D &msk->copied_seq; + if (flags & MSG_PEEK) { + peek_seq =3D msk->copied_seq; + seq =3D &peek_seq; + } =20 if (unlikely(msk->recvmsg_inq)) cmsg_flags =3D MPTCP_CMSG_INQ; @@ -2477,7 +2458,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msgh= dr *msg, size_t len, int err, bytes_read; =20 bytes_read =3D __mptcp_recvmsg_mskq(sk, msg, len - copied, flags, - copied, &tss, &cmsg_flags, + seq, &tss, &cmsg_flags, &last); if (unlikely(bytes_read < 0)) { if (!copied) @@ -2487,8 +2468,11 @@ static int mptcp_recvmsg(struct sock *sk, struct msg= hdr *msg, size_t len, =20 copied +=3D bytes_read; =20 - if (!list_empty(&msk->backlog_list) && mptcp_move_skbs(sk)) + if (!list_empty(&msk->backlog_list) && mptcp_move_skbs(sk)) { + if (flags & MSG_PEEK) + peek_seq =3D msk->copied_seq + copied; continue; + } =20 /* only the MPTCP socket status is relevant here. The exit * conditions mirror closely tcp_recvmsg() @@ -2531,6 +2515,10 @@ static int mptcp_recvmsg(struct sock *sk, struct msg= hdr *msg, size_t len, copied =3D copied ? : err; goto out_err; } + + /* Recompute peek offset after eventual seq resync. */ + if (flags & MSG_PEEK) + peek_seq =3D msk->copied_seq + copied; } =20 mptcp_cleanup_rbuf(msk, copied); @@ -3713,11 +3701,13 @@ static int mptcp_disconnect(struct sock *sk, int fl= ags) msk->bytes_retrans =3D 0; msk->rcvspace_init =3D 0; msk->fastclosing =3D 0; + msk->tfo_skb_len =3D 0; mptcp_init_rtt_est(msk); =20 /* for fallback's sake */ WRITE_ONCE(msk->ack_seq, 0); atomic64_set(&msk->rcv_wnd_sent, 0); + msk->copied_seq =3D 0; =20 WRITE_ONCE(sk->sk_shutdown, 0); sk_error_report(sk); @@ -3968,6 +3958,7 @@ static void mptcp_release_cb(struct sock *sk) * the flag */ smp_rmb(); + msk->copied_seq +=3D mptcp_iasn(msk); __mptcp_sync_rcv_sequence(sk); } } @@ -4641,7 +4632,7 @@ static struct sk_buff *mptcp_recv_skb(struct sock *sk= , u32 *off) mptcp_move_skbs(sk); =20 while ((skb =3D skb_peek(&sk->sk_receive_queue)) !=3D NULL) { - offset =3D MPTCP_SKB_CB(skb)->offset; + offset =3D msk->copied_seq - MPTCP_SKB_CB(skb)->map_seq; if (offset < skb->len) { *off =3D offset; return skb; @@ -4683,11 +4674,9 @@ static int __mptcp_read_sock(struct sock *sk, read_d= escriptor_t *desc, copied +=3D count; =20 msk->bytes_consumed +=3D count; - if (count < data_len) { - MPTCP_SKB_CB(skb)->offset +=3D count; - MPTCP_SKB_CB(skb)->map_seq +=3D count; + msk->copied_seq +=3D count; + if (count < data_len) break; - } =20 mptcp_eat_recv_skb(sk, skb); if (!desc->count) diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 609b572f8eb0..1cb7989b6fb0 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -131,7 +131,6 @@ struct mptcp_skb_cb { u64 map_seq; u64 end_seq; - u32 offset; u8 has_rxtstamp; }; =20 @@ -306,6 +305,7 @@ struct mptcp_sock { u64 bytes_sent; u64 snd_nxt; u64 bytes_received; + u64 copied_seq; u64 ack_seq; atomic64_t rcv_wnd_sent; u64 rcv_data_fin_seq; @@ -325,6 +325,7 @@ struct mptcp_sock { u32 last_ack_recv; unsigned long timer_ival; u32 token; + u32 tfo_skb_len; unsigned long flags; unsigned long cb_flags; bool rcvd_dummy_seq; @@ -884,6 +885,11 @@ struct sock *mptcp_subflow_get_retrans(struct mptcp_so= ck *msk); int mptcp_sched_get_send(struct mptcp_sock *msk); int mptcp_sched_get_retrans(struct mptcp_sock *msk); =20 +static inline u64 mptcp_iasn(const struct mptcp_sock *msk) +{ + return msk->ack_seq - msk->bytes_received + msk->tfo_skb_len; +} + static inline u64 mptcp_data_avail(const struct mptcp_sock *msk) { return READ_ONCE(msk->bytes_received) - READ_ONCE(msk->bytes_consumed); diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index bf6ba235c268..ebba77f05a42 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -537,6 +537,8 @@ static void subflow_set_remote_key(struct mptcp_sock *m= sk, atomic64_set(&msk->rcv_wnd_sent, subflow->iasn); =20 if (!sock_owned_by_user(sk)) { + /* User space could have already read partially the TFO skb */ + msk->copied_seq +=3D subflow->iasn; __mptcp_sync_rcv_sequence(sk); } else { /* Ensure ack_seq is visible before setting the flag */ @@ -559,6 +561,17 @@ static void mptcp_propagate_state(struct sock *sk, str= uct sock *ssk, WRITE_ONCE(msk->snd_una, subflow->idsn + 1); WRITE_ONCE(msk->wnd_end, subflow->idsn + 1 + tcp_sk(ssk)->snd_wnd); subflow_set_remote_key(msk, subflow, mp_opt); + } else { + /* Fallback (no MPTCP options at SYN-ACK): initialise the + * sequence space to 0 so that skb map_seq starts from 0 + * to match msk->copied_seq. Safe without deferral because + * mptcp_data_lock() is already held. + */ + subflow->map_seq =3D 0; + subflow->map_subflow_seq =3D tcp_sk(ssk)->copied_seq - + subflow->ssn_offset; + WRITE_ONCE(msk->ack_seq, 0); + msk->copied_seq =3D 0; } =20 if (!sock_owned_by_user(sk)) { --=20 2.55.0 From nobody Thu Nov 5 07:28:35 2026 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1792720750; b=PoJMd6NEhq2WIOfUm6f6bZuoSUft2NPCqVsXMQBGSBVr/hBt0ZnMzelEpojyDHISqVSm aRSAR/fNws3BAZL2ZMslf/Tsh+gVZtp6FXX8KVHvBGjR0+jyYEfbWB8ndMdD6LId5TjQu QfOM5GEqHNl8iUE++uqSso5db+iOaMZ6rVOcOuRNw2wPWFNO92nF+FkcA1FkJG+w2SBxB n8+f4Qz0nizqL13P/FJXQN2H4DVTllntpaWls3QorAy+efOG6o4idcT6UkPQtJVPal/iw Ovc1U2PAcyQ6z5YBcq/N0WG2srBbQNqL3942eJvJdTjMkzz26/WspdfBB0tjOhcZ0MQ== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1792720750; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=WzX09kxqqRuLfagDwLeLMOsXteym5NpV3UxSePHhhs0=; b=BBrNtKdkK+GQY4ErekkLwPuBl2VPajjPgsFlUyIEJCxEOGWjkBDgH1r6s56ga6eYK893 2rw7C1V/Lo8g70yihX2hlohB3UJX+W6JSRTCxiU6yw21Ihk5YrygtoRjMcmbCvlOaDJK9 yF8z1CtltfFVDlTH4GNvHi85XrjT/sQxH8mJpJQI6GvAc0P/8aLWETcJ474hC2svjfIk4 O4MIFNxF3kKIwKYSQcIgDp80l4QZNzvTMCpWU0ITLkWflwvMXKj/UktQnyijScXyIFreR 6OClf+PdNL7M1/WSStBMORxaKZ4snzDJBg23pJqzbI1jRNrAy14RqJJWxStx/tnrJnw== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=UJzEeoOo; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 69D58606A319 for ; Fri, 23 Oct 2026 01:59:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=UJzEeoOo Received: by smtp.kernel.org (Postfix) with ESMTPSA id F3F251F031E0; Fri, 23 Oct 2026 01:59:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1792720750; bh=WzX09kxqqRuLfagDwLeLMOsXteym5NpV3UxSePHhhs0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=UJzEeoOo07ttz8P7Su4srhkxpvp9ks9CNCBaHYuj7KIjmRZHl76YONHvRxEvyt1mt RHd90FyM+pIYzjw6KhIuBXpsg1Vg22JzITg7+nQx3et9yMKg6+x8C4RpodC/XT4e6c UjsNJXGEDxfyhGXmYqAaqcSwJHQgDQPTN2Iw56nQ9D/mrowbq2CpkLUb/xeCe/vY30 mF6VV6qgNjdn42zeGnLoXG+XqKXBBdMXjpzEkLzOtlrEQqWf8r1n9Pcp2LzsnWGQws i8qEw8+xLro9wrxxsDtNes7Lu8ocPlLERgMfUWt2IqWePFa68xr3QJ7vUQNkgv6jCE xPpx2zWjA+omA== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Paolo Abeni , Geliang Tang Subject: [PATCH mptcp-next v15 04/11] mptcp: sync mptcp skb cb layout with tcp one Date: Fri, 23 Oct 2026 09:58:45 +0800 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Paolo Abeni The MPTCP protocol uses a significantly different CB layout WRT TCP, as it includes different information and use 64 bits for the sequence numbers. As the msk-level rcvbuf buffer size is limited by the core socket code the INT_MAX; after validating the incoming skb vs the current receive window, we can safely use 32 bits for MPTCP-level sequence number. This allow updating the MPTCP CB layout so that fields with a corresponding TCP-level data use the same area inside the CB itself. The 32-bit sequence numbers are safe because all SKBs in the receive queue and OFO queue have been validated against the receive window (max INT_MAX), so their sequence numbers are guaranteed to be within 2^31 of the current ack_seq or copied_seq. This ensures that 32-bit arithmetic (comparisons and subtractions) produces correct results even when 64-bit values cross the 2^32 boundary, as the relative distance remains small. Add build time check to ensure the latter invariant. Co-developed-by: Geliang Tang Signed-off-by: Geliang Tang Signed-off-by: Paolo Abeni --- net/mptcp/fastopen.c | 6 ++- net/mptcp/protocol.c | 90 +++++++++++++++++++++++++++----------------- net/mptcp/protocol.h | 7 +++- 3 files changed, 65 insertions(+), 38 deletions(-) diff --git a/net/mptcp/fastopen.c b/net/mptcp/fastopen.c index 421a50a85547..0d339dd454f9 100644 --- a/net/mptcp/fastopen.c +++ b/net/mptcp/fastopen.c @@ -48,8 +48,10 @@ void mptcp_fastopen_subflow_synack_set_params(struct mpt= cp_subflow_context *subf /* The TFO segment data sits before the IASN; before receiving * the remote key, IASN is assumed being 0. */ - MPTCP_SKB_CB(skb)->map_seq =3D -(u64)skb->len; + MPTCP_SKB_CB(skb)->map_seq64 =3D -(u64)skb->len; + MPTCP_SKB_CB(skb)->map_seq =3D MPTCP_SKB_CB(skb)->map_seq64; MPTCP_SKB_CB(skb)->end_seq =3D 0; + MPTCP_SKB_CB(skb)->flags =3D 0; MPTCP_SKB_CB(skb)->has_rxtstamp =3D has_rxtstamp; =20 mptcp_data_lock(sk); @@ -57,7 +59,7 @@ void mptcp_fastopen_subflow_synack_set_params(struct mptc= p_subflow_context *subf =20 msk =3D mptcp_sk(sk); msk->rcvd_dummy_seq =3D true; - msk->copied_seq =3D MPTCP_SKB_CB(skb)->map_seq; + msk->copied_seq =3D MPTCP_SKB_CB(skb)->map_seq64; msk->tfo_skb_len =3D skb->len; mptcp_borrow_fwdmem(sk, skb); skb_set_owner_r(skb, sk); diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index f2840c8d9c82..01eb7fb314e7 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -168,11 +168,13 @@ static bool __mptcp_try_coalesce(struct sock *sk, str= uct sk_buff *to, int limit =3D READ_ONCE(sk->sk_rcvbuf); =20 if (MPTCP_SKB_CB(from)->map_seq !=3D MPTCP_SKB_CB(to)->end_seq || + MPTCP_SKB_CB(from)->map_seq64 !=3D MPTCP_SKB_CB(to)->map_seq64 + + to->len || ((to->len + from->len) > (limit >> 3)) || !skb_try_coalesce(to, from, fragstolen, delta)) return false; =20 - pr_debug("colesced seq %llx into %llx new len %d new end seq %llx\n", + pr_debug("colesced seq %x into %x new len %d new end seq %x\n", MPTCP_SKB_CB(from)->map_seq, MPTCP_SKB_CB(to)->map_seq, to->len, MPTCP_SKB_CB(from)->end_seq); MPTCP_SKB_CB(to)->end_seq =3D MPTCP_SKB_CB(from)->end_seq; @@ -254,8 +256,8 @@ static void mptcp_prune_ofo_queue(struct sock *sk, struct sk_buff *skb =3D rb_to_skb(node); =20 /* Stop pruning if the incoming skb would land in OoO tail. */ - if (after64(MPTCP_SKB_CB(in_skb)->map_seq, - MPTCP_SKB_CB(skb)->map_seq)) + if (after(MPTCP_SKB_CB(in_skb)->map_seq, + MPTCP_SKB_CB(skb)->map_seq)) break; =20 pruned =3D true; @@ -301,16 +303,21 @@ static void mptcp_data_queue_ofo(struct mptcp_sock *m= sk, struct sk_buff *skb) { struct sock *sk =3D (struct sock *)msk; struct rb_node **p, *parent; - u64 seq, end_seq, max_seq; + u64 end_seq, max_seq; struct sk_buff *skb1; + u32 seq; =20 seq =3D MPTCP_SKB_CB(skb)->map_seq; - end_seq =3D MPTCP_SKB_CB(skb)->end_seq; + end_seq =3D MPTCP_SKB_CB(skb)->map_seq64 + skb->len; max_seq =3D atomic64_read(&msk->rcv_wnd_sent); =20 - pr_debug("msk=3D%p seq=3D%llx limit=3D%llx empty=3D%d\n", msk, seq, max_s= eq, + pr_debug("msk=3D%p seq=3D%x limit=3D%llx empty=3D%d\n", msk, seq, max_seq, RB_EMPTY_ROOT(&msk->out_of_order_queue)); - if (after64(end_seq, max_seq)) { + /* Use the full sequence space to perform the admission checks, to + * protect vs possible wrap-arounds. + */ + if (after64(MPTCP_SKB_CB(skb)->map_seq64, max_seq) || + after64(end_seq, max_seq)) { /* out of window */ mptcp_drop(sk, skb); pr_debug("oow by %lld, rcv_wnd_sent %llu\n", @@ -345,7 +352,7 @@ static void mptcp_data_queue_ofo(struct mptcp_sock *msk= , struct sk_buff *skb) } =20 /* Can avoid an rbtree lookup if we are adding skb after ooo_last_skb */ - if (!before64(seq, MPTCP_SKB_CB(msk->ooo_last_skb)->end_seq)) { + if (!before(seq, MPTCP_SKB_CB(msk->ooo_last_skb)->end_seq)) { MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_OFOQUEUETAIL); parent =3D &msk->ooo_last_skb->rbnode; p =3D &parent->rb_right; @@ -357,18 +364,18 @@ static void mptcp_data_queue_ofo(struct mptcp_sock *m= sk, struct sk_buff *skb) while (*p) { parent =3D *p; skb1 =3D rb_to_skb(parent); - if (before64(seq, MPTCP_SKB_CB(skb1)->map_seq)) { + if (before(seq, MPTCP_SKB_CB(skb1)->map_seq)) { p =3D &parent->rb_left; continue; } - if (before64(seq, MPTCP_SKB_CB(skb1)->end_seq)) { - if (!after64(end_seq, MPTCP_SKB_CB(skb1)->end_seq)) { + if (before(seq, MPTCP_SKB_CB(skb1)->end_seq)) { + if (!after(end_seq, MPTCP_SKB_CB(skb1)->end_seq)) { /* All the bits are present. Drop. */ mptcp_drop(sk, skb); MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DUPDATA); return; } - if (after64(seq, MPTCP_SKB_CB(skb1)->map_seq)) { + if (after(seq, MPTCP_SKB_CB(skb1)->map_seq)) { /* partial overlap: * | skb | * | skb1 | @@ -399,7 +406,7 @@ static void mptcp_data_queue_ofo(struct mptcp_sock *msk= , struct sk_buff *skb) merge_right: /* Remove other segments covered by skb. */ while ((skb1 =3D skb_rb_next(skb)) !=3D NULL) { - if (before64(end_seq, MPTCP_SKB_CB(skb1)->end_seq)) + if (before((u32)end_seq, MPTCP_SKB_CB(skb1)->end_seq)) break; rb_erase(&skb1->rbnode, &msk->out_of_order_queue); mptcp_drop(sk, skb1); @@ -421,11 +428,13 @@ static void mptcp_init_skb(struct sock *ssk, struct s= k_buff *skb, int offset) =20 /* the skb map_seq accounts for the skb offset: * mptcp_subflow_get_mapped_dsn() is based on the current tp->copied_seq - * value + * value; note that end seq number is only available in 32bits format. */ - MPTCP_SKB_CB(skb)->map_seq =3D mptcp_subflow_get_mapped_dsn(subflow) - - offset; + MPTCP_SKB_CB(skb)->map_seq64 =3D mptcp_subflow_get_mapped_dsn(subflow) - + offset; + MPTCP_SKB_CB(skb)->map_seq =3D (u32)MPTCP_SKB_CB(skb)->map_seq64; MPTCP_SKB_CB(skb)->end_seq =3D MPTCP_SKB_CB(skb)->map_seq + skb->len; + MPTCP_SKB_CB(skb)->flags =3D 0; MPTCP_SKB_CB(skb)->has_rxtstamp =3D has_rxtstamp; =20 __skb_unlink(skb, &ssk->sk_receive_queue); @@ -449,13 +458,14 @@ void __mptcp_sync_rcv_sequence(struct sock *sk) if (!skb) return; =20 - MPTCP_SKB_CB(skb)->map_seq =3D mptcp_iasn(msk) - skb->len; + MPTCP_SKB_CB(skb)->map_seq64 =3D mptcp_iasn(msk) - skb->len; + MPTCP_SKB_CB(skb)->map_seq =3D (u32)MPTCP_SKB_CB(skb)->map_seq64; MPTCP_SKB_CB(skb)->end_seq =3D MPTCP_SKB_CB(skb)->map_seq + skb->len; } =20 static bool __mptcp_move_skb(struct sock *sk, struct sk_buff *skb) { - u64 copy_len =3D MPTCP_SKB_CB(skb)->end_seq - MPTCP_SKB_CB(skb)->map_seq; + u32 copy_len =3D MPTCP_SKB_CB(skb)->end_seq - MPTCP_SKB_CB(skb)->map_seq; struct mptcp_sock *msk =3D mptcp_sk(sk); struct sk_buff *tail; =20 @@ -473,7 +483,7 @@ static bool __mptcp_move_skb(struct sock *sk, struct sk= _buff *skb) __mptcp_sync_rcv_sequence(sk); } =20 - if (MPTCP_SKB_CB(skb)->map_seq =3D=3D msk->ack_seq) { + if (MPTCP_SKB_CB(skb)->map_seq64 =3D=3D msk->ack_seq) { /* in sequence */ insert: if (!mptcp_try_rmem_schedule(sk, skb)) { @@ -491,14 +501,14 @@ static bool __mptcp_move_skb(struct sock *sk, struct = sk_buff *skb) skb_set_owner_r(skb, sk); __skb_queue_tail(&sk->sk_receive_queue, skb); return true; - } else if (after64(MPTCP_SKB_CB(skb)->map_seq, msk->ack_seq)) { + } else if (after64(MPTCP_SKB_CB(skb)->map_seq64, msk->ack_seq)) { mptcp_data_queue_ofo(msk, skb); return false; } =20 /* Partial packet */ - if (after64(MPTCP_SKB_CB(skb)->end_seq, msk->ack_seq)) { - copy_len =3D MPTCP_SKB_CB(skb)->end_seq - msk->ack_seq; + if (after64(MPTCP_SKB_CB(skb)->map_seq64 + skb->len, msk->ack_seq)) { + copy_len =3D MPTCP_SKB_CB(skb)->end_seq - (u32)msk->ack_seq; goto insert; } =20 @@ -893,37 +903,37 @@ static bool __mptcp_ofo_queue(struct mptcp_sock *msk) { struct sock *sk =3D (struct sock *)msk; struct sk_buff *skb, *tail; + u32 seq_delta, ack_seq; bool moved =3D false; struct rb_node *p; - u64 end_seq; =20 p =3D rb_first(&msk->out_of_order_queue); pr_debug("msk=3D%p empty=3D%d\n", msk, RB_EMPTY_ROOT(&msk->out_of_order_q= ueue)); while (p) { + ack_seq =3D msk->ack_seq; skb =3D rb_to_skb(p); - if (after64(MPTCP_SKB_CB(skb)->map_seq, msk->ack_seq)) + if (after(MPTCP_SKB_CB(skb)->map_seq, ack_seq)) break; =20 p =3D rb_next(p); rb_erase(&skb->rbnode, &msk->out_of_order_queue); =20 - if (unlikely(!after64(MPTCP_SKB_CB(skb)->end_seq, - msk->ack_seq))) { + if (unlikely(!after(MPTCP_SKB_CB(skb)->end_seq, ack_seq))) { mptcp_drop(sk, skb); MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DUPDATA); continue; } =20 - end_seq =3D MPTCP_SKB_CB(skb)->end_seq; + seq_delta =3D MPTCP_SKB_CB(skb)->end_seq - ack_seq; tail =3D skb_peek_tail(&sk->sk_receive_queue); if (!tail || !mptcp_try_coalesce(sk, tail, skb)) { - pr_debug("uncoalesced seq=3D%llx ack seq=3D%llx delta=3D%d\n", - MPTCP_SKB_CB(skb)->map_seq, msk->ack_seq, - (int)(msk->ack_seq - MPTCP_SKB_CB(skb)->map_seq)); + pr_debug("uncoalesced seq=3D%x ack seq=3D%x delta=3D%d\n", + MPTCP_SKB_CB(skb)->map_seq, ack_seq, + ack_seq - MPTCP_SKB_CB(skb)->map_seq); __skb_queue_tail(&sk->sk_receive_queue, skb); } - msk->bytes_received +=3D end_seq - msk->ack_seq; - WRITE_ONCE(msk->ack_seq, end_seq); + msk->bytes_received +=3D seq_delta; + WRITE_ONCE(msk->ack_seq, msk->ack_seq + seq_delta); moved =3D true; } return moved; @@ -2212,7 +2222,7 @@ static int __mptcp_recvmsg_mskq(struct sock *sk, stru= ct msghdr *msg, int copied =3D 0; =20 skb_queue_walk_safe(&sk->sk_receive_queue, skb, tmp) { - u64 offset =3D *seq - MPTCP_SKB_CB(skb)->map_seq; + u32 offset =3D (u32)(*seq) - MPTCP_SKB_CB(skb)->map_seq; u32 data_len =3D skb->len - offset; u32 count; int err; @@ -4632,7 +4642,7 @@ static struct sk_buff *mptcp_recv_skb(struct sock *sk= , u32 *off) mptcp_move_skbs(sk); =20 while ((skb =3D skb_peek(&sk->sk_receive_queue)) !=3D NULL) { - offset =3D msk->copied_seq - MPTCP_SKB_CB(skb)->map_seq; + offset =3D (u32)msk->copied_seq - MPTCP_SKB_CB(skb)->map_seq; if (offset < skb->len) { *off =3D offset; return skb; @@ -4882,11 +4892,23 @@ static int mptcp_napi_poll(struct napi_struct *napi= , int budget) return work_done; } =20 +#define CHK_CB_FIELD(mptcp_field, tcp_field) \ + ({ \ + BUILD_BUG_ON(offsetof(struct mptcp_skb_cb, mptcp_field) !=3D \ + offsetof(struct tcp_skb_cb, tcp_field)); \ + BUILD_BUG_ON(offsetofend(struct mptcp_skb_cb, mptcp_field) !=3D \ + offsetofend(struct tcp_skb_cb, tcp_field)); \ + }) + void __init mptcp_proto_init(void) { struct mptcp_delegated_action *delegated; int cpu; =20 + CHK_CB_FIELD(map_seq, seq); + CHK_CB_FIELD(end_seq, end_seq); + CHK_CB_FIELD(flags, tcp_flags); + mptcp_prot.h.hashinfo =3D tcp_prot.h.hashinfo; =20 if (percpu_counter_init(&mptcp_sockets_allocated, 0, GFP_KERNEL)) diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 1cb7989b6fb0..fc39fd733860 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -129,9 +129,12 @@ #define MPTCP_SYNC_SEQ 8 =20 struct mptcp_skb_cb { - u64 map_seq; - u64 end_seq; + u32 map_seq; + u32 end_seq; + u32 unused; + u16 flags; u8 has_rxtstamp; + u64 map_seq64; }; =20 #define MPTCP_SKB_CB(__skb) ((struct mptcp_skb_cb *)&((__skb)->cb[0])) --=20 2.55.0 From nobody Thu Nov 5 07:28:35 2026 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1792720752; b=c2e9eGtK0JIOvp8Ay1EPKyk7WobekvpqIV271wrxbQvgONmxAHgiiPt4XLxqW+S1EDdX W8lfxiMkvhhEXx3KJCCWwcHjUBw0jE+8/vIr20HAtSHEedPoVmD9WQdPaFGUGKd5XZUb9 BBVJlU+8VB/E3kMghF2VSmeT1kFDOR+3A3g6PCyxfkXD09HzBa5f7kYoTwn8O0g6KEQxx rnudByyl6hGwIZLU0DpK5KCp3Gne+my4lpkQbTZl29F5l7h8lUjMht0cjLJF0Zae53W5B +tW6IuYQXOWgIVHCSOAIn/IHDmsYANXNNL5lJy0bv1qnvuza9WmDbRlJDP6DQNvcGMQ== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1792720752; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=RqybjaPV9Ri2JPP7lqjDXG1E9kIT7QMmog5K7Qgl5rU=; b=zHl3Ch3sSlTAmDkc6M6chHCc3y5GvMEySPS+VAW0FAd2P+3naEc+yTGK4eL4UUGU38TI sHRM1D4GymhMT3bhwMFp9ad8LDbgm9Vx0CE565lWZolEfixTUvn/c19/sTLqfSN3J/paw I9q+qAapNVPfvauU6wnV1s49oTP2DcC8+1KlFA2sZv4sCB07vsFx6UjlxPAef2q9bXh3s 0KP6O9JU4n1fIh0o7yzqBQopXSvE52zXsurpYgN3vvE/hNTuZVYh3wFjKRI6zZXHTRmDo XZXdS5iP4ir24x0VJdveyFzCEfaUSGJdOjlvee0vWphWL+JU8o8z7U8u6BU70CSThGg== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b="Ny/mwq3x"; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C6974606A319 for ; Fri, 23 Oct 2026 01:59:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=Ny/mwq3x Received: by smtp.kernel.org (Postfix) with ESMTPSA id 97B7E1F01825; Fri, 23 Oct 2026 01:59:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1792720751; bh=RqybjaPV9Ri2JPP7lqjDXG1E9kIT7QMmog5K7Qgl5rU=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Ny/mwq3xzesLFJQMyRFIb9cjHw1kiqJj31UCpNNj17zJr5ZYXCiNBEXNF19rUskau UsU3k+3yJdGKJHmUw3ZgVn3wFXjgRyicdfq3y4VE5Zb8zIj+a5o1oDmpK+vPObDIOZ nlYiR+8mk+X2Yzkf9knGCML5rwwGiu7F7nCIElryU/RnA07FHG4vryEmE4bp2BDBOQ gRHO/HP+doqIyMQbiiw75cRYpV9DF1OYRwD+EFCb0PaGnnJVPlz4U31FwLJYqrODBI zCaroHkiVudboKbHtrVZfq56703fMg/kiOYrZzn2Wp98TuyTQXXjoLspWb9ViIkbmH Yr/dWyGl8Z7Pg== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Paolo Abeni , Geliang Tang Subject: [PATCH mptcp-next v15 05/11] mptcp: defer read_sock cleanup to mptcp_worker Date: Fri, 23 Oct 2026 09:58:46 +0800 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Paolo Abeni This is preparatory work for an upcoming kTLS-over-MPTCP series. When MPTCP carries TLS, __mptcp_read_sock() will be reached from BH context (via tls_strp_read_copyin() -> sk->sk_read_sock()), where calling mptcp_rcv_space_adjust() and mptcp_cleanup_rbuf() inline is not safe: both expect process context. Move both calls to mptcp_worker(): __mptcp_read_sock() accumulates the consumed byte count in msk->read_copied and signals the worker through a new MPTCP_WORK_READ_COMPLETE bit. The worker drains the accumulator under mptcp_data_lock() and runs the rcvbuf autotuning and RDB update in process context. To prevent integer overflow when read_copied wraps to negative values, mptcp_read_complete() only calls mptcp_cleanup_rbuf() when read_copied > 0. Since the worker now owns the post-read housekeeping, remove the backlog flush from mptcp_recv_skb() (it ran mptcp_move_skbs() which is already covered by mptcp_release_cb() when the worker calls release_sock()) and drop the msk_owned_by_me() assertion from __mptcp_read_sock() (the BH caller does not own the msk lock). Also drop the now-redundant mptcp_recv_skb() call after the main loop in __mptcp_read_sock(): its return value and offset output were unused, and fully-consumed SKBs are already eaten by mptcp_eat_recv_skb() within the loop. Initialize msk->read_copied in __mptcp_init_sock() and reset it in mptcp_disconnect() alongside the other per-connection counters, so a socket does not carry a stale byte count across connections. Co-developed-by: Geliang Tang Signed-off-by: Geliang Tang Signed-off-by: Paolo Abeni --- net/mptcp/protocol.c | 37 ++++++++++++++++++++++++++++--------- net/mptcp/protocol.h | 2 ++ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 01eb7fb314e7..3c3ad8991799 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -3149,6 +3149,21 @@ static void mptcp_backlog_purge(struct sock *sk) sk_mem_reclaim(sk); } =20 +static void mptcp_read_complete(struct sock *sk) +{ + struct mptcp_sock *msk =3D mptcp_sk(sk); + int read_copied; + + mptcp_data_lock(sk); + read_copied =3D msk->read_copied; + msk->read_copied =3D 0; + mptcp_data_unlock(sk); + + mptcp_rcv_space_adjust(msk, read_copied); + if (read_copied > 0) + mptcp_cleanup_rbuf(msk, read_copied); +} + static void mptcp_do_fastclose(struct sock *sk) { struct mptcp_subflow_context *subflow, *tmp; @@ -3224,6 +3239,9 @@ static void mptcp_worker(struct work_struct *work) if (test_and_clear_bit(MPTCP_WORK_RTX, &msk->flags)) __mptcp_retrans(sk); =20 + if (test_and_clear_bit(MPTCP_WORK_READ_COMPLETE, &msk->flags)) + mptcp_read_complete(sk); + fail_tout =3D msk->first ? READ_ONCE(mptcp_subflow_ctx(msk->first)->fail_= tout) : 0; if (fail_tout && time_after(jiffies, fail_tout)) mptcp_mp_fail_no_response(msk); @@ -3267,6 +3285,7 @@ static void __mptcp_init_sock(struct sock *sk) msk->last_data_sent =3D tcp_jiffies32; msk->last_data_recv =3D tcp_jiffies32; msk->last_ack_recv =3D tcp_jiffies32; + msk->read_copied =3D 0; =20 mptcp_pm_data_init(msk); spin_lock_init(&msk->fallback_lock); @@ -3709,6 +3728,7 @@ static int mptcp_disconnect(struct sock *sk, int flag= s) msk->bytes_received =3D 0; msk->bytes_sent =3D 0; msk->bytes_retrans =3D 0; + msk->read_copied =3D 0; msk->rcvspace_init =3D 0; msk->fastclosing =3D 0; msk->tfo_skb_len =3D 0; @@ -4638,9 +4658,6 @@ static struct sk_buff *mptcp_recv_skb(struct sock *sk= , u32 *off) struct sk_buff *skb; u32 offset; =20 - if (!list_empty(&msk->backlog_list)) - mptcp_move_skbs(sk); - while ((skb =3D skb_peek(&sk->sk_receive_queue)) !=3D NULL) { offset =3D (u32)msk->copied_seq - MPTCP_SKB_CB(skb)->map_seq; if (offset < skb->len) { @@ -4655,6 +4672,7 @@ static struct sk_buff *mptcp_recv_skb(struct sock *sk= , u32 *off) /* * Note: * - It is assumed that the socket was locked by the caller. + * - Can be invoked in BH scope. */ static int __mptcp_read_sock(struct sock *sk, read_descriptor_t *desc, sk_read_actor_t recv_actor, bool noack) @@ -4664,8 +4682,6 @@ static int __mptcp_read_sock(struct sock *sk, read_de= scriptor_t *desc, int copied =3D 0; u32 offset; =20 - msk_owned_by_me(msk); - if (sk->sk_state =3D=3D TCP_LISTEN) return -ENOTCONN; while ((skb =3D mptcp_recv_skb(sk, &offset)) !=3D NULL) { @@ -4696,11 +4712,14 @@ static int __mptcp_read_sock(struct sock *sk, read_= descriptor_t *desc, if (noack) goto out; =20 - mptcp_rcv_space_adjust(msk, copied); - + /* The backlog flushing is only needed when some data is actually + * moved and will take place in mptcp_release_cb() via + * release_sock() in the worker. + */ if (copied > 0) { - mptcp_recv_skb(sk, &offset); - mptcp_cleanup_rbuf(msk, copied); + msk->read_copied +=3D copied; + set_bit(MPTCP_WORK_READ_COMPLETE, &msk->flags); + mptcp_schedule_work(sk); } out: return copied; diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index fc39fd733860..a061609f6152 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -117,6 +117,7 @@ #define MPTCP_FALLBACK_DONE 2 #define MPTCP_WORK_CLOSE_SUBFLOW 3 #define MPTCP_RTX_ENABLED 4 +#define MPTCP_WORK_READ_COMPLETE 5 =20 /* MPTCP socket release cb flags */ #define MPTCP_PUSH_PENDING 1 @@ -326,6 +327,7 @@ struct mptcp_sock { u32 last_data_sent; u32 last_data_recv; u32 last_ack_recv; + int read_copied; unsigned long timer_ival; u32 token; u32 tfo_skb_len; --=20 2.55.0 From nobody Thu Nov 5 07:28:35 2026 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1792720753; b=vZwt/p37VTEjBT9xf3arJJfOSfZVZMvgOrGn6aU0DPMiBbjKrrqVCpTtuBHFdrp8vOTr 5djBgRu4lTjdHfBZGvu9MFRDhW1Eco3xAug1ad7+31JgCBMiwfrJvLwa0nu0cMr5gej7c Krw94SF45Kx+/yqAHmrp9PmnFg8TdUSl1n1LvJvsrqSxUiA3Ql1V7TiEqZeUNv2sX9Shf BP+AsrRtTV7+TCIf1jPBNp1nTTquvGWfdwIL9PlBcOQLmivCOQ7uEWOYk6cpXSqeW91Eh i9DGgMhEHlCziLgxDSFp4hF9WnTfpMsJG22Kt8H9jq66ULTQkOgb119Ie42ibuuJgxw== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1792720753; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=aFdF5u/9iPbWs+2wPPKei9h8xLo9BMNish6khhgYwxg=; b=zrYetlaLICaP2BzgdphBnIhaYYngAZp1NqsMinPuHuLHB8VqP5JcxmmFG3mAa7xwzZqG l8lv5xWJQIv+K22zvTSYn3og2phhmKhEO7Mha+ZH6auzw4j9GmyTZJWOQ0AJuZADA5u7L iJv4F1bRGBPoQSKRulTGJ7psO6OVxLPdwwKkC66nLyygKB2x0jqGJXfL7ZA12dtI78gbx QZHYxD+wCGqsZluQh8rZOc7Wv04PmQPI8137w8wb2JpjK7e2ghnm9qzAsxF92kCeaSuy5 ThseF3Ym2pfW01FjD24LBhEMf0Kd9FUtQ2zd0ctbrO4ltUSTMKa2QMmK9aUi088eSyQ== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=LwgZUbyE; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 99AF1606A31E for ; Fri, 23 Oct 2026 01:59:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=LwgZUbyE Received: by smtp.kernel.org (Postfix) with ESMTPSA id 284121F01829; Fri, 23 Oct 2026 01:59:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1792720753; bh=aFdF5u/9iPbWs+2wPPKei9h8xLo9BMNish6khhgYwxg=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=LwgZUbyEy6RyW3B3Jm28T6ZWjTPhkJy6EaeVOfGwA29EwVEPA+rT8X1gs/d4G18gx JQq3Q+MMs8/P0RCBI51HWeZgmtRQytG6j5SigIx2LR3Si76a/+PvYLkMgNS6zqQ1nH 1EvBec592WIchBNQFeAE5LYWI9Ygvn1opF063kLNr0GQJGtOdCfTGL6GxbiUdgXwi2 a+r0QY2VYOApN+ZlkIYtmER4bAL2ho67pa3/UrMRfL0ciOA2OIj53XFIlVif/InHSa OzYiGrq5BR02UHhkbLmR53vm1jHr/MP6oLaPeylveyKh9GaoHwbircTfquEzTPYaFy 1iZS89+/r1ARg== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Geliang Tang , Zqiang Subject: [PATCH mptcp-next v15 06/11] mptcp: align FIN handling with TCP via SOCK_DONE Date: Fri, 23 Oct 2026 09:58:47 +0800 Message-ID: <920d36c7943127f886900b7cdd7404e9b2acab85.1792718041.git.tanggeliang@kylinos.cn> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Geliang Tang TCP uses SOCK_DONE to mark FIN reception because RCV_SHUTDOWN alone is ambiguous: it is also set by RST (via SHUTDOWN_MASK) without an ack_seq increment. Mirror tcp_fin()/tcp_disconnect() in MPTCP: - Set SOCK_DONE in mptcp_check_data_fin() next to RCV_SHUTDOWN. - Use SOCK_DONE in mptcp_inq_hint() instead of TCP_CLOSE/RCV_SHUTDOWN, mirroring tcp_inq_hint(). - Check SOCK_DONE in mptcp_recvmsg() before sock_error() for clean-close path. - Reset SOCK_DONE in mptcp_disconnect(). All SOCK_DONE access runs under msk socket ownership; existing smp_mb__before_atomic() orders RCV_SHUTDOWN before state transitions. Co-developed-by: Zqiang Signed-off-by: Zqiang Signed-off-by: Geliang Tang --- net/mptcp/protocol.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 3c3ad8991799..7b0005d47bea 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -740,6 +740,7 @@ static void mptcp_check_data_fin(struct sock *sk) =20 WRITE_ONCE(sk->sk_shutdown, sk->sk_shutdown | RCV_SHUTDOWN); smp_mb__before_atomic(); /* SHUTDOWN must be visible first */ + sock_set_flag(sk, SOCK_DONE); =20 switch (sk->sk_state) { case TCP_ESTABLISHED: @@ -2423,7 +2424,7 @@ static unsigned int mptcp_inq_hint(const struct sock = *sk) return INT_MAX; =20 if (!hint_val && - (sk->sk_state =3D=3D TCP_CLOSE || (sk->sk_shutdown & RCV_SHUTDOWN))) + sock_flag(sk, SOCK_DONE)) return 1; =20 return (unsigned int)hint_val; @@ -2495,6 +2496,9 @@ static int mptcp_recvmsg(struct sock *sk, struct msgh= dr *msg, size_t len, !timeo) break; } else { + if (sock_flag(sk, SOCK_DONE)) + break; + copied =3D sock_error(sk); if (copied) break; @@ -3740,6 +3744,7 @@ static int mptcp_disconnect(struct sock *sk, int flag= s) msk->copied_seq =3D 0; =20 WRITE_ONCE(sk->sk_shutdown, 0); + sock_reset_flag(sk, SOCK_DONE); sk_error_report(sk); return 0; } --=20 2.55.0 From nobody Thu Nov 5 07:28:36 2026 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1792720756; b=17fUTzr+mDJhUeSeGUmIOatxaTivWYsPw8p9qmBWINeLH9Pw59wEPrEQ93IkczYwS+ge +AEfdir+yMGq234sQmII5pfB8sSGhchK/9ttnZCc8NjzkDB25F4lJcGrkxWld2MzSvUSE q+KOaZWIIrcJNspCODuAvaVnhhbQ3OPCiwIni7xXDIL+u8M9AmqKQf5QkHqbmP9AFFJJO Bq03FnJIeuNXXkPHNkDOxpML4Kft1Sx3cjSUbV9l4U+EI5bXG4EBoNrtRk9ADgzHe4Rai TlqZwfFYk/Fa+WUnPyThqpf28oiWk/+3Mcb9vo2LlPnYamDo209OcBCujwXHjIYjuLw== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1792720756; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=fZ7uK5stCwqc0Zb8Gqg439vzOzK3ptSq1zLHsqPr/NM=; b=ptmk8WTNxvt5/Fm1vs+A69h5BuD5xwPHUfJT5tvTl8Jk05TFZcYdXyeZ6NNf5tvaObFQ 6/syql4VLLQYmhzlQJamWUakEvgQp5GKljhcjU364X+9fDhBOXBLZcqjoHQYOi+Cz9g84 a4z8HRjgYmARz/UNdK0EMAVPed00Jtm3nB3/8g6dx2dUP6ePFsY/562Xe2tUspXSbGwKD XAax+sQQqRaM3/cAxUb4GRXDKC442XJJ7sQF8S0M3bRx2MqvnlrSw4IIpuGM3STzutg4L oNvbiQpl9sOJ4MuzQB8WU/BgnLppucoezDNh7CzxnyYA1naWuIFhiAqzb24+bnJAC6w== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b="EUqVwl1/"; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A7EE7606A31A for ; Fri, 23 Oct 2026 01:59:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=EUqVwl1/ Received: by smtp.kernel.org (Postfix) with ESMTPSA id B8A521F031E4; Fri, 23 Oct 2026 01:59:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1792720755; bh=fZ7uK5stCwqc0Zb8Gqg439vzOzK3ptSq1zLHsqPr/NM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=EUqVwl1/+zJaaBs9e36n/gaRxgO5QBiTpquVmNhNKzi+nVNMZ+1abIMHRM6ciMJYW W23Ri0Qxa4jO9XdXvUqIcoKexImI8MOlhmpHRSEDzqQhxMqWYW1UcAmEjTXb6+uP/4 81ZiqvlmgJK4FHyyHkjKpv468aCudtfdJo7PDvxB+YNQRizF7Cn+tLZmlNl5FqDMet llxvDysGJZKS+w+Ohc5PHL0ROBh+sAr8tTmS0mpOnHYOud1FqYK9vUz06u97wfzOEB s0gvYm8l43GT08/BJsNfWxF1q8R5FKAUWfJsLmfcvZ1inWWkp2xNWpAx59bte05i0g L2qg3tOIwvwPg== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Geliang Tang , Zqiang Subject: [PATCH mptcp-next v15 07/11] mptcp: implement peek_len for proto_ops Date: Fri, 23 Oct 2026 09:58:48 +0800 Message-ID: <7f915090708935804fe0b5a61b50e24fcd232a40.1792718041.git.tanggeliang@kylinos.cn> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Geliang Tang Add mptcp_inq() to compute the number of readable bytes at the MPTCP level. It derives the count from ack_seq - copied_seq, returns 0 while the connection is still handshaking (TCP_SYN_SENT/TCP_SYN_RECV), and subtracts 1 once a FIN has been received, mirroring tcp_inq(). The subtraction is needed because MPTCP's ack_seq is incremented by 1 in mptcp_check_datafin() when the DATA_FIN is processed, consuming a sequence number without carrying any payload data. Without subtracting 1, peek_len would over-report by one byte after DATA_FIN. READ_ONCE() is used instead of mptcp_data_lock() for the u64 reads of ack_seq and copied_seq because mptcp_inq() will be called from TLS contexts with the socket lock held - taking the spinlock would deadlock. On 32-bit systems a torn read can produce a wrapped subtraction (close to 2^64), which is caught by the INT_MAX clamp. Wire mptcp_inq() into mptcp_peek_len() and assign .peek_len in both mptcp_stream_ops and mptcp_v6_stream_ops. This is preparatory work for an upcoming kTLS-over-MPTCP series: no in-tree consumer currently reaches ->peek_len on an MPTCP socket (the only caller, strp_peek_len(), cannot attach strparser to MPTCP; the existing TLS receive path calls tcp_inq() directly rather than going through ->peek_len). Note: mptcp_inq() intentionally differs from mptcp_inq_hint() when the calculated value is 0 and SOCK_DONE is set. mptcp_inq_hint() returns 1 in this case to signal EOF to ioctl/cmsg users (mirroring tcp_inq_hint()), while mptcp_inq() returns 0 because peek_len should report the actual readable byte count (mirroring tcp_inq()). Co-developed-by: Zqiang Signed-off-by: Zqiang Signed-off-by: Geliang Tang --- net/mptcp/protocol.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 7b0005d47bea..ad11a96b83eb 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -4848,6 +4848,43 @@ static ssize_t mptcp_splice_read(struct socket *sock= , loff_t *ppos, return ret; } =20 +static int mptcp_inq(struct sock *sk) +{ + const struct mptcp_sock *msk =3D mptcp_sk(sk); + int answ; + + if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { + answ =3D 0; + } else if (test_bit(MPTCP_SYNC_SEQ, &msk->cb_flags)) { + answ =3D 0; + } else { + bool sock_done =3D sock_flag(sk, SOCK_DONE); + u64 hint_val; + + /* Ensure we see updated ack_seq and copied_seq after + * checking MPTCP_SYNC_SEQ flag. + */ + smp_rmb(); + + hint_val =3D READ_ONCE(msk->ack_seq) - READ_ONCE(msk->copied_seq); + if (hint_val >=3D INT_MAX) + hint_val =3D INT_MAX; + + answ =3D (unsigned int)hint_val; + + /* Subtract 1, if FIN was received. Mirror tcp_inq() */ + if (answ && sock_done) + answ--; + } + + return answ; +} + +static int mptcp_peek_len(struct socket *sock) +{ + return mptcp_inq(sock->sk); +} + static const struct proto_ops mptcp_stream_ops =3D { .family =3D PF_INET, .owner =3D THIS_MODULE, @@ -4870,6 +4907,7 @@ static const struct proto_ops mptcp_stream_ops =3D { .set_rcvlowat =3D mptcp_set_rcvlowat, .read_sock =3D mptcp_read_sock, .splice_read =3D mptcp_splice_read, + .peek_len =3D mptcp_peek_len, }; =20 static struct inet_protosw mptcp_protosw =3D { @@ -4994,6 +5032,7 @@ static const struct proto_ops mptcp_v6_stream_ops =3D= { .set_rcvlowat =3D mptcp_set_rcvlowat, .read_sock =3D mptcp_read_sock, .splice_read =3D mptcp_splice_read, + .peek_len =3D mptcp_peek_len, }; =20 static struct proto mptcp_v6_prot; --=20 2.55.0 From nobody Thu Nov 5 07:28:36 2026 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1792720757; b=MMKslH0J9vV+YMg7KiYkKKsakJIDMQp7ZdCstFiiArcL4W5COiLOs/E1uttN3EtejXOm /QDhW9IBc0G7Apl2N1IZxf1styZ3gRyaUJx6BbpT0Nb4OvMMymI6biL6T7S1gJahzkK+P Fla3cJrvOtO3gxQ5m0xrJ2ZulHhI+3/vce+lltU8JkCqyIYvDJfxvVYj5R2c8fVsF043P 6T1CshrxHsNKlAbpHqwYtU+7tYlWOIA8EqKbmuqNlAaaawbI9aybHIJNO47nccK3iCb+0 CqOZMlhMoYovtJH072DPYxN5PEY8WuqFxveWE5DyWPHR8arZRt9cjeRlIaiCngRyKDQ== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1792720757; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=3Yx5WagaV8PyPnOtOjjMRe5nurlPioUMn2siTOOgMAc=; b=5bOEJ5Bb/qa6tghwB+yNMd+7nWAM7iEZtRWuOwr/prXgnb0fOhzDd7xmHbETyEz2X6Nr Emj/LjJHHX32a1K6TexSFyZTsIxqWAk3skvQgA1bXOZe+QJsE0gZSj4NVf3LQsUyMj3CJ K1JittSfU7x6JVglzQDmw1odIX/bbYQmSCMhH9xYFnb1Jk5FFxN0rKfVcn16pkbR92Vl5 1LY7vmyOk3nfkVYqFo2BzspMP7nOHzqPL1LCxsHFq+jXzVdEQtOrauN/bvU9eRO+rKkJu Bs5vgHa7b5LQG177EG8pnyFn8tCNSsdnt+N5BLUBSMd5XaSBNCx4ZOeq3/Ifdf+Lr3Q== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=lhj6ZrIL; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E758A606A31A for ; Fri, 23 Oct 2026 01:59:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=lhj6ZrIL Received: by smtp.kernel.org (Postfix) with ESMTPSA id CE13B1F01828; Fri, 23 Oct 2026 01:59:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1792720756; bh=3Yx5WagaV8PyPnOtOjjMRe5nurlPioUMn2siTOOgMAc=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=lhj6ZrILerDUDaRFPzUpU5krleMXCf8c0w/00U8qf2Gxn++V5rP3Nc/G4AYscNMoy bCyvSEZwvVAmJpjlVT/n1oxIqeY+t/Wg61NQl7cAWuwTCGhqSUGDefef1LWFDZNT3U A17B5pZYV8yFhZBdFtjKQ2uI7SBIh1sJXkx1434aRwFfd+gAt2joW/N8AAYB3TC+jv esKcn1vFOHDKUIrJ4N3Y7C8n+99eYSQ6lHbuX5hfJT6ucj8wykhcL1fVjuMvvAwZo+ tNdNhALla207fbkCA0OxuZx9GNbq/dPQxHCoy5lyS5MHruJt9MmmxyQEva2tEdN/Tk ZgF6E5j/CbWAw== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Geliang Tang Subject: [PATCH mptcp-next v15 08/11] mptcp: add sendmsg_locked to proto_ops Date: Fri, 23 Oct 2026 09:58:49 +0800 Message-ID: <3c3ead37362824e55e5b565dd678e61507f3fbc0.1792718041.git.tanggeliang@kylinos.cn> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Geliang Tang MPTCP currently provides a standard sendmsg() implementation which acquires and releases the socket lock internally. However, certain upper layers need to call the sendmsg method while the socket lock is already held. Split the existing mptcp_sendmsg() into mptcp_sendmsg_locked() which assumes the caller holds the socket lock, and a tiny wrapper mptcp_sendmsg() that acquires the lock and calls the locked version. Expose .sendmsg_locked in both mptcp_stream_ops and mptcp_v6_stream_ops. Signed-off-by: Geliang Tang --- net/mptcp/protocol.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index ad11a96b83eb..086de4f3100e 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -2058,7 +2058,7 @@ static void mptcp_rps_record_subflows(const struct mp= tcp_sock *msk) } } =20 -static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) +static int mptcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_= t len) { struct mptcp_sock *msk =3D mptcp_sk(sk); struct page_frag *pfrag; @@ -2070,8 +2070,6 @@ static int mptcp_sendmsg(struct sock *sk, struct msgh= dr *msg, size_t len) msg->msg_flags &=3D MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL | MSG_FASTOPEN | MSG_EOR; =20 - lock_sock(sk); - mptcp_rps_record_subflows(msk); =20 if (unlikely(inet_test_bit(DEFER_CONNECT, sk) || @@ -2187,7 +2185,6 @@ static int mptcp_sendmsg(struct sock *sk, struct msgh= dr *msg, size_t len) } =20 out: - release_sock(sk); return copied; =20 do_error: @@ -2200,6 +2197,17 @@ static int mptcp_sendmsg(struct sock *sk, struct msg= hdr *msg, size_t len) goto out; } =20 +static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) +{ + int ret; + + lock_sock(sk); + ret =3D mptcp_sendmsg_locked(sk, msg, len); + release_sock(sk); + + return ret; +} + static void mptcp_rcv_space_adjust(struct mptcp_sock *msk, int copied); =20 static void mptcp_eat_recv_skb(struct sock *sk, struct sk_buff *skb) @@ -4908,6 +4916,7 @@ static const struct proto_ops mptcp_stream_ops =3D { .read_sock =3D mptcp_read_sock, .splice_read =3D mptcp_splice_read, .peek_len =3D mptcp_peek_len, + .sendmsg_locked =3D mptcp_sendmsg_locked, }; =20 static struct inet_protosw mptcp_protosw =3D { @@ -5033,6 +5042,7 @@ static const struct proto_ops mptcp_v6_stream_ops =3D= { .read_sock =3D mptcp_read_sock, .splice_read =3D mptcp_splice_read, .peek_len =3D mptcp_peek_len, + .sendmsg_locked =3D mptcp_sendmsg_locked, }; =20 static struct proto mptcp_v6_prot; --=20 2.55.0 From nobody Thu Nov 5 07:28:36 2026 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1792720758; b=bH2a53rhgoM0wnevy5aBIpV8aKGBNa8KDolFoY/JViUTKlU/4K1IUGn0BoXNjWi/52ag vVNVsDGZNqWwEHscKm8uCuo2HsM0HsT3NWTljDvdeaffexdhGwO8KH4fnZ1Uey9lYK0+g 8NGlXEB17Yi5csEAomRnK8fsMl8Yt6XfDo5Fd3A82a7cfIfHDuHwjNDjCzBVLvqXMO7lN Czo2A6rq0EAAqk1ZOf5G9YDn/4VeKtYEzidJ3bUBEaXcHyCfSPGjwugHULVoPpp6pXxwj Cm093ryTduoCZKY3sfifJzKDBjDkyatWbkWb4ZhacotVspNak+ljAWqKXAigVstfTJw== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1792720758; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=QRTh9c/ChdNy4zRXe6J0ON5wGrSsLQuJldVLAaSIMRQ=; b=i5xHqolMgoJJayeFcIxWCbIZvEPvvvZS3EZ/7CNHGZ9XG8xQW/ec/z1a2TYcVdo/Vzit naOBu7pSW6WcKsHeJC6DqDK56gUy6MG26zmE5+8u62NV7CK++Or93pQ81OY5efeU/SgCb ZJN1rJK27cebP/TzvqetEKOQLhctclh93/5vrWnltlloMUTqbwAdJQlJWOWrP19c/k4aq l4k1HgaNXPuGYzxrna6Oo08qhtWUh7mlJpMwMA2WVqITZrYMYAr6HItm3SibIFjsZFRlH 3D83Mdxg2ovf6fjxnNW80I4PjNpgKk+Mglp+Zh/b6gkr00bmEBIYTRaC5pbVik0pefA== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=S58hlOkq; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6882F606A31A for ; Fri, 23 Oct 2026 01:59:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=S58hlOkq Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2F3C01F01829; Fri, 23 Oct 2026 01:59:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1792720758; bh=QRTh9c/ChdNy4zRXe6J0ON5wGrSsLQuJldVLAaSIMRQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=S58hlOkqJGA5cTkj1RFR1gsUVAFrAlPfyTxq4L0bnhXWjG/CxgPSCtP2hpYEcaCby nHhxqMWQlgVlZkCgFbga/FqUWOCrZwiAc4BhOgbZQdOUvKXVFCLJcEjRKHO23JmpcS T2IxXW3aGbOEDmnPjMY1eXVfsDtRE3dJr3IPKqN5t2FlN/O412LZlMvYOSmIs3eqeU ZEAuh4a7jh9PzXel/0hjExNFJgV0Ht5jwohF+l4KAo1L8jyR1Q5KBiFGM9go2DlJ0x Q6LGP22V1/1k8BO45lMFsDDuBHHsoqYhAaHsTySvAhP326C45FK2QTs5QE/pC0ZlNn ysgba18Ucvauw== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Geliang Tang Subject: [PATCH mptcp-next v15 09/11] mptcp: track app-limited state in mptcp_sendmsg Date: Fri, 23 Oct 2026 09:58:50 +0800 Message-ID: <38d46163209730399bc8927b0e37cdd79f9c4b70.1792718041.git.tanggeliang@kylinos.cn> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Geliang Tang Add mptcp_rate_check_app_limited() that walks every subflow of the mptcp_sock and runs tcp_rate_check_app_limited() under each subflow's socket lock. The helper bails out early when MPTCP still has unsent data (msk->write_seq !=3D msk->snd_nxt), because in that case the subflows may look idle only because mptcp_sendmsg_frag() has not pushed data down yet - e.g. due to a constrained MPTCP receive window - and marking them app-limited would be wrong. Invoke mptcp_rate_check_app_limited() from mptcp_sendmsg_locked() right after the send-side setup, so the delivery-rate app_limited state stays in sync with what the application actually has to send across each subflow. With this in place, subflow rate samples taken while the MPTCP connection is genuinely application-limited are flagged as such, allowing congestion controllers like BBR to ignore them when estimating bandwidth. Signed-off-by: Geliang Tang --- net/mptcp/protocol.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 086de4f3100e..7870b9be76c7 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -2058,6 +2058,24 @@ static void mptcp_rps_record_subflows(const struct m= ptcp_sock *msk) } } =20 +static void mptcp_rate_check_app_limited(struct sock *sk) +{ + struct mptcp_sock *msk =3D mptcp_sk(sk); + struct mptcp_subflow_context *subflow; + + if (msk->write_seq !=3D msk->snd_nxt) + return; + + mptcp_for_each_subflow(msk, subflow) { + struct sock *ssk =3D mptcp_subflow_tcp_sock(subflow); + bool slow; + + slow =3D lock_sock_fast_nested(ssk); + tcp_rate_check_app_limited(ssk); + unlock_sock_fast(ssk, slow); + } +} + static int mptcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_= t len) { struct mptcp_sock *msk =3D mptcp_sk(sk); @@ -2086,6 +2104,9 @@ static int mptcp_sendmsg_locked(struct sock *sk, stru= ct msghdr *msg, size_t len) =20 timeo =3D sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); =20 + /* is sending application-limited? */ + mptcp_rate_check_app_limited(sk); + if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) { ret =3D sk_stream_wait_connect(sk, &timeo); if (ret) --=20 2.55.0 From nobody Thu Nov 5 07:28:36 2026 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1792720760; b=fK0H1hZwIThInhpQoDs+bJzmo0dSVnuqW4VQGGd8k/gMlfJXyE1548eald4qvRkzrRIV p2Jjs3UBpZe8/tCsPimXPBKnqbVticoH3+ldiJU5d6F44Hg3QB5WMJ1FSdrGAkKfaO9RU 3weoqt1ZkFuT8SL0sRrn2apg+sGniI9aMIHBoAtqHfZ8MH296oMYYRo+pDmKiP/ncUPWW Y2Y0GYrPbqj3MX0mP2Q8To1Fn8UACWapV3VZOm0K3HwBTFZyY1D6LVD2sXsvY+pdADoVY nN+ykJBJxas1WlduHW1N4kwDM0CCqbH4gSbAN4Q3n0/RW0djdHI3ptO73EopITZF7cg== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1792720760; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=+gOLQ02/NTNKZ+XxapkuoZpLo3esQRw2sPS8XUF0ZO4=; b=b5YOIZt+CtXVn+ON6o09FVpWXnjo+opLoBWX089oapWpXD/wOXhPFHScHbn91wK2IWjB 0E+5ItxGKMoYoLl3RHtpUcWjM1yRC3+iSXJI++zIUnZPiLrfJhvuCY0h1tK6L9IKh0pmR DTsWh+GH/zb7/MU1UIppVSRzaPHIzpm0Ycnyx+za3b8jdw3aHGiTLDOa9ekzm1M0byokq fiuEK9ZXJETY0V5WhApmSpOnVGuuNGcrVsy1Mp1z+abg3UC5U4pV2xvuysWipeOpdjECX eHPHlm0rY1PEoi2H0+xd5aD5IIqIv9UvfYye1V95CFa5s4XtQMStcvbgH5kmEn2VmSA== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=NF1A93X5; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1683C606A319 for ; Fri, 23 Oct 2026 01:59:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=NF1A93X5 Received: by smtp.kernel.org (Postfix) with ESMTPSA id C55C81F01829; Fri, 23 Oct 2026 01:59:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1792720759; bh=+gOLQ02/NTNKZ+XxapkuoZpLo3esQRw2sPS8XUF0ZO4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=NF1A93X5Tkh5jOT6vRfpvx3NK62RFx2sAH3d5H/Sc71xNaBhVNcV/goZyhm8FdMxR gv9eAo47s1bkDXeSONWLq+KPIzlRGIYFRMDyDs4i4ApxtcW5/nKcc5KgV0F5eAJnlD gW10O/oQw0fgq+sR4WfaV5jjAmwL8iXEXtU1NXHpWIOLp4jN1zMQXAbaifHXEied23 RxCea9vFDoHYfFFg3Jr00iJN89w4OjKq8+kW1titzzwDDIUFs/hG0YquutY75Gm0EB QfPr/sPuafkJZhyUcCX084c6RecBkW8EhSfwnUkWhG9DQIWEVo74V5I9NLOdh9y9U5 wHGEAWMZ3kHhA== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Geliang Tang Subject: [PATCH mptcp-next v15 10/11] selftests: mptcp: sockopt: check app_limited Date: Fri, 23 Oct 2026 09:58:51 +0800 Message-ID: <24897c9e72a3f0a2d489dcd7f1c2413eef88c85a.1792718041.git.tanggeliang@kylinos.cn> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Geliang Tang connect_one_server() in mptcp_sockopt exchanges only a few packets between the client and server, then closes the socket. After such a small transfer the application has nothing further to send, so the connection is, by definition, application-limited. Extend the TCP_INFO readback at the end of the function to assert s.tcp_info.tcpi_delivery_rate_app_limited =3D=3D 1. Without the preceding commit, mptcp_sendmsg() never updates the per-subflow app-limited state, and this field stays at 0 - the assertion would fail. With it in place, the value is forced to 1, turning this into a regression guard for the subflow-side application-limited accounting. Signed-off-by: Geliang Tang --- tools/testing/selftests/net/mptcp/mptcp_sockopt.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/test= ing/selftests/net/mptcp/mptcp_sockopt.c index b8158a1198eb..f7a45b93cbe0 100644 --- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c +++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c @@ -635,6 +635,11 @@ static void connect_one_server(int fd, int pipefd) do_getsockopts(&s, fd, total, total); =20 assert(s.mptcpi_rcv_delta =3D=3D (uint64_t)total); + + /* app-limited accounting requires a recent kernel */ + if (expect_all_features()) + assert(s.tcp_info.tcpi_delivery_rate_app_limited =3D=3D 1); + close(fd); } =20 --=20 2.55.0 From nobody Thu Nov 5 07:28:36 2026 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1792720761; b=W8MPL5h+5pFPfJtCghBbocpzfsWmbIe4lzNAmbqjjeNzxABya3zlLLplOv/VscT6ZnES WfliB90x3X2uUG4oyL6Y1l7UkOo9jCD/fkVlccx3LT9XAvxEF/IniNXgLxECIOmfQcN2F MAxUq+B842dayoMtf8i2h4PqdSkOqHAg/5iCNDOGDiGooP9VysnvizSc1X99Eo21YdjwP xS2SWlCYTEXMWEMC9BF6AI7/fYT15eQeF56eDBPlYP8epYf9a23IuxwcHJz5QP3iNAXAh TLHRqh4RxH8Ti+JB8CwF8Vb02xoGjuQ5far2VvQ3stnFfEicOutOEylu4EYbzcYnEtg== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1792720761; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=QLA8nRp+J+ZN/0Lmikqab9RD9h6hAbJWHw0a5dRFjPo=; b=BoEcFdt6bjoSxCDYWUbdjI9EYVrn5sFC1yAXXvFsyd6o2piFG8HR8XK9Z0sKJyAGSA6b cw5StRPwtBCgkWJuUCrsvOC3HOeMDxmGXyFq/98h4SA1CRIAoDiXTTwMNQsaT0WQXF0YO qiAQhq/tkLv7K7q6P4C5U/YFv6wl8MmYHtacKqm8/S7V+tXHLFaNPuPY232Zhn+Jo8uN8 KE6bnq/Hgg+G4TIM+VYDp0cMRwTVWM3ZDNlr9RokAFWglSeb/LVnIc9Pw697Aiy5Si/kw 7iYN+IWqAZxFrOE1eKeE+PjCr+0A5xDLPPWkvAB8pHa9fiB/53WXnBoA8A/M2g4B3jA== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=LWFgfggD; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 72659606A319 for ; Fri, 23 Oct 2026 01:59:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=LWFgfggD Received: by smtp.kernel.org (Postfix) with ESMTPSA id 27A521F031E4; Fri, 23 Oct 2026 01:59:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1792720761; bh=QLA8nRp+J+ZN/0Lmikqab9RD9h6hAbJWHw0a5dRFjPo=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=LWFgfggDbr9e3IxXMOeA2VugjEVv6ZFHU4HtlH5H3xrgQWe14Iv383+M8T3dwvrTx de3w8I7Dfw3szRQNKpmbGeH+XGEXeN7PvhOY7EbCPIocVRf4JNW/w/BmNVfDG5lh6W VZnwwNx14AAOWLuEGJsIxS4LZjoSYBx1n2PjgVC+OG04QR7OG3AlV4RJarS8Kuy9ZC Olt4up40HCTG5I7+lZ4fH2PRdxluu43M8ajOlTH2yy4BCUdUafmQelxoc8TTmclklY koIZfEc6rynM7NKLI1J9DZC8qEDDVbdMU6UzokSl7C7paWOBPAvu5Mfs/HYIRuwZVh 4f7UUNANzro9A== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Gang Yan , Geliang Tang Subject: [PATCH mptcp-next v15 11/11] mptcp: update mptcp_check_readable Date: Fri, 23 Oct 2026 09:58:52 +0800 Message-ID: <318e9e95ab018136db65e2c82a7718687cae755a.1792718041.git.tanggeliang@kylinos.cn> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Gang Yan This patch makes mptcp_check_readable() aligned with TCP, and renames it to mptcp_stream_is_readable(). It will be used in the case of KTLS, because 'prot' will be modified, tls_sw_sock_is_readable() is expected to be called from prot->sock_is_readable(). Co-developed-by: Geliang Tang Signed-off-by: Geliang Tang Signed-off-by: Gang Yan --- net/mptcp/protocol.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 7870b9be76c7..b224b53c0888 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -3550,9 +3550,11 @@ void __mptcp_unaccepted_force_close(struct sock *sk) __mptcp_destroy_sock(sk); } =20 -static __poll_t mptcp_check_readable(struct sock *sk) +static bool mptcp_stream_is_readable(struct sock *sk) { - return mptcp_epollin_ready(sk) ? EPOLLIN | EPOLLRDNORM : 0; + if (mptcp_epollin_ready(sk)) + return true; + return sk_is_readable(sk); } =20 static void mptcp_check_listen_stop(struct sock *sk) @@ -4666,7 +4668,8 @@ static __poll_t mptcp_poll(struct file *file, struct = socket *sock, mask |=3D EPOLLIN | EPOLLRDNORM | EPOLLRDHUP; =20 if (state !=3D TCP_SYN_SENT && state !=3D TCP_SYN_RECV) { - mask |=3D mptcp_check_readable(sk); + if (mptcp_stream_is_readable(sk)) + mask |=3D EPOLLIN | EPOLLRDNORM; if (shutdown & SEND_SHUTDOWN) mask |=3D EPOLLOUT | EPOLLWRNORM; else --=20 2.55.0