2 # SPDX-License-Identifier: GPL-2.0
4 net_dir=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")")
5 source "$net_dir/lib/sh/defer.sh"
7 ##############################################################################
10 : "${WAIT_TIMEOUT:=20}"
12 # Whether to pause on after a failure.
13 : "${PAUSE_ON_FAIL:=no}"
15 BUSYWAIT_TIMEOUT=$((WAIT_TIMEOUT * 1000)) # ms
17 # Kselftest framework constants.
23 # namespace list created by setup_ns
26 # Exit status to return at the end. Set in case one of the tests fails.
28 # Per-test return value. Clear at the beginning of each test.
31 ##############################################################################
43 weights[$i]=$((weight++))
46 if [[ ${weights[$a]} > ${weights[$b]} ]]; then
60 __ksft_status_merge "$a" "$b" \
61 $ksft_pass $ksft_xfail $ksft_skip $ksft_fail
64 ksft_exit_status_merge()
69 __ksft_status_merge "$a" "$b" \
70 $ksft_xfail $ksft_pass $ksft_skip $ksft_fail
75 local sleep_cmd=$1; shift
76 local timeout_ms=$1; shift
78 local start_time="$(date -u +%s%3N)"
87 local current_time="$(date -u +%s%3N)"
88 if ((current_time - start_time > timeout_ms)); then
99 local timeout_ms=$1; shift
101 loopy_wait : "$timeout_ms" "$@"
107 local timeout_sec=$1; shift
109 loopy_wait "sleep 0.1" "$((timeout_sec * 1000))" "$@"
115 local current=$("$@")
121 busywait_for_counter()
123 local timeout=$1; shift
124 local delta=$1; shift
127 busywait "$timeout" until_counter_is ">= $((base + delta))" "$@"
130 slowwait_for_counter()
132 local timeout=$1; shift
133 local delta=$1; shift
136 slowwait "$timeout" until_counter_is ">= $((base + delta))" "$@"
139 # Check for existence of tools which are built as part of selftests
140 # but may also already exist in $PATH
143 local prog_name=$1; shift
145 if ! which $prog_name >/dev/null 2>/dev/null; then
147 if ! which $prog_name >/dev/null; then
148 echo "'$prog_name' command not found; skipping tests"
158 local ns_list=("${NS_LIST[@]}")
161 for ns in "${ns_list[@]}"; do
162 if [ "${ns}" != "${item}" ]; then
174 [ -z "${ns}" ] && continue
175 ip netns pids "${ns}" 2> /dev/null | xargs -r kill || true
176 ip netns delete "${ns}" &> /dev/null || true
177 if ! busywait $BUSYWAIT_TIMEOUT ip netns list \| grep -vq "^$ns$" &> /dev/null; then
178 echo "Warn: Failed to remove namespace $ns"
181 remove_ns_list "${ns}"
190 cleanup_ns "${NS_LIST[@]}"
193 # setup netns with given names as prefix. e.g
194 # setup_ns local remote
199 for ns_name in "$@"; do
200 # avoid conflicts with local var: internal error
201 if [ "${ns_name}" = "ns_name" ]; then
202 echo "Failed to setup namespace '${ns_name}': invalid name"
203 cleanup_ns "${ns_list[@]}"
207 # Some test may setup/remove same netns multi times
208 if [ -z "${!ns_name}" ]; then
209 eval "${ns_name}=${ns_name,,}-$(mktemp -u XXXXXX)"
211 cleanup_ns "${!ns_name}"
214 if ! ip netns add "${!ns_name}"; then
215 echo "Failed to create namespace $ns_name"
216 cleanup_ns "${ns_list[@]}"
219 ip -n "${!ns_name}" link set lo up
220 ns_list+=("${!ns_name}")
222 NS_LIST+=("${ns_list[@]}")
229 local dir=${1:-ingress}; shift
230 local selector=${1:-.packets}; shift
232 tc -j -s filter show dev $dev $dir pref $pref \
233 | jq ".[1].options.actions[].stats$selector"
236 tc_rule_handle_stats_get()
239 local handle=$1; shift
240 local selector=${1:-.packets}; shift
241 local netns=${1:-""}; shift
243 tc $netns -j -s filter show $id \
244 | jq ".[] | select(.options.handle == $handle) | \
245 .options.actions[0].stats$selector"
248 ret_set_ksft_status()
250 local ksft_status=$1; shift
253 RET=$(ksft_status_merge $RET $ksft_status)
261 local test_name=$1; shift
262 local opt_str=$1; shift
263 local result=$1; shift
264 local retmsg=$1; shift
266 printf "TEST: %-60s [%s]\n" "$test_name $opt_str" "$result"
267 if [[ $retmsg ]]; then
268 printf "\t%s\n" "$retmsg"
274 if [[ $PAUSE_ON_FAIL == yes ]]; then
275 echo "Hit enter to continue, 'q' to quit"
277 [[ $a == q ]] && exit 1
281 handle_test_result_pass()
283 local test_name=$1; shift
284 local opt_str=$1; shift
286 log_test_result "$test_name" "$opt_str" " OK "
289 handle_test_result_fail()
291 local test_name=$1; shift
292 local opt_str=$1; shift
294 log_test_result "$test_name" "$opt_str" FAIL "$retmsg"
298 handle_test_result_xfail()
300 local test_name=$1; shift
301 local opt_str=$1; shift
303 log_test_result "$test_name" "$opt_str" XFAIL "$retmsg"
307 handle_test_result_skip()
309 local test_name=$1; shift
310 local opt_str=$1; shift
312 log_test_result "$test_name" "$opt_str" SKIP "$retmsg"
320 if [[ $# -eq 2 ]]; then
324 if ((RET == ksft_pass)); then
325 handle_test_result_pass "$test_name" "$opt_str"
326 elif ((RET == ksft_xfail)); then
327 handle_test_result_xfail "$test_name" "$opt_str"
328 elif ((RET == ksft_skip)); then
329 handle_test_result_skip "$test_name" "$opt_str"
331 handle_test_result_fail "$test_name" "$opt_str"
334 EXIT_STATUS=$(ksft_exit_status_merge $EXIT_STATUS $RET)
340 RET=$ksft_skip retmsg= log_test "$@"
345 RET=$ksft_xfail retmsg= log_test "$@"
359 for current_test in ${TESTS:-$ALL_TESTS}; do
365 # Whether FAILs should be interpreted as XFAILs. Internal.
374 if [[ $FAIL_TO_XFAIL = yes ]]; then
375 ret_set_ksft_status $ksft_xfail "$msg"
377 ret_set_ksft_status $ksft_fail "$msg"
387 check_err $((!err)) "$msg"
392 local should_fail=$1; shift
396 if ((should_fail)); then
397 check_fail $err "$what succeeded, but should have failed"
399 check_err $err "$what failed"
405 FAIL_TO_XFAIL=yes "$@"
410 if [[ $KSFT_MACHINE_SLOW = yes ]]; then
411 FAIL_TO_XFAIL=yes "$@"
419 if [[ $KSFT_MACHINE_SLOW != yes ]]; then
429 kind=$(ip -j -d link show dev $dev |
430 jq -r '.[].linkinfo.info_kind')
431 if [[ $kind = veth ]]; then
432 FAIL_TO_XFAIL=yes "$@"
442 ip -j link show dev $if_name | jq -r '.[]["address"]'
449 # Suppress noise from killing the process.
450 { kill $pid && wait $pid; } 2>/dev/null
457 ip link add name "$name" "$@"
458 defer ip link del dev "$name"
463 local member=$1; shift
464 local master=$1; shift
466 ip link set dev "$member" master "$master"
467 defer ip link set dev "$member" nomaster
475 local old_addr=$(mac_get "$name")
476 ip link set dev "$name" address "$addr"
477 defer ip link set dev "$name" address "$old_addr"
484 local state=$(ip -j link show "$name" |
485 jq -r '(.[].flags[] | select(. == "UP")) // "DOWN"')
493 if ! ip_link_is_up "$name"; then
494 ip link set dev "$name" up
495 defer ip link set dev "$name" down
503 if ip_link_is_up "$name"; then
504 ip link set dev "$name" down
505 defer ip link set dev "$name" up
513 ip addr add dev "$name" "$@"
514 defer ip addr del dev "$name" "$@"
520 defer ip route del "$@"
526 defer bridge vlan del "$@"