These two TFO client tests are imported from google/packetdrill on GitHub: * client_nonblocking-sendto-errnos.pkt * nonblocking-sendto-empty-buf.pkt Both files had tests for 0 payload sendto(MSG_FASTOPEN) assuming that SYN will be sent w/ TFO cookie if cached, +0 sendto(4, ..., 0, MSG_FASTOPEN, ..., ...) = -1 EINPROGRESS (Operation is now in progress) +0 > S 0:0(0) and now it fails with the previous patch, so this part is fixed up in both files. In addition, the former had lengthy 6s wait in the last test case to ensure that there will not be multiple SYN retransmissions, and I changed it to 2s because now linear timeout is enabled by default (it can be reduced further to 1s, but 2s just in case to avoid flakiness). Signed-off-by: Kuniyuki Iwashima --- ...en_client_nonblocking-sendto-empty-buf.pkt | 45 +++++++ ...topen_client_nonblocking-sendto-errnos.pkt | 125 ++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 tools/testing/selftests/net/packetdrill/tcp_fastopen_client_nonblocking-sendto-empty-buf.pkt create mode 100644 tools/testing/selftests/net/packetdrill/tcp_fastopen_client_nonblocking-sendto-errnos.pkt diff --git a/tools/testing/selftests/net/packetdrill/tcp_fastopen_client_nonblocking-sendto-empty-buf.pkt b/tools/testing/selftests/net/packetdrill/tcp_fastopen_client_nonblocking-sendto-empty-buf.pkt new file mode 100644 index 0000000000000..6ebeff7c5857e --- /dev/null +++ b/tools/testing/selftests/net/packetdrill/tcp_fastopen_client_nonblocking-sendto-empty-buf.pkt @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Non-blocking Fast Open with an empty buffer +// +`./defaults.sh + ./set_sysctls.py /proc/sys/net/ipv4/tcp_timestamps=0` + + 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 + +0 sendto(3, ..., 0, MSG_FASTOPEN, ..., ...) = -1 EINPROGRESS (Operation is now in progress) + +0 > S 0:0(0) + +0 < S. 123:123(0) ack 1 win 14600 + +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: non-blocking sendto() of 0B +// + +0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 4 + +0 sendto(4, ..., 0, MSG_FASTOPEN, ..., ...) = -1 EINPROGRESS (Operation is now in progress) + +// TFO cookie (FO abcd1234) is not sent w/o payload + +0 > S 0:0(0) + +// Server acks FO and replies a different MSS (940B) + +0 < S. 1234:1234(0) ack 1 win 14600 + +0 > . 1:1(0) ack 1 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }% + + +// +// Test: previous server's MSS (940B) and cookie are still cached +// + +0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 5 + +0 sendto(5, ..., 2000, MSG_FASTOPEN, ..., ...) = 900 + +0 > S 0:900(900) +// Sever acknowledges the data but also sends new cookie + +0 < S. 5678:5678(0) ack 901 win 14600 + +0 > . 901:901(0) ack 1 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }% + +`/tmp/sysctl_restore_${PPID}.sh` diff --git a/tools/testing/selftests/net/packetdrill/tcp_fastopen_client_nonblocking-sendto-errnos.pkt b/tools/testing/selftests/net/packetdrill/tcp_fastopen_client_nonblocking-sendto-errnos.pkt new file mode 100644 index 0000000000000..2f74880fe3bbc --- /dev/null +++ b/tools/testing/selftests/net/packetdrill/tcp_fastopen_client_nonblocking-sendto-errnos.pkt @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Test non-blocking sendto(MSG_FASTOPEN) errno(s). +// +`./defaults.sh + ./set_sysctls.py /proc/sys/net/ipv4/tcp_timestamps=0 \ + /proc/sys/net/ipv4/tcp_fastopen_blackhole_timeout_sec=0` + +/////////////////////////////////////////////////////////////////////////////// +// Non-blocking errnos +// + 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 + +0 `sysctl -q net.ipv4.tcp_fastopen=0` +// +// Test: EOPNOTSUPP if fastopen is disabled +// + +0 sendto(3, ..., 1000, MSG_FASTOPEN, ..., ...) = -1 EOPNOTSUPP (Operation not supported) + +0 `sysctl -q net.ipv4.tcp_fastopen=1` + + +// +// Test: 0-byte sendto() returns EINPROGRESS when no cookie is in cache +// + +0 sendto(3, ..., 0, MSG_FASTOPEN, ..., ...) = -1 EINPROGRESS (Operation now in progress) + +0 > S 0:0(0) + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }% + +0 close(3) = 0 + + + +0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 4 +// +// Test: 1000-byte sendto() returns EINPROGRESS when no cookie is in cache +// + +0 sendto(4, ..., 1000, MSG_FASTOPEN|MSG_DONTWAIT, ..., ...) = -1 EINPROGRESS (Operation now in progress) + +0 > S 0:0(0) +// +// Test: EALREADY on multiple sendto(MSG_FASTOPEN) in SYN-SENT +// + +0 sendto(4, ..., 1000, MSG_FASTOPEN, ..., ...) = -1 EALREADY (Operation already in progress) +// +// Test: EAGAIN on write() in SYN-SENT +// + +0 write(4, ..., 1000) = -1 EAGAIN (Resource temporarily unavailable) + +0 < S. 0:0(0) ack 1 win 5840 + +0 > . 1:1(0) ack 1 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }% + +0 close(4) = 0 + + +// +// Repeat previous tests with a valid cookie cached locally +// + +0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 5 +// +// Test: *NO* EINPROGRESS in SYN-SENT b/c data are buffered and transmitted +// + +0 sendto(5, ..., 1000, MSG_FASTOPEN, ..., ...) = 1000 + +0 > S 0:1000(1000) +// +// Test: EALREADY on multiple sendto(MSG_FASTOPEN) in SYN-SENT +// + +0 sendto(5, ..., 1000, MSG_FASTOPEN, ..., ...) = -1 EALREADY (Operation already in progress) +// +// Test: EAGAIN on write() in SYN-SENT +// + +0 write(5, ..., 1000) = -1 EAGAIN (Resource temporarily unavailable) + +0 < S. 506036:506036(0) ack 1001 win 5840 + +0 > . 1001:1001(0) ack 1 + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }% + +0 close(5) = 0 + + +// +// Test: a 0-byte sendto() returns EINPROGRESS even if cookie is in the cache. +// since sendto(MSG_FASTOPEN) is a connect and write combo, and a null +// write is a no-op, so it should behave like a normal connect() +// + +0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 6 + +0 sendto(6, ..., 0, MSG_FASTOPEN, ..., ...) = -1 EINPROGRESS (Operation now in progress) + +0 > S 0:0(0) + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }% + +0 close(6) = 0 + + +// +// Test: ECONNREFUSED when remote resets on SYN +// + +0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 7 + +0 sendto(7, ..., 2000, MSG_FASTOPEN, ..., ...) = 1420 + +0 > S 0:1420(1420) + +0 < R. 0:0(0) ack 1 win 0 + +0 write(7, ..., 2000) = -1 ECONNREFUSED (Connection Refused) + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }% + +0 close(7) = 0 + + +// +// Test: ECONNRESET if RST is received after SYN +// + +0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 8 + +0 sendto(8, ..., 1420, MSG_FASTOPEN, ..., ...) = 1420 + +0 > S 0:1420(1420) + +0 < S. 0:0(0) ack 1421 win 5840 + +0 > . 1421:1421(0) ack 1 + +0 < R. 1:1(0) ack 1421 win 0 + +0 write(8, ..., 2000) = -1 ECONNRESET (Connection reset by peer) + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) != 0, tcpi_options }% + + +// +// Test: ETIMEOUT when SYN timed out +// + +0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 9 + +0 sendto(9, ..., 2000, MSG_FASTOPEN|MSG_DONTWAIT, ..., ...) = 1420 +// Retry once to make this test shorter. + +0 setsockopt(9, IPPROTO_TCP, TCP_SYNCNT, [1], 4) = 0 + +0 > S 0:1420(1420) + +1 > S 0:0(0) +// Why wait 2 sec? it's a bug fixed in 4d22f7d372f5 +// https://bugzilla.redhat.com/show_bug.cgi?id=688989 +// Originally, it was 6 sec but now 2 sec thanks to linear timeout + +2 write(9, ..., 2000) = -1 ETIMEDOUT (Connection timed out) + +0 %{ assert (tcpi_options & TCPI_OPT_SYN_DATA) == 0, tcpi_options }% + +`/tmp/sysctl_restore_${PPID}.sh` -- 2.51.0.788.g6d19910ace-goog