Commit ae18d300 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'selftests-net-add-packetdrill'

Willem de Bruijn says:

====================
selftests/net: add packetdrill

Lay the groundwork to import into kselftests the over 150 packetdrill
TCP/IP conformance tests on github.com/google/packetdrill.

1/2: add kselftest infra for TEST_PROGS that need an interpreter

2/2: add the specific packetdrill tests
====================

Link: https://patch.msgid.link/20240905231653.2427327-1-willemdebruijn.kernel@gmail.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents bcd138b1 8a405552
......@@ -65,10 +65,11 @@ TARGETS += net/af_unix
TARGETS += net/forwarding
TARGETS += net/hsr
TARGETS += net/mptcp
TARGETS += net/openvswitch
TARGETS += net/tcp_ao
TARGETS += net/netfilter
TARGETS += net/openvswitch
TARGETS += net/packetdrill
TARGETS += net/rds
TARGETS += net/tcp_ao
TARGETS += nsfs
TARGETS += perf_events
TARGETS += pidfd
......
......@@ -111,8 +111,11 @@ run_one()
stdbuf="/usr/bin/stdbuf --output=L "
fi
eval kselftest_cmd_args="\$${kselftest_cmd_args_ref:-}"
cmd="$stdbuf ./$BASENAME_TEST $kselftest_cmd_args"
if [ ! -x "$TEST" ]; then
if [ -x "$TEST" ]; then
cmd="$stdbuf ./$BASENAME_TEST $kselftest_cmd_args"
elif [ -x "./ksft_runner.sh" ]; then
cmd="$stdbuf ./ksft_runner.sh ./$BASENAME_TEST"
else
echo "# Warning: file $TEST is not executable"
if [ $(head -n 1 "$TEST" | cut -c -2) = "#!" ]
......
# SPDX-License-Identifier: GPL-2.0
TEST_INCLUDES := ksft_runner.sh \
defaults.sh \
../../kselftest/ktap_helpers.sh
TEST_PROGS := $(wildcard *.pkt)
include ../../lib.mk
CONFIG_IPV6=y
CONFIG_NET_SCH_FIFO=y
CONFIG_PROC_SYSCTL=y
CONFIG_TCP_MD5SIG=y
CONFIG_TUN=y
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Set standard production config values that relate to TCP behavior.
# Flush old cached data (fastopen cookies).
ip tcp_metrics flush all > /dev/null 2>&1
# TCP min, default, and max receive and send buffer sizes.
sysctl -q net.ipv4.tcp_rmem="4096 540000 $((15*1024*1024))"
sysctl -q net.ipv4.tcp_wmem="4096 $((256*1024)) 4194304"
# TCP timestamps.
sysctl -q net.ipv4.tcp_timestamps=1
# TCP SYN(ACK) retry thresholds
sysctl -q net.ipv4.tcp_syn_retries=5
sysctl -q net.ipv4.tcp_synack_retries=5
# TCP Forward RTO-Recovery, RFC 5682.
sysctl -q net.ipv4.tcp_frto=2
# TCP Selective Acknowledgements (SACK)
sysctl -q net.ipv4.tcp_sack=1
# TCP Duplicate Selective Acknowledgements (DSACK)
sysctl -q net.ipv4.tcp_dsack=1
# TCP FACK (Forward Acknowldgement)
sysctl -q net.ipv4.tcp_fack=0
# TCP reordering degree ("dupthresh" threshold for entering Fast Recovery).
sysctl -q net.ipv4.tcp_reordering=3
# TCP congestion control.
sysctl -q net.ipv4.tcp_congestion_control=cubic
# TCP slow start after idle.
sysctl -q net.ipv4.tcp_slow_start_after_idle=0
# TCP RACK and TLP.
sysctl -q net.ipv4.tcp_early_retrans=4 net.ipv4.tcp_recovery=1
# TCP method for deciding when to defer sending to accumulate big TSO packets.
sysctl -q net.ipv4.tcp_tso_win_divisor=3
# TCP Explicit Congestion Notification (ECN)
sysctl -q net.ipv4.tcp_ecn=0
sysctl -q net.ipv4.tcp_pacing_ss_ratio=200
sysctl -q net.ipv4.tcp_pacing_ca_ratio=120
sysctl -q net.ipv4.tcp_notsent_lowat=4294967295 > /dev/null 2>&1
sysctl -q net.ipv4.tcp_fastopen=0x70403
sysctl -q net.ipv4.tcp_fastopen_key=a1a1a1a1-b2b2b2b2-c3c3c3c3-d4d4d4d4
sysctl -q net.ipv4.tcp_syncookies=1
# Override the default qdisc on the tun device.
# Many tests fail with timing errors if the default
# is FQ and that paces their flows.
tc qdisc add dev tun0 root pfifo
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
source "$(dirname $(realpath $0))/../../kselftest/ktap_helpers.sh"
readonly ipv4_args=('--ip_version=ipv4 '
'--local_ip=192.168.0.1 '
'--gateway_ip=192.168.0.1 '
'--netmask_ip=255.255.0.0 '
'--remote_ip=192.0.2.1 '
'-D CMSG_LEVEL_IP=SOL_IP '
'-D CMSG_TYPE_RECVERR=IP_RECVERR ')
readonly ipv6_args=('--ip_version=ipv6 '
'--mtu=1520 '
'--local_ip=fd3d:0a0b:17d6::1 '
'--gateway_ip=fd3d:0a0b:17d6:8888::1 '
'--remote_ip=fd3d:fa7b:d17d::1 '
'-D CMSG_LEVEL_IP=SOL_IPV6 '
'-D CMSG_TYPE_RECVERR=IPV6_RECVERR ')
if [ $# -ne 1 ]; then
ktap_exit_fail_msg "usage: $0 <script>"
exit "$KSFT_FAIL"
fi
script="$1"
if [ -z "$(which packetdrill)" ]; then
ktap_skip_all "packetdrill not found in PATH"
exit "$KSFT_SKIP"
fi
ktap_print_header
ktap_set_plan 2
packetdrill ${ipv4_args[@]} $(basename $script) > /dev/null \
&& ktap_test_pass "ipv4" || ktap_test_fail "ipv4"
packetdrill ${ipv6_args[@]} $(basename $script) > /dev/null \
&& ktap_test_pass "ipv6" || ktap_test_fail "ipv6"
ktap_finished
// SPDX-License-Identifier: GPL-2.0
// Test TCP_INQ and TCP_CM_INQ on the client side.
`./defaults.sh
`
// Create a socket and set it to non-blocking.
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
+0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
// Connect to the server and enable TCP_INQ.
+0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress)
+0 setsockopt(3, SOL_TCP, TCP_INQ, [1], 4) = 0
+0 > S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+.01 < S. 0:0(0) ack 1 win 5792 <mss 1460,sackOK,TS val 700 ecr 100,nop,wscale 7>
+0 > . 1:1(0) ack 1 <nop,nop,TS val 200 ecr 700>
// Now we have 10K of data ready on the socket.
+0 < . 1:10001(10000) ack 1 win 514
+0 > . 1:1(0) ack 10001 <nop,nop,TS val 200 ecr 700>
// We read 1K and we should have 9K ready to read.
+0 recvmsg(3, {msg_name(...)=...,
msg_iov(1)=[{..., 1000}],
msg_flags=0,
msg_control=[{cmsg_level=SOL_TCP,
cmsg_type=TCP_CM_INQ,
cmsg_data=9000}]}, 0) = 1000
// We read 9K and we should have no further data ready to read.
+0 recvmsg(3, {msg_name(...)=...,
msg_iov(1)=[{..., 9000}],
msg_flags=0,
msg_control=[{cmsg_level=SOL_TCP,
cmsg_type=TCP_CM_INQ,
cmsg_data=0}]}, 0) = 9000
// Server sends more data and closes the connections.
+0 < F. 10001:20001(10000) ack 1 win 514
+0 > . 1:1(0) ack 20002 <nop,nop,TS val 200 ecr 700>
// We read 10K and we should have one "fake" byte because the connection is
// closed.
+0 recvmsg(3, {msg_name(...)=...,
msg_iov(1)=[{..., 10000}],
msg_flags=0,
msg_control=[{cmsg_level=SOL_TCP,
cmsg_type=TCP_CM_INQ,
cmsg_data=1}]}, 0) = 10000
// Now, receive EOF.
+0 read(3, ..., 2000) = 0
// SPDX-License-Identifier: GPL-2.0
// Test TCP_INQ and TCP_CM_INQ on the server side.
`./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,nop,wscale 10>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.01 < . 1:1(0) ack 1 win 514
// Accept the connection and enable TCP_INQ.
+0 accept(3, ..., ...) = 4
+0 setsockopt(4, SOL_TCP, TCP_INQ, [1], 4) = 0
// Now we have 10K of data ready on the socket.
+0 < . 1:10001(10000) ack 1 win 514
+0 > . 1:1(0) ack 10001
// We read 2K and we should have 8K ready to read.
+0 recvmsg(4, {msg_name(...)=...,
msg_iov(1)=[{..., 2000}],
msg_flags=0,
msg_control=[{cmsg_level=SOL_TCP,
cmsg_type=TCP_CM_INQ,
cmsg_data=8000}]}, 0) = 2000
// We read 8K and we should have no further data ready to read.
+0 recvmsg(4, {msg_name(...)=...,
msg_iov(1)=[{..., 8000}],
msg_flags=0,
msg_control=[{cmsg_level=SOL_TCP,
cmsg_type=TCP_CM_INQ,
cmsg_data=0}]}, 0) = 8000
// Client sends more data and closes the connections.
+0 < F. 10001:20001(10000) ack 1 win 514
+0 > . 1:1(0) ack 20002
// We read 10K and we should have one "fake" byte because the connection is
// closed.
+0 recvmsg(4, {msg_name(...)=...,
msg_iov(1)=[{..., 10000}],
msg_flags=0,
msg_control=[{cmsg_level=SOL_TCP,
cmsg_type=TCP_CM_INQ,
cmsg_data=1}]}, 0) = 10000
// Now, receive error.
+0 read(3, ..., 2000) = -1 ENOTCONN (Transport endpoint is not connected)
// SPDX-License-Identifier: GPL-2.0
// Test what happens when client does not provide MD5 on SYN,
// but then does on the ACK that completes the three-way handshake.
`./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
+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>
// Ooh, weird: client provides MD5 option on the ACK:
+.01 < . 1:1(0) ack 1 win 514 <md5 000102030405060708090a0b0c0d0e0f,nop,nop>
+.01 < . 1:1(0) ack 1 win 514 <md5 000102030405060708090a0b0c0d0e0f,nop,nop>
// The TCP listener refcount should be 2, but on buggy kernels it can be 0:
+0 `grep " 0A " /proc/net/tcp /proc/net/tcp6 | grep ":1F90"`
// Now here comes the legit ACK:
+.01 < . 1:1(0) ack 1 win 514
// Make sure the connection is OK:
+0 accept(3, ..., ...) = 4
+.01 write(4, ..., 1000) = 1000
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment