From: gang.yan@linux.dev
To: "Paolo Abeni" <pabeni@redhat.com>, mptcp@lists.linux.dev
Cc: "Shardul Bankar" <shardul.b@mpiricsoftware.com>
Subject: Re: [PATCH mptcp-next v5 06/12] mptcp: remove CB offset field
Date: Wed, 27 May 2026 08:28:11 +0000 [thread overview]
Message-ID: <f5c9f4f37aaa1c80e4cee213afdeb483ca9d957d@linux.dev> (raw)
In-Reply-To: <ec9e2e3d5004c3fc86353fc9a419529c956f8e44.1778446731.git.pabeni@redhat.com>
May 11, 2026 at 5:03 AM, "Paolo Abeni" <pabeni@redhat.com mailto:pabeni@redhat.com?to=%22Paolo%20Abeni%22%20%3Cpabeni%40redhat.com%3E > wrote:
>
> 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 was always ignored, now it
> affects the `copied_seq` initial update: be sure to extends the sign
> correctly of such mapping initialization time.
>
> Overall this simplify a bit the __mptcp_recvmsg_mskq(), mptcp_inq_hint()
> and the __mptcp_move_skb() code and will also make possible the next
> patch.
>
> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
> ---
> v4 -> v5:
> - fix transient build issue, restoring a __mptcp_move_skb() chunk that
> leaked in the next patch.
>
> v3 -> v4:
> - fix peek seq race
>
> v2 -> v3:
> - do not use msk->first in release_cb to deal with MPTCP_SYNC_SEQ:
> subflow->iasn access is (data) racy and msk->first can be null, instead
> recompute iasn from msk bytes_received and TFO skb len
> - when updating copied_seq after remote key reception, add iasn to it
> instead of overwriting, to avoid deleting any partial progress.
>
> v1 -> v2:
> - deal correctly with peek, as usally "inspired" from the correspondent
> tcp code
> - update mptcp_inq_hint(), too
>
> Notes:
> - this explicitly relays on "mptcp: do not drop partial packets" to
> avoid dropping partially consumed packets
> - sashiko may confuse the 'offset' in mptcp_init_skb for an MPTCP-level
> one, but it refers to the TCP sequence space. Conclusion out of the
> that assumptions are wrong.
> - the data race in mptcp_inq_hint() is real, but pre-existing and can
> impact only sockopt() output - the other call-sites are race free, as
> ack_seq updates are serialized by the RX path.
> Fixing the race for good without sashiko tripping on other similar
> minor races would require another largish series. Postponed.
> - sashiko may see a race with `copied_seq` in mptcp_recv_skb(), that is
> not real: subflow_set_remote_key()/__mptcp_sync_rcv_sequence() has seen
> the msk owned; if mptcp_data_ready() has seen again the msk owend, the
> only skb in the receive queue can be the (unsynched) TFO one, with dummy
> sequence. If mptcp_data_ready() observed msk not owned and queued more
> skbs, the release_cb() has run and synched `copied_seq` and TFO skb
> map_seq.
> ---
> net/mptcp/fastopen.c | 15 +++--
> net/mptcp/protocol.c | 129 ++++++++++++++++++-------------------------
> net/mptcp/protocol.h | 8 ++-
> net/mptcp/subflow.c | 7 ++-
> 4 files changed, 77 insertions(+), 82 deletions(-)
>
> diff --git a/net/mptcp/fastopen.c b/net/mptcp/fastopen.c
> index c7d5bee8088e..03e605b050f8 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;
> @@ -43,20 +44,24 @@ void mptcp_fastopen_subflow_synack_set_params(struct mptcp_subflow_context *subf
> subflow->ssn_offset += skb->len;
> has_rxtstamp = TCP_SKB_CB(skb)->has_rxtstamp;
>
> - /* Only the sequence delta is relevant */
> - MPTCP_SKB_CB(skb)->map_seq = -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 = -(u64)skb->len;
> MPTCP_SKB_CB(skb)->end_seq = 0;
> - MPTCP_SKB_CB(skb)->offset = 0;
> MPTCP_SKB_CB(skb)->has_rxtstamp = has_rxtstamp;
>
> mptcp_data_lock(sk);
> DEBUG_NET_WARN_ON_ONCE(sock_owned_by_user_nocheck(sk));
>
> - mptcp_sk(sk)->rcvd_dummy_seq = true;
> + msk = mptcp_sk(sk);
> + msk->rcvd_dummy_seq = true;
> + msk->copied_seq = MPTCP_SKB_CB(skb)->map_seq;
> + msk->tfo_skb_len = skb->len;
> mptcp_borrow_fwdmem(sk, skb);
> skb_set_owner_r(skb, sk);
> __skb_queue_tail(&sk->sk_receive_queue, skb);
> - mptcp_sk(sk)->bytes_received += skb->len;
> + msk->bytes_received += skb->len;
>
> sk->sk_data_ready(sk);
>
> diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> index 6909586a3090..47df6d4a26a7 100644
> --- a/net/mptcp/protocol.c
> +++ b/net/mptcp/protocol.c
> @@ -28,7 +28,7 @@
> #include "protocol.h"
> #include "mib.h"
>
> -static unsigned int mptcp_inq_hint(const struct sock *sk);
> +static unsigned int mptcp_inq_hint(struct sock *sk);
>
> #define CREATE_TRACE_POINTS
> #include <trace/events/mptcp.h>
> @@ -160,7 +160,6 @@ static bool __mptcp_try_coalesce(struct sock *sk, struct sk_buff *to,
> int limit = READ_ONCE(sk->sk_rcvbuf);
>
> if (MPTCP_SKB_CB(from)->map_seq != 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;
> @@ -342,8 +341,7 @@ static void mptcp_data_queue_ofo(struct mptcp_sock *msk, struct sk_buff *skb)
> skb_set_owner_r(skb, sk);
> }
>
> -static void mptcp_init_skb(struct sock *ssk, struct sk_buff *skb, int offset,
> - int copy_len)
> +static void mptcp_init_skb(struct sock *ssk, struct sk_buff *skb, int offset)
> {
> struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
> bool has_rxtstamp = TCP_SKB_CB(skb)->has_rxtstamp;
> @@ -352,9 +350,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 = mptcp_subflow_get_mapped_dsn(subflow);
> - MPTCP_SKB_CB(skb)->end_seq = MPTCP_SKB_CB(skb)->map_seq + copy_len;
> - MPTCP_SKB_CB(skb)->offset = offset;
Hi Paolo:
Sorry for digging up this old thread.
Do you still plan to remove the offset field?
I've left some comments on Geliang's TLS patches [1], and the workaround patch needs
the offset field. Geliang and I would like to know whether you intend to drop it,
address it in the short term, or have no near-term plan for it.
[1] https://patchwork.kernel.org/project/mptcp/patch/6557d95ab11416b3e798781cf95811bd6dd60d9e.1779788090.git.tanggeliang@kylinos.cn/
Thanks
Gang
> + MPTCP_SKB_CB(skb)->map_seq = mptcp_subflow_get_mapped_dsn(subflow) -
> + offset;
> + MPTCP_SKB_CB(skb)->end_seq = MPTCP_SKB_CB(skb)->map_seq + skb->len;
> MPTCP_SKB_CB(skb)->has_rxtstamp = has_rxtstamp;
>
> __skb_unlink(skb, &ssk->sk_receive_queue);
> @@ -377,8 +375,8 @@ void __mptcp_sync_rcv_sequence(struct sock *sk)
> if (!skb)
> return;
>
> - MPTCP_SKB_CB(skb)->map_seq = msk->ack_seq - skb->len;
> - MPTCP_SKB_CB(skb)->end_seq = msk->ack_seq;
> + MPTCP_SKB_CB(skb)->map_seq = mptcp_iasn(msk) - skb->len;
> + MPTCP_SKB_CB(skb)->end_seq = MPTCP_SKB_CB(skb)->map_seq + skb->len;
> }
>
> static bool __mptcp_move_skb(struct sock *sk, struct sk_buff *skb)
> @@ -405,6 +403,7 @@ static bool __mptcp_move_skb(struct sock *sk, struct sk_buff *skb)
> }
>
> if (MPTCP_SKB_CB(skb)->map_seq == msk->ack_seq) {
> +add_queue:
> /* in sequence */
> msk->bytes_received += copy_len;
> WRITE_ONCE(msk->ack_seq, msk->ack_seq + copy_len);
> @@ -418,28 +417,16 @@ static bool __mptcp_move_skb(struct sock *sk, struct sk_buff *skb)
> } else if (after64(MPTCP_SKB_CB(skb)->map_seq, msk->ack_seq)) {
> mptcp_data_queue_ofo(msk, skb);
> return false;
> + } else if (after64(MPTCP_SKB_CB(skb)->end_seq, msk->ack_seq)) {
> + /* Partial packet: map_seq < ack_seq < end_seq.*/
> + copy_len -= msk->ack_seq - MPTCP_SKB_CB(skb)->map_seq;
> + goto add_queue;
> }
>
> - /* Completely old data? */
> - if (!after64(MPTCP_SKB_CB(skb)->end_seq, msk->ack_seq)) {
> - MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DUPDATA);
> - mptcp_drop(sk, skb);
> - return false;
> - }
> -
> - /* Partial packet: map_seq < ack_seq < end_seq.
> - * Skip the already-acked bytes and enqueue the new data.
> - */
> - copy_len = MPTCP_SKB_CB(skb)->end_seq - msk->ack_seq;
> - MPTCP_SKB_CB(skb)->offset += msk->ack_seq - MPTCP_SKB_CB(skb)->map_seq;
> - MPTCP_SKB_CB(skb)->map_seq += msk->ack_seq -
> - MPTCP_SKB_CB(skb)->map_seq;
> - msk->bytes_received += copy_len;
> - WRITE_ONCE(msk->ack_seq, msk->ack_seq + copy_len);
> -
> - skb_set_owner_r(skb, sk);
> - __skb_queue_tail(&sk->sk_receive_queue, skb);
> - return true;
> + /* Completely old data. */
> + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DUPDATA);
> + mptcp_drop(sk, skb);
> + return false;
> }
>
> static void mptcp_stop_rtx_timer(struct sock *sk)
> @@ -783,7 +770,7 @@ static bool __mptcp_move_skbs_from_subflow(struct mptcp_sock *msk,
> if (offset < skb->len) {
> size_t len = skb->len - offset;
>
> - mptcp_init_skb(ssk, skb, offset, len);
> + mptcp_init_skb(ssk, skb, offset);
>
> if (own_msk) {
> mptcp_subflow_lend_fwdmem(subflow, skb);
> @@ -850,8 +837,6 @@ static bool __mptcp_ofo_queue(struct mptcp_sock *msk)
> pr_debug("uncoalesced seq=%llx ack seq=%llx delta=%d\n",
> MPTCP_SKB_CB(skb)->map_seq, msk->ack_seq,
> delta);
> - MPTCP_SKB_CB(skb)->offset += delta;
> - MPTCP_SKB_CB(skb)->map_seq += delta;
> __skb_queue_tail(&sk->sk_receive_queue, skb);
> }
> msk->bytes_received += end_seq - msk->ack_seq;
> @@ -2095,34 +2080,22 @@ static void mptcp_eat_recv_skb(struct sock *sk, struct sk_buff *skb)
> }
>
> 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 = mptcp_sk(sk);
> struct sk_buff *skb, *tmp;
> - int total_data_len = 0;
> int copied = 0;
>
> skb_queue_walk_safe(&sk->sk_receive_queue, skb, tmp) {
> - u32 delta, offset = MPTCP_SKB_CB(skb)->offset;
> - u32 data_len = skb->len - offset;
> - u32 count;
> + u64 offset = *seq - MPTCP_SKB_CB(skb)->map_seq;
> + u32 count, data_len = skb->len - offset;
> int err;
>
> - if (flags & MSG_PEEK) {
> - /* skip already peeked skbs */
> - if (total_data_len + data_len <= copied_total) {
> - total_data_len += data_len;
> - *last = skb;
> - continue;
> - }
> -
> - /* skip the already peeked data in the current skb */
> - delta = copied_total - total_data_len;
> - offset += delta;
> - data_len -= delta;
> - }
> + /* Skip the already peeked data. */
> + if (offset >= skb->len)
> + continue;
>
> count = min_t(size_t, len - copied, data_len);
> if (!(flags & MSG_TRUNC)) {
> @@ -2140,14 +2113,12 @@ static int __mptcp_recvmsg_mskq(struct sock *sk, struct msghdr *msg,
> }
>
> copied += count;
> + *seq += count;
>
> if (!(flags & MSG_PEEK)) {
> msk->bytes_consumed += count;
> - if (count < data_len) {
> - MPTCP_SKB_CB(skb)->offset += count;
> - MPTCP_SKB_CB(skb)->map_seq += count;
> + if (count < data_len)
> break;
> - }
>
> mptcp_eat_recv_skb(sk, skb);
> } else {
> @@ -2296,25 +2267,23 @@ static bool mptcp_move_skbs(struct sock *sk)
> return enqueued;
> }
>
> -static unsigned int mptcp_inq_hint(const struct sock *sk)
> +static unsigned int mptcp_inq_hint(struct sock *sk)
> {
> const struct mptcp_sock *msk = mptcp_sk(sk);
> - const struct sk_buff *skb;
> -
> - skb = skb_peek(&sk->sk_receive_queue);
> - if (skb) {
> - u64 hint_val = READ_ONCE(msk->ack_seq) - MPTCP_SKB_CB(skb)->map_seq;
> + u64 hint_val;
>
> - if (hint_val >= INT_MAX)
> - return INT_MAX;
> -
> - return (unsigned int)hint_val;
> - }
> + /* Avoid races vs ack_seq updates. */
> + mptcp_data_lock(sk);
> + hint_val = msk->ack_seq - msk->copied_seq;
> + mptcp_data_unlock(sk);
> + if (hint_val >= INT_MAX)
> + return INT_MAX;
>
> - if (sk->sk_state == TCP_CLOSE || (sk->sk_shutdown & RCV_SHUTDOWN))
> + if (!hint_val &&
> + (sk->sk_state == TCP_CLOSE || (sk->sk_shutdown & RCV_SHUTDOWN)))
> return 1;
>
> - return 0;
> + return (unsigned int)hint_val;
> }
>
> static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
> @@ -2323,6 +2292,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
> struct mptcp_sock *msk = mptcp_sk(sk);
> struct scm_timestamping_internal tss;
> int copied = 0, cmsg_flags = 0;
> + u64 peek_seq, *seq;
> int target;
> long timeo;
>
> @@ -2342,6 +2312,11 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
>
> len = min_t(size_t, len, INT_MAX);
> target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
> + seq = &msk->copied_seq;
> + if (flags & MSG_PEEK) {
> + peek_seq = msk->copied_seq;
> + seq = &peek_seq;
> + }
>
> if (unlikely(msk->recvmsg_inq))
> cmsg_flags = MPTCP_CMSG_INQ;
> @@ -2351,7 +2326,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
> int err, bytes_read;
>
> bytes_read = __mptcp_recvmsg_mskq(sk, msg, len - copied, flags,
> - copied, &tss, &cmsg_flags,
> + seq, &tss, &cmsg_flags,
> &last);
> if (unlikely(bytes_read < 0)) {
> if (!copied)
> @@ -2406,6 +2381,10 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
> err = copied ? : err;
> goto out_err;
> }
> +
> + /* Recompute peek offset after eventual seq resync. */
> + if (flags & MSG_PEEK)
> + peek_seq = msk->copied_seq + copied;
> }
>
> mptcp_cleanup_rbuf(msk, copied);
> @@ -3500,11 +3479,13 @@ static int mptcp_disconnect(struct sock *sk, int flags)
> msk->bytes_retrans = 0;
> msk->rcvspace_init = 0;
> msk->fastclosing = 0;
> + msk->tfo_skb_len = 0;
> mptcp_init_rtt_est(msk);
>
> /* for fallback's sake */
> WRITE_ONCE(msk->ack_seq, 0);
> atomic64_set(&msk->rcv_wnd_sent, 0);
> + msk->copied_seq = 0;
>
> WRITE_ONCE(sk->sk_shutdown, 0);
> sk_error_report(sk);
> @@ -3729,8 +3710,10 @@ 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))
> + if (__test_and_clear_bit(MPTCP_SYNC_SEQ, &msk->cb_flags)) {
> + msk->copied_seq += mptcp_iasn(msk);
> __mptcp_sync_rcv_sequence(sk);
> + }
> }
> }
>
> @@ -4390,7 +4373,7 @@ static struct sk_buff *mptcp_recv_skb(struct sock *sk, u32 *off)
> mptcp_move_skbs(sk);
>
> while ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) {
> - offset = MPTCP_SKB_CB(skb)->offset;
> + offset = msk->copied_seq - MPTCP_SKB_CB(skb)->map_seq;
> if (offset < skb->len) {
> *off = offset;
> return skb;
> @@ -4432,11 +4415,9 @@ static int __mptcp_read_sock(struct sock *sk, read_descriptor_t *desc,
> copied += count;
>
> msk->bytes_consumed += count;
> - if (count < data_len) {
> - MPTCP_SKB_CB(skb)->offset += count;
> - MPTCP_SKB_CB(skb)->map_seq += count;
> + msk->copied_seq += count;
> + if (count < data_len)
> break;
> - }
>
> mptcp_eat_recv_skb(sk, skb);
> }
> diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
> index 16a1f4531dad..f3d852e52982 100644
> --- a/net/mptcp/protocol.h
> +++ b/net/mptcp/protocol.h
> @@ -129,7 +129,6 @@
> struct mptcp_skb_cb {
> u64 map_seq;
> u64 end_seq;
> - u32 offset;
> u8 has_rxtstamp;
> };
>
> @@ -289,6 +288,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;
> @@ -308,6 +308,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;
> @@ -859,6 +860,11 @@ struct sock *mptcp_subflow_get_retrans(struct mptcp_sock *msk);
> int mptcp_sched_get_send(struct mptcp_sock *msk);
> int mptcp_sched_get_retrans(struct mptcp_sock *msk);
>
> +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 5f371bf773f8..c8ea876bdd03 100644
> --- a/net/mptcp/subflow.c
> +++ b/net/mptcp/subflow.c
> @@ -499,10 +499,13 @@ static void subflow_set_remote_key(struct mptcp_sock *msk,
> WRITE_ONCE(msk->can_ack, true);
> atomic64_set(&msk->rcv_wnd_sent, subflow->iasn);
>
> - if (!sock_owned_by_user(sk))
> + if (!sock_owned_by_user(sk)) {
> + /* User space could have already read partially the TFO skb */
> + msk->copied_seq += subflow->iasn;
> __mptcp_sync_rcv_sequence(sk);
> - else
> + } else {
> __set_bit(MPTCP_SYNC_SEQ, &msk->cb_flags);
> + }
> }
>
> static void mptcp_propagate_state(struct sock *sk, struct sock *ssk,
> --
> 2.54.0
>
next prev parent reply other threads:[~2026-05-27 8:28 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-10 21:03 [PATCH mptcp-next v5 00/12] mptcp: address stall under memory pressure Paolo Abeni
2026-05-10 21:03 ` [PATCH mptcp-next v5 01/12] mptcp: do not drop partial packets Paolo Abeni
2026-05-11 10:14 ` Matthieu Baerts
2026-05-11 10:29 ` Matthieu Baerts
2026-05-11 10:52 ` Matthieu Baerts
2026-05-10 21:03 ` [PATCH mptcp-next v5 02/12] mptcp: explicitly drop over memory limits Paolo Abeni
2026-05-10 21:03 ` [PATCH mptcp-next v5 03/12] mptcp: enforce hard limit on backlog flushing Paolo Abeni
2026-05-10 21:03 ` [PATCH mptcp-next v5 04/12] mptcp: drop the mptcp_ooo_try_coalesce() helper Paolo Abeni
2026-05-10 21:03 ` [PATCH mptcp-next v5 05/12] mptcp: drop the cant_coalesce CB field Paolo Abeni
2026-05-10 21:03 ` [PATCH mptcp-next v5 06/12] mptcp: remove CB offset field Paolo Abeni
2026-05-27 8:28 ` gang.yan [this message]
2026-05-10 21:03 ` [PATCH mptcp-next v5 07/12] mptcp: sync mptcp skb cb layout with tcp one Paolo Abeni
2026-05-10 21:03 ` [PATCH mptcp-next v5 08/12] tcp: expose the tcp_collapse_ofo_queue() helper to mptcp usage, too Paolo Abeni
2026-05-10 21:03 ` [PATCH mptcp-next v5 09/12] mptcp: implemented OoO queue pruning Paolo Abeni
2026-05-10 21:03 ` [PATCH mptcp-next v5 10/12] mptcp: track prune recovery status Paolo Abeni
2026-05-10 21:03 ` [PATCH mptcp-next v5 11/12] mptcp: move the retrans loop to a separate helper Paolo Abeni
2026-05-10 21:03 ` [PATCH mptcp-next v5 12/12] mptcp: let the retrans scheduler do its job Paolo Abeni
2026-05-10 22:16 ` [PATCH mptcp-next v5 00/12] mptcp: address stall under memory pressure MPTCP CI
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=f5c9f4f37aaa1c80e4cee213afdeb483ca9d957d@linux.dev \
--to=gang.yan@linux.dev \
--cc=mptcp@lists.linux.dev \
--cc=pabeni@redhat.com \
--cc=shardul.b@mpiricsoftware.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox