1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4############################################################################## 5# Defines 6 7: "${WAIT_TIMEOUT:=20}" 8 9BUSYWAIT_TIMEOUT=$((WAIT_TIMEOUT * 1000)) # ms 10 11# Kselftest framework constants. 12ksft_pass=0 13ksft_fail=1 14ksft_xfail=2 15ksft_skip=4 16 17# namespace list created by setup_ns 18NS_LIST="" 19 20############################################################################## 21# Helpers 22 23__ksft_status_merge() 24{ 25 local a=$1; shift 26 local b=$1; shift 27 local -A weights 28 local weight=0 29 30 for i in "$@"; do 31 weights[$i]=$((weight++)) 32 done 33 34 if [[ ${weights[$a]} > ${weights[$b]} ]]; then 35 echo "$a" 36 return 0 37 else 38 echo "$b" 39 return 1 40 fi 41} 42 43ksft_status_merge() 44{ 45 local a=$1; shift 46 local b=$1; shift 47 48 __ksft_status_merge "$a" "$b" \ 49 $ksft_pass $ksft_xfail $ksft_skip $ksft_fail 50} 51 52ksft_exit_status_merge() 53{ 54 local a=$1; shift 55 local b=$1; shift 56 57 __ksft_status_merge "$a" "$b" \ 58 $ksft_xfail $ksft_pass $ksft_skip $ksft_fail 59} 60 61loopy_wait() 62{ 63 local sleep_cmd=$1; shift 64 local timeout_ms=$1; shift 65 66 local start_time="$(date -u +%s%3N)" 67 while true 68 do 69 local out 70 out=$("$@") 71 local ret=$? 72 if ((!ret)); then 73 echo -n "$out" 74 return 0 75 fi 76 77 local current_time="$(date -u +%s%3N)" 78 if ((current_time - start_time > timeout_ms)); then 79 echo -n "$out" 80 return 1 81 fi 82 83 $sleep_cmd 84 done 85} 86 87busywait() 88{ 89 local timeout_ms=$1; shift 90 91 loopy_wait : "$timeout_ms" "$@" 92} 93 94# timeout in seconds 95slowwait() 96{ 97 local timeout_sec=$1; shift 98 99 loopy_wait "sleep 0.1" "$((timeout_sec * 1000))" "$@" 100} 101 102until_counter_is() 103{ 104 local expr=$1; shift 105 local current=$("$@") 106 107 echo $((current)) 108 ((current $expr)) 109} 110 111busywait_for_counter() 112{ 113 local timeout=$1; shift 114 local delta=$1; shift 115 116 local base=$("$@") 117 busywait "$timeout" until_counter_is ">= $((base + delta))" "$@" 118} 119 120slowwait_for_counter() 121{ 122 local timeout=$1; shift 123 local delta=$1; shift 124 125 local base=$("$@") 126 slowwait "$timeout" until_counter_is ">= $((base + delta))" "$@" 127} 128 129cleanup_ns() 130{ 131 local ns="" 132 local errexit=0 133 local ret=0 134 135 # disable errexit temporary 136 if [[ $- =~ "e" ]]; then 137 errexit=1 138 set +e 139 fi 140 141 for ns in "$@"; do 142 ip netns delete "${ns}" &> /dev/null 143 if ! busywait $BUSYWAIT_TIMEOUT ip netns list \| grep -vq "^$ns$" &> /dev/null; then 144 echo "Warn: Failed to remove namespace $ns" 145 ret=1 146 fi 147 done 148 149 [ $errexit -eq 1 ] && set -e 150 return $ret 151} 152 153cleanup_all_ns() 154{ 155 cleanup_ns $NS_LIST 156} 157 158# setup netns with given names as prefix. e.g 159# setup_ns local remote 160setup_ns() 161{ 162 local ns="" 163 local ns_name="" 164 local ns_list="" 165 local ns_exist= 166 for ns_name in "$@"; do 167 # Some test may setup/remove same netns multi times 168 if unset ${ns_name} 2> /dev/null; then 169 ns="${ns_name,,}-$(mktemp -u XXXXXX)" 170 eval readonly ${ns_name}="$ns" 171 ns_exist=false 172 else 173 eval ns='$'${ns_name} 174 cleanup_ns "$ns" 175 ns_exist=true 176 fi 177 178 if ! ip netns add "$ns"; then 179 echo "Failed to create namespace $ns_name" 180 cleanup_ns "$ns_list" 181 return $ksft_skip 182 fi 183 ip -n "$ns" link set lo up 184 ! $ns_exist && ns_list="$ns_list $ns" 185 done 186 NS_LIST="$NS_LIST $ns_list" 187} 188 189tc_rule_stats_get() 190{ 191 local dev=$1; shift 192 local pref=$1; shift 193 local dir=$1; shift 194 local selector=${1:-.packets}; shift 195 196 tc -j -s filter show dev $dev ${dir:-ingress} pref $pref \ 197 | jq ".[1].options.actions[].stats$selector" 198} 199 200tc_rule_handle_stats_get() 201{ 202 local id=$1; shift 203 local handle=$1; shift 204 local selector=${1:-.packets}; shift 205 local netns=${1:-""}; shift 206 207 tc $netns -j -s filter show $id \ 208 | jq ".[] | select(.options.handle == $handle) | \ 209 .options.actions[0].stats$selector" 210} 211