1// SPDX-License-Identifier: GPL-2.0 2--ip_version=ipv4 3// 4// Reproduce urg_ptr being copied across segments on a multi-segment retransmit 5// in urgent mode (regression since 10d3be569243). 6// 7// server (kernel, under test) client (packetdrill) 8// | write(5000): 1:1001 .. 4001:5001 | mss 1000 from 9// | -------------------------------------------> | the client SYN 10// | send(MSG_OOB): 5001:5002 urg 1 | snd_up = 5002 11// | -------------------------------------------> | 12// | SACK 2001:5002, leaving hole 1:2001| 13// | <------------------------------------------- | 14// | retransmit hole 1:2001 as ONE skb: | 15// | seq=1, 2 segments, urg_ptr = 5002-1 = 5001| 16// | tun tso off -> software GSO splits it: | 17// | seg A 1:1001 urg_ptr 5001 (correct) | 18// | seg B 1001:2001 urg_ptr ? | 19// | want 5002-1001 = 4001 | 20// | bug inherits 5001 <- caught here | 21// | -------------------------------------------> | 22// 23 24`./defaults.sh` 25 26 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 27 +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 28 +0 bind(3, ..., ...) = 0 29 +0 listen(3, 1) = 0 30 31// 1. client force mss=1000 32 +.1 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7> 33 +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8> 34 +.1 < . 1:1(0) ack 1 win 320 35 +0 accept(3, ..., ...) = 4 36 37// 2. server sends 5000 bytes; TSO on, so packetdrill sees whole super-skbs 38 +0 write(4, ..., 5000) = 5000 39 +0 > P. 1:5001(5000) ack 1 40 41// 3. server send OOB 42 +0 send(4, ..., 1, MSG_OOB) = 1 43 +0 > PU. 5001:5002(1) ack 1 urg 1 44 45// We could disable GSO at the start of the script, but then the PSH flag on 46// the 5 initial server segments is not deterministic and hard to match. Keep 47// TSO on for the initial send (one super-skb, stable PSH) and disable it only 48// here, so software GSO splits the retransmit and each segment's urg_ptr is 49// checked on the wire. 50 +0 `ethtool -K tun0 tso off gso off gro off lro off 2>/dev/null` 51 52// 4. SACKed blocks reach dupthresh -> fast retransmit of the 1:2001 hole. 53 +.05 < . 1:1(0) ack 1 win 320 <sack 2001:3001,nop,nop> 54 +0 < . 1:1(0) ack 1 win 320 <sack 2001:4001,nop,nop> 55 +0 < . 1:1(0) ack 1 win 320 <sack 2001:5002,nop,nop> 56 57// Retransmit must keep a per-segment urg_ptr (5002 - seg.seq): seg A 5001, 58// seg B 4001. The fix sends the hole as two independent skbs, so seg B has 59// no PSH. Unpatched it goes out as one super-skb whose GSO split copies 60// urg_ptr onto seg B and also adds PSH there, so on an unpatched kernel the 61// mismatch shows up on the PSH bit before the urg_ptr. 62 +0 > U. 1:1001(1000) ack 1 urg 5001 63 +0 > U. 1001:2001(1000) ack 1 urg 4001 64 65 +.1 < . 1:1(0) ack 5002 win 320 66