xref: /openbmc/linux/tools/testing/selftests/net/forwarding/lib.sh (revision 6c71a0574249f5e5a45fe055ab5f837023d5eeca)
173bae673SIdo Schimmel#!/bin/bash
273bae673SIdo Schimmel# SPDX-License-Identifier: GPL-2.0
373bae673SIdo Schimmel
473bae673SIdo Schimmel##############################################################################
573bae673SIdo Schimmel# Defines
673bae673SIdo Schimmel
773bae673SIdo Schimmel# Can be overridden by the configuration file.
873bae673SIdo SchimmelPING=${PING:=ping}
973bae673SIdo SchimmelPING6=${PING6:=ping6}
10d4deb014SIdo SchimmelMZ=${MZ:=mausezahn}
11ca70a562SPetr MachataARPING=${ARPING:=arping}
129d9e6bdeSPetr MachataTEAMD=${TEAMD:=teamd}
1373bae673SIdo SchimmelWAIT_TIME=${WAIT_TIME:=5}
1473bae673SIdo SchimmelPAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
1573bae673SIdo SchimmelPAUSE_ON_CLEANUP=${PAUSE_ON_CLEANUP:=no}
1659be45c3SIdo SchimmelNETIF_TYPE=${NETIF_TYPE:=veth}
1759be45c3SIdo SchimmelNETIF_CREATE=${NETIF_CREATE:=yes}
186d4efadaSNir DotanMCD=${MCD:=smcrouted}
196d4efadaSNir DotanMC_CLI=${MC_CLI:=smcroutectl}
200cd0b1f7SAmit CohenPING_COUNT=${PING_COUNT:=10}
21b6a4fd68SIdo SchimmelPING_TIMEOUT=${PING_TIMEOUT:=5}
228f72a9cfSAmit CohenWAIT_TIMEOUT=${WAIT_TIMEOUT:=20}
238f72a9cfSAmit CohenINTERFACE_TIMEOUT=${INTERFACE_TIMEOUT:=600}
2408119759STobias WaldekranzLOW_AGEING_TIME=${LOW_AGEING_TIME:=1000}
25d70b51f2SVladimir OlteanREQUIRE_JQ=${REQUIRE_JQ:=yes}
26d70b51f2SVladimir OlteanREQUIRE_MZ=${REQUIRE_MZ:=yes}
27f23cddc7SVladimir OlteanREQUIRE_MTOOLS=${REQUIRE_MTOOLS:=no}
28b343734eSVladimir OlteanSTABLE_MAC_ADDRS=${STABLE_MAC_ADDRS:=no}
29fe32dffdSJoachim WibergTCPDUMP_EXTRA_FLAGS=${TCPDUMP_EXTRA_FLAGS:=}
3038f7c44dSIdo SchimmelTROUTE6=${TROUTE6:=traceroute6}
3173bae673SIdo Schimmel
3287d8fb18SYuval Mintzrelative_path="${BASH_SOURCE%/*}"
3387d8fb18SYuval Mintzif [[ "$relative_path" == "${BASH_SOURCE}" ]]; then
3487d8fb18SYuval Mintz	relative_path="."
3587d8fb18SYuval Mintzfi
3687d8fb18SYuval Mintz
3787d8fb18SYuval Mintzif [[ -f $relative_path/forwarding.config ]]; then
3887d8fb18SYuval Mintz	source "$relative_path/forwarding.config"
3973bae673SIdo Schimmelfi
4073bae673SIdo Schimmel
41*bb2f3187SBenjamin Poirier# Kselftest framework requirement - SKIP code is 4.
42*bb2f3187SBenjamin Poirierksft_skip=4
43*bb2f3187SBenjamin Poirier
44*bb2f3187SBenjamin Poirierbusywait()
45*bb2f3187SBenjamin Poirier{
46*bb2f3187SBenjamin Poirier	local timeout=$1; shift
47*bb2f3187SBenjamin Poirier
48*bb2f3187SBenjamin Poirier	local start_time="$(date -u +%s%3N)"
49*bb2f3187SBenjamin Poirier	while true
50*bb2f3187SBenjamin Poirier	do
51*bb2f3187SBenjamin Poirier		local out
52*bb2f3187SBenjamin Poirier		out=$("$@")
53*bb2f3187SBenjamin Poirier		local ret=$?
54*bb2f3187SBenjamin Poirier		if ((!ret)); then
55*bb2f3187SBenjamin Poirier			echo -n "$out"
56*bb2f3187SBenjamin Poirier			return 0
57*bb2f3187SBenjamin Poirier		fi
58*bb2f3187SBenjamin Poirier
59*bb2f3187SBenjamin Poirier		local current_time="$(date -u +%s%3N)"
60*bb2f3187SBenjamin Poirier		if ((current_time - start_time > timeout)); then
61*bb2f3187SBenjamin Poirier			echo -n "$out"
62*bb2f3187SBenjamin Poirier			return 1
63*bb2f3187SBenjamin Poirier		fi
64*bb2f3187SBenjamin Poirier	done
65*bb2f3187SBenjamin Poirier}
66*bb2f3187SBenjamin Poirier
6773bae673SIdo Schimmel##############################################################################
6873bae673SIdo Schimmel# Sanity checks
6973bae673SIdo Schimmel
70198979beSDavid Aherncheck_tc_version()
71198979beSDavid Ahern{
72198979beSDavid Ahern	tc -j &> /dev/null
73198979beSDavid Ahern	if [[ $? -ne 0 ]]; then
74198979beSDavid Ahern		echo "SKIP: iproute2 too old; tc is missing JSON support"
757844ec21SPo-Hsu Lin		exit $ksft_skip
76198979beSDavid Ahern	fi
777f333cbfSJiri Pirko}
78198979beSDavid Ahern
79203ee5cdSGuillaume Nault# Old versions of tc don't understand "mpls_uc"
80203ee5cdSGuillaume Naultcheck_tc_mpls_support()
81203ee5cdSGuillaume Nault{
82203ee5cdSGuillaume Nault	local dev=$1; shift
83203ee5cdSGuillaume Nault
84203ee5cdSGuillaume Nault	tc filter add dev $dev ingress protocol mpls_uc pref 1 handle 1 \
85203ee5cdSGuillaume Nault		matchall action pipe &> /dev/null
86203ee5cdSGuillaume Nault	if [[ $? -ne 0 ]]; then
87203ee5cdSGuillaume Nault		echo "SKIP: iproute2 too old; tc is missing MPLS support"
887844ec21SPo-Hsu Lin		return $ksft_skip
89203ee5cdSGuillaume Nault	fi
90203ee5cdSGuillaume Nault	tc filter del dev $dev ingress protocol mpls_uc pref 1 handle 1 \
91203ee5cdSGuillaume Nault		matchall
92203ee5cdSGuillaume Nault}
93203ee5cdSGuillaume Nault
94c09bfd9aSGuillaume Nault# Old versions of tc produce invalid json output for mpls lse statistics
95c09bfd9aSGuillaume Naultcheck_tc_mpls_lse_stats()
96c09bfd9aSGuillaume Nault{
97c09bfd9aSGuillaume Nault	local dev=$1; shift
98c09bfd9aSGuillaume Nault	local ret;
99c09bfd9aSGuillaume Nault
100c09bfd9aSGuillaume Nault	tc filter add dev $dev ingress protocol mpls_uc pref 1 handle 1 \
101c09bfd9aSGuillaume Nault		flower mpls lse depth 2                                 \
102c09bfd9aSGuillaume Nault		action continue &> /dev/null
103c09bfd9aSGuillaume Nault
104c09bfd9aSGuillaume Nault	if [[ $? -ne 0 ]]; then
105c09bfd9aSGuillaume Nault		echo "SKIP: iproute2 too old; tc-flower is missing extended MPLS support"
1067844ec21SPo-Hsu Lin		return $ksft_skip
107c09bfd9aSGuillaume Nault	fi
108c09bfd9aSGuillaume Nault
109c09bfd9aSGuillaume Nault	tc -j filter show dev $dev ingress protocol mpls_uc | jq . &> /dev/null
110c09bfd9aSGuillaume Nault	ret=$?
111c09bfd9aSGuillaume Nault	tc filter del dev $dev ingress protocol mpls_uc pref 1 handle 1 \
112c09bfd9aSGuillaume Nault		flower
113c09bfd9aSGuillaume Nault
114c09bfd9aSGuillaume Nault	if [[ $ret -ne 0 ]]; then
115c09bfd9aSGuillaume Nault		echo "SKIP: iproute2 too old; tc-flower produces invalid json output for extended MPLS filters"
1167844ec21SPo-Hsu Lin		return $ksft_skip
117c09bfd9aSGuillaume Nault	fi
118c09bfd9aSGuillaume Nault}
119c09bfd9aSGuillaume Nault
1207f333cbfSJiri Pirkocheck_tc_shblock_support()
1217f333cbfSJiri Pirko{
122198979beSDavid Ahern	tc filter help 2>&1 | grep block &> /dev/null
123198979beSDavid Ahern	if [[ $? -ne 0 ]]; then
124198979beSDavid Ahern		echo "SKIP: iproute2 too old; tc is missing shared block support"
1257844ec21SPo-Hsu Lin		exit $ksft_skip
126198979beSDavid Ahern	fi
127198979beSDavid Ahern}
128198979beSDavid Ahern
1292d73c887SJiri Pirkocheck_tc_chain_support()
1302d73c887SJiri Pirko{
1312d73c887SJiri Pirko	tc help 2>&1|grep chain &> /dev/null
1322d73c887SJiri Pirko	if [[ $? -ne 0 ]]; then
1332d73c887SJiri Pirko		echo "SKIP: iproute2 too old; tc is missing chain support"
1347844ec21SPo-Hsu Lin		exit $ksft_skip
1352d73c887SJiri Pirko	fi
1362d73c887SJiri Pirko}
1372d73c887SJiri Pirko
138ee4848acSJiri Pirkocheck_tc_action_hw_stats_support()
139ee4848acSJiri Pirko{
140ee4848acSJiri Pirko	tc actions help 2>&1 | grep -q hw_stats
141ee4848acSJiri Pirko	if [[ $? -ne 0 ]]; then
142ee4848acSJiri Pirko		echo "SKIP: iproute2 too old; tc is missing action hw_stats support"
1437844ec21SPo-Hsu Lin		exit $ksft_skip
144ee4848acSJiri Pirko	fi
145ee4848acSJiri Pirko}
146ee4848acSJiri Pirko
147e6991384SVladimir Olteancheck_tc_fp_support()
148e6991384SVladimir Oltean{
149e6991384SVladimir Oltean	tc qdisc add dev lo mqprio help 2>&1 | grep -q "fp "
150e6991384SVladimir Oltean	if [[ $? -ne 0 ]]; then
151e6991384SVladimir Oltean		echo "SKIP: iproute2 too old; tc is missing frame preemption support"
152e6991384SVladimir Oltean		exit $ksft_skip
153e6991384SVladimir Oltean	fi
154e6991384SVladimir Oltean}
155e6991384SVladimir Oltean
156f72e2f48SDanielle Ratsoncheck_ethtool_lanes_support()
157f72e2f48SDanielle Ratson{
158f72e2f48SDanielle Ratson	ethtool --help 2>&1| grep lanes &> /dev/null
159f72e2f48SDanielle Ratson	if [[ $? -ne 0 ]]; then
160f72e2f48SDanielle Ratson		echo "SKIP: ethtool too old; it is missing lanes support"
1617844ec21SPo-Hsu Lin		exit $ksft_skip
162f72e2f48SDanielle Ratson	fi
163f72e2f48SDanielle Ratson}
164f72e2f48SDanielle Ratson
165e6991384SVladimir Olteancheck_ethtool_mm_support()
166e6991384SVladimir Oltean{
167e6991384SVladimir Oltean	ethtool --help 2>&1| grep -- '--show-mm' &> /dev/null
168e6991384SVladimir Oltean	if [[ $? -ne 0 ]]; then
169e6991384SVladimir Oltean		echo "SKIP: ethtool too old; it is missing MAC Merge layer support"
170e6991384SVladimir Oltean		exit $ksft_skip
171e6991384SVladimir Oltean	fi
172e6991384SVladimir Oltean}
173e6991384SVladimir Oltean
174b2b681a4SHans Schultzcheck_locked_port_support()
175b2b681a4SHans Schultz{
176b2b681a4SHans Schultz	if ! bridge -d link show | grep -q " locked"; then
177b2b681a4SHans Schultz		echo "SKIP: iproute2 too old; Locked port feature not supported."
178b2b681a4SHans Schultz		return $ksft_skip
179b2b681a4SHans Schultz	fi
180b2b681a4SHans Schultz}
181b2b681a4SHans Schultz
1824a331d34SHans J. Schultzcheck_port_mab_support()
1834a331d34SHans J. Schultz{
1844a331d34SHans J. Schultz	if ! bridge -d link show | grep -q "mab"; then
1854a331d34SHans J. Schultz		echo "SKIP: iproute2 too old; MacAuth feature not supported."
1864a331d34SHans J. Schultz		return $ksft_skip
1874a331d34SHans J. Schultz	fi
1884a331d34SHans J. Schultz}
1894a331d34SHans J. Schultz
19066e13186SIdo Schimmelskip_on_veth()
19166e13186SIdo Schimmel{
19266e13186SIdo Schimmel	local kind=$(ip -j -d link show dev ${NETIFS[p1]} |
19366e13186SIdo Schimmel		jq -r '.[].linkinfo.info_kind')
19466e13186SIdo Schimmel
19566e13186SIdo Schimmel	if [[ $kind == veth ]]; then
19666e13186SIdo Schimmel		echo "SKIP: Test cannot be run with veth pairs"
19766e13186SIdo Schimmel		exit $ksft_skip
19866e13186SIdo Schimmel	fi
19966e13186SIdo Schimmel}
20066e13186SIdo Schimmel
20173bae673SIdo Schimmelif [[ "$(id -u)" -ne 0 ]]; then
20273bae673SIdo Schimmel	echo "SKIP: need root privileges"
2037844ec21SPo-Hsu Lin	exit $ksft_skip
20473bae673SIdo Schimmelfi
20573bae673SIdo Schimmel
206198979beSDavid Ahernif [[ "$CHECK_TC" = "yes" ]]; then
207198979beSDavid Ahern	check_tc_version
2084908e24bSJiri Pirkofi
2094908e24bSJiri Pirko
210e094574fSPetr Machatarequire_command()
211e094574fSPetr Machata{
212e094574fSPetr Machata	local cmd=$1; shift
21373bae673SIdo Schimmel
214e094574fSPetr Machata	if [[ ! -x "$(command -v "$cmd")" ]]; then
215e094574fSPetr Machata		echo "SKIP: $cmd not installed"
2167844ec21SPo-Hsu Lin		exit $ksft_skip
217d4deb014SIdo Schimmel	fi
218e094574fSPetr Machata}
219e094574fSPetr Machata
220d70b51f2SVladimir Olteanif [[ "$REQUIRE_JQ" = "yes" ]]; then
221e094574fSPetr Machata	require_command jq
222d70b51f2SVladimir Olteanfi
223d70b51f2SVladimir Olteanif [[ "$REQUIRE_MZ" = "yes" ]]; then
224e094574fSPetr Machata	require_command $MZ
225d70b51f2SVladimir Olteanfi
226f23cddc7SVladimir Olteanif [[ "$REQUIRE_MTOOLS" = "yes" ]]; then
227f23cddc7SVladimir Oltean	# https://github.com/vladimiroltean/mtools/
228f23cddc7SVladimir Oltean	# patched for IPv6 support
229f23cddc7SVladimir Oltean	require_command msend
230f23cddc7SVladimir Oltean	require_command mreceive
231f23cddc7SVladimir Olteanfi
232d4deb014SIdo Schimmel
23373bae673SIdo Schimmelif [[ ! -v NUM_NETIFS ]]; then
23473bae673SIdo Schimmel	echo "SKIP: importer does not define \"NUM_NETIFS\""
2357844ec21SPo-Hsu Lin	exit $ksft_skip
23673bae673SIdo Schimmelfi
23773bae673SIdo Schimmel
23873bae673SIdo Schimmel##############################################################################
239781fe631SJiri Pirko# Command line options handling
240781fe631SJiri Pirko
241781fe631SJiri Pirkocount=0
242781fe631SJiri Pirko
243781fe631SJiri Pirkowhile [[ $# -gt 0 ]]; do
244781fe631SJiri Pirko	if [[ "$count" -eq "0" ]]; then
245781fe631SJiri Pirko		unset NETIFS
246781fe631SJiri Pirko		declare -A NETIFS
247781fe631SJiri Pirko	fi
248781fe631SJiri Pirko	count=$((count + 1))
249781fe631SJiri Pirko	NETIFS[p$count]="$1"
250781fe631SJiri Pirko	shift
251781fe631SJiri Pirkodone
252781fe631SJiri Pirko
253781fe631SJiri Pirko##############################################################################
25473bae673SIdo Schimmel# Network interfaces configuration
25573bae673SIdo Schimmel
256190f887cSDavid Aherncreate_netif_veth()
257190f887cSDavid Ahern{
258190f887cSDavid Ahern	local i
259190f887cSDavid Ahern
260601bc1c1SPetr Machata	for ((i = 1; i <= NUM_NETIFS; ++i)); do
261190f887cSDavid Ahern		local j=$((i+1))
262190f887cSDavid Ahern
263d72c83b1SIdo Schimmel		if [ -z ${NETIFS[p$i]} ]; then
264d72c83b1SIdo Schimmel			echo "SKIP: Cannot create interface. Name not specified"
265d72c83b1SIdo Schimmel			exit $ksft_skip
266d72c83b1SIdo Schimmel		fi
267d72c83b1SIdo Schimmel
268190f887cSDavid Ahern		ip link show dev ${NETIFS[p$i]} &> /dev/null
269190f887cSDavid Ahern		if [[ $? -ne 0 ]]; then
270190f887cSDavid Ahern			ip link add ${NETIFS[p$i]} type veth \
271190f887cSDavid Ahern				peer name ${NETIFS[p$j]}
272190f887cSDavid Ahern			if [[ $? -ne 0 ]]; then
273190f887cSDavid Ahern				echo "Failed to create netif"
274190f887cSDavid Ahern				exit 1
275190f887cSDavid Ahern			fi
276190f887cSDavid Ahern		fi
277190f887cSDavid Ahern		i=$j
278190f887cSDavid Ahern	done
279190f887cSDavid Ahern}
280190f887cSDavid Ahern
281190f887cSDavid Aherncreate_netif()
282190f887cSDavid Ahern{
283190f887cSDavid Ahern	case "$NETIF_TYPE" in
284190f887cSDavid Ahern	veth) create_netif_veth
285190f887cSDavid Ahern	      ;;
286190f887cSDavid Ahern	*) echo "Can not create interfaces of type \'$NETIF_TYPE\'"
287190f887cSDavid Ahern	   exit 1
288190f887cSDavid Ahern	   ;;
289190f887cSDavid Ahern	esac
290190f887cSDavid Ahern}
291190f887cSDavid Ahern
292b343734eSVladimir Olteandeclare -A MAC_ADDR_ORIG
293b343734eSVladimir Olteanmac_addr_prepare()
294b343734eSVladimir Oltean{
295b343734eSVladimir Oltean	local new_addr=
296b343734eSVladimir Oltean	local dev=
297b343734eSVladimir Oltean
298b343734eSVladimir Oltean	for ((i = 1; i <= NUM_NETIFS; ++i)); do
299b343734eSVladimir Oltean		dev=${NETIFS[p$i]}
300b343734eSVladimir Oltean		new_addr=$(printf "00:01:02:03:04:%02x" $i)
301b343734eSVladimir Oltean
302b343734eSVladimir Oltean		MAC_ADDR_ORIG["$dev"]=$(ip -j link show dev $dev | jq -e '.[].address')
303b343734eSVladimir Oltean		# Strip quotes
304b343734eSVladimir Oltean		MAC_ADDR_ORIG["$dev"]=${MAC_ADDR_ORIG["$dev"]//\"/}
305b343734eSVladimir Oltean		ip link set dev $dev address $new_addr
306b343734eSVladimir Oltean	done
307b343734eSVladimir Oltean}
308b343734eSVladimir Oltean
309b343734eSVladimir Olteanmac_addr_restore()
310b343734eSVladimir Oltean{
311b343734eSVladimir Oltean	local dev=
312b343734eSVladimir Oltean
313b343734eSVladimir Oltean	for ((i = 1; i <= NUM_NETIFS; ++i)); do
314b343734eSVladimir Oltean		dev=${NETIFS[p$i]}
315b343734eSVladimir Oltean		ip link set dev $dev address ${MAC_ADDR_ORIG["$dev"]}
316b343734eSVladimir Oltean	done
317b343734eSVladimir Oltean}
318b343734eSVladimir Oltean
319190f887cSDavid Ahernif [[ "$NETIF_CREATE" = "yes" ]]; then
320190f887cSDavid Ahern	create_netif
321190f887cSDavid Ahernfi
322190f887cSDavid Ahern
323b343734eSVladimir Olteanif [[ "$STABLE_MAC_ADDRS" = "yes" ]]; then
324b343734eSVladimir Oltean	mac_addr_prepare
325b343734eSVladimir Olteanfi
326b343734eSVladimir Oltean
327601bc1c1SPetr Machatafor ((i = 1; i <= NUM_NETIFS; ++i)); do
32873bae673SIdo Schimmel	ip link show dev ${NETIFS[p$i]} &> /dev/null
32973bae673SIdo Schimmel	if [[ $? -ne 0 ]]; then
33073bae673SIdo Schimmel		echo "SKIP: could not find all required interfaces"
3317844ec21SPo-Hsu Lin		exit $ksft_skip
33273bae673SIdo Schimmel	fi
33373bae673SIdo Schimmeldone
33473bae673SIdo Schimmel
33573bae673SIdo Schimmel##############################################################################
33673bae673SIdo Schimmel# Helpers
33773bae673SIdo Schimmel
33873bae673SIdo Schimmel# Exit status to return at the end. Set in case one of the tests fails.
33973bae673SIdo SchimmelEXIT_STATUS=0
34073bae673SIdo Schimmel# Per-test return value. Clear at the beginning of each test.
34173bae673SIdo SchimmelRET=0
34273bae673SIdo Schimmel
34373bae673SIdo Schimmelcheck_err()
34473bae673SIdo Schimmel{
34573bae673SIdo Schimmel	local err=$1
34673bae673SIdo Schimmel	local msg=$2
34773bae673SIdo Schimmel
34873bae673SIdo Schimmel	if [[ $RET -eq 0 && $err -ne 0 ]]; then
34973bae673SIdo Schimmel		RET=$err
35073bae673SIdo Schimmel		retmsg=$msg
35173bae673SIdo Schimmel	fi
35273bae673SIdo Schimmel}
35373bae673SIdo Schimmel
35473bae673SIdo Schimmelcheck_fail()
35573bae673SIdo Schimmel{
35673bae673SIdo Schimmel	local err=$1
35773bae673SIdo Schimmel	local msg=$2
35873bae673SIdo Schimmel
35973bae673SIdo Schimmel	if [[ $RET -eq 0 && $err -eq 0 ]]; then
36073bae673SIdo Schimmel		RET=1
36173bae673SIdo Schimmel		retmsg=$msg
36273bae673SIdo Schimmel	fi
36373bae673SIdo Schimmel}
36473bae673SIdo Schimmel
36596fa91d2SPetr Machatacheck_err_fail()
36696fa91d2SPetr Machata{
36796fa91d2SPetr Machata	local should_fail=$1; shift
36896fa91d2SPetr Machata	local err=$1; shift
36996fa91d2SPetr Machata	local what=$1; shift
37096fa91d2SPetr Machata
37196fa91d2SPetr Machata	if ((should_fail)); then
37296fa91d2SPetr Machata		check_fail $err "$what succeeded, but should have failed"
37396fa91d2SPetr Machata	else
37496fa91d2SPetr Machata		check_err $err "$what failed"
37596fa91d2SPetr Machata	fi
37696fa91d2SPetr Machata}
37796fa91d2SPetr Machata
37873bae673SIdo Schimmellog_test()
37973bae673SIdo Schimmel{
38073bae673SIdo Schimmel	local test_name=$1
38173bae673SIdo Schimmel	local opt_str=$2
38273bae673SIdo Schimmel
38373bae673SIdo Schimmel	if [[ $# -eq 2 ]]; then
38473bae673SIdo Schimmel		opt_str="($opt_str)"
38573bae673SIdo Schimmel	fi
38673bae673SIdo Schimmel
38773bae673SIdo Schimmel	if [[ $RET -ne 0 ]]; then
38873bae673SIdo Schimmel		EXIT_STATUS=1
38973bae673SIdo Schimmel		printf "TEST: %-60s  [FAIL]\n" "$test_name $opt_str"
39073bae673SIdo Schimmel		if [[ ! -z "$retmsg" ]]; then
39173bae673SIdo Schimmel			printf "\t%s\n" "$retmsg"
39273bae673SIdo Schimmel		fi
39373bae673SIdo Schimmel		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
39473bae673SIdo Schimmel			echo "Hit enter to continue, 'q' to quit"
39573bae673SIdo Schimmel			read a
39673bae673SIdo Schimmel			[ "$a" = "q" ] && exit 1
39773bae673SIdo Schimmel		fi
39873bae673SIdo Schimmel		return 1
39973bae673SIdo Schimmel	fi
40073bae673SIdo Schimmel
4013cab0de9SIdo Schimmel	printf "TEST: %-60s  [ OK ]\n" "$test_name $opt_str"
40273bae673SIdo Schimmel	return 0
40373bae673SIdo Schimmel}
40473bae673SIdo Schimmel
405b8bfafe4SPetr Machatalog_test_skip()
406b8bfafe4SPetr Machata{
407b8bfafe4SPetr Machata	local test_name=$1
408b8bfafe4SPetr Machata	local opt_str=$2
409b8bfafe4SPetr Machata
410b8bfafe4SPetr Machata	printf "TEST: %-60s  [SKIP]\n" "$test_name $opt_str"
411b8bfafe4SPetr Machata	return 0
412b8bfafe4SPetr Machata}
413b8bfafe4SPetr Machata
4143d578d87SIdo Schimmellog_info()
4153d578d87SIdo Schimmel{
4163d578d87SIdo Schimmel	local msg=$1
4173d578d87SIdo Schimmel
4183d578d87SIdo Schimmel	echo "INFO: $msg"
4193d578d87SIdo Schimmel}
4203d578d87SIdo Schimmel
42105ef614cSDanielle Ratsonnot()
42205ef614cSDanielle Ratson{
42305ef614cSDanielle Ratson	"$@"
42405ef614cSDanielle Ratson	[[ $? != 0 ]]
42505ef614cSDanielle Ratson}
42605ef614cSDanielle Ratson
427f72e2f48SDanielle Ratsonget_max()
428f72e2f48SDanielle Ratson{
429f72e2f48SDanielle Ratson	local arr=("$@")
430f72e2f48SDanielle Ratson
431f72e2f48SDanielle Ratson	max=${arr[0]}
432f72e2f48SDanielle Ratson	for cur in ${arr[@]}; do
433f72e2f48SDanielle Ratson		if [[ $cur -gt $max ]]; then
434f72e2f48SDanielle Ratson			max=$cur
435f72e2f48SDanielle Ratson		fi
436f72e2f48SDanielle Ratson	done
437f72e2f48SDanielle Ratson
438f72e2f48SDanielle Ratson	echo $max
439f72e2f48SDanielle Ratson}
440f72e2f48SDanielle Ratson
44105ef614cSDanielle Ratsongrep_bridge_fdb()
44205ef614cSDanielle Ratson{
44305ef614cSDanielle Ratson	local addr=$1; shift
44405ef614cSDanielle Ratson	local word
44505ef614cSDanielle Ratson	local flag
44605ef614cSDanielle Ratson
44705ef614cSDanielle Ratson	if [ "$1" == "self" ] || [ "$1" == "master" ]; then
44805ef614cSDanielle Ratson		word=$1; shift
44905ef614cSDanielle Ratson		if [ "$1" == "-v" ]; then
45005ef614cSDanielle Ratson			flag=$1; shift
45105ef614cSDanielle Ratson		fi
45205ef614cSDanielle Ratson	fi
45305ef614cSDanielle Ratson
45405ef614cSDanielle Ratson	$@ | grep $addr | grep $flag "$word"
45505ef614cSDanielle Ratson}
45605ef614cSDanielle Ratson
457f72e2f48SDanielle Ratsonwait_for_port_up()
458f72e2f48SDanielle Ratson{
459f72e2f48SDanielle Ratson	"$@" | grep -q "Link detected: yes"
460f72e2f48SDanielle Ratson}
461f72e2f48SDanielle Ratson
4620c22f993SDanielle Ratsonwait_for_offload()
4630c22f993SDanielle Ratson{
4640c22f993SDanielle Ratson	"$@" | grep -q offload
4650c22f993SDanielle Ratson}
4660c22f993SDanielle Ratson
467ffd3e9b0SIdo Schimmelwait_for_trap()
468ffd3e9b0SIdo Schimmel{
469ffd3e9b0SIdo Schimmel	"$@" | grep -q trap
470ffd3e9b0SIdo Schimmel}
471ffd3e9b0SIdo Schimmel
4724121d947SPetr Machatauntil_counter_is()
4734121d947SPetr Machata{
474844f0556SPetr Machata	local expr=$1; shift
4754121d947SPetr Machata	local current=$("$@")
4764121d947SPetr Machata
4774121d947SPetr Machata	echo $((current))
478844f0556SPetr Machata	((current $expr))
4794121d947SPetr Machata}
4804121d947SPetr Machata
4814121d947SPetr Machatabusywait_for_counter()
4824121d947SPetr Machata{
4834121d947SPetr Machata	local timeout=$1; shift
4844121d947SPetr Machata	local delta=$1; shift
4854121d947SPetr Machata
4864121d947SPetr Machata	local base=$("$@")
487844f0556SPetr Machata	busywait "$timeout" until_counter_is ">= $((base + delta))" "$@"
4884121d947SPetr Machata}
4894121d947SPetr Machata
490010079baSPetr Machatasetup_wait_dev()
49173bae673SIdo Schimmel{
492010079baSPetr Machata	local dev=$1; shift
4938f72a9cfSAmit Cohen	local wait_time=${1:-$WAIT_TIME}; shift
494010079baSPetr Machata
4958f72a9cfSAmit Cohen	setup_wait_dev_with_timeout "$dev" $INTERFACE_TIMEOUT $wait_time
4968f72a9cfSAmit Cohen
4978f72a9cfSAmit Cohen	if (($?)); then
4988f72a9cfSAmit Cohen		check_err 1
4998f72a9cfSAmit Cohen		log_test setup_wait_dev ": Interface $dev does not come up."
5008f72a9cfSAmit Cohen		exit 1
5018f72a9cfSAmit Cohen	fi
5028f72a9cfSAmit Cohen}
5038f72a9cfSAmit Cohen
5048f72a9cfSAmit Cohensetup_wait_dev_with_timeout()
5058f72a9cfSAmit Cohen{
5068f72a9cfSAmit Cohen	local dev=$1; shift
5078f72a9cfSAmit Cohen	local max_iterations=${1:-$WAIT_TIMEOUT}; shift
5088f72a9cfSAmit Cohen	local wait_time=${1:-$WAIT_TIME}; shift
5098f72a9cfSAmit Cohen	local i
5108f72a9cfSAmit Cohen
5118f72a9cfSAmit Cohen	for ((i = 1; i <= $max_iterations; ++i)); do
512010079baSPetr Machata		ip link show dev $dev up \
51373bae673SIdo Schimmel			| grep 'state UP' &> /dev/null
51473bae673SIdo Schimmel		if [[ $? -ne 0 ]]; then
51573bae673SIdo Schimmel			sleep 1
51673bae673SIdo Schimmel		else
5178f72a9cfSAmit Cohen			sleep $wait_time
5188f72a9cfSAmit Cohen			return 0
51973bae673SIdo Schimmel		fi
52073bae673SIdo Schimmel	done
5218f72a9cfSAmit Cohen
5228f72a9cfSAmit Cohen	return 1
523010079baSPetr Machata}
524010079baSPetr Machata
525010079baSPetr Machatasetup_wait()
526010079baSPetr Machata{
52768d9cea5SPetr Machata	local num_netifs=${1:-$NUM_NETIFS}
5288f72a9cfSAmit Cohen	local i
52968d9cea5SPetr Machata
53068d9cea5SPetr Machata	for ((i = 1; i <= num_netifs; ++i)); do
5318f72a9cfSAmit Cohen		setup_wait_dev ${NETIFS[p$i]} 0
53273bae673SIdo Schimmel	done
53373bae673SIdo Schimmel
53473bae673SIdo Schimmel	# Make sure links are ready.
53573bae673SIdo Schimmel	sleep $WAIT_TIME
53673bae673SIdo Schimmel}
53773bae673SIdo Schimmel
538d87e5edbSJiri Pirkocmd_jq()
539d87e5edbSJiri Pirko{
540d87e5edbSJiri Pirko	local cmd=$1
541d87e5edbSJiri Pirko	local jq_exp=$2
542c04d71b5SJiri Pirko	local jq_opts=$3
543d87e5edbSJiri Pirko	local ret
544d87e5edbSJiri Pirko	local output
545d87e5edbSJiri Pirko
546d87e5edbSJiri Pirko	output="$($cmd)"
547d87e5edbSJiri Pirko	# it the command fails, return error right away
548d87e5edbSJiri Pirko	ret=$?
549d87e5edbSJiri Pirko	if [[ $ret -ne 0 ]]; then
550d87e5edbSJiri Pirko		return $ret
551d87e5edbSJiri Pirko	fi
552c04d71b5SJiri Pirko	output=$(echo $output | jq -r $jq_opts "$jq_exp")
553c04d71b5SJiri Pirko	ret=$?
554c04d71b5SJiri Pirko	if [[ $ret -ne 0 ]]; then
555c04d71b5SJiri Pirko		return $ret
556c04d71b5SJiri Pirko	fi
557d87e5edbSJiri Pirko	echo $output
558d87e5edbSJiri Pirko	# return success only in case of non-empty output
559d87e5edbSJiri Pirko	[ ! -z "$output" ]
560d87e5edbSJiri Pirko}
561d87e5edbSJiri Pirko
56273bae673SIdo Schimmelpre_cleanup()
56373bae673SIdo Schimmel{
56473bae673SIdo Schimmel	if [ "${PAUSE_ON_CLEANUP}" = "yes" ]; then
56573bae673SIdo Schimmel		echo "Pausing before cleanup, hit any key to continue"
56673bae673SIdo Schimmel		read
56773bae673SIdo Schimmel	fi
568b343734eSVladimir Oltean
569b343734eSVladimir Oltean	if [[ "$STABLE_MAC_ADDRS" = "yes" ]]; then
570b343734eSVladimir Oltean		mac_addr_restore
571b343734eSVladimir Oltean	fi
57273bae673SIdo Schimmel}
57373bae673SIdo Schimmel
57473bae673SIdo Schimmelvrf_prepare()
57573bae673SIdo Schimmel{
57673bae673SIdo Schimmel	ip -4 rule add pref 32765 table local
57773bae673SIdo Schimmel	ip -4 rule del pref 0
57873bae673SIdo Schimmel	ip -6 rule add pref 32765 table local
57973bae673SIdo Schimmel	ip -6 rule del pref 0
58073bae673SIdo Schimmel}
58173bae673SIdo Schimmel
58273bae673SIdo Schimmelvrf_cleanup()
58373bae673SIdo Schimmel{
58473bae673SIdo Schimmel	ip -6 rule add pref 0 table local
58573bae673SIdo Schimmel	ip -6 rule del pref 32765
58673bae673SIdo Schimmel	ip -4 rule add pref 0 table local
58773bae673SIdo Schimmel	ip -4 rule del pref 32765
58873bae673SIdo Schimmel}
58973bae673SIdo Schimmel
59073bae673SIdo Schimmel__last_tb_id=0
59173bae673SIdo Schimmeldeclare -A __TB_IDS
59273bae673SIdo Schimmel
59373bae673SIdo Schimmel__vrf_td_id_assign()
59473bae673SIdo Schimmel{
59573bae673SIdo Schimmel	local vrf_name=$1
59673bae673SIdo Schimmel
59773bae673SIdo Schimmel	__last_tb_id=$((__last_tb_id + 1))
59873bae673SIdo Schimmel	__TB_IDS[$vrf_name]=$__last_tb_id
59973bae673SIdo Schimmel	return $__last_tb_id
60073bae673SIdo Schimmel}
60173bae673SIdo Schimmel
60273bae673SIdo Schimmel__vrf_td_id_lookup()
60373bae673SIdo Schimmel{
60473bae673SIdo Schimmel	local vrf_name=$1
60573bae673SIdo Schimmel
60673bae673SIdo Schimmel	return ${__TB_IDS[$vrf_name]}
60773bae673SIdo Schimmel}
60873bae673SIdo Schimmel
60973bae673SIdo Schimmelvrf_create()
61073bae673SIdo Schimmel{
61173bae673SIdo Schimmel	local vrf_name=$1
61273bae673SIdo Schimmel	local tb_id
61373bae673SIdo Schimmel
61473bae673SIdo Schimmel	__vrf_td_id_assign $vrf_name
61573bae673SIdo Schimmel	tb_id=$?
61673bae673SIdo Schimmel
61773bae673SIdo Schimmel	ip link add dev $vrf_name type vrf table $tb_id
61873bae673SIdo Schimmel	ip -4 route add table $tb_id unreachable default metric 4278198272
61973bae673SIdo Schimmel	ip -6 route add table $tb_id unreachable default metric 4278198272
62073bae673SIdo Schimmel}
62173bae673SIdo Schimmel
62273bae673SIdo Schimmelvrf_destroy()
62373bae673SIdo Schimmel{
62473bae673SIdo Schimmel	local vrf_name=$1
62573bae673SIdo Schimmel	local tb_id
62673bae673SIdo Schimmel
62773bae673SIdo Schimmel	__vrf_td_id_lookup $vrf_name
62873bae673SIdo Schimmel	tb_id=$?
62973bae673SIdo Schimmel
63073bae673SIdo Schimmel	ip -6 route del table $tb_id unreachable default metric 4278198272
63173bae673SIdo Schimmel	ip -4 route del table $tb_id unreachable default metric 4278198272
63273bae673SIdo Schimmel	ip link del dev $vrf_name
63373bae673SIdo Schimmel}
63473bae673SIdo Schimmel
63573bae673SIdo Schimmel__addr_add_del()
63673bae673SIdo Schimmel{
63773bae673SIdo Schimmel	local if_name=$1
63873bae673SIdo Schimmel	local add_del=$2
63973bae673SIdo Schimmel	local array
64073bae673SIdo Schimmel
64173bae673SIdo Schimmel	shift
64273bae673SIdo Schimmel	shift
64373bae673SIdo Schimmel	array=("${@}")
64473bae673SIdo Schimmel
64573bae673SIdo Schimmel	for addrstr in "${array[@]}"; do
64673bae673SIdo Schimmel		ip address $add_del $addrstr dev $if_name
64773bae673SIdo Schimmel	done
64873bae673SIdo Schimmel}
64973bae673SIdo Schimmel
6503368b223SPetr Machata__simple_if_init()
6513368b223SPetr Machata{
6523368b223SPetr Machata	local if_name=$1; shift
6533368b223SPetr Machata	local vrf_name=$1; shift
6543368b223SPetr Machata	local addrs=("${@}")
6553368b223SPetr Machata
6563368b223SPetr Machata	ip link set dev $if_name master $vrf_name
6573368b223SPetr Machata	ip link set dev $if_name up
6583368b223SPetr Machata
6593368b223SPetr Machata	__addr_add_del $if_name add "${addrs[@]}"
6603368b223SPetr Machata}
6613368b223SPetr Machata
6623368b223SPetr Machata__simple_if_fini()
6633368b223SPetr Machata{
6643368b223SPetr Machata	local if_name=$1; shift
6653368b223SPetr Machata	local addrs=("${@}")
6663368b223SPetr Machata
6673368b223SPetr Machata	__addr_add_del $if_name del "${addrs[@]}"
6683368b223SPetr Machata
6693368b223SPetr Machata	ip link set dev $if_name down
6703368b223SPetr Machata	ip link set dev $if_name nomaster
6713368b223SPetr Machata}
6723368b223SPetr Machata
67373bae673SIdo Schimmelsimple_if_init()
67473bae673SIdo Schimmel{
67573bae673SIdo Schimmel	local if_name=$1
67673bae673SIdo Schimmel	local vrf_name
67773bae673SIdo Schimmel	local array
67873bae673SIdo Schimmel
67973bae673SIdo Schimmel	shift
68073bae673SIdo Schimmel	vrf_name=v$if_name
68173bae673SIdo Schimmel	array=("${@}")
68273bae673SIdo Schimmel
68373bae673SIdo Schimmel	vrf_create $vrf_name
68473bae673SIdo Schimmel	ip link set dev $vrf_name up
6853368b223SPetr Machata	__simple_if_init $if_name $vrf_name "${array[@]}"
68673bae673SIdo Schimmel}
68773bae673SIdo Schimmel
68873bae673SIdo Schimmelsimple_if_fini()
68973bae673SIdo Schimmel{
69073bae673SIdo Schimmel	local if_name=$1
69173bae673SIdo Schimmel	local vrf_name
69273bae673SIdo Schimmel	local array
69373bae673SIdo Schimmel
69473bae673SIdo Schimmel	shift
69573bae673SIdo Schimmel	vrf_name=v$if_name
69673bae673SIdo Schimmel	array=("${@}")
69773bae673SIdo Schimmel
6983368b223SPetr Machata	__simple_if_fini $if_name "${array[@]}"
69973bae673SIdo Schimmel	vrf_destroy $vrf_name
70073bae673SIdo Schimmel}
70173bae673SIdo Schimmel
7027d4cbae0SPetr Machatatunnel_create()
7037d4cbae0SPetr Machata{
7047d4cbae0SPetr Machata	local name=$1; shift
7057d4cbae0SPetr Machata	local type=$1; shift
7067d4cbae0SPetr Machata	local local=$1; shift
7077d4cbae0SPetr Machata	local remote=$1; shift
7087d4cbae0SPetr Machata
7097d4cbae0SPetr Machata	ip link add name $name type $type \
7107d4cbae0SPetr Machata	   local $local remote $remote "$@"
7117d4cbae0SPetr Machata	ip link set dev $name up
7127d4cbae0SPetr Machata}
7137d4cbae0SPetr Machata
7147d4cbae0SPetr Machatatunnel_destroy()
7157d4cbae0SPetr Machata{
7167d4cbae0SPetr Machata	local name=$1; shift
7177d4cbae0SPetr Machata
7187d4cbae0SPetr Machata	ip link del dev $name
7197d4cbae0SPetr Machata}
7207d4cbae0SPetr Machata
7210e7a504cSPetr Machatavlan_create()
7220e7a504cSPetr Machata{
7230e7a504cSPetr Machata	local if_name=$1; shift
7240e7a504cSPetr Machata	local vid=$1; shift
7250e7a504cSPetr Machata	local vrf=$1; shift
7260e7a504cSPetr Machata	local ips=("${@}")
7270e7a504cSPetr Machata	local name=$if_name.$vid
7280e7a504cSPetr Machata
7290e7a504cSPetr Machata	ip link add name $name link $if_name type vlan id $vid
7300e7a504cSPetr Machata	if [ "$vrf" != "" ]; then
7310e7a504cSPetr Machata		ip link set dev $name master $vrf
7320e7a504cSPetr Machata	fi
7330e7a504cSPetr Machata	ip link set dev $name up
7340e7a504cSPetr Machata	__addr_add_del $name add "${ips[@]}"
7350e7a504cSPetr Machata}
7360e7a504cSPetr Machata
7370e7a504cSPetr Machatavlan_destroy()
7380e7a504cSPetr Machata{
7390e7a504cSPetr Machata	local if_name=$1; shift
7400e7a504cSPetr Machata	local vid=$1; shift
7410e7a504cSPetr Machata	local name=$if_name.$vid
7420e7a504cSPetr Machata
7430e7a504cSPetr Machata	ip link del dev $name
7440e7a504cSPetr Machata}
7450e7a504cSPetr Machata
7469d9e6bdeSPetr Machatateam_create()
7479d9e6bdeSPetr Machata{
7489d9e6bdeSPetr Machata	local if_name=$1; shift
7499d9e6bdeSPetr Machata	local mode=$1; shift
7509d9e6bdeSPetr Machata
7519d9e6bdeSPetr Machata	require_command $TEAMD
7529d9e6bdeSPetr Machata	$TEAMD -t $if_name -d -c '{"runner": {"name": "'$mode'"}}'
7539d9e6bdeSPetr Machata	for slave in "$@"; do
7549d9e6bdeSPetr Machata		ip link set dev $slave down
7559d9e6bdeSPetr Machata		ip link set dev $slave master $if_name
7569d9e6bdeSPetr Machata		ip link set dev $slave up
7579d9e6bdeSPetr Machata	done
7589d9e6bdeSPetr Machata	ip link set dev $if_name up
7599d9e6bdeSPetr Machata}
7609d9e6bdeSPetr Machata
7619d9e6bdeSPetr Machatateam_destroy()
7629d9e6bdeSPetr Machata{
7639d9e6bdeSPetr Machata	local if_name=$1; shift
7649d9e6bdeSPetr Machata
7659d9e6bdeSPetr Machata	$TEAMD -t $if_name -k
7669d9e6bdeSPetr Machata}
7679d9e6bdeSPetr Machata
76873bae673SIdo Schimmelmaster_name_get()
76973bae673SIdo Schimmel{
77073bae673SIdo Schimmel	local if_name=$1
77173bae673SIdo Schimmel
77273bae673SIdo Schimmel	ip -j link show dev $if_name | jq -r '.[]["master"]'
77373bae673SIdo Schimmel}
77473bae673SIdo Schimmel
775d1038cd0SPetr Machatalink_stats_get()
776d1038cd0SPetr Machata{
777d1038cd0SPetr Machata	local if_name=$1; shift
778d1038cd0SPetr Machata	local dir=$1; shift
779d1038cd0SPetr Machata	local stat=$1; shift
780d1038cd0SPetr Machata
781d1038cd0SPetr Machata	ip -j -s link show dev $if_name \
782d1038cd0SPetr Machata		| jq '.[]["stats64"]["'$dir'"]["'$stat'"]'
783d1038cd0SPetr Machata}
784d1038cd0SPetr Machata
7853d578d87SIdo Schimmellink_stats_tx_packets_get()
7863d578d87SIdo Schimmel{
787d1038cd0SPetr Machata	link_stats_get $1 tx packets
788d1038cd0SPetr Machata}
7893d578d87SIdo Schimmel
790d1038cd0SPetr Machatalink_stats_rx_errors_get()
791d1038cd0SPetr Machata{
792d1038cd0SPetr Machata	link_stats_get $1 rx errors
7933d578d87SIdo Schimmel}
7943d578d87SIdo Schimmel
7957d4cbae0SPetr Machatatc_rule_stats_get()
7967d4cbae0SPetr Machata{
7977d4cbae0SPetr Machata	local dev=$1; shift
7987d4cbae0SPetr Machata	local pref=$1; shift
799a66d62d8SPetr Machata	local dir=$1; shift
800c143139bSPetr Machata	local selector=${1:-.packets}; shift
8017d4cbae0SPetr Machata
802a66d62d8SPetr Machata	tc -j -s filter show dev $dev ${dir:-ingress} pref $pref \
803c143139bSPetr Machata	    | jq ".[1].options.actions[].stats$selector"
8047d4cbae0SPetr Machata}
8057d4cbae0SPetr Machata
80684ea1f85SPetr Machatatc_rule_handle_stats_get()
80784ea1f85SPetr Machata{
80884ea1f85SPetr Machata	local id=$1; shift
80984ea1f85SPetr Machata	local handle=$1; shift
81084ea1f85SPetr Machata	local selector=${1:-.packets}; shift
811b6d1599fSHangbin Liu	local netns=${1:-""}; shift
81284ea1f85SPetr Machata
813b6d1599fSHangbin Liu	tc $netns -j -s filter show $id \
81484ea1f85SPetr Machata	    | jq ".[] | select(.options.handle == $handle) | \
81584ea1f85SPetr Machata		  .options.actions[0].stats$selector"
81684ea1f85SPetr Machata}
81784ea1f85SPetr Machata
8183136a369SPetr Machataethtool_stats_get()
8193136a369SPetr Machata{
8203136a369SPetr Machata	local dev=$1; shift
8213136a369SPetr Machata	local stat=$1; shift
8223136a369SPetr Machata
8233136a369SPetr Machata	ethtool -S $dev | grep "^ *$stat:" | head -n 1 | cut -d: -f2
8243136a369SPetr Machata}
8253136a369SPetr Machata
826b5bf7126SVladimir Olteanethtool_std_stats_get()
827b5bf7126SVladimir Oltean{
828b5bf7126SVladimir Oltean	local dev=$1; shift
829b5bf7126SVladimir Oltean	local grp=$1; shift
830b5bf7126SVladimir Oltean	local name=$1; shift
831b5bf7126SVladimir Oltean	local src=$1; shift
832b5bf7126SVladimir Oltean
833b5bf7126SVladimir Oltean	ethtool --json -S $dev --groups $grp -- --src $src | \
834b5bf7126SVladimir Oltean		jq '.[]."'"$grp"'"."'$name'"'
835b5bf7126SVladimir Oltean}
836b5bf7126SVladimir Oltean
8373de611b5SPetr Machataqdisc_stats_get()
8383de611b5SPetr Machata{
8393de611b5SPetr Machata	local dev=$1; shift
8403de611b5SPetr Machata	local handle=$1; shift
8413de611b5SPetr Machata	local selector=$1; shift
8423de611b5SPetr Machata
8433de611b5SPetr Machata	tc -j -s qdisc show dev "$dev" \
8443de611b5SPetr Machata	    | jq '.[] | select(.handle == "'"$handle"'") | '"$selector"
8453de611b5SPetr Machata}
8463de611b5SPetr Machata
847b9b72999SPetr Machataqdisc_parent_stats_get()
848b9b72999SPetr Machata{
849b9b72999SPetr Machata	local dev=$1; shift
850b9b72999SPetr Machata	local parent=$1; shift
851b9b72999SPetr Machata	local selector=$1; shift
852b9b72999SPetr Machata
853b9b72999SPetr Machata	tc -j -s qdisc show dev "$dev" invisible \
854b9b72999SPetr Machata	    | jq '.[] | select(.parent == "'"$parent"'") | '"$selector"
855b9b72999SPetr Machata}
856b9b72999SPetr Machata
8570857d6f8SStephen Suryaputraipv6_stats_get()
8580857d6f8SStephen Suryaputra{
8590857d6f8SStephen Suryaputra	local dev=$1; shift
8600857d6f8SStephen Suryaputra	local stat=$1; shift
8610857d6f8SStephen Suryaputra
8620857d6f8SStephen Suryaputra	cat /proc/net/dev_snmp6/$dev | grep "^$stat" | cut -f2
8630857d6f8SStephen Suryaputra}
8640857d6f8SStephen Suryaputra
86532fb67a3SPetr Machatahw_stats_get()
86632fb67a3SPetr Machata{
86732fb67a3SPetr Machata	local suite=$1; shift
86832fb67a3SPetr Machata	local if_name=$1; shift
86932fb67a3SPetr Machata	local dir=$1; shift
87032fb67a3SPetr Machata	local stat=$1; shift
87132fb67a3SPetr Machata
87232fb67a3SPetr Machata	ip -j stats show dev $if_name group offload subgroup $suite |
87332fb67a3SPetr Machata		jq ".[0].stats64.$dir.$stat"
87432fb67a3SPetr Machata}
87532fb67a3SPetr Machata
876adc6c7ecSPetr Machatahumanize()
877adc6c7ecSPetr Machata{
878adc6c7ecSPetr Machata	local speed=$1; shift
879adc6c7ecSPetr Machata
880adc6c7ecSPetr Machata	for unit in bps Kbps Mbps Gbps; do
881adc6c7ecSPetr Machata		if (($(echo "$speed < 1024" | bc))); then
882adc6c7ecSPetr Machata			break
883adc6c7ecSPetr Machata		fi
884adc6c7ecSPetr Machata
885adc6c7ecSPetr Machata		speed=$(echo "scale=1; $speed / 1024" | bc)
886adc6c7ecSPetr Machata	done
887adc6c7ecSPetr Machata
888adc6c7ecSPetr Machata	echo "$speed${unit}"
889adc6c7ecSPetr Machata}
890adc6c7ecSPetr Machata
891adc6c7ecSPetr Machatarate()
892adc6c7ecSPetr Machata{
893adc6c7ecSPetr Machata	local t0=$1; shift
894adc6c7ecSPetr Machata	local t1=$1; shift
895adc6c7ecSPetr Machata	local interval=$1; shift
896adc6c7ecSPetr Machata
897adc6c7ecSPetr Machata	echo $((8 * (t1 - t0) / interval))
898adc6c7ecSPetr Machata}
899adc6c7ecSPetr Machata
90053b61f29SBaowen Zhengpackets_rate()
90153b61f29SBaowen Zheng{
90253b61f29SBaowen Zheng	local t0=$1; shift
90353b61f29SBaowen Zheng	local t1=$1; shift
90453b61f29SBaowen Zheng	local interval=$1; shift
90553b61f29SBaowen Zheng
90653b61f29SBaowen Zheng	echo $(((t1 - t0) / interval))
90753b61f29SBaowen Zheng}
90853b61f29SBaowen Zheng
9094e4272d2SJiri Pirkomac_get()
9104e4272d2SJiri Pirko{
9114e4272d2SJiri Pirko	local if_name=$1
9124e4272d2SJiri Pirko
9134e4272d2SJiri Pirko	ip -j link show dev $if_name | jq -r '.[]["address"]'
9144e4272d2SJiri Pirko}
9154e4272d2SJiri Pirko
916a5114df6SVladimir Olteanipv6_lladdr_get()
917a5114df6SVladimir Oltean{
918a5114df6SVladimir Oltean	local if_name=$1
919a5114df6SVladimir Oltean
920a5114df6SVladimir Oltean	ip -j addr show dev $if_name | \
921a5114df6SVladimir Oltean		jq -r '.[]["addr_info"][] | select(.scope == "link").local' | \
922a5114df6SVladimir Oltean		head -1
923a5114df6SVladimir Oltean}
924a5114df6SVladimir Oltean
925d4deb014SIdo Schimmelbridge_ageing_time_get()
926d4deb014SIdo Schimmel{
927d4deb014SIdo Schimmel	local bridge=$1
928d4deb014SIdo Schimmel	local ageing_time
929d4deb014SIdo Schimmel
930d4deb014SIdo Schimmel	# Need to divide by 100 to convert to seconds.
931d4deb014SIdo Schimmel	ageing_time=$(ip -j -d link show dev $bridge \
932d4deb014SIdo Schimmel		      | jq '.[]["linkinfo"]["info_data"]["ageing_time"]')
933d4deb014SIdo Schimmel	echo $((ageing_time / 100))
934d4deb014SIdo Schimmel}
935d4deb014SIdo Schimmel
936f5ae5778SPetr Machatadeclare -A SYSCTL_ORIG
937f5ae5778SPetr Machatasysctl_set()
938f5ae5778SPetr Machata{
939f5ae5778SPetr Machata	local key=$1; shift
940f5ae5778SPetr Machata	local value=$1; shift
941f5ae5778SPetr Machata
942f5ae5778SPetr Machata	SYSCTL_ORIG[$key]=$(sysctl -n $key)
9433a082086SHangbin Liu	sysctl -qw $key="$value"
944f5ae5778SPetr Machata}
945f5ae5778SPetr Machata
946f5ae5778SPetr Machatasysctl_restore()
947f5ae5778SPetr Machata{
948f5ae5778SPetr Machata	local key=$1; shift
949f5ae5778SPetr Machata
9503a082086SHangbin Liu	sysctl -qw $key="${SYSCTL_ORIG[$key]}"
951f5ae5778SPetr Machata}
952f5ae5778SPetr Machata
9537b7bc875SIdo Schimmelforwarding_enable()
9547b7bc875SIdo Schimmel{
955d51d10aaSPetr Machata	sysctl_set net.ipv4.conf.all.forwarding 1
956d51d10aaSPetr Machata	sysctl_set net.ipv6.conf.all.forwarding 1
9577b7bc875SIdo Schimmel}
9587b7bc875SIdo Schimmel
9597b7bc875SIdo Schimmelforwarding_restore()
9607b7bc875SIdo Schimmel{
961d51d10aaSPetr Machata	sysctl_restore net.ipv6.conf.all.forwarding
962d51d10aaSPetr Machata	sysctl_restore net.ipv4.conf.all.forwarding
9637b7bc875SIdo Schimmel}
9647b7bc875SIdo Schimmel
965a381ed12SPetr Machatadeclare -A MTU_ORIG
966a381ed12SPetr Machatamtu_set()
967a381ed12SPetr Machata{
968a381ed12SPetr Machata	local dev=$1; shift
969a381ed12SPetr Machata	local mtu=$1; shift
970a381ed12SPetr Machata
971a381ed12SPetr Machata	MTU_ORIG["$dev"]=$(ip -j link show dev $dev | jq -e '.[].mtu')
972a381ed12SPetr Machata	ip link set dev $dev mtu $mtu
973a381ed12SPetr Machata}
974a381ed12SPetr Machata
975a381ed12SPetr Machatamtu_restore()
976a381ed12SPetr Machata{
977a381ed12SPetr Machata	local dev=$1; shift
978a381ed12SPetr Machata
979a381ed12SPetr Machata	ip link set dev $dev mtu ${MTU_ORIG["$dev"]}
980a381ed12SPetr Machata}
981a381ed12SPetr Machata
9822f19f212SJiri Pirkotc_offload_check()
9832f19f212SJiri Pirko{
98468d9cea5SPetr Machata	local num_netifs=${1:-$NUM_NETIFS}
98568d9cea5SPetr Machata
98668d9cea5SPetr Machata	for ((i = 1; i <= num_netifs; ++i)); do
9872f19f212SJiri Pirko		ethtool -k ${NETIFS[p$i]} \
9882f19f212SJiri Pirko			| grep "hw-tc-offload: on" &> /dev/null
9892f19f212SJiri Pirko		if [[ $? -ne 0 ]]; then
9902f19f212SJiri Pirko			return 1
9912f19f212SJiri Pirko		fi
9922f19f212SJiri Pirko	done
9932f19f212SJiri Pirko
9942f19f212SJiri Pirko	return 0
9952f19f212SJiri Pirko}
9962f19f212SJiri Pirko
99787c0c046SPetr Machatatrap_install()
9987d4cbae0SPetr Machata{
9997d4cbae0SPetr Machata	local dev=$1; shift
10007d4cbae0SPetr Machata	local direction=$1; shift
10017d4cbae0SPetr Machata
1002ac0fcadfSPetr Machata	# Some devices may not support or need in-hardware trapping of traffic
1003ac0fcadfSPetr Machata	# (e.g. the veth pairs that this library creates for non-existent
1004ac0fcadfSPetr Machata	# loopbacks). Use continue instead, so that there is a filter in there
1005ac0fcadfSPetr Machata	# (some tests check counters), and so that other filters are still
1006ac0fcadfSPetr Machata	# processed.
1007ac0fcadfSPetr Machata	tc filter add dev $dev $direction pref 1 \
1008ac0fcadfSPetr Machata		flower skip_sw action trap 2>/dev/null \
1009ac0fcadfSPetr Machata	    || tc filter add dev $dev $direction pref 1 \
1010ac0fcadfSPetr Machata		       flower action continue
101187c0c046SPetr Machata}
101287c0c046SPetr Machata
101387c0c046SPetr Machatatrap_uninstall()
101487c0c046SPetr Machata{
101587c0c046SPetr Machata	local dev=$1; shift
101687c0c046SPetr Machata	local direction=$1; shift
101787c0c046SPetr Machata
1018ac0fcadfSPetr Machata	tc filter del dev $dev $direction pref 1 flower
101987c0c046SPetr Machata}
102087c0c046SPetr Machata
102187c0c046SPetr Machataslow_path_trap_install()
102287c0c046SPetr Machata{
1023ac0fcadfSPetr Machata	# For slow-path testing, we need to install a trap to get to
1024ac0fcadfSPetr Machata	# slow path the packets that would otherwise be switched in HW.
102587c0c046SPetr Machata	if [ "${tcflags/skip_hw}" != "$tcflags" ]; then
102687c0c046SPetr Machata		trap_install "$@"
10277d4cbae0SPetr Machata	fi
10287d4cbae0SPetr Machata}
10297d4cbae0SPetr Machata
10307d4cbae0SPetr Machataslow_path_trap_uninstall()
10317d4cbae0SPetr Machata{
10327d4cbae0SPetr Machata	if [ "${tcflags/skip_hw}" != "$tcflags" ]; then
103387c0c046SPetr Machata		trap_uninstall "$@"
10347d4cbae0SPetr Machata	fi
10357d4cbae0SPetr Machata}
10367d4cbae0SPetr Machata
10377d4cbae0SPetr Machata__icmp_capture_add_del()
10387d4cbae0SPetr Machata{
10397d4cbae0SPetr Machata	local add_del=$1; shift
10407d4cbae0SPetr Machata	local pref=$1; shift
10417d4cbae0SPetr Machata	local vsuf=$1; shift
10427d4cbae0SPetr Machata	local tundev=$1; shift
10437d4cbae0SPetr Machata	local filter=$1; shift
10447d4cbae0SPetr Machata
10457d4cbae0SPetr Machata	tc filter $add_del dev "$tundev" ingress \
10467d4cbae0SPetr Machata	   proto ip$vsuf pref $pref \
10477d4cbae0SPetr Machata	   flower ip_proto icmp$vsuf $filter \
10487d4cbae0SPetr Machata	   action pass
10497d4cbae0SPetr Machata}
10507d4cbae0SPetr Machata
10517d4cbae0SPetr Machataicmp_capture_install()
10527d4cbae0SPetr Machata{
10537d4cbae0SPetr Machata	__icmp_capture_add_del add 100 "" "$@"
10547d4cbae0SPetr Machata}
10557d4cbae0SPetr Machata
10567d4cbae0SPetr Machataicmp_capture_uninstall()
10577d4cbae0SPetr Machata{
10587d4cbae0SPetr Machata	__icmp_capture_add_del del 100 "" "$@"
10597d4cbae0SPetr Machata}
10607d4cbae0SPetr Machata
10617d4cbae0SPetr Machataicmp6_capture_install()
10627d4cbae0SPetr Machata{
10637d4cbae0SPetr Machata	__icmp_capture_add_del add 100 v6 "$@"
10647d4cbae0SPetr Machata}
10657d4cbae0SPetr Machata
10667d4cbae0SPetr Machataicmp6_capture_uninstall()
10677d4cbae0SPetr Machata{
10687d4cbae0SPetr Machata	__icmp_capture_add_del del 100 v6 "$@"
10697d4cbae0SPetr Machata}
10707d4cbae0SPetr Machata
10712004a9bcSPetr Machata__vlan_capture_add_del()
10722004a9bcSPetr Machata{
10732004a9bcSPetr Machata	local add_del=$1; shift
10742004a9bcSPetr Machata	local pref=$1; shift
10752004a9bcSPetr Machata	local dev=$1; shift
10762004a9bcSPetr Machata	local filter=$1; shift
10772004a9bcSPetr Machata
10782004a9bcSPetr Machata	tc filter $add_del dev "$dev" ingress \
10792004a9bcSPetr Machata	   proto 802.1q pref $pref \
10802004a9bcSPetr Machata	   flower $filter \
10812004a9bcSPetr Machata	   action pass
10822004a9bcSPetr Machata}
10832004a9bcSPetr Machata
10842004a9bcSPetr Machatavlan_capture_install()
10852004a9bcSPetr Machata{
10862004a9bcSPetr Machata	__vlan_capture_add_del add 100 "$@"
10872004a9bcSPetr Machata}
10882004a9bcSPetr Machata
10892004a9bcSPetr Machatavlan_capture_uninstall()
10902004a9bcSPetr Machata{
10912004a9bcSPetr Machata	__vlan_capture_add_del del 100 "$@"
10922004a9bcSPetr Machata}
10932004a9bcSPetr Machata
1094cf608698SPetr Machata__dscp_capture_add_del()
1095cf608698SPetr Machata{
1096cf608698SPetr Machata	local add_del=$1; shift
1097cf608698SPetr Machata	local dev=$1; shift
1098cf608698SPetr Machata	local base=$1; shift
1099cf608698SPetr Machata	local dscp;
1100cf608698SPetr Machata
1101cf608698SPetr Machata	for prio in {0..7}; do
1102cf608698SPetr Machata		dscp=$((base + prio))
1103cf608698SPetr Machata		__icmp_capture_add_del $add_del $((dscp + 100)) "" $dev \
1104cf608698SPetr Machata				       "skip_hw ip_tos $((dscp << 2))"
1105cf608698SPetr Machata	done
1106cf608698SPetr Machata}
1107cf608698SPetr Machata
1108cf608698SPetr Machatadscp_capture_install()
1109cf608698SPetr Machata{
1110cf608698SPetr Machata	local dev=$1; shift
1111cf608698SPetr Machata	local base=$1; shift
1112cf608698SPetr Machata
1113cf608698SPetr Machata	__dscp_capture_add_del add $dev $base
1114cf608698SPetr Machata}
1115cf608698SPetr Machata
1116cf608698SPetr Machatadscp_capture_uninstall()
1117cf608698SPetr Machata{
1118cf608698SPetr Machata	local dev=$1; shift
1119cf608698SPetr Machata	local base=$1; shift
1120cf608698SPetr Machata
1121cf608698SPetr Machata	__dscp_capture_add_del del $dev $base
1122cf608698SPetr Machata}
1123cf608698SPetr Machata
1124cf608698SPetr Machatadscp_fetch_stats()
1125cf608698SPetr Machata{
1126cf608698SPetr Machata	local dev=$1; shift
1127cf608698SPetr Machata	local base=$1; shift
1128cf608698SPetr Machata
1129cf608698SPetr Machata	for prio in {0..7}; do
1130cf608698SPetr Machata		local dscp=$((base + prio))
1131cf608698SPetr Machata		local t=$(tc_rule_stats_get $dev $((dscp + 100)))
1132cf608698SPetr Machata		echo "[$dscp]=$t "
1133cf608698SPetr Machata	done
1134cf608698SPetr Machata}
1135cf608698SPetr Machata
11367d4cbae0SPetr Machatamatchall_sink_create()
11377d4cbae0SPetr Machata{
11387d4cbae0SPetr Machata	local dev=$1; shift
11397d4cbae0SPetr Machata
11407d4cbae0SPetr Machata	tc qdisc add dev $dev clsact
11417d4cbae0SPetr Machata	tc filter add dev $dev ingress \
11427d4cbae0SPetr Machata	   pref 10000 \
11437d4cbae0SPetr Machata	   matchall \
11447d4cbae0SPetr Machata	   action drop
11457d4cbae0SPetr Machata}
11467d4cbae0SPetr Machata
11470eb8053cSIdo Schimmeltests_run()
11480eb8053cSIdo Schimmel{
11490eb8053cSIdo Schimmel	local current_test
11500eb8053cSIdo Schimmel
11510eb8053cSIdo Schimmel	for current_test in ${TESTS:-$ALL_TESTS}; do
11520eb8053cSIdo Schimmel		$current_test
11530eb8053cSIdo Schimmel	done
11540eb8053cSIdo Schimmel}
11550eb8053cSIdo Schimmel
1156b2c47872SPetr Machatamultipath_eval()
1157b2c47872SPetr Machata{
1158b2c47872SPetr Machata	local desc="$1"
1159b2c47872SPetr Machata	local weight_rp12=$2
1160b2c47872SPetr Machata	local weight_rp13=$3
1161b2c47872SPetr Machata	local packets_rp12=$4
1162b2c47872SPetr Machata	local packets_rp13=$5
1163b2c47872SPetr Machata	local weights_ratio packets_ratio diff
1164b2c47872SPetr Machata
1165b2c47872SPetr Machata	RET=0
1166b2c47872SPetr Machata
11671b86fa3bSPetr Machata	if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
11681b86fa3bSPetr Machata		weights_ratio=$(echo "scale=2; $weight_rp12 / $weight_rp13" \
11691b86fa3bSPetr Machata				| bc -l)
11701b86fa3bSPetr Machata	else
11711b86fa3bSPetr Machata		weights_ratio=$(echo "scale=2; $weight_rp13 / $weight_rp12" \
11721b86fa3bSPetr Machata				| bc -l)
11731b86fa3bSPetr Machata	fi
11741b86fa3bSPetr Machata
1175b2c47872SPetr Machata	if [[ "$packets_rp12" -eq "0" || "$packets_rp13" -eq "0" ]]; then
1176b2c47872SPetr Machata	       check_err 1 "Packet difference is 0"
1177b2c47872SPetr Machata	       log_test "Multipath"
1178b2c47872SPetr Machata	       log_info "Expected ratio $weights_ratio"
1179b2c47872SPetr Machata	       return
1180b2c47872SPetr Machata	fi
1181b2c47872SPetr Machata
1182b2c47872SPetr Machata	if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
1183b2c47872SPetr Machata		packets_ratio=$(echo "scale=2; $packets_rp12 / $packets_rp13" \
1184b2c47872SPetr Machata				| bc -l)
1185b2c47872SPetr Machata	else
11861b86fa3bSPetr Machata		packets_ratio=$(echo "scale=2; $packets_rp13 / $packets_rp12" \
11871b86fa3bSPetr Machata				| bc -l)
1188b2c47872SPetr Machata	fi
1189b2c47872SPetr Machata
1190b2c47872SPetr Machata	diff=$(echo $weights_ratio - $packets_ratio | bc -l)
1191b2c47872SPetr Machata	diff=${diff#-}
1192b2c47872SPetr Machata
1193b2c47872SPetr Machata	test "$(echo "$diff / $weights_ratio > 0.15" | bc -l)" -eq 0
1194b2c47872SPetr Machata	check_err $? "Too large discrepancy between expected and measured ratios"
1195b2c47872SPetr Machata	log_test "$desc"
1196b2c47872SPetr Machata	log_info "Expected ratio $weights_ratio Measured ratio $packets_ratio"
1197b2c47872SPetr Machata}
1198b2c47872SPetr Machata
1199d0540d17SPetr Machatain_ns()
1200d0540d17SPetr Machata{
1201d0540d17SPetr Machata	local name=$1; shift
1202d0540d17SPetr Machata
1203d0540d17SPetr Machata	ip netns exec $name bash <<-EOF
1204d0540d17SPetr Machata		NUM_NETIFS=0
1205d0540d17SPetr Machata		source lib.sh
1206d0540d17SPetr Machata		$(for a in "$@"; do printf "%q${IFS:0:1}" "$a"; done)
1207d0540d17SPetr Machata	EOF
1208d0540d17SPetr Machata}
1209d0540d17SPetr Machata
121073bae673SIdo Schimmel##############################################################################
121173bae673SIdo Schimmel# Tests
121273bae673SIdo Schimmel
1213967450c5SNikolay Aleksandrovping_do()
121473bae673SIdo Schimmel{
121573bae673SIdo Schimmel	local if_name=$1
121673bae673SIdo Schimmel	local dip=$2
1217d20b0f21SPetr Machata	local args=$3
121873bae673SIdo Schimmel	local vrf_name
121973bae673SIdo Schimmel
122073bae673SIdo Schimmel	vrf_name=$(master_name_get $if_name)
1221b6a4fd68SIdo Schimmel	ip vrf exec $vrf_name \
12220cd0b1f7SAmit Cohen		$PING $args $dip -c $PING_COUNT -i 0.1 \
12230cd0b1f7SAmit Cohen		-w $PING_TIMEOUT &> /dev/null
1224967450c5SNikolay Aleksandrov}
1225967450c5SNikolay Aleksandrov
1226967450c5SNikolay Aleksandrovping_test()
1227967450c5SNikolay Aleksandrov{
1228967450c5SNikolay Aleksandrov	RET=0
1229967450c5SNikolay Aleksandrov
1230967450c5SNikolay Aleksandrov	ping_do $1 $2
123173bae673SIdo Schimmel	check_err $?
123258c7a2d1SPetr Machata	log_test "ping$3"
123373bae673SIdo Schimmel}
123473bae673SIdo Schimmel
12355f44a714SPetr Machataping_test_fails()
12365f44a714SPetr Machata{
12375f44a714SPetr Machata	RET=0
12385f44a714SPetr Machata
12395f44a714SPetr Machata	ping_do $1 $2
12405f44a714SPetr Machata	check_fail $?
12415f44a714SPetr Machata	log_test "ping fails$3"
12425f44a714SPetr Machata}
12435f44a714SPetr Machata
1244967450c5SNikolay Aleksandrovping6_do()
124573bae673SIdo Schimmel{
124673bae673SIdo Schimmel	local if_name=$1
124773bae673SIdo Schimmel	local dip=$2
1248d20b0f21SPetr Machata	local args=$3
124973bae673SIdo Schimmel	local vrf_name
125073bae673SIdo Schimmel
125173bae673SIdo Schimmel	vrf_name=$(master_name_get $if_name)
1252b6a4fd68SIdo Schimmel	ip vrf exec $vrf_name \
12530cd0b1f7SAmit Cohen		$PING6 $args $dip -c $PING_COUNT -i 0.1 \
12540cd0b1f7SAmit Cohen		-w $PING_TIMEOUT &> /dev/null
1255967450c5SNikolay Aleksandrov}
1256967450c5SNikolay Aleksandrov
1257967450c5SNikolay Aleksandrovping6_test()
1258967450c5SNikolay Aleksandrov{
1259967450c5SNikolay Aleksandrov	RET=0
1260967450c5SNikolay Aleksandrov
1261967450c5SNikolay Aleksandrov	ping6_do $1 $2
126273bae673SIdo Schimmel	check_err $?
126358c7a2d1SPetr Machata	log_test "ping6$3"
126473bae673SIdo Schimmel}
1265d4deb014SIdo Schimmel
12665f44a714SPetr Machataping6_test_fails()
12675f44a714SPetr Machata{
12685f44a714SPetr Machata	RET=0
12695f44a714SPetr Machata
12705f44a714SPetr Machata	ping6_do $1 $2
12715f44a714SPetr Machata	check_fail $?
12725f44a714SPetr Machata	log_test "ping6 fails$3"
12735f44a714SPetr Machata}
12745f44a714SPetr Machata
1275d4deb014SIdo Schimmellearning_test()
1276d4deb014SIdo Schimmel{
1277d4deb014SIdo Schimmel	local bridge=$1
1278d4deb014SIdo Schimmel	local br_port1=$2	# Connected to `host1_if`.
1279d4deb014SIdo Schimmel	local host1_if=$3
1280d4deb014SIdo Schimmel	local host2_if=$4
1281d4deb014SIdo Schimmel	local mac=de:ad:be:ef:13:37
1282d4deb014SIdo Schimmel	local ageing_time
1283d4deb014SIdo Schimmel
1284d4deb014SIdo Schimmel	RET=0
1285d4deb014SIdo Schimmel
1286d4deb014SIdo Schimmel	bridge -j fdb show br $bridge brport $br_port1 \
1287d4deb014SIdo Schimmel		| jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
1288d4deb014SIdo Schimmel	check_fail $? "Found FDB record when should not"
1289d4deb014SIdo Schimmel
1290d4deb014SIdo Schimmel	# Disable unknown unicast flooding on `br_port1` to make sure
1291d4deb014SIdo Schimmel	# packets are only forwarded through the port after a matching
1292d4deb014SIdo Schimmel	# FDB entry was installed.
1293d4deb014SIdo Schimmel	bridge link set dev $br_port1 flood off
1294d4deb014SIdo Schimmel
12951a635d3eSVladimir Oltean	ip link set $host1_if promisc on
1296d4deb014SIdo Schimmel	tc qdisc add dev $host1_if ingress
1297d4deb014SIdo Schimmel	tc filter add dev $host1_if ingress protocol ip pref 1 handle 101 \
1298d4deb014SIdo Schimmel		flower dst_mac $mac action drop
1299d4deb014SIdo Schimmel
1300d4deb014SIdo Schimmel	$MZ $host2_if -c 1 -p 64 -b $mac -t ip -q
1301d4deb014SIdo Schimmel	sleep 1
1302d4deb014SIdo Schimmel
1303d4deb014SIdo Schimmel	tc -j -s filter show dev $host1_if ingress \
1304d4deb014SIdo Schimmel		| jq -e ".[] | select(.options.handle == 101) \
1305d4deb014SIdo Schimmel		| select(.options.actions[0].stats.packets == 1)" &> /dev/null
130683844aacSVladimir Oltean	check_fail $? "Packet reached first host when should not"
1307d4deb014SIdo Schimmel
1308d4deb014SIdo Schimmel	$MZ $host1_if -c 1 -p 64 -a $mac -t ip -q
1309d4deb014SIdo Schimmel	sleep 1
1310d4deb014SIdo Schimmel
1311d4deb014SIdo Schimmel	bridge -j fdb show br $bridge brport $br_port1 \
1312d4deb014SIdo Schimmel		| jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
1313d4deb014SIdo Schimmel	check_err $? "Did not find FDB record when should"
1314d4deb014SIdo Schimmel
1315d4deb014SIdo Schimmel	$MZ $host2_if -c 1 -p 64 -b $mac -t ip -q
1316d4deb014SIdo Schimmel	sleep 1
1317d4deb014SIdo Schimmel
1318d4deb014SIdo Schimmel	tc -j -s filter show dev $host1_if ingress \
1319d4deb014SIdo Schimmel		| jq -e ".[] | select(.options.handle == 101) \
1320d4deb014SIdo Schimmel		| select(.options.actions[0].stats.packets == 1)" &> /dev/null
1321d4deb014SIdo Schimmel	check_err $? "Packet did not reach second host when should"
1322d4deb014SIdo Schimmel
1323d4deb014SIdo Schimmel	# Wait for 10 seconds after the ageing time to make sure FDB
1324d4deb014SIdo Schimmel	# record was aged-out.
1325d4deb014SIdo Schimmel	ageing_time=$(bridge_ageing_time_get $bridge)
1326d4deb014SIdo Schimmel	sleep $((ageing_time + 10))
1327d4deb014SIdo Schimmel
1328d4deb014SIdo Schimmel	bridge -j fdb show br $bridge brport $br_port1 \
1329d4deb014SIdo Schimmel		| jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
1330d4deb014SIdo Schimmel	check_fail $? "Found FDB record when should not"
1331d4deb014SIdo Schimmel
1332d4deb014SIdo Schimmel	bridge link set dev $br_port1 learning off
1333d4deb014SIdo Schimmel
1334d4deb014SIdo Schimmel	$MZ $host1_if -c 1 -p 64 -a $mac -t ip -q
1335d4deb014SIdo Schimmel	sleep 1
1336d4deb014SIdo Schimmel
1337d4deb014SIdo Schimmel	bridge -j fdb show br $bridge brport $br_port1 \
1338d4deb014SIdo Schimmel		| jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
1339d4deb014SIdo Schimmel	check_fail $? "Found FDB record when should not"
1340d4deb014SIdo Schimmel
1341d4deb014SIdo Schimmel	bridge link set dev $br_port1 learning on
1342d4deb014SIdo Schimmel
1343d4deb014SIdo Schimmel	tc filter del dev $host1_if ingress protocol ip pref 1 handle 101 flower
1344d4deb014SIdo Schimmel	tc qdisc del dev $host1_if ingress
13451a635d3eSVladimir Oltean	ip link set $host1_if promisc off
1346d4deb014SIdo Schimmel
1347d4deb014SIdo Schimmel	bridge link set dev $br_port1 flood on
1348d4deb014SIdo Schimmel
1349d4deb014SIdo Schimmel	log_test "FDB learning"
1350d4deb014SIdo Schimmel}
1351236dd50bSIdo Schimmel
1352236dd50bSIdo Schimmelflood_test_do()
1353236dd50bSIdo Schimmel{
1354236dd50bSIdo Schimmel	local should_flood=$1
1355236dd50bSIdo Schimmel	local mac=$2
1356236dd50bSIdo Schimmel	local ip=$3
1357236dd50bSIdo Schimmel	local host1_if=$4
1358236dd50bSIdo Schimmel	local host2_if=$5
1359236dd50bSIdo Schimmel	local err=0
1360236dd50bSIdo Schimmel
1361236dd50bSIdo Schimmel	# Add an ACL on `host2_if` which will tell us whether the packet
1362236dd50bSIdo Schimmel	# was flooded to it or not.
1363b8e629b0SVladimir Oltean	ip link set $host2_if promisc on
1364236dd50bSIdo Schimmel	tc qdisc add dev $host2_if ingress
1365236dd50bSIdo Schimmel	tc filter add dev $host2_if ingress protocol ip pref 1 handle 101 \
1366236dd50bSIdo Schimmel		flower dst_mac $mac action drop
1367236dd50bSIdo Schimmel
1368236dd50bSIdo Schimmel	$MZ $host1_if -c 1 -p 64 -b $mac -B $ip -t ip -q
1369236dd50bSIdo Schimmel	sleep 1
1370236dd50bSIdo Schimmel
1371236dd50bSIdo Schimmel	tc -j -s filter show dev $host2_if ingress \
1372236dd50bSIdo Schimmel		| jq -e ".[] | select(.options.handle == 101) \
1373236dd50bSIdo Schimmel		| select(.options.actions[0].stats.packets == 1)" &> /dev/null
1374236dd50bSIdo Schimmel	if [[ $? -ne 0 && $should_flood == "true" || \
1375236dd50bSIdo Schimmel	      $? -eq 0 && $should_flood == "false" ]]; then
1376236dd50bSIdo Schimmel		err=1
1377236dd50bSIdo Schimmel	fi
1378236dd50bSIdo Schimmel
1379236dd50bSIdo Schimmel	tc filter del dev $host2_if ingress protocol ip pref 1 handle 101 flower
1380236dd50bSIdo Schimmel	tc qdisc del dev $host2_if ingress
1381b8e629b0SVladimir Oltean	ip link set $host2_if promisc off
1382236dd50bSIdo Schimmel
1383236dd50bSIdo Schimmel	return $err
1384236dd50bSIdo Schimmel}
1385236dd50bSIdo Schimmel
1386236dd50bSIdo Schimmelflood_unicast_test()
1387236dd50bSIdo Schimmel{
1388236dd50bSIdo Schimmel	local br_port=$1
1389236dd50bSIdo Schimmel	local host1_if=$2
1390236dd50bSIdo Schimmel	local host2_if=$3
1391236dd50bSIdo Schimmel	local mac=de:ad:be:ef:13:37
1392236dd50bSIdo Schimmel	local ip=192.0.2.100
1393236dd50bSIdo Schimmel
1394236dd50bSIdo Schimmel	RET=0
1395236dd50bSIdo Schimmel
1396236dd50bSIdo Schimmel	bridge link set dev $br_port flood off
1397236dd50bSIdo Schimmel
1398236dd50bSIdo Schimmel	flood_test_do false $mac $ip $host1_if $host2_if
1399236dd50bSIdo Schimmel	check_err $? "Packet flooded when should not"
1400236dd50bSIdo Schimmel
1401236dd50bSIdo Schimmel	bridge link set dev $br_port flood on
1402236dd50bSIdo Schimmel
1403236dd50bSIdo Schimmel	flood_test_do true $mac $ip $host1_if $host2_if
1404236dd50bSIdo Schimmel	check_err $? "Packet was not flooded when should"
1405236dd50bSIdo Schimmel
1406236dd50bSIdo Schimmel	log_test "Unknown unicast flood"
1407236dd50bSIdo Schimmel}
1408236dd50bSIdo Schimmel
1409236dd50bSIdo Schimmelflood_multicast_test()
1410236dd50bSIdo Schimmel{
1411236dd50bSIdo Schimmel	local br_port=$1
1412236dd50bSIdo Schimmel	local host1_if=$2
1413236dd50bSIdo Schimmel	local host2_if=$3
1414236dd50bSIdo Schimmel	local mac=01:00:5e:00:00:01
1415236dd50bSIdo Schimmel	local ip=239.0.0.1
1416236dd50bSIdo Schimmel
1417236dd50bSIdo Schimmel	RET=0
1418236dd50bSIdo Schimmel
1419236dd50bSIdo Schimmel	bridge link set dev $br_port mcast_flood off
1420236dd50bSIdo Schimmel
1421236dd50bSIdo Schimmel	flood_test_do false $mac $ip $host1_if $host2_if
1422236dd50bSIdo Schimmel	check_err $? "Packet flooded when should not"
1423236dd50bSIdo Schimmel
1424236dd50bSIdo Schimmel	bridge link set dev $br_port mcast_flood on
1425236dd50bSIdo Schimmel
1426236dd50bSIdo Schimmel	flood_test_do true $mac $ip $host1_if $host2_if
1427236dd50bSIdo Schimmel	check_err $? "Packet was not flooded when should"
1428236dd50bSIdo Schimmel
1429236dd50bSIdo Schimmel	log_test "Unregistered multicast flood"
1430236dd50bSIdo Schimmel}
1431236dd50bSIdo Schimmel
1432236dd50bSIdo Schimmelflood_test()
1433236dd50bSIdo Schimmel{
1434236dd50bSIdo Schimmel	# `br_port` is connected to `host2_if`
1435236dd50bSIdo Schimmel	local br_port=$1
1436236dd50bSIdo Schimmel	local host1_if=$2
1437236dd50bSIdo Schimmel	local host2_if=$3
1438236dd50bSIdo Schimmel
1439236dd50bSIdo Schimmel	flood_unicast_test $br_port $host1_if $host2_if
1440236dd50bSIdo Schimmel	flood_multicast_test $br_port $host1_if $host2_if
1441236dd50bSIdo Schimmel}
14424cf9b8f9SPetr Machata
14434113b048SPetr Machata__start_traffic()
14444cf9b8f9SPetr Machata{
14451531cc63SPetr Machata	local pktsize=$1; shift
14464113b048SPetr Machata	local proto=$1; shift
14474cf9b8f9SPetr Machata	local h_in=$1; shift    # Where the traffic egresses the host
14484cf9b8f9SPetr Machata	local sip=$1; shift
14494cf9b8f9SPetr Machata	local dip=$1; shift
14504cf9b8f9SPetr Machata	local dmac=$1; shift
14514cf9b8f9SPetr Machata
14521531cc63SPetr Machata	$MZ $h_in -p $pktsize -A $sip -B $dip -c 0 \
14534113b048SPetr Machata		-a own -b $dmac -t "$proto" -q "$@" &
14544cf9b8f9SPetr Machata	sleep 1
14554cf9b8f9SPetr Machata}
14564cf9b8f9SPetr Machata
14571531cc63SPetr Machatastart_traffic_pktsize()
14581531cc63SPetr Machata{
14591531cc63SPetr Machata	local pktsize=$1; shift
14601531cc63SPetr Machata
14611531cc63SPetr Machata	__start_traffic $pktsize udp "$@"
14621531cc63SPetr Machata}
14631531cc63SPetr Machata
14641531cc63SPetr Machatastart_tcp_traffic_pktsize()
14651531cc63SPetr Machata{
14661531cc63SPetr Machata	local pktsize=$1; shift
14671531cc63SPetr Machata
14681531cc63SPetr Machata	__start_traffic $pktsize tcp "$@"
14691531cc63SPetr Machata}
14701531cc63SPetr Machata
14714113b048SPetr Machatastart_traffic()
14724113b048SPetr Machata{
14731531cc63SPetr Machata	start_traffic_pktsize 8000 "$@"
14744113b048SPetr Machata}
14754113b048SPetr Machata
14764113b048SPetr Machatastart_tcp_traffic()
14774113b048SPetr Machata{
14781531cc63SPetr Machata	start_tcp_traffic_pktsize 8000 "$@"
14794113b048SPetr Machata}
14804113b048SPetr Machata
14814cf9b8f9SPetr Machatastop_traffic()
14824cf9b8f9SPetr Machata{
14834cf9b8f9SPetr Machata	# Suppress noise from killing mausezahn.
14844cf9b8f9SPetr Machata	{ kill %% && wait %%; } 2>/dev/null
14854cf9b8f9SPetr Machata}
14868cd6b020SVladimir Oltean
14876182c5c5SJoachim Wibergdeclare -A cappid
14886182c5c5SJoachim Wibergdeclare -A capfile
14896182c5c5SJoachim Wibergdeclare -A capout
14906182c5c5SJoachim Wiberg
14918cd6b020SVladimir Olteantcpdump_start()
14928cd6b020SVladimir Oltean{
14938cd6b020SVladimir Oltean	local if_name=$1; shift
14948cd6b020SVladimir Oltean	local ns=$1; shift
14958cd6b020SVladimir Oltean
14966182c5c5SJoachim Wiberg	capfile[$if_name]=$(mktemp)
14976182c5c5SJoachim Wiberg	capout[$if_name]=$(mktemp)
14988cd6b020SVladimir Oltean
14998cd6b020SVladimir Oltean	if [ -z $ns ]; then
15008cd6b020SVladimir Oltean		ns_cmd=""
15018cd6b020SVladimir Oltean	else
15028cd6b020SVladimir Oltean		ns_cmd="ip netns exec ${ns}"
15038cd6b020SVladimir Oltean	fi
15048cd6b020SVladimir Oltean
15058cd6b020SVladimir Oltean	if [ -z $SUDO_USER ] ; then
15068cd6b020SVladimir Oltean		capuser=""
15078cd6b020SVladimir Oltean	else
15088cd6b020SVladimir Oltean		capuser="-Z $SUDO_USER"
15098cd6b020SVladimir Oltean	fi
15108cd6b020SVladimir Oltean
1511fe32dffdSJoachim Wiberg	$ns_cmd tcpdump $TCPDUMP_EXTRA_FLAGS -e -n -Q in -i $if_name \
15126182c5c5SJoachim Wiberg		-s 65535 -B 32768 $capuser -w ${capfile[$if_name]} \
15136182c5c5SJoachim Wiberg		> "${capout[$if_name]}" 2>&1 &
15146182c5c5SJoachim Wiberg	cappid[$if_name]=$!
15158cd6b020SVladimir Oltean
15168cd6b020SVladimir Oltean	sleep 1
15178cd6b020SVladimir Oltean}
15188cd6b020SVladimir Oltean
15198cd6b020SVladimir Olteantcpdump_stop()
15208cd6b020SVladimir Oltean{
15216182c5c5SJoachim Wiberg	local if_name=$1
15226182c5c5SJoachim Wiberg	local pid=${cappid[$if_name]}
15236182c5c5SJoachim Wiberg
15246182c5c5SJoachim Wiberg	$ns_cmd kill "$pid" && wait "$pid"
15258cd6b020SVladimir Oltean	sleep 1
15268cd6b020SVladimir Oltean}
15278cd6b020SVladimir Oltean
15288cd6b020SVladimir Olteantcpdump_cleanup()
15298cd6b020SVladimir Oltean{
15306182c5c5SJoachim Wiberg	local if_name=$1
15316182c5c5SJoachim Wiberg
15326182c5c5SJoachim Wiberg	rm ${capfile[$if_name]} ${capout[$if_name]}
15338cd6b020SVladimir Oltean}
15348cd6b020SVladimir Oltean
15358cd6b020SVladimir Olteantcpdump_show()
15368cd6b020SVladimir Oltean{
15376182c5c5SJoachim Wiberg	local if_name=$1
15386182c5c5SJoachim Wiberg
15396182c5c5SJoachim Wiberg	tcpdump -e -n -r ${capfile[$if_name]} 2>&1
15408cd6b020SVladimir Oltean}
1541537e4825SNikolay Aleksandrov
1542537e4825SNikolay Aleksandrov# return 0 if the packet wasn't seen on host2_if or 1 if it was
1543537e4825SNikolay Aleksandrovmcast_packet_test()
1544537e4825SNikolay Aleksandrov{
1545537e4825SNikolay Aleksandrov	local mac=$1
1546537e4825SNikolay Aleksandrov	local src_ip=$2
1547537e4825SNikolay Aleksandrov	local ip=$3
1548537e4825SNikolay Aleksandrov	local host1_if=$4
1549537e4825SNikolay Aleksandrov	local host2_if=$5
1550537e4825SNikolay Aleksandrov	local seen=0
1551450b0b84SNikolay Aleksandrov	local tc_proto="ip"
1552450b0b84SNikolay Aleksandrov	local mz_v6arg=""
1553450b0b84SNikolay Aleksandrov
1554450b0b84SNikolay Aleksandrov	# basic check to see if we were passed an IPv4 address, if not assume IPv6
1555450b0b84SNikolay Aleksandrov	if [[ ! $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
1556450b0b84SNikolay Aleksandrov		tc_proto="ipv6"
1557450b0b84SNikolay Aleksandrov		mz_v6arg="-6"
1558450b0b84SNikolay Aleksandrov	fi
1559537e4825SNikolay Aleksandrov
1560537e4825SNikolay Aleksandrov	# Add an ACL on `host2_if` which will tell us whether the packet
1561537e4825SNikolay Aleksandrov	# was received by it or not.
1562537e4825SNikolay Aleksandrov	tc qdisc add dev $host2_if ingress
1563450b0b84SNikolay Aleksandrov	tc filter add dev $host2_if ingress protocol $tc_proto pref 1 handle 101 \
1564537e4825SNikolay Aleksandrov		flower ip_proto udp dst_mac $mac action drop
1565537e4825SNikolay Aleksandrov
1566450b0b84SNikolay Aleksandrov	$MZ $host1_if $mz_v6arg -c 1 -p 64 -b $mac -A $src_ip -B $ip -t udp "dp=4096,sp=2048" -q
1567537e4825SNikolay Aleksandrov	sleep 1
1568537e4825SNikolay Aleksandrov
1569537e4825SNikolay Aleksandrov	tc -j -s filter show dev $host2_if ingress \
1570537e4825SNikolay Aleksandrov		| jq -e ".[] | select(.options.handle == 101) \
1571537e4825SNikolay Aleksandrov		| select(.options.actions[0].stats.packets == 1)" &> /dev/null
1572537e4825SNikolay Aleksandrov	if [[ $? -eq 0 ]]; then
1573537e4825SNikolay Aleksandrov		seen=1
1574537e4825SNikolay Aleksandrov	fi
1575537e4825SNikolay Aleksandrov
1576450b0b84SNikolay Aleksandrov	tc filter del dev $host2_if ingress protocol $tc_proto pref 1 handle 101 flower
1577537e4825SNikolay Aleksandrov	tc qdisc del dev $host2_if ingress
1578537e4825SNikolay Aleksandrov
1579537e4825SNikolay Aleksandrov	return $seen
1580537e4825SNikolay Aleksandrov}
158195e6f430SNikolay Aleksandrov
158295e6f430SNikolay Aleksandrovbrmcast_check_sg_entries()
158395e6f430SNikolay Aleksandrov{
158495e6f430SNikolay Aleksandrov	local report=$1; shift
158595e6f430SNikolay Aleksandrov	local slist=("$@")
158695e6f430SNikolay Aleksandrov	local sarg=""
158795e6f430SNikolay Aleksandrov
158895e6f430SNikolay Aleksandrov	for src in "${slist[@]}"; do
158995e6f430SNikolay Aleksandrov		sarg="${sarg} and .source_list[].address == \"$src\""
159095e6f430SNikolay Aleksandrov	done
159195e6f430SNikolay Aleksandrov	bridge -j -d -s mdb show dev br0 \
159295e6f430SNikolay Aleksandrov		| jq -e ".[].mdb[] | \
159395e6f430SNikolay Aleksandrov			 select(.grp == \"$TEST_GROUP\" and .source_list != null $sarg)" &>/dev/null
159495e6f430SNikolay Aleksandrov	check_err $? "Wrong *,G entry source list after $report report"
159595e6f430SNikolay Aleksandrov
159695e6f430SNikolay Aleksandrov	for sgent in "${slist[@]}"; do
159795e6f430SNikolay Aleksandrov		bridge -j -d -s mdb show dev br0 \
159895e6f430SNikolay Aleksandrov			| jq -e ".[].mdb[] | \
159995e6f430SNikolay Aleksandrov				 select(.grp == \"$TEST_GROUP\" and .src == \"$sgent\")" &>/dev/null
160095e6f430SNikolay Aleksandrov		check_err $? "Missing S,G entry ($sgent, $TEST_GROUP)"
160195e6f430SNikolay Aleksandrov	done
160295e6f430SNikolay Aleksandrov}
160395e6f430SNikolay Aleksandrov
160495e6f430SNikolay Aleksandrovbrmcast_check_sg_fwding()
160595e6f430SNikolay Aleksandrov{
160695e6f430SNikolay Aleksandrov	local should_fwd=$1; shift
160795e6f430SNikolay Aleksandrov	local sources=("$@")
160895e6f430SNikolay Aleksandrov
160995e6f430SNikolay Aleksandrov	for src in "${sources[@]}"; do
161095e6f430SNikolay Aleksandrov		local retval=0
161195e6f430SNikolay Aleksandrov
161295e6f430SNikolay Aleksandrov		mcast_packet_test $TEST_GROUP_MAC $src $TEST_GROUP $h2 $h1
161395e6f430SNikolay Aleksandrov		retval=$?
161495e6f430SNikolay Aleksandrov		if [ $should_fwd -eq 1 ]; then
161595e6f430SNikolay Aleksandrov			check_fail $retval "Didn't forward traffic from S,G ($src, $TEST_GROUP)"
161695e6f430SNikolay Aleksandrov		else
161795e6f430SNikolay Aleksandrov			check_err $retval "Forwarded traffic for blocked S,G ($src, $TEST_GROUP)"
161895e6f430SNikolay Aleksandrov		fi
161995e6f430SNikolay Aleksandrov	done
162095e6f430SNikolay Aleksandrov}
162195e6f430SNikolay Aleksandrov
162295e6f430SNikolay Aleksandrovbrmcast_check_sg_state()
162395e6f430SNikolay Aleksandrov{
162495e6f430SNikolay Aleksandrov	local is_blocked=$1; shift
162595e6f430SNikolay Aleksandrov	local sources=("$@")
162695e6f430SNikolay Aleksandrov	local should_fail=1
162795e6f430SNikolay Aleksandrov
162895e6f430SNikolay Aleksandrov	if [ $is_blocked -eq 1 ]; then
162995e6f430SNikolay Aleksandrov		should_fail=0
163095e6f430SNikolay Aleksandrov	fi
163195e6f430SNikolay Aleksandrov
163295e6f430SNikolay Aleksandrov	for src in "${sources[@]}"; do
163395e6f430SNikolay Aleksandrov		bridge -j -d -s mdb show dev br0 \
163495e6f430SNikolay Aleksandrov			| jq -e ".[].mdb[] | \
163595e6f430SNikolay Aleksandrov				 select(.grp == \"$TEST_GROUP\" and .source_list != null) |
163695e6f430SNikolay Aleksandrov				 .source_list[] |
163795e6f430SNikolay Aleksandrov				 select(.address == \"$src\") |
163895e6f430SNikolay Aleksandrov				 select(.timer == \"0.00\")" &>/dev/null
163995e6f430SNikolay Aleksandrov		check_err_fail $should_fail $? "Entry $src has zero timer"
164095e6f430SNikolay Aleksandrov
164195e6f430SNikolay Aleksandrov		bridge -j -d -s mdb show dev br0 \
164295e6f430SNikolay Aleksandrov			| jq -e ".[].mdb[] | \
164395e6f430SNikolay Aleksandrov				 select(.grp == \"$TEST_GROUP\" and .src == \"$src\" and \
164495e6f430SNikolay Aleksandrov				 .flags[] == \"blocked\")" &>/dev/null
164595e6f430SNikolay Aleksandrov		check_err_fail $should_fail $? "Entry $src has blocked flag"
164695e6f430SNikolay Aleksandrov	done
164795e6f430SNikolay Aleksandrov}
16489b18942eSPetr Machata
1649f23cddc7SVladimir Olteanmc_join()
1650f23cddc7SVladimir Oltean{
1651f23cddc7SVladimir Oltean	local if_name=$1
1652f23cddc7SVladimir Oltean	local group=$2
1653f23cddc7SVladimir Oltean	local vrf_name=$(master_name_get $if_name)
1654f23cddc7SVladimir Oltean
1655f23cddc7SVladimir Oltean	# We don't care about actual reception, just about joining the
1656f23cddc7SVladimir Oltean	# IP multicast group and adding the L2 address to the device's
1657f23cddc7SVladimir Oltean	# MAC filtering table
1658f23cddc7SVladimir Oltean	ip vrf exec $vrf_name \
1659f23cddc7SVladimir Oltean		mreceive -g $group -I $if_name > /dev/null 2>&1 &
1660f23cddc7SVladimir Oltean	mreceive_pid=$!
1661f23cddc7SVladimir Oltean
1662f23cddc7SVladimir Oltean	sleep 1
1663f23cddc7SVladimir Oltean}
1664f23cddc7SVladimir Oltean
1665f23cddc7SVladimir Olteanmc_leave()
1666f23cddc7SVladimir Oltean{
1667f23cddc7SVladimir Oltean	kill "$mreceive_pid" && wait "$mreceive_pid"
1668f23cddc7SVladimir Oltean}
1669f23cddc7SVladimir Oltean
1670f23cddc7SVladimir Olteanmc_send()
1671f23cddc7SVladimir Oltean{
1672f23cddc7SVladimir Oltean	local if_name=$1
1673f23cddc7SVladimir Oltean	local groups=$2
1674f23cddc7SVladimir Oltean	local vrf_name=$(master_name_get $if_name)
1675f23cddc7SVladimir Oltean
1676f23cddc7SVladimir Oltean	ip vrf exec $vrf_name \
1677f23cddc7SVladimir Oltean		msend -g $groups -I $if_name -c 1 > /dev/null 2>&1
1678f23cddc7SVladimir Oltean}
1679f23cddc7SVladimir Oltean
16809b18942eSPetr Machatastart_ip_monitor()
16819b18942eSPetr Machata{
16829b18942eSPetr Machata	local mtype=$1; shift
16839b18942eSPetr Machata	local ip=${1-ip}; shift
16849b18942eSPetr Machata
16859b18942eSPetr Machata	# start the monitor in the background
16869b18942eSPetr Machata	tmpfile=`mktemp /var/run/nexthoptestXXX`
16879b18942eSPetr Machata	mpid=`($ip monitor $mtype > $tmpfile & echo $!) 2>/dev/null`
16889b18942eSPetr Machata	sleep 0.2
16899b18942eSPetr Machata	echo "$mpid $tmpfile"
16909b18942eSPetr Machata}
16919b18942eSPetr Machata
16929b18942eSPetr Machatastop_ip_monitor()
16939b18942eSPetr Machata{
16949b18942eSPetr Machata	local mpid=$1; shift
16959b18942eSPetr Machata	local tmpfile=$1; shift
16969b18942eSPetr Machata	local el=$1; shift
16979b18942eSPetr Machata	local what=$1; shift
16989b18942eSPetr Machata
16999b18942eSPetr Machata	sleep 0.2
17009b18942eSPetr Machata	kill $mpid
17019b18942eSPetr Machata	local lines=`grep '^\w' $tmpfile | wc -l`
17029b18942eSPetr Machata	test $lines -eq $el
17039b18942eSPetr Machata	check_err $? "$what: $lines lines of events, expected $el"
17049b18942eSPetr Machata	rm -rf $tmpfile
17059b18942eSPetr Machata}
17069b18942eSPetr Machata
17079b18942eSPetr Machatahw_stats_monitor_test()
17089b18942eSPetr Machata{
17099b18942eSPetr Machata	local dev=$1; shift
17109b18942eSPetr Machata	local type=$1; shift
17119b18942eSPetr Machata	local make_suitable=$1; shift
17129b18942eSPetr Machata	local make_unsuitable=$1; shift
17139b18942eSPetr Machata	local ip=${1-ip}; shift
17149b18942eSPetr Machata
17159b18942eSPetr Machata	RET=0
17169b18942eSPetr Machata
17179b18942eSPetr Machata	# Expect a notification about enablement.
17189b18942eSPetr Machata	local ipmout=$(start_ip_monitor stats "$ip")
17199b18942eSPetr Machata	$ip stats set dev $dev ${type}_stats on
17209b18942eSPetr Machata	stop_ip_monitor $ipmout 1 "${type}_stats enablement"
17219b18942eSPetr Machata
17229b18942eSPetr Machata	# Expect a notification about offload.
17239b18942eSPetr Machata	local ipmout=$(start_ip_monitor stats "$ip")
17249b18942eSPetr Machata	$make_suitable
17259b18942eSPetr Machata	stop_ip_monitor $ipmout 1 "${type}_stats installation"
17269b18942eSPetr Machata
17279b18942eSPetr Machata	# Expect a notification about loss of offload.
17289b18942eSPetr Machata	local ipmout=$(start_ip_monitor stats "$ip")
17299b18942eSPetr Machata	$make_unsuitable
17309b18942eSPetr Machata	stop_ip_monitor $ipmout 1 "${type}_stats deinstallation"
17319b18942eSPetr Machata
17329b18942eSPetr Machata	# Expect a notification about disablement
17339b18942eSPetr Machata	local ipmout=$(start_ip_monitor stats "$ip")
17349b18942eSPetr Machata	$ip stats set dev $dev ${type}_stats off
17359b18942eSPetr Machata	stop_ip_monitor $ipmout 1 "${type}_stats disablement"
17369b18942eSPetr Machata
17379b18942eSPetr Machata	log_test "${type}_stats notifications"
17389b18942eSPetr Machata}
1739344dd2c9SPetr Machata
1740fcf49276SPetr Machataipv4_to_bytes()
1741fcf49276SPetr Machata{
1742fcf49276SPetr Machata	local IP=$1; shift
1743fcf49276SPetr Machata
1744fcf49276SPetr Machata	printf '%02x:' ${IP//./ } |
1745fcf49276SPetr Machata	    sed 's/:$//'
1746fcf49276SPetr Machata}
1747fcf49276SPetr Machata
1748fcf49276SPetr Machata# Convert a given IPv6 address, `IP' such that the :: token, if present, is
1749fcf49276SPetr Machata# expanded, and each 16-bit group is padded with zeroes to be 4 hexadecimal
1750fcf49276SPetr Machata# digits. An optional `BYTESEP' parameter can be given to further separate
1751fcf49276SPetr Machata# individual bytes of each 16-bit group.
1752fcf49276SPetr Machataexpand_ipv6()
1753fcf49276SPetr Machata{
1754fcf49276SPetr Machata	local IP=$1; shift
1755fcf49276SPetr Machata	local bytesep=$1; shift
1756fcf49276SPetr Machata
1757fcf49276SPetr Machata	local cvt_ip=${IP/::/_}
1758fcf49276SPetr Machata	local colons=${cvt_ip//[^:]/}
1759fcf49276SPetr Machata	local allcol=:::::::
1760fcf49276SPetr Machata	# IP where :: -> the appropriate number of colons:
1761fcf49276SPetr Machata	local allcol_ip=${cvt_ip/_/${allcol:${#colons}}}
1762fcf49276SPetr Machata
1763fcf49276SPetr Machata	echo $allcol_ip | tr : '\n' |
1764fcf49276SPetr Machata	    sed s/^/0000/ |
1765fcf49276SPetr Machata	    sed 's/.*\(..\)\(..\)/\1'"$bytesep"'\2/' |
1766fcf49276SPetr Machata	    tr '\n' : |
1767fcf49276SPetr Machata	    sed 's/:$//'
1768fcf49276SPetr Machata}
1769fcf49276SPetr Machata
1770fcf49276SPetr Machataipv6_to_bytes()
1771fcf49276SPetr Machata{
1772fcf49276SPetr Machata	local IP=$1; shift
1773fcf49276SPetr Machata
1774fcf49276SPetr Machata	expand_ipv6 "$IP" :
1775fcf49276SPetr Machata}
1776fcf49276SPetr Machata
1777952e0ee3SPetr Machatau16_to_bytes()
1778952e0ee3SPetr Machata{
1779952e0ee3SPetr Machata	local u16=$1; shift
1780952e0ee3SPetr Machata
1781952e0ee3SPetr Machata	printf "%04x" $u16 | sed 's/^/000/;s/^.*\(..\)\(..\)$/\1:\2/'
1782952e0ee3SPetr Machata}
1783952e0ee3SPetr Machata
1784952e0ee3SPetr Machata# Given a mausezahn-formatted payload (colon-separated bytes given as %02x),
1785952e0ee3SPetr Machata# possibly with a keyword CHECKSUM stashed where a 16-bit checksum should be,
1786952e0ee3SPetr Machata# calculate checksum as per RFC 1071, assuming the CHECKSUM field (if any)
1787952e0ee3SPetr Machata# stands for 00:00.
1788952e0ee3SPetr Machatapayload_template_calc_checksum()
1789952e0ee3SPetr Machata{
1790952e0ee3SPetr Machata	local payload=$1; shift
1791952e0ee3SPetr Machata
1792952e0ee3SPetr Machata	(
1793952e0ee3SPetr Machata	    # Set input radix.
1794952e0ee3SPetr Machata	    echo "16i"
1795952e0ee3SPetr Machata	    # Push zero for the initial checksum.
1796952e0ee3SPetr Machata	    echo 0
1797952e0ee3SPetr Machata
1798952e0ee3SPetr Machata	    # Pad the payload with a terminating 00: in case we get an odd
1799952e0ee3SPetr Machata	    # number of bytes.
1800952e0ee3SPetr Machata	    echo "${payload%:}:00:" |
1801952e0ee3SPetr Machata		sed 's/CHECKSUM/00:00/g' |
1802952e0ee3SPetr Machata		tr '[:lower:]' '[:upper:]' |
1803952e0ee3SPetr Machata		# Add the word to the checksum.
1804952e0ee3SPetr Machata		sed 's/\(..\):\(..\):/\1\2+\n/g' |
1805952e0ee3SPetr Machata		# Strip the extra odd byte we pushed if left unconverted.
1806952e0ee3SPetr Machata		sed 's/\(..\):$//'
1807952e0ee3SPetr Machata
1808952e0ee3SPetr Machata	    echo "10000 ~ +"	# Calculate and add carry.
1809952e0ee3SPetr Machata	    echo "FFFF r - p"	# Bit-flip and print.
1810952e0ee3SPetr Machata	) |
1811952e0ee3SPetr Machata	    dc |
1812952e0ee3SPetr Machata	    tr '[:upper:]' '[:lower:]'
1813952e0ee3SPetr Machata}
1814952e0ee3SPetr Machata
1815952e0ee3SPetr Machatapayload_template_expand_checksum()
1816952e0ee3SPetr Machata{
1817952e0ee3SPetr Machata	local payload=$1; shift
1818952e0ee3SPetr Machata	local checksum=$1; shift
1819952e0ee3SPetr Machata
1820952e0ee3SPetr Machata	local ckbytes=$(u16_to_bytes $checksum)
1821952e0ee3SPetr Machata
1822952e0ee3SPetr Machata	echo "$payload" | sed "s/CHECKSUM/$ckbytes/g"
1823952e0ee3SPetr Machata}
1824952e0ee3SPetr Machata
1825952e0ee3SPetr Machatapayload_template_nbytes()
1826952e0ee3SPetr Machata{
1827952e0ee3SPetr Machata	local payload=$1; shift
1828952e0ee3SPetr Machata
1829952e0ee3SPetr Machata	payload_template_expand_checksum "${payload%:}" 0 |
1830952e0ee3SPetr Machata		sed 's/:/\n/g' | wc -l
1831952e0ee3SPetr Machata}
1832952e0ee3SPetr Machata
1833344dd2c9SPetr Machataigmpv3_is_in_get()
1834344dd2c9SPetr Machata{
1835506a1ac9SPetr Machata	local GRP=$1; shift
1836705d4bc7SPetr Machata	local sources=("$@")
1837506a1ac9SPetr Machata
1838344dd2c9SPetr Machata	local igmpv3
1839705d4bc7SPetr Machata	local nsources=$(u16_to_bytes ${#sources[@]})
1840344dd2c9SPetr Machata
1841705d4bc7SPetr Machata	# IS_IN ( $sources )
1842344dd2c9SPetr Machata	igmpv3=$(:
1843344dd2c9SPetr Machata		)"22:"$(			: Type - Membership Report
1844344dd2c9SPetr Machata		)"00:"$(			: Reserved
1845506a1ac9SPetr Machata		)"CHECKSUM:"$(			: Checksum
1846344dd2c9SPetr Machata		)"00:00:"$(			: Reserved
1847344dd2c9SPetr Machata		)"00:01:"$(			: Number of Group Records
1848344dd2c9SPetr Machata		)"01:"$(			: Record Type - IS_IN
1849344dd2c9SPetr Machata		)"00:"$(			: Aux Data Len
1850705d4bc7SPetr Machata		)"${nsources}:"$(		: Number of Sources
1851506a1ac9SPetr Machata		)"$(ipv4_to_bytes $GRP):"$(	: Multicast Address
1852705d4bc7SPetr Machata		)"$(for src in "${sources[@]}"; do
1853705d4bc7SPetr Machata			ipv4_to_bytes $src
1854705d4bc7SPetr Machata			echo -n :
1855705d4bc7SPetr Machata		    done)"$(			: Source Addresses
1856344dd2c9SPetr Machata		)
1857506a1ac9SPetr Machata	local checksum=$(payload_template_calc_checksum "$igmpv3")
1858344dd2c9SPetr Machata
1859506a1ac9SPetr Machata	payload_template_expand_checksum "$igmpv3" $checksum
1860344dd2c9SPetr Machata}
1861344dd2c9SPetr Machata
18629ae85469SPetr Machataigmpv2_leave_get()
18639ae85469SPetr Machata{
18649ae85469SPetr Machata	local GRP=$1; shift
18659ae85469SPetr Machata
18669ae85469SPetr Machata	local payload=$(:
18679ae85469SPetr Machata		)"17:"$(			: Type - Leave Group
18689ae85469SPetr Machata		)"00:"$(			: Max Resp Time - not meaningful
18699ae85469SPetr Machata		)"CHECKSUM:"$(			: Checksum
18709ae85469SPetr Machata		)"$(ipv4_to_bytes $GRP)"$(	: Group Address
18719ae85469SPetr Machata		)
18729ae85469SPetr Machata	local checksum=$(payload_template_calc_checksum "$payload")
18739ae85469SPetr Machata
18749ae85469SPetr Machata	payload_template_expand_checksum "$payload" $checksum
18759ae85469SPetr Machata}
18769ae85469SPetr Machata
1877344dd2c9SPetr Machatamldv2_is_in_get()
1878344dd2c9SPetr Machata{
1879506a1ac9SPetr Machata	local SIP=$1; shift
1880506a1ac9SPetr Machata	local GRP=$1; shift
1881705d4bc7SPetr Machata	local sources=("$@")
1882506a1ac9SPetr Machata
1883344dd2c9SPetr Machata	local hbh
1884344dd2c9SPetr Machata	local icmpv6
1885705d4bc7SPetr Machata	local nsources=$(u16_to_bytes ${#sources[@]})
1886344dd2c9SPetr Machata
1887344dd2c9SPetr Machata	hbh=$(:
1888344dd2c9SPetr Machata		)"3a:"$(			: Next Header - ICMPv6
1889344dd2c9SPetr Machata		)"00:"$(			: Hdr Ext Len
1890344dd2c9SPetr Machata		)"00:00:00:00:00:00:"$(		: Options and Padding
1891344dd2c9SPetr Machata		)
1892344dd2c9SPetr Machata
1893344dd2c9SPetr Machata	icmpv6=$(:
1894344dd2c9SPetr Machata		)"8f:"$(			: Type - MLDv2 Report
1895344dd2c9SPetr Machata		)"00:"$(			: Code
1896506a1ac9SPetr Machata		)"CHECKSUM:"$(			: Checksum
1897344dd2c9SPetr Machata		)"00:00:"$(			: Reserved
1898344dd2c9SPetr Machata		)"00:01:"$(			: Number of Group Records
1899344dd2c9SPetr Machata		)"01:"$(			: Record Type - IS_IN
1900344dd2c9SPetr Machata		)"00:"$(			: Aux Data Len
1901705d4bc7SPetr Machata		)"${nsources}:"$(		: Number of Sources
1902506a1ac9SPetr Machata		)"$(ipv6_to_bytes $GRP):"$(	: Multicast address
1903705d4bc7SPetr Machata		)"$(for src in "${sources[@]}"; do
1904705d4bc7SPetr Machata			ipv6_to_bytes $src
1905705d4bc7SPetr Machata			echo -n :
1906705d4bc7SPetr Machata		    done)"$(			: Source Addresses
1907344dd2c9SPetr Machata		)
1908344dd2c9SPetr Machata
1909506a1ac9SPetr Machata	local len=$(u16_to_bytes $(payload_template_nbytes $icmpv6))
1910506a1ac9SPetr Machata	local sudohdr=$(:
1911506a1ac9SPetr Machata		)"$(ipv6_to_bytes $SIP):"$(	: SIP
1912506a1ac9SPetr Machata		)"$(ipv6_to_bytes $GRP):"$(	: DIP is multicast address
1913506a1ac9SPetr Machata	        )"${len}:"$(			: Upper-layer length
1914506a1ac9SPetr Machata	        )"00:3a:"$(			: Zero and next-header
1915506a1ac9SPetr Machata	        )
1916506a1ac9SPetr Machata	local checksum=$(payload_template_calc_checksum ${sudohdr}${icmpv6})
1917506a1ac9SPetr Machata
1918506a1ac9SPetr Machata	payload_template_expand_checksum "$hbh$icmpv6" $checksum
1919344dd2c9SPetr Machata}
19209ae85469SPetr Machata
19219ae85469SPetr Machatamldv1_done_get()
19229ae85469SPetr Machata{
19239ae85469SPetr Machata	local SIP=$1; shift
19249ae85469SPetr Machata	local GRP=$1; shift
19259ae85469SPetr Machata
19269ae85469SPetr Machata	local hbh
19279ae85469SPetr Machata	local icmpv6
19289ae85469SPetr Machata
19299ae85469SPetr Machata	hbh=$(:
19309ae85469SPetr Machata		)"3a:"$(			: Next Header - ICMPv6
19319ae85469SPetr Machata		)"00:"$(			: Hdr Ext Len
19329ae85469SPetr Machata		)"00:00:00:00:00:00:"$(		: Options and Padding
19339ae85469SPetr Machata		)
19349ae85469SPetr Machata
19359ae85469SPetr Machata	icmpv6=$(:
19369ae85469SPetr Machata		)"84:"$(			: Type - MLDv1 Done
19379ae85469SPetr Machata		)"00:"$(			: Code
19389ae85469SPetr Machata		)"CHECKSUM:"$(			: Checksum
19399ae85469SPetr Machata		)"00:00:"$(			: Max Resp Delay - not meaningful
19409ae85469SPetr Machata		)"00:00:"$(			: Reserved
19419ae85469SPetr Machata		)"$(ipv6_to_bytes $GRP):"$(	: Multicast address
19429ae85469SPetr Machata		)
19439ae85469SPetr Machata
19449ae85469SPetr Machata	local len=$(u16_to_bytes $(payload_template_nbytes $icmpv6))
19459ae85469SPetr Machata	local sudohdr=$(:
19469ae85469SPetr Machata		)"$(ipv6_to_bytes $SIP):"$(	: SIP
19479ae85469SPetr Machata		)"$(ipv6_to_bytes $GRP):"$(	: DIP is multicast address
19489ae85469SPetr Machata	        )"${len}:"$(			: Upper-layer length
19499ae85469SPetr Machata	        )"00:3a:"$(			: Zero and next-header
19509ae85469SPetr Machata	        )
19519ae85469SPetr Machata	local checksum=$(payload_template_calc_checksum ${sudohdr}${icmpv6})
19529ae85469SPetr Machata
19539ae85469SPetr Machata	payload_template_expand_checksum "$hbh$icmpv6" $checksum
19549ae85469SPetr Machata}
19558fcac792SPetr Machata
19568fcac792SPetr Machatabail_on_lldpad()
19578fcac792SPetr Machata{
19588fcac792SPetr Machata	local reason1="$1"; shift
19598fcac792SPetr Machata	local reason2="$1"; shift
19608fcac792SPetr Machata
19618fcac792SPetr Machata	if systemctl is-active --quiet lldpad; then
19628fcac792SPetr Machata
19638fcac792SPetr Machata		cat >/dev/stderr <<-EOF
19648fcac792SPetr Machata		WARNING: lldpad is running
19658fcac792SPetr Machata
19668fcac792SPetr Machata			lldpad will likely $reason1, and this test will
19678fcac792SPetr Machata			$reason2. Both are not supported at the same time,
19688fcac792SPetr Machata			one of them is arbitrarily going to overwrite the
19698fcac792SPetr Machata			other. That will cause spurious failures (or, unlikely,
19708fcac792SPetr Machata			passes) of this test.
19718fcac792SPetr Machata		EOF
19728fcac792SPetr Machata
19738fcac792SPetr Machata		if [[ -z $ALLOW_LLDPAD ]]; then
19748fcac792SPetr Machata			cat >/dev/stderr <<-EOF
19758fcac792SPetr Machata
19768fcac792SPetr Machata				If you want to run the test anyway, please set
19778fcac792SPetr Machata				an environment variable ALLOW_LLDPAD to a
19788fcac792SPetr Machata				non-empty string.
19798fcac792SPetr Machata			EOF
19808fcac792SPetr Machata			exit 1
19818fcac792SPetr Machata		else
19828fcac792SPetr Machata			return
19838fcac792SPetr Machata		fi
19848fcac792SPetr Machata	fi
19858fcac792SPetr Machata}
1986