* [PATCH net-next v3 1/4] tcp: initialize MTU probing before syncing MSS at connection setup
2026-11-09 16:44 [PATCH net-next v3 0/4] tcp: fix tcp_base_mss on passive connections and test MTU probing Yongjian Wang via B4 Relay
@ 2026-11-09 16:44 ` Yongjian Wang via B4 Relay
2026-11-09 16:44 ` [PATCH net-next v3 2/4] selftests/net: packetdrill: test tcp_base_mss on passive connections Yongjian Wang via B4 Relay
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Yongjian Wang via B4 Relay @ 2026-11-09 16:44 UTC (permalink / raw)
To: davem, edumazet, pabeni, shuah, kuniyu, horms, ncardwell, kuba
Cc: netdev, panweiping3, linux-kernel, linux-kselftest, Yongjian Wang
From: Yongjian Wang <echoowall@gmail.com>
With tcp_mtu_probing=2, a passive connection starts at the full MSS
rather than tcp_base_mss. The IPv4 and IPv6 syn_recv_sock() paths
call tcp_sync_mss() before tcp_init_transfer() enables MTU probing.
With tcp_base_mss=1024, the first successful probe can therefore lower
the MSS from 1460 to 1242. On a black hole path, the first reduction
skips 1024 and goes straight to 512.
The issue surfaced while developing packetdrill coverage for MTU
probing and comparing the initial send MSS on active and passive
IPv4 connections.
Commit 4d83e1773031 ("tcp: delete redundant calls of tcp_mtup_init()")
removed tcp_mtup_init() from the passive setup paths.
Commit 27204aaa9dc6
("tcp: uniform the set up of sockets after successful connection")
later moved MTU probing initialization into tcp_init_transfer(),
away from tcp_sync_mss().
Initialize MTU probing immediately before the existing tcp_sync_mss()
calls in the IPv4 and IPv6 passive setup paths and when processing
a SYN-ACK for an active connection. Remove the late initialization
from tcp_init_transfer(). This lets tcp_sync_mss() apply tcp_base_mss
without adding another MSS calculation to connection setup. The
crossed-SYN path already uses this order.
Fixes: 4d83e1773031 ("tcp: delete redundant calls of tcp_mtup_init()")
Suggested-by: Kuniyuki Iwashima <kuniyu@google.com>
Suggested-by: Neal Cardwell <ncardwell@google.com>
Signed-off-by: Yongjian Wang <echoowall@gmail.com>
---
net/ipv4/tcp_input.c | 2 +-
net/ipv4/tcp_ipv4.c | 1 +
net/ipv6/tcp_ipv6.c | 1 +
3 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 3fd0e215324d..2b54b99f1f45 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -6763,7 +6763,6 @@ void tcp_init_transfer(struct sock *sk, int bpf_op, struct sk_buff *skb)
struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
- tcp_mtup_init(sk);
icsk->icsk_af_ops->rebuild_header(sk);
tcp_init_metrics(sk);
@@ -7020,6 +7019,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
tp->tcp_header_len = sizeof(struct tcphdr);
}
+ tcp_mtup_init(sk);
tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
tcp_initialize_rcv_mss(sk);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 0dc3b087665d..fb968798be36 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1740,6 +1740,7 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
tcp_ca_openreq_child(newsk, dst);
+ tcp_mtup_init(newsk);
tcp_sync_mss(newsk, dst4_mtu(dst));
newtp->advmss = tcp_mss_clamp(tcp_sk(sk), tcp_dst_advmss(dst));
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index b1dec5d86d63..8ea1ae1ad2b2 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1490,6 +1490,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
tcp_ca_openreq_child(newsk, dst);
+ tcp_mtup_init(newsk);
tcp_sync_mss(newsk, dst6_mtu(dst));
newtp->advmss = tcp_mss_clamp(tcp_sk(sk), tcp_dst_advmss(dst));
--
Git-157)
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH net-next v3 2/4] selftests/net: packetdrill: test tcp_base_mss on passive connections
2026-11-09 16:44 [PATCH net-next v3 0/4] tcp: fix tcp_base_mss on passive connections and test MTU probing Yongjian Wang via B4 Relay
2026-11-09 16:44 ` [PATCH net-next v3 1/4] tcp: initialize MTU probing before syncing MSS at connection setup Yongjian Wang via B4 Relay
@ 2026-11-09 16:44 ` Yongjian Wang via B4 Relay
2026-11-09 16:44 ` [PATCH net-next v3 3/4] selftests/net: packetdrill: add TCP black hole detection test Yongjian Wang via B4 Relay
2026-11-09 16:44 ` [PATCH net-next v3 4/4] selftests/net: packetdrill: add TCP MTU probing test Yongjian Wang via B4 Relay
3 siblings, 0 replies; 6+ messages in thread
From: Yongjian Wang via B4 Relay @ 2026-11-09 16:44 UTC (permalink / raw)
To: davem, edumazet, pabeni, shuah, kuniyu, horms, ncardwell, kuba
Cc: netdev, panweiping3, linux-kernel, linux-kselftest, Yongjian Wang
From: Yongjian Wang <echoowall@gmail.com>
Check that a passive connection starts at tcp_base_mss with
net.ipv4.tcp_mtu_probing=2, as an active connection does.
Signed-off-by: Yongjian Wang <echoowall@gmail.com>
---
.../net/packetdrill/tcp_mtu_probing_passive.pkt | 27 ++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/tools/testing/selftests/net/packetdrill/tcp_mtu_probing_passive.pkt b/tools/testing/selftests/net/packetdrill/tcp_mtu_probing_passive.pkt
new file mode 100644
index 000000000000..14bae144cce2
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_mtu_probing_passive.pkt
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test that a passive connection starts at tcp_base_mss with tcp_mtu_probing=2,
+// the same way as an active connection.
+
+`./defaults.sh
+sysctl -q net.ipv4.tcp_mtu_probing=2
+sysctl -q net.ipv4.tcp_base_mss=1024
+sysctl -q net.ipv4.tcp_timestamps=0`
+
+ 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,nop,nop,sackOK>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK>
+ +.1 < . 1:1(0) ack 1 win 65535
+ +0 accept(3, ..., ...) = 4
+
+// The initial window is sent with tcp_base_mss, not the peer's MSS.
+ +0 write(4, ..., 10240) = 10240
+ +0 > P. 1:2049(2048) ack 1
+ +0 > P. 2049:4097(2048) ack 1
+ +0 > P. 4097:6145(2048) ack 1
+ +0 > P. 6145:8193(2048) ack 1
+ +0 > P. 8193:10241(2048) ack 1
+ +.1 < . 1:1(0) ack 10241 win 65535
--
Git-157)
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH net-next v3 3/4] selftests/net: packetdrill: add TCP black hole detection test
2026-11-09 16:44 [PATCH net-next v3 0/4] tcp: fix tcp_base_mss on passive connections and test MTU probing Yongjian Wang via B4 Relay
2026-11-09 16:44 ` [PATCH net-next v3 1/4] tcp: initialize MTU probing before syncing MSS at connection setup Yongjian Wang via B4 Relay
2026-11-09 16:44 ` [PATCH net-next v3 2/4] selftests/net: packetdrill: test tcp_base_mss on passive connections Yongjian Wang via B4 Relay
@ 2026-11-09 16:44 ` Yongjian Wang via B4 Relay
2026-11-09 18:12 ` Neal Cardwell
2026-11-09 16:44 ` [PATCH net-next v3 4/4] selftests/net: packetdrill: add TCP MTU probing test Yongjian Wang via B4 Relay
3 siblings, 1 reply; 6+ messages in thread
From: Yongjian Wang via B4 Relay @ 2026-11-09 16:44 UTC (permalink / raw)
To: davem, edumazet, pabeni, shuah, kuniyu, horms, ncardwell, kuba
Cc: netdev, panweiping3, linux-kernel, linux-kselftest, Yongjian Wang
From: Yongjian Wang <echoowall@gmail.com>
Black hole detection (net.ipv4.tcp_mtu_probing=1) has no selftest
coverage.
Add a test where a full-sized segment keeps timing out without any ICMP
feedback. Check that the MSS drops to tcp_base_mss once tcp_retries1 is
exceeded, and that the smaller MSS is also used for new data after the
retransmission is acknowledged.
Set tcp_retries1 to 1 to keep the test short, and disable TLP so that
every retransmission comes from the RTO timer, which is what
tcp_write_timeout() counts.
Signed-off-by: Yongjian Wang <echoowall@gmail.com>
---
.../net/packetdrill/tcp_mtu_probing_blackhole.pkt | 37 ++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/tools/testing/selftests/net/packetdrill/tcp_mtu_probing_blackhole.pkt b/tools/testing/selftests/net/packetdrill/tcp_mtu_probing_blackhole.pkt
new file mode 100644
index 000000000000..f10dbb36dd2d
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_mtu_probing_blackhole.pkt
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test black hole detection with tcp_mtu_probing=1: when full-sized segments
+// keep timing out and no ICMP arrives, TCP falls back to tcp_base_mss.
+
+`./defaults.sh
+sysctl -q net.ipv4.tcp_mtu_probing=1
+sysctl -q net.ipv4.tcp_base_mss=1024
+sysctl -q net.ipv4.tcp_retries1=1
+sysctl -q net.ipv4.tcp_early_retrans=0`
+
+ 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,nop,nop,sackOK>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK>
+ +.1 < . 1:1(0) ack 1 win 65535
+ +0 accept(3, ..., ...) = 4
+
+ +0 write(4, ..., 1460) = 1460
+ +0 > P. 1:1461(1460) ack 1
+
+// The first retransmission keeps the full size.
+ +.3 > P. 1:1461(1460) ack 1
+
+// Once tcp_retries1 is exceeded the MSS drops to tcp_base_mss.
+ +.6 > . 1:1025(1024) ack 1
+ +.1 < . 1:1(0) ack 1025 win 65535
+ +0 > P. 1025:1461(436) ack 1
+ +.1 < . 1:1(0) ack 1461 win 65535
+
+// New data keeps using the smaller MSS.
+ +0 write(4, ..., 1460) = 1460
+ +0 > . 1461:2485(1024) ack 1
+ +0 > P. 2485:2921(436) ack 1
+ +.1 < . 1:1(0) ack 2921 win 65535
--
Git-157)
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net-next v3 3/4] selftests/net: packetdrill: add TCP black hole detection test
2026-11-09 16:44 ` [PATCH net-next v3 3/4] selftests/net: packetdrill: add TCP black hole detection test Yongjian Wang via B4 Relay
@ 2026-11-09 18:12 ` Neal Cardwell
0 siblings, 0 replies; 6+ messages in thread
From: Neal Cardwell @ 2026-11-09 18:12 UTC (permalink / raw)
To: echoowall
Cc: davem, edumazet, pabeni, shuah, kuniyu, horms, kuba, netdev,
panweiping3, linux-kernel, linux-kselftest
On Mon, Nov 9, 2026 at 11:44 AM Yongjian Wang via B4 Relay
<devnull+echoowall.gmail.com@kernel.org> wrote:
>
> From: Yongjian Wang <echoowall@gmail.com>
>
> Black hole detection (net.ipv4.tcp_mtu_probing=1) has no selftest
> coverage.
>
> Add a test where a full-sized segment keeps timing out without any ICMP
> feedback. Check that the MSS drops to tcp_base_mss once tcp_retries1 is
> exceeded, and that the smaller MSS is also used for new data after the
> retransmission is acknowledged.
>
> Set tcp_retries1 to 1 to keep the test short, and disable TLP so that
> every retransmission comes from the RTO timer, which is what
> tcp_write_timeout() counts.
>
> Signed-off-by: Yongjian Wang <echoowall@gmail.com>
> ---
> .../net/packetdrill/tcp_mtu_probing_blackhole.pkt | 37 ++++++++++++++++++++++
> 1 file changed, 37 insertions(+)
>
> diff --git a/tools/testing/selftests/net/packetdrill/tcp_mtu_probing_blackhole.pkt b/tools/testing/selftests/net/packetdrill/tcp_mtu_probing_blackhole.pkt
> new file mode 100644
> index 000000000000..f10dbb36dd2d
> --- /dev/null
> +++ b/tools/testing/selftests/net/packetdrill/tcp_mtu_probing_blackhole.pkt
> @@ -0,0 +1,37 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Test black hole detection with tcp_mtu_probing=1: when full-sized segments
> +// keep timing out and no ICMP arrives, TCP falls back to tcp_base_mss.
> +
> +`./defaults.sh
> +sysctl -q net.ipv4.tcp_mtu_probing=1
> +sysctl -q net.ipv4.tcp_base_mss=1024
> +sysctl -q net.ipv4.tcp_retries1=1
> +sysctl -q net.ipv4.tcp_early_retrans=0`
Thanks for the test! Though because of all these sysctl settings, this
is testing a fairly non-standard configuration. That's better than no
test at all, but IMHO it's more important to test the default
configurations users will be using.
So I'd suggest renaming this case to be something like
tcp_mtu_probing_blackhole_no_tlp_retries1_is_1.pkt.
Then I'd suggest creating a test like this, but with only the following setting:
`./defaults.sh
sysctl -q net.ipv4.tcp_mtu_probing=1`
That way we get test coverage for the most important scenarios and
code paths, and can understand the behavior that users will see if
they just set net.ipv4.tcp_mtu_probing=1 and do nothing else.
Thanks!
neal
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH net-next v3 4/4] selftests/net: packetdrill: add TCP MTU probing test
2026-11-09 16:44 [PATCH net-next v3 0/4] tcp: fix tcp_base_mss on passive connections and test MTU probing Yongjian Wang via B4 Relay
` (2 preceding siblings ...)
2026-11-09 16:44 ` [PATCH net-next v3 3/4] selftests/net: packetdrill: add TCP black hole detection test Yongjian Wang via B4 Relay
@ 2026-11-09 16:44 ` Yongjian Wang via B4 Relay
3 siblings, 0 replies; 6+ messages in thread
From: Yongjian Wang via B4 Relay @ 2026-11-09 16:44 UTC (permalink / raw)
To: davem, edumazet, pabeni, shuah, kuniyu, horms, ncardwell, kuba
Cc: netdev, panweiping3, linux-kernel, linux-kselftest, Yongjian Wang
From: Yongjian Wang <echoowall@gmail.com>
Packetization layer path MTU discovery (net.ipv4.tcp_mtu_probing=2) has
no selftest coverage.
Add a test for an active connection. Check that it starts at
tcp_base_mss, that it sends the first probe half way between
tcp_base_mss and the peer's MSS once cwnd allows it, and that an
acknowledged probe raises the MSS and leads to a larger probe.
The SYN offers timestamps and the scripted SYN-ACK declines them.
This also checks that MTU probing uses the negotiated header length
for the initial send MSS.
Signed-off-by: Yongjian Wang <echoowall@gmail.com>
---
.../net/packetdrill/tcp_mtu_probing_search.pkt | 42 ++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/tools/testing/selftests/net/packetdrill/tcp_mtu_probing_search.pkt b/tools/testing/selftests/net/packetdrill/tcp_mtu_probing_search.pkt
new file mode 100644
index 000000000000..a48acff8685e
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_mtu_probing_search.pkt
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test packetization layer path MTU discovery with tcp_mtu_probing=2: an
+// active connection starts at tcp_base_mss and raises its MSS by binary search
+// as probes are acknowledged.
+
+`./defaults.sh
+sysctl -q net.ipv4.tcp_mtu_probing=2
+sysctl -q net.ipv4.tcp_base_mss=1024`
+
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+ +0 connect(3, ..., ...) = -1 EINPROGRESS (Operation is now in progress)
+ +0 > S 0:0(0) <...>
+ +.1 < S. 0:0(0) ack 1 win 65535 <mss 1460,nop,nop,sackOK>
+ +0 > . 1:1(0) ack 1
+ +0 fcntl(3, F_SETFL, O_RDWR) = 0
+
+// The initial window is sent with tcp_base_mss. No probe yet, cwnd is below 11.
+ +0 write(3, ..., 40000) = 40000
+ +0 > P. 1:2049(2048) ack 1
+ +0 > P. 2049:4097(2048) ack 1
+ +0 > P. 4097:6145(2048) ack 1
+ +0 > P. 6145:8193(2048) ack 1
+ +0 > P. 8193:10241(2048) ack 1
+
+// The first probe is half way between tcp_base_mss and the peer's MSS.
+ +.1 < . 1:1(0) ack 10241 win 65535
+ +0 > . 10241:11483(1242) ack 1
+ +0 > P. 11483:13531(2048) ack 1
+ +0 > P. 13531:15579(2048) ack 1
+ +0 > P. 15579:17627(2048) ack 1
+ +0 > P. 17627:19675(2048) ack 1
+ +0 > P. 19675:21723(2048) ack 1
+ +0 > P. 21723:23771(2048) ack 1
+ +0 > P. 23771:25819(2048) ack 1
+ +0 > P. 25819:27867(2048) ack 1
+ +0 > P. 27867:29915(2048) ack 1
+
+// Acknowledging the probe raises the MSS, and the next probe is larger.
+ +.1 < . 1:1(0) ack 29915 win 65535
+ +0 > . 29915:31266(1351) ack 1
+ +0 > P. 31266:33750(2484) ack 1
--
Git-157)
^ permalink raw reply [flat|nested] 6+ messages in thread