selftests/net: use tc rule to filter the na packet

Test arp_ndisc_untracked_subnets use tcpdump to filter the unsolicited
and untracked na messages. It set -e before calling tcpdump. But if
tcpdump filters 0 packet, it will return none zero, and cause the script
to exit.

Instead of using slow tcpdump to capture packets, let's using tc rule
to filter out the na message.

At the same time, fix function setup_v6 which only needs one parameter.
Move all the related helpers from forwarding lib.sh to net lib.sh.

Fixes: 0ea7b0a454 ("selftests: net: arp_ndisc_untracked_subnets: test for arp_accept and accept_untracked_na")
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://lore.kernel.org/r/20240517010327.2631319-1-liuhangbin@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Hangbin Liu 2024-05-17 09:03:27 +08:00 committed by Paolo Abeni
parent efb9f4f19f
commit ea63ac1429
3 changed files with 75 additions and 94 deletions

View File

@ -73,25 +73,19 @@ setup_v6() {
# namespaces. veth0 is veth-router, veth1 is veth-host. # namespaces. veth0 is veth-router, veth1 is veth-host.
# first, set up the inteface's link to the namespace # first, set up the inteface's link to the namespace
# then, set the interface "up" # then, set the interface "up"
ip -6 -netns ${ROUTER_NS_V6} link add name ${ROUTER_INTF} \ ip -n ${ROUTER_NS_V6} link add name ${ROUTER_INTF} \
type veth peer name ${HOST_INTF} type veth peer name ${HOST_INTF} netns ${HOST_NS_V6}
ip -6 -netns ${ROUTER_NS_V6} link set dev ${ROUTER_INTF} up # Add tc rule to filter out host na message
ip -6 -netns ${ROUTER_NS_V6} link set dev ${HOST_INTF} netns \ tc -n ${ROUTER_NS_V6} qdisc add dev ${ROUTER_INTF} clsact
${HOST_NS_V6} tc -n ${ROUTER_NS_V6} filter add dev ${ROUTER_INTF} \
ingress protocol ipv6 pref 1 handle 101 \
ip -6 -netns ${HOST_NS_V6} link set dev ${HOST_INTF} up flower src_ip ${HOST_ADDR_V6} ip_proto icmpv6 type 136 skip_hw action pass
ip -6 -netns ${ROUTER_NS_V6} addr add \
${ROUTER_ADDR_V6}/${PREFIX_WIDTH_V6} dev ${ROUTER_INTF} nodad
HOST_CONF=net.ipv6.conf.${HOST_INTF} HOST_CONF=net.ipv6.conf.${HOST_INTF}
ip netns exec ${HOST_NS_V6} sysctl -qw ${HOST_CONF}.ndisc_notify=1 ip netns exec ${HOST_NS_V6} sysctl -qw ${HOST_CONF}.ndisc_notify=1
ip netns exec ${HOST_NS_V6} sysctl -qw ${HOST_CONF}.disable_ipv6=0 ip netns exec ${HOST_NS_V6} sysctl -qw ${HOST_CONF}.disable_ipv6=0
ip -6 -netns ${HOST_NS_V6} addr add ${HOST_ADDR_V6}/${PREFIX_WIDTH_V6} \
dev ${HOST_INTF}
ROUTER_CONF=net.ipv6.conf.${ROUTER_INTF} ROUTER_CONF=net.ipv6.conf.${ROUTER_INTF}
ip netns exec ${ROUTER_NS_V6} sysctl -w \ ip netns exec ${ROUTER_NS_V6} sysctl -w \
${ROUTER_CONF}.forwarding=1 >/dev/null 2>&1 ${ROUTER_CONF}.forwarding=1 >/dev/null 2>&1
ip netns exec ${ROUTER_NS_V6} sysctl -w \ ip netns exec ${ROUTER_NS_V6} sysctl -w \
@ -99,6 +93,13 @@ setup_v6() {
ip netns exec ${ROUTER_NS_V6} sysctl -w \ ip netns exec ${ROUTER_NS_V6} sysctl -w \
${ROUTER_CONF}.accept_untracked_na=${accept_untracked_na} \ ${ROUTER_CONF}.accept_untracked_na=${accept_untracked_na} \
>/dev/null 2>&1 >/dev/null 2>&1
ip -n ${ROUTER_NS_V6} link set dev ${ROUTER_INTF} up
ip -n ${HOST_NS_V6} link set dev ${HOST_INTF} up
ip -n ${ROUTER_NS_V6} addr add ${ROUTER_ADDR_V6}/${PREFIX_WIDTH_V6} \
dev ${ROUTER_INTF} nodad
ip -n ${HOST_NS_V6} addr add ${HOST_ADDR_V6}/${PREFIX_WIDTH_V6} \
dev ${HOST_INTF}
set +e set +e
} }
@ -162,26 +163,6 @@ arp_test_gratuitous_combinations() {
arp_test_gratuitous 2 1 arp_test_gratuitous 2 1
} }
cleanup_tcpdump() {
set -e
[[ ! -z ${tcpdump_stdout} ]] && rm -f ${tcpdump_stdout}
[[ ! -z ${tcpdump_stderr} ]] && rm -f ${tcpdump_stderr}
tcpdump_stdout=
tcpdump_stderr=
set +e
}
start_tcpdump() {
set -e
tcpdump_stdout=`mktemp`
tcpdump_stderr=`mktemp`
ip netns exec ${ROUTER_NS_V6} timeout 15s \
tcpdump --immediate-mode -tpni ${ROUTER_INTF} -c 1 \
"icmp6 && icmp6[0] == 136 && src ${HOST_ADDR_V6}" \
> ${tcpdump_stdout} 2> /dev/null
set +e
}
verify_ndisc() { verify_ndisc() {
local accept_untracked_na=$1 local accept_untracked_na=$1
local same_subnet=$2 local same_subnet=$2
@ -222,8 +203,9 @@ ndisc_test_untracked_advertisements() {
HOST_ADDR_V6=2001:db8:abcd:0012::3 HOST_ADDR_V6=2001:db8:abcd:0012::3
fi fi
fi fi
setup_v6 $1 $2 setup_v6 $1
start_tcpdump slowwait_for_counter 15 1 \
tc_rule_handle_stats_get "dev ${ROUTER_INTF} ingress" 101 ".packets" "-n ${ROUTER_NS_V6}"
if verify_ndisc $1 $2; then if verify_ndisc $1 $2; then
printf " TEST: %-60s [ OK ]\n" "${test_msg[*]}" printf " TEST: %-60s [ OK ]\n" "${test_msg[*]}"
@ -231,7 +213,6 @@ ndisc_test_untracked_advertisements() {
printf " TEST: %-60s [FAIL]\n" "${test_msg[*]}" printf " TEST: %-60s [FAIL]\n" "${test_msg[*]}"
fi fi
cleanup_tcpdump
cleanup_v6 cleanup_v6
set +e set +e
} }

View File

@ -129,14 +129,6 @@ fi
source "$net_forwarding_dir/../lib.sh" source "$net_forwarding_dir/../lib.sh"
# timeout in seconds
slowwait()
{
local timeout_sec=$1; shift
loopy_wait "sleep 0.1" "$((timeout_sec * 1000))" "$@"
}
############################################################################## ##############################################################################
# Sanity checks # Sanity checks
@ -678,33 +670,6 @@ wait_for_trap()
"$@" | grep -q trap "$@" | grep -q trap
} }
until_counter_is()
{
local expr=$1; shift
local current=$("$@")
echo $((current))
((current $expr))
}
busywait_for_counter()
{
local timeout=$1; shift
local delta=$1; shift
local base=$("$@")
busywait "$timeout" until_counter_is ">= $((base + delta))" "$@"
}
slowwait_for_counter()
{
local timeout=$1; shift
local delta=$1; shift
local base=$("$@")
slowwait "$timeout" until_counter_is ">= $((base + delta))" "$@"
}
setup_wait_dev() setup_wait_dev()
{ {
local dev=$1; shift local dev=$1; shift
@ -1023,29 +988,6 @@ link_stats_rx_errors_get()
link_stats_get $1 rx errors link_stats_get $1 rx errors
} }
tc_rule_stats_get()
{
local dev=$1; shift
local pref=$1; shift
local dir=$1; shift
local selector=${1:-.packets}; shift
tc -j -s filter show dev $dev ${dir:-ingress} pref $pref \
| jq ".[1].options.actions[].stats$selector"
}
tc_rule_handle_stats_get()
{
local id=$1; shift
local handle=$1; shift
local selector=${1:-.packets}; shift
local netns=${1:-""}; shift
tc $netns -j -s filter show $id \
| jq ".[] | select(.options.handle == $handle) | \
.options.actions[0].stats$selector"
}
ethtool_stats_get() ethtool_stats_get()
{ {
local dev=$1; shift local dev=$1; shift

View File

@ -91,6 +91,41 @@ busywait()
loopy_wait : "$timeout_ms" "$@" loopy_wait : "$timeout_ms" "$@"
} }
# timeout in seconds
slowwait()
{
local timeout_sec=$1; shift
loopy_wait "sleep 0.1" "$((timeout_sec * 1000))" "$@"
}
until_counter_is()
{
local expr=$1; shift
local current=$("$@")
echo $((current))
((current $expr))
}
busywait_for_counter()
{
local timeout=$1; shift
local delta=$1; shift
local base=$("$@")
busywait "$timeout" until_counter_is ">= $((base + delta))" "$@"
}
slowwait_for_counter()
{
local timeout=$1; shift
local delta=$1; shift
local base=$("$@")
slowwait "$timeout" until_counter_is ">= $((base + delta))" "$@"
}
cleanup_ns() cleanup_ns()
{ {
local ns="" local ns=""
@ -150,3 +185,26 @@ setup_ns()
done done
NS_LIST="$NS_LIST $ns_list" NS_LIST="$NS_LIST $ns_list"
} }
tc_rule_stats_get()
{
local dev=$1; shift
local pref=$1; shift
local dir=$1; shift
local selector=${1:-.packets}; shift
tc -j -s filter show dev $dev ${dir:-ingress} pref $pref \
| jq ".[1].options.actions[].stats$selector"
}
tc_rule_handle_stats_get()
{
local id=$1; shift
local handle=$1; shift
local selector=${1:-.packets}; shift
local netns=${1:-""}; shift
tc $netns -j -s filter show $id \
| jq ".[] | select(.options.handle == $handle) | \
.options.actions[0].stats$selector"
}