mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH net 0/2] Revert advertising the TCP MSS from the configured MTU
@ 2026-10-26  7:23 Esko Mobius via B4 Relay
  2026-10-26  7:23 ` [PATCH net 1/2] Revert "selftests: net: packetdrill: add tests for advertised MSS with PMTU exceptions" Esko Mobius via B4 Relay
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Esko Mobius via B4 Relay @ 2026-10-26  7:23 UTC (permalink / raw)
  To: netdev
  Cc: Jakub Kicinski, Paolo Abeni, David S. Miller, Simon Horman,
	David Ahern, Ido Schimmel, Jiayuan Chen, Shuah Khan,
	Thorsten Leemhuis, regressions, linux-kselftest, linux-kernel,
	stable, Esko Mobius, Eric Dumazet

Commit 2640e6419594 ("net: advertise TCP MSS from the configured MTU,
not the learned PMTU") breaks TCP for clients behind networks that
filter inbound ICMP, when the server reaches them through a hop with a
smaller MTU: the handshake completes, then the connection stalls as
soon as the client sends full-size segments. This was reported in [1]
and confirmed on 7.3-rc7; reverting the commit on top of 7.3-rc7 fixes
it. Details and numbers are in patch 2.

The asymmetric (DSR-style) case that commit targets can still be served
by the existing per-route advmss metric, which overrides the default
after the revert; patch 2 includes a test of that as well. If you would
rather keep the new behaviour as an explicit opt-in some other way, I
am happy to test or rework this.

Patch 1 removes the packetdrill tests that assert the reverted
behaviour, patch 2 is the revert itself.

[1] https://lore.kernel.org/regressions/4F0FAEB6-A13B-47F3-BFF1-C706686C6F64@gmail.com/

Signed-off-by: Esko Mobius <echoowall@gmail.com>
---
Esko Mobius (2):
      Revert "selftests: net: packetdrill: add tests for advertised MSS with PMTU exceptions"
      Revert "net: advertise TCP MSS from the configured MTU, not the learned PMTU"

 include/net/ip.h                                   | 25 --------
 include/net/ip6_route.h                            | 37 ------------
 net/ipv4/route.c                                   |  4 +-
 net/ipv6/route.c                                   |  2 +-
 .../net/packetdrill/tcp_advmss_pmtu_ipv4.pkt       | 67 ----------------------
 .../net/packetdrill/tcp_advmss_pmtu_ipv6.pkt       | 67 ----------------------
 6 files changed, 3 insertions(+), 199 deletions(-)
---
base-commit: 7076f684d5132e6a6145e1da2fa74771ecd052e5
change-id: 20261026-advmss-revert-5805de17369f

Best regards,
--  
Esko Mobius <echoowall@gmail.com>



^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH net 1/2] Revert "selftests: net: packetdrill: add tests for advertised MSS with PMTU exceptions"
  2026-10-26  7:23 [PATCH net 0/2] Revert advertising the TCP MSS from the configured MTU Esko Mobius via B4 Relay
@ 2026-10-26  7:23 ` Esko Mobius via B4 Relay
  2026-10-27 11:44   ` Jiayuan Chen
  2026-10-26  7:23 ` [PATCH net 2/2] Revert "net: advertise TCP MSS from the configured MTU, not the learned PMTU" Esko Mobius via B4 Relay
  2026-10-26 13:28 ` [PATCH net 0/2] Revert advertising the TCP MSS from the configured MTU Eric Dumazet
  2 siblings, 1 reply; 9+ messages in thread
From: Esko Mobius via B4 Relay @ 2026-10-26  7:23 UTC (permalink / raw)
  To: netdev
  Cc: Jakub Kicinski, Paolo Abeni, David S. Miller, Simon Horman,
	David Ahern, Ido Schimmel, Jiayuan Chen, Shuah Khan,
	Thorsten Leemhuis, regressions, linux-kselftest, linux-kernel,
	stable, Esko Mobius, Eric Dumazet

From: Esko Mobius <echoowall@gmail.com>

This reverts commit e5c8e301b497 ("selftests: net: packetdrill: add
tests for advertised MSS with PMTU exceptions").

These tests assert the behaviour introduced by commit 2640e6419594
("net: advertise TCP MSS from the configured MTU, not the learned
PMTU"), which is reverted in the next patch because it causes a
regression. Remove them first so the series stays bisectable.

Signed-off-by: Esko Mobius <echoowall@gmail.com>
---
 .../net/packetdrill/tcp_advmss_pmtu_ipv4.pkt       | 67 ----------------------
 .../net/packetdrill/tcp_advmss_pmtu_ipv6.pkt       | 67 ----------------------
 2 files changed, 134 deletions(-)

diff --git a/tools/testing/selftests/net/packetdrill/tcp_advmss_pmtu_ipv4.pkt b/tools/testing/selftests/net/packetdrill/tcp_advmss_pmtu_ipv4.pkt
deleted file mode 100644
index f2ef931b7..000000000
--- a/tools/testing/selftests/net/packetdrill/tcp_advmss_pmtu_ipv4.pkt
+++ /dev/null
@@ -1,67 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Test that IPv4 advertised MSS in SYN-ACK is derived from the configured
-// interface MTU (1500 -> MSS 1460), not the ICMP-learned Path MTU.
-
---ip_version=ipv4
-
-`./defaults.sh
-ethtool -K tun0 tso off
-`
-
-//
-// Connection 1: Learn PMTU exception (MTU 1200 -> MSS 1160)
-//
-    0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
-   +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
-   +0 bind(3, ..., ...) = 0
-   +0 listen(3, 1) = 0
-
-   +0 < S 0:0(0) win 65535 <mss 1460,sackOK,nop,nop,nop,wscale 8>
-   +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
-  +.1 < . 1:1(0) ack 1 win 257
-   +0 accept(3, ..., ...) = 4
-
-// Send a full 1460-byte segment
-   +0 write(4, ..., 1460) = 1460
-   +0 > P. 1:1461(1460) ack 1
-
-// ICMP Fragmentation Needed arrives indicating next-hop MTU 1200
-   +0 < icmp unreachable frag_needed mtu 1200 [1:1461(1460)]
-
-// Local host retransmits using the learned MTU 1200 (MSS = 1200 - 40 = 1160)
-   +0 > . 1:1161(1160) ack 1
-   +0 > P. 1161:1461(300) ack 1
-   +0 < R 1:1(0) ack 1461 win 0
-
-// Close connection 1 and listener
-   +0 close(4) = 0
-   +0 close(3) = 0
-
-//
-// Connection 2: New connection from the same peer
-//
-   +0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
-   +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
-   +0 bind(3, ..., ...) = 0
-   +0 listen(3, 1) = 0
-
-   +0 < S 0:0(0) win 65535 <mss 1460,sackOK,nop,nop,nop,wscale 8>
-
-// Verify: SYN-ACK MUST advertise configured MSS 1460, NOT the learned PMTU MSS 1160
-   +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
-   +0 < . 1:1(0) ack 1 win 257
-   +0 accept(3, ..., ...) = 4
-
-// Verify: Outgoing transmit MSS is still constrained by the learned PMTU 1200
-   +0 write(4, ..., 1460) = 1460
-   +0 > . 1:1161(1160) ack 1
-   +0 > P. 1161:1461(300) ack 1
-   +0 < . 1:1(0) ack 1461 win 257
-
-// Clean up
-   +0 close(4) = 0
-   +0 > F. 1461:1461(0) ack 1
-   +0 < F. 1:1(0) ack 1462 win 257
-   +0 > . 1462:1462(0) ack 2
-   +0 close(3) = 0
diff --git a/tools/testing/selftests/net/packetdrill/tcp_advmss_pmtu_ipv6.pkt b/tools/testing/selftests/net/packetdrill/tcp_advmss_pmtu_ipv6.pkt
deleted file mode 100644
index c7638b11a..000000000
--- a/tools/testing/selftests/net/packetdrill/tcp_advmss_pmtu_ipv6.pkt
+++ /dev/null
@@ -1,67 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Test that IPv6 advertised MSS in SYN-ACK is derived from the configured
-// interface MTU (1520 -> MSS 1460), not the ICMPv6-learned Path MTU.
-
---ip_version=ipv6
-
-`./defaults.sh
-ethtool -K tun0 tso off
-`
-
-//
-// Connection 1: Learn PMTU exception (MTU 1280 -> MSS 1220)
-//
-    0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
-   +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
-   +0 bind(3, ..., ...) = 0
-   +0 listen(3, 1) = 0
-
-   +0 < S 0:0(0) win 65535 <mss 1460,sackOK,nop,nop,nop,wscale 8>
-   +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
-  +.1 < . 1:1(0) ack 1 win 257
-   +0 accept(3, ..., ...) = 4
-
-// Send a full 1460-byte segment
-   +0 write(4, ..., 1460) = 1460
-   +0 > P. 1:1461(1460) ack 1
-
-// ICMPv6 Packet Too Big arrives indicating next-hop MTU 1280
-   +0 < icmp packet_too_big mtu 1280 [1:1461(1460)]
-
-// Local host retransmits using the learned MTU 1280 (MSS = 1280 - 40 - 20 = 1220)
-   +0 > . 1:1221(1220) ack 1
-   +0 > P. 1221:1461(240) ack 1
-   +0 < R 1:1(0) ack 1461 win 0
-
-// Close connection 1 and listener
-   +0 close(4) = 0
-   +0 close(3) = 0
-
-//
-// Connection 2: New connection from the same peer
-//
-   +0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
-   +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
-   +0 bind(3, ..., ...) = 0
-   +0 listen(3, 1) = 0
-
-   +0 < S 0:0(0) win 65535 <mss 1460,sackOK,nop,nop,nop,wscale 8>
-
-// Verify: SYN-ACK MUST advertise configured MSS 1460, NOT the learned PMTU MSS 1220
-   +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
-   +0 < . 1:1(0) ack 1 win 257
-   +0 accept(3, ..., ...) = 4
-
-// Verify: Outgoing transmit MSS is still constrained by the learned PMTU 1280
-   +0 write(4, ..., 1460) = 1460
-   +0 > . 1:1221(1220) ack 1
-   +0 > P. 1221:1461(240) ack 1
-   +0 < . 1:1(0) ack 1461 win 257
-
-// Clean up
-   +0 close(4) = 0
-   +0 > F. 1461:1461(0) ack 1
-   +0 < F. 1:1(0) ack 1462 win 257
-   +0 > . 1462:1462(0) ack 2
-   +0 close(3) = 0

-- 
Git-157)



^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH net 2/2] Revert "net: advertise TCP MSS from the configured MTU, not the learned PMTU"
  2026-10-26  7:23 [PATCH net 0/2] Revert advertising the TCP MSS from the configured MTU Esko Mobius via B4 Relay
  2026-10-26  7:23 ` [PATCH net 1/2] Revert "selftests: net: packetdrill: add tests for advertised MSS with PMTU exceptions" Esko Mobius via B4 Relay
