From nobody Mon Aug 24 01:46:19 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 288FE443E21 for ; Mon, 17 Aug 2026 15:24:45 +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=1786980287; cv=pass; b=f6DcPg4fsXRgiVmZqR9KCSBE07Y/OCOHB40lnoNhX5Vfu5Nrh4EzWUe6fxmfDymqoi/MG7fI6TRMY83oVrLXEK/i8RZP/yULp80gzBH9UsFokJjdFyRNCfr+Qy8rnSrVdfcZP2/E4x3MexdF/WtziDCEKA7l8w6b/luTfmGZCfA= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786980287; c=relaxed/simple; bh=5qpBq6TMufhwOS//ppC7S8hbcjs6uSlV+ENpUdvWLwI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=F5gNSSk9oeEzWHVtuvvjJL8NzhnZ0xgUqDlkndZoBnOEqcbnJRpBvCmmFtnXDYbRT/YHaON7lfBfswrwjcNkphmrDVluxsV45rm72EoT+gnxusETX9Fyaerne/NgJuXSlWD02jTQ7SlSc75DJ1d/tyG5MwqUAynjR7N7v2u5IPA= 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=NoFwwOOV 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="NoFwwOOV" ARC-Seal: i=1; a=rsa-sha256; t=1786980276; cv=none; d=zohomail.com; s=zohoarc; b=nFVHWGBNmluNVTz1ZOfdlZdplPRjaktGYJtKuP1zxPYPrPyaXSfjYNOinYAX9nA5hVoPjNKQdFTM4ZW3U8n9A0fIFHlvFEwnwszyVebw5HOsLn83E1kMgIt8wLU0aHOPEyAM3Irdum+pfae+7Wu/i8VHGzcJy3jSoBQFqdNprew= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1786980276; 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=8DOkAHGpCJ8ngu+8XF3DXCdb4pYiNRd55hWsSFkl5t4=; b=Pr0JYxxx5j04rij87s+5YW8M/yd4SkCnDeS0qOmutB/0ptui7oX4qHktW1r8U/JzrcEZf2jGa4YleZK3oGeCMaAHNDjb9VITfK2T+DiGPPKLC/Y1YCVsEpKyGJAyl+ADDvnOogoH0A/2ziRvO5TQYWxsatMWd0rud5OkizoNqko= 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=1786980276; 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=8DOkAHGpCJ8ngu+8XF3DXCdb4pYiNRd55hWsSFkl5t4=; b=NoFwwOOVi2ole8AorvfEzt1cwJt0C2/jHpl83jPEsm5zo3zlcWoVBuw6QIw+4R7W ySIgMljdbNx+PTE/4sqbREZb+nKK/Ir+BGa3PB4AR5zPXRC7u0395HMrVS+joq+xUwL B9pMUtS+oE4rDzEblNoIr2LNNUqCCtaiHPnOOmLk= Received: by mx.zohomail.com with SMTPS id 1786980273228277.124296770401; Mon, 17 Aug 2026 08:24:33 -0700 (PDT) From: Shardul Bankar Date: Mon, 17 Aug 2026 20:54:14 +0530 Subject: [PATCH mptcp-next v3 1/4] mptcp: sched: avoid truncating the pacing rate in the scheduler 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: <20260817-mptcp_penalise_send_v2-v3-1-e6a2ad2f1b82@mpiricsoftware.com> References: <20260817-mptcp_penalise_send_v2-v3-0-e6a2ad2f1b82@mpiricsoftware.com> In-Reply-To: <20260817-mptcp_penalise_send_v2-v3-0-e6a2ad2f1b82@mpiricsoftware.com> To: mptcp@lists.linux.dev Cc: "Matthieu Baerts (NGI0)" , Janak Patel , Kalpan Jani , Shardul Bankar , Shardul Bankar X-Mailer: b4 0.15.2 X-ZohoMailClient: External mptcp_subflow_get_send() derives each subflow's linger time and a running pacing-rate average through a u32 "pace", while sk_pacing_rate and avg_pacing_rate are unsigned long. On 64-bit systems the u32 truncates pacing rates above ~4.29 GB/s, skewing the linger-time based subflow selection on very fast paths. On 32-bit systems, where unsigned long is also 32-bit, the sk_pacing_rate * burst product overflows: with burst up to ~65428 it wraps once the pacing rate exceeds ~526 kbit/s, misestimating the running average at ordinary rates. Widen "pace" to unsigned long, divide the linger time with a 64-bit divisor, and cast the pacing-rate average product to u64. Fixes: 3ce0852c86b9 ("mptcp: enforce HoL-blocking estimation") Suggested-by: Matthieu Baerts (NGI0) Signed-off-by: Shardul Bankar --- net/mptcp/protocol.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index c2762d74f29d..46a49ec75e78 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -1626,7 +1626,8 @@ 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; + unsigned long pace; + u32 burst, wmem; int i, nr_active =3D 0; struct sock *ssk; u64 linger_time; @@ -1657,7 +1658,7 @@ struct sock *mptcp_subflow_get_send(struct mptcp_sock= *msk) continue; } =20 - linger_time =3D div_u64((u64)READ_ONCE(ssk->sk_wmem_queued) << 32, pace); + linger_time =3D div64_u64((u64)READ_ONCE(ssk->sk_wmem_queued) << 32, pac= e); if (linger_time < send_info[backup].linger_time) { send_info[backup].ssk =3D ssk; send_info[backup].linger_time =3D linger_time; @@ -1691,7 +1692,7 @@ struct sock *mptcp_subflow_get_send(struct mptcp_sock= *msk) =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, + (u64)READ_ONCE(ssk->sk_pacing_rate) * burst, burst + wmem); msk->snd_burst =3D burst; return ssk; --=20 2.34.1 From nobody Mon Aug 24 01:46:19 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 79F1544780A for ; Mon, 17 Aug 2026 15:24:54 +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=1786980296; cv=pass; b=X72tXei8O8WprcFD0CMi/YOoHdYrc52spHqa6US6RbuGgVzllGQ9kHCunpeX6/nWJ72AG/Y5wYLSm3fdqRy96rY8yuNB6v9teWjsAWb4QXx0heMKX515gXEZj/y8WRoWxBd8obKuI5dwbeyIyzfnzpHo87jrPS2Hr0DrO+nfrxg= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786980296; c=relaxed/simple; bh=ZxexvrsCYi8oLZz5AAG150TFLFja1pDpM8pRvyIGVm8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KYLB8E8k1WysM2TyeUUwqlkSIhHaLkRCphPaZK029opPXC9M7cf6Tektaeln3DTGjbxf/itQQE/agWoSyFrnTJ0K161GCO+4eg+mr991cGLkm9sy2W20l2mCFAOMn7yjE5IYzZaxbOrcnJTUaOu/5xhw0bKDrznaJTbnvWxpsv0= 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=UpUQICau 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="UpUQICau" ARC-Seal: i=1; a=rsa-sha256; t=1786980280; cv=none; d=zohomail.com; s=zohoarc; b=LRQ4EB4EhiCKygCIPgayqUVPoapQUTQiDI9c1ykb/uoGws1Ymg10JbZBk6ZD6YrdkMAwWmIWtMgNO3wlo4cc7ifOVF0qDcM58zwfzQ5PoHXysVUxbn7OyaFnX6qAMLefVNZIix44K5kAkstFVI02gTLGj76cLcVQ1BOucjrFncA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1786980280; 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=ZVV6or4Eaj3eiGqEbMvw5TS3CQe+YKl3UdJDJfxbrAk=; b=L8P33o+f2rxggpTkixk5GUhV2y+RXOl9BAUYdd5/s4GyFnx63evDK0pl6CvQwqbHLptAWdHKvekmsuIBf6/RRWoPMka1XbifR9NLsQds5+3Y3uX+z3h7Qxtxym99Nlu4fsgmywnvLukUT4RLntkjklmKw0K3BXc6d6pn1JMf7NM= 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=1786980280; 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=ZVV6or4Eaj3eiGqEbMvw5TS3CQe+YKl3UdJDJfxbrAk=; b=UpUQICau9IiezaBSBQx5rasZ1phg3y5DiOa1siRtbzDVOenOvzqIhH8QWZ/jSLob zdQ0PcHNiigfI3jfE+qGqxldNKGXiDtP3B+Kq97w9PF/8hlXfjexJc9l+FKtfbRKJb+ FOhA5pR9EkdUyrcNQv5LsQXcr0JgAGBqz4uJKrCU= Received: by mx.zohomail.com with SMTPS id 1786980276042660.7226623471341; Mon, 17 Aug 2026 08:24:36 -0700 (PDT) From: Shardul Bankar Date: Mon, 17 Aug 2026 20:54:15 +0530 Subject: [PATCH mptcp-next v3 2/4] 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: <20260817-mptcp_penalise_send_v2-v3-2-e6a2ad2f1b82@mpiricsoftware.com> References: <20260817-mptcp_penalise_send_v2-v3-0-e6a2ad2f1b82@mpiricsoftware.com> In-Reply-To: <20260817-mptcp_penalise_send_v2-v3-0-e6a2ad2f1b82@mpiricsoftware.com> To: mptcp@lists.linux.dev Cc: "Matthieu Baerts (NGI0)" , Janak Patel , Kalpan Jani , Shardul Bankar , Shardul Bankar X-Mailer: b4 0.15.2 X-ZohoMailClient: External 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; - its cwnd is still above MPTCP_PENALISE_MIN_CWND, so a subflow already at the floor is left to recover instead of being churned by a halving that can no longer reduce it; - it has not been penalised in the last RTT. The reduction halves tcp_snd_cwnd, floored at MPTCP_PENALISE_MIN_CWND, 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. Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/345 Co-developed-by: Matthieu Baerts (NGI0) Signed-off-by: Shardul Bankar --- net/mptcp/protocol.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++= ---- net/mptcp/protocol.h | 2 ++ 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 46a49ec75e78..63cc6cb33044 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -1617,6 +1617,41 @@ bool mptcp_subflow_active(struct mptcp_subflow_conte= xt *subflow) #define SSK_MODE_BACKUP 1 #define SSK_MODE_MAX 2 =20 +/* Penalise a subflow pacing below the fastest path's rate / this ratio */ +#define MPTCP_PENALISE_RATE_RATIO 2 +/* cwnd floor for the penalty: skip a subflow already there, and never red= uce + * below it (halving at the floor only churns congestion control). + */ +#define MPTCP_PENALISE_MIN_CWND 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(READ_ONCE(tcp_sk(ssk)->srtt_us) >> 3); + + return tcp_jiffies32 - subflow->last_penalise >=3D max_t(u32, rtt, 1); +} + +/* Halve cwnd (and ssthresh if past it) under the subflow socket lock. */ +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; + /* CA state may have left TCP_CA_Open since get_send flagged this */ + if (inet_csk(ssk)->icsk_ca_state !=3D TCP_CA_Open) + return; + subflow->last_penalise =3D tcp_jiffies32; + tcp_snd_cwnd_set(tp, max_t(u32, cwnd >> 1, MPTCP_PENALISE_MIN_CWND)); + 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 @@ -1626,10 +1661,11 @@ struct sock *mptcp_subflow_get_send(struct mptcp_so= ck *msk) struct subflow_send_info send_info[SSK_MODE_MAX]; struct mptcp_subflow_context *subflow; struct sock *sk =3D (struct sock *)msk; - unsigned long pace; + unsigned long pace, max_pace =3D 0; u32 burst, wmem; + bool penal_cand; int i, nr_active =3D 0; - struct sock *ssk; + struct sock *ssk, *fastest =3D NULL; u64 linger_time; long tout =3D 0; =20 @@ -1658,6 +1694,12 @@ struct sock *mptcp_subflow_get_send(struct mptcp_soc= k *msk) continue; } =20 + /* track the fastest path; slower ones get throttled below */ + if (pace > max_pace) { + max_pace =3D pace; + fastest =3D ssk; + } + linger_time =3D div64_u64((u64)READ_ONCE(ssk->sk_wmem_queued) << 32, pac= e); if (linger_time < send_info[backup].linger_time) { send_info[backup].ssk =3D ssk; @@ -1685,12 +1727,24 @@ struct sock *mptcp_subflow_get_send(struct mptcp_so= ck *msk) if (!ssk || !sk_stream_memory_free(ssk)) return NULL; =20 + /* Flag a slow subflow for cwnd halving, applied in the push path */ + subflow =3D mptcp_subflow_ctx(ssk); + penal_cand =3D fastest && ssk !=3D fastest && + subflow->avg_pacing_rate < max_pace / MPTCP_PENALISE_RATE_RATIO; + subflow->penalise =3D penal_cand && + tcp_snd_cwnd(tcp_sk(ssk)) > MPTCP_PENALISE_MIN_CWND && + 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) + if (!burst) { + /* no window room to send; skip the penalty */ + subflow->penalise =3D false; return ssk; + } =20 - subflow =3D mptcp_subflow_ctx(ssk); subflow->avg_pacing_rate =3D div_u64((u64)subflow->avg_pacing_rate * wmem= + (u64)READ_ONCE(ssk->sk_pacing_rate) * burst, burst + wmem); @@ -1747,6 +1801,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 7e168e450fb0..ab9ba6699ccd 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -588,6 +588,7 @@ struct mptcp_subflow_context { __unused : 9; 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; @@ -611,6 +612,7 @@ struct mptcp_subflow_context { */ =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 01:46:19 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 926884457BD for ; Mon, 17 Aug 2026 15:25:03 +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=1786980304; cv=pass; b=W1vf9Kf+Vn9KSl5I0akrT9XLPxHi1fJOQ6fvVvx+KdJdpbpNz/BOWBdlHyZW5ZD0/NnGKPEG5kgATteBYfFwVVItoWwouhE4cPLYZSuggw5EQC6LtfdzNhK2AEfffgCjFbITWzFUd3Br4/HmRDQWvR+Sn72JrPFZSac/R+bb+ms= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786980304; c=relaxed/simple; bh=cmz+LFXRimnYZcBvePEmJn3lepx4hKH9TYoEq/anJuI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=oztyGKOguwF4Po3Gb312Hg0dBc+T9Y5zbAWzSMhj+eDjXfOU7utkSv6oJ7CwsSYztvFrVpVEW5Jdwxzl+hMJvzTDJ0T+DfU/uGpjdpd6sgR6oGMougzPm0sVzLL93UT8ZckJeKzWcxrGHICdRXEaaLaz+rpSOWuz32gH7bQLMPg= 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=NSD4Tre8 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="NSD4Tre8" ARC-Seal: i=1; a=rsa-sha256; t=1786980280; cv=none; d=zohomail.com; s=zohoarc; b=SJ/d6xJc32yhy+CSa0C30t849UAr7DrAzBCMRKCxP7gnFa0Al3247M6B/hSSXImmenz8w0hknASZeSjdMsJo3fwa1x/s146KrAV7XJCMeCj1/KnRvqNf7xYfsA1x5A3S7oIjrrmybclQabRduRtQtQG10mTmCpScTQHa13NSWRY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1786980280; 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=IT1RGbSMj2olkziZrqSlVR4n7m42XP3jJUmSRWhoJIM=; b=DZhsKhcdbgy3mXpD2IEkRdfnE/cSAA/yO5kPDMkxZuuxc1DMPcVaqDjAoc5jT1fuuExjWTdbna3XcsHSiFncvngUIAfz+x8bBSjyHrMI7ySrS3pNeVPUX431DAvc0DeaBSQI2qHOzjmdf0L9y+VtbkZ65LuZCsrer1HUv5+Plj8= 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=1786980280; 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=IT1RGbSMj2olkziZrqSlVR4n7m42XP3jJUmSRWhoJIM=; b=NSD4Tre8BagSXu7Yt7YN14bNLfWbwMeJvLvFPB4gey/ufmSGZhJdkVNOEog0l52y 3NNTYv57G3tGVNX3GdQ9vmsQ90Y/iLsGQcN9kOG0ZZH9Wc8Qfxsf9QdF7QxQxRNrhzW Up/6jgiK7AzGCGvEhZ6TmoXeD9+4tCGA8M1eiuak= Received: by mx.zohomail.com with SMTPS id 1786980278812793.2591084765892; Mon, 17 Aug 2026 08:24:38 -0700 (PDT) From: Shardul Bankar Date: Mon, 17 Aug 2026 20:54:16 +0530 Subject: [PATCH mptcp-next v3 3/4] 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: <20260817-mptcp_penalise_send_v2-v3-3-e6a2ad2f1b82@mpiricsoftware.com> References: <20260817-mptcp_penalise_send_v2-v3-0-e6a2ad2f1b82@mpiricsoftware.com> In-Reply-To: <20260817-mptcp_penalise_send_v2-v3-0-e6a2ad2f1b82@mpiricsoftware.com> To: mptcp@lists.linux.dev Cc: "Matthieu Baerts (NGI0)" , Janak Patel , Kalpan Jani , Shardul Bankar , 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. Neither write_seq (application demand) nor wnd_end (peer window) is derived from cwnd, so the test is not made circular by the window itself suppressing cwnd. Co-developed-by: Matthieu Baerts (NGI0) Signed-off-by: Shardul Bankar --- net/mptcp/protocol.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 63cc6cb33044..e4d26c2dce1e 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -1635,6 +1635,14 @@ static bool mptcp_penalise_throttle_ok(struct mptcp_= subflow_context *subflow) return tcp_jiffies32 - subflow->last_penalise >=3D max_t(u32, rtt, 1); } =20 +/* Like tcp_snd_wnd_test() but without an skb: true while queued data stil= l fits + * the send window, i.e. not receive-window-limited. + */ +static bool mptcp_snd_wnd_test(const struct mptcp_sock *msk) +{ + return !after64(msk->write_seq, mptcp_wnd_end(msk)); +} + /* Halve cwnd (and ssthresh if past it) under the subflow socket lock. */ static void mptcp_penalise_cwnd(struct sock *ssk) { @@ -1735,6 +1743,7 @@ struct sock *mptcp_subflow_get_send(struct mptcp_sock= *msk) tcp_snd_cwnd(tcp_sk(ssk)) > MPTCP_PENALISE_MIN_CWND && inet_csk(ssk)->icsk_ca_state =3D=3D TCP_CA_Open && tcp_is_cwnd_limited(fastest) && + mptcp_snd_wnd_test(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 01:46:19 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 D9FC44457A3 for ; Mon, 17 Aug 2026 15:25:11 +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=1786980313; cv=pass; b=tNuC6cVVzP+zOZEtC55qohDFoAY8hjHrlSzNdya48M6dF2qVKj8OwcZEdfctOTK62izPu7mEOwSs7XeOVqzCue3NjTZM1Vhm+2ylrjPgr2tQe0TfdysbmRGovfnbPnlKjE9KpZU7AhA7QnTnbOEmH1bLgvx6f+peWWk3XkpizRs= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786980313; c=relaxed/simple; bh=5Xlx2BdGhALhfgav/kNpUyUqqOfTNacfISs5LAHPIeE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=TnxQ7sGcBoL2y+gqmc24fFKdiKV6sD+GihLk+nKzkuNTBZ4LD0UwcV3tvYMkYNzYGHxbIg3yJF83cjUVfTqgR7uEIxh6PXYt53RsFWZWBiF5JJWuLBXb+auYy4doHNFn/I2/ZZ80sE0lDK/9Xo4wR+V+3iEJlENIF1noovEo/gE= 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=S9Zn4ugV 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="S9Zn4ugV" ARC-Seal: i=1; a=rsa-sha256; t=1786980284; cv=none; d=zohomail.com; s=zohoarc; b=Mn/N1mEkh8KD5K7gjHcpTJFi11LAZdJyuyFNwLxouoIN9cU/w1AjYXrouLboTd7VIN/cv8ili5w70bRBLeA9BMCkF09irCdOuudNvyhKrorTuZguYUsqLFIEGwIrOxK0jsxv19e9LW/e0t37XDaB5OY56pmwdy2H/bck8NsR4gU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1786980284; 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=y7QMjbRHXPk2m/YiLplTnKNPyWF4VNjbA8T2fHagA6E=; b=h9f4mzwYnzTU8LF1M62SoGpGrqc0STWfa8tX9mKh967O2N5B1C86qlTbO+atS6oafjm9V+RDNjE2noxRFyvQ+6EtN9CZP2iKmFYUSA2si65V4g5sskF/jqO3k2C2KqKQsbCF0qELwD0OMAxl7YGD4u/+Zkh+Jq4SHxHDbSeQSL0= 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=1786980284; 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=y7QMjbRHXPk2m/YiLplTnKNPyWF4VNjbA8T2fHagA6E=; b=S9Zn4ugVwCiolsWtCbe9b7krhYd/6cqaGADRsrxRP5gt3PG3wZAILKk4oS3sqVwP I0iuusGYhAKhVDbjXKaOdlgsHCHfowbCtmHyDEETNK9fgKY5V7nchD6o5sgrqZnvCe1 mG/IP2lqUMXgxxaED8Z8EwEaBfzDMOz1ykwksYWw= Received: by mx.zohomail.com with SMTPS id 1786980281520509.3735642146253; Mon, 17 Aug 2026 08:24:41 -0700 (PDT) From: Shardul Bankar Date: Mon, 17 Aug 2026 20:54:17 +0530 Subject: [PATCH mptcp-next v3 4/4] mptcp: sched: add penalise counters and tracepoint 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: <20260817-mptcp_penalise_send_v2-v3-4-e6a2ad2f1b82@mpiricsoftware.com> References: <20260817-mptcp_penalise_send_v2-v3-0-e6a2ad2f1b82@mpiricsoftware.com> In-Reply-To: <20260817-mptcp_penalise_send_v2-v3-0-e6a2ad2f1b82@mpiricsoftware.com> To: mptcp@lists.linux.dev Cc: "Matthieu Baerts (NGI0)" , Janak Patel , Kalpan Jani , Shardul Bankar , Shardul Bankar X-Mailer: b4 0.15.2 X-ZohoMailClient: External Add observability for the cwnd-halving penalty introduced in the previous patches. Two MPTcpExt SNMP counters: - CwndPenalised: times a subflow cwnd was actually halved; - PenalCandidate: times the rate trigger picked a slow subflow. The two show whether the rate trigger fired at all and how many of those candidates were actually halved; the gap reflects the gates and the once-per-RTT limiter collectively, not any single condition. Add a mptcp_subflow_penalise tracepoint. The penalise verdict is decided after the subflow-selection loop, once the fastest path is known, so it is exposed through a dedicated tracepoint rather than the per-candidate mptcp_subflow_get_send emit. It reports the selected subflow's pace, the fastest path's pace and its cwnd alongside the verdict, so a slow-but-gated subflow and its window can be watched from a single line. Co-developed-by: Matthieu Baerts (NGI0) Signed-off-by: Shardul Bankar --- include/trace/events/mptcp.h | 30 ++++++++++++++++++++++++++++++ net/mptcp/mib.c | 2 ++ net/mptcp/mib.h | 2 ++ net/mptcp/protocol.c | 6 ++++++ 4 files changed, 40 insertions(+) diff --git a/include/trace/events/mptcp.h b/include/trace/events/mptcp.h index 22882bd03459..fe13f0c8a34d 100644 --- a/include/trace/events/mptcp.h +++ b/include/trace/events/mptcp.h @@ -68,6 +68,36 @@ TRACE_EVENT(mptcp_subflow_get_send, __entry->backup, __entry->ratio) ); =20 +TRACE_EVENT(mptcp_subflow_penalise, + + TP_PROTO(struct mptcp_subflow_context *subflow, unsigned long max_pace), + + TP_ARGS(subflow, max_pace), + + TP_STRUCT__entry( + __field(u64, pace) + __field(u64, max_pace) + __field(u32, cwnd) + __field(bool, penalise) + ), + + TP_fast_assign( + struct sock *ssk =3D mptcp_subflow_tcp_sock(subflow); + + __entry->pace =3D subflow->avg_pacing_rate; + __entry->max_pace =3D max_pace; + if (ssk && sk_fullsock(ssk)) + __entry->cwnd =3D tcp_snd_cwnd(tcp_sk(ssk)); + else + __entry->cwnd =3D 0; + __entry->penalise =3D subflow->penalise; + ), + + TP_printk("pace=3D%llu max_pace=3D%llu cwnd=3D%u penalise=3D%d", + __entry->pace, __entry->max_pace, + __entry->cwnd, __entry->penalise) +); + DECLARE_EVENT_CLASS(mptcp_dump_mpext, =20 TP_PROTO(struct mptcp_ext *mpext), diff --git a/net/mptcp/mib.c b/net/mptcp/mib.c index 608cb568897c..b39b5511345d 100644 --- a/net/mptcp/mib.c +++ b/net/mptcp/mib.c @@ -95,6 +95,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_OFOPRUNED), + SNMP_MIB_ITEM("CwndPenalised", MPTCP_MIB_CWNDPENALISED), + 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 1ebdb55e9534..a7b5bf684af7 100644 --- a/net/mptcp/mib.h +++ b/net/mptcp/mib.h @@ -98,6 +98,8 @@ enum linux_mptcp_mib_field { MPTCP_MIB_BACKLOGDROP, /* Backlog over memory limit */ MPTCP_MIB_RCVPRUNED, /* Dropped due to memory constraints */ MPTCP_MIB_OFOPRUNED, /* MPTCP-level OoO queue pruned */ + MPTCP_MIB_CWNDPENALISED, /* subflow cwnd halved by the scheduler */ + MPTCP_MIB_PENALCAND, /* scheduler picked a slow (low-rate) subflow */ __MPTCP_MIB_MAX }; =20 diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index e4d26c2dce1e..0cd18705ab40 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -1656,6 +1656,7 @@ static void mptcp_penalise_cwnd(struct sock *ssk) return; subflow->last_penalise =3D tcp_jiffies32; tcp_snd_cwnd_set(tp, max_t(u32, cwnd >> 1, MPTCP_PENALISE_MIN_CWND)); + MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_CWNDPENALISED); if (cwnd >=3D tp->snd_ssthresh) tp->snd_ssthresh =3D max_t(u32, tp->snd_ssthresh >> 1, 2); } @@ -1739,6 +1740,8 @@ struct sock *mptcp_subflow_get_send(struct mptcp_sock= *msk) subflow =3D mptcp_subflow_ctx(ssk); penal_cand =3D fastest && ssk !=3D fastest && subflow->avg_pacing_rate < max_pace / MPTCP_PENALISE_RATE_RATIO; + if (penal_cand) + MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_PENALCAND); subflow->penalise =3D penal_cand && tcp_snd_cwnd(tcp_sk(ssk)) > MPTCP_PENALISE_MIN_CWND && inet_csk(ssk)->icsk_ca_state =3D=3D TCP_CA_Open && @@ -1746,6 +1749,9 @@ struct sock *mptcp_subflow_get_send(struct mptcp_sock= *msk) mptcp_snd_wnd_test(msk) && mptcp_penalise_throttle_ok(subflow); =20 + /* trace the penalise verdict, decided here after the selection loop */ + trace_mptcp_subflow_penalise(subflow, max_pace); + burst =3D min(MPTCP_SEND_BURST_SIZE, mptcp_wnd_end(msk) - msk->snd_nxt); wmem =3D READ_ONCE(ssk->sk_wmem_queued); if (!burst) { --=20 2.34.1