From: Neil Ramaswamy <[email protected]> Reproduces a partial undo bug where a segment is unmarked as lost but is never returned to RACK's timestamp sorted list, which makes it ineligible for future fast retransmission.
Signed-off-by: Neil Ramaswamy <[email protected]> Assisted-by: LLM sparse --- ...tcp_partial_undo-restores-to-rack-list.pkt | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 tools/testing/selftests/net/packetdrill/tcp_partial_undo-restores-to-rack-list.pkt diff --git a/tools/testing/selftests/net/packetdrill/tcp_partial_undo-restores-to-rack-list.pkt b/tools/testing/selftests/net/packetdrill/tcp_partial_undo-restores-to-rack-list.pkt new file mode 100644 index 000000000000..c07a2f8a5cbd --- /dev/null +++ b/tools/testing/selftests/net/packetdrill/tcp_partial_undo-restores-to-rack-list.pkt @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Test that a segment unmarked as lost during partial undo is eligible +// for future fast retransmission. + +`./defaults.sh` + +// Establish a connection with a 100 ms RTT and a 1000-byte payload MSS. +// Linux subtracts the 12-byte timestamp options from the advertised MSS. + 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 + + +.1 < S 0:0(0) win 20000 <mss 1012,sackOK,TS val 1000 ecr 0> + +0 > S. 0:0(0) ack 1 <mss 1460,sackOK,TS val 100 ecr 1000> + +.1 < . 1:1(0) ack 1 win 20000 <nop,nop,TS val 1100 ecr 100> + +0 accept(3, ..., ...) = 4 + +// Send A, B, C and D, then E 47 ms after D. + +.01 write(4, ..., 1000) = 1000 + +0 > P. 1:1001(1000) ack 1 <nop,nop,TS val 210 ecr 1100> ++.001 write(4, ..., 1000) = 1000 + +0 > P. 1001:2001(1000) ack 1 <...> ++.001 write(4, ..., 1000) = 1000 + +0 > P. 2001:3001(1000) ack 1 <...> ++.001 write(4, ..., 1000) = 1000 + +0 > P. 3001:4001(1000) ack 1 <...> ++.047 write(4, ..., 1000) = 1000 + +0 > P. 4001:5001(1000) ack 1 <...> + +// SACK C and E together. RACK marks A, B and D lost. D is old enough +// to be retransmitted, but this ACK reports only two newly delivered +// segments, allowing A and B to be retransmitted while D waits. + +.12 < . 1:1(0) ack 1 win 20000 <TS val 1280 ecr 100,sack 4001:5001 2001:3001> + +0 > P. 1:1001(1000) ack 1 <...> + +0 > P. 1001:2001(1000) ack 1 <...> + +0 %{ +assert tcpi_ca_state == TCP_CA_Recovery, tcpi_ca_state +assert tcpi_lost == 3, tcpi_lost +assert tcpi_retrans == 2, tcpi_retrans +}% + +// Deliver retransmitted B and then the original A. D stays missing, +// and we ACK through C with A's original timestamp, which is before +// retransmission started. This triggers partial undo, but D should +// remain eligible for fast retransmission (critically, the timeout +// retransmission counter should be 0). + +.07 < . 1:1(0) ack 3001 win 20000 <TS val 1350 ecr 210,sack 4001:5001> + +0~+.05 > P. 3001:4001(1000) ack 1 <nop,nop,TS val 450 ecr 1350> + +0 %{ assert tcpi_retransmits == 0, tcpi_retransmits }% + +// Acknowledge all five segments. + +.01 < . 1:1(0) ack 5001 win 20000 <nop,nop,TS val 1360 ecr 450> -- 2.55.0