@ 2026-10-26  7:23 ` Esko Mobius via B4 Relay
  2026-10-27 12:45   ` Jiayuan Chen
  2026-10-26 13:28 ` [PATCH net 0/2] Revert advertising the TCP MSS from the configured MTU Eric Dumazet
  2 siblings, 1 reply; 9+ messages in thread
From: Esko Mobius via B4 Relay @ 2026-10-26  7:23 UTC (permalink / raw)
  To: netdev
  Cc: Jakub Kicinski, Paolo Abeni, David S. Miller, Simon Horman,
	David Ahern, Ido Schimmel, Jiayuan Chen, Shuah Khan,
	Thorsten Leemhuis, regressions, linux-kselftest, linux-kernel,
	stable, Esko Mobius, Eric Dumazet

From: Esko Mobius <echoowall@gmail.com>

This reverts commit 2640e6419594 ("net: advertise TCP MSS from the
configured MTU, not the learned PMTU").

That commit stopped the learned PMTU from lowering the MSS we advertise
in SYN and SYN-ACK. For symmetric paths it argued that "the peer runs
its own PMTU discovery and usually already knows the real path MTU".
That only holds if ICMP "fragmentation needed" can reach the peer. When
the peer sits behind a firewall that drops inbound ICMP, its PMTU
discovery is a black hole (RFC 2923, section 2.1), and the smaller MSS
we advertised was the only thing keeping its full-size segments off the
narrow hop.

Inbound ICMP filtering is very common in enterprise and carrier
networks, and it is pervasive in mainland China. We hit this in
production after the commit was backported to 6.12.111: TCP connections
that reach a server through a relay with a smaller-MTU hop complete the
handshake, then stall as soon as the client sends full-size segments.
Clients on networks that let ICMP through, and connections that bypass
the relay, are unaffected, which made it hard to trace back to the
kernel.

Reproducer, network namespaces on a single host:

  cli --(1500)-- r1 --(1456)-- r2 --(1500)-- srv

r1 drops ICMP frag-needed towards cli. srv has already learned PMTU
1456 towards cli, then cli uploads 1 MB to srv:

  kernel                     SYN-ACK MSS   1 MB upload
  6.12.107                   1416          OK
  6.12.111                   1460          stalls, times out
  7.3-rc7                    1460          stalls, times out
  7.3-rc7 + this revert      1416          OK

The asymmetric case the commit was written for does not need a new
default: the advertised MSS can already be set per route with the
advmss metric, which takes precedence over default_advmss(). With this
revert applied, on an asymmetric path where srv learned PMTU 1456
towards cli while cli->srv is 1500 end to end:

  srv route to cli           SYN-ACK MSS   largest cli->srv segment
  default                    1416          1404
  advmss 1460                1460          1448

So DSR-style setups can opt in with "ip route ... advmss <mss>", while
hosts whose peers cannot complete PMTU discovery keep working by
default.

Fixes: 2640e6419594 ("net: advertise TCP MSS from the configured MTU, not the learned PMTU")
Reported-by: Esko Mobius <echoowall@gmail.com>
Closes: https://lore.kernel.org/regressions/4F0FAEB6-A13B-47F3-BFF1-C706686C6F64@gmail.com/
Cc: stable@vger.kernel.org
Signed-off-by: Esko Mobius <echoowall@gmail.com>
---
 include/net/ip.h        | 25 -------------------------
 include/net/ip6_route.h | 37 -------------------------------------
 net/ipv4/route.c        |  4 ++--
 net/ipv6/route.c        |  2 +-
 4 files changed, 3 insertions(+), 65 deletions(-)

diff --git a/include/net/ip.h b/include/net/ip.h
index 618b9806c..0acc4ba5e 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -513,31 +513,6 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
 	return res;
 }
 
-/* Configured/administrative MTU of a route, for advertising the TCP MSS.
- *
- * Unlike ip_dst_mtu_maybe_forward(), this deliberately ignores the
- * ICMP-learned path MTU (rt->rt_pmtu).  The advertised MSS bounds what the
- * peer may send to us and must reflect our receive capability (the device or
- * route-configured MTU), not a path MTU learned on the reverse (send)
- * direction, which may not apply to the peer->us path and outlives the fnhe
- * for the whole connection.  See RFC 2923 section 2.3 and the comment above
- * tcp_advertise_mss().
- */
-static inline unsigned int ip_dst_mtu_configured(const struct dst_entry *dst)
-{
-	unsigned int mtu, res;
-
-	rcu_read_lock();
-	mtu = dst_metric_raw(dst, RTAX_MTU);
-	if (!mtu)
-		mtu = READ_ONCE(dst_dev_rcu(dst)->mtu);
-	mtu = min_t(unsigned int, mtu, IP_MAX_MTU);
-	res = mtu - lwtunnel_headroom(dst->lwtstate, mtu);
-	rcu_read_unlock();
-
-	return res;
-}
-
 static inline unsigned int ip_skb_dst_mtu(struct sock *sk,
 					  const struct sk_buff *skb)
 {
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 5f47cef0b..95f936be3 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -396,43 +396,6 @@ static inline unsigned int ip6_dst_mtu_maybe_forward(const struct dst_entry *dst
 	return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
 }
 
-/* Configured/administrative MTU of a route, for advertising the TCP MSS.
- *
- * Unlike ip6_dst_mtu_maybe_forward(), this ignores any ICMPv6-learned path
- * MTU (which is kept on the RTF_CACHE exception route) and returns the MTU of
- * the underlying route (fib6_pmtu) or the egress device.  The advertised MSS
- * bounds what the peer may send to us and must reflect our receive
- * capability, not a path MTU learned on the reverse (send) direction.  See
- * RFC 2923 section 2.3 and the comment above tcp_advertise_mss().
- */
-static inline unsigned int ip6_dst_mtu_configured(const struct dst_entry *dst)
-{
-	const struct rt6_info *rt = dst_rt6_info(dst);
-	const struct fib6_info *from;
-	struct inet6_dev *idev;
-	unsigned int mtu = 0;
-
-	rcu_read_lock();
-	/* IPv6 keeps the learned PMTU and the configured MTU in the same
-	 * RTAX_MTU slot: the learned value sits on this (possibly RTF_CACHE)
-	 * dst, the configured one on the underlying route.  Reach the latter
-	 * via ->from (fib6_pmtu), populated by ip6_route_info_create().
-	 */
-	from = rcu_dereference(rt->from);
-	if (from)
-		mtu = from->fib6_pmtu;
-	if (!mtu) {
-		mtu = IPV6_MIN_MTU;
-		idev = __in6_dev_get(dst_dev_rcu(dst));
-		if (idev)
-			mtu = max_t(unsigned int, mtu, READ_ONCE(idev->cnf.mtu6));
-	}
-	rcu_read_unlock();
-
-	mtu = min_t(unsigned int, mtu, IP6_MAX_MTU);
-	return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
-}
-
 u32 ip6_mtu_from_fib6(const struct fib6_result *res,
 		      const struct in6_addr *daddr,
 		      const struct in6_addr *saddr);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 595a3b7f1..93b9f4189 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1365,8 +1365,8 @@ static unsigned int ipv4_default_advmss(const struct dst_entry *dst)
 
 	rcu_read_lock();
 	net = dst_dev_net_rcu(dst);
-	advmss = max_t(unsigned int, ip_dst_mtu_configured(dst) - header_size,
-		       net->ipv4.ip_rt_min_advmss);
+	advmss = max_t(unsigned int, ipv4_mtu(dst) - header_size,
+				   net->ipv4.ip_rt_min_advmss);
 	rcu_read_unlock();
 
 	return min(advmss, IPV4_MAX_PMTU - header_size);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 94e5ef1c4..5760a357e 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -3239,7 +3239,7 @@ void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk)
 
 static unsigned int ip6_default_advmss(const struct dst_entry *dst)
 {
-	unsigned int mtu = ip6_dst_mtu_configured(dst);
+	unsigned int mtu = dst6_mtu(dst);
 	struct net *net;
 
 	mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr);

-- 
Git-157)



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net 0/2] Revert advertising the TCP MSS from the configured MTU
  2026-10-26  7:23 [PATCH net 0/2] Revert advertising the TCP MSS from the configured MTU Esko Mobius via B4 Relay
  2026-10-26  7:23 ` [PATCH net 1/2] Revert "selftests: net: packetdrill: add tests for advertised MSS with PMTU exceptions" Esko Mobius via B4 Relay
  2026-10-26  7:23 ` [PATCH net 2/2] Revert "net: advertise TCP MSS from the configured MTU, not the learned PMTU" Esko Mobius via B4 Relay
@ 2026-10-26 13:28 ` Eric Dumazet
  2 siblings, 0 replies; 9+ messages in thread
