Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'selftest-packetdrill-import-tfo-server-tests'

Kuniyuki Iwashima says:

====================
selftest: packetdrill: Import TFO server tests.

The series imports 15 TFO server tests from google/packetdrill and
adds 2 more tests.

The repository has two versions of tests for most scenarios; one uses
the non-experimental option (34), and the other uses the experimental
option (255) with 0xF989.

Basically, we only import the non-experimental version of tests, and
for the experimental option, tcp_fastopen_server_experimental_option.pkt
is added.

The following tests are not (yet) imported:

* icmp-baseline.pkt
* simple1.pkt / simple2.pkt / simple3.pkt

The former is completely covered by icmp-before-accept.pkt.

The later's delta is the src/dst IP pair to generate a different
cookie, but supporting dualstack requires churn in ksft_runner.sh,
so defered to future series. Also, sockopt-fastopen-key.pkt covers
the same function.

The following tests have the experimental version only, so converted
to the non-experimental option:

* client-ack-dropped-then-recovery-ms-timestamps.pkt
* sockopt-fastopen-key.pkt

For the imported tests, these common changes are applied.

* Add SPDX header
* Adjust path to default.sh
* Adjust sysctl w/ set_sysctls.py
* Use TFO_COOKIE instead of a raw hex value
* Use SOCK_NONBLOCK for socket() not to block accept()
* Add assertions for TCP state if commented
* Remove unnecessary delay (e.g. +0.1 setsockopt(SO_REUSEADDR), etc)

With this series, except for simple{1,2,3}.pkt, we can remove TFO server
tests in google/packetdrill.
====================

