From nobody Mon Aug 24 20:43:28 2026 Received: from sender4-of-o52.zoho.com (sender4-of-o52.zoho.com [136.143.188.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 98E7A345EBA for ; Sun, 26 Jul 2026 05:55:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.52 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785045358; cv=pass; b=RKpIcjjnVm0zQqR0mAwMnKDYUVEN6adeEKyNRn5UMchhH7ypOCYMeXfAInFEoXUl9L2GXyN4okgw9A7m3kIVwqybyHnwK607p4bJpxUY4jorEQLBSawQfLiYTQUjWPqZUFLqvCjtkn91EbPeOlSAWdB41H9Qm4B+iUCylpnORnE= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785045358; c=relaxed/simple; bh=Cv4Vjadr/xT4540f5vJ4RvllAke9wZV6FPfeUgyBrew=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=c4SSJp7SjPdwmRsqMb7kyZFC0AmsAWOR6/5Q8uc2JKJHXhum9N3sZxPekfOIwEAa7TAYfSGB9SOzbY6ntQqOHJpK1w+s7Z7lei1poRUqFOWAzYBaOqj+IGz7ohd002qneXuGiH9vroD/TBM/sYDx8/QWv2jtpxYxZGCXqdcuk1M= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mpiricsoftware.com; spf=pass smtp.mailfrom=mpiricsoftware.com; dkim=fail (0-bit key) header.d=mpiricsoftware.com header.i=shardul.b@mpiricsoftware.com header.b=nlUx+g44 reason="key not found in DNS"; arc=pass smtp.client-ip=136.143.188.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mpiricsoftware.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mpiricsoftware.com Authentication-Results: smtp.subspace.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=mpiricsoftware.com header.i=shardul.b@mpiricsoftware.com header.b="nlUx+g44" ARC-Seal: i=1; a=rsa-sha256; t=1785045349; cv=none; d=zohomail.com; s=zohoarc; b=Pcx6aJSTCAAZmXgax45oErpj13cUkYIIze+xWGb/NLtykmTAUMLc4oVC8QalsF5In6K5eKbbaPgr2o8/S142XRT+Xc+PFS9Sr7o9pk3eEk+A10xaMUbCTszAjamMAuKAd/9DNRsAtL4khes20s0zJ4jJ0CmwLbr7TuMSp63xHHY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785045349; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:Subject:Subject:To:To:Message-Id:Reply-To; bh=UVtITDEgz/KxhUnTc1UPqAUDFUyjySAdLQEixgkK4g0=; b=ZX36XphVUht70CUmHl09GD3AvgOisB5KfLN6SEwuXZ4gqZfSeiQIQs+fB49K3P4IPJPEYjV6Kp66ZCJUBbweRogglaOIvbYB/KXNKN6q1lxKAvB5dkQsj/qDeVUhHpDSulcfKs1fY9bkyca/YhV+lj4efAY7nHU/zbl4gxnfiJk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=mpiricsoftware.com; spf=pass smtp.mailfrom=shardul.b@mpiricsoftware.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1785045349; s=mpiric; d=mpiricsoftware.com; i=shardul.b@mpiricsoftware.com; h=From:From:Date:Date:Subject:Subject:MIME-Version:Content-Type:Content-Transfer-Encoding:Message-Id:Message-Id:In-Reply-To:To:To:Cc:Cc:Reply-To; bh=UVtITDEgz/KxhUnTc1UPqAUDFUyjySAdLQEixgkK4g0=; b=nlUx+g44IyNdNgvEg2qHDX/H+mIQatrYmdhb6wWyamSDdB0zi02C/1A1W16lBtTA 8Xl9bhfk+Ad12gTkFgAde5YzhuCZ0ifxATpHKAgz6XKQTuJgVW+vJ6UGcyPqiwoURBg ZaIiKUzUZiiOHtBoB/ZPihQDFZ5oGtgFHiiXm2Z0= Received: by mx.zohomail.com with SMTPS id 1785045347193826.8495920531584; Sat, 25 Jul 2026 22:55:47 -0700 (PDT) From: Shardul Bankar Date: Sun, 26 Jul 2026 11:25:39 +0530 Subject: [PATCH mptcp-next 1/3] mptcp: sched: penalise a slow subflow by halving its cwnd Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260726-mptcp_penalise_send-v1-1-84485e0e995b@mpiricsoftware.com> References: <20260726-mptcp_penalise_send-v1-0-84485e0e995b@mpiricsoftware.com> In-Reply-To: <20260726-mptcp_penalise_send-v1-0-84485e0e995b@mpiricsoftware.com> To: "Matthieu Baerts (NGI0)" , MPTCP Linux Cc: shardulsb08@gmail.com, Shardul Bankar X-Mailer: b4 0.15.2 X-ZohoMailClient: External Issue #345: a poorly-performing but usable subflow (high latency, loss, bufferbloat) can soak up connection resources and cause head-of-line blocking of the aggregate stream. Give the default packet scheduler a way to send less than such a subflow's full congestion window. Once a subflow has been picked for transmission, flag it for penalisation when: - its smoothed delivery rate (avg_pacing_rate) is below half that of the fastest path, keying on rate, not RTT, so a slow-but-high-throughput path is left alone; - the fastest path is cwnd-limited (saturated), so shifting load off the slow path is worthwhile; - the subflow is in TCP_CA_Open, so its cwnd is not already being reduced by loss recovery; - it has not been penalised in the last RTT. The reduction halves tcp_snd_cwnd (floor 2) and ssthresh if cwnd is past it. It is applied in the push path under the subflow socket lock, which protects snd_cwnd (the scheduler runs under the msk lock). The congestion control grows the window back, ACK-clocked; that regrowth is the built-in probe, so no explicit MPTCP-side probing is needed. Co-developed-by: Matthieu Baerts (NGI0) Signed-off-by: Shardul Bankar --- net/mptcp/protocol.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++= +--- net/mptcp/protocol.h | 2 ++ 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 954e20bb27de..d31bcb9ad894 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -1556,6 +1556,44 @@ bool mptcp_subflow_active(struct mptcp_subflow_conte= xt *subflow) #define SSK_MODE_BACKUP 1 #define SSK_MODE_MAX 2 =20 +/* Penalise a subflow whose delivery (pacing) rate is below the fraction + * 1 / MPTCP_PENALISE_RATE_RATIO of the fastest path's rate. Keying on rat= e, + * not RTT, throttles only a path whose throughput contribution is small + * relative to the head-of-line cost it imposes, and leaves a merely + * higher-latency but high-throughput path alone. + */ +#define MPTCP_PENALISE_RATE_RATIO 2 + +/* Rate-limit the penalty to at most once per subflow RTT, so the congesti= on + * control can grow the window back between reductions. + */ +static bool mptcp_penalise_throttle_ok(struct mptcp_subflow_context *subfl= ow) +{ + struct sock *ssk =3D mptcp_subflow_tcp_sock(subflow); + u32 rtt =3D usecs_to_jiffies(tcp_sk(ssk)->srtt_us >> 3); + + return tcp_jiffies32 - subflow->last_penalise >=3D max_t(u32, rtt, 1); +} + +/* Halve the congestion window (and ssthresh, if cwnd is past it) of a sub= flow + * the scheduler flagged. Runs in the push path under the subflow socket l= ock, + * which protects snd_cwnd. The congestion control grows the window back, + * ACK-clocked, and that regrowth is the built-in probe, so no explicit pr= obing + * is needed. + */ +static void mptcp_penalise_cwnd(struct sock *ssk) +{ + struct mptcp_subflow_context *subflow =3D mptcp_subflow_ctx(ssk); + struct tcp_sock *tp =3D tcp_sk(ssk); + u32 cwnd =3D tcp_snd_cwnd(tp); + + subflow->penalise =3D false; + subflow->last_penalise =3D tcp_jiffies32; + tcp_snd_cwnd_set(tp, max_t(u32, cwnd >> 1, 2)); + if (cwnd >=3D tp->snd_ssthresh) + tp->snd_ssthresh =3D max_t(u32, tp->snd_ssthresh >> 1, 2); +} + /* implement the mptcp packet scheduler; * returns the subflow that will transmit the next DSS * additionally updates the rtx timeout @@ -1565,9 +1603,9 @@ struct sock *mptcp_subflow_get_send(struct mptcp_sock= *msk) struct subflow_send_info send_info[SSK_MODE_MAX]; struct mptcp_subflow_context *subflow; struct sock *sk =3D (struct sock *)msk; - u32 pace, burst, wmem; + u32 pace, burst, wmem, max_pace =3D 0; int i, nr_active =3D 0; - struct sock *ssk; + struct sock *ssk, *fastest =3D NULL; u64 linger_time; long tout =3D 0; =20 @@ -1596,6 +1634,14 @@ struct sock *mptcp_subflow_get_send(struct mptcp_soc= k *msk) continue; } =20 + /* track the fastest path by delivery rate; the penalty below + * throttles paths that are slow relative to it. + */ + if (pace > max_pace) { + max_pace =3D pace; + fastest =3D ssk; + } + linger_time =3D div_u64((u64)READ_ONCE(ssk->sk_wmem_queued) << 32, pace); if (linger_time < send_info[backup].linger_time) { send_info[backup].ssk =3D ssk; @@ -1623,12 +1669,25 @@ struct sock *mptcp_subflow_get_send(struct mptcp_so= ck *msk) if (!ssk || !sk_stream_memory_free(ssk)) return NULL; =20 + /* Flag the chosen subflow for cwnd halving (applied in the push path) + * when its delivery rate is a small fraction of the fastest path's and + * that fast path is saturated (cwnd-limited), so moving load off the + * slow path is worthwhile. Only penalise a path in TCP_CA_Open, one + * whose cwnd is not already being shrunk by loss recovery, and at most + * once per RTT. + */ + subflow =3D mptcp_subflow_ctx(ssk); + subflow->penalise =3D fastest && ssk !=3D fastest && + (u64)subflow->avg_pacing_rate * MPTCP_PENALISE_RATE_RATIO < max_pac= e && + inet_csk(ssk)->icsk_ca_state =3D=3D TCP_CA_Open && + tcp_is_cwnd_limited(fastest) && + mptcp_penalise_throttle_ok(subflow); + burst =3D min(MPTCP_SEND_BURST_SIZE, mptcp_wnd_end(msk) - msk->snd_nxt); wmem =3D READ_ONCE(ssk->sk_wmem_queued); if (!burst) return ssk; =20 - subflow =3D mptcp_subflow_ctx(ssk); subflow->avg_pacing_rate =3D div_u64((u64)subflow->avg_pacing_rate * wmem= + READ_ONCE(ssk->sk_pacing_rate) * burst, burst + wmem); @@ -1685,6 +1744,9 @@ static int __subflow_push_pending(struct sock *sk, st= ruct sock *ssk, struct mptcp_data_frag *dfrag; int len, copied =3D 0, err =3D 0; =20 + if (mptcp_subflow_ctx(ssk)->penalise) + mptcp_penalise_cwnd(ssk); + while ((dfrag =3D mptcp_send_head(sk))) { info->sent =3D dfrag->already_sent; info->limit =3D dfrag->data_len; diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index da40c6f3705f..2bf801292563 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -587,6 +587,7 @@ struct mptcp_subflow_context { __unused : 8; bool data_avail; bool scheduled; + bool penalise; /* scheduler flagged this subflow for cwnd halving */ bool pm_listener; /* a listener managed by the kernel PM? */ bool fully_established; /* path validated */ u32 lent_mem_frag; @@ -606,6 +607,7 @@ struct mptcp_subflow_context { u8 stale_count; =20 u32 subflow_id; + u32 last_penalise; /* tcp_jiffies32 of the last cwnd penalty */ =20 long delegated_status; unsigned long fail_tout; --=20 2.34.1 From nobody Mon Aug 24 20:43:28 2026 Received: from sender4-of-o52.zoho.com (sender4-of-o52.zoho.com [136.143.188.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 93B2D339872 for ; Sun, 26 Jul 2026 05:56:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.52 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785045362; cv=pass; b=c7CVh9U+9+aH+G0xfu0ifxE66W07DJgY5IE8VANmXnK64xqV7ZfOvqny8pNARTCxEW6B2aObmnPwN6Y2wYs+ZMn2bCoCj7beJbSsXjRV5TrXCd87ewzJeJ+PUmKdjRnd6yw6w2GIs1+91nYoh86HCY4dLNdATdxierUpTHM774M= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785045362; c=relaxed/simple; bh=IrngOTyv/xvkQAyj1Sj54FBujjTULFNZDjyxERE2b3k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZZdsRqmndlaPQ+i/mpZEMoNvW9NNFxAlzlqJGmZzdnsnVpqpLbytCBXom1xDpdzVPmfpWwsTJJ/7ceiQu7xJKK5cluLczW5R2cBV0X0CL7jEluMUw+CRzTdJiYflBEqpwbHqH+Brcu6vkiT2DH9uDXii2t+Tj3YXYVTDPiwMbow= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mpiricsoftware.com; spf=pass smtp.mailfrom=mpiricsoftware.com; dkim=fail (0-bit key) header.d=mpiricsoftware.com header.i=shardul.b@mpiricsoftware.com header.b=JSroui9U reason="key not found in DNS"; arc=pass smtp.client-ip=136.143.188.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mpiricsoftware.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mpiricsoftware.com Authentication-Results: smtp.subspace.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=mpiricsoftware.com header.i=shardul.b@mpiricsoftware.com header.b="JSroui9U" ARC-Seal: i=1; a=rsa-sha256; t=1785045351; cv=none; d=zohomail.com; s=zohoarc; b=hTe08R8AJw5AB3R0L2hbcX57HirTdcVCCnN6/GIsXqrAfKCPaBiRt69LN1IUd50Zx8z660hk2qObN0T1uDJGfgkJqmDU4jQL0dkFKGZLINBIRMs/9xxcOHaTx//+jMnKSmMZI+ksPeE3LotAMJoAZAXibxEby5RCRCQgySj0th0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785045351; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:Subject:Subject:To:To:Message-Id:Reply-To; bh=raXRfOMEUBNatKu/dd12OUtxcNp1/GlVlHMcItvi4tw=; b=a7RKw+OggX6ix+gfhx6mfQRvnXCYK+tszwMycjD4G2E3AGXOFZbx+HFvAv1BmsvhE80Hrt8s/Yr7y6/BAAc5WB7uCq1D9c70ARWZecURVUf79kVkO4c32c6DyKRxTYSf1/XFm/H1m0pzc4jPE6oJkbEKhTfPvagxF8TzrnsAZ/M= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=mpiricsoftware.com; spf=pass smtp.mailfrom=shardul.b@mpiricsoftware.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1785045351; s=mpiric; d=mpiricsoftware.com; i=shardul.b@mpiricsoftware.com; h=From:From:Date:Date:Subject:Subject:MIME-Version:Content-Type:Content-Transfer-Encoding:Message-Id:Message-Id:In-Reply-To:To:To:Cc:Cc:Reply-To; bh=raXRfOMEUBNatKu/dd12OUtxcNp1/GlVlHMcItvi4tw=; b=JSroui9U2N2Ye8rEbh4BIlnDJJqQ/7hw0sOoxzDEK7/aaNxTZigk6aKDgtVn6tHP ZfPyhNguZ/pgfeGHS9F2fQg+xPXgcrd1BBitJIKf4lQ236fKlAk3eJclGJp4I0vsnQ2 0UZMiLGsIgaRUNmlHluSgOEDmYIl52+6vy3N1jvw= Received: by mx.zohomail.com with SMTPS id 17850453493021008.3102665354129; Sat, 25 Jul 2026 22:55:49 -0700 (PDT) From: Shardul Bankar Date: Sun, 26 Jul 2026 11:25:40 +0530 Subject: [PATCH mptcp-next 2/3] mptcp: sched: do not penalise when receive-window-limited Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260726-mptcp_penalise_send-v1-2-84485e0e995b@mpiricsoftware.com> References: <20260726-mptcp_penalise_send-v1-0-84485e0e995b@mpiricsoftware.com> In-Reply-To: <20260726-mptcp_penalise_send-v1-0-84485e0e995b@mpiricsoftware.com> To: "Matthieu Baerts (NGI0)" , MPTCP Linux Cc: shardulsb08@gmail.com, Shardul Bankar X-Mailer: b4 0.15.2 X-ZohoMailClient: External The penalty in the previous patch shifts load off a slow subflow onto the fastest one, which only helps if the fastest path can absorb it. When the connection is receive-window-limited (the receiver's advertised window, not our congestion window, is the bottleneck), the fastest path is capped by that shared window too and cannot send more, so halving the slow path's cwnd just sheds its throughput. In a receive-window-limited transfer this was measured roughly 2x slower than baseline. Gate on the application's queued data fitting within the send window: penalise only while write_seq <=3D wnd_end. If the application has queued past the window edge the receive window is the binding constraint, so skip the penalty. Both write_seq (application demand) and wnd_end (peer window) are standing values and neither is derived from cwnd, so the test is not biased by the scheduler sampling just after an ACK opened the window, nor made circular by the window itself suppressing cwnd. Co-developed-by: Matthieu Baerts (NGI0) Signed-off-by: Shardul Bankar --- net/mptcp/protocol.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index d31bcb9ad894..7cbc5aa17e22 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -1575,6 +1575,23 @@ static bool mptcp_penalise_throttle_ok(struct mptcp_= subflow_context *subflow) return tcp_jiffies32 - subflow->last_penalise >=3D max_t(u32, rtt, 1); } =20 +/* Only penalise when the connection is not receive-window-limited: all the + * data the application has queued fits within the current send window + * (write_seq <=3D wnd_end). If it has queued past the window edge, the pe= er's + * receive window (not our congestion window) is the bottleneck: the fast + * path is capped by that shared window too and cannot use capacity freed = from + * the slow path, so penalising would only shed the slow path's throughput. + * + * write_seq (application demand) and wnd_end (peer-advertised window) are= both + * standing values and neither is derived from cwnd, so unlike the instant= aneous + * window headroom this is not biased by the scheduler sampling just after= an + * ACK opened the window, nor circular when the window is what suppresses = cwnd. + */ +static bool mptcp_penalise_send_window_ok(const struct mptcp_sock *msk) +{ + return msk->write_seq <=3D mptcp_wnd_end(msk); +} + /* Halve the congestion window (and ssthresh, if cwnd is past it) of a sub= flow * the scheduler flagged. Runs in the push path under the subflow socket l= ock, * which protects snd_cwnd. The congestion control grows the window back, @@ -1681,6 +1698,7 @@ struct sock *mptcp_subflow_get_send(struct mptcp_sock= *msk) (u64)subflow->avg_pacing_rate * MPTCP_PENALISE_RATE_RATIO < max_pac= e && inet_csk(ssk)->icsk_ca_state =3D=3D TCP_CA_Open && tcp_is_cwnd_limited(fastest) && + mptcp_penalise_send_window_ok(msk) && mptcp_penalise_throttle_ok(subflow); =20 burst =3D min(MPTCP_SEND_BURST_SIZE, mptcp_wnd_end(msk) - msk->snd_nxt); --=20 2.34.1 From nobody Mon Aug 24 20:43:28 2026 Received: from sender4-of-o52.zoho.com (sender4-of-o52.zoho.com [136.143.188.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9D92F3451A6 for ; Sun, 26 Jul 2026 05:56:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.52 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785045366; cv=pass; b=kcRsFaogyd9yj93zqKQWTB2xW++qv9tGQdG95PxZwq7/JA+r1jG7+J9f0bpROHPvMXKX1GLqJnsztTjDAV/ymTIpjVR0OGHpd/F5PTiorrKl6qSybckMHMVlPCLWSWZ76HuW1ByTOhIucsF1lE3EOCXBt7y/avK1c4VKDW5fqVE= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785045366; c=relaxed/simple; bh=Wcl1OWRiaFLVILmKZz6aZn8uCA7GjZEbPMOJ+sshIak=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=DN8g3BBZC8yBkZvOkYMHmbS2hYtof+04x9T1vnb3tTvE3nOFptEVacrTKPN1Rs81QCEiFE+DpEzFUzwWPx3VP5dG9eqy0FfvcxHuTp0WDKF2HouwqBS9UqN1FcDvMmqw3jApCbTSt4ZJZX1tJEk4i+mKVaafKM/8Y2wyLvsNhRo= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mpiricsoftware.com; spf=pass smtp.mailfrom=mpiricsoftware.com; dkim=fail (0-bit key) header.d=mpiricsoftware.com header.i=shardul.b@mpiricsoftware.com header.b=jbi1Hhvc reason="key not found in DNS"; arc=pass smtp.client-ip=136.143.188.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mpiricsoftware.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mpiricsoftware.com Authentication-Results: smtp.subspace.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=mpiricsoftware.com header.i=shardul.b@mpiricsoftware.com header.b="jbi1Hhvc" ARC-Seal: i=1; a=rsa-sha256; t=1785045353; cv=none; d=zohomail.com; s=zohoarc; b=KnHbiCLnkordcWjHpJXxEYdTCRYaKdF5KpN6UEFvqknEPyJiAyCYHPXSim4+S4abNQ+U66qjUHnUez83wVdKAtLW+eZ2d/qiZSaeMH/qphKcsCTFlVCTlm5e9nvLpEVPO4Jc+aB/xUqyNJjYO2W8UK/82hFjP29IFJR5D2OL4Sk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785045353; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:Subject:Subject:To:To:Message-Id:Reply-To; bh=Tqt2yBJEanyGRFea0nNwPoftyscrGxxlGP6g7vyJOzI=; b=BxFNY/kvZI7Mgv20lYKetKHzcXPJkP7XmqTyDONMJZt9pg2Nf9iuoyQrXbD1AUZzC11so6d9Fq4mcynH9k3+qXWTHe744fLhL4HzaSG41nRgxIYsJoyhjbbH4qrf287xhQSrPALtisVpH5WYUwD5paLcqZKq1S3urnbOiapOvbs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=mpiricsoftware.com; spf=pass smtp.mailfrom=shardul.b@mpiricsoftware.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1785045353; s=mpiric; d=mpiricsoftware.com; i=shardul.b@mpiricsoftware.com; h=From:From:Date:Date:Subject:Subject:MIME-Version:Content-Type:Content-Transfer-Encoding:Message-Id:Message-Id:In-Reply-To:To:To:Cc:Cc:Reply-To; bh=Tqt2yBJEanyGRFea0nNwPoftyscrGxxlGP6g7vyJOzI=; b=jbi1Hhvc24bV7oQI/UWcBtav4ZkB54kWMi9oGX0ak3SOOqkKyH5d9vODckcPmZkX QqWufQdwOTiOYm3C7GP0J5RCyt9SHRmnKAAgb1+lxxwW2Nyy//yVP9WYMOdmq/wroS7 NUj9Zoepr9QYLePQRjE2r/zET12qIU7RKa6q0g78= Received: by mx.zohomail.com with SMTPS id 1785045351427869.0745547738172; Sat, 25 Jul 2026 22:55:51 -0700 (PDT) From: Shardul Bankar Date: Sun, 26 Jul 2026 11:25:41 +0530 Subject: [PATCH mptcp-next 3/3] DO-NOT-MERGE: mptcp: sched: penalise counters Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260726-mptcp_penalise_send-v1-3-84485e0e995b@mpiricsoftware.com> References: <20260726-mptcp_penalise_send-v1-0-84485e0e995b@mpiricsoftware.com> In-Reply-To: <20260726-mptcp_penalise_send-v1-0-84485e0e995b@mpiricsoftware.com> To: "Matthieu Baerts (NGI0)" , MPTCP Linux Cc: shardulsb08@gmail.com, Shardul Bankar X-Mailer: b4 0.15.2 X-ZohoMailClient: External Instrumentation for validating the two preceding patches; not for merge. Adds two MPTcpExt SNMP counters: - CwndPenalized: times a subflow cwnd was actually halved; - PenalCandidate: times the rate trigger picked a slow subflow. Together they separate "the guard held the penalty back" (PenalCandidate high, CwndPenalized ~0) from "the trigger never fired" (both ~0), which is what the receive-window-limited case needs to be read correctly. Co-developed-by: Matthieu Baerts (NGI0) Signed-off-by: Shardul Bankar --- net/mptcp/mib.c | 2 ++ net/mptcp/mib.h | 2 ++ net/mptcp/protocol.c | 8 ++++++++ 3 files changed, 12 insertions(+) diff --git a/net/mptcp/mib.c b/net/mptcp/mib.c index d9bd4f4afcc0..1299613e183b 100644 --- a/net/mptcp/mib.c +++ b/net/mptcp/mib.c @@ -88,6 +88,8 @@ static const struct snmp_mib mptcp_snmp_list[] =3D { SNMP_MIB_ITEM("BacklogDrop", MPTCP_MIB_BACKLOGDROP), SNMP_MIB_ITEM("RcvPruned", MPTCP_MIB_RCVPRUNED), SNMP_MIB_ITEM("OfoPruned", MPTCP_MIB_OFO_PRUNED), + SNMP_MIB_ITEM("CwndPenalized", MPTCP_MIB_CWNDPENALIZED), + SNMP_MIB_ITEM("PenalCandidate", MPTCP_MIB_PENALCAND), }; =20 /* mptcp_mib_alloc - allocate percpu mib counters diff --git a/net/mptcp/mib.h b/net/mptcp/mib.h index 18f35f7e0a2d..93b3a7e9584f 100644 --- a/net/mptcp/mib.h +++ b/net/mptcp/mib.h @@ -91,6 +91,8 @@ enum linux_mptcp_mib_field { MPTCP_MIB_BACKLOGDROP, /* Backlog over memory limit */ MPTCP_MIB_RCVPRUNED, /* Dropped due to memory constrains */ MPTCP_MIB_OFO_PRUNED, /* MPTCP-level OoO queue pruned */ + MPTCP_MIB_CWNDPENALIZED, /* DEBUG: subflow cwnd halved by the scheduler (= #345) */ + MPTCP_MIB_PENALCAND, /* DEBUG: picker chose a slow (low-rate) subflow */ __MPTCP_MIB_MAX }; =20 diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 7cbc5aa17e22..80866f09831a 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -1607,6 +1607,7 @@ static void mptcp_penalise_cwnd(struct sock *ssk) subflow->penalise =3D false; subflow->last_penalise =3D tcp_jiffies32; tcp_snd_cwnd_set(tp, max_t(u32, cwnd >> 1, 2)); + MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_CWNDPENALIZED); if (cwnd >=3D tp->snd_ssthresh) tp->snd_ssthresh =3D max_t(u32, tp->snd_ssthresh >> 1, 2); } @@ -1694,6 +1695,13 @@ struct sock *mptcp_subflow_get_send(struct mptcp_soc= k *msk) * once per RTT. */ subflow =3D mptcp_subflow_ctx(ssk); + /* DEBUG: count how often the trigger picks a slow path, so a gated-off + * run (PenalCandidate high, CwndPenalized 0) is distinguishable from one + * where the trigger never fired. + */ + if (fastest && ssk !=3D fastest && + (u64)subflow->avg_pacing_rate * MPTCP_PENALISE_RATE_RATIO < max_pace) + MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_PENALCAND); subflow->penalise =3D fastest && ssk !=3D fastest && (u64)subflow->avg_pacing_rate * MPTCP_PENALISE_RATE_RATIO < max_pac= e && inet_csk(ssk)->icsk_ca_state =3D=3D TCP_CA_Open && --=20 2.34.1