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>
210 lines
3.5 KiB
Bash
210 lines
3.5 KiB
Bash
#!/bin/bash
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
|
|
##############################################################################
|
|
# Defines
|
|
|
|
: "${WAIT_TIMEOUT:=20}"
|
|
|
|
BUSYWAIT_TIMEOUT=$((WAIT_TIMEOUT * 1000)) # ms
|
|
|
|
# Kselftest framework constants.
|
|
ksft_pass=0
|
|
ksft_fail=1
|
|
ksft_xfail=2
|
|
ksft_skip=4
|
|
|
|
# namespace list created by setup_ns
|
|
NS_LIST=""
|
|
|
|
##############################################################################
|
|
# Helpers
|
|
|
|
__ksft_status_merge()
|
|
{
|
|
local a=$1; shift
|
|
local b=$1; shift
|
|
local -A weights
|
|
local weight=0
|
|
|
|
for i in "$@"; do
|
|
weights[$i]=$((weight++))
|
|
done
|
|
|
|
if [[ ${weights[$a]} > ${weights[$b]} ]]; then
|
|
echo "$a"
|
|
return 0
|
|
else
|
|
echo "$b"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
ksft_status_merge()
|
|
{
|
|
local a=$1; shift
|
|
local b=$1; shift
|
|
|
|
__ksft_status_merge "$a" "$b" \
|
|
$ksft_pass $ksft_xfail $ksft_skip $ksft_fail
|
|
}
|
|
|
|
ksft_exit_status_merge()
|
|
{
|
|
local a=$1; shift
|
|
local b=$1; shift
|
|
|
|
__ksft_status_merge "$a" "$b" \
|
|
$ksft_xfail $ksft_pass $ksft_skip $ksft_fail
|
|
}
|
|
|
|
loopy_wait()
|
|
{
|
|
local sleep_cmd=$1; shift
|
|
local timeout_ms=$1; shift
|
|
|
|
local start_time="$(date -u +%s%3N)"
|
|
while true
|
|
do
|
|
local out
|
|
out=$("$@")
|
|
local ret=$?
|
|
if ((!ret)); then
|
|
echo -n "$out"
|
|
return 0
|
|
fi
|
|
|
|
local current_time="$(date -u +%s%3N)"
|
|
if ((current_time - start_time > timeout_ms)); then
|
|
echo -n "$out"
|
|
return 1
|
|
fi
|
|
|
|
$sleep_cmd
|
|
done
|
|
}
|
|
|
|
busywait()
|
|
{
|
|
local timeout_ms=$1; shift
|
|
|
|
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()
|
|
{
|
|
local ns=""
|
|
local errexit=0
|
|
local ret=0
|
|
|
|
# disable errexit temporary
|
|
if [[ $- =~ "e" ]]; then
|
|
errexit=1
|
|
set +e
|
|
fi
|
|
|
|
for ns in "$@"; do
|
|
ip netns delete "${ns}" &> /dev/null
|
|
if ! busywait $BUSYWAIT_TIMEOUT ip netns list \| grep -vq "^$ns$" &> /dev/null; then
|
|
echo "Warn: Failed to remove namespace $ns"
|
|
ret=1
|
|
fi
|
|
done
|
|
|
|
[ $errexit -eq 1 ] && set -e
|
|
return $ret
|
|
}
|
|
|
|
cleanup_all_ns()
|
|
{
|
|
cleanup_ns $NS_LIST
|
|
}
|
|
|
|
# setup netns with given names as prefix. e.g
|
|
# setup_ns local remote
|
|
setup_ns()
|
|
{
|
|
local ns=""
|
|
local ns_name=""
|
|
local ns_list=""
|
|
local ns_exist=
|
|
for ns_name in "$@"; do
|
|
# Some test may setup/remove same netns multi times
|
|
if unset ${ns_name} 2> /dev/null; then
|
|
ns="${ns_name,,}-$(mktemp -u XXXXXX)"
|
|
eval readonly ${ns_name}="$ns"
|
|
ns_exist=false
|
|
else
|
|
eval ns='$'${ns_name}
|
|
cleanup_ns "$ns"
|
|
ns_exist=true
|
|
fi
|
|
|
|
if ! ip netns add "$ns"; then
|
|
echo "Failed to create namespace $ns_name"
|
|
cleanup_ns "$ns_list"
|
|
return $ksft_skip
|
|
fi
|
|
ip -n "$ns" link set lo up
|
|
! $ns_exist && ns_list="$ns_list $ns"
|
|
done
|
|
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"
|
|
}
|