From nobody Thu Nov 5 07:28:14 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=1793256452; b=mHimpaJAZLevnPSPSZ63rkFmVxgoXTgGFZqTiU/t85sfbQyowVugyZGJkTSvb4ivPDQR +RPimgPkthDAGDZqWigpnQDtWx1eU0nWT8XfY0KXoI5CswLlq/dX9k9yqdfeu+v7Ghtmm wOYIoWJDOC1RMEdpZnFyVhToPs9AVB49UzezejhqUvFR7ppXAnHPHptD8PYBJ86QXMijD 4bGMc4beqGo2jcAJWMD4ZcRLg+MIcRmEd0RKbT3Fgpz73qZO6f+yJxY6HufgLjb6/XDMo 7Rqm7bew6AyfTisebftAWNt2SEyiMtq4m4vc9aHh75+tW4p0fLcT9bjri45tEDQTQWQ== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793256452; 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=Ht2rY0zEDIr7+ak10JaxU3A0vDh5APUFTH8AbvufCFUAScho4xsTUzNQmaiWnIjvDye0 YAcdhpJ5P+rVB8ek+xvAIGK6lguhc6T+kI2OBXI5q4DdciCuI8LeezSeq2l1J7NBtDJEr lyz6oHRyJUubFquw00dTVLFkpzLlgTg1hDgAofevHHt8ywg60Yr060eu3+8nl4aFcwNH8 h8nUTKK36N0OVWYnDFLkbcWm3GHhmsLL4mbSQSbulX3driXBMQFuUmuCCC0r95udyU1zX v1KZi20IrnrYrRPFlNpAkYkVcSwmq09Utp+1fPU4kxx5ACw9fCIHiQuwqqUPGd+PUuw== 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=MMWM40qL; 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 E8D87606A31A for ; Thu, 29 Oct 2026 06:47:31 +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=MMWM40qL Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6C5981F01828; Thu, 29 Oct 2026 06:47:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1793256451; bh=1J8C7pphSK2zVga48ZXLypGHUwLsv9JZ0n5GsGZOvyg=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=MMWM40qLvJ8llgxVVr4OR97AV2nQxDBw9NEzOQacftiAFqY5culm6UNzHV/0dU7kc 2WxMJ+s0Q7mAbvTqMz5ARwatvoynK9527uTNmBtzbi0ZEhBdMazInIqGaMGoHSo+SV jEOSCXvUdXMgBvaWJFHgSH+Ky+KQImY0Nm0MXVODsPL/jjZMgRoYW5XrxsYBoFzTq4 efF1kSPlFJEeT9/Ruxi2uVJg+ILhQi9xrQm0FVgdAf8dBAdOddMMWLuCXhp/h4uGoG O4uDJ2j6kaqFzYsPzeBh8FBihzboBu1eeCkpW0K6CX7Vio+MaDgkaAq2ATUbxL1v4g Edwb4bOH4Jn/A== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Paolo Abeni , Geliang Tang Subject: [PATCH mptcp-next v16 1/4] mptcp: drop the mptcp_ooo_try_coalesce() helper Date: Thu, 29 Oct 2026 14:47:18 +0800 Message-ID: <5dac2eda41edcfe40c67dab12718b118d6fbb39a.1793255126.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:14 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=1793256454; b=4UWCecZCluexoiX/TABiky7ug3qPBW3DO4lN3r4YcJ0VcU2G8w74Zr/oYk3d/mUJChLa +PXOPUtmCvt7vv3tpGvBZfU/Yf35FMDRT1gLpHHOcKFkDVbCAZKpLQqQakB93m22mDEeL dRUKv17Mu/LhdcoJQtYY5dr66/UX2H1iFGLMZ5LufX/PTt2Gv3p/9UHKOJaPNRkVEandZ XDQtmX/s4bmWuVXkXwhhe2sdsuwk/+jNExL70dYUOeYrGtX7futxT1QCfduZlJ6hYzVNO 6fh54fP9feKDHGnKOSTn3kI+vYmP5ME/0T9IrdipMRov4L4SgouLiF4pwbojBENM0Hg== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793256454; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=yof/nC0RT8Otoozptm3z/VS84Wqjdf+jiK0E83lkWl4=; b=XTWqF5I+q9n5yo5tYn4gUWGirPFwF9bX70kcSuy9Ao7+Tro6MIzwBTktTIHnjMqkp2Kr 7ZIDZlnGX5opspRmLSDBv+yIHA3UloBbqMcnslCvR/gv/RkjzfEa4PrIzi+oMqfcu7et1 egh7h5YNHdcHRpjId8ecOVgc57/x7wXPVLtCsNEE096PfWG8zVgASus/M/2jwC26sEGrr IrNBEXlKyy4/jKYUtpqyHNpQyUqkIogikr8Q/tT84Vf/ag58u7pGdTDXvJdvnLWujT5H+ GX+goycLp296Pd0X0sdIkVEX2SEXh1ab+zSZcnGU+1Qo1To3qaAwSf/CbwdKgNCOunw== 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="iMZ/1LqT"; 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 C7BBD606A31A for ; Thu, 29 Oct 2026 06:47:33 +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=iMZ/1LqT Received: by smtp.kernel.org (Postfix) with ESMTPSA id EFA051F01825; Thu, 29 Oct 2026 06:47:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1793256453; bh=yof/nC0RT8Otoozptm3z/VS84Wqjdf+jiK0E83lkWl4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=iMZ/1LqTyASZtQgZ3szMTjKFGh7ypxMNrRbdr3A4jBq/eiGIuR95hMHFAZLqxcTSA AlwAj9QO7Hw7mylFqxqJnHPQuh0fhERM7v08BWBWDkPiLnuHXv+OMLHmSSdF8vCo5Q duGAQI4XtDkXcg0wJB63v9jYKhQ7e5vKSdGTQuq7gO9ByZePDxuOBZY0KSyOS3744N pMFTbLwalWU7tPmGXqau5pWOui1aBbhjJZlLe3zMciFlcQpNnZzGYMYsGVBJ+PW81l 1hh8ap4IibGRAKDwixBpxFuG67xh7h/I+wQkLFExd6+TMECM3n28FjxUDTFRIxJjuG VaRaVQkftH32w== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Paolo Abeni , Geliang Tang Subject: [PATCH mptcp-next v16 2/4] mptcp: remove CB offset field Date: Thu, 29 Oct 2026 14:47:19 +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 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() and the __mptcp_move_skb() code and will also make possible the next patch. Co-developed-by: Geliang Tang Signed-off-by: Geliang Tang Signed-off-by: Paolo Abeni --- net/mptcp/fastopen.c | 12 ++++++++---- net/mptcp/protocol.c | 42 ++++++++++++++++++------------------------ net/mptcp/protocol.h | 2 +- net/mptcp/subflow.c | 15 ++++++++++++++- 4 files changed, 41 insertions(+), 30 deletions(-) diff --git a/net/mptcp/fastopen.c b/net/mptcp/fastopen.c index f717750906ff..04b1038b5200 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; @@ -44,20 +45,23 @@ 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; 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->copied_seq =3D MPTCP_SKB_CB(skb)->map_seq; 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..f89ed94b668d 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -169,7 +169,6 @@ static bool __mptcp_try_coalesce(struct sock *sk, struc= t sk_buff *to, =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)) return false; @@ -416,8 +415,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; @@ -426,9 +424,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; MPTCP_SKB_CB(skb)->cant_coalesce =3D 0; =20 @@ -472,10 +470,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 @@ -833,7 +827,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); @@ -896,12 +890,9 @@ static bool __mptcp_ofo_queue(struct mptcp_sock *msk) 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 */ 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; __skb_queue_tail(&sk->sk_receive_queue, skb); } msk->bytes_received +=3D end_seq - msk->ack_seq; @@ -2195,11 +2186,17 @@ static int __mptcp_recvmsg_mskq(struct sock *sk, st= ruct msghdr *msg, int copied =3D 0; =20 skb_queue_walk_safe(&sk->sk_receive_queue, skb, tmp) { - u32 delta, offset =3D MPTCP_SKB_CB(skb)->offset; + u32 delta, offset =3D (u32)msk->copied_seq - MPTCP_SKB_CB(skb)->map_seq; u32 data_len =3D skb->len - offset; u32 count; int err; =20 + /* Skip skbs that are entirely before copied_seq */ + if (offset >=3D skb->len) { + *last =3D skb; + continue; + } + if (flags & MSG_PEEK) { /* skip already peeked skbs */ if (total_data_len + data_len <=3D copied_total) { @@ -2233,11 +2230,9 @@ static int __mptcp_recvmsg_mskq(struct sock *sk, str= uct msghdr *msg, =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; + msk->copied_seq +=3D count; + if (count < data_len) break; - } =20 mptcp_eat_recv_skb(sk, skb); } else { @@ -3674,6 +3669,7 @@ static int mptcp_disconnect(struct sock *sk, int flag= s) mptcp_pm_data_reset(msk); mptcp_ca_reset(sk); msk->bytes_consumed =3D 0; + msk->copied_seq =3D 0; msk->bytes_acked =3D 0; msk->bytes_received =3D 0; msk->bytes_sent =3D 0; @@ -4601,7 +4597,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 (u32)msk->copied_seq - MPTCP_SKB_CB(skb)->map_seq; if (offset < skb->len) { *off =3D offset; return skb; @@ -4643,11 +4639,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 3be60da12924..5c1fa117e5d5 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -130,7 +130,6 @@ struct mptcp_skb_cb { u64 map_seq; u64 end_seq; - u32 offset; u8 has_rxtstamp; u8 cant_coalesce; }; @@ -311,6 +310,7 @@ struct mptcp_sock { u64 rcv_data_fin_seq; u64 bytes_retrans; u64 bytes_consumed; + u64 copied_seq; int snd_burst; int old_wspace; u64 recovery_snd_nxt; /* in recovery mode accept up to this seq; diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 78e886b20258..5e553adb9397 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -533,6 +533,19 @@ 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); + msk->copied_seq =3D subflow->iasn; + + if (subflow->is_mptfo) { + struct sock *sk =3D (struct sock *)msk; + struct sk_buff *skb; + + skb =3D skb_peek(&sk->sk_receive_queue); + if (skb) { + MPTCP_SKB_CB(skb)->map_seq =3D subflow->iasn - skb->len; + MPTCP_SKB_CB(skb)->end_seq =3D subflow->iasn; + msk->copied_seq -=3D skb->len; + } + } } =20 static void mptcp_propagate_state(struct sock *sk, struct sock *ssk, @@ -1485,7 +1498,7 @@ static bool subflow_check_data_avail(struct sock *ssk) skb =3D skb_peek(&ssk->sk_receive_queue); subflow->map_valid =3D 1; subflow->map_data_len =3D skb->len; - subflow->map_subflow_seq =3D tcp_sk(ssk)->copied_seq - subflow->ssn_offse= t; + subflow->map_subflow_seq =3D TCP_SKB_CB(skb)->seq - subflow->ssn_offset; subflow->map_seq =3D __mptcp_expand_seq(subflow->map_seq, subflow->iasn + TCP_SKB_CB(skb)->seq - --=20 2.55.0 From nobody Thu Nov 5 07:28:14 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=1793256456; b=WNzqpePhi4ZxmKwxlAz538km4YH5wHFkZ8uXQ2wcLtP+3wOEKTy0a4pHGrKDO80ISHyy neKjpmVqjqhEGYRI5drzH51PxttAPGB3XkrH/Ytbw8syvOjfofjJ1G00ACT1xvDVoB4W3 MtybZawp/fjn3aOTN8DBhVIRdmimFM9uzvfbZxbEg7eXwR3ry0QKtkLu3AvYWEqCt6sE0 mzs/6oDMku/oMIp3U5fL9Ta/uMsFWeOnNZkEqNX1nLv1bGwQWjpih3++WdE5lx1Bf4/AI ZPlx6AuxJLMsvZ1kZcRF+LAxguCrENPoHrmU6CDVWV+4PvZpM0teTkFJChkFrQymBLQ== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793256456; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=oN+HoiJUZboaHzoi8VhTYrI6OcWNUIyAZ6GD9gIoCjQ=; b=FffPey29SwBf8gGcyKtDPTOkALR38dZAK9rUr3u+APRWBul9PkXWGpvlhvhHu2Ct78zi whkRfWnai+58QgcP5bhvoqALHbwAMz+tsZSBJwdr1IuBB4XE3GhgcrNjQwwLwnNYepQZx 0enXldx43FJdCI3vbzJ/PJ1j85dThQoX34jjUlSYDU9Cl9wqrDmI/DkgW7srJskIdF9fc sqjALo1I9lF9h6DkLVQnEnTlsFl/ELX3JoP1aTKyReygk/vp4PkwOeXUfHD3m2XAAUahB SQ9qajPjMuqZDtxi6MlC/57Csrx+1MHwffk4Hsz86B7tKCr1l9SDlLs1sfjnuGCYWxg== 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=L2M8IVg3; 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 9B321606A31A for ; Thu, 29 Oct 2026 06:47:35 +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=L2M8IVg3 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3A26A1F01825; Thu, 29 Oct 2026 06:47:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1793256455; bh=oN+HoiJUZboaHzoi8VhTYrI6OcWNUIyAZ6GD9gIoCjQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=L2M8IVg3P8h3ctT3JMAai40eoN3T8pYoJx58+ScX1aTi+OuQQNEsoSdM2n75X8N4A BF6hfbmYxyS38LXibMRuzzN0J5n7r84t5DxgbcjJyD3eRw+0lyWUxIkBYHr3D+N8QV LPoHIj+RYNdAO7vEqhW4/PS0zPotZZNGdGSK2j0cABTYGRwilZmQlkXeoJ4spiQZhG ikhRdC84DrS4KvD6Y/xxNTClUaMZiI8HZlGCNuPh7x5P3UX8YHjoHGeEiEEFHZ2ecx EbdRnpRKGkqv3izDx/Rg1lOVC+9yI25aMandN9nrbitqZoO3v/M0UFpnr9Rigc94Rb Y2DPdPnP83iuw== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Paolo Abeni , Geliang Tang Subject: [PATCH mptcp-next v16 3/4] mptcp: sync mptcp skb cb layout with tcp one Date: Thu, 29 Oct 2026 14:47:20 +0800 Message-ID: <147b74d32860b750a1b281ae5b25951067d499d7.1793255126.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 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 | 88 +++++++++++++++++++++++++++----------------- net/mptcp/protocol.h | 7 +++- net/mptcp/subflow.c | 1 + 4 files changed, 64 insertions(+), 38 deletions(-) diff --git a/net/mptcp/fastopen.c b/net/mptcp/fastopen.c index 04b1038b5200..08f0402324c2 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; MPTCP_SKB_CB(skb)->cant_coalesce =3D 1; =20 @@ -57,7 +59,7 @@ void mptcp_fastopen_subflow_synack_set_params(struct mptc= p_subflow_context *subf DEBUG_NET_WARN_ON_ONCE(sock_owned_by_user_nocheck(sk)); =20 msk =3D mptcp_sk(sk); - msk->copied_seq =3D MPTCP_SKB_CB(skb)->map_seq; + msk->copied_seq =3D MPTCP_SKB_CB(skb)->map_seq64; 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 f89ed94b668d..bbce1bafa40e 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -168,12 +168,14 @@ 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 || unlikely(MPTCP_SKB_CB(to)->cant_coalesce) || ((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; @@ -255,8 +257,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; @@ -302,16 +304,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", @@ -346,7 +353,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; @@ -358,18 +365,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((u32)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 | @@ -400,7 +407,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); @@ -422,11 +429,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; MPTCP_SKB_CB(skb)->cant_coalesce =3D 0; =20 @@ -438,13 +447,13 @@ static void mptcp_init_skb(struct sock *ssk, struct s= k_buff *skb, int offset) =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 mptcp_borrow_fwdmem(sk, skb); =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)) { @@ -462,14 +471,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 @@ -864,39 +873,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)) { - int delta =3D msk->ack_seq - MPTCP_SKB_CB(skb)->map_seq; - - pr_debug("uncoalesced seq=3D%llx ack seq=3D%llx delta=3D%d\n", - MPTCP_SKB_CB(skb)->map_seq, msk->ack_seq, - delta); + 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; @@ -2392,7 +2399,8 @@ static unsigned int mptcp_inq_hint(const struct sock = *sk) =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; + u64 hint_val =3D READ_ONCE(msk->ack_seq) - + MPTCP_SKB_CB(skb)->map_seq64; =20 if (hint_val >=3D INT_MAX) return INT_MAX; @@ -4847,11 +4855,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 5c1fa117e5d5..2ab8342e198d 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -128,10 +128,13 @@ #define MPTCP_SYNC_SNDBUF 7 =20 struct mptcp_skb_cb { - u64 map_seq; - u64 end_seq; + u32 map_seq; + u32 end_seq; + u32 unused; + u16 flags; u8 has_rxtstamp; u8 cant_coalesce; + u64 map_seq64; }; =20 #define MPTCP_SKB_CB(__skb) ((struct mptcp_skb_cb *)&((__skb)->cb[0])) diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 5e553adb9397..d144eb2373ef 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -542,6 +542,7 @@ static void subflow_set_remote_key(struct mptcp_sock *m= sk, skb =3D skb_peek(&sk->sk_receive_queue); if (skb) { MPTCP_SKB_CB(skb)->map_seq =3D subflow->iasn - skb->len; + MPTCP_SKB_CB(skb)->map_seq64 =3D subflow->iasn - skb->len; MPTCP_SKB_CB(skb)->end_seq =3D subflow->iasn; msk->copied_seq -=3D skb->len; } --=20 2.55.0 From nobody Thu Nov 5 07:28:14 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=1793256457; b=q1Rmfw6/0l01l+frYSK4jgZbrzQtoTVMcmibVIWW658JIHLPPxO45oY0Y0NBbWd5vp19 NbO5B1Il54XV+CP/RUkdWEiftfgDRWmDQ/mEjssQ+G8qc0ueFrLaaasxBmjkjv0agpY3R b1BLSaqYW1AJhfOsPxdr6/JIjxXt1ewzhMs7EbWqgFBhWrYVa6W92QRj4dPCsLqsAg8K5 xDMawSQ1kwsc5JotSFgKt/adbVTNZGDV/YWQlrI1jadnK96Fr/Me7beZeUvDo+VZYD18k 99XsrQ6TWQ+nUFaS7h4zodoLY2i2Q6oaFtZFyHaLNBL2ij6c6LO6llEinNHWSoLBpww== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793256457; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=/pdOhH9uifXrjLVp13tr0nslqktQOyaJAlhej0blgow=; b=IMPIG/LmU2KtC/zSYqhhBdbipvcbw7rgfDlCxpmwgr1CmbzYFslelkKCyQYsLbWDyn9Y kB/PISr+WzZPqj/696crB8ivb4EExEEhjccxMSJh12M+Fh/BR6h30JaNZqj+2JkY568/q z6qksGmmgqGSD0FPReEzVaSRpiVJzpoiSBpgwYjLpl2yvZgWj/IC9RLuudNyeAxNApeBh lzs+Je1vcMJvVosiZD06qBBfya2JK5m+EwkUhQ8YiaP0yX/RohamxsWhoa2Mv8HOLdDGm JInHXhfhBh4GRF+8JmyVkh+jp+O95jKJPTIJ2Bq2cToqYSPOGxJUv7mP43sQYoIkFKA== 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=SwppdsVl; 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 8540A606A31A for ; Thu, 29 Oct 2026 06:47:37 +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=SwppdsVl Received: by smtp.kernel.org (Postfix) with ESMTPSA id A36EA1F031E2; Thu, 29 Oct 2026 06:47:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1793256456; bh=/pdOhH9uifXrjLVp13tr0nslqktQOyaJAlhej0blgow=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=SwppdsVlow80+WfUJ+hQI1aV1P/QmgQH2AC2S85xVy+m6P3f2ul0XrT/RLdYZnDY+ DGFxPYXbEvjqY+tAbwofDJWQoRLOVRhn1JRCqtKNHwtn5CHLW3gRpQzZSvN+sFCl5Q KrcdgcKawCL8h6g9pl1ahuK6NDIjYiLPg5Oew7vEwgBV+QjJCAq6Mitquai0r4fGqP ne0KYP6yLkGgo0TC0gK8Dv5t+Mgs+eAuXMarN9dskcyjIqooCc1yHZ8Zqgqt4uKerJ 4Bva3y2fMHXENFMeFx2wTv6IwU4H1hpPX49KEELiHQAPYWaVYnyTfsA81A08dHEO3S r3KnWhAXFevLg== From: Geliang Tang To: mptcp@lists.linux.dev Cc: Paolo Abeni , Geliang Tang Subject: [PATCH mptcp-next v16 4/4] mptcp: defer read_sock cleanup to mptcp_worker Date: Thu, 29 Oct 2026 14:47:21 +0800 Message-ID: <636807b42883e8ec741f2535293e02ff751af276.1793255126.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 When MPTCP carries TLS, __mptcp_read_sock() is reached from BH context (via tls_strp_read_copyin() -> sk->sk_read_sock()), where calling mptcp_rcv_space_adjust() and mptcp_cleanup_rbuf() is not safe as both expect process context. Move both calls to mptcp_worker(): __mptcp_read_sock() accumulates the consumed bytes 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 rcvbuf autotuning and RBU update in process context. Also remove the backlog flush from mptcp_recv_skb() (covered by mptcp_release_cb()), drop the msk_owned_by_me() assertion (BH caller does not own the msk lock), and drop the redundant mptcp_recv_skb() call after the main loop. Initialize msk->read_copied in __mptcp_init_sock() and reset it in mptcp_disconnect(). 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 bbce1bafa40e..322d7a5ba0b8 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -3121,6 +3121,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; @@ -3196,6 +3211,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); @@ -3239,6 +3257,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); @@ -3684,6 +3703,7 @@ static int mptcp_disconnect(struct sock *sk, int flag= s) msk->bytes_retrans =3D 0; msk->rcvspace_init =3D 0; msk->fastclosing =3D 0; + msk->read_copied =3D 0; mptcp_init_rtt_est(msk); =20 /* for fallback's sake */ @@ -4601,9 +4621,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) { @@ -4618,6 +4635,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) @@ -4627,8 +4645,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) { @@ -4659,11 +4675,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 2ab8342e198d..b0082e1c83f0 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; unsigned long flags; --=20 2.55.0