On Tue, Sep 22, 2026 at 12:26 AM Jeff Jo <[email protected]> wrote:
>
> Add a regression test for a gap-filling packet whose acknowledgment has
> become old. Linux first sends data to the peer. Deliver two peer data
> packets out of order: the later packet acknowledges Linux's data, while
> the delayed packet still carries the earlier acknowledgment. Require
> the final reply to echo the delayed packet's timestamp.
>
> Use a large jump in peer timestamps to represent the idle interval.
> The test checks the echo directly, without waiting for that interval
> and without packet loss or retransmission.
>
> Packetdrill does not currently compare the timestamp-echo field (TSecr),
> so the packet script alone can pass on a broken kernel. Add a shell
> wrapper to check all four outgoing timestamp echoes in packetdrill's
> output. Register the wrapper as the runnable test and keep the packet
> script as a supporting file.
>
> Run the test in a separate network namespace for each of IPv4, IPv6
> and IPv4-mapped IPv6.
>
> Assisted-by: LLM
> Signed-off-by: Jeff Jo <[email protected]>

Thanks for your patches. But really we must not work around
packetdrill bugs like this.

pw-bot:cr

In the original 2013 packetdrill (commit 77954df72a78),
verify_outbound_live_tcp_options()
checked TS val against tolerance_usecs, then temporarily overwrote
actual_packet's TS val
with script_ts_val and called same_tcp_options(actual_packet,
script_packet) (memcmp),
which did verify TS ecr.

When commit 9a0ade62b7c8 ("net-test: packetdrill: merge Google
packetdrill changes
through April 2018") refactored option verification into a per-option
switch (actual_option->kind),
case TCPOPT_TIMESTAMP: checked actual_ts_val vs script_ts_val and
ended with break;
instead of checking actual_option->data.time_stamp.ecr (or rewriting
actual_ts_val to script_ts_val
and falling through to default:).

Fixing packetdrill in run_packet.c is just:

diff --git a/gtests/net/packetdrill/run_packet.c
b/gtests/net/packetdrill/run_packet.c
index 4aa235d35585..f5fdc8699970 100644
--- a/gtests/net/packetdrill/run_packet.c
+++ b/gtests/net/packetdrill/run_packet.c
@@ -1483,6 +1483,10 @@ static int verify_outbound_tcp_option(
                        asprintf(error, "bad outbound TCP timestamp
value, tolerance %ld", tolerance_usecs);
                        return STATUS_ERR;
                }
+               if (check_field("tcp_ts_ecr",
+                               packet_tcp_ts_ecr(script_packet),
+                               packet_tcp_ts_ecr(actual_packet), error))
+                       return STATUS_ERR;
                break;

        default:

Please work with Neal Cardwell to get packetdrill fixed, then ask
netdev maintainers to
upgrade packetdrill on their test servers.



Note: Even with existing packetdrill binaries in the wild that don't
check TS ecr,
tp->rx_opt.ts_recent is still directly testable in pure .pkt via PAWS
(tcp_paws_discard()),
the same way tcp_ts_recent_invalid_ack.pkt works:


// SPDX-License-Identifier: GPL-2.0
// An out-of-order segment advances SND.UNA. The gap filler still carries
// its original, older ACK; accepting its data must refresh TS.Recent.
--tcp_ts_tick_usecs=1000
`./defaults.sh`
0.000 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.100 < S 0:0(0) win 20000 <mss 1000,sackOK,TS val 900 ecr 0>
+0 > S. 0:0(0) ack 1 <mss 1460,sackOK,TS val 100 ecr 900>
0.200 < . 1:1(0) ack 1 win 20000 <nop,nop,TS val 1000 ecr 100>
+0 accept(3, ..., ...) = 4
0.300 write(4, ..., 17) = 17
+0 > P. 1:18(17) ack 1 <nop,nop,TS val 300 ecr 1000>
0.310 < P. 18:35(17) ack 18 win 20000 <nop,nop,TS val 301001 ecr 300>
+0 > . 18:18(0) ack 1 <nop,nop,TS val 310 ecr 1000,nop,nop,sack 18:35>
0.320 < P. 1:18(17) ack 1 win 20000 <nop,nop,TS val 301000 ecr 100>
+0 > . 18:18(0) ack 35 <nop,nop,TS val 320 ecr 301000>
// Verify TS.Recent was updated to 301000: a segment with TSval < 301000
// (but > old TS.Recent 1000) must be rejected by PAWS and trigger dupack 35.
0.330 < P. 35:52(17) ack 18 win 20000 <nop,nop,TS val 300999 ecr 320>
+0 > . 18:18(0) ack 35 <nop,nop,TS val 330 ecr 301000>
+0 read(4, ..., 34) = 34

Reply via email to