Matthieu Baerts wrote:
Hi Willem,
On 06/09/2024 01:15, Willem de Bruijn wrote:
From: Willem de Bruijn willemb@google.com
Lay the groundwork to import into kselftests the over 150 packetdrill TCP/IP conformance tests on github.com/google/packetdrill.
Florian recently added support for packetdrill tests in nf_conntrack, in commit a8a388c2aae49 ("selftests: netfilter: add packetdrill based conntrack tests").
This patch takes a slightly different approach. It relies on ksft_runner.sh to run every *.pkt file in the directory.
Thank you for adding this support! I'm looking forward to seeing more packetdrill tests being validated by the CI, and I hope that will encourage people to add more tests, and increase the code coverage!
Thanks for taking a look and your feedback.
I have some questions about how the packetdrill should be executed: should they be isolated in dedicated netns?
Yes. The runner decides that, by passing -n
There are some other comments, but feel free to ignore them if they are not relevant, or if they can be fixed later.
Tested: make -C tools/testing/selftests \ TARGETS=net/packetdrill \ run_tests
Please note that this will not run the packetdrill tests in a dedicated netns. I don't think that's a good idea. Especially when sysctl knobs are being changed during the tests, and more.
make -C tools/testing/selftests \ TARGETS=net/packetdrill \ install INSTALL_PATH=$KSFT_INSTALL_PATH
# in virtme-ng ./run_kselftest.sh -c net/packetdrill ./run_kselftest.sh -t net/packetdrill:tcp_inq_client.pkt
I see that ./run_kselftest.sh can be executed with the "-n | --netns" option to run each test in a dedicated net namespace, but it doesn't seem to work:
# ./run_kselftest.sh -n -c net/packetdrill [ 411.087208] kselftest: Running tests in net/packetdrill TAP version 13 1..3 Cannot open network namespace "tcp_inq_client.pkt-TaQ8iN": No such file or directory setting the network namespace "tcp_inq_server.pkt-sW8YCz" failed: Invalid argument Cannot open network namespace "tcp_md5_md5-only-on-client-ack.pkt-YzJal6": No such file or directory
Ah, I guess this requires adding CONFIG_NET_NS=y to tools/testing/selftests/net/packetdrill/config
But maybe it would be better to create the netns in ksft_runner.sh? Please see below.
No, we opted for this design exactly to use existing kselftest infra, rather than reimplementing that in our wrapper, as I did in the RFC.
(...)
diff --git a/tools/testing/selftests/net/packetdrill/defaults.sh b/tools/testing/selftests/net/packetdrill/defaults.sh new file mode 100755 index 0000000000000..1095a7b22f44d --- /dev/null +++ b/tools/testing/selftests/net/packetdrill/defaults.sh @@ -0,0 +1,63 @@ +#!/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
(Why ignoring errors if any?)
I don't know. Just importing this verbatim from github. As that is debugged over a long time and proven to work.
+# 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
(maybe safer to add CONFIG_TCP_CONG_CUBIC=y?)
Ack, thanks. Also below.
+# 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
(maybe safer to add CONFIG_SYN_COOKIES=y?)
+# 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
(when applying your patches with 'b4 shazam', I got the following error, I guess it was due to this blank line at the end)
Applying: selftests: support interpreted scripts with ksft_runner.sh Applying: selftests/net: integrate packetdrill with ksft .git/rebase-apply/patch:142: new blank line at EOF.
diff --git a/tools/testing/selftests/net/packetdrill/ksft_runner.sh b/tools/testing/selftests/net/packetdrill/ksft_runner.sh new file mode 100755 index 0000000000000..2f62caccbbbc5 --- /dev/null +++ b/tools/testing/selftests/net/packetdrill/ksft_runner.sh @@ -0,0 +1,41 @@ +#!/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 ')
(nit: that's a strange Bash array with spaces in the strings :) You can simply remove the quotes, then below, you can use the variable with double quotes: "${ipv4_args[@]}" and shellcheck will stop reporting an error for that)
Thanks!
+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 \
(Why muting stdout? I see that the TCP MD5 test output lines from /proc/net/tcp*, is it why? Is this info useful? Or should it be removed from the test?)
Indeed that's why. If a test fails in automated testing we can run manually to inspect such output.
- && ktap_test_pass "ipv4" || ktap_test_fail "ipv4"
+packetdrill ${ipv6_args[@]} $(basename $script) > /dev/null \
- && ktap_test_pass "ipv6" || ktap_test_fail "ipv6"
Even if "run_kselftest.sh" creates dedicated netns before running this script (RUN_IN_NETNS=1), it looks like the tests in v4 and in v6 will share the same netns. Is it OK? It means that if a packetdrill test sets something that is not reset by 'defaults.sh', it might break the following v6 test.
That should be fine. If a test cares about a sysctl, then it needs to set it at the start. In this case, they both will set exactly the same anyway.
Why not having "ksft_runner.sh" creating the netns? It should be easy to do so, using helpers from the "../lib.sh" file:
See above.
ns_v4= ns_v6=
trap cleanup_all_ns EXIT if ! setup_ns ns_v4 ns_v6; then (...) # fail + exit fi
ip netns exec "${ns_v4}" packetdrill "${ipv4_args[@]}" \ "$(basename "${script}")" (...)
(Note that if these tests are isolated in dedicated netns, and if later we want to accelerate their execution, it should be easy to run these two tests in parallel, something like the following)
ip netns exec "${ns_v4}" (...) & pid_v4=$! ip netns exec "${ns_v6}" (...) & pid_v6=$!
wait ${pid_v4} && tap_test_pass "ipv4" || ktap_test_fail "ipv4" wait ${pid_v6} && tap_test_pass "ipv6" || ktap_test_fail "ipv6"
+ktap_finished diff --git a/tools/testing/selftests/net/packetdrill/tcp_inq_client.pkt b/tools/testing/selftests/net/packetdrill/tcp_inq_client.pkt new file mode 100644 index 0000000000000..df49c67645ac8 --- /dev/null +++ b/tools/testing/selftests/net/packetdrill/tcp_inq_client.pkt @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0 +// Test TCP_INQ and TCP_CM_INQ on the client side. +`./defaults.sh +`
(I guess you prefer not to modify these tests, and keep them self-contained, but just in case it is easier for you, this line could be removed, and have ksft_runner.sh sourcing this file before executing the packetdrill test.)
Future packetdrill tests can have different shell preambles. Let's indeed leave it to the tests themselves.
Cheers, Matt -- Sponsored by the NGI0 Core fund.