From: Bochao Cao Track the DUT shell job so cleanup does not kill other test instances. Wait for readiness while the DUT is alive. Give each run separate DUT and tester namespaces to avoid name, address and port conflicts. Handle signals during setup and ignore repeated signals during cleanup. Fixes: 4dba3e7852b7 ("selftests/bpf: introduce XDP compliance test tool") Signed-off-by: Bochao Cao --- tools/testing/selftests/bpf/test_xdp_features.sh | 122 ++++++++++++++++++----- 1 file changed, 95 insertions(+), 27 deletions(-) diff --git a/tools/testing/selftests/bpf/test_xdp_features.sh b/tools/testing/selftests/bpf/test_xdp_features.sh index 0aa71c4455c05..7b96222b690a6 100755 --- a/tools/testing/selftests/bpf/test_xdp_features.sh +++ b/tools/testing/selftests/bpf/test_xdp_features.sh @@ -1,107 +1,175 @@ #!/bin/bash # SPDX-License-Identifier: GPL-2.0 readonly NS="ns1-$(mktemp -u XXXXXX)" +readonly DUT_NS="dut-${NS}" readonly V0_IP4=10.10.0.11 readonly V1_IP4=10.10.0.1 readonly V0_IP6=2001:db8::11 readonly V1_IP6=2001:db8::1 ret=1 +dut_pid="" +peer_created=false +dut_created=false +setup_in_progress=true +pending_signal=0 setup() { { - ip netns add ${NS} + ip netns add "${NS}" + peer_created=true + ip netns add "${DUT_NS}" + dut_created=true - ip link add v1 type veth peer name v0 netns ${NS} + ip -n "$DUT_NS" link add v1 type veth peer name v0 netns ${NS} - ip link set v1 up - ip addr add $V1_IP4/24 dev v1 - ip addr add $V1_IP6/64 nodad dev v1 + ip -n "$DUT_NS" link set v1 up + ip -n "$DUT_NS" addr add $V1_IP4/24 dev v1 + ip -n "$DUT_NS" addr add $V1_IP6/64 nodad dev v1 ip -n ${NS} link set dev v0 up ip -n ${NS} addr add $V0_IP4/24 dev v0 ip -n ${NS} addr add $V0_IP6/64 nodad dev v0 # Enable XDP mode and disable checksum offload - ethtool -K v1 gro on - ethtool -K v1 tx-checksumming off + ip netns exec "$DUT_NS" ethtool -K v1 gro on + ip netns exec "$DUT_NS" ethtool -K v1 tx-checksumming off ip netns exec ${NS} ethtool -K v0 gro on ip netns exec ${NS} ethtool -K v0 tx-checksumming off } > /dev/null 2>&1 + setup_in_progress=false + [ "$pending_signal" -eq 0 ] || exit "$pending_signal" +} + +terminate_dut_server() { + local pid + + # Use the shell job instead of dut_pid, which may not have been assigned + # yet if a signal arrived immediately after the server was started. + pid=$(jobs -pr %% 2> /dev/null) || true + if [ -z "$pid" ]; then + dut_pid="" + return + fi + + kill -KILL %% 2> /dev/null || true + wait "$pid" 2> /dev/null || true + dut_pid="" } cleanup() { - ip link del v1 2> /dev/null - ip netns del ${NS} 2> /dev/null - [ "$(pidof xdp_features)" = "" ] || kill $(pidof xdp_features) 2> /dev/null + trap - EXIT + trap '' HUP INT QUIT ABRT TERM + terminate_dut_server + if "$dut_created"; then + ip netns del "$DUT_NS" 2> /dev/null || true + fi + if "$peer_created"; then + ip netns del "$NS" 2> /dev/null || true + fi } wait_for_dut_server() { - while sleep 1; do - ss -tlp | grep -q xdp_features - [ $? -eq 0 ] && break + while true; do + if [ "$(jobs -pr %% 2> /dev/null)" != "$dut_pid" ]; then + echo "xdp_features server $dut_pid exited before readiness" >&2 + return 1 + fi + + if ip netns exec "$DUT_NS" ss -tlp 2> /dev/null | + grep -q "pid=$dut_pid,"; then + return 0 + fi + + sleep 1 done } +start_dut_server() { + ip netns exec "$DUT_NS" ./xdp_features "$@" & + dut_pid=$! + wait_for_dut_server +} + +reap_dut_server() { + local status=0 + + wait "$dut_pid" || status=$? + dut_pid="" + return "$status" +} + test_xdp_features() { setup ## XDP_PASS - ./xdp_features -f XDP_PASS -D $V1_IP6 -T $V0_IP6 v1 & - wait_for_dut_server + start_dut_server -f XDP_PASS -D $V1_IP6 -T $V0_IP6 v1 ip netns exec ${NS} ./xdp_features -t -f XDP_PASS \ -D $V1_IP6 -C $V1_IP6 \ -T $V0_IP6 v0 [ $? -ne 0 ] && exit + reap_dut_server ## XDP_DROP - ./xdp_features -f XDP_DROP -D ::ffff:$V1_IP4 -T ::ffff:$V0_IP4 v1 & - wait_for_dut_server + start_dut_server -f XDP_DROP -D ::ffff:$V1_IP4 -T ::ffff:$V0_IP4 v1 ip netns exec ${NS} ./xdp_features -t -f XDP_DROP \ -D ::ffff:$V1_IP4 \ -C ::ffff:$V1_IP4 \ -T ::ffff:$V0_IP4 v0 [ $? -ne 0 ] && exit + reap_dut_server ## XDP_ABORTED - ./xdp_features -f XDP_ABORTED -D $V1_IP6 -T $V0_IP6 v1 & - wait_for_dut_server + start_dut_server -f XDP_ABORTED -D $V1_IP6 -T $V0_IP6 v1 ip netns exec ${NS} ./xdp_features -t -f XDP_ABORTED \ -D $V1_IP6 -C $V1_IP6 \ -T $V0_IP6 v0 [ $? -ne 0 ] && exit + reap_dut_server ## XDP_TX - ./xdp_features -f XDP_TX -D ::ffff:$V1_IP4 -T ::ffff:$V0_IP4 v1 & - wait_for_dut_server + start_dut_server -f XDP_TX -D ::ffff:$V1_IP4 -T ::ffff:$V0_IP4 v1 ip netns exec ${NS} ./xdp_features -t -f XDP_TX \ -D ::ffff:$V1_IP4 \ -C ::ffff:$V1_IP4 \ -T ::ffff:$V0_IP4 v0 [ $? -ne 0 ] && exit + reap_dut_server ## XDP_REDIRECT - ./xdp_features -f XDP_REDIRECT -D $V1_IP6 -T $V0_IP6 v1 & - wait_for_dut_server + start_dut_server -f XDP_REDIRECT -D $V1_IP6 -T $V0_IP6 v1 ip netns exec ${NS} ./xdp_features -t -f XDP_REDIRECT \ -D $V1_IP6 -C $V1_IP6 \ -T $V0_IP6 v0 [ $? -ne 0 ] && exit + reap_dut_server ## XDP_NDO_XMIT - ./xdp_features -f XDP_NDO_XMIT -D ::ffff:$V1_IP4 -T ::ffff:$V0_IP4 v1 & - wait_for_dut_server + start_dut_server -f XDP_NDO_XMIT -D ::ffff:$V1_IP4 -T ::ffff:$V0_IP4 v1 ip netns exec ${NS} ./xdp_features -t -f XDP_NDO_XMIT \ -D ::ffff:$V1_IP4 \ -C ::ffff:$V1_IP4 \ -T ::ffff:$V0_IP4 v0 ret=$? - cleanup + reap_dut_server +} + +handle_signal() { + if "$setup_in_progress"; then + pending_signal=$1 + else + exit "$1" + fi } set -e -trap cleanup 2 3 6 9 +trap cleanup EXIT +trap 'handle_signal 129' HUP +trap 'handle_signal 130' INT +trap 'handle_signal 131' QUIT +trap 'handle_signal 134' ABRT +trap 'handle_signal 143' TERM test_xdp_features exit $ret -- Git-155)