xref: /linux/tools/testing/selftests/net/packetdrill/tcp_urg_ptr_retransmit.pkt (revision 67f8bc848ee31831336bd478e57d2f993551902e)
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