From nobody Sat Aug 15 20:35:21 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 752434248C9 for ; Sat, 15 Aug 2026 14:47:39 +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=1786805268; cv=pass; b=cTuokscTUekQu70LvMoMcgaoO6IkItpba8xnHnV3j8YmOUqT1nDvcN8Igm5E4lZaVXeeSsuMvUz7ViNCTa5RNKAHJ4H/K2jrF2NZHop6EozLs64lEk2ezAlqoapPJHIzIAi52GHiljdf2nesfZKn7X1/Lj1IdFQk4C9xLmpJkS4= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786805268; c=relaxed/simple; bh=vBbbKGN5T0BtLVxMzPn0CcCZwK/f9k6hfR6B5NbYrLA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=THt01QKVcMPi8XxZkK6nTieYG29enI43ebySCUUl0jxRT6mr9C8VK62B+2aNlFFPWl0ol61CcTRcFRwYqD0ObfkH6BO2Ga6JoRhAHYmj/8iK1OecS0WLsnQxs8iJFg+KRGCqB4oUzSYUe5kI5+BoQdWBfXFCyLZ55O78HC7Q3s4= 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=RXG8RS9w 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="RXG8RS9w" ARC-Seal: i=1; a=rsa-sha256; t=1786805239; cv=none; d=zohomail.com; s=zohoarc; b=ex4j/fFtSFGgQFmOIKnlk0+ZpHV0yJEMGDpzdAKVqOqMKSEjbilRZJ6RwOVpIGOY0CpuccatKVEo+bE85zk42G54dsLS92fmyrAZvOtyzmTB36cjbijxL8/adEJAlfT8KGxqn4eHgukUOfoBaPDJBfP6+YdCqHLEiGRUKZEy6Sg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1786805239; 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=r8fYAOFqVo8O9YlgnSht+w4dcYH3rMOr7Dd5/qjkL+M=; b=EyYWG1SOi6BlBG2krhCVO0R+UqIW0xFgEoUUgZRjBqTKf3dy47w0G2HsxtlacdpA0Exc02+gHQWHHXOucJ9Bc7octVr4lr2z/Ntjf+RBCNStHCgZMN+K9UO5JLiIkxXkMJiJLvmwThRQmndomGI4pQ6lf2XIxnQzvK/RbQPDvyo= 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=1786805239; 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=r8fYAOFqVo8O9YlgnSht+w4dcYH3rMOr7Dd5/qjkL+M=; b=RXG8RS9wc7WSg1t0Elta7/N7qj4w4czHjmAOkt8/T8CWNghPzQMB/5hUzzMZXNY0 qNIUHOg0WYyi1aKG+W181IjwwUVgmVVRxmsdPyLGr/Uv/nONBjI2/pkgfY77g/ejyvu 0IES5kgPh9e3oorY/ZEbCsof3zxnZc4Tu1QO+d4I= Received: by mx.zohomail.com with SMTPS id 178680523587137.545802684552996; Sat, 15 Aug 2026 07:47:15 -0700 (PDT) From: Shardul Bankar Date: Sat, 15 Aug 2026 20:10:14 +0530 Subject: [PATCH RFC mptcp-next v2 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: <20260815-mptcp_penalise_send_v2-v2-1-3e5049a73681@mpiricsoftware.com> References: <20260815-mptcp_penalise_send_v2-v2-0-3e5049a73681@mpiricsoftware.com> In-Reply-To: <20260815-mptcp_penalise_send_v2-v2-0-3e5049a73681@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 f879b1061f2d..c04b73123d27 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 Sat Aug 15 20:35:21 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 2F0BA424D72 for ; Sat, 15 Aug 2026 14:47:57 +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=1786805282; cv=pass; b=cTdia9WkyR3FW8C8042G13iF4Ly3FLiqYSLAoUJvLXS4K01fOdcUfOf9OOcBk6Cj0OLR5lffopSBKMuM9hPxz4h0PAav28e3BisdjEwHKXNjDazRBmCuLp8A1VHlCQkjTfxopwjwQp7m59hpVaIzxc/Dc/kLD+wWd+buUEDGZ7M= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786805282; c=relaxed/simple; bh=0tAX1/EjDPui5oDCnluljlkfvf8LhEn5/iSxT7jGxh4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=cga+6KldEuyqRvbk7B/lHAvEd0YwI71+cah6B5tSukYjtxbgChWsbuvggylv1ivwb2Fn3S5LffGV1lLcOh3Z6Mpc3TuS1xd7ZirGF2lDKfsZGSkz0fN4Q9Ui1xXXiR5rp1BieBMEfEHpMIoXyS09dvbguLAmXs+FTyqWLj57gME= 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=nkduTtFZ 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="nkduTtFZ" ARC-Seal: i=1; a=rsa-sha256; t=1786805241; cv=none; d=zohomail.com; s=zohoarc; b=BL53r9iq8p7bkH9BKpXz8JqDcGL0J6cn9PYjsF/2aHsXs+D/xgJKQf7ilswwOXCo1t/vzcPVzWSEVFnLBnn896pwlCDsGYzLw5DkatZ5t546V2Ixq1hXUcodmY8qe77gJjviX1txlGs0GZhmVYoaa8jXwZVxc5kVBQ3bdWzKJJI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1786805241; 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=IrVC3zH71eVCMp/ikREEGvlw10mSjXgnJQASjKw0nb4=; b=aHUf90FPT/l+acOVVLPlCMsAPCK9d3c5puYnsnJsp0hrcFhJ9a5JGSoClsxz9vRERxiyVUpowByjENzzuvLH7Q0bnuRvMD3UCRuKpeZpDX9BSeq5QNkbmvYRGrpAhK4tD6Qxz+3Hh0UZAivsCU/s1olBTIp5DoY6hGkQ6mYJPWw= 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=1786805241; 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=IrVC3zH71eVCMp/ikREEGvlw10mSjXgnJQASjKw0nb4=; b=nkduTtFZiqpeBO7+MGTxdnsoPDKq1rGIgwLZsu/NXXtH09aEWKxPIkhtr3QjfUP8 lL8ts9J3Ufg5V5ock8rcROamPejnWUgTWxoR0L3F84s6md6oU5al84yBR0gWaZG1Jni mfedlcVJs9HzsDDv6vDmJ/yY0wel6myFUQvbEZlE= Received: by mx.zohomail.com with SMTPS id 1786805238754302.3452029794872; Sat, 15 Aug 2026 07:47:18 -0700 (PDT) From: Shardul Bankar Date: Sat, 15 Aug 2026 20:10:15 +0530 Subject: [PATCH RFC mptcp-next v2 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: <20260815-mptcp_penalise_send_v2-v2-2-3e5049a73681@mpiricsoftware.com> References: <20260815-mptcp_penalise_send_v2-v2-0-3e5049a73681@mpiricsoftware.com> In-Reply-To: <20260815-mptcp_penalise_send_v2-v2-0-3e5049a73681@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 c04b73123d27..075d468d0e14 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 Sat Aug 15 20:35:21 2026 Received: from sender6-of-o52.zoho.com (sender6-of-o52.zoho.com [165.173.180.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 2F261423EB7 for ; Sat, 15 Aug 2026 14:48:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=165.173.180.52 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786805298; cv=pass; b=TzwAFh1fDKahZyRIHOuxZqTJhzflZQG1HYENmM6l7QVZ1MgJVji7oihMS6s5CAUdECHIdqKL/N/6KikF8ceJttrYakk/5BftNexApGOZpiXqxlXagLWPqaLBbZVip/qXrRBwSq8yu/utn/B272iRRtoTL/9YGwzuFJ1rbTKXkxQ= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786805298; c=relaxed/simple; bh=t4JpLva6E6l2BnwRPzP2IlLO5OtEFujlYYzI0JPwZAM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=UYHMTutBtDyvUs7o3yPJHTIGk5G0i1V5fIV8kz8bL94EZW9oI8Cab2khWsi8Y8y6H+hHG4X+bcmpZNj4fpxT42G7GWnmi73RxdbWSqrF9mRRe2nW98NIeUyshwsUoITuxF5r+HBkr459rGih3zWLsQpkiZMoLbfuio8qLViBzXY= 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=Ko2A2C8N reason="key not found in DNS"; arc=pass smtp.client-ip=165.173.180.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="Ko2A2C8N" ARC-Seal: i=1; a=rsa-sha256; t=1786805243; cv=none; d=zohomail.com; s=zohoarc; b=HqO6cCkgTK8igH7hWyOJ+bmEdLBhaMmF1a4JQp0UAgO8IIuwjEufaTu5fRqD3ZslktrB0kFeh18EinQDF39j0bwrkDP/1UB+/wb7DhnkHnyISf4aJicUNuKjeEmo/vRwzBgmx1azRS437fNPszBAYkkn6+dmCrcnwdTvugakdf4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1786805243; 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=qWdhoWKR7tU5pg6MP7NlJrmFtlYl5a3eVxPTsQcJsUY=; b=S5xG6uB8IMV3IP7LlOqSLP1SS0A/YtS4om2UiQ4Bs8tZjcNdiFOHMPWfcFErGhpskmG08/kTcSilRUKKpnoAs6J0gekG+kGtMZR4AOQGK9i5dP712xV9bbLXgIB1P9KoVWwWZzhnvvY3+Bzm3cdMoI0dB0/a2lW9PoFTRA/CkzY= 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=1786805243; 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=qWdhoWKR7tU5pg6MP7NlJrmFtlYl5a3eVxPTsQcJsUY=; b=Ko2A2C8NhIoCYe9Wrzj0wH4Rv236KA4aq3Ny+CrhWX0F7ffk/cqknjtNrvy1o2gU jo0jzTtd4FO+uciNf5m60USdCqNACNZy/Bb64LqbehTDD6e+kOrUUhHM8dVV5cL4XsW w/kkg4b5CliFU8CjfMiL2l5qj1K9LMDnXSKpFb1s= Received: by mx.zohomail.com with SMTPS id 1786805241454889.9099580751931; Sat, 15 Aug 2026 07:47:21 -0700 (PDT) From: Shardul Bankar Date: Sat, 15 Aug 2026 20:10:16 +0530 Subject: [PATCH RFC mptcp-next v2 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: <20260815-mptcp_penalise_send_v2-v2-3-3e5049a73681@mpiricsoftware.com> References: <20260815-mptcp_penalise_send_v2-v2-0-3e5049a73681@mpiricsoftware.com> In-Reply-To: <20260815-mptcp_penalise_send_v2-v2-0-3e5049a73681@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 075d468d0e14..e6c10816df8d 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 Sat Aug 15 20:35:21 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 51F4241F5CA for ; Sat, 15 Aug 2026 14:48:25 +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=1786805314; cv=pass; b=POdYNXNkNeJ4Oapr2zaPnxClFDx4r2c9rqrGDooBBvz7aWeOvWOFNxcqBe/l7wqaXaBAtVYSUtIoawWyyQR/M/ZwtwZv1+TB/2gmZ74mVYpsI/A8WEC9Qqoa4JxzWaafCpK9ZllaSWVCFAurLMcD42MI/od55Nsvv/k08fmE33g= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786805314; c=relaxed/simple; bh=hmrFll5gDUlbGoaiu5CxiZhxJRVum3JldNTTZi+z6RI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ec1o3xf4nxNnVPW9p5kEiCBSh83xJTLkJ5Djc2WZCIbC+O6s7P8LBVVSo7VxIZP7+tgiEvpDXRsane0SlR+jzF8RWHeFUKzZNRycQTnKAghZzE2z8qcftTLVTTLcIakZTDE9jxx/6L4BgfTsba1HwJSrcLK4btj8Ws9uKkrFtnU= 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=TfR0rqOc 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="TfR0rqOc" ARC-Seal: i=1; a=rsa-sha256; t=1786805247; cv=none; d=zohomail.com; s=zohoarc; b=DsXRve9mZdN31ek4FPEPnmB6MusYVyHHYmb0/zIu2tPW3GOSntVUbL8uGphwVvJXa5xlJvLb8jRq/gWdbx7Twe8G+HAl9lrtoRMMcNeKd5KsRb2fnoEClACIfZy0AMXtPyDU14Dhr1e4ilrpl4fDmP4dFBM9Lv5leqXckFJ1GEw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1786805247; 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=1vF3F7Sz6iWc16IumqxikyVHDBfjussqUACbo8JBYw0=; b=dG7Tawz5VJZRonDQ9PXJRLoSSEr45/V6CxxjEba4OLgSozKAKJ12bcjL/hB331Z1SFdAjVPGhFxXrON0ikNAJvBCyHHtAkZPF3NLn773DgbLX+ZJljZtsQM23HwT556ygg2bnb5/yHjvHPHfXMM9nzuYKuFkRfdYp4ALaR2hsK0= 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=1786805247; 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=1vF3F7Sz6iWc16IumqxikyVHDBfjussqUACbo8JBYw0=; b=TfR0rqOcqIYULY4PMjcsu4KH91qo3HRLkduUSkCTpmJOEgYAX1AF/AlckOB8iI4J RLvP8922U+eckAlDFf+DOo3nit2D/PdnQaxl3vYxYj7cKpipgHozC/EIbjtQiTUFyMA stI9g1vuhJoOJIVmUPMe/pvTbdrEEVJm0d4cLn7Q= Received: by mx.zohomail.com with SMTPS id 1786805244111507.42978943774676; Sat, 15 Aug 2026 07:47:24 -0700 (PDT) From: Shardul Bankar Date: Sat, 15 Aug 2026 20:10:17 +0530 Subject: [PATCH RFC mptcp-next v2 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: <20260815-mptcp_penalise_send_v2-v2-4-3e5049a73681@mpiricsoftware.com> References: <20260815-mptcp_penalise_send_v2-v2-0-3e5049a73681@mpiricsoftware.com> In-Reply-To: <20260815-mptcp_penalise_send_v2-v2-0-3e5049a73681@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 e6c10816df8d..ee7a3baa45e4 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