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

selftests/net: packetdrill: import tcp/fast_recovery, tcp/nagle, tcp/timestamping

Use the standard import and testing method, as described in the
import of tcp/ecn , 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-3-sohamch.kernel@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Soham Chakradeo and committed by
Jakub Kicinski
eab35989 88395c07

+683
+72
tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-10pkt-lost-1.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Test PRR-slowstart implementation. 3 + // In this variant we test a simple case where in-flight == ssthresh 4 + // all the way through recovery, so during fast recovery we send one segment 5 + // for each segment SACKed/ACKed. 6 + 7 + // Set up config. 8 + `./defaults.sh` 9 + 10 + // Establish a connection. 11 + 0 socket(..., SOCK_STREAM, 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 + 16 + +.1 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7> 17 + +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8> 18 + // RTT 100ms 19 + +.1 < . 1:1(0) ack 1 win 320 20 + +0 accept(3, ..., ...) = 4 21 + 22 + // Send 10 data segments. 23 + +0 write(4, ..., 10000) = 10000 24 + +0 > P. 1:10001(10000) ack 1 25 + 26 + // Lost packet 1:1001. 27 + +.11 < . 1:1(0) ack 1 win 320 <sack 1001:2001,nop,nop> 28 + +.01 < . 1:1(0) ack 1 win 320 <sack 1001:3001,nop,nop> 29 + +.01 < . 1:1(0) ack 1 win 320 <sack 1001:4001,nop,nop> 30 + // Enter fast recovery. 31 + +0 > . 1:1001(1000) ack 1 32 + +.01 %{ 33 + assert tcpi_ca_state == TCP_CA_Recovery, tcpi_ca_state 34 + assert tcpi_snd_cwnd == 7, tcpi_snd_cwnd 35 + assert tcpi_snd_ssthresh == 7, tcpi_snd_ssthresh 36 + }% 37 + 38 + // Write some more, which we will send 1 MSS at a time, 39 + // as in-flight segments are SACKed or ACKed. 40 + +.01 write(4, ..., 7000) = 7000 41 + 42 + +.01 < . 1:1(0) ack 1 win 320 <sack 1001:5001,nop,nop> 43 + +0 > . 10001:11001(1000) ack 1 44 + 45 + +.01 < . 1:1(0) ack 1 win 320 <sack 1001:6001,nop,nop> 46 + +0 > . 11001:12001(1000) ack 1 47 + 48 + +.01 < . 1:1(0) ack 1 win 320 <sack 1001:7001,nop,nop> 49 + +0 > . 12001:13001(1000) ack 1 50 + 51 + +.01 < . 1:1(0) ack 1 win 320 <sack 1001:8001,nop,nop> 52 + +0 > . 13001:14001(1000) ack 1 53 + 54 + +.01 < . 1:1(0) ack 1 win 320 <sack 1001:9001,nop,nop> 55 + +0 > . 14001:15001(1000) ack 1 56 + 57 + +.01 < . 1:1(0) ack 1 win 320 <sack 1001:10001,nop,nop> 58 + +0 > . 15001:16001(1000) ack 1 59 + 60 + +.02 < . 1:1(0) ack 10001 win 320 61 + +0 > P. 16001:17001(1000) ack 1 62 + // Leave fast recovery. 63 + +.01 %{ 64 + assert tcpi_ca_state == TCP_CA_Open, tcpi_ca_state 65 + assert tcpi_snd_cwnd == 7, tcpi_snd_cwnd 66 + assert tcpi_snd_ssthresh == 7, tcpi_snd_ssthresh 67 + }% 68 + 69 + +.03 < . 1:1(0) ack 12001 win 320 70 + +.02 < . 1:1(0) ack 14001 win 320 71 + +.02 < . 1:1(0) ack 16001 win 320 72 + +.02 < . 1:1(0) ack 17001 win 320
+50
tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-30pkt-lost-1_4-11_16.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Test PRR-slowstart implementation. The sender sends 20 packets. Packet 3 + // 1 to 4, and 11 to 16 are dropped. 4 + `./defaults.sh` 5 + 6 + // Establish a connection. 7 + 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 8 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 9 + +0 bind(3, ..., ...) = 0 10 + +0 listen(3, 1) = 0 11 + 12 + +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7> 13 + +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8> 14 + 15 + +.01 < . 1:1(0) ack 1 win 320 16 + +0 accept(3, ..., ...) = 4 17 + 18 + // Write 20 data segments. 19 + +0 write(4, ..., 20000) = 20000 20 + +0 > P. 1:10001(10000) ack 1 21 + 22 + // Receive first DUPACK, entering PRR part 23 + +.01 < . 1:1(0) ack 1 win 320 <sack 4001:5001,nop,nop> 24 + +0 > . 10001:11001(1000) ack 1 25 + +.002 < . 1:1(0) ack 1 win 320 <sack 4001:6001,nop,nop> 26 + +0 > . 11001:12001(1000) ack 1 27 + +.002 < . 1:1(0) ack 1 win 320 <sack 4001:7001,nop,nop> 28 + +0 > . 1:1001(1000) ack 1 29 + +.002 < . 1:1(0) ack 1 win 320 <sack 4001:8001,nop,nop> 30 + +0 > . 1001:2001(1000) ack 1 31 + +.002 < . 1:1(0) ack 1 win 320 <sack 4001:9001,nop,nop> 32 + +0 > . 2001:3001(1000) ack 1 33 + +.002 < . 1:1(0) ack 1 win 320 <sack 4001:10001,nop,nop> 34 + +0 > . 3001:4001(1000) ack 1 35 + // Enter PRR CRB 36 + +.002 < . 1:1(0) ack 1 win 320 <sack 4001:11001,nop,nop> 37 + +0 > . 12001:13001(1000) ack 1 38 + +.002 < . 1:1(0) ack 1 win 320 <sack 4001:12001,nop,nop> 39 + +0 > . 13001:14001(1000) ack 1 40 + // Enter PRR slow start 41 + +.01 < . 1:1(0) ack 1001 win 320 <sack 4001:12001,nop,nop> 42 + +0 > P. 14001:16001(2000) ack 1 43 + +.002 < . 1:1(0) ack 1001 win 320 <sack 2001:12001,nop,nop> 44 + +0 > . 1001:2001(1000) ack 1 45 + +0 > . 16001:17001(1000) ack 1 46 + // inflight reaches ssthresh, goes into packet conservation mode 47 + +.002 < . 1:1(0) ack 1001 win 320 <sack 2001:13001,nop,nop> 48 + +0 > . 17001:18001(1000) ack 1 49 + +.002 < . 1:1(0) ack 1001 win 320 <sack 2001:14001,nop,nop> 50 + +0 > . 18001:19001(1000) ack 1
+43
tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-30pkt-lost1_4.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Test PRR-slowstart implementation. The sender sends 20 packets. Packet 3 + // 1 to 4 are lost. The sender writes another 10 packets. 4 + `./defaults.sh` 5 + 6 + // Establish a connection. 7 + 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 8 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 9 + +0 bind(3, ..., ...) = 0 10 + +0 listen(3, 1) = 0 11 + 12 + +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7> 13 + +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8> 14 + 15 + +.01 < . 1:1(0) ack 1 win 320 16 + +0 accept(3, ..., ...) = 4 17 + 18 + // Send 20 data segments. 19 + +0 write(4, ..., 10000) = 10000 20 + +0 > P. 1:10001(10000) ack 1 21 + 22 + // Lost packet 1,2,3,4 23 + +.01 < . 1:1(0) ack 1 win 320 <sack 4001:5001,nop,nop> 24 + +.002 < . 1:1(0) ack 1 win 320 <sack 4001:6001,nop,nop> 25 + +0 < . 1:1(0) ack 1 win 320 <sack 4001:7001,nop,nop> 26 + +0 > . 1:1001(1000) ack 1 27 + +0 < . 1:1(0) ack 1 win 320 <sack 4001:8001,nop,nop> 28 + +0 > . 1001:2001(1000) ack 1 29 + +0 < . 1:1(0) ack 1 win 320 <sack 4001:9001,nop,nop> 30 + +0 > . 2001:3001(1000) ack 1 31 + +0 < . 1:1(0) ack 1 win 320 <sack 4001:10001,nop,nop> 32 + +0 > . 3001:4001(1000) ack 1 33 + 34 + // Receiver ACKs all data. 35 + +.01 < . 1:1(0) ack 1001 win 320 <sack 4001:10001,nop,nop> 36 + +0 < . 1:1(0) ack 2001 win 320 <sack 4001:10001,nop,nop> 37 + +0 < . 1:1(0) ack 3001 win 320 <sack 4001:10001,nop,nop> 38 + +0 < . 1:1(0) ack 10001 win 320 39 + 40 + // Writes another 10 packets, which the ssthresh*mss amount 41 + // should be sent right away 42 + +.01 write(4, ..., 10000) = 10000 43 + +0 > . 10001:17001(7000) ack 1
+41
tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-ack-below-snd_una-cubic.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Test PRR-slowstart implementation. 3 + // In this variant we verify that the sender uses SACK info on an ACK 4 + // below snd_una. 5 + 6 + // Set up config. 7 + `./defaults.sh` 8 + 9 + // Establish a connection. 10 + 0 socket(..., SOCK_STREAM, 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:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 8> 16 + +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8> 17 + // RTT 10ms 18 + +.01 < . 1:1(0) ack 1 win 320 19 + +0 accept(3, ..., ...) = 4 20 + 21 + // Send 10 data segments. 22 + +0 write(4, ..., 10000) = 10000 23 + +0 > P. 1:10001(10000) ack 1 24 + 25 + // Lost packet 1:1001,4001:5001,7001:8001. 26 + +.01 < . 1:1(0) ack 1 win 320 <sack 1001:2001,nop,nop> 27 + +0 < . 1:1(0) ack 1 win 320 <sack 1001:3001,nop,nop> 28 + +0 < . 1:1(0) ack 1 win 320 <sack 1001:3001 8001:9001,nop,nop> 29 + +0 > . 1:1001(1000) ack 1 30 + 31 + +.012 < . 1:1(0) ack 4001 win 320 <sack 8001:9001,nop,nop> 32 + +0 > . 4001:7001(3000) ack 1 33 + 34 + +0 write(4, ..., 10000) = 10000 35 + 36 + // The following ACK was reordered - delayed so that it arrives with 37 + // an ACK field below snd_una. Here we check that the newly-SACKed 38 + // 2MSS at 5001:7001 cause us to send out 2 more MSS. 39 + +.002 < . 1:1(0) ack 3001 win 320 <sack 5001:7001,nop,nop> 40 + +0 > . 7001:8001(1000) ack 1 41 + +0 > . 10001:11001(1000) ack 1
+40
tools/testing/selftests/net/packetdrill/tcp_nagle_https_client.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // This is a test inspired by an Android client app using SSL. This 3 + // test verifies using TCP_NODELAY would save application latency 4 + // (Perhaps even better with TCP_NAGLE). 5 + // 6 + `./defaults.sh 7 + ethtool -K tun0 tso off gso off 8 + ./set_sysctls.py /proc/sys/net/ipv4/tcp_timestamps=0` 9 + 10 + 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4 11 + +0 fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0 12 + +0 setsockopt(4, SOL_TCP, TCP_NODELAY, [1], 4) = 0 13 + 14 + +0 connect(4, ..., ...) = -1 EINPROGRESS (Operation now in progress) 15 + +0 > S 0:0(0) <mss 1460,nop,nop,sackOK,nop,wscale 8> 16 + +.1 < S. 0:0(0) ack 1 win 5792 <mss 974,nop,nop,sackOK,nop,wscale 7> 17 + +0 > . 1:1(0) ack 1 18 + 19 + // SSL handshake (resumed session) 20 + +0 write(4, ..., 517) = 517 21 + +0 > P. 1:518(517) ack 1 22 + +.1 < . 1:1(0) ack 518 win 229 23 + 24 + +0 < P. 1:144(143) ack 1 win 229 25 + +0 > . 518:518(0) ack 144 26 + +0 read(4, ..., 1000) = 143 27 + 28 + // Application POST header (51B) and body (2002B) 29 + +0 write(4, ..., 51) = 51 30 + +0 > P. 518:569(51) ack 144 31 + +.03 write(4, ..., 2002) = 2002 32 + +0 > . 569:1543(974) ack 144 33 + +0 > P. 1543:2517(974) ack 144 34 + // Without disabling Nagle, this packet will not happen until the remote ACK. 35 + +0 > P. 2517:2571(54) ack 144 36 + 37 + +.1 < . 1:1(0) ack 2571 win 229 38 + 39 + // Reset sysctls 40 + `/tmp/sysctl_restore_${PPID}.sh`
+66
tools/testing/selftests/net/packetdrill/tcp_nagle_sendmsg_msg_more.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Test the MSG_MORE flag will correctly corks the tiny writes 3 + `./defaults.sh` 4 + 5 + 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 6 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 7 + +0 bind(3, ..., ...) = 0 8 + +0 listen(3, 1) = 0 9 + 10 + +0 < S 0:0(0) win 32792 <mss 1000,nop,wscale 7> 11 + +0 > S. 0:0(0) ack 1 <mss 1460,nop,wscale 8> 12 + +.01 < . 1:1(0) ack 1 win 257 13 + +0 accept(3, ..., ...) = 4 14 + // Disable Nagle by default on this socket. 15 + +0 setsockopt(4, SOL_TCP, TCP_NODELAY, [1], 4) = 0 16 + 17 + // Test the basic case: MSG_MORE overwrites TCP_NODELAY and enables Nagle. 18 + +0 sendmsg(4, {msg_name(...)=..., 19 + msg_iov(1)=[{..., 40}], msg_flags=0}, MSG_MORE) = 40 20 + +.21~+.215 > P. 1:41(40) ack 1 21 + +.01 < . 1:1(0) ack 41 win 257 22 + 23 + // Test unsetting MSG_MORE releases the packet 24 + +0 sendmsg(4, {msg_name(...)=..., 25 + msg_iov(1)=[{..., 100}], msg_flags=0}, MSG_MORE) = 100 26 + +.005 sendmsg(4, {msg_name(...)=..., 27 + msg_iov(1)=[{..., 160}], msg_flags=0}, MSG_MORE) = 160 28 + +.01 sendmsg(4, {msg_name(...)=..., 29 + msg_iov(3)=[{..., 100}, {..., 200}, {..., 195}], 30 + msg_flags=0}, MSG_MORE) = 495 31 + +.008 sendmsg(4, {msg_name(...)=..., 32 + msg_iov(1)=[{..., 5}], msg_flags=0}, 0) = 5 33 + +0 > P. 41:801(760) ack 1 34 + +.02 < . 1:1(0) ack 801 win 257 35 + 36 + 37 + // Test >MSS write will unleash MSS packets but hold on the remaining data. 38 + +.1 sendmsg(4, {msg_name(...)=..., 39 + msg_iov(1)=[{..., 3100}], msg_flags=0}, MSG_MORE) = 3100 40 + +0 > . 801:3801(3000) ack 1 41 + +.003 sendmsg(4, {msg_name(...)=..., 42 + msg_iov(1)=[{..., 50}], msg_flags=0}, MSG_MORE) = 50 43 + 44 + +.01 < . 1:1(0) ack 2801 win 257 45 + // Err... we relase the remaining right after the ACK? note that PUSH is reset 46 + +0 > . 3801:3951(150) ack 1 47 + 48 + // Test we'll hold on the subsequent writes when inflight (3801:3951) > 0 49 + +.001 sendmsg(4, {msg_name(...)=..., 50 + msg_iov(1)=[{..., 1}], msg_flags=0}, MSG_MORE) = 1 51 + +.002 sendmsg(4, {msg_name(...)=..., 52 + msg_iov(1)=[{..., 2}], msg_flags=0}, MSG_MORE) = 2 53 + +.003 sendmsg(4, {msg_name(...)=..., 54 + msg_iov(1)=[{..., 3}], msg_flags=0}, MSG_MORE) = 3 55 + +.004 sendmsg(4, {msg_name(...)=..., 56 + msg_iov(1)=[{..., 4}], msg_flags=0}, MSG_MORE) = 4 57 + +.02 < . 1:1(0) ack 3951 win 257 58 + +0 > . 3951:3961(10) ack 1 59 + +.02 < . 1:1(0) ack 3961 win 257 60 + 61 + 62 + // Test the case a MSG_MORE send followed by a write flushes the data 63 + +0 sendmsg(4, {msg_name(...)=..., 64 + msg_iov(1)=[{..., 20}], msg_flags=0}, MSG_MORE) = 20 65 + +.05 write(4, ..., 20) = 20 66 + +0 > P. 3961:4001(40) ack 1
+43
tools/testing/selftests/net/packetdrill/tcp_nagle_sockopt_cork_nodelay.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Test TCP_CORK and TCP_NODELAY sockopt behavior 3 + `./defaults.sh` 4 + 5 + 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 6 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 7 + +0 bind(3, ..., ...) = 0 8 + +0 listen(3, 1) = 0 9 + 10 + +0 < S 0:0(0) win 32792 <mss 1000,nop,wscale 7> 11 + +0 > S. 0:0(0) ack 1 <mss 1460,nop,wscale 8> 12 + +.01 < . 1:1(0) ack 1 win 257 13 + +0 accept(3, ..., ...) = 4 14 + // Set TCP_CORK sockopt to hold small packets 15 + +0 setsockopt(4, SOL_TCP, TCP_CORK, [1], 4) = 0 16 + 17 + +0 write(4, ..., 40) = 40 18 + +.05 write(4, ..., 40) = 40 19 + 20 + // Unset TCP_CORK should push pending bytes out 21 + +.01 setsockopt(4, SOL_TCP, TCP_CORK, [0], 4) = 0 22 + +0 > P. 1:81(80) ack 1 23 + +.01 < . 1:1(0) ack 81 win 257 24 + 25 + // Set TCP_CORK sockopt to hold small packets 26 + +0 setsockopt(4, SOL_TCP, TCP_CORK, [1], 4) = 0 27 + 28 + +0 write(4, ..., 40) = 40 29 + +.05 write(4, ..., 40) = 40 30 + 31 + // Set TCP_NODELAY sockopt should push pending bytes out 32 + +0 setsockopt(4, SOL_TCP, TCP_NODELAY, [1], 4) = 0 33 + +0 > P. 81:161(80) ack 1 34 + +.01 < . 1:1(0) ack 161 win 257 35 + 36 + // Set MSG_MORE to hold small packets 37 + +0 send(4, ..., 40, MSG_MORE) = 40 38 + +.05 send(4, ..., 40, MSG_MORE) = 40 39 + 40 + // Set TCP_NODELAY sockopt should push pending bytes out 41 + +.01 setsockopt(4, SOL_TCP, TCP_NODELAY, [1], 4) = 0 42 + +0 > . 161:241(80) ack 1 43 + +.01 < . 1:1(0) ack 241 win 257
+92
tools/testing/selftests/net/packetdrill/tcp_timestamping_client-only-last-byte.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Test that tx timestamping sends timestamps only for 3 + // the last byte of each sendmsg. 4 + `./defaults.sh 5 + ` 6 + 7 + // Create a socket and set it to non-blocking. 8 + 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 9 + +0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR) 10 + +0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 11 + 12 + // Establish connection and verify that there was no error. 13 + +0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress) 14 + +0 > S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8> 15 + +.01 < S. 0:0(0) ack 1 win 20000 <mss 1000,nop,nop,sackOK> 16 + +0 > . 1:1(0) ack 1 17 + +0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0 18 + +0 fcntl(3, F_SETFL, O_RDWR) = 0 // set back to blocking 19 + 20 + +0 setsockopt(3, SOL_SOCKET, SO_TIMESTAMPING, 21 + [SOF_TIMESTAMPING_TX_SCHED | SOF_TIMESTAMPING_TX_SOFTWARE | 22 + SOF_TIMESTAMPING_TX_ACK | SOF_TIMESTAMPING_SOFTWARE | 23 + SOF_TIMESTAMPING_OPT_ID], 4) = 0 24 + 25 + +0 write(3, ..., 11000) = 11000 26 + +0 > P. 1:10001(10000) ack 1 27 + +.01 < . 1:1(0) ack 10001 win 4000 28 + +0 > P. 10001:11001(1000) ack 1 29 + +.01 < . 1:1(0) ack 11001 win 4000 30 + 31 + // Make sure that internal TCP timestamps are not overwritten and we have sane 32 + // RTT measurement. 33 + +0 %{ 34 + assert 5000 <= tcpi_rtt <= 20000, 'srtt=%d us' % tcpi_rtt 35 + }% 36 + 37 + // SCM_TSTAMP_SCHED for the last byte should be received almost immediately 38 + // once 10001 is acked at t=20ms. 39 + // setsockopt(..., [SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_OPT_ID], ...) 40 + // is called after when SYN is acked. So, we expect the last byte of the first 41 + // chunk to have a timestamp key of 10999 (i.e., 11000 - 1). 42 + +0 recvmsg(3, {msg_name(...)=..., 43 + msg_iov(1)=[{...,0}], 44 + msg_flags=MSG_ERRQUEUE|MSG_TRUNC, 45 + msg_control=[ 46 + {cmsg_level=SOL_SOCKET, 47 + cmsg_type=SCM_TIMESTAMPING, 48 + cmsg_data={scm_sec=0,scm_nsec=20000000}}, 49 + {cmsg_level=CMSG_LEVEL_IP, 50 + cmsg_type=CMSG_TYPE_RECVERR, 51 + cmsg_data={ee_errno=ENOMSG, 52 + ee_origin=SO_EE_ORIGIN_TIMESTAMPING, 53 + ee_type=0, 54 + ee_code=0, 55 + ee_info=SCM_TSTAMP_SCHED, 56 + ee_data=10999}} 57 + ]}, MSG_ERRQUEUE) = 0 58 + // SCM_TSTAMP_SND for the last byte should be received almost immediately 59 + // once 10001 is acked at t=20ms. 60 + +0 recvmsg(3, {msg_name(...)=..., 61 + msg_iov(1)=[{...,0}], 62 + msg_flags=MSG_ERRQUEUE|MSG_TRUNC, 63 + msg_control=[ 64 + {cmsg_level=SOL_SOCKET, 65 + cmsg_type=SCM_TIMESTAMPING, 66 + cmsg_data={scm_sec=0,scm_nsec=20000000}}, 67 + {cmsg_level=CMSG_LEVEL_IP, 68 + cmsg_type=CMSG_TYPE_RECVERR, 69 + cmsg_data={ee_errno=ENOMSG, 70 + ee_origin=SO_EE_ORIGIN_TIMESTAMPING, 71 + ee_type=0, 72 + ee_code=0, 73 + ee_info=SCM_TSTAMP_SND, 74 + ee_data=10999}} 75 + ]}, MSG_ERRQUEUE) = 0 76 + // SCM_TSTAMP_ACK for the last byte should be received at t=30ms. 77 + +0 recvmsg(3, {msg_name(...)=..., 78 + msg_iov(1)=[{...,0}], 79 + msg_flags=MSG_ERRQUEUE|MSG_TRUNC, 80 + msg_control=[ 81 + {cmsg_level=SOL_SOCKET, 82 + cmsg_type=SCM_TIMESTAMPING, 83 + cmsg_data={scm_sec=0,scm_nsec=30000000}}, 84 + {cmsg_level=CMSG_LEVEL_IP, 85 + cmsg_type=CMSG_TYPE_RECVERR, 86 + cmsg_data={ee_errno=ENOMSG, 87 + ee_origin=SO_EE_ORIGIN_TIMESTAMPING, 88 + ee_type=0, 89 + ee_code=0, 90 + ee_info=SCM_TSTAMP_ACK, 91 + ee_data=10999}} 92 + ]}, MSG_ERRQUEUE) = 0
+91
tools/testing/selftests/net/packetdrill/tcp_timestamping_partial.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Test tx timestamping for partial writes (IPv4). 3 + `./defaults.sh 4 + ` 5 + 6 + // Create a socket and set it to non-blocking. 7 + 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 8 + +0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR) 9 + +0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 10 + 11 + // Establish connection and verify that there was no error. 12 + +0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress) 13 + +0 > S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8> 14 + +.01 < S. 0:0(0) ack 1 win 2000 <mss 1000,sackOK,TS val 700 ecr 100,nop,wscale 7> 15 + +0 > . 1:1(0) ack 1 <nop,nop,TS val 200 ecr 700> 16 + +0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0 17 + 18 + +0 setsockopt(3, SOL_SOCKET, SO_SNDBUF, [1000], 4) = 0 19 + +0 setsockopt(3, SOL_SOCKET, SO_TIMESTAMPING, 20 + [SOF_TIMESTAMPING_TX_SCHED | SOF_TIMESTAMPING_TX_SOFTWARE | 21 + SOF_TIMESTAMPING_TX_ACK | SOF_TIMESTAMPING_SOFTWARE | 22 + SOF_TIMESTAMPING_OPT_ID], 4) = 0 23 + 24 + // We have a partial write. 25 + +0 write(3, ..., 10000) = 2964 26 + +0 > . 1:989(988) ack 1 <nop,nop,TS val 110 ecr 700> 27 + +0 > P. 989:1977(988) ack 1 <nop,nop,TS val 110 ecr 700> 28 + +.01 < . 1:1(0) ack 1977 win 92 <nop,nop,TS val 800 ecr 200> 29 + +0 > P. 1977:2965(988) ack 1 <nop,nop,TS val 114 ecr 800> 30 + +.01 < . 1:1(0) ack 2965 win 92 <nop,nop,TS val 800 ecr 200> 31 + 32 + // Make sure that internal TCP timestamps are not overwritten and we have sane 33 + // RTT measurement. 34 + +0 %{ 35 + assert 5000 <= tcpi_rtt <= 20000, 'srtt=%d us' % tcpi_rtt 36 + }% 37 + 38 + // SCM_TSTAMP_SCHED for the first chunk should be received almost immediately 39 + // after the first ack at t=20ms. 40 + +0 recvmsg(3, {msg_name(...)=..., 41 + msg_iov(1)=[{...,0}], 42 + msg_flags=MSG_ERRQUEUE|MSG_TRUNC, 43 + msg_control=[ 44 + {cmsg_level=SOL_SOCKET, 45 + cmsg_type=SCM_TIMESTAMPING, 46 + cmsg_data={scm_sec=0,scm_nsec=20000000}}, 47 + {cmsg_level=CMSG_LEVEL_IP, 48 + cmsg_type=CMSG_TYPE_RECVERR, 49 + cmsg_data={ee_errno=ENOMSG, 50 + ee_origin=SO_EE_ORIGIN_TIMESTAMPING, 51 + ee_type=0, 52 + ee_code=0, 53 + ee_info=SCM_TSTAMP_SCHED, 54 + ee_data=2963}} 55 + ]}, MSG_ERRQUEUE) = 0 56 + // SCM_TSTAMP_SND for the first chunk should be received almost immediately 57 + // after the first ack at t=20ms. 58 + +0 recvmsg(3, {msg_name(...)=..., 59 + msg_iov(1)=[{...,0}], 60 + msg_flags=MSG_ERRQUEUE|MSG_TRUNC, 61 + msg_control=[ 62 + {cmsg_level=SOL_SOCKET, 63 + cmsg_type=SCM_TIMESTAMPING, 64 + cmsg_data={scm_sec=0,scm_nsec=20000000}}, 65 + {cmsg_level=CMSG_LEVEL_IP, 66 + cmsg_type=CMSG_TYPE_RECVERR, 67 + cmsg_data={ee_errno=ENOMSG, 68 + ee_origin=SO_EE_ORIGIN_TIMESTAMPING, 69 + ee_type=0, 70 + ee_code=0, 71 + ee_info=SCM_TSTAMP_SND, 72 + ee_data=2963}} 73 + ]}, MSG_ERRQUEUE) = 0 74 + // SCM_TSTAMP_ACK for the first chunk should be received after the last ack at 75 + // t=30ms. 76 + +0 recvmsg(3, {msg_name(...)=..., 77 + msg_iov(1)=[{...,0}], 78 + msg_flags=MSG_ERRQUEUE|MSG_TRUNC, 79 + msg_control=[ 80 + {cmsg_level=SOL_SOCKET, 81 + cmsg_type=SCM_TIMESTAMPING, 82 + cmsg_data={scm_sec=0,scm_nsec=30000000}}, 83 + {cmsg_level=CMSG_LEVEL_IP, 84 + cmsg_type=CMSG_TYPE_RECVERR, 85 + cmsg_data={ee_errno=ENOMSG, 86 + ee_origin=SO_EE_ORIGIN_TIMESTAMPING, 87 + ee_type=0, 88 + ee_code=0, 89 + ee_info=SCM_TSTAMP_ACK, 90 + ee_data=2963}} 91 + ]}, MSG_ERRQUEUE) = 0
+145
tools/testing/selftests/net/packetdrill/tcp_timestamping_server.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Test tx timestamping for server-side (IPv4). 3 + `./defaults.sh 4 + ` 5 + 6 + // Initialize connection 7 + 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 8 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 9 + +0 bind(3, ..., ...) = 0 10 + +0 listen(3, 1) = 0 11 + 12 + +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 10> 13 + +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8> 14 + +.01 < . 1:1(0) ack 1 win 514 15 + 16 + +0 accept(3, ..., ...) = 4 17 + +0 setsockopt(4, SOL_SOCKET, SO_TIMESTAMPING, 18 + [SOF_TIMESTAMPING_TX_SCHED | SOF_TIMESTAMPING_TX_SOFTWARE | 19 + SOF_TIMESTAMPING_TX_ACK | SOF_TIMESTAMPING_SOFTWARE | 20 + SOF_TIMESTAMPING_OPT_ID], 4) = 0 21 + 22 + // Write two 2KB chunks. 23 + // setsockopt(..., [SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_OPT_ID], ...) 24 + // is called after when SYN is acked. So, we expect the last byte of the first 25 + // and the second chunks to have timestamp keys of 1999 (i.e., 2000 - 1) and 26 + // 3999 (i.e., 4000 - 1) respectively. 27 + +0 write(4, ..., 2000) = 2000 28 + +0 write(4, ..., 2000) = 2000 29 + +0 > P. 1:2001(2000) ack 1 30 + +0 > P. 2001:4001(2000) ack 1 31 + +.01 < . 1:1(0) ack 2001 win 514 32 + +.01 < . 1:1(0) ack 4001 win 514 33 + 34 + // Make sure that internal TCP timestamps are not overwritten and we have sane 35 + // RTT measurement. 36 + +0 %{ 37 + assert 5000 <= tcpi_rtt <= 20000, 'srtt=%d us' % tcpi_rtt 38 + }% 39 + 40 + // SCM_TSTAMP_SCHED for the first chunk should be received almost immediately 41 + // after write at t=10ms. 42 + +0 recvmsg(4, {msg_name(...)=..., 43 + msg_iov(1)=[{...,0}], 44 + msg_flags=MSG_ERRQUEUE|MSG_TRUNC, 45 + msg_control=[ 46 + {cmsg_level=SOL_SOCKET, 47 + cmsg_type=SCM_TIMESTAMPING, 48 + cmsg_data={scm_sec=0,scm_nsec=10000000}}, 49 + {cmsg_level=CMSG_LEVEL_IP, 50 + cmsg_type=CMSG_TYPE_RECVERR, 51 + cmsg_data={ee_errno=ENOMSG, 52 + ee_origin=SO_EE_ORIGIN_TIMESTAMPING, 53 + ee_type=0, 54 + ee_code=0, 55 + ee_info=SCM_TSTAMP_SCHED, 56 + ee_data=1999}} 57 + ]}, MSG_ERRQUEUE) = 0 58 + // SCM_TSTAMP_SND for the first chunk should be received almost immediately 59 + // after write at t=10ms. 60 + +0 recvmsg(4, {msg_name(...)=..., 61 + msg_iov(1)=[{...,0}], 62 + msg_flags=MSG_ERRQUEUE|MSG_TRUNC, 63 + msg_control=[ 64 + {cmsg_level=SOL_SOCKET, 65 + cmsg_type=SCM_TIMESTAMPING, 66 + cmsg_data={scm_sec=0,scm_nsec=10000000}}, 67 + {cmsg_level=CMSG_LEVEL_IP, 68 + cmsg_type=CMSG_TYPE_RECVERR, 69 + cmsg_data={ee_errno=ENOMSG, 70 + ee_origin=SO_EE_ORIGIN_TIMESTAMPING, 71 + ee_type=0, 72 + ee_code=0, 73 + ee_info=SCM_TSTAMP_SND, 74 + ee_data=1999}} 75 + ]}, MSG_ERRQUEUE) = 0 76 + // SCM_TSTAMP_SCHED for the second chunk should be received almost immediately 77 + // after that at t=10ms. 78 + +0 recvmsg(4, {msg_name(...)=..., 79 + msg_iov(1)=[{...,0}], 80 + msg_flags=MSG_ERRQUEUE|MSG_TRUNC, 81 + msg_control=[ 82 + {cmsg_level=SOL_SOCKET, 83 + cmsg_type=SCM_TIMESTAMPING, 84 + cmsg_data={scm_sec=0,scm_nsec=10000000}}, 85 + {cmsg_level=CMSG_LEVEL_IP, 86 + cmsg_type=CMSG_TYPE_RECVERR, 87 + cmsg_data={ee_errno=ENOMSG, 88 + ee_origin=SO_EE_ORIGIN_TIMESTAMPING, 89 + ee_type=0, 90 + ee_code=0, 91 + ee_info=SCM_TSTAMP_SCHED, 92 + ee_data=3999}} 93 + ]}, MSG_ERRQUEUE) = 0 94 + // SCM_TSTAMP_SND for the second chunk should be received almost immediately 95 + // after that at t=10ms. 96 + +0 recvmsg(4, {msg_name(...)=..., 97 + msg_iov(1)=[{...,0}], 98 + msg_flags=MSG_ERRQUEUE|MSG_TRUNC, 99 + msg_control=[ 100 + {cmsg_level=SOL_SOCKET, 101 + cmsg_type=SCM_TIMESTAMPING, 102 + cmsg_data={scm_sec=0,scm_nsec=10000000}}, 103 + {cmsg_level=CMSG_LEVEL_IP, 104 + cmsg_type=CMSG_TYPE_RECVERR, 105 + cmsg_data={ee_errno=ENOMSG, 106 + ee_origin=SO_EE_ORIGIN_TIMESTAMPING, 107 + ee_type=0, 108 + ee_code=0, 109 + ee_info=SCM_TSTAMP_SND, 110 + ee_data=3999}} 111 + ]}, MSG_ERRQUEUE) = 0 112 + // SCM_TSTAMP_ACK for the first chunk should be received at t=20ms. 113 + +0 recvmsg(4, {msg_name(...)=..., 114 + msg_iov(1)=[{...,0}], 115 + msg_flags=MSG_ERRQUEUE|MSG_TRUNC, 116 + msg_control=[ 117 + {cmsg_level=SOL_SOCKET, 118 + cmsg_type=SCM_TIMESTAMPING, 119 + cmsg_data={scm_sec=0,scm_nsec=20000000}}, 120 + {cmsg_level=CMSG_LEVEL_IP, 121 + cmsg_type=CMSG_TYPE_RECVERR, 122 + cmsg_data={ee_errno=ENOMSG, 123 + ee_origin=SO_EE_ORIGIN_TIMESTAMPING, 124 + ee_type=0, 125 + ee_code=0, 126 + ee_info=SCM_TSTAMP_ACK, 127 + ee_data=1999}} 128 + ]}, MSG_ERRQUEUE) = 0 129 + // SCM_TSTAMP_ACK for the second chunk should be received at t=30ms. 130 + +0 recvmsg(4, {msg_name(...)=..., 131 + msg_iov(1)=[{...,0}], 132 + msg_flags=MSG_ERRQUEUE|MSG_TRUNC, 133 + msg_control=[ 134 + {cmsg_level=SOL_SOCKET, 135 + cmsg_type=SCM_TIMESTAMPING, 136 + cmsg_data={scm_sec=0,scm_nsec=30000000}}, 137 + {cmsg_level=CMSG_LEVEL_IP, 138 + cmsg_type=CMSG_TYPE_RECVERR, 139 + cmsg_data={ee_errno=ENOMSG, 140 + ee_origin=SO_EE_ORIGIN_TIMESTAMPING, 141 + ee_type=0, 142 + ee_code=0, 143 + ee_info=SCM_TSTAMP_ACK, 144 + ee_data=3999}} 145 + ]}, MSG_ERRQUEUE) = 0