From: Eric Dumazet @ 2026-10-26 13:28 UTC (permalink / raw)
  To: echoowall
  Cc: netdev, Jakub Kicinski, Paolo Abeni, David S. Miller,
	Simon Horman, David Ahern, Ido Schimmel, Jiayuan Chen,
	Shuah Khan, Thorsten Leemhuis, regressions, linux-kselftest,
	linux-kernel, stable

Le lun. 26 oct. 2026 à 08:23, Esko Mobius via B4 Relay
<devnull+echoowall.gmail.com@kernel.org> a écrit :
>
> Commit 2640e6419594 ("net: advertise TCP MSS from the configured MTU,
> not the learned PMTU") breaks TCP for clients behind networks that
> filter inbound ICMP, when the server reaches them through a hop with a
> smaller MTU: the handshake completes, then the connection stalls as
> soon as the client sends full-size segments. This was reported in [1]
> and confirmed on 7.3-rc7; reverting the commit on top of 7.3-rc7 fixes
> it. Details and numbers are in patch 2.
>
> The asymmetric (DSR-style) case that commit targets can still be served
> by the existing per-route advmss metric, which overrides the default
> after the revert; patch 2 includes a test of that as well. If you would
> rather keep the new behaviour as an explicit opt-in some other way, I
> am happy to test or rework this.
>
> Patch 1 removes the packetdrill tests that assert the reverted
> behaviour, patch 2 is the revert itself.
>
> [1] https://lore.kernel.org/regressions/4F0FAEB6-A13B-47F3-BFF1-C706686C6F64@gmail.com/

Reviewed-by: Eric Dumazet <edumazet@kernel.org>

Even if the reverted behavior was closer to RFC 2923 / RFC 1122, it
was a long-standing
user visible behavior and should not have been tagged for stable.

Relays should really clamp MSS (nft "tcp option maxseg size set rt mtu"),
but a revert is the right call for net and stable trees.

If needed, the asymmetric/DSR case can be revisited in net-next as an opt-in.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net 1/2] Revert "selftests: net: packetdrill: add tests for advertised MSS with PMTU exceptions"
  2026-10-26  7:23 ` [PATCH net 1/2] Revert "selftests: net: packetdrill: add tests for advertised MSS with PMTU exceptions" Esko Mobius via B4 Relay
@ 2026-10-27 11:44   ` Jiayuan Chen
  0 siblings, 0 replies; 9+ messages in thread
From: Jiayuan Chen @ 2026-10-27 11:44 UTC (permalink / raw)
  To: echoowall, netdev
  Cc: Jakub Kicinski, Paolo Abeni, David S. Miller, Simon Horman,
	David Ahern, Ido Schimmel, Shuah Khan, Thorsten Leemhuis,
	regressions, linux-kselftest, linux-kernel, stable, Eric Dumazet


On 10/26/26 3:23 PM, Esko Mobius via B4 Relay wrote:
> From: Esko Mobius <echoowall@gmail.com>
>
> This reverts commit e5c8e301b497 ("selftests: net: packetdrill: add
> tests for advertised MSS with PMTU exceptions").
>
> These tests assert the behaviour introduced by commit 2640e6419594
> ("net: advertise TCP MSS from the configured MTU, not the learned
> PMTU"), which is reverted in the next patch because it causes a
> regression. Remove them first so the series stays bisectable.
>
> Signed-off-by: Esko Mobius <echoowall@gmail.com>


Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>


> ---
>   .../net/packetdrill/tcp_advmss_pmtu_ipv4.pkt       | 67 ----------------------
>   .../net/packetdrill/tcp_advmss_pmtu_ipv6.pkt       | 67 ----------------------
>   2 files changed, 134 deletions(-)
>
> diff --git a/tools/testing/selftests/net/packetdrill/tcp_advmss_pmtu_ipv4.pkt b/tools/testing/selftests/net/packetdrill/tcp_advmss_pmtu_ipv4.pkt
> deleted file mode 100644
> index f2ef931b7..000000000
> --- a/tools/testing/selftests/net/packetdrill/tcp_advmss_pmtu_ipv4.pkt
> +++ /dev/null
> @@ -1,67 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -//
> -// Test that IPv4 advertised MSS in SYN-ACK is derived from the configured
> -// interface MTU (1500 -> MSS 1460), not the ICMP-learned Path MTU.
> -
> ---ip_version=ipv4
> -
> -`./defaults.sh
> -ethtool -K tun0 tso off
> -`
> -
> -//
> -// Connection 1: Learn PMTU exception (MTU 1200 -> MSS 1160)
> -//
> -    0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
> -   +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
> -   +0 bind(3, ..., ...) = 0
> -   +0 listen(3, 1) = 0
> -
> -   +0 < S 0:0(0) win 65535 <mss 1460,sackOK,nop,nop,nop,wscale 8>
> -   +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
> -  +.1 < . 1:1(0) ack 1 win 257
> -   +0 accept(3, ..., ...) = 4
> -
> -// Send a full 1460-byte segment
> -   +0 write(4, ..., 1460) = 1460
> -   +0 > P. 1:1461(1460) ack 1
> -
> -// ICMP Fragmentation Needed arrives indicating next-hop MTU 1200
> -   +0 < icmp unreachable frag_needed mtu 1200 [1:1461(1460)]
> -
> -// Local host retransmits using the learned MTU 1200 (MSS = 1200 - 40 = 1160)
> -   +0 > . 1:1161(1160) ack 1
> -   +0 > P. 1161:1461(300) ack 1
> -   +0 < R 1:1(0) ack 1461 win 0
> -
> -// Close connection 1 and listener
> -   +0 close(4) = 0
> -   +0 close(3) = 0
> -
> -//
> -// Connection 2: New connection from the same peer
> -//
> -   +0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
> -   +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
> -   +0 bind(3, ..., ...) = 0
> -   +0 listen(3, 1) = 0
> -
> -   +0 < S 0:0(0) win 65535 <mss 1460,sackOK,nop,nop,nop,wscale 8>
> -
> -// Verify: SYN-ACK MUST advertise configured MSS 1460, NOT the learned PMTU MSS 1160
> -   +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
> -   +0 < . 1:1(0) ack 1 win 257
> -   +0 accept(3, ..., ...) = 4
> -
> -// Verify: Outgoing transmit MSS is still constrained by the learned PMTU 1200
> -   +0 write(4, ..., 1460) = 1460
> -   +0 > . 1:1161(1160) ack 1
> -   +0 > P. 1161:1461(300) ack 1
> -   +0 < . 1:1(0) ack 1461 win 257
> -
> -// Clean up
> -   +0 close(4) = 0
> -   +0 > F. 1461:1461(0) ack 1
> -   +0 < F. 1:1(0) ack 1462 win 257
> -   +0 > . 1462:1462(0) ack 2
> -   +0 close(3) = 0
> diff --git a/tools/testing/selftests/net/packetdrill/tcp_advmss_pmtu_ipv6.pkt b/tools/testing/selftests/net/packetdrill/tcp_advmss_pmtu_ipv6.pkt
> deleted file mode 100644
> index c7638b11a..000000000
> --- a/tools/testing/selftests/net/packetdrill/tcp_advmss_pmtu_ipv6.pkt
> +++ /dev/null
> @@ -1,67 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -//
> -// Test that IPv6 advertised MSS in SYN-ACK is derived from the configured
> -// interface MTU (1520 -> MSS 1460), not the ICMPv6-learned Path MTU.
> -
> ---ip_version=ipv6
> -
> -`./defaults.sh
> -ethtool -K tun0 tso off
> -`
> -
> -//
> -// Connection 1: Learn PMTU exception (MTU 1280 -> MSS 1220)
> -//
> -    0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
> -   +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
> -   +0 bind(3, ..., ...) = 0
> -   +0 listen(3, 1) = 0
> -
> -   +0 < S 0:0(0) win 65535 <mss 1460,sackOK,nop,nop,nop,wscale 8>
> -   +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
> -  +.1 < . 1:1(0) ack 1 win 257
> -   +0 accept(3, ..., ...) = 4
> -
> -// Send a full 1460-byte segment
> -   +0 write(4, ..., 1460) = 1460
> -   +0 > P. 1:1461(1460) ack 1
> -
> -// ICMPv6 Packet Too Big arrives indicating next-hop MTU 1280
> -   +0 < icmp packet_too_big mtu 1280 [1:1461(1460)]
> -
> -// Local host retransmits using the learned MTU 1280 (MSS = 1280 - 40 - 20 = 1220)
> -   +0 > . 1:1221(1220) ack 1
> -   +0 > P. 1221:1461(240) ack 1
> -   +0 < R 1:1(0) ack 1461 win 0
> -
> -// Close connection 1 and listener
> -   +0 close(4) = 0
> -   +0 close(3) = 0
> -
> -//
> -// Connection 2: New connection from the same peer
> -//
> -   +0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
> -   +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
> -   +0 bind(3, ..., ...) = 0
> -   +0 listen(3, 1) = 0
> -
> -   +0 < S 0:0(0) win 65535 <mss 1460,sackOK,nop,nop,nop,wscale 8>
> -
> -// Verify: SYN-ACK MUST advertise configured MSS 1460, NOT the learned PMTU MSS 1220
> -   +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
> -   +0 < . 1:1(0) ack 1 win 257
> -   +0 accept(3, ..., ...) = 4
> -
> -// Verify: Outgoing transmit MSS is still constrained by the learned PMTU 1280
> -   +0 write(4, ..., 1460) = 1460
> -   +0 > . 1:1221(1220) ack 1
> -   +0 > P. 1221:1461(240) ack 1
> -   +0 < . 1:1(0) ack 1461 win 257
> -
> -// Clean up
> -   +0 close(4) = 0
> -   +0 > F. 1461:1461(0) ack 1
> -   +0 < F. 1:1(0) ack 1462 win 257
> -   +0 > . 1462:1462(0) ack 2
> -   +0 close(3) = 0
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net 2/2] Revert "net: advertise TCP MSS from the configured MTU, not the learned PMTU"
  2026-10-26  7:23 ` [PATCH net 2/2] Revert "net: advertise TCP MSS from the configured MTU, not the learned PMTU" Esko Mobius via B4 Relay
@ 2026-10-27 12:45   ` Jiayuan Chen
  2026-10-27 13:02     ` Eric Dumazet
  0 siblings, 1 reply; 9+ messages in thread
From: Jiayuan Chen @ 2026-10-27 12:45 UTC (permalink / raw)
  To: echoowall, netdev
  Cc: Jakub Kicinski, Paolo Abeni, David S. Miller, Simon Horman,
	David Ahern, Ido Schimmel, Shuah Khan, Thorsten Leemhuis,
	regressions, linux-kselftest, linux-kernel, stable, Eric Dumazet


On 10/26/26 3:23 PM, Esko Mobius via B4 Relay wrote:
> From: Esko Mobius <echoowall@gmail.com>
>
> This reverts commit 2640e6419594 ("net: advertise TCP MSS from the
> configured MTU, not the learned PMTU").
>
> That commit stopped the learned PMTU from lowering the MSS we advertise
> in SYN and SYN-ACK. For symmetric paths it argued that "the peer runs
> its own PMTU discovery and usually already knows the real path MTU".
> That only holds if ICMP "fragmentation needed" can reach the peer. When
> the peer sits behind a firewall that drops inbound ICMP, its PMTU
> discovery is a black hole (RFC 2923, section 2.1), and the smaller MSS
> we advertised was the only thing keeping its full-size segments off the
> narrow hop.


A client that cannot receive ICMP is broken beyond this: QUIC's DPLPMTUD
hits the same black hole, and nothing the server advertises can help it.


>
> Inbound ICMP filtering is very common in enterprise and carrier
> networks, and it is pervasive in mainland China. We hit this in
> production after the commit was backported to 6.12.111: TCP connections
> that reach a server through a relay with a smaller-MTU hop complete the
> handshake, then stall as soon as the client sends full-size segments.



The learned PMTU is keyed per destination address. If your relay
masquerades the clients, the server sees a single address, and one
client's download seeds the entry for everyone behind it. That is why
this looked reliable. Once the clients are spread over their own
addresses, each one needs its own fresh entry and it falls apart. The
old behaviour was never a mechanism for this.


> Clients on networks that let ICMP through, and connections that bypass
> the relay, are unaffected, which made it hard to trace back to the
> kernel.
>
> Reproducer, network namespaces on a single host:
>
>    cli --(1500)-- r1 --(1456)-- r2 --(1500)-- srv
>
> r1 drops ICMP frag-needed towards cli. srv has already learned PMTU
> 1456 towards cli, then cli uploads 1 MB to srv:


This precondition does all the work. The server only learns the PMTU
when it sends a full-size segment itself. If it only sends ACKs or small
replies it never learns it, the SYN-ACK MSS is 1460 on 6.12.107 as well,
and the upload stalls the same way. The entry also expires after 10
minutes (ip_rt_mtu_expires), so the server must have received a
frag-needed within the last 10 minutes before each new connection.

Please re-run the 6.12.107 case without seeding the PMTU.


>
>    kernel                     SYN-ACK MSS   1 MB upload
>    6.12.107                   1416          OK
>    6.12.111                   1460          stalls, times out
>    7.3-rc7                    1460          stalls, times out
>    7.3-rc7 + this revert      1416          OK
>
> The asymmetric case the commit was written for does not need a new
> default: the advertised MSS can already be set per route with the
> advmss metric, which takes precedence over default_advmss(). With this
> revert applied, on an asymmetric path where srv learned PMTU 1456
> towards cli while cli->srv is 1500 end to end:
>
>    srv route to cli           SYN-ACK MSS   largest cli->srv segment
>    default                    1416          1404
>    advmss 1460                1460          1448
>
> So DSR-style setups can opt in with "ip route ... advmss <mss>", while
> hosts whose peers cannot complete PMTU discovery keep working by
> default.
>
> Fixes: 2640e6419594 ("net: advertise TCP MSS from the configured MTU, not the learned PMTU")
> Reported-by: Esko Mobius <echoowall@gmail.com>
> Closes: https://lore.kernel.org/regressions/4F0FAEB6-A13B-47F3-BFF1-C706686C6F64@gmail.com/
> Cc: stable@vger.kernel.org
> Signed-off-by: Esko Mobius <echoowall@gmail.com>




Maybe a better way out than a plain revert:

Revert in stable, and in net-next add a sysctl, something like 
net.ipv4.tcp_advmss_use_pmtu,
that decides whether an endpoint uses the PMTU it learned on its send
side for the MSS it advertises (even though these are two opposite
directions). Default on keeps your setup working, DSR-style setups turn
it off



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net 2/2] Revert "net: advertise TCP MSS from the configured MTU, not the learned PMTU"
  2026-10-27 12:45   ` Jiayuan Chen
@ 2026-10-27 13:02     ` Eric Dumazet
  2026-10-27 13:12       ` Esko Mobius
  0 siblings, 1 reply; 9+ messages in thread
From: Eric Dumazet @ 2026-10-27 13:02 UTC (permalink / raw)
  To: Jiayuan Chen
  Cc: echoowall, netdev, Jakub Kicinski, Paolo Abeni, David S. Miller,
	Simon Horman, David Ahern, Ido Schimmel, Shuah Khan,
	Thorsten Leemhuis, regressions, linux-kselftest, linux-kernel,
	stable

Le mar. 27 oct. 2026 à 13:45, Jiayuan Chen <jiayuan.chen@linux.dev> a écrit :
>
>
> On 10/26/26 3:23 PM, Esko Mobius via B4 Relay wrote:
> > From: Esko Mobius <echoowall@gmail.com>
> >
> > This reverts commit 2640e6419594 ("net: advertise TCP MSS from the
> > configured MTU, not the learned PMTU").
> >
> > That commit stopped the learned PMTU from lowering the MSS we advertise
> > in SYN and SYN-ACK. For symmetric paths it argued that "the peer runs
> > its own PMTU discovery and usually already knows the real path MTU".
> > That only holds if ICMP "fragmentation needed" can reach the peer. When
> > the peer sits behind a firewall that drops inbound ICMP, its PMTU
> > discovery is a black hole (RFC 2923, section 2.1), and the smaller MSS
> > we advertised was the only thing keeping its full-size segments off the
> > narrow hop.
>
>
> A client that cannot receive ICMP is broken beyond this: QUIC's DPLPMTUD
> hits the same black hole, and nothing the server advertises can help it.
>
>
> >
> > Inbound ICMP filtering is very common in enterprise and carrier
> > networks, and it is pervasive in mainland China. We hit this in
> > production after the commit was backported to 6.12.111: TCP connections
> > that reach a server through a relay with a smaller-MTU hop complete the
> > handshake, then stall as soon as the client sends full-size segments.
>
>
>
> The learned PMTU is keyed per destination address. If your relay
> masquerades the clients, the server sees a single address, and one
> client's download seeds the entry for everyone behind it. That is why
> this looked reliable. Once the clients are spread over their own
> addresses, each one needs its own fresh entry and it falls apart. The
> old behaviour was never a mechanism for this.

Hi Jiayuan

You are right on the technical side, and your patch was correct
from an RFC point of view. The old behavior was a side effect,
not a designed mechanism, and the reporter setup only works
because the masquerading relay keeps the exception fresh.

But it did work for them, for years, and it stopped working after
a stable update. That is the part we have to fix first, even if the
setup relies on an accident. MSS clamping on the relay is the proper
long term answer for them.

This is partly my fault: I reviewed the patch and did not object to
the Fixes: 1da177e4c3f4 + Cc: stable tags. A behavior change like this
one should have stayed in net-next.

> Maybe a better way out than a plain revert:
>
> Revert in stable, and in net-next add a sysctl, something like
> net.ipv4.tcp_advmss_use_pmtu,
> that decides whether an endpoint uses the PMTU it learned on its send
> side for the MSS it advertises (even though these are two opposite
> directions). Default on keeps your setup working, DSR-style setups turn
> it off

I think we mus take the revert in net as well, so that
mainline and stable trees behave the same, and the stable
backports do not diverge.

Then a net-next patch is welcome, keeping the historical behavior
as the default. Before adding a new sysctl, please check if the
existing per-route advmss metric is enough for the DSR case,
as Esko showed in the changelog. If it is not (for instance because
it is too hard to deploy on many routes), a sysctl sounds fine to me.

Thanks!

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net 2/2] Revert "net: advertise TCP MSS from the configured MTU, not the learned PMTU"
  2026-10-27 13:02     ` Eric Dumazet
@ 2026-10-27 13:12       ` Esko Mobius
  2026-10-27 13:44         ` Jiayuan Chen
  0 siblings, 1 reply; 9+ messages in thread
From: Esko Mobius @ 2026-10-27 13:12 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Jiayuan Chen, netdev, Jakub Kicinski, Paolo Abeni,
	David S. Miller, Simon Horman, David Ahern, Ido Schimmel,
	Shuah Khan, Thorsten Leemhuis, regressions, linux-kselftest,
	linux-kernel, stable

On 10/27/26 1:45 PM, Jiayuan Chen wrote:
> This precondition does all the work. The server only learns the PMTU
> when it sends a full-size segment itself. [...]
>
> Please re-run the 6.12.107 case without seeding the PMTU.

You are right. Without seeding, 6.12.107 stalls the same way:

  kernel        PMTU seeded   SYN-ACK MSS   1 MB upload
  6.12.107      no            1460          stalls
  6.12.107      yes (ping)    1416          OK

My reproducer took a shortcut there. What it should have modelled is
our production setup, which is the masquerading relay you describe:
the clients share the relay's address, so ordinary downloads by other
clients keep the server's PMTU entry fresh. Modelling that directly,
with no artificial seeding (cliA downloads 1 MB, then cliB, behind a
firewall dropping frag-needed, uploads 1 MB through the same relay):

  kernel        SYN-ACK MSS to cliB   cliB upload
  6.12.107      1416                  OK
  6.12.111      1460                  stalls

So I agree it was never a designed mechanism, it is the side effect
Eric describes. We have since added MSS clamping on our relays.

If it helps, I can send a v2 that describes the masquerading case
instead of the seeded one in the changelog. And I am happy to test
the net-next follow-up on this setup.

Thanks,
Esko


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net 2/2] Revert "net: advertise TCP MSS from the configured MTU, not the learned PMTU"
  2026-10-27 13:12       ` Esko Mobius
@ 2026-10-27 13:44         ` Jiayuan Chen
  0 siblings, 0 replies; 9+ messages in thread
From: Jiayuan Chen @ 2026-10-27 13:44 UTC (permalink / raw)
  To: Esko Mobius, Eric Dumazet
  Cc: netdev, Jakub Kicinski, Paolo Abeni, David S. Miller,
	Simon Horman, David Ahern, Ido Schimmel, Shuah Khan,
	Thorsten Leemhuis, regressions, linux-kselftest, linux-kernel,
	stable


On 10/27/26 9:12 PM, Esko Mobius wrote:
> On 10/27/26 1:45 PM, Jiayuan Chen wrote:
>> This precondition does all the work. The server only learns the PMTU
>> when it sends a full-size segment itself. [...]
>>
>> Please re-run the 6.12.107 case without seeding the PMTU.
> You are right. Without seeding, 6.12.107 stalls the same way:
>
>    kernel        PMTU seeded   SYN-ACK MSS   1 MB upload
>    6.12.107      no            1460          stalls
>    6.12.107      yes (ping)    1416          OK
>
> My reproducer took a shortcut there. What it should have modelled is
> our production setup, which is the masquerading relay you describe:
> the clients share the relay's address, so ordinary downloads by other
> clients keep the server's PMTU entry fresh. Modelling that directly,
> with no artificial seeding (cliA downloads 1 MB, then cliB, behind a
> firewall dropping frag-needed, uploads 1 MB through the same relay):
>
>    kernel        SYN-ACK MSS to cliB   cliB upload
>    6.12.107      1416                  OK
>    6.12.111      1460                  stalls


Thanks Esko for the testing, and Eric for the explanation. Agreed.


> So I agree it was never a designed mechanism, it is the side effect
> Eric describes. We have since added MSS clamping on our relays.
>
> If it helps, I can send a v2 that describes the masquerading case
> instead of the seeded one in the changelog. And I am happy to test
> the net-next follow-up on this setup.


No need for a v2 from my side, I just wanted to confirm the actual scenario.

I saw your report earlier but was swamped and could not get to it in 
time, sorry about that.


Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>

>
> Thanks,
> Esko

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-10-27 13:45 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-26  7:23 [PATCH net 0/2] Revert advertising the TCP MSS from the configured MTU Esko Mobius via B4 Relay
2026-10-26  7:23 ` [PATCH net 1/2] Revert "selftests: net: packetdrill: add tests for advertised MSS with PMTU exceptions" Esko Mobius via B4 Relay
2026-10-27 11:44   ` Jiayuan Chen
2026-10-26  7:23 ` [PATCH net 2/2] Revert "net: advertise TCP MSS from the configured MTU, not the learned PMTU" Esko Mobius via B4 Relay
2026-10-27 12:45   ` Jiayuan Chen
2026-10-27 13:02     ` Eric Dumazet
2026-10-27 13:12       ` Esko Mobius
2026-10-27 13:44         ` Jiayuan Chen
2026-10-26 13:28 ` [PATCH net 0/2] Revert advertising the TCP MSS from the configured MTU Eric Dumazet

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®