Link: https://patch.msgid.link/20250927213022.1850048-1-kuniyu@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+611 -6
+2 -1
tools/testing/selftests/net/packetdrill/defaults.sh
··· 51 51 sysctl -q net.ipv4.tcp_pacing_ca_ratio=120 52 52 sysctl -q net.ipv4.tcp_notsent_lowat=4294967295 > /dev/null 2>&1 53 53 54 - sysctl -q net.ipv4.tcp_fastopen=0x70403 54 + sysctl -q net.ipv4.tcp_fastopen=0x3 55 + # Use TFO_COOKIE in ksft_runner.sh for this key. 55 56 sysctl -q net.ipv4.tcp_fastopen_key=a1a1a1a1-b2b2b2b2-c3c3c3c3-d4d4d4d4 56 57 57 58 sysctl -q net.ipv4.tcp_syncookies=1
+6 -2
tools/testing/selftests/net/packetdrill/ksft_runner.sh
··· 9 9 --gateway_ip=192.168.0.1 10 10 --netmask_ip=255.255.0.0 11 11 --remote_ip=192.0.2.1 12 + -D TFO_COOKIE=3021b9d889017eeb 13 + -D TFO_COOKIE_ZERO=b7c12350a90dc8f5 12 14 -D CMSG_LEVEL_IP=SOL_IP 13 15 -D CMSG_TYPE_RECVERR=IP_RECVERR" 14 16 [ipv6]="--ip_version=ipv6 ··· 18 16 --local_ip=fd3d:0a0b:17d6::1 19 17 --gateway_ip=fd3d:0a0b:17d6:8888::1 20 18 --remote_ip=fd3d:fa7b:d17d::1 19 + -D TFO_COOKIE=c1d1e9742a47a9bc 20 + -D TFO_COOKIE_ZERO=82af1a8f9a205c34 21 21 -D CMSG_LEVEL_IP=SOL_IPV6 22 22 -D CMSG_TYPE_RECVERR=IPV6_RECVERR" 23 23 ) ··· 52 48 fi 53 49 54 50 ktap_print_header 55 - ktap_set_plan 2 51 + ktap_set_plan $(echo $ip_versions | wc -w) 56 52 57 53 for ip_version in $ip_versions; do 58 54 unshare -n packetdrill ${ip_args[$ip_version]} ${optargs[@]} $script > /dev/null \ 59 - && ktap_test_pass $ip_version || $failfunc $ip_version 55 + && ktap_test_pass $ip_version || $failfunc $ip_version 60 56 done 61 57 62 58 ktap_finished
+21
tools/testing/selftests/net/packetdrill/tcp_fastopen_server_basic-no-setsockopt.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Basic TFO server test 4 + // 5 + // Test TFO_SERVER_WO_SOCKOPT1 without setsockopt(TCP_FASTOPEN) 6 + 7 + `./defaults.sh 8 + ./set_sysctls.py /proc/sys/net/ipv4/tcp_fastopen=0x402` 9 + 10 + 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 11 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 12 + +0 bind(3, ..., ...) = 0 13 + +0 listen(3, 1) = 0 14 + 15 + +0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,FO TFO_COOKIE,nop,nop> 16 + +0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK> 17 + 18 + +0 accept(3, ..., ...) = 4 19 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }% 20 + 21 + +0 read(4, ..., 512) = 10
+26
tools/testing/selftests/net/packetdrill/tcp_fastopen_server_basic-non-tfo-listener.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Basic TFO server test 4 + // 5 + // Server w/o TCP_FASTOPEN socket option 6 + 7 + `./defaults.sh` 8 + 9 + 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 10 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 11 + +0 bind(3, ..., ...) = 0 12 + +0 listen(3, 1) = 0 13 + 14 + +0 < S 0:10(10) win 32792 <mss 1460,sackOK,FO TFO_COOKIE> 15 + 16 + // Data is ignored since TCP_FASTOPEN is not set on the listener 17 + +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK> 18 + 19 + +0 accept(3, ..., ...) = -1 EAGAIN (Resource temporarily unavailable) 20 + 21 + // The above should block until ack comes in below. 22 + +0 < . 1:31(30) ack 1 win 5840 23 + +0 accept(3, ..., ...) = 4 24 + 25 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }% 26 + +0 read(4, ..., 512) = 30
+50
tools/testing/selftests/net/packetdrill/tcp_fastopen_server_basic-pure-syn-data.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Basic TFO server test 4 + // 5 + // Test that TFO-enabled server would not respond SYN-ACK with any TFO option 6 + // when receiving a pure SYN-data. It should respond a pure SYN-ack. 7 + 8 + `./defaults.sh` 9 + 10 + 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 11 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 12 + +0 bind(3, ..., ...) = 0 13 + +0 listen(3, 1) = 0 14 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 15 + 16 + +0 < S 999000:999040(40) win 32792 <mss 1460,sackOK,TS val 100 ecr 100,nop,wscale 6> 17 + +0 > S. 1234:1234(0) ack 999001 <mss 1460,sackOK,TS val 100 ecr 100,nop,wscale 8> 18 + +0 < . 1:1(0) ack 1 win 100 19 + +0 accept(3, ..., ...) = 4 20 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }% 21 + +0 close(3) = 0 22 + 23 + // Test ECN-setup SYN with ECN disabled because this has happened in reality 24 + +0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 25 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 26 + +0 bind(3, ..., ...) = 0 27 + +0 listen(3, 1) = 0 28 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 29 + 30 + +0 < SEW 999000:999040(40) win 32792 <mss 1460,sackOK,TS val 100 ecr 100,nop,wscale 6> 31 + +0 > S. 1234:1234(0) ack 999001 <mss 1460,sackOK,TS val 100 ecr 100,nop,wscale 8> 32 + +0 < . 1:1(0) ack 1 win 100 33 + +0 accept(3, ..., ...) = 4 34 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }% 35 + +0 close(3) = 0 36 + 37 + // Test ECN-setup SYN w/ ECN enabled 38 + +0 `sysctl -q net.ipv4.tcp_ecn=2` 39 + +0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 40 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 41 + +0 bind(3, ..., ...) = 0 42 + +0 listen(3, 1) = 0 43 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 44 + 45 + +0 < SEW 999000:999040(40) win 32792 <mss 1460,sackOK,TS val 100 ecr 100,nop,wscale 6> 46 + +0 > SE. 1234:1234(0) ack 999001 <mss 1460,sackOK,TS val 100 ecr 100,nop,wscale 8> 47 + +0 < . 1:1(0) ack 1 win 100 48 + +0 accept(3, ..., ...) = 4 49 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }% 50 + +0 close(3) = 0
+23
tools/testing/selftests/net/packetdrill/tcp_fastopen_server_basic-rw.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Basic TFO server test 4 + // 5 + // Test TFO server with SYN that has TFO cookie and data. 6 + 7 + `./defaults.sh` 8 + 9 + 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 10 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 11 + +0 bind(3, ..., ...) = 0 12 + +0 listen(3, 1) = 0 13 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 14 + 15 + +0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,FO TFO_COOKIE,nop,nop> 16 + +0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK> 17 + 18 + +0 accept(3, ..., ...) = 4 19 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }% 20 + 21 + +0 read(4, ..., 512) = 10 22 + +0 write(4, ..., 100) = 100 23 + +0 > P. 1:101(100) ack 11
+26
tools/testing/selftests/net/packetdrill/tcp_fastopen_server_basic-zero-payload.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Basic TFO server test 4 + // 5 + // Test zero-payload packet w/ valid TFO cookie - a TFO socket will 6 + // still be created and accepted but read() will not return until a 7 + // later pkt with 10 byte. 8 + 9 + `./defaults.sh` 10 + 11 + 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 12 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 13 + +0 bind(3, ..., ...) = 0 14 + +0 listen(3, 1) = 0 15 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 16 + 17 + +0 < S 0:0(0) win 32792 <mss 1460,sackOK,nop,nop,FO TFO_COOKIE,nop,nop> 18 + +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK> 19 + +0 accept(3, ..., ...) = 4 20 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }% 21 + 22 + // A TFO socket is created and is writable. 23 + +0 write(4, ..., 100) = 100 24 + +0 > P. 1:101(100) ack 1 25 + +0...0.300 read(4, ..., 512) = 10 26 + +.3 < P. 1:11(10) ack 1 win 5840
+46
tools/testing/selftests/net/packetdrill/tcp_fastopen_server_client-ack-dropped-then-recovery-ms-timestamps.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // A reproducer case for a TFO SYNACK RTO undo bug in: 4 + // 794200d66273 ("tcp: undo cwnd on Fast Open spurious SYNACK retransmit") 5 + // This sequence that tickles this bug is: 6 + // - Fast Open server receives TFO SYN with data, sends SYNACK 7 + // - (client receives SYNACK and sends ACK, but ACK is lost) 8 + // - server app sends some data packets 9 + // - (N of the first data packets are lost) 10 + // - server receives client ACK that has a TS ECR matching first SYNACK, 11 + // and also SACKs suggesting the first N data packets were lost 12 + // - server performs undo of SYNACK RTO, then immediately enters recovery 13 + // - buggy behavior in 794200d66273 then performed an undo that caused 14 + // the connection to be in a bad state, in CA_Open with retrans_out != 0 15 + 16 + // Check that outbound TS Val ticks are as we would expect with 1000 usec per 17 + // timestamp tick: 18 + --tcp_ts_tick_usecs=1000 19 + 20 + `./defaults.sh` 21 + 22 + // Initialize connection 23 + 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 24 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 25 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 26 + +0 bind(3, ..., ...) = 0 27 + +0 listen(3, 1) = 0 28 + 29 + +0 < S 0:1000(1000) win 65535 <mss 1012,sackOK,TS val 1000 ecr 0,wscale 7,nop,nop,nop,FO TFO_COOKIE> 30 + +0 > S. 0:0(0) ack 1001 <mss 1460,sackOK,TS val 2000 ecr 1000,nop,wscale 8> 31 + +0 accept(3, ..., ...) = 4 32 + 33 + // Application writes more data 34 + +.010 write(4, ..., 10000) = 10000 35 + +0 > P. 1:5001(5000) ack 1001 <nop,nop,TS val 2010 ecr 1000> 36 + +0 > P. 5001:10001(5000) ack 1001 <nop,nop,TS val 2010 ecr 1000> 37 + +0 %{ assert tcpi_snd_cwnd == 10, tcpi_snd_cwnd }% 38 + 39 + +0 < . 1001:1001(0) ack 1 win 257 <TS val 1010 ecr 2000,sack 2001:5001> 40 + +0 > P. 1:2001(2000) ack 1001 <nop,nop,TS val 2010 ecr 1010> 41 + +0 %{ assert tcpi_ca_state == TCP_CA_Recovery, tcpi_ca_state }% 42 + +0 %{ assert tcpi_snd_cwnd == 7, tcpi_snd_cwnd }% 43 + 44 + +0 < . 1001:1001(0) ack 1 win 257 <TS val 1011 ecr 2000,sack 2001:6001> 45 + +0 %{ assert tcpi_ca_state == TCP_CA_Recovery, tcpi_ca_state }% 46 + +0 %{ assert tcpi_snd_cwnd == 7, tcpi_snd_cwnd }%
+37
tools/testing/selftests/net/packetdrill/tcp_fastopen_server_experimental_option.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Test the Experimental Option 4 + // 5 + // SYN w/ FOEXP w/o cookie must generates SYN+ACK w/ FOEXP 6 + // w/ a valid cookie, and the cookie must be the same one 7 + // with one generated by IANA FO 8 + 9 + `./defaults.sh` 10 + 11 + // Request a TFO cookie by Experimental Option 12 + // This must generate the same TFO_COOKIE 13 + 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 14 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 15 + +0 bind(3, ..., ...) = 0 16 + +0 listen(3, 1) = 0 17 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 18 + 19 + +0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,FOEXP> 20 + +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,FOEXP TFO_COOKIE> 21 + 22 + +0 close(3) = 0 23 + 24 + // Test if FOEXP with a valid cookie creates a TFO socket 25 + 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 26 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 27 + +0 bind(3, ..., ...) = 0 28 + +0 listen(3, 1) = 0 29 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 30 + 31 + +0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,FOEXP TFO_COOKIE> 32 + +0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK> 33 + 34 + +0 accept(3, ..., ...) = 4 35 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }% 36 + 37 + +0 read(4, ..., 512) = 10
+30
tools/testing/selftests/net/packetdrill/tcp_fastopen_server_fin-close-socket.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Send a FIN pkt with the ACK bit to a TFO socket. 4 + // The socket will go to TCP_CLOSE_WAIT state and data can be 5 + // read until the socket is closed, at which time a FIN will be sent. 6 + 7 + `./defaults.sh` 8 + 9 + 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 10 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 11 + +0 bind(3, ..., ...) = 0 12 + +0 listen(3, 1) = 0 13 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 14 + 15 + +0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,FO TFO_COOKIE,nop,nop> 16 + +0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK> 17 + 18 + // FIN is acked and the socket goes to TCP_CLOSE_WAIT state 19 + // in tcp_fin() called from tcp_data_queue(). 20 + +0 < F. 11:11(0) ack 1 win 32792 21 + +0 > . 1:1(0) ack 12 22 + 23 + +0 accept(3, ..., ...) = 4 24 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }% 25 + +0 %{ assert tcpi_state == TCP_CLOSE_WAIT, tcpi_state }% 26 + 27 + +0 read(4, ..., 512) = 10 28 + +0 close(4) = 0 29 + +0 > F. 1:1(0) ack 12 30 + * > F. 1:1(0) ack 12
+49
tools/testing/selftests/net/packetdrill/tcp_fastopen_server_icmp-before-accept.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Send an ICMP host_unreachable pkt to a pending SYN_RECV req. 4 + // 5 + // If it's a TFO req, the ICMP error will cause it to switch 6 + // to TCP_CLOSE state but remains in the acceptor queue. 7 + 8 + --ip_version=ipv4 9 + 10 + `./defaults.sh` 11 + 12 + 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 13 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 14 + +0 bind(3, ..., ...) = 0 15 + +0 listen(3, 1) = 0 16 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 17 + 18 + +0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,FO TFO_COOKIE,nop,nop> 19 + +0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK> 20 + 21 + // Out-of-window icmp is ignored but accounted. 22 + +0 `nstat > /dev/null` 23 + +0 < icmp unreachable [5000:6000(1000)] 24 + +0 `nstat | grep TcpExtOutOfWindowIcmps > /dev/null` 25 + 26 + // Valid ICMP unreach. 27 + +0 < icmp unreachable host_unreachable [0:10(10)] 28 + 29 + // Unlike the non-TFO case, the req is still there to be accepted. 30 + +0 accept(3, ..., ...) = 4 31 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }% 32 + 33 + // tcp_done_with_error() in tcp_v4_err() sets sk->sk_state 34 + // to TCP_CLOSE 35 + +0 %{ assert tcpi_state == TCP_CLOSE, tcpi_state }% 36 + 37 + // The 1st read will succeed and return the data in SYN 38 + +0 read(4, ..., 512) = 10 39 + 40 + // The 2nd read will fail. 41 + +0 read(4, ..., 512) = -1 EHOSTUNREACH (No route to host) 42 + 43 + // But is no longer writable because it's in TCP_CLOSE state. 44 + +0 write(4, ..., 100) = -1 EPIPE (Broken Pipe) 45 + 46 + // inbound pkt will trigger RST because the socket has been moved 47 + // off the TCP hash tables. 48 + +0 < . 1:1(0) ack 1 win 32792 49 + +0 > R 1:1(0)
+37
tools/testing/selftests/net/packetdrill/tcp_fastopen_server_reset-after-accept.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Send a RST to a TFO socket after it has been accepted. 4 + // 5 + // First read() will return all the data and this is consistent 6 + // with the non-TFO case. Second read will return -1 7 + 8 + `./defaults.sh` 9 + 10 + 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 11 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 12 + +0 bind(3, ..., ...) = 0 13 + +0 listen(3, 1) = 0 14 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 15 + 16 + +0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,FO TFO_COOKIE,nop,nop> 17 + +0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK> 18 + 19 + +0 accept(3, ..., ...) = 4 20 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }% 21 + +0 %{ assert tcpi_state == TCP_SYN_RECV, tcpi_state }% 22 + 23 + // 1st read will return the data from SYN. 24 + // tcp_reset() sets sk->sk_err to ECONNRESET for SYN_RECV. 25 + +0 < R. 11:11(0) win 32792 26 + +0 %{ assert tcpi_state == TCP_CLOSE, tcpi_state }% 27 + 28 + // This one w/o ACK bit will cause the same effect. 29 + // +0 < R 11:11(0) win 32792 30 + // See Step 2 in tcp_validate_incoming(). 31 + 32 + // found_ok_skb in tcp_recvmsg_locked() 33 + +0 read(4, ..., 512) = 10 34 + 35 + // !copied && sk->sk_err -> sock_error(sk) 36 + +0 read(4, ..., 512) = -1 ECONNRESET (Connection reset by peer) 37 + +0 close(4) = 0
+7 -3
tools/testing/selftests/net/packetdrill/tcp_fastopen_server_reset-after-disconnect.pkt tools/testing/selftests/net/packetdrill/tcp_fastopen_server_trigger-rst-reconnect.pkt
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 `./defaults.sh 3 - ./set_sysctls.py /proc/sys/net/ipv4/tcp_fastopen=0x602 /proc/sys/net/ipv4/tcp_timestamps=0` 3 + ./set_sysctls.py /proc/sys/net/ipv4/tcp_timestamps=0` 4 4 5 5 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 6 6 +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 7 7 +0 bind(3, ..., ...) = 0 8 8 +0 listen(3, 1) = 0 9 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 9 10 10 - +0 < S 0:10(10) win 32792 <mss 1460,nop,nop,sackOK> 11 + +0 < S 0:10(10) win 32792 <mss 1460,nop,nop,sackOK,nop,nop,FO TFO_COOKIE> 11 12 +0 > S. 0:0(0) ack 11 win 65535 <mss 1460,nop,nop,sackOK> 12 13 13 14 // sk->sk_state is TCP_SYN_RECV 14 - +.1 accept(3, ..., ...) = 4 15 + +0 accept(3, ..., ...) = 4 16 + +0 %{ assert tcpi_state == TCP_SYN_RECV, tcpi_state }% 15 17 16 18 // tcp_disconnect() sets sk->sk_state to TCP_CLOSE 17 19 +0 connect(4, AF_UNSPEC, ...) = 0 18 20 +0 > R. 1:1(0) ack 11 win 65535 21 + +0 %{ assert tcpi_state == TCP_CLOSE, tcpi_state }% 19 22 20 23 // connect() sets sk->sk_state to TCP_SYN_SENT 21 24 +0 fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0 22 25 +0 connect(4, ..., ...) = -1 EINPROGRESS (Operation is now in progress) 23 26 +0 > S 0:0(0) win 65535 <mss 1460,nop,nop,sackOK,nop,wscale 8> 27 + +0 %{ assert tcpi_state == TCP_SYN_SENT, tcpi_state }% 24 28 25 29 // tp->fastopen_rsk must be NULL 26 30 +1 > S 0:0(0) win 65535 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+32
tools/testing/selftests/net/packetdrill/tcp_fastopen_server_reset-before-accept.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Send a RST to a TFO socket before it is accepted. 4 + // 5 + // The socket won't go away and after it's accepted the data 6 + // in the SYN pkt can still be read. But that's about all that 7 + // the acceptor can do with the socket. 8 + 9 + `./defaults.sh` 10 + 11 + 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 12 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 13 + +0 bind(3, ..., ...) = 0 14 + +0 listen(3, 1) = 0 15 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 16 + 17 + +0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,nop,wscale 7,FO TFO_COOKIE,nop,nop> 18 + +0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK,nop,wscale 8> 19 + 20 + // 1st read will return the data from SYN. 21 + +0 < R. 11:11(0) win 257 22 + 23 + // This one w/o ACK bit will cause the same effect. 24 + // +0 < R 11:11(0) win 257 25 + 26 + +0 accept(3, ..., ...) = 4 27 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }% 28 + +0 %{ assert tcpi_state == TCP_CLOSE, tcpi_state }% 29 + 30 + +0 read(4, ..., 512) = 10 31 + +0 read(4, ..., 512) = -1 ECONNRESET (Connection reset by peer) 32 + +0 close(4) = 0
+32
tools/testing/selftests/net/packetdrill/tcp_fastopen_server_reset-close-with-unread-data.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Send a RST to a TFO socket after it is accepted. 4 + // 5 + // The socket will change to TCP_CLOSE state with pending data so 6 + // write() will fail. Pending data can be still be read and close() 7 + // won't trigger RST if data is not read 8 + // 9 + // 565b7b2d2e63 ("tcp: do not send reset to already closed sockets") 10 + // https://lore.kernel.org/netdev/4C1A2502.1030502@openvz.org/ 11 + 12 + `./defaults.sh` 13 + 14 + 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 15 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 16 + +0 bind(3, ..., ...) = 0 17 + +0 listen(3, 1) = 0 18 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 19 + 20 + +0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop, FO TFO_COOKIE,nop,nop> 21 + +0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK> 22 + 23 + +0 accept(3, ..., ...) = 4 24 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }% 25 + +0 %{ assert tcpi_state == TCP_SYN_RECV, tcpi_state }% 26 + 27 + // tcp_done() sets sk->sk_state to TCP_CLOSE and clears tp->fastopen_rsk 28 + +0 < R. 11:11(0) win 32792 29 + +0 %{ assert tcpi_state == TCP_CLOSE, tcpi_state }% 30 + 31 + +0 write(4, ..., 100) = -1 ECONNRESET(Connection reset by peer) 32 + +0 close(4) = 0
+37
tools/testing/selftests/net/packetdrill/tcp_fastopen_server_reset-non-tfo-socket.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Send a RST to a fully established socket with pending data before 4 + // it is accepted. 5 + // 6 + // The socket with pending data won't go away and can still be accepted 7 + // with data read. But it will be in TCP_CLOSE state. 8 + 9 + `./defaults.sh` 10 + 11 + 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 12 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 13 + +0 bind(3, ..., ...) = 0 14 + +0 listen(3, 1) = 0 15 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 16 + 17 + // Invalid cookie, so accept() fails. 18 + +0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,FO aaaaaaaaaaaaaaaa,nop,nop> 19 + +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK, FO TFO_COOKIE,nop,nop> 20 + 21 + +0 accept(3, ..., ...) = -1 EAGAIN (Resource temporarily unavailable) 22 + 23 + // Complete 3WHS and send data and RST 24 + +0 < . 1:1(0) ack 1 win 32792 25 + +0 < . 1:11(10) ack 1 win 32792 26 + +0 < R. 11:11(0) win 32792 27 + 28 + // A valid reset won't make the fully-established socket go away. 29 + // It's just that the acceptor will get a dead, unusable socket 30 + // in TCP_CLOSE state. 31 + +0 accept(3, ..., ...) = 4 32 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }% 33 + +0 %{ assert tcpi_state == TCP_CLOSE, tcpi_state }% 34 + 35 + +0 write(4, ..., 100) = -1 ECONNRESET(Connection reset by peer) 36 + +0 read(4, ..., 512) = 10 37 + +0 read(4, ..., 512) = 0
+74
tools/testing/selftests/net/packetdrill/tcp_fastopen_server_sockopt-fastopen-key.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Test the server cookie is generated by aes64 encoding of remote and local 4 + // IP addresses with a master key specified via sockopt TCP_FASTOPEN_KEY 5 + // 6 + `./defaults.sh 7 + ./set_sysctls.py /proc/sys/net/ipv4/tcp_fastopen_key=00000000-00000000-00000000-00000000` 8 + 9 + 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 10 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 11 + 12 + // Set a key of a1a1a1a1-b2b2b2b2-c3c3c3c3-d4d4d4d4 (big endian). 13 + // This would produce a cookie of TFO_COOKIE like many other 14 + // tests (which the same key but set via sysctl). 15 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN_KEY, 16 + "\xa1\xa1\xa1\xa1\xb2\xb2\xb2\xb2\xc3\xc3\xc3\xc3\xd4\xd4\xd4\xd4", 16) = 0 17 + 18 + +0 bind(3, ..., ...) = 0 19 + +0 listen(3, 1) = 0 20 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 21 + 22 + // Request a valid cookie TFO_COOKIE 23 + +0 < S 1428932:1428942(10) win 10000 <mss 1012,nop,nop,FO,sackOK,TS val 1 ecr 0,nop,wscale 7> 24 + +0 > S. 0:0(0) ack 1428933 <mss 1460,sackOK,TS val 10000 ecr 1,nop,wscale 8,FO TFO_COOKIE,nop,nop> 25 + +0 < . 1:1(0) ack 1 win 257 <nop,nop,TS val 2 ecr 10000> 26 + +0 accept(3, ..., ...) = 4 27 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }% 28 + 29 + +0 close(4) = 0 30 + +0 > F. 1:1(0) ack 1 <nop,nop,TS val 10001 ecr 2> 31 + +0 < F. 1:1(0) ack 2 win 257 <nop,nop,TS val 3 ecr 10001> 32 + +0 > . 2:2(0) ack 2 <nop,nop,TS val 10002 ecr 3> 33 + 34 + +0 close(3) = 0 35 + 36 + // Restart the listener 37 + +0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 38 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 39 + +0 bind(3, ..., ...) = 0 40 + +0 listen(3, 1) = 0 41 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 42 + 43 + // Test setting the key in the listen state, and produces an identical cookie 44 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN_KEY, 45 + "\xa1\xa1\xa1\xa1\xb2\xb2\xb2\xb2\xc3\xc3\xc3\xc3\xd4\xd4\xd4\xd4", 16) = 0 46 + 47 + +0 < S 6814000:6815000(1000) win 10000 <mss 1012,nop,nop,FO TFO_COOKIE,sackOK,TS val 10 ecr 0,nop,wscale 7> 48 + +0 > S. 0:0(0) ack 6815001 <mss 1460,sackOK,TS val 10000 ecr 10,nop,wscale 8> 49 + +0 accept(3, ..., ...) = 4 50 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }% 51 + +0 < . 1001:1001(0) ack 1 win 257 <nop,nop,TS val 12 ecr 10000> 52 + +0 read(4, ..., 8192) = 1000 53 + 54 + +0 close(4) = 0 55 + +0 > F. 1:1(0) ack 1001 <nop,nop,TS val 10101 ecr 12> 56 + +0 < F. 1001:1001(0) ack 2 win 257 <nop,nop,TS val 112 ecr 10101> 57 + +0 > . 2:2(0) ack 1002 <nop,nop,TS val 10102 ecr 112> 58 + 59 + +0 close(3) = 0 60 + 61 + // Restart the listener 62 + +0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 63 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 64 + +0 bind(3, ..., ...) = 0 65 + +0 listen(3, 1) = 0 66 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 67 + 68 + // Test invalid key length (must be 16 bytes) 69 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN_KEY, "", 0) = -1 (Invalid Argument) 70 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN_KEY, "", 3) = -1 (Invalid Argument) 71 + 72 + // Previous cookie won't be accepted b/c this listener uses the global key (0-0-0-0) 73 + +0 < S 6814000:6815000(1000) win 10000 <mss 1012,nop,nop,FO TFO_COOKIE,sackOK,TS val 10 ecr 0,nop,wscale 7> 74 + +0 > S. 0:0(0) ack 6814001 <mss 1460,sackOK,TS val 10000 ecr 10,nop,wscale 8,FO TFO_COOKIE_ZERO,nop,nop>
+21
tools/testing/selftests/net/packetdrill/tcp_fastopen_server_trigger-rst-listener-closed.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Close a listener socket with pending TFO child. 4 + // This will trigger RST pkt to go out. 5 + 6 + `./defaults.sh` 7 + 8 + 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 9 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 10 + +0 bind(3, ..., ...) = 0 11 + +0 listen(3, 1) = 0 12 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 13 + 14 + +0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,FO TFO_COOKIE,nop,nop> 15 + +0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK> 16 + 17 + // RST pkt is generated for each not-yet-accepted TFO child. 18 + // inet_csk_listen_stop() -> inet_child_forget() -> tcp_disconnect() 19 + // -> tcp_need_reset() is true for SYN_RECV 20 + +0 close(3) = 0 21 + +0 > R. 1:1(0) ack 11
+23
tools/testing/selftests/net/packetdrill/tcp_fastopen_server_trigger-rst-unread-data-closed.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Close a TFO socket with unread data. 4 + // This will trigger a RST pkt. 5 + 6 + `./defaults.sh` 7 + 8 + 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 9 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 10 + +0 bind(3, ..., ...) = 0 11 + +0 listen(3, 1) = 0 12 + +0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [1], 4) = 0 13 + 14 + +0 < S 0:10(10) win 32792 <mss 1460,sackOK,nop,nop,FO TFO_COOKIE,nop,nop> 15 + +0 > S. 0:0(0) ack 11 <mss 1460,nop,nop,sackOK> 16 + 17 + +0 accept(3, ..., ...) = 4 18 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }% 19 + +0 %{ assert tcpi_state == TCP_SYN_RECV, tcpi_state }% 20 + 21 + // data_was_unread == true in __tcp_close() 22 + +0 close(4) = 0 23 + +0 > R. 1:1(0) ack 11