blob: 22f750ce09c19dc04e769210762210c483223f35 [file]
// SPDX-License-Identifier: GPL-2.0
--ip_version=ipv4
//
// Reproduce urg_ptr being copied across segments on a multi-segment retransmit
// in urgent mode (regression since 10d3be569243).
//
// server (kernel, under test) client (packetdrill)
// | write(5000): 1:1001 .. 4001:5001 | mss 1000 from
// | -------------------------------------------> | the client SYN
// | send(MSG_OOB): 5001:5002 urg 1 | snd_up = 5002
// | -------------------------------------------> |
// | SACK 2001:5002, leaving hole 1:2001|
// | <------------------------------------------- |
// | retransmit hole 1:2001 as ONE skb: |
// | seq=1, 2 segments, urg_ptr = 5002-1 = 5001|
// | tun tso off -> software GSO splits it: |
// | seg A 1:1001 urg_ptr 5001 (correct) |
// | seg B 1001:2001 urg_ptr ? |
// | want 5002-1001 = 4001 |
// | bug inherits 5001 <- caught here |
// | -------------------------------------------> |
//
`./defaults.sh`
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. client force mss=1000
+.1 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.1 < . 1:1(0) ack 1 win 320
+0 accept(3, ..., ...) = 4
// 2. server sends 5000 bytes; TSO on, so packetdrill sees whole super-skbs
+0 write(4, ..., 5000) = 5000
+0 > P. 1:5001(5000) ack 1
// 3. server send OOB
+0 send(4, ..., 1, MSG_OOB) = 1
+0 > PU. 5001:5002(1) ack 1 urg 1
// We could disable GSO at the start of the script, but then the PSH flag on
// the 5 initial server segments is not deterministic and hard to match. Keep
// TSO on for the initial send (one super-skb, stable PSH) and disable it only
// here, so software GSO splits the retransmit and each segment's urg_ptr is
// checked on the wire.
+0 `ethtool -K tun0 tso off gso off gro off lro off 2>/dev/null`
// 4. SACKed blocks reach dupthresh -> fast retransmit of the 1:2001 hole.
+.05 < . 1:1(0) ack 1 win 320 <sack 2001:3001,nop,nop>
+0 < . 1:1(0) ack 1 win 320 <sack 2001:4001,nop,nop>
+0 < . 1:1(0) ack 1 win 320 <sack 2001:5002,nop,nop>
// Retransmit must keep a per-segment urg_ptr (5002 - seg.seq): seg A 5001,
// seg B 4001. The fix sends the hole as two independent skbs, so seg B has
// no PSH. Unpatched it goes out as one super-skb whose GSO split copies
// urg_ptr onto seg B and also adds PSH there, so on an unpatched kernel the
// mismatch shows up on the PSH bit before the urg_ptr.
+0 > U. 1:1001(1000) ack 1 urg 5001
+0 > U. 1001:2001(1000) ack 1 urg 4001
+.1 < . 1:1(0) ack 5002 win 320