selftests/net: packetdrill: import tcp/user_timeout, tcp/validate, tcp/sendfile, tcp/limited-transmit, tcp/syscall_bad_arg

Use the standard import and testing method, as described in the
import of tcp/ecn and tcp/close , tcp/sack , tcp/tcp_info.

Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Soham Chakradeo <sohamch@google.com>
Link: https://patch.msgid.link/20241217185203.297935-5-sohamch.kernel@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Soham Chakradeo 2024-12-17 18:52:01 +00:00 committed by Jakub Kicinski
parent 6f66920539
commit 5d4cadef52
9 changed files with 319 additions and 0 deletions

View File

@ -0,0 +1,53 @@
// SPDX-License-Identifier: GPL-2.0
// Test RFC 3042 "Limited Transmit": "sending a new data segment in
// response to each of the first two duplicate acknowledgments that
// arrive at the sender".
// This variation tests a receiver that doesn't support SACK.
`./defaults.sh`
// Establish a connection.
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 32792 <mss 1000,nop,wscale 7>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,wscale 8>
+.1 < . 1:1(0) ack 1 win 320
+0 accept(3, ..., ...) = 4
// Write some data, and send the initial congestion window.
+0 write(4, ..., 15000) = 15000
+0 > P. 1:10001(10000) ack 1
// Limited transmit: on first dupack, send a new data segment.
+.11 < . 1:1(0) ack 1 win 320
+0 > . 10001:11001(1000) ack 1
// Limited transmit: on second dupack, send a new data segment.
+.01 < . 1:1(0) ack 1 win 320
+0 > . 11001:12001(1000) ack 1
// It turned out to be reordering, not loss.
// We have one packet newly acked (1001:3001 were DUP-ACK'd)
// So we revert state back to Open. Slow start cwnd from 10 to 11
// and send 11 - 9 = 2 packets
+.01 < . 1:1(0) ack 3001 win 320
+0 > P. 12001:14001(2000) ack 1
+.02 < . 1:1(0) ack 5001 win 320
+0 > P. 14001:15001(1000) ack 1
// Client gradually ACKs all data.
+.02 < . 1:1(0) ack 7001 win 320
+.02 < . 1:1(0) ack 9001 win 320
+.02 < . 1:1(0) ack 11001 win 320
+.02 < . 1:1(0) ack 13001 win 320
+.02 < . 1:1(0) ack 15001 win 320
// Clean up.
+.17 close(4) = 0
+0 > F. 15001:15001(0) ack 1
+.1 < F. 1:1(0) ack 15002 win 257
+0 > . 15002:15002(0) ack 2

View File

@ -0,0 +1,50 @@
// SPDX-License-Identifier: GPL-2.0
// Test RFC 3042 "Limited Transmit": "sending a new data segment in
// response to each of the first two duplicate acknowledgments that
// arrive at the sender".
// This variation tests a receiver that supports SACK.
`./defaults.sh`
// Establish a connection.
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 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
// Write some data, and send the initial congestion window.
+0 write(4, ..., 15000) = 15000
+0 > P. 1:10001(10000) ack 1
// Limited transmit: on first dupack, send a new data segment.
+.11 < . 1:1(0) ack 1 win 320 <sack 1001:2001,nop,nop>
+0 > . 10001:11001(1000) ack 1
// Limited transmit: on second dupack, send a new data segment.
+.01 < . 1:1(0) ack 1 win 320 <sack 1001:3001,nop,nop>
+0 > . 11001:12001(1000) ack 1
// It turned out to be reordering, not loss.
+.01 < . 1:1(0) ack 3001 win 320
+0 > P. 12001:14001(2000) ack 1
+.02 < . 1:1(0) ack 5001 win 320
+0 > P. 14001:15001(1000) ack 1
// Client gradually ACKs all data.
+.02 < . 1:1(0) ack 7001 win 320
+.02 < . 1:1(0) ack 9001 win 320
+.02 < . 1:1(0) ack 11001 win 320
+.02 < . 1:1(0) ack 13001 win 320
+.02 < . 1:1(0) ack 15001 win 320
// Clean up.
+.17 close(4) = 0
+0 > F. 15001:15001(0) ack 1
+.1 < F. 1:1(0) ack 15002 win 257
+0 > . 15002:15002(0) ack 2

View File

@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-2.0
// Simplest possible test of open() and then sendfile().
// We write some zeroes into a file (since packetdrill expects payloads
// to be all zeroes) and then open() the file, then use sendfile()
// and verify that the correct number of zeroes goes out.
`./defaults.sh
/bin/rm -f /tmp/testfile
/bin/dd bs=1 count=5 if=/dev/zero of=/tmp/testfile status=none
`
// Initialize connection
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
+0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 10>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+0 < . 1:1(0) ack 1 win 514
+0 accept(3, ..., ...) = 4
+0 open("/tmp/testfile", O_RDONLY) = 5
+0 sendfile(4, 5, [0], 5) = 5
+0 > P. 1:6(5) ack 1

View File

@ -0,0 +1,42 @@
// SPDX-License-Identifier: GPL-2.0
// Test TCP fastopen behavior with NULL as buffer pointer, but a non-zero
// buffer length.
`./defaults.sh
./set_sysctls.py /proc/sys/net/ipv4/tcp_timestamps=0`
// Cache warmup: send a Fast Open cookie request
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+0 setsockopt(3, SOL_TCP, TCP_FASTOPEN_CONNECT, [1], 4) = 0
+0 connect(3, ..., ...) = -1 EINPROGRESS (Operation is now in progress)
+0 > S 0:0(0) <mss 1460,nop,nop,sackOK,nop,wscale 8,FO,nop,nop>
+0 < S. 123:123(0) ack 1 win 14600 <mss 1460,nop,nop,sackOK,nop,wscale 6,FO abcd1234,nop,nop>
+0 > . 1:1(0) ack 1
+0 close(3) = 0
+0 > F. 1:1(0) ack 1
+0 < F. 1:1(0) ack 2 win 92
+0 > . 2:2(0) ack 2
// Test with MSG_FASTOPEN without TCP_FASTOPEN_CONNECT.
+0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+0 fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+0 sendto(4, NULL, 1, MSG_FASTOPEN, ..., ...) = -1
+0 close(4) = 0
// Test with TCP_FASTOPEN_CONNECT without MSG_FASTOPEN.
+0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 5
+0 fcntl(5, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+0 setsockopt(5, SOL_TCP, TCP_FASTOPEN_CONNECT, [1], 4) = 0
+0 connect(5, ..., ...) = 0
+0 sendto(5, NULL, 1, 0, ..., ...) = -1
+0 close(5) = 0
// Test with both TCP_FASTOPEN_CONNECT and MSG_FASTOPEN.
+0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 6
+0 fcntl(6, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+0 setsockopt(6, SOL_TCP, TCP_FASTOPEN_CONNECT, [1], 4) = 0
+0 connect(6, ..., ...) = 0
+0 sendto(6, NULL, 1, MSG_FASTOPEN, ..., ...) = -1
+0 close(6) = 0
`/tmp/sysctl_restore_${PPID}.sh`

View File

@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-2.0
// Test that we correctly skip zero-length IOVs.
`./defaults.sh`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_ZEROCOPY, [1], 4) = 0
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < S 0:0(0) win 32792 <mss 1000,nop,wscale 7>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,wscale 8>
+.01 < . 1:1(0) ack 1 win 257
+0 accept(3, ..., ...) = 4
+0 setsockopt(4, SOL_TCP, TCP_NODELAY, [1], 4) = 0
+0 sendmsg(4, {msg_name(...)=...,
msg_iov(4)=[{..., 0}, {..., 40}, {..., 0}, {..., 20}],
msg_flags=0}, 0) = 60
+0 > P. 1:61(60) ack 1
+.01 < . 1:1(0) ack 61 win 257
+0 sendmsg(4, {msg_name(...)=...,
msg_iov(4)=[{..., 0}, {..., 0}, {..., 0}, {..., 0}],
msg_flags=0}, MSG_ZEROCOPY) = 0
+0 sendmsg(4, {msg_name(...)=...,
msg_iov(4)=[{..., 0}, {..., 10}, {..., 0}, {..., 50}],
msg_flags=0}, MSG_ZEROCOPY) = 60
+0 > P. 61:121(60) ack 1
+.01 < . 1:1(0) ack 121 win 257

View File

@ -0,0 +1,25 @@
// SPDX-License-Identifier: GPL-2.0
// Test kernel behavior with NULL as buffer pointer
`./defaults.sh`
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 10>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.2 < . 1:1(0) ack 1 win 514
+0 accept(3, ..., ...) = 4
+0 write(4, NULL, 1000) = -1 EFAULT (Bad address)
+0 send(4, NULL, 1000, 0) = -1 EFAULT (Bad address)
+0 sendto(4, NULL, 1000, 0, ..., ...) = -1 EFAULT (Bad address)
+0 < . 1:1001(1000) ack 1 win 200
+0 read(4, NULL, 1000) = -1 EFAULT (Bad address)
+0 recv(4, NULL, 1000, 0) = -1 EFAULT (Bad address)
+0 recvfrom(4, NULL, 1000, 0, ..., ...) = -1 EFAULT (Bad address)

View File

@ -0,0 +1,37 @@
// SPDX-License-Identifier: GPL-2.0
`./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
+0 < S 0:0(0) win 0 <mss 1460>
+0 > S. 0:0(0) ack 1 <mss 1460>
+.1 < . 1:1(0) ack 1 win 65530
+0 accept(3, ..., ...) = 4
+0 setsockopt(4, SOL_TCP, TCP_USER_TIMEOUT, [3000], 4) = 0
+0 write(4, ..., 24) = 24
+0 > P. 1:25(24) ack 1
+.1 < . 1:1(0) ack 25 win 65530
+0 %{ assert tcpi_probes == 0, tcpi_probes; \
assert tcpi_backoff == 0, tcpi_backoff }%
// install a qdisc dropping all packets
+0 `tc qdisc delete dev tun0 root 2>/dev/null ; tc qdisc add dev tun0 root pfifo limit 0`
+0 write(4, ..., 24) = 24
// When qdisc is congested we retry every 500ms
// (TCP_RESOURCE_PROBE_INTERVAL) and therefore
// we retry 6 times before hitting 3s timeout.
// First verify that the connection is alive:
+3.250 write(4, ..., 24) = 24
// Now verify that shortly after that the socket is dead:
+.100 write(4, ..., 24) = -1 ETIMEDOUT (Connection timed out)
+0 %{ assert tcpi_probes == 6, tcpi_probes; \
assert tcpi_backoff == 0, tcpi_backoff }%
+0 close(4) = 0

View File

@ -0,0 +1,32 @@
// SPDX-License-Identifier: GPL-2.0
`./defaults.sh`
// Initialize connection
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
+0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK>
+.1 < . 1:1(0) ack 1 win 32792
+0 accept(3, ..., ...) = 4
// Okay, we received nothing, and decide to close this idle socket.
// We set TCP_USER_TIMEOUT to 3 seconds because really it is not worth
// trying hard to cleanly close this flow, at the price of keeping
// a TCP structure in kernel for about 1 minute !
+2 setsockopt(4, SOL_TCP, TCP_USER_TIMEOUT, [3000], 4) = 0
+0 close(4) = 0
+0 > F. 1:1(0) ack 1
+.3~+.400 > F. 1:1(0) ack 1
+.3~+.400 > F. 1:1(0) ack 1
+.6~+.800 > F. 1:1(0) ack 1
// We finally receive something from the peer, but it is way too late
// Our socket vanished because TCP_USER_TIMEOUT was really small
+0 < . 1:2(1) ack 1 win 32792
+0 > R 1:1(0)

View File

@ -0,0 +1,24 @@
// SPDX-License-Identifier: GPL-2.0
// Verify that established connections drop a segment without the ACK flag set.
`./defaults.sh`
// Create a socket.
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
// Establish a connection.
+0 < S 0:0(0) win 20000 <mss 1000,sackOK,nop,nop>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK>
+.01 < . 1:1(0) ack 1 win 20000
+0 accept(3, ..., ...) = 4
// Receive a segment with no flags set, verify that it's not enqueued.
+.01 < - 1:1001(1000) win 20000
+0 ioctl(4, SIOCINQ, [0]) = 0
// Receive a segment with ACK flag set, verify that it is enqueued.
+.01 < . 1:1001(1000) ack 1 win 20000
+0 ioctl(4, SIOCINQ, [1000]) = 0