From: sashiko-bot@kernel.org
To: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>,
"MPTCP Linux" <mptcp@lists.linux.dev>
Subject: Re: [PATCH mptcp-next v2 3/8] mptcp: sched: let get_retrans reinject on an idle subflow
Date: Sat, 31 Oct 2026 22:57:55 +0000 [thread overview]
Message-ID: <sashiko-outbox-192214@kernel.org> (raw)
In-Reply-To: <20261031-mptcp-sched-opp-retrans-v2-3-e9c4a30f6841@kernel.org>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] mptcp: 32-bit overflow in __mptcp_oppr() and mptcp_oppr_send_range() budget math
- [Medium] mptcp: __mptcp_oppr() continues to later DSN ranges after partial send failure
--
commit be2c71f8537cecaea5b15cddbe5f79d5a824718f
Author: Abdul Wasey <w453y.me@gmail.com>
mptcp: sched: let get_retrans reinject on an idle subflow
This commit extends the MPTCP scheduler get_retrans callback to support
opportunistic reinjection on an idle subflow when no new data can be sent.
The core collects the unacknowledged DSN ranges held by other subflows and
resends them on the selected subflow up to reinject_limit and one cwnd.
Link: https://github.com/multipath-tcp/mptcp_net-next/issues/332 [1]
> diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> index d960ab9c76b32..7117786e52513 100644
> --- a/net/mptcp/protocol.c
> +++ b/net/mptcp/protocol.c
> @@ -3057,6 +3057,92 @@ static int __mptcp_push_retrans(struct sock *sk, struct mptcp_data_frag *dfrag,
> return len;
> }
>
> +/* resend [start, end) on @ssk from the msk rtx queue; < 0 on a send error */
> +static int mptcp_oppr_send_range(struct sock *sk, struct sock *ssk, u64 start,
> + u64 end, int budget,
> + struct mptcp_sendmsg_info *info)
> +{
> + struct mptcp_data_frag *dfrag;
> + int copied = 0, ret;
> +
> + list_for_each_entry(dfrag, &mptcp_sk(sk)->rtx_queue, list) {
> + if (!dfrag->already_sent || !before64(dfrag->data_seq, end))
> + break;
> + if (!after64(dfrag->data_seq + dfrag->already_sent, start))
> + continue;
> +
> + info->sent = before64(dfrag->data_seq, start) ?
> + start - dfrag->data_seq : 0;
> + info->limit = min_t(u64, dfrag->already_sent,
> + end - dfrag->data_seq);
> + info->limit = min_t(u64, info->limit,
> + info->sent + budget - copied);
> + while (info->sent < info->limit && copied < budget) {
> + ret = mptcp_sendmsg_frag(sk, ssk, dfrag, info);
> + if (ret <= 0)
> + return copied ? : -1;
> + copied += ret;
> + info->sent += ret;
> + }
> + if (copied >= budget)
> + break;
> + }
> + return copied;
> +}
> +
> +/* Opportunistic reinjection: the scheduling part is in sched.c */
> +static void __mptcp_oppr(struct sock *sk)
> +{
> + struct mptcp_sendmsg_info info = { .data_lock_held = true, };
> + struct mptcp_sock *msk = mptcp_sk(sk);
> + int copied = 0, budget, ret, i;
> + struct mptcp_sched_oppr oppr;
> + struct sock *ssk;
> +
> + mptcp_data_lock(sk);
> + __mptcp_clean_una_wakeup(sk);
> + oppr.una = msk->snd_una;
> + mptcp_data_unlock(sk);
> +
> + if (!mptcp_sched_oppr_get(msk, &oppr))
> + return;
> +
> + ssk = oppr.ssk;
> + lock_sock(ssk);
> + /* the scheduler's limit, and no more than one cwnd */
> + budget = min_t(u64, oppr.limit,
> + tcp_snd_cwnd(tcp_sk(ssk)) * tcp_sk(ssk)->mss_cache);
[Severity: Medium]
Can the budget calculation in __mptcp_oppr() and mptcp_oppr_send_range()
overflow 32-bit integers when a scheduler sets a large subflow->reinject_limit
on a subflow with a large cwnd?
In __mptcp_oppr(), tcp_snd_cwnd(tcp_sk(ssk)) and tcp_sk(ssk)->mss_cache are
both u32, so their multiplication is evaluated in 32-bit unsigned arithmetic
before min_t(u64, ...) promotes the product to u64, wrapping if the product
reaches 2^32.
In addition, oppr.limit is u32 while budget and copied are signed int. If both
oppr.limit and the cwnd * mss_cache product are >= 0x80000000U (for example
when a scheduler sets reinject_limit = U32_MAX on a high-BDP path), assigning
the min_t(u64, ...) result to signed int budget makes budget negative. The
loop condition copied < budget in __mptcp_oppr() is then immediately false,
skipping reinjection without updating msk->oppr_una.
Similarly, in mptcp_oppr_send_range():
info->limit = min_t(u64, info->limit,
info->sent + budget - copied);
info->sent + budget - copied is evaluated as a signed 32-bit int before
min_t(u64, ...) casts it to u64. If budget is near INT_MAX and info->sent >
copied (such as when start > dfrag->data_seq), the signed addition overflows
to a negative int, which sign-extends to a large u64 and fails to clamp
info->limit to the remaining budget.
> +
> + spin_lock_bh(&msk->fallback_lock);
> + if (__mptcp_check_fallback(msk) || !msk->allow_subflows)
> + goto unlock;
> +
> + for (i = 0; i < oppr.n && copied < budget; i++) {
> + ret = mptcp_oppr_send_range(sk, ssk, oppr.r[i].start,
> + oppr.r[i].end, budget - copied,
> + &info);
> + if (ret < 0)
> + break;
> + copied += ret;
> + }
[Severity: Medium]
If mptcp_sendmsg_frag() fails partway through sending a DSN range in
mptcp_oppr_send_range(), should __mptcp_oppr() stop rather than continuing to
subsequent ranges in oppr.r[]?
In mptcp_oppr_send_range(), when mptcp_sendmsg_frag() returns <= 0 (for
example -ENOMEM from sk_wmem_schedule() or 0 when hitting mptcp_wnd_end(msk))
after an earlier fragment in the same range already sent data (copied > 0),
it returns the positive copied count via:
if (ret <= 0)
return copied ? : -1;
Because the loop in __mptcp_oppr() only breaks on ret < 0, a partial send on
oppr.r[i] causes __mptcp_oppr() to advance to oppr.r[i + 1]. If a later,
smaller range succeeds, higher-DSN data is transmitted while leaving an unsent
gap in the earlier range that holds back snd_una, and msk->oppr_una is still
recorded as oppr.una so the failed portion is not retried for this snd_una.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261031-mptcp-sched-opp-retrans-v2-0-e9c4a30f6841@kernel.org?part=3
next prev parent reply other threads:[~2026-10-31 22:57 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-31 22:44 [PATCH mptcp-next v2 0/8] mptcp: sched: reinjection and a send limit as scheduler actions Matthieu Baerts (NGI0)
2026-10-31 22:44 ` [PATCH mptcp-next v2 1/8] mptcp: do not use a raised snd_wnd for the send window Matthieu Baerts (NGI0)
2026-10-31 22:44 ` [PATCH mptcp-next v2 2/8] mptcp: sched: let get_send limit what one decision sends Matthieu Baerts (NGI0)
2026-10-31 22:44 ` [PATCH mptcp-next v2 3/8] mptcp: sched: let get_retrans reinject on an idle subflow Matthieu Baerts (NGI0)
2026-10-31 22:57 ` sashiko-bot [this message]
2026-10-31 22:44 ` [PATCH mptcp-next v2 4/8] mptcp: sched: look for an idle subflow on each DATA_ACK Matthieu Baerts (NGI0)
2026-10-31 22:44 ` [PATCH mptcp-next v2 5/8] mptcp: sched: reinject on an idle subflow with the default scheduler Matthieu Baerts (NGI0)
2026-10-31 23:10 ` sashiko-bot
2026-10-31 22:44 ` [PATCH mptcp-next v2 6/8] mptcp: sched: let a BPF scheduler set the send and reinject limits Matthieu Baerts (NGI0)
2026-10-31 22:44 ` [PATCH mptcp-next v2 7/8] selftests: bpf: mptcp: test the send limit of a scheduler Matthieu Baerts (NGI0)
2026-10-31 22:58 ` sashiko-bot
2026-10-31 22:44 ` [PATCH mptcp-next v2 8/8] selftests: bpf: mptcp: test a scheduler reinjecting on an idle subflow Matthieu Baerts (NGI0)
2026-10-31 22:57 ` sashiko-bot
2026-11-01 13:20 ` [PATCH mptcp-next v2 0/8] mptcp: sched: reinjection and a send limit as scheduler actions 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=sashiko-outbox-192214@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=matttbe@kernel.org \
--cc=mptcp@lists.linux.dev \
--cc=sashiko-reviews@lists.linux.dev \
/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