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

selftests/net: packetdrill: import tcp/ecn, tcp/close, tcp/sack, tcp/tcp_info

Same as initial tests, import verbatim from
github.com/google/packetdrill, aside from:

- update `source ./defaults.sh` path to adjust for flat dir
- add SPDX headers
- remove author statements if any
- drop blank lines at EOF

Same test process as previous tests. Both with and without debug mode.
Recording the steps once:

make mrproper
vng --build \
--config tools/testing/selftests/net/packetdrill/config \
--config kernel/configs/debug.config
vng -v --run . --user root --cpus 4 -- \
make -C tools/testing/selftests TARGETS=net/packetdrill run_tests

Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Soham Chakradeo <sohamch@google.com>
Link: https://patch.msgid.link/20241217185203.297935-2-sohamch.kernel@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Soham Chakradeo and committed by
Jakub Kicinski
88395c07 c1bad69f

+442
+23
tools/testing/selftests/net/packetdrill/tcp_close_close-local-close-then-remote-fin.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Test basic connection teardown where local process closes first: 3 + // the local process calls close() first, so we send a FIN, and receive an ACK. 4 + // Then we receive a FIN and ACK it. 5 + 6 + `./defaults.sh` 7 + 8 + 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 9 + +.01...0.011 connect(3, ..., ...) = 0 10 + +0 > S 0:0(0) <...> 11 + +0 < S. 0:0(0) ack 1 win 32768 <mss 1000,nop,wscale 6,nop,nop,sackOK> 12 + +0 > . 1:1(0) ack 1 13 + 14 + +0 write(3, ..., 1000) = 1000 15 + +0 > P. 1:1001(1000) ack 1 16 + +0 < . 1:1(0) ack 1001 win 257 17 + 18 + +0 close(3) = 0 19 + +0 > F. 1001:1001(0) ack 1 20 + +0 < . 1:1(0) ack 1002 win 257 21 + 22 + +0 < F. 1:1(0) ack 1002 win 257 23 + +0 > . 1002:1002(0) ack 2
+21
tools/testing/selftests/net/packetdrill/tcp_close_close-on-syn-sent.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Test to make sure no RST is being sent when close() 3 + // is called on a socket with SYN_SENT state. 4 + 5 + `./defaults.sh` 6 + 7 + 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 8 + +0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 9 + 10 + +0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress) 11 + +0 > S 0:0(0) <...> 12 + 13 + // Application decideds to close the socket in SYN_SENT state 14 + // Make sure no RST is sent after close(). 15 + +0 close(3) = 0 16 + 17 + // Receive syn-ack to trigger the send side packet examination: 18 + // If a RESET were sent right after close(), it would have failed with 19 + // a mismatched timestamp. 20 + +.1 < S. 0:0(0) ack 1 win 32000 <mss 1460,nop,wscale 7> 21 + +0 > R 1:1(0)
+36
tools/testing/selftests/net/packetdrill/tcp_close_close-remote-fin-then-close.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Verify behavior for the sequence: remote side sends FIN, then we close(). 3 + // Since the remote side (client) closes first, we test our LAST_ACK code path. 4 + 5 + `./defaults.sh` 6 + 7 + // Initialize a server socket. 8 + 0 socket(..., SOCK_STREAM, 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 + 13 + +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7> 14 + +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8> 15 + +0 < . 1:1(0) ack 1 win 257 16 + 17 + +0 accept(3, ..., ...) = 4 18 + 19 + // Client closes first. 20 + +.01 < F. 1:1(0) ack 1 win 257 21 + +0 > . 1:1(0) ack 2 22 + 23 + // App notices that client closed. 24 + +0 read(4, ..., 1000) = 0 25 + 26 + // Then we close. 27 + +.01 close(4) = 0 28 + +0 > F. 1:1(0) ack 2 29 + 30 + // Client ACKs our FIN. 31 + +.01 < . 2:2(0) ack 2 win 257 32 + 33 + // Verify that we send RST in response to any incoming segments 34 + // (because the kernel no longer has any record of this socket). 35 + +.01 < . 2:2(0) ack 2 win 257 36 + +0 > R 2:2(0)
+21
tools/testing/selftests/net/packetdrill/tcp_ecn_ecn-uses-ect0.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Test ECN: verify that Linux TCP ECN sending code uses ECT0 (not ECT1). 3 + // 4 + `./defaults.sh 5 + sysctl -q net.ipv4.tcp_ecn=1 # fully enabled 6 + ` 7 + 8 + // Initialize connection 9 + 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4 10 + 11 + // ECN handshake: send EW flags in SYN packet, E flag in SYN-ACK response 12 + +.002 ... 0.004 connect(4, ..., ...) = 0 13 + 14 + +0 > SEW 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8> 15 + +.002 < SE. 0:0(0) ack 1 win 32767 <mss 1000,nop,wscale 6,nop,nop,sackOK> 16 + +0 > . 1:1(0) ack 1 17 + 18 + // Write 1 MSS. 19 + +.002 write(4, ..., 1000) = 1000 20 + // Send 1 MSS with ect0. 21 + +0 > [ect0] P. 1:1001(1000) ack 1
+37
tools/testing/selftests/net/packetdrill/tcp_sack_sack-route-refresh-ip-tos.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Verify that setsockopt calls that force a route refresh do not 3 + // cause problems matching SACKs with packets in the write queue. 4 + // This variant tests IP_TOS. 5 + 6 + `./defaults.sh` 7 + 8 + // Establish a connection. 9 + 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 10 + +0 setsockopt(3, SOL_IP, IP_MTU_DISCOVER, [IP_PMTUDISC_DONT], 1) = 0 11 + +0...0.010 connect(3, ..., ...) = 0 12 + 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 65535 <mss 1460,nop,wscale 2,nop,nop,sackOK> 15 + +0 > . 1:1(0) ack 1 16 + 17 + +.01 write(3, ..., 5840) = 5840 18 + +0 > P. 1:5841(5840) ack 1 19 + +.01 < . 1:1(0) ack 5841 win 65535 20 + 21 + +.01 write(3, ..., 5840) = 5840 22 + +0 > P. 5841:11681(5840) ack 1 23 + +.01 < . 1:1(0) ack 11681 win 65535 24 + 25 + +.01 write(3, ..., 14600) = 14600 26 + +0 > P. 11681:26281(14600) ack 1 27 + 28 + // Try the socket option that we know can force a route refresh. 29 + +0 setsockopt(3, SOL_IP, IP_TOS, [4], 1) = 0 30 + // Then revert to avoid routing/mangling/etc implications of that setting. 31 + +0 setsockopt(3, SOL_IP, IP_TOS, [0], 1) = 0 32 + 33 + // Verify that we do not retransmit the SACKed segments. 34 + +.01 < . 1:1(0) ack 13141 win 65535 <sack 16061:17521 20441:26281,nop,nop> 35 + +0 > . 13141:16061(2920) ack 1 36 + +0 > P. 17521:20441(2920) ack 1 37 + +.01 < . 1:1(0) ack 26281 win 65535
+64
tools/testing/selftests/net/packetdrill/tcp_sack_sack-shift-sacked-2-6-8-3-9-nofack.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Test shifting of newly-SACKed ranges onto the previous already-SACKed skb. 3 + // This variant tests non-FACK SACK with SACKs coming in the order 4 + // 2 6 8 3 9, to test what happens when we get a new SACKed range 5 + // (for packet 3) that is on the right of an existing SACKed range 6 + // (for packet 2). 7 + 8 + `./defaults.sh` 9 + 10 + // Establish a connection and send 10 MSS. 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 + +0 < 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 + +.1 < . 1:1(0) ack 1 win 1024 19 + +0 accept(3, ..., ...) = 4 20 + 21 + +0 write(4, ..., 10000) = 10000 22 + +0 > P. 1:10001(10000) ack 1 23 + 24 + +.1 < . 1:1(0) ack 1 win 257 <sack 2001:3001,nop,nop> 25 + +.001 < . 1:1(0) ack 1 win 257 <sack 2001:3001 6001:7001,nop,nop> 26 + +.001 < . 1:1(0) ack 1 win 257 <sack 2001:3001 6001:7001 8001:9001,nop,nop> 27 + 28 + // 3 SACKed packets, so we enter Fast Recovery. 29 + +0 > . 1:1001(1000) ack 1 30 + +0 %{ assert tcpi_ca_state == TCP_CA_Recovery, tcpi_ca_state }% 31 + +0 %{ assert tcpi_lost == 6, tcpi_lost }% 32 + 33 + // SACK for 3001:4001. 34 + // This SACK for an adjacent range causes the sender to 35 + // shift the newly-SACKed range onto the previous skb. 36 + +.007 < . 1:1(0) ack 1 win 257 <sack 2001:4001 6001:7001 8001:9001,nop,nop> 37 + +0 > . 1001:2001(1000) ack 1 38 + +0 %{ assert tcpi_lost == 5, tcpi_lost }% 39 + +0 %{ assert tcpi_reordering == 6, tcpi_reordering }% // 8001:9001 -> 3001:4001 is 6 40 + 41 + // SACK for 9001:10001. 42 + +.01 < . 1:1(0) ack 1 win 257 <sack 2001:4001 6001:7001 8001:10001,nop,nop> 43 + +0 %{ assert tcpi_lost == 5, tcpi_lost }% 44 + 45 + // ACK for 1:1001 as packets from t=0.303 arrive. 46 + +.083 < . 1:1(0) ack 1001 win 257 <sack 2001:4001 6001:7001 8001:10001,nop,nop> 47 + +0 %{ assert tcpi_lost == 4,tcpi_lost }% 48 + 49 + // ACK for 1:4001 as packets from t=0.310 arrive. 50 + +.017 < . 1:1(0) ack 4001 win 257 <sack 6001:7001 8001:10001,nop,nop> 51 + +0 %{ assert tcpi_lost == 3,tcpi_lost }% 52 + 53 + // ACK for 1:7001 as packets from t=0.320 arrive. 54 + +.01 < . 1:1(0) ack 7001 win 257 <sack 8001:10001,nop,nop> 55 + 56 + // ACK for all data as packets from t=0.403 arrive. 57 + +.1 < . 1:1(0) ack 10001 win 257 58 + +0 %{ 59 + assert tcpi_ca_state == TCP_CA_Open, tcpi_ca_state 60 + assert tcpi_unacked == 0, tcpi_unacked 61 + assert tcpi_sacked == 0, tcpi_sacked 62 + assert tcpi_lost == 0, tcpi_lost 63 + assert tcpi_retrans == 0, tcpi_retrans 64 + }%
+66
tools/testing/selftests/net/packetdrill/tcp_sack_sack-shift-sacked-7-3-4-8-9-fack.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Test shifting of newly-SACKed ranges onto the previous already-SACKed skb. 3 + // This variant tests the case where we mark packets 0-4 lost, then 4 + // get a SACK for 3, and then a SACK for 4. 5 + 6 + `./defaults.sh` 7 + 8 + // Establish a connection and send 10 MSS. 9 + 0 socket(..., SOCK_STREAM, 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:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7> 15 + +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8> 16 + +.1 < . 1:1(0) ack 1 win 1024 17 + +0 accept(3, ..., ...) = 4 18 + 19 + +0 write(4, ..., 10000) = 10000 20 + +0 > P. 1:10001(10000) ack 1 21 + 22 + // SACK for 7001:8001. Using RACK we delay the fast retransmit. 23 + +.1 < . 1:1(0) ack 1 win 257 <sack 7001:8001,nop,nop> 24 + // RACK reordering timer 25 + +.027 > . 1:1001(1000) ack 1 26 + +0 %{ 27 + assert tcpi_ca_state == TCP_CA_Recovery, tcpi_ca_state 28 + assert tcpi_lost == 7, tcpi_lost # RACK thinks 1:7001 are lost 29 + assert tcpi_reordering == 3, tcpi_reordering 30 + }% 31 + 32 + // SACK for 3001:4001. 33 + +.002 < . 1:1(0) ack 1 win 257 <sack 3001:4001 7001:8001,nop,nop> 34 + +0 > . 1001:2001(1000) ack 1 35 + +0 %{ 36 + assert tcpi_lost == 6, tcpi_lost # since 3001:4001 is no longer lost 37 + assert tcpi_reordering == 5, tcpi_reordering # 7001:8001 -> 3001:4001 38 + }% 39 + 40 + // SACK for 4001:5001. 41 + // This SACK for an adjacent range causes the sender to 42 + // shift the newly-SACKed range onto the previous skb. 43 + // It uses the RFC3517 algorithm to mark 1:3001 lost 44 + // because >=3 higher-sequence packets are SACKed. 45 + +.002 < . 1:1(0) ack 1 win 257 <sack 3001:5001 7001:8001,nop,nop> 46 + +0 > . 2001:3001(1000) ack 1 47 + +0 %{ 48 + assert tcpi_lost == 5,tcpi_lost # SACK/RFC3517 thinks 1:3001 are lost 49 + }% 50 + 51 + // SACK for 8001:9001. 52 + +.002 < . 1:1(0) ack 1 win 257 <sack 3001:5001 7001:9001,nop,nop> 53 + 54 + // SACK for 9001:10001. 55 + +.002 < . 1:1(0) ack 1 win 257 <sack 3001:5001 7001:10001,nop,nop> 56 + +0 > . 5001:6001(1000) ack 1 57 + 58 + // To simplify clean-up, say we get an ACK for all data. 59 + +.1 < . 1:1(0) ack 10001 win 257 60 + +0 %{ 61 + assert tcpi_ca_state == TCP_CA_Open, tcpi_ca_state 62 + assert tcpi_unacked == 0, tcpi_unacked 63 + assert tcpi_sacked == 0, tcpi_sacked 64 + assert tcpi_lost == 0, tcpi_lost 65 + assert tcpi_retrans == 0, tcpi_retrans 66 + }%
+62
tools/testing/selftests/net/packetdrill/tcp_sack_sack-shift-sacked-7-5-6-8-9-fack.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Test shifting of newly-SACKed ranges onto the previous already-SACKed skb. 3 + // This variant tests the case where we mark packets 0-4 lost, then 4 + // get a SACK for 5, and then a SACK for 6. 5 + 6 + `./defaults.sh` 7 + 8 + // Establish a connection and send 10 MSS. 9 + 0 socket(..., SOCK_STREAM, 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:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7> 15 + +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8> 16 + +.1 < . 1:1(0) ack 1 win 1024 17 + +0 accept(3, ..., ...) = 4 18 + 19 + +0 write(4, ..., 10000) = 10000 20 + +0 > P. 1:10001(10000) ack 1 21 + 22 + // SACK for 7001:8001. Using RACK we delay a fast retransmit. 23 + +.1 < . 1:1(0) ack 1 win 257 <sack 7001:8001,nop,nop> 24 + +.027 > . 1:1001(1000) ack 1 25 + +0 %{ 26 + assert tcpi_ca_state == TCP_CA_Recovery, tcpi_ca_state 27 + assert tcpi_lost == 7,tcpi_lost # RACK thinks 1:7001 are lost 28 + assert tcpi_reordering == 3, tcpi_reordering 29 + }% 30 + 31 + // SACK for 5001:6001. 32 + +0 < . 1:1(0) ack 1 win 257 <sack 5001:6001 7001:8001,nop,nop> 33 + +0 > . 1001:2001(1000) ack 1 34 + +0 %{ 35 + assert tcpi_lost == 6, tcpi_lost 36 + assert tcpi_reordering == 3, tcpi_reordering # 7001:8001 -> 5001:6001 is 3 37 + }% 38 + 39 + // SACK for 6001:7001. 40 + // This SACK for an adjacent range causes the sender to 41 + // shift the newly-SACKed range onto the previous skb. 42 + +0 < . 1:1(0) ack 1 win 257 <sack 5001:8001,nop,nop> 43 + +0 > . 2001:3001(1000) ack 1 44 + +0 %{ assert tcpi_lost == 5, tcpi_lost }% 45 + 46 + // SACK for 8001:9001. 47 + +0 < . 1:1(0) ack 1 win 257 <sack 5001:9001,nop,nop> 48 + +0 > . 3001:4001(1000) ack 1 49 + 50 + // SACK for 9001:10001. 51 + +0 < . 1:1(0) ack 1 win 257 <sack 5001:10001,nop,nop> 52 + +0 > . 4001:5001(1000) ack 1 53 + 54 + // To simplify clean-up, say we get an ACK for all data. 55 + +.1 < . 1:1(0) ack 10001 win 257 56 + +0 %{ 57 + assert tcpi_ca_state == TCP_CA_Open, tcpi_ca_state 58 + assert tcpi_unacked == 0, tcpi_unacked 59 + assert tcpi_sacked == 0, tcpi_sacked 60 + assert tcpi_lost == 0, tcpi_lost 61 + assert tcpi_retrans == 0, tcpi_retrans 62 + }%
+20
tools/testing/selftests/net/packetdrill/tcp_tcp_info_tcp-info-last_data_recv.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Test tcpi_last_data_recv for active session 3 + `./defaults.sh` 4 + 5 + // Create a socket and set it to non-blocking. 6 + +0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 7 + +0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR) 8 + +0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 9 + 10 + +0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress) 11 + +0 > S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8> 12 + +.030 < S. 0:0(0) ack 1 win 10000 <mss 1000,sackOK,nop,nop,nop,wscale 8> 13 + +0 > . 1:1(0) ack 1 14 + 15 + +1 %{ assert 990 <= tcpi_last_data_recv <= 1010, tcpi_last_data_recv }% 16 + 17 + +0 < . 1:1001(1000) ack 1 win 300 18 + +0 > . 1:1(0) ack 1001 19 + 20 + +0 %{ assert tcpi_last_data_recv <= 10, tcpi_last_data_recv }%
+54
tools/testing/selftests/net/packetdrill/tcp_tcp_info_tcp-info-rwnd-limited.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Test rwnd limited time in tcp_info for client side. 3 + 4 + `./defaults.sh` 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 + +0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress) 12 + +0 > S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8> 13 + 14 + // Server advertises 0 receive window. 15 + +.01 < S. 0:0(0) ack 1 win 0 <mss 1000,nop,nop,sackOK> 16 + 17 + +0 > . 1:1(0) ack 1 18 + +0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0 19 + +0 fcntl(3, F_SETFL, O_RDWR) = 0 // set back to blocking 20 + 21 + // Make sure that initial rwnd limited time is 0. 22 + +0 %{ assert tcpi_rwnd_limited == 0, tcpi_rwnd_limited }% 23 + 24 + // Receive window limited time starts here. 25 + +0 write(3, ..., 1000) = 1000 26 + 27 + // Check that rwnd limited time in tcp_info is around 0.1s. 28 + +.1 %{ assert 98000 <= tcpi_rwnd_limited <= 110000, tcpi_rwnd_limited }% 29 + 30 + // Server opens the receive window. 31 + +.1 < . 1:1(0) ack 1 win 2000 32 + 33 + // Check that rwnd limited time in tcp_info is around 0.2s. 34 + +0 %{ assert 198000 <= tcpi_rwnd_limited <= 210000, tcpi_rwnd_limited }% 35 + 36 + +0 > P. 1:1001(1000) ack 1 37 + 38 + // Server advertises a very small receive window. 39 + +.03 < . 1:1(0) ack 1001 win 10 40 + 41 + // Receive window limited time starts again. 42 + +0 write(3, ..., 1000) = 1000 43 + 44 + // Server opens the receive window again. 45 + +.1 < . 1:1(0) ack 1001 win 2000 46 + // Check that rwnd limited time in tcp_info is around 0.3s 47 + // and busy time is 0.3 + 0.03 (server opened small window temporarily). 48 + +0 %{ assert 298000 <= tcpi_rwnd_limited <= 310000, tcpi_rwnd_limited;\ 49 + assert 328000 <= tcpi_busy_time <= 340000, tcpi_busy_time;\ 50 + }% 51 + 52 + +0 > P. 1001:2001(1000) ack 1 53 + +.02 < . 1:1(0) ack 2001 win 2000 54 + +0 %{ assert 348000 <= tcpi_busy_time <= 360000, tcpi_busy_time }%
+38
tools/testing/selftests/net/packetdrill/tcp_tcp_info_tcp-info-sndbuf-limited.pkt
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Test send-buffer-limited time in tcp_info for client side. 3 + `./defaults.sh` 4 + 5 + // Create a socket and set it to non-blocking. 6 + 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 7 + +0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR) 8 + +0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 9 + 10 + +0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress) 11 + +0 > S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8> 12 + +.01 < S. 0:0(0) ack 1 win 10000 <mss 1000,sackOK,nop,nop,nop,wscale 8> 13 + +0 > . 1:1(0) ack 1 14 + +0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0 15 + +0 fcntl(3, F_SETFL, O_RDWR) = 0 // set back to blocking 16 + +0 setsockopt(3, SOL_SOCKET, SO_SNDBUF, [10000], 4) = 0 17 + +0 getsockopt(3, SOL_SOCKET, SO_SNDBUF, [20000], [4]) = 0 18 + 19 + +.09...0.14 write(3, ..., 150000) = 150000 20 + 21 + +.01 < . 1:1(0) ack 10001 win 10000 22 + 23 + +.01 < . 1:1(0) ack 30001 win 10000 24 + 25 + // cwnd goes from 40(60KB) to 80(120KB), and that we hit the tiny sndbuf limit 10KB 26 + +.01 < . 1:1(0) ack 70001 win 10000 27 + 28 + +.02 < . 1:1(0) ack 95001 win 10000 29 + +0 %{ assert 19000 <= tcpi_sndbuf_limited <= 21000, tcpi_sndbuf_limited; \ 30 + assert 49000 <= tcpi_busy_time <= 52000, tcpi_busy_time; \ 31 + assert 0 == tcpi_rwnd_limited, tcpi_rwnd_limited }% 32 + 33 + // This ack frees up enough buffer so we are no longer 34 + // buffer limited (socket flag SOCK_NOSPACE is cleared) 35 + +.02 < . 1:1(0) ack 150001 win 10000 36 + +0 %{ assert 19000 <= tcpi_sndbuf_limited <= 21000, tcpi_sndbuf_limited;\ 37 + assert 69000 <= tcpi_busy_time <= 73000, tcpi_busy_time;\ 38 + assert 0 == tcpi_rwnd_limited, tcpi_rwnd_limited }%