162306a36Sopenharmony_ci#!/bin/bash
262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci##############################################################################
562306a36Sopenharmony_ci# Defines
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci# Kselftest framework requirement - SKIP code is 4.
862306a36Sopenharmony_ciksft_skip=4
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci# Can be overridden by the configuration file.
1162306a36Sopenharmony_ciPING=${PING:=ping}
1262306a36Sopenharmony_ciPING6=${PING6:=ping6}
1362306a36Sopenharmony_ciMZ=${MZ:=mausezahn}
1462306a36Sopenharmony_ciARPING=${ARPING:=arping}
1562306a36Sopenharmony_ciTEAMD=${TEAMD:=teamd}
1662306a36Sopenharmony_ciWAIT_TIME=${WAIT_TIME:=5}
1762306a36Sopenharmony_ciPAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
1862306a36Sopenharmony_ciPAUSE_ON_CLEANUP=${PAUSE_ON_CLEANUP:=no}
1962306a36Sopenharmony_ciNETIF_TYPE=${NETIF_TYPE:=veth}
2062306a36Sopenharmony_ciNETIF_CREATE=${NETIF_CREATE:=yes}
2162306a36Sopenharmony_ciMCD=${MCD:=smcrouted}
2262306a36Sopenharmony_ciMC_CLI=${MC_CLI:=smcroutectl}
2362306a36Sopenharmony_ciPING_COUNT=${PING_COUNT:=10}
2462306a36Sopenharmony_ciPING_TIMEOUT=${PING_TIMEOUT:=5}
2562306a36Sopenharmony_ciWAIT_TIMEOUT=${WAIT_TIMEOUT:=20}
2662306a36Sopenharmony_ciINTERFACE_TIMEOUT=${INTERFACE_TIMEOUT:=600}
2762306a36Sopenharmony_ciLOW_AGEING_TIME=${LOW_AGEING_TIME:=1000}
2862306a36Sopenharmony_ciREQUIRE_JQ=${REQUIRE_JQ:=yes}
2962306a36Sopenharmony_ciREQUIRE_MZ=${REQUIRE_MZ:=yes}
3062306a36Sopenharmony_ciREQUIRE_MTOOLS=${REQUIRE_MTOOLS:=no}
3162306a36Sopenharmony_ciSTABLE_MAC_ADDRS=${STABLE_MAC_ADDRS:=no}
3262306a36Sopenharmony_ciTCPDUMP_EXTRA_FLAGS=${TCPDUMP_EXTRA_FLAGS:=}
3362306a36Sopenharmony_ciTROUTE6=${TROUTE6:=traceroute6}
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cirelative_path="${BASH_SOURCE%/*}"
3662306a36Sopenharmony_ciif [[ "$relative_path" == "${BASH_SOURCE}" ]]; then
3762306a36Sopenharmony_ci	relative_path="."
3862306a36Sopenharmony_cifi
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ciif [[ -f $relative_path/forwarding.config ]]; then
4162306a36Sopenharmony_ci	source "$relative_path/forwarding.config"
4262306a36Sopenharmony_cifi
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci##############################################################################
4562306a36Sopenharmony_ci# Sanity checks
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cicheck_tc_version()
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	tc -j &> /dev/null
5062306a36Sopenharmony_ci	if [[ $? -ne 0 ]]; then
5162306a36Sopenharmony_ci		echo "SKIP: iproute2 too old; tc is missing JSON support"
5262306a36Sopenharmony_ci		exit $ksft_skip
5362306a36Sopenharmony_ci	fi
5462306a36Sopenharmony_ci}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci# Old versions of tc don't understand "mpls_uc"
5762306a36Sopenharmony_cicheck_tc_mpls_support()
5862306a36Sopenharmony_ci{
5962306a36Sopenharmony_ci	local dev=$1; shift
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	tc filter add dev $dev ingress protocol mpls_uc pref 1 handle 1 \
6262306a36Sopenharmony_ci		matchall action pipe &> /dev/null
6362306a36Sopenharmony_ci	if [[ $? -ne 0 ]]; then
6462306a36Sopenharmony_ci		echo "SKIP: iproute2 too old; tc is missing MPLS support"
6562306a36Sopenharmony_ci		return $ksft_skip
6662306a36Sopenharmony_ci	fi
6762306a36Sopenharmony_ci	tc filter del dev $dev ingress protocol mpls_uc pref 1 handle 1 \
6862306a36Sopenharmony_ci		matchall
6962306a36Sopenharmony_ci}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci# Old versions of tc produce invalid json output for mpls lse statistics
7262306a36Sopenharmony_cicheck_tc_mpls_lse_stats()
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	local dev=$1; shift
7562306a36Sopenharmony_ci	local ret;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	tc filter add dev $dev ingress protocol mpls_uc pref 1 handle 1 \
7862306a36Sopenharmony_ci		flower mpls lse depth 2                                 \
7962306a36Sopenharmony_ci		action continue &> /dev/null
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	if [[ $? -ne 0 ]]; then
8262306a36Sopenharmony_ci		echo "SKIP: iproute2 too old; tc-flower is missing extended MPLS support"
8362306a36Sopenharmony_ci		return $ksft_skip
8462306a36Sopenharmony_ci	fi
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	tc -j filter show dev $dev ingress protocol mpls_uc | jq . &> /dev/null
8762306a36Sopenharmony_ci	ret=$?
8862306a36Sopenharmony_ci	tc filter del dev $dev ingress protocol mpls_uc pref 1 handle 1 \
8962306a36Sopenharmony_ci		flower
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	if [[ $ret -ne 0 ]]; then
9262306a36Sopenharmony_ci		echo "SKIP: iproute2 too old; tc-flower produces invalid json output for extended MPLS filters"
9362306a36Sopenharmony_ci		return $ksft_skip
9462306a36Sopenharmony_ci	fi
9562306a36Sopenharmony_ci}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_cicheck_tc_shblock_support()
9862306a36Sopenharmony_ci{
9962306a36Sopenharmony_ci	tc filter help 2>&1 | grep block &> /dev/null
10062306a36Sopenharmony_ci	if [[ $? -ne 0 ]]; then
10162306a36Sopenharmony_ci		echo "SKIP: iproute2 too old; tc is missing shared block support"
10262306a36Sopenharmony_ci		exit $ksft_skip
10362306a36Sopenharmony_ci	fi
10462306a36Sopenharmony_ci}
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_cicheck_tc_chain_support()
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	tc help 2>&1|grep chain &> /dev/null
10962306a36Sopenharmony_ci	if [[ $? -ne 0 ]]; then
11062306a36Sopenharmony_ci		echo "SKIP: iproute2 too old; tc is missing chain support"
11162306a36Sopenharmony_ci		exit $ksft_skip
11262306a36Sopenharmony_ci	fi
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cicheck_tc_action_hw_stats_support()
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	tc actions help 2>&1 | grep -q hw_stats
11862306a36Sopenharmony_ci	if [[ $? -ne 0 ]]; then
11962306a36Sopenharmony_ci		echo "SKIP: iproute2 too old; tc is missing action hw_stats support"
12062306a36Sopenharmony_ci		exit $ksft_skip
12162306a36Sopenharmony_ci	fi
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_cicheck_tc_fp_support()
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci	tc qdisc add dev lo mqprio help 2>&1 | grep -q "fp "
12762306a36Sopenharmony_ci	if [[ $? -ne 0 ]]; then
12862306a36Sopenharmony_ci		echo "SKIP: iproute2 too old; tc is missing frame preemption support"
12962306a36Sopenharmony_ci		exit $ksft_skip
13062306a36Sopenharmony_ci	fi
13162306a36Sopenharmony_ci}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_cicheck_ethtool_lanes_support()
13462306a36Sopenharmony_ci{
13562306a36Sopenharmony_ci	ethtool --help 2>&1| grep lanes &> /dev/null
13662306a36Sopenharmony_ci	if [[ $? -ne 0 ]]; then
13762306a36Sopenharmony_ci		echo "SKIP: ethtool too old; it is missing lanes support"
13862306a36Sopenharmony_ci		exit $ksft_skip
13962306a36Sopenharmony_ci	fi
14062306a36Sopenharmony_ci}
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cicheck_ethtool_mm_support()
14362306a36Sopenharmony_ci{
14462306a36Sopenharmony_ci	ethtool --help 2>&1| grep -- '--show-mm' &> /dev/null
14562306a36Sopenharmony_ci	if [[ $? -ne 0 ]]; then
14662306a36Sopenharmony_ci		echo "SKIP: ethtool too old; it is missing MAC Merge layer support"
14762306a36Sopenharmony_ci		exit $ksft_skip
14862306a36Sopenharmony_ci	fi
14962306a36Sopenharmony_ci}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cicheck_locked_port_support()
15262306a36Sopenharmony_ci{
15362306a36Sopenharmony_ci	if ! bridge -d link show | grep -q " locked"; then
15462306a36Sopenharmony_ci		echo "SKIP: iproute2 too old; Locked port feature not supported."
15562306a36Sopenharmony_ci		return $ksft_skip
15662306a36Sopenharmony_ci	fi
15762306a36Sopenharmony_ci}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_cicheck_port_mab_support()
16062306a36Sopenharmony_ci{
16162306a36Sopenharmony_ci	if ! bridge -d link show | grep -q "mab"; then
16262306a36Sopenharmony_ci		echo "SKIP: iproute2 too old; MacAuth feature not supported."
16362306a36Sopenharmony_ci		return $ksft_skip
16462306a36Sopenharmony_ci	fi
16562306a36Sopenharmony_ci}
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ciskip_on_veth()
16862306a36Sopenharmony_ci{
16962306a36Sopenharmony_ci	local kind=$(ip -j -d link show dev ${NETIFS[p1]} |
17062306a36Sopenharmony_ci		jq -r '.[].linkinfo.info_kind')
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	if [[ $kind == veth ]]; then
17362306a36Sopenharmony_ci		echo "SKIP: Test cannot be run with veth pairs"
17462306a36Sopenharmony_ci		exit $ksft_skip
17562306a36Sopenharmony_ci	fi
17662306a36Sopenharmony_ci}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ciif [[ "$(id -u)" -ne 0 ]]; then
17962306a36Sopenharmony_ci	echo "SKIP: need root privileges"
18062306a36Sopenharmony_ci	exit $ksft_skip
18162306a36Sopenharmony_cifi
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ciif [[ "$CHECK_TC" = "yes" ]]; then
18462306a36Sopenharmony_ci	check_tc_version
18562306a36Sopenharmony_cifi
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_cirequire_command()
18862306a36Sopenharmony_ci{
18962306a36Sopenharmony_ci	local cmd=$1; shift
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	if [[ ! -x "$(command -v "$cmd")" ]]; then
19262306a36Sopenharmony_ci		echo "SKIP: $cmd not installed"
19362306a36Sopenharmony_ci		exit $ksft_skip
19462306a36Sopenharmony_ci	fi
19562306a36Sopenharmony_ci}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ciif [[ "$REQUIRE_JQ" = "yes" ]]; then
19862306a36Sopenharmony_ci	require_command jq
19962306a36Sopenharmony_cifi
20062306a36Sopenharmony_ciif [[ "$REQUIRE_MZ" = "yes" ]]; then
20162306a36Sopenharmony_ci	require_command $MZ
20262306a36Sopenharmony_cifi
20362306a36Sopenharmony_ciif [[ "$REQUIRE_MTOOLS" = "yes" ]]; then
20462306a36Sopenharmony_ci	# https://github.com/vladimiroltean/mtools/
20562306a36Sopenharmony_ci	# patched for IPv6 support
20662306a36Sopenharmony_ci	require_command msend
20762306a36Sopenharmony_ci	require_command mreceive
20862306a36Sopenharmony_cifi
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ciif [[ ! -v NUM_NETIFS ]]; then
21162306a36Sopenharmony_ci	echo "SKIP: importer does not define \"NUM_NETIFS\""
21262306a36Sopenharmony_ci	exit $ksft_skip
21362306a36Sopenharmony_cifi
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci##############################################################################
21662306a36Sopenharmony_ci# Command line options handling
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_cicount=0
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ciwhile [[ $# -gt 0 ]]; do
22162306a36Sopenharmony_ci	if [[ "$count" -eq "0" ]]; then
22262306a36Sopenharmony_ci		unset NETIFS
22362306a36Sopenharmony_ci		declare -A NETIFS
22462306a36Sopenharmony_ci	fi
22562306a36Sopenharmony_ci	count=$((count + 1))
22662306a36Sopenharmony_ci	NETIFS[p$count]="$1"
22762306a36Sopenharmony_ci	shift
22862306a36Sopenharmony_cidone
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci##############################################################################
23162306a36Sopenharmony_ci# Network interfaces configuration
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_cicreate_netif_veth()
23462306a36Sopenharmony_ci{
23562306a36Sopenharmony_ci	local i
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	for ((i = 1; i <= NUM_NETIFS; ++i)); do
23862306a36Sopenharmony_ci		local j=$((i+1))
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci		if [ -z ${NETIFS[p$i]} ]; then
24162306a36Sopenharmony_ci			echo "SKIP: Cannot create interface. Name not specified"
24262306a36Sopenharmony_ci			exit $ksft_skip
24362306a36Sopenharmony_ci		fi
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci		ip link show dev ${NETIFS[p$i]} &> /dev/null
24662306a36Sopenharmony_ci		if [[ $? -ne 0 ]]; then
24762306a36Sopenharmony_ci			ip link add ${NETIFS[p$i]} type veth \
24862306a36Sopenharmony_ci				peer name ${NETIFS[p$j]}
24962306a36Sopenharmony_ci			if [[ $? -ne 0 ]]; then
25062306a36Sopenharmony_ci				echo "Failed to create netif"
25162306a36Sopenharmony_ci				exit 1
25262306a36Sopenharmony_ci			fi
25362306a36Sopenharmony_ci		fi
25462306a36Sopenharmony_ci		i=$j
25562306a36Sopenharmony_ci	done
25662306a36Sopenharmony_ci}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_cicreate_netif()
25962306a36Sopenharmony_ci{
26062306a36Sopenharmony_ci	case "$NETIF_TYPE" in
26162306a36Sopenharmony_ci	veth) create_netif_veth
26262306a36Sopenharmony_ci	      ;;
26362306a36Sopenharmony_ci	*) echo "Can not create interfaces of type \'$NETIF_TYPE\'"
26462306a36Sopenharmony_ci	   exit 1
26562306a36Sopenharmony_ci	   ;;
26662306a36Sopenharmony_ci	esac
26762306a36Sopenharmony_ci}
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_cideclare -A MAC_ADDR_ORIG
27062306a36Sopenharmony_cimac_addr_prepare()
27162306a36Sopenharmony_ci{
27262306a36Sopenharmony_ci	local new_addr=
27362306a36Sopenharmony_ci	local dev=
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	for ((i = 1; i <= NUM_NETIFS; ++i)); do
27662306a36Sopenharmony_ci		dev=${NETIFS[p$i]}
27762306a36Sopenharmony_ci		new_addr=$(printf "00:01:02:03:04:%02x" $i)
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci		MAC_ADDR_ORIG["$dev"]=$(ip -j link show dev $dev | jq -e '.[].address')
28062306a36Sopenharmony_ci		# Strip quotes
28162306a36Sopenharmony_ci		MAC_ADDR_ORIG["$dev"]=${MAC_ADDR_ORIG["$dev"]//\"/}
28262306a36Sopenharmony_ci		ip link set dev $dev address $new_addr
28362306a36Sopenharmony_ci	done
28462306a36Sopenharmony_ci}
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_cimac_addr_restore()
28762306a36Sopenharmony_ci{
28862306a36Sopenharmony_ci	local dev=
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	for ((i = 1; i <= NUM_NETIFS; ++i)); do
29162306a36Sopenharmony_ci		dev=${NETIFS[p$i]}
29262306a36Sopenharmony_ci		ip link set dev $dev address ${MAC_ADDR_ORIG["$dev"]}
29362306a36Sopenharmony_ci	done
29462306a36Sopenharmony_ci}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ciif [[ "$NETIF_CREATE" = "yes" ]]; then
29762306a36Sopenharmony_ci	create_netif
29862306a36Sopenharmony_cifi
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ciif [[ "$STABLE_MAC_ADDRS" = "yes" ]]; then
30162306a36Sopenharmony_ci	mac_addr_prepare
30262306a36Sopenharmony_cifi
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_cifor ((i = 1; i <= NUM_NETIFS; ++i)); do
30562306a36Sopenharmony_ci	ip link show dev ${NETIFS[p$i]} &> /dev/null
30662306a36Sopenharmony_ci	if [[ $? -ne 0 ]]; then
30762306a36Sopenharmony_ci		echo "SKIP: could not find all required interfaces"
30862306a36Sopenharmony_ci		exit $ksft_skip
30962306a36Sopenharmony_ci	fi
31062306a36Sopenharmony_cidone
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci##############################################################################
31362306a36Sopenharmony_ci# Helpers
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci# Exit status to return at the end. Set in case one of the tests fails.
31662306a36Sopenharmony_ciEXIT_STATUS=0
31762306a36Sopenharmony_ci# Per-test return value. Clear at the beginning of each test.
31862306a36Sopenharmony_ciRET=0
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_cicheck_err()
32162306a36Sopenharmony_ci{
32262306a36Sopenharmony_ci	local err=$1
32362306a36Sopenharmony_ci	local msg=$2
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	if [[ $RET -eq 0 && $err -ne 0 ]]; then
32662306a36Sopenharmony_ci		RET=$err
32762306a36Sopenharmony_ci		retmsg=$msg
32862306a36Sopenharmony_ci	fi
32962306a36Sopenharmony_ci}
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_cicheck_fail()
33262306a36Sopenharmony_ci{
33362306a36Sopenharmony_ci	local err=$1
33462306a36Sopenharmony_ci	local msg=$2
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	if [[ $RET -eq 0 && $err -eq 0 ]]; then
33762306a36Sopenharmony_ci		RET=1
33862306a36Sopenharmony_ci		retmsg=$msg
33962306a36Sopenharmony_ci	fi
34062306a36Sopenharmony_ci}
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_cicheck_err_fail()
34362306a36Sopenharmony_ci{
34462306a36Sopenharmony_ci	local should_fail=$1; shift
34562306a36Sopenharmony_ci	local err=$1; shift
34662306a36Sopenharmony_ci	local what=$1; shift
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	if ((should_fail)); then
34962306a36Sopenharmony_ci		check_fail $err "$what succeeded, but should have failed"
35062306a36Sopenharmony_ci	else
35162306a36Sopenharmony_ci		check_err $err "$what failed"
35262306a36Sopenharmony_ci	fi
35362306a36Sopenharmony_ci}
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_cilog_test()
35662306a36Sopenharmony_ci{
35762306a36Sopenharmony_ci	local test_name=$1
35862306a36Sopenharmony_ci	local opt_str=$2
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	if [[ $# -eq 2 ]]; then
36162306a36Sopenharmony_ci		opt_str="($opt_str)"
36262306a36Sopenharmony_ci	fi
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	if [[ $RET -ne 0 ]]; then
36562306a36Sopenharmony_ci		EXIT_STATUS=1
36662306a36Sopenharmony_ci		printf "TEST: %-60s  [FAIL]\n" "$test_name $opt_str"
36762306a36Sopenharmony_ci		if [[ ! -z "$retmsg" ]]; then
36862306a36Sopenharmony_ci			printf "\t%s\n" "$retmsg"
36962306a36Sopenharmony_ci		fi
37062306a36Sopenharmony_ci		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
37162306a36Sopenharmony_ci			echo "Hit enter to continue, 'q' to quit"
37262306a36Sopenharmony_ci			read a
37362306a36Sopenharmony_ci			[ "$a" = "q" ] && exit 1
37462306a36Sopenharmony_ci		fi
37562306a36Sopenharmony_ci		return 1
37662306a36Sopenharmony_ci	fi
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci	printf "TEST: %-60s  [ OK ]\n" "$test_name $opt_str"
37962306a36Sopenharmony_ci	return 0
38062306a36Sopenharmony_ci}
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_cilog_test_skip()
38362306a36Sopenharmony_ci{
38462306a36Sopenharmony_ci	local test_name=$1
38562306a36Sopenharmony_ci	local opt_str=$2
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	printf "TEST: %-60s  [SKIP]\n" "$test_name $opt_str"
38862306a36Sopenharmony_ci	return 0
38962306a36Sopenharmony_ci}
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_cilog_info()
39262306a36Sopenharmony_ci{
39362306a36Sopenharmony_ci	local msg=$1
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci	echo "INFO: $msg"
39662306a36Sopenharmony_ci}
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_cibusywait()
39962306a36Sopenharmony_ci{
40062306a36Sopenharmony_ci	local timeout=$1; shift
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	local start_time="$(date -u +%s%3N)"
40362306a36Sopenharmony_ci	while true
40462306a36Sopenharmony_ci	do
40562306a36Sopenharmony_ci		local out
40662306a36Sopenharmony_ci		out=$("$@")
40762306a36Sopenharmony_ci		local ret=$?
40862306a36Sopenharmony_ci		if ((!ret)); then
40962306a36Sopenharmony_ci			echo -n "$out"
41062306a36Sopenharmony_ci			return 0
41162306a36Sopenharmony_ci		fi
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci		local current_time="$(date -u +%s%3N)"
41462306a36Sopenharmony_ci		if ((current_time - start_time > timeout)); then
41562306a36Sopenharmony_ci			echo -n "$out"
41662306a36Sopenharmony_ci			return 1
41762306a36Sopenharmony_ci		fi
41862306a36Sopenharmony_ci	done
41962306a36Sopenharmony_ci}
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_cinot()
42262306a36Sopenharmony_ci{
42362306a36Sopenharmony_ci	"$@"
42462306a36Sopenharmony_ci	[[ $? != 0 ]]
42562306a36Sopenharmony_ci}
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ciget_max()
42862306a36Sopenharmony_ci{
42962306a36Sopenharmony_ci	local arr=("$@")
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	max=${arr[0]}
43262306a36Sopenharmony_ci	for cur in ${arr[@]}; do
43362306a36Sopenharmony_ci		if [[ $cur -gt $max ]]; then
43462306a36Sopenharmony_ci			max=$cur
43562306a36Sopenharmony_ci		fi
43662306a36Sopenharmony_ci	done
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	echo $max
43962306a36Sopenharmony_ci}
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_cigrep_bridge_fdb()
44262306a36Sopenharmony_ci{
44362306a36Sopenharmony_ci	local addr=$1; shift
44462306a36Sopenharmony_ci	local word
44562306a36Sopenharmony_ci	local flag
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	if [ "$1" == "self" ] || [ "$1" == "master" ]; then
44862306a36Sopenharmony_ci		word=$1; shift
44962306a36Sopenharmony_ci		if [ "$1" == "-v" ]; then
45062306a36Sopenharmony_ci			flag=$1; shift
45162306a36Sopenharmony_ci		fi
45262306a36Sopenharmony_ci	fi
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	$@ | grep $addr | grep $flag "$word"
45562306a36Sopenharmony_ci}
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ciwait_for_port_up()
45862306a36Sopenharmony_ci{
45962306a36Sopenharmony_ci	"$@" | grep -q "Link detected: yes"
46062306a36Sopenharmony_ci}
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ciwait_for_offload()
46362306a36Sopenharmony_ci{
46462306a36Sopenharmony_ci	"$@" | grep -q offload
46562306a36Sopenharmony_ci}
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ciwait_for_trap()
46862306a36Sopenharmony_ci{
46962306a36Sopenharmony_ci	"$@" | grep -q trap
47062306a36Sopenharmony_ci}
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ciuntil_counter_is()
47362306a36Sopenharmony_ci{
47462306a36Sopenharmony_ci	local expr=$1; shift
47562306a36Sopenharmony_ci	local current=$("$@")
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	echo $((current))
47862306a36Sopenharmony_ci	((current $expr))
47962306a36Sopenharmony_ci}
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_cibusywait_for_counter()
48262306a36Sopenharmony_ci{
48362306a36Sopenharmony_ci	local timeout=$1; shift
48462306a36Sopenharmony_ci	local delta=$1; shift
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	local base=$("$@")
48762306a36Sopenharmony_ci	busywait "$timeout" until_counter_is ">= $((base + delta))" "$@"
48862306a36Sopenharmony_ci}
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_cisetup_wait_dev()
49162306a36Sopenharmony_ci{
49262306a36Sopenharmony_ci	local dev=$1; shift
49362306a36Sopenharmony_ci	local wait_time=${1:-$WAIT_TIME}; shift
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	setup_wait_dev_with_timeout "$dev" $INTERFACE_TIMEOUT $wait_time
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	if (($?)); then
49862306a36Sopenharmony_ci		check_err 1
49962306a36Sopenharmony_ci		log_test setup_wait_dev ": Interface $dev does not come up."
50062306a36Sopenharmony_ci		exit 1
50162306a36Sopenharmony_ci	fi
50262306a36Sopenharmony_ci}
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_cisetup_wait_dev_with_timeout()
50562306a36Sopenharmony_ci{
50662306a36Sopenharmony_ci	local dev=$1; shift
50762306a36Sopenharmony_ci	local max_iterations=${1:-$WAIT_TIMEOUT}; shift
50862306a36Sopenharmony_ci	local wait_time=${1:-$WAIT_TIME}; shift
50962306a36Sopenharmony_ci	local i
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	for ((i = 1; i <= $max_iterations; ++i)); do
51262306a36Sopenharmony_ci		ip link show dev $dev up \
51362306a36Sopenharmony_ci			| grep 'state UP' &> /dev/null
51462306a36Sopenharmony_ci		if [[ $? -ne 0 ]]; then
51562306a36Sopenharmony_ci			sleep 1
51662306a36Sopenharmony_ci		else
51762306a36Sopenharmony_ci			sleep $wait_time
51862306a36Sopenharmony_ci			return 0
51962306a36Sopenharmony_ci		fi
52062306a36Sopenharmony_ci	done
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	return 1
52362306a36Sopenharmony_ci}
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_cisetup_wait()
52662306a36Sopenharmony_ci{
52762306a36Sopenharmony_ci	local num_netifs=${1:-$NUM_NETIFS}
52862306a36Sopenharmony_ci	local i
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	for ((i = 1; i <= num_netifs; ++i)); do
53162306a36Sopenharmony_ci		setup_wait_dev ${NETIFS[p$i]} 0
53262306a36Sopenharmony_ci	done
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	# Make sure links are ready.
53562306a36Sopenharmony_ci	sleep $WAIT_TIME
53662306a36Sopenharmony_ci}
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_cicmd_jq()
53962306a36Sopenharmony_ci{
54062306a36Sopenharmony_ci	local cmd=$1
54162306a36Sopenharmony_ci	local jq_exp=$2
54262306a36Sopenharmony_ci	local jq_opts=$3
54362306a36Sopenharmony_ci	local ret
54462306a36Sopenharmony_ci	local output
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	output="$($cmd)"
54762306a36Sopenharmony_ci	# it the command fails, return error right away
54862306a36Sopenharmony_ci	ret=$?
54962306a36Sopenharmony_ci	if [[ $ret -ne 0 ]]; then
55062306a36Sopenharmony_ci		return $ret
55162306a36Sopenharmony_ci	fi
55262306a36Sopenharmony_ci	output=$(echo $output | jq -r $jq_opts "$jq_exp")
55362306a36Sopenharmony_ci	ret=$?
55462306a36Sopenharmony_ci	if [[ $ret -ne 0 ]]; then
55562306a36Sopenharmony_ci		return $ret
55662306a36Sopenharmony_ci	fi
55762306a36Sopenharmony_ci	echo $output
55862306a36Sopenharmony_ci	# return success only in case of non-empty output
55962306a36Sopenharmony_ci	[ ! -z "$output" ]
56062306a36Sopenharmony_ci}
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_cipre_cleanup()
56362306a36Sopenharmony_ci{
56462306a36Sopenharmony_ci	if [ "${PAUSE_ON_CLEANUP}" = "yes" ]; then
56562306a36Sopenharmony_ci		echo "Pausing before cleanup, hit any key to continue"
56662306a36Sopenharmony_ci		read
56762306a36Sopenharmony_ci	fi
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	if [[ "$STABLE_MAC_ADDRS" = "yes" ]]; then
57062306a36Sopenharmony_ci		mac_addr_restore
57162306a36Sopenharmony_ci	fi
57262306a36Sopenharmony_ci}
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_civrf_prepare()
57562306a36Sopenharmony_ci{
57662306a36Sopenharmony_ci	ip -4 rule add pref 32765 table local
57762306a36Sopenharmony_ci	ip -4 rule del pref 0
57862306a36Sopenharmony_ci	ip -6 rule add pref 32765 table local
57962306a36Sopenharmony_ci	ip -6 rule del pref 0
58062306a36Sopenharmony_ci}
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_civrf_cleanup()
58362306a36Sopenharmony_ci{
58462306a36Sopenharmony_ci	ip -6 rule add pref 0 table local
58562306a36Sopenharmony_ci	ip -6 rule del pref 32765
58662306a36Sopenharmony_ci	ip -4 rule add pref 0 table local
58762306a36Sopenharmony_ci	ip -4 rule del pref 32765
58862306a36Sopenharmony_ci}
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci__last_tb_id=0
59162306a36Sopenharmony_cideclare -A __TB_IDS
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci__vrf_td_id_assign()
59462306a36Sopenharmony_ci{
59562306a36Sopenharmony_ci	local vrf_name=$1
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	__last_tb_id=$((__last_tb_id + 1))
59862306a36Sopenharmony_ci	__TB_IDS[$vrf_name]=$__last_tb_id
59962306a36Sopenharmony_ci	return $__last_tb_id
60062306a36Sopenharmony_ci}
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci__vrf_td_id_lookup()
60362306a36Sopenharmony_ci{
60462306a36Sopenharmony_ci	local vrf_name=$1
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci	return ${__TB_IDS[$vrf_name]}
60762306a36Sopenharmony_ci}
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_civrf_create()
61062306a36Sopenharmony_ci{
61162306a36Sopenharmony_ci	local vrf_name=$1
61262306a36Sopenharmony_ci	local tb_id
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	__vrf_td_id_assign $vrf_name
61562306a36Sopenharmony_ci	tb_id=$?
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	ip link add dev $vrf_name type vrf table $tb_id
61862306a36Sopenharmony_ci	ip -4 route add table $tb_id unreachable default metric 4278198272
61962306a36Sopenharmony_ci	ip -6 route add table $tb_id unreachable default metric 4278198272
62062306a36Sopenharmony_ci}
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_civrf_destroy()
62362306a36Sopenharmony_ci{
62462306a36Sopenharmony_ci	local vrf_name=$1
62562306a36Sopenharmony_ci	local tb_id
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_ci	__vrf_td_id_lookup $vrf_name
62862306a36Sopenharmony_ci	tb_id=$?
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ci	ip -6 route del table $tb_id unreachable default metric 4278198272
63162306a36Sopenharmony_ci	ip -4 route del table $tb_id unreachable default metric 4278198272
63262306a36Sopenharmony_ci	ip link del dev $vrf_name
63362306a36Sopenharmony_ci}
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci__addr_add_del()
63662306a36Sopenharmony_ci{
63762306a36Sopenharmony_ci	local if_name=$1
63862306a36Sopenharmony_ci	local add_del=$2
63962306a36Sopenharmony_ci	local array
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci	shift
64262306a36Sopenharmony_ci	shift
64362306a36Sopenharmony_ci	array=("${@}")
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	for addrstr in "${array[@]}"; do
64662306a36Sopenharmony_ci		ip address $add_del $addrstr dev $if_name
64762306a36Sopenharmony_ci	done
64862306a36Sopenharmony_ci}
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci__simple_if_init()
65162306a36Sopenharmony_ci{
65262306a36Sopenharmony_ci	local if_name=$1; shift
65362306a36Sopenharmony_ci	local vrf_name=$1; shift
65462306a36Sopenharmony_ci	local addrs=("${@}")
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci	ip link set dev $if_name master $vrf_name
65762306a36Sopenharmony_ci	ip link set dev $if_name up
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci	__addr_add_del $if_name add "${addrs[@]}"
66062306a36Sopenharmony_ci}
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci__simple_if_fini()
66362306a36Sopenharmony_ci{
66462306a36Sopenharmony_ci	local if_name=$1; shift
66562306a36Sopenharmony_ci	local addrs=("${@}")
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci	__addr_add_del $if_name del "${addrs[@]}"
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	ip link set dev $if_name down
67062306a36Sopenharmony_ci	ip link set dev $if_name nomaster
67162306a36Sopenharmony_ci}
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_cisimple_if_init()
67462306a36Sopenharmony_ci{
67562306a36Sopenharmony_ci	local if_name=$1
67662306a36Sopenharmony_ci	local vrf_name
67762306a36Sopenharmony_ci	local array
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci	shift
68062306a36Sopenharmony_ci	vrf_name=v$if_name
68162306a36Sopenharmony_ci	array=("${@}")
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci	vrf_create $vrf_name
68462306a36Sopenharmony_ci	ip link set dev $vrf_name up
68562306a36Sopenharmony_ci	__simple_if_init $if_name $vrf_name "${array[@]}"
68662306a36Sopenharmony_ci}
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_cisimple_if_fini()
68962306a36Sopenharmony_ci{
69062306a36Sopenharmony_ci	local if_name=$1
69162306a36Sopenharmony_ci	local vrf_name
69262306a36Sopenharmony_ci	local array
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci	shift
69562306a36Sopenharmony_ci	vrf_name=v$if_name
69662306a36Sopenharmony_ci	array=("${@}")
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	__simple_if_fini $if_name "${array[@]}"
69962306a36Sopenharmony_ci	vrf_destroy $vrf_name
70062306a36Sopenharmony_ci}
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_citunnel_create()
70362306a36Sopenharmony_ci{
70462306a36Sopenharmony_ci	local name=$1; shift
70562306a36Sopenharmony_ci	local type=$1; shift
70662306a36Sopenharmony_ci	local local=$1; shift
70762306a36Sopenharmony_ci	local remote=$1; shift
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci	ip link add name $name type $type \
71062306a36Sopenharmony_ci	   local $local remote $remote "$@"
71162306a36Sopenharmony_ci	ip link set dev $name up
71262306a36Sopenharmony_ci}
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_citunnel_destroy()
71562306a36Sopenharmony_ci{
71662306a36Sopenharmony_ci	local name=$1; shift
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	ip link del dev $name
71962306a36Sopenharmony_ci}
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_civlan_create()
72262306a36Sopenharmony_ci{
72362306a36Sopenharmony_ci	local if_name=$1; shift
72462306a36Sopenharmony_ci	local vid=$1; shift
72562306a36Sopenharmony_ci	local vrf=$1; shift
72662306a36Sopenharmony_ci	local ips=("${@}")
72762306a36Sopenharmony_ci	local name=$if_name.$vid
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci	ip link add name $name link $if_name type vlan id $vid
73062306a36Sopenharmony_ci	if [ "$vrf" != "" ]; then
73162306a36Sopenharmony_ci		ip link set dev $name master $vrf
73262306a36Sopenharmony_ci	fi
73362306a36Sopenharmony_ci	ip link set dev $name up
73462306a36Sopenharmony_ci	__addr_add_del $name add "${ips[@]}"
73562306a36Sopenharmony_ci}
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_civlan_destroy()
73862306a36Sopenharmony_ci{
73962306a36Sopenharmony_ci	local if_name=$1; shift
74062306a36Sopenharmony_ci	local vid=$1; shift
74162306a36Sopenharmony_ci	local name=$if_name.$vid
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci	ip link del dev $name
74462306a36Sopenharmony_ci}
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_citeam_create()
74762306a36Sopenharmony_ci{
74862306a36Sopenharmony_ci	local if_name=$1; shift
74962306a36Sopenharmony_ci	local mode=$1; shift
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	require_command $TEAMD
75262306a36Sopenharmony_ci	$TEAMD -t $if_name -d -c '{"runner": {"name": "'$mode'"}}'
75362306a36Sopenharmony_ci	for slave in "$@"; do
75462306a36Sopenharmony_ci		ip link set dev $slave down
75562306a36Sopenharmony_ci		ip link set dev $slave master $if_name
75662306a36Sopenharmony_ci		ip link set dev $slave up
75762306a36Sopenharmony_ci	done
75862306a36Sopenharmony_ci	ip link set dev $if_name up
75962306a36Sopenharmony_ci}
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_citeam_destroy()
76262306a36Sopenharmony_ci{
76362306a36Sopenharmony_ci	local if_name=$1; shift
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci	$TEAMD -t $if_name -k
76662306a36Sopenharmony_ci}
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_cimaster_name_get()
76962306a36Sopenharmony_ci{
77062306a36Sopenharmony_ci	local if_name=$1
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_ci	ip -j link show dev $if_name | jq -r '.[]["master"]'
77362306a36Sopenharmony_ci}
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_cilink_stats_get()
77662306a36Sopenharmony_ci{
77762306a36Sopenharmony_ci	local if_name=$1; shift
77862306a36Sopenharmony_ci	local dir=$1; shift
77962306a36Sopenharmony_ci	local stat=$1; shift
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_ci	ip -j -s link show dev $if_name \
78262306a36Sopenharmony_ci		| jq '.[]["stats64"]["'$dir'"]["'$stat'"]'
78362306a36Sopenharmony_ci}
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_cilink_stats_tx_packets_get()
78662306a36Sopenharmony_ci{
78762306a36Sopenharmony_ci	link_stats_get $1 tx packets
78862306a36Sopenharmony_ci}
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_cilink_stats_rx_errors_get()
79162306a36Sopenharmony_ci{
79262306a36Sopenharmony_ci	link_stats_get $1 rx errors
79362306a36Sopenharmony_ci}
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_citc_rule_stats_get()
79662306a36Sopenharmony_ci{
79762306a36Sopenharmony_ci	local dev=$1; shift
79862306a36Sopenharmony_ci	local pref=$1; shift
79962306a36Sopenharmony_ci	local dir=$1; shift
80062306a36Sopenharmony_ci	local selector=${1:-.packets}; shift
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci	tc -j -s filter show dev $dev ${dir:-ingress} pref $pref \
80362306a36Sopenharmony_ci	    | jq ".[1].options.actions[].stats$selector"
80462306a36Sopenharmony_ci}
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_citc_rule_handle_stats_get()
80762306a36Sopenharmony_ci{
80862306a36Sopenharmony_ci	local id=$1; shift
80962306a36Sopenharmony_ci	local handle=$1; shift
81062306a36Sopenharmony_ci	local selector=${1:-.packets}; shift
81162306a36Sopenharmony_ci	local netns=${1:-""}; shift
81262306a36Sopenharmony_ci
81362306a36Sopenharmony_ci	tc $netns -j -s filter show $id \
81462306a36Sopenharmony_ci	    | jq ".[] | select(.options.handle == $handle) | \
81562306a36Sopenharmony_ci		  .options.actions[0].stats$selector"
81662306a36Sopenharmony_ci}
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ciethtool_stats_get()
81962306a36Sopenharmony_ci{
82062306a36Sopenharmony_ci	local dev=$1; shift
82162306a36Sopenharmony_ci	local stat=$1; shift
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci	ethtool -S $dev | grep "^ *$stat:" | head -n 1 | cut -d: -f2
82462306a36Sopenharmony_ci}
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ciethtool_std_stats_get()
82762306a36Sopenharmony_ci{
82862306a36Sopenharmony_ci	local dev=$1; shift
82962306a36Sopenharmony_ci	local grp=$1; shift
83062306a36Sopenharmony_ci	local name=$1; shift
83162306a36Sopenharmony_ci	local src=$1; shift
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci	ethtool --json -S $dev --groups $grp -- --src $src | \
83462306a36Sopenharmony_ci		jq '.[]."'"$grp"'"."'$name'"'
83562306a36Sopenharmony_ci}
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ciqdisc_stats_get()
83862306a36Sopenharmony_ci{
83962306a36Sopenharmony_ci	local dev=$1; shift
84062306a36Sopenharmony_ci	local handle=$1; shift
84162306a36Sopenharmony_ci	local selector=$1; shift
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci	tc -j -s qdisc show dev "$dev" \
84462306a36Sopenharmony_ci	    | jq '.[] | select(.handle == "'"$handle"'") | '"$selector"
84562306a36Sopenharmony_ci}
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ciqdisc_parent_stats_get()
84862306a36Sopenharmony_ci{
84962306a36Sopenharmony_ci	local dev=$1; shift
85062306a36Sopenharmony_ci	local parent=$1; shift
85162306a36Sopenharmony_ci	local selector=$1; shift
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci	tc -j -s qdisc show dev "$dev" invisible \
85462306a36Sopenharmony_ci	    | jq '.[] | select(.parent == "'"$parent"'") | '"$selector"
85562306a36Sopenharmony_ci}
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ciipv6_stats_get()
85862306a36Sopenharmony_ci{
85962306a36Sopenharmony_ci	local dev=$1; shift
86062306a36Sopenharmony_ci	local stat=$1; shift
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci	cat /proc/net/dev_snmp6/$dev | grep "^$stat" | cut -f2
86362306a36Sopenharmony_ci}
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_cihw_stats_get()
86662306a36Sopenharmony_ci{
86762306a36Sopenharmony_ci	local suite=$1; shift
86862306a36Sopenharmony_ci	local if_name=$1; shift
86962306a36Sopenharmony_ci	local dir=$1; shift
87062306a36Sopenharmony_ci	local stat=$1; shift
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci	ip -j stats show dev $if_name group offload subgroup $suite |
87362306a36Sopenharmony_ci		jq ".[0].stats64.$dir.$stat"
87462306a36Sopenharmony_ci}
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_cihumanize()
87762306a36Sopenharmony_ci{
87862306a36Sopenharmony_ci	local speed=$1; shift
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_ci	for unit in bps Kbps Mbps Gbps; do
88162306a36Sopenharmony_ci		if (($(echo "$speed < 1024" | bc))); then
88262306a36Sopenharmony_ci			break
88362306a36Sopenharmony_ci		fi
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_ci		speed=$(echo "scale=1; $speed / 1024" | bc)
88662306a36Sopenharmony_ci	done
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_ci	echo "$speed${unit}"
88962306a36Sopenharmony_ci}
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_cirate()
89262306a36Sopenharmony_ci{
89362306a36Sopenharmony_ci	local t0=$1; shift
89462306a36Sopenharmony_ci	local t1=$1; shift
89562306a36Sopenharmony_ci	local interval=$1; shift
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci	echo $((8 * (t1 - t0) / interval))
89862306a36Sopenharmony_ci}
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_cipackets_rate()
90162306a36Sopenharmony_ci{
90262306a36Sopenharmony_ci	local t0=$1; shift
90362306a36Sopenharmony_ci	local t1=$1; shift
90462306a36Sopenharmony_ci	local interval=$1; shift
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci	echo $(((t1 - t0) / interval))
90762306a36Sopenharmony_ci}
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_cimac_get()
91062306a36Sopenharmony_ci{
91162306a36Sopenharmony_ci	local if_name=$1
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci	ip -j link show dev $if_name | jq -r '.[]["address"]'
91462306a36Sopenharmony_ci}
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ciipv6_lladdr_get()
91762306a36Sopenharmony_ci{
91862306a36Sopenharmony_ci	local if_name=$1
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci	ip -j addr show dev $if_name | \
92162306a36Sopenharmony_ci		jq -r '.[]["addr_info"][] | select(.scope == "link").local' | \
92262306a36Sopenharmony_ci		head -1
92362306a36Sopenharmony_ci}
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_cibridge_ageing_time_get()
92662306a36Sopenharmony_ci{
92762306a36Sopenharmony_ci	local bridge=$1
92862306a36Sopenharmony_ci	local ageing_time
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ci	# Need to divide by 100 to convert to seconds.
93162306a36Sopenharmony_ci	ageing_time=$(ip -j -d link show dev $bridge \
93262306a36Sopenharmony_ci		      | jq '.[]["linkinfo"]["info_data"]["ageing_time"]')
93362306a36Sopenharmony_ci	echo $((ageing_time / 100))
93462306a36Sopenharmony_ci}
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_cideclare -A SYSCTL_ORIG
93762306a36Sopenharmony_cisysctl_set()
93862306a36Sopenharmony_ci{
93962306a36Sopenharmony_ci	local key=$1; shift
94062306a36Sopenharmony_ci	local value=$1; shift
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci	SYSCTL_ORIG[$key]=$(sysctl -n $key)
94362306a36Sopenharmony_ci	sysctl -qw $key="$value"
94462306a36Sopenharmony_ci}
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_cisysctl_restore()
94762306a36Sopenharmony_ci{
94862306a36Sopenharmony_ci	local key=$1; shift
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci	sysctl -qw $key="${SYSCTL_ORIG[$key]}"
95162306a36Sopenharmony_ci}
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ciforwarding_enable()
95462306a36Sopenharmony_ci{
95562306a36Sopenharmony_ci	sysctl_set net.ipv4.conf.all.forwarding 1
95662306a36Sopenharmony_ci	sysctl_set net.ipv6.conf.all.forwarding 1
95762306a36Sopenharmony_ci}
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ciforwarding_restore()
96062306a36Sopenharmony_ci{
96162306a36Sopenharmony_ci	sysctl_restore net.ipv6.conf.all.forwarding
96262306a36Sopenharmony_ci	sysctl_restore net.ipv4.conf.all.forwarding
96362306a36Sopenharmony_ci}
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_cideclare -A MTU_ORIG
96662306a36Sopenharmony_cimtu_set()
96762306a36Sopenharmony_ci{
96862306a36Sopenharmony_ci	local dev=$1; shift
96962306a36Sopenharmony_ci	local mtu=$1; shift
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_ci	MTU_ORIG["$dev"]=$(ip -j link show dev $dev | jq -e '.[].mtu')
97262306a36Sopenharmony_ci	ip link set dev $dev mtu $mtu
97362306a36Sopenharmony_ci}
97462306a36Sopenharmony_ci
97562306a36Sopenharmony_cimtu_restore()
97662306a36Sopenharmony_ci{
97762306a36Sopenharmony_ci	local dev=$1; shift
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	ip link set dev $dev mtu ${MTU_ORIG["$dev"]}
98062306a36Sopenharmony_ci}
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_citc_offload_check()
98362306a36Sopenharmony_ci{
98462306a36Sopenharmony_ci	local num_netifs=${1:-$NUM_NETIFS}
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_ci	for ((i = 1; i <= num_netifs; ++i)); do
98762306a36Sopenharmony_ci		ethtool -k ${NETIFS[p$i]} \
98862306a36Sopenharmony_ci			| grep "hw-tc-offload: on" &> /dev/null
98962306a36Sopenharmony_ci		if [[ $? -ne 0 ]]; then
99062306a36Sopenharmony_ci			return 1
99162306a36Sopenharmony_ci		fi
99262306a36Sopenharmony_ci	done
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci	return 0
99562306a36Sopenharmony_ci}
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_citrap_install()
99862306a36Sopenharmony_ci{
99962306a36Sopenharmony_ci	local dev=$1; shift
100062306a36Sopenharmony_ci	local direction=$1; shift
100162306a36Sopenharmony_ci
100262306a36Sopenharmony_ci	# Some devices may not support or need in-hardware trapping of traffic
100362306a36Sopenharmony_ci	# (e.g. the veth pairs that this library creates for non-existent
100462306a36Sopenharmony_ci	# loopbacks). Use continue instead, so that there is a filter in there
100562306a36Sopenharmony_ci	# (some tests check counters), and so that other filters are still
100662306a36Sopenharmony_ci	# processed.
100762306a36Sopenharmony_ci	tc filter add dev $dev $direction pref 1 \
100862306a36Sopenharmony_ci		flower skip_sw action trap 2>/dev/null \
100962306a36Sopenharmony_ci	    || tc filter add dev $dev $direction pref 1 \
101062306a36Sopenharmony_ci		       flower action continue
101162306a36Sopenharmony_ci}
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_citrap_uninstall()
101462306a36Sopenharmony_ci{
101562306a36Sopenharmony_ci	local dev=$1; shift
101662306a36Sopenharmony_ci	local direction=$1; shift
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	tc filter del dev $dev $direction pref 1 flower
101962306a36Sopenharmony_ci}
102062306a36Sopenharmony_ci
102162306a36Sopenharmony_cislow_path_trap_install()
102262306a36Sopenharmony_ci{
102362306a36Sopenharmony_ci	# For slow-path testing, we need to install a trap to get to
102462306a36Sopenharmony_ci	# slow path the packets that would otherwise be switched in HW.
102562306a36Sopenharmony_ci	if [ "${tcflags/skip_hw}" != "$tcflags" ]; then
102662306a36Sopenharmony_ci		trap_install "$@"
102762306a36Sopenharmony_ci	fi
102862306a36Sopenharmony_ci}
102962306a36Sopenharmony_ci
103062306a36Sopenharmony_cislow_path_trap_uninstall()
103162306a36Sopenharmony_ci{
103262306a36Sopenharmony_ci	if [ "${tcflags/skip_hw}" != "$tcflags" ]; then
103362306a36Sopenharmony_ci		trap_uninstall "$@"
103462306a36Sopenharmony_ci	fi
103562306a36Sopenharmony_ci}
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_ci__icmp_capture_add_del()
103862306a36Sopenharmony_ci{
103962306a36Sopenharmony_ci	local add_del=$1; shift
104062306a36Sopenharmony_ci	local pref=$1; shift
104162306a36Sopenharmony_ci	local vsuf=$1; shift
104262306a36Sopenharmony_ci	local tundev=$1; shift
104362306a36Sopenharmony_ci	local filter=$1; shift
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_ci	tc filter $add_del dev "$tundev" ingress \
104662306a36Sopenharmony_ci	   proto ip$vsuf pref $pref \
104762306a36Sopenharmony_ci	   flower ip_proto icmp$vsuf $filter \
104862306a36Sopenharmony_ci	   action pass
104962306a36Sopenharmony_ci}
105062306a36Sopenharmony_ci
105162306a36Sopenharmony_ciicmp_capture_install()
105262306a36Sopenharmony_ci{
105362306a36Sopenharmony_ci	__icmp_capture_add_del add 100 "" "$@"
105462306a36Sopenharmony_ci}
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ciicmp_capture_uninstall()
105762306a36Sopenharmony_ci{
105862306a36Sopenharmony_ci	__icmp_capture_add_del del 100 "" "$@"
105962306a36Sopenharmony_ci}
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ciicmp6_capture_install()
106262306a36Sopenharmony_ci{
106362306a36Sopenharmony_ci	__icmp_capture_add_del add 100 v6 "$@"
106462306a36Sopenharmony_ci}
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ciicmp6_capture_uninstall()
106762306a36Sopenharmony_ci{
106862306a36Sopenharmony_ci	__icmp_capture_add_del del 100 v6 "$@"
106962306a36Sopenharmony_ci}
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci__vlan_capture_add_del()
107262306a36Sopenharmony_ci{
107362306a36Sopenharmony_ci	local add_del=$1; shift
107462306a36Sopenharmony_ci	local pref=$1; shift
107562306a36Sopenharmony_ci	local dev=$1; shift
107662306a36Sopenharmony_ci	local filter=$1; shift
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	tc filter $add_del dev "$dev" ingress \
107962306a36Sopenharmony_ci	   proto 802.1q pref $pref \
108062306a36Sopenharmony_ci	   flower $filter \
108162306a36Sopenharmony_ci	   action pass
108262306a36Sopenharmony_ci}
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_civlan_capture_install()
108562306a36Sopenharmony_ci{
108662306a36Sopenharmony_ci	__vlan_capture_add_del add 100 "$@"
108762306a36Sopenharmony_ci}
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_civlan_capture_uninstall()
109062306a36Sopenharmony_ci{
109162306a36Sopenharmony_ci	__vlan_capture_add_del del 100 "$@"
109262306a36Sopenharmony_ci}
109362306a36Sopenharmony_ci
109462306a36Sopenharmony_ci__dscp_capture_add_del()
109562306a36Sopenharmony_ci{
109662306a36Sopenharmony_ci	local add_del=$1; shift
109762306a36Sopenharmony_ci	local dev=$1; shift
109862306a36Sopenharmony_ci	local base=$1; shift
109962306a36Sopenharmony_ci	local dscp;
110062306a36Sopenharmony_ci
110162306a36Sopenharmony_ci	for prio in {0..7}; do
110262306a36Sopenharmony_ci		dscp=$((base + prio))
110362306a36Sopenharmony_ci		__icmp_capture_add_del $add_del $((dscp + 100)) "" $dev \
110462306a36Sopenharmony_ci				       "skip_hw ip_tos $((dscp << 2))"
110562306a36Sopenharmony_ci	done
110662306a36Sopenharmony_ci}
110762306a36Sopenharmony_ci
110862306a36Sopenharmony_cidscp_capture_install()
110962306a36Sopenharmony_ci{
111062306a36Sopenharmony_ci	local dev=$1; shift
111162306a36Sopenharmony_ci	local base=$1; shift
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci	__dscp_capture_add_del add $dev $base
111462306a36Sopenharmony_ci}
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_cidscp_capture_uninstall()
111762306a36Sopenharmony_ci{
111862306a36Sopenharmony_ci	local dev=$1; shift
111962306a36Sopenharmony_ci	local base=$1; shift
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	__dscp_capture_add_del del $dev $base
112262306a36Sopenharmony_ci}
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_cidscp_fetch_stats()
112562306a36Sopenharmony_ci{
112662306a36Sopenharmony_ci	local dev=$1; shift
112762306a36Sopenharmony_ci	local base=$1; shift
112862306a36Sopenharmony_ci
112962306a36Sopenharmony_ci	for prio in {0..7}; do
113062306a36Sopenharmony_ci		local dscp=$((base + prio))
113162306a36Sopenharmony_ci		local t=$(tc_rule_stats_get $dev $((dscp + 100)))
113262306a36Sopenharmony_ci		echo "[$dscp]=$t "
113362306a36Sopenharmony_ci	done
113462306a36Sopenharmony_ci}
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_cimatchall_sink_create()
113762306a36Sopenharmony_ci{
113862306a36Sopenharmony_ci	local dev=$1; shift
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_ci	tc qdisc add dev $dev clsact
114162306a36Sopenharmony_ci	tc filter add dev $dev ingress \
114262306a36Sopenharmony_ci	   pref 10000 \
114362306a36Sopenharmony_ci	   matchall \
114462306a36Sopenharmony_ci	   action drop
114562306a36Sopenharmony_ci}
114662306a36Sopenharmony_ci
114762306a36Sopenharmony_citests_run()
114862306a36Sopenharmony_ci{
114962306a36Sopenharmony_ci	local current_test
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci	for current_test in ${TESTS:-$ALL_TESTS}; do
115262306a36Sopenharmony_ci		$current_test
115362306a36Sopenharmony_ci	done
115462306a36Sopenharmony_ci}
115562306a36Sopenharmony_ci
115662306a36Sopenharmony_cimultipath_eval()
115762306a36Sopenharmony_ci{
115862306a36Sopenharmony_ci	local desc="$1"
115962306a36Sopenharmony_ci	local weight_rp12=$2
116062306a36Sopenharmony_ci	local weight_rp13=$3
116162306a36Sopenharmony_ci	local packets_rp12=$4
116262306a36Sopenharmony_ci	local packets_rp13=$5
116362306a36Sopenharmony_ci	local weights_ratio packets_ratio diff
116462306a36Sopenharmony_ci
116562306a36Sopenharmony_ci	RET=0
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ci	if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
116862306a36Sopenharmony_ci		weights_ratio=$(echo "scale=2; $weight_rp12 / $weight_rp13" \
116962306a36Sopenharmony_ci				| bc -l)
117062306a36Sopenharmony_ci	else
117162306a36Sopenharmony_ci		weights_ratio=$(echo "scale=2; $weight_rp13 / $weight_rp12" \
117262306a36Sopenharmony_ci				| bc -l)
117362306a36Sopenharmony_ci	fi
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci	if [[ "$packets_rp12" -eq "0" || "$packets_rp13" -eq "0" ]]; then
117662306a36Sopenharmony_ci	       check_err 1 "Packet difference is 0"
117762306a36Sopenharmony_ci	       log_test "Multipath"
117862306a36Sopenharmony_ci	       log_info "Expected ratio $weights_ratio"
117962306a36Sopenharmony_ci	       return
118062306a36Sopenharmony_ci	fi
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci	if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
118362306a36Sopenharmony_ci		packets_ratio=$(echo "scale=2; $packets_rp12 / $packets_rp13" \
118462306a36Sopenharmony_ci				| bc -l)
118562306a36Sopenharmony_ci	else
118662306a36Sopenharmony_ci		packets_ratio=$(echo "scale=2; $packets_rp13 / $packets_rp12" \
118762306a36Sopenharmony_ci				| bc -l)
118862306a36Sopenharmony_ci	fi
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci	diff=$(echo $weights_ratio - $packets_ratio | bc -l)
119162306a36Sopenharmony_ci	diff=${diff#-}
119262306a36Sopenharmony_ci
119362306a36Sopenharmony_ci	test "$(echo "$diff / $weights_ratio > 0.15" | bc -l)" -eq 0
119462306a36Sopenharmony_ci	check_err $? "Too large discrepancy between expected and measured ratios"
119562306a36Sopenharmony_ci	log_test "$desc"
119662306a36Sopenharmony_ci	log_info "Expected ratio $weights_ratio Measured ratio $packets_ratio"
119762306a36Sopenharmony_ci}
119862306a36Sopenharmony_ci
119962306a36Sopenharmony_ciin_ns()
120062306a36Sopenharmony_ci{
120162306a36Sopenharmony_ci	local name=$1; shift
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci	ip netns exec $name bash <<-EOF
120462306a36Sopenharmony_ci		NUM_NETIFS=0
120562306a36Sopenharmony_ci		source lib.sh
120662306a36Sopenharmony_ci		$(for a in "$@"; do printf "%q${IFS:0:1}" "$a"; done)
120762306a36Sopenharmony_ci	EOF
120862306a36Sopenharmony_ci}
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_ci##############################################################################
121162306a36Sopenharmony_ci# Tests
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_ciping_do()
121462306a36Sopenharmony_ci{
121562306a36Sopenharmony_ci	local if_name=$1
121662306a36Sopenharmony_ci	local dip=$2
121762306a36Sopenharmony_ci	local args=$3
121862306a36Sopenharmony_ci	local vrf_name
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_ci	vrf_name=$(master_name_get $if_name)
122162306a36Sopenharmony_ci	ip vrf exec $vrf_name \
122262306a36Sopenharmony_ci		$PING $args $dip -c $PING_COUNT -i 0.1 \
122362306a36Sopenharmony_ci		-w $PING_TIMEOUT &> /dev/null
122462306a36Sopenharmony_ci}
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_ciping_test()
122762306a36Sopenharmony_ci{
122862306a36Sopenharmony_ci	RET=0
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci	ping_do $1 $2
123162306a36Sopenharmony_ci	check_err $?
123262306a36Sopenharmony_ci	log_test "ping$3"
123362306a36Sopenharmony_ci}
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ciping_test_fails()
123662306a36Sopenharmony_ci{
123762306a36Sopenharmony_ci	RET=0
123862306a36Sopenharmony_ci
123962306a36Sopenharmony_ci	ping_do $1 $2
124062306a36Sopenharmony_ci	check_fail $?
124162306a36Sopenharmony_ci	log_test "ping fails$3"
124262306a36Sopenharmony_ci}
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_ciping6_do()
124562306a36Sopenharmony_ci{
124662306a36Sopenharmony_ci	local if_name=$1
124762306a36Sopenharmony_ci	local dip=$2
124862306a36Sopenharmony_ci	local args=$3
124962306a36Sopenharmony_ci	local vrf_name
125062306a36Sopenharmony_ci
125162306a36Sopenharmony_ci	vrf_name=$(master_name_get $if_name)
125262306a36Sopenharmony_ci	ip vrf exec $vrf_name \
125362306a36Sopenharmony_ci		$PING6 $args $dip -c $PING_COUNT -i 0.1 \
125462306a36Sopenharmony_ci		-w $PING_TIMEOUT &> /dev/null
125562306a36Sopenharmony_ci}
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_ciping6_test()
125862306a36Sopenharmony_ci{
125962306a36Sopenharmony_ci	RET=0
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci	ping6_do $1 $2
126262306a36Sopenharmony_ci	check_err $?
126362306a36Sopenharmony_ci	log_test "ping6$3"
126462306a36Sopenharmony_ci}
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_ciping6_test_fails()
126762306a36Sopenharmony_ci{
126862306a36Sopenharmony_ci	RET=0
126962306a36Sopenharmony_ci
127062306a36Sopenharmony_ci	ping6_do $1 $2
127162306a36Sopenharmony_ci	check_fail $?
127262306a36Sopenharmony_ci	log_test "ping6 fails$3"
127362306a36Sopenharmony_ci}
127462306a36Sopenharmony_ci
127562306a36Sopenharmony_cilearning_test()
127662306a36Sopenharmony_ci{
127762306a36Sopenharmony_ci	local bridge=$1
127862306a36Sopenharmony_ci	local br_port1=$2	# Connected to `host1_if`.
127962306a36Sopenharmony_ci	local host1_if=$3
128062306a36Sopenharmony_ci	local host2_if=$4
128162306a36Sopenharmony_ci	local mac=de:ad:be:ef:13:37
128262306a36Sopenharmony_ci	local ageing_time
128362306a36Sopenharmony_ci
128462306a36Sopenharmony_ci	RET=0
128562306a36Sopenharmony_ci
128662306a36Sopenharmony_ci	bridge -j fdb show br $bridge brport $br_port1 \
128762306a36Sopenharmony_ci		| jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
128862306a36Sopenharmony_ci	check_fail $? "Found FDB record when should not"
128962306a36Sopenharmony_ci
129062306a36Sopenharmony_ci	# Disable unknown unicast flooding on `br_port1` to make sure
129162306a36Sopenharmony_ci	# packets are only forwarded through the port after a matching
129262306a36Sopenharmony_ci	# FDB entry was installed.
129362306a36Sopenharmony_ci	bridge link set dev $br_port1 flood off
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_ci	ip link set $host1_if promisc on
129662306a36Sopenharmony_ci	tc qdisc add dev $host1_if ingress
129762306a36Sopenharmony_ci	tc filter add dev $host1_if ingress protocol ip pref 1 handle 101 \
129862306a36Sopenharmony_ci		flower dst_mac $mac action drop
129962306a36Sopenharmony_ci
130062306a36Sopenharmony_ci	$MZ $host2_if -c 1 -p 64 -b $mac -t ip -q
130162306a36Sopenharmony_ci	sleep 1
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_ci	tc -j -s filter show dev $host1_if ingress \
130462306a36Sopenharmony_ci		| jq -e ".[] | select(.options.handle == 101) \
130562306a36Sopenharmony_ci		| select(.options.actions[0].stats.packets == 1)" &> /dev/null
130662306a36Sopenharmony_ci	check_fail $? "Packet reached first host when should not"
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci	$MZ $host1_if -c 1 -p 64 -a $mac -t ip -q
130962306a36Sopenharmony_ci	sleep 1
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_ci	bridge -j fdb show br $bridge brport $br_port1 \
131262306a36Sopenharmony_ci		| jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
131362306a36Sopenharmony_ci	check_err $? "Did not find FDB record when should"
131462306a36Sopenharmony_ci
131562306a36Sopenharmony_ci	$MZ $host2_if -c 1 -p 64 -b $mac -t ip -q
131662306a36Sopenharmony_ci	sleep 1
131762306a36Sopenharmony_ci
131862306a36Sopenharmony_ci	tc -j -s filter show dev $host1_if ingress \
131962306a36Sopenharmony_ci		| jq -e ".[] | select(.options.handle == 101) \
132062306a36Sopenharmony_ci		| select(.options.actions[0].stats.packets == 1)" &> /dev/null
132162306a36Sopenharmony_ci	check_err $? "Packet did not reach second host when should"
132262306a36Sopenharmony_ci
132362306a36Sopenharmony_ci	# Wait for 10 seconds after the ageing time to make sure FDB
132462306a36Sopenharmony_ci	# record was aged-out.
132562306a36Sopenharmony_ci	ageing_time=$(bridge_ageing_time_get $bridge)
132662306a36Sopenharmony_ci	sleep $((ageing_time + 10))
132762306a36Sopenharmony_ci
132862306a36Sopenharmony_ci	bridge -j fdb show br $bridge brport $br_port1 \
132962306a36Sopenharmony_ci		| jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
133062306a36Sopenharmony_ci	check_fail $? "Found FDB record when should not"
133162306a36Sopenharmony_ci
133262306a36Sopenharmony_ci	bridge link set dev $br_port1 learning off
133362306a36Sopenharmony_ci
133462306a36Sopenharmony_ci	$MZ $host1_if -c 1 -p 64 -a $mac -t ip -q
133562306a36Sopenharmony_ci	sleep 1
133662306a36Sopenharmony_ci
133762306a36Sopenharmony_ci	bridge -j fdb show br $bridge brport $br_port1 \
133862306a36Sopenharmony_ci		| jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
133962306a36Sopenharmony_ci	check_fail $? "Found FDB record when should not"
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci	bridge link set dev $br_port1 learning on
134262306a36Sopenharmony_ci
134362306a36Sopenharmony_ci	tc filter del dev $host1_if ingress protocol ip pref 1 handle 101 flower
134462306a36Sopenharmony_ci	tc qdisc del dev $host1_if ingress
134562306a36Sopenharmony_ci	ip link set $host1_if promisc off
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci	bridge link set dev $br_port1 flood on
134862306a36Sopenharmony_ci
134962306a36Sopenharmony_ci	log_test "FDB learning"
135062306a36Sopenharmony_ci}
135162306a36Sopenharmony_ci
135262306a36Sopenharmony_ciflood_test_do()
135362306a36Sopenharmony_ci{
135462306a36Sopenharmony_ci	local should_flood=$1
135562306a36Sopenharmony_ci	local mac=$2
135662306a36Sopenharmony_ci	local ip=$3
135762306a36Sopenharmony_ci	local host1_if=$4
135862306a36Sopenharmony_ci	local host2_if=$5
135962306a36Sopenharmony_ci	local err=0
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci	# Add an ACL on `host2_if` which will tell us whether the packet
136262306a36Sopenharmony_ci	# was flooded to it or not.
136362306a36Sopenharmony_ci	ip link set $host2_if promisc on
136462306a36Sopenharmony_ci	tc qdisc add dev $host2_if ingress
136562306a36Sopenharmony_ci	tc filter add dev $host2_if ingress protocol ip pref 1 handle 101 \
136662306a36Sopenharmony_ci		flower dst_mac $mac action drop
136762306a36Sopenharmony_ci
136862306a36Sopenharmony_ci	$MZ $host1_if -c 1 -p 64 -b $mac -B $ip -t ip -q
136962306a36Sopenharmony_ci	sleep 1
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_ci	tc -j -s filter show dev $host2_if ingress \
137262306a36Sopenharmony_ci		| jq -e ".[] | select(.options.handle == 101) \
137362306a36Sopenharmony_ci		| select(.options.actions[0].stats.packets == 1)" &> /dev/null
137462306a36Sopenharmony_ci	if [[ $? -ne 0 && $should_flood == "true" || \
137562306a36Sopenharmony_ci	      $? -eq 0 && $should_flood == "false" ]]; then
137662306a36Sopenharmony_ci		err=1
137762306a36Sopenharmony_ci	fi
137862306a36Sopenharmony_ci
137962306a36Sopenharmony_ci	tc filter del dev $host2_if ingress protocol ip pref 1 handle 101 flower
138062306a36Sopenharmony_ci	tc qdisc del dev $host2_if ingress
138162306a36Sopenharmony_ci	ip link set $host2_if promisc off
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ci	return $err
138462306a36Sopenharmony_ci}
138562306a36Sopenharmony_ci
138662306a36Sopenharmony_ciflood_unicast_test()
138762306a36Sopenharmony_ci{
138862306a36Sopenharmony_ci	local br_port=$1
138962306a36Sopenharmony_ci	local host1_if=$2
139062306a36Sopenharmony_ci	local host2_if=$3
139162306a36Sopenharmony_ci	local mac=de:ad:be:ef:13:37
139262306a36Sopenharmony_ci	local ip=192.0.2.100
139362306a36Sopenharmony_ci
139462306a36Sopenharmony_ci	RET=0
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ci	bridge link set dev $br_port flood off
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci	flood_test_do false $mac $ip $host1_if $host2_if
139962306a36Sopenharmony_ci	check_err $? "Packet flooded when should not"
140062306a36Sopenharmony_ci
140162306a36Sopenharmony_ci	bridge link set dev $br_port flood on
140262306a36Sopenharmony_ci
140362306a36Sopenharmony_ci	flood_test_do true $mac $ip $host1_if $host2_if
140462306a36Sopenharmony_ci	check_err $? "Packet was not flooded when should"
140562306a36Sopenharmony_ci
140662306a36Sopenharmony_ci	log_test "Unknown unicast flood"
140762306a36Sopenharmony_ci}
140862306a36Sopenharmony_ci
140962306a36Sopenharmony_ciflood_multicast_test()
141062306a36Sopenharmony_ci{
141162306a36Sopenharmony_ci	local br_port=$1
141262306a36Sopenharmony_ci	local host1_if=$2
141362306a36Sopenharmony_ci	local host2_if=$3
141462306a36Sopenharmony_ci	local mac=01:00:5e:00:00:01
141562306a36Sopenharmony_ci	local ip=239.0.0.1
141662306a36Sopenharmony_ci
141762306a36Sopenharmony_ci	RET=0
141862306a36Sopenharmony_ci
141962306a36Sopenharmony_ci	bridge link set dev $br_port mcast_flood off
142062306a36Sopenharmony_ci
142162306a36Sopenharmony_ci	flood_test_do false $mac $ip $host1_if $host2_if
142262306a36Sopenharmony_ci	check_err $? "Packet flooded when should not"
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_ci	bridge link set dev $br_port mcast_flood on
142562306a36Sopenharmony_ci
142662306a36Sopenharmony_ci	flood_test_do true $mac $ip $host1_if $host2_if
142762306a36Sopenharmony_ci	check_err $? "Packet was not flooded when should"
142862306a36Sopenharmony_ci
142962306a36Sopenharmony_ci	log_test "Unregistered multicast flood"
143062306a36Sopenharmony_ci}
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_ciflood_test()
143362306a36Sopenharmony_ci{
143462306a36Sopenharmony_ci	# `br_port` is connected to `host2_if`
143562306a36Sopenharmony_ci	local br_port=$1
143662306a36Sopenharmony_ci	local host1_if=$2
143762306a36Sopenharmony_ci	local host2_if=$3
143862306a36Sopenharmony_ci
143962306a36Sopenharmony_ci	flood_unicast_test $br_port $host1_if $host2_if
144062306a36Sopenharmony_ci	flood_multicast_test $br_port $host1_if $host2_if
144162306a36Sopenharmony_ci}
144262306a36Sopenharmony_ci
144362306a36Sopenharmony_ci__start_traffic()
144462306a36Sopenharmony_ci{
144562306a36Sopenharmony_ci	local pktsize=$1; shift
144662306a36Sopenharmony_ci	local proto=$1; shift
144762306a36Sopenharmony_ci	local h_in=$1; shift    # Where the traffic egresses the host
144862306a36Sopenharmony_ci	local sip=$1; shift
144962306a36Sopenharmony_ci	local dip=$1; shift
145062306a36Sopenharmony_ci	local dmac=$1; shift
145162306a36Sopenharmony_ci
145262306a36Sopenharmony_ci	$MZ $h_in -p $pktsize -A $sip -B $dip -c 0 \
145362306a36Sopenharmony_ci		-a own -b $dmac -t "$proto" -q "$@" &
145462306a36Sopenharmony_ci	sleep 1
145562306a36Sopenharmony_ci}
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_cistart_traffic_pktsize()
145862306a36Sopenharmony_ci{
145962306a36Sopenharmony_ci	local pktsize=$1; shift
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci	__start_traffic $pktsize udp "$@"
146262306a36Sopenharmony_ci}
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_cistart_tcp_traffic_pktsize()
146562306a36Sopenharmony_ci{
146662306a36Sopenharmony_ci	local pktsize=$1; shift
146762306a36Sopenharmony_ci
146862306a36Sopenharmony_ci	__start_traffic $pktsize tcp "$@"
146962306a36Sopenharmony_ci}
147062306a36Sopenharmony_ci
147162306a36Sopenharmony_cistart_traffic()
147262306a36Sopenharmony_ci{
147362306a36Sopenharmony_ci	start_traffic_pktsize 8000 "$@"
147462306a36Sopenharmony_ci}
147562306a36Sopenharmony_ci
147662306a36Sopenharmony_cistart_tcp_traffic()
147762306a36Sopenharmony_ci{
147862306a36Sopenharmony_ci	start_tcp_traffic_pktsize 8000 "$@"
147962306a36Sopenharmony_ci}
148062306a36Sopenharmony_ci
148162306a36Sopenharmony_cistop_traffic()
148262306a36Sopenharmony_ci{
148362306a36Sopenharmony_ci	# Suppress noise from killing mausezahn.
148462306a36Sopenharmony_ci	{ kill %% && wait %%; } 2>/dev/null
148562306a36Sopenharmony_ci}
148662306a36Sopenharmony_ci
148762306a36Sopenharmony_cideclare -A cappid
148862306a36Sopenharmony_cideclare -A capfile
148962306a36Sopenharmony_cideclare -A capout
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_citcpdump_start()
149262306a36Sopenharmony_ci{
149362306a36Sopenharmony_ci	local if_name=$1; shift
149462306a36Sopenharmony_ci	local ns=$1; shift
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci	capfile[$if_name]=$(mktemp)
149762306a36Sopenharmony_ci	capout[$if_name]=$(mktemp)
149862306a36Sopenharmony_ci
149962306a36Sopenharmony_ci	if [ -z $ns ]; then
150062306a36Sopenharmony_ci		ns_cmd=""
150162306a36Sopenharmony_ci	else
150262306a36Sopenharmony_ci		ns_cmd="ip netns exec ${ns}"
150362306a36Sopenharmony_ci	fi
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci	if [ -z $SUDO_USER ] ; then
150662306a36Sopenharmony_ci		capuser=""
150762306a36Sopenharmony_ci	else
150862306a36Sopenharmony_ci		capuser="-Z $SUDO_USER"
150962306a36Sopenharmony_ci	fi
151062306a36Sopenharmony_ci
151162306a36Sopenharmony_ci	$ns_cmd tcpdump $TCPDUMP_EXTRA_FLAGS -e -n -Q in -i $if_name \
151262306a36Sopenharmony_ci		-s 65535 -B 32768 $capuser -w ${capfile[$if_name]} \
151362306a36Sopenharmony_ci		> "${capout[$if_name]}" 2>&1 &
151462306a36Sopenharmony_ci	cappid[$if_name]=$!
151562306a36Sopenharmony_ci
151662306a36Sopenharmony_ci	sleep 1
151762306a36Sopenharmony_ci}
151862306a36Sopenharmony_ci
151962306a36Sopenharmony_citcpdump_stop()
152062306a36Sopenharmony_ci{
152162306a36Sopenharmony_ci	local if_name=$1
152262306a36Sopenharmony_ci	local pid=${cappid[$if_name]}
152362306a36Sopenharmony_ci
152462306a36Sopenharmony_ci	$ns_cmd kill "$pid" && wait "$pid"
152562306a36Sopenharmony_ci	sleep 1
152662306a36Sopenharmony_ci}
152762306a36Sopenharmony_ci
152862306a36Sopenharmony_citcpdump_cleanup()
152962306a36Sopenharmony_ci{
153062306a36Sopenharmony_ci	local if_name=$1
153162306a36Sopenharmony_ci
153262306a36Sopenharmony_ci	rm ${capfile[$if_name]} ${capout[$if_name]}
153362306a36Sopenharmony_ci}
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_citcpdump_show()
153662306a36Sopenharmony_ci{
153762306a36Sopenharmony_ci	local if_name=$1
153862306a36Sopenharmony_ci
153962306a36Sopenharmony_ci	tcpdump -e -n -r ${capfile[$if_name]} 2>&1
154062306a36Sopenharmony_ci}
154162306a36Sopenharmony_ci
154262306a36Sopenharmony_ci# return 0 if the packet wasn't seen on host2_if or 1 if it was
154362306a36Sopenharmony_cimcast_packet_test()
154462306a36Sopenharmony_ci{
154562306a36Sopenharmony_ci	local mac=$1
154662306a36Sopenharmony_ci	local src_ip=$2
154762306a36Sopenharmony_ci	local ip=$3
154862306a36Sopenharmony_ci	local host1_if=$4
154962306a36Sopenharmony_ci	local host2_if=$5
155062306a36Sopenharmony_ci	local seen=0
155162306a36Sopenharmony_ci	local tc_proto="ip"
155262306a36Sopenharmony_ci	local mz_v6arg=""
155362306a36Sopenharmony_ci
155462306a36Sopenharmony_ci	# basic check to see if we were passed an IPv4 address, if not assume IPv6
155562306a36Sopenharmony_ci	if [[ ! $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
155662306a36Sopenharmony_ci		tc_proto="ipv6"
155762306a36Sopenharmony_ci		mz_v6arg="-6"
155862306a36Sopenharmony_ci	fi
155962306a36Sopenharmony_ci
156062306a36Sopenharmony_ci	# Add an ACL on `host2_if` which will tell us whether the packet
156162306a36Sopenharmony_ci	# was received by it or not.
156262306a36Sopenharmony_ci	tc qdisc add dev $host2_if ingress
156362306a36Sopenharmony_ci	tc filter add dev $host2_if ingress protocol $tc_proto pref 1 handle 101 \
156462306a36Sopenharmony_ci		flower ip_proto udp dst_mac $mac action drop
156562306a36Sopenharmony_ci
156662306a36Sopenharmony_ci	$MZ $host1_if $mz_v6arg -c 1 -p 64 -b $mac -A $src_ip -B $ip -t udp "dp=4096,sp=2048" -q
156762306a36Sopenharmony_ci	sleep 1
156862306a36Sopenharmony_ci
156962306a36Sopenharmony_ci	tc -j -s filter show dev $host2_if ingress \
157062306a36Sopenharmony_ci		| jq -e ".[] | select(.options.handle == 101) \
157162306a36Sopenharmony_ci		| select(.options.actions[0].stats.packets == 1)" &> /dev/null
157262306a36Sopenharmony_ci	if [[ $? -eq 0 ]]; then
157362306a36Sopenharmony_ci		seen=1
157462306a36Sopenharmony_ci	fi
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci	tc filter del dev $host2_if ingress protocol $tc_proto pref 1 handle 101 flower
157762306a36Sopenharmony_ci	tc qdisc del dev $host2_if ingress
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_ci	return $seen
158062306a36Sopenharmony_ci}
158162306a36Sopenharmony_ci
158262306a36Sopenharmony_cibrmcast_check_sg_entries()
158362306a36Sopenharmony_ci{
158462306a36Sopenharmony_ci	local report=$1; shift
158562306a36Sopenharmony_ci	local slist=("$@")
158662306a36Sopenharmony_ci	local sarg=""
158762306a36Sopenharmony_ci
158862306a36Sopenharmony_ci	for src in "${slist[@]}"; do
158962306a36Sopenharmony_ci		sarg="${sarg} and .source_list[].address == \"$src\""
159062306a36Sopenharmony_ci	done
159162306a36Sopenharmony_ci	bridge -j -d -s mdb show dev br0 \
159262306a36Sopenharmony_ci		| jq -e ".[].mdb[] | \
159362306a36Sopenharmony_ci			 select(.grp == \"$TEST_GROUP\" and .source_list != null $sarg)" &>/dev/null
159462306a36Sopenharmony_ci	check_err $? "Wrong *,G entry source list after $report report"
159562306a36Sopenharmony_ci
159662306a36Sopenharmony_ci	for sgent in "${slist[@]}"; do
159762306a36Sopenharmony_ci		bridge -j -d -s mdb show dev br0 \
159862306a36Sopenharmony_ci			| jq -e ".[].mdb[] | \
159962306a36Sopenharmony_ci				 select(.grp == \"$TEST_GROUP\" and .src == \"$sgent\")" &>/dev/null
160062306a36Sopenharmony_ci		check_err $? "Missing S,G entry ($sgent, $TEST_GROUP)"
160162306a36Sopenharmony_ci	done
160262306a36Sopenharmony_ci}
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_cibrmcast_check_sg_fwding()
160562306a36Sopenharmony_ci{
160662306a36Sopenharmony_ci	local should_fwd=$1; shift
160762306a36Sopenharmony_ci	local sources=("$@")
160862306a36Sopenharmony_ci
160962306a36Sopenharmony_ci	for src in "${sources[@]}"; do
161062306a36Sopenharmony_ci		local retval=0
161162306a36Sopenharmony_ci
161262306a36Sopenharmony_ci		mcast_packet_test $TEST_GROUP_MAC $src $TEST_GROUP $h2 $h1
161362306a36Sopenharmony_ci		retval=$?
161462306a36Sopenharmony_ci		if [ $should_fwd -eq 1 ]; then
161562306a36Sopenharmony_ci			check_fail $retval "Didn't forward traffic from S,G ($src, $TEST_GROUP)"
161662306a36Sopenharmony_ci		else
161762306a36Sopenharmony_ci			check_err $retval "Forwarded traffic for blocked S,G ($src, $TEST_GROUP)"
161862306a36Sopenharmony_ci		fi
161962306a36Sopenharmony_ci	done
162062306a36Sopenharmony_ci}
162162306a36Sopenharmony_ci
162262306a36Sopenharmony_cibrmcast_check_sg_state()
162362306a36Sopenharmony_ci{
162462306a36Sopenharmony_ci	local is_blocked=$1; shift
162562306a36Sopenharmony_ci	local sources=("$@")
162662306a36Sopenharmony_ci	local should_fail=1
162762306a36Sopenharmony_ci
162862306a36Sopenharmony_ci	if [ $is_blocked -eq 1 ]; then
162962306a36Sopenharmony_ci		should_fail=0
163062306a36Sopenharmony_ci	fi
163162306a36Sopenharmony_ci
163262306a36Sopenharmony_ci	for src in "${sources[@]}"; do
163362306a36Sopenharmony_ci		bridge -j -d -s mdb show dev br0 \
163462306a36Sopenharmony_ci			| jq -e ".[].mdb[] | \
163562306a36Sopenharmony_ci				 select(.grp == \"$TEST_GROUP\" and .source_list != null) |
163662306a36Sopenharmony_ci				 .source_list[] |
163762306a36Sopenharmony_ci				 select(.address == \"$src\") |
163862306a36Sopenharmony_ci				 select(.timer == \"0.00\")" &>/dev/null
163962306a36Sopenharmony_ci		check_err_fail $should_fail $? "Entry $src has zero timer"
164062306a36Sopenharmony_ci
164162306a36Sopenharmony_ci		bridge -j -d -s mdb show dev br0 \
164262306a36Sopenharmony_ci			| jq -e ".[].mdb[] | \
164362306a36Sopenharmony_ci				 select(.grp == \"$TEST_GROUP\" and .src == \"$src\" and \
164462306a36Sopenharmony_ci				 .flags[] == \"blocked\")" &>/dev/null
164562306a36Sopenharmony_ci		check_err_fail $should_fail $? "Entry $src has blocked flag"
164662306a36Sopenharmony_ci	done
164762306a36Sopenharmony_ci}
164862306a36Sopenharmony_ci
164962306a36Sopenharmony_cimc_join()
165062306a36Sopenharmony_ci{
165162306a36Sopenharmony_ci	local if_name=$1
165262306a36Sopenharmony_ci	local group=$2
165362306a36Sopenharmony_ci	local vrf_name=$(master_name_get $if_name)
165462306a36Sopenharmony_ci
165562306a36Sopenharmony_ci	# We don't care about actual reception, just about joining the
165662306a36Sopenharmony_ci	# IP multicast group and adding the L2 address to the device's
165762306a36Sopenharmony_ci	# MAC filtering table
165862306a36Sopenharmony_ci	ip vrf exec $vrf_name \
165962306a36Sopenharmony_ci		mreceive -g $group -I $if_name > /dev/null 2>&1 &
166062306a36Sopenharmony_ci	mreceive_pid=$!
166162306a36Sopenharmony_ci
166262306a36Sopenharmony_ci	sleep 1
166362306a36Sopenharmony_ci}
166462306a36Sopenharmony_ci
166562306a36Sopenharmony_cimc_leave()
166662306a36Sopenharmony_ci{
166762306a36Sopenharmony_ci	kill "$mreceive_pid" && wait "$mreceive_pid"
166862306a36Sopenharmony_ci}
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_cimc_send()
167162306a36Sopenharmony_ci{
167262306a36Sopenharmony_ci	local if_name=$1
167362306a36Sopenharmony_ci	local groups=$2
167462306a36Sopenharmony_ci	local vrf_name=$(master_name_get $if_name)
167562306a36Sopenharmony_ci
167662306a36Sopenharmony_ci	ip vrf exec $vrf_name \
167762306a36Sopenharmony_ci		msend -g $groups -I $if_name -c 1 > /dev/null 2>&1
167862306a36Sopenharmony_ci}
167962306a36Sopenharmony_ci
168062306a36Sopenharmony_cistart_ip_monitor()
168162306a36Sopenharmony_ci{
168262306a36Sopenharmony_ci	local mtype=$1; shift
168362306a36Sopenharmony_ci	local ip=${1-ip}; shift
168462306a36Sopenharmony_ci
168562306a36Sopenharmony_ci	# start the monitor in the background
168662306a36Sopenharmony_ci	tmpfile=`mktemp /var/run/nexthoptestXXX`
168762306a36Sopenharmony_ci	mpid=`($ip monitor $mtype > $tmpfile & echo $!) 2>/dev/null`
168862306a36Sopenharmony_ci	sleep 0.2
168962306a36Sopenharmony_ci	echo "$mpid $tmpfile"
169062306a36Sopenharmony_ci}
169162306a36Sopenharmony_ci
169262306a36Sopenharmony_cistop_ip_monitor()
169362306a36Sopenharmony_ci{
169462306a36Sopenharmony_ci	local mpid=$1; shift
169562306a36Sopenharmony_ci	local tmpfile=$1; shift
169662306a36Sopenharmony_ci	local el=$1; shift
169762306a36Sopenharmony_ci	local what=$1; shift
169862306a36Sopenharmony_ci
169962306a36Sopenharmony_ci	sleep 0.2
170062306a36Sopenharmony_ci	kill $mpid
170162306a36Sopenharmony_ci	local lines=`grep '^\w' $tmpfile | wc -l`
170262306a36Sopenharmony_ci	test $lines -eq $el
170362306a36Sopenharmony_ci	check_err $? "$what: $lines lines of events, expected $el"
170462306a36Sopenharmony_ci	rm -rf $tmpfile
170562306a36Sopenharmony_ci}
170662306a36Sopenharmony_ci
170762306a36Sopenharmony_cihw_stats_monitor_test()
170862306a36Sopenharmony_ci{
170962306a36Sopenharmony_ci	local dev=$1; shift
171062306a36Sopenharmony_ci	local type=$1; shift
171162306a36Sopenharmony_ci	local make_suitable=$1; shift
171262306a36Sopenharmony_ci	local make_unsuitable=$1; shift
171362306a36Sopenharmony_ci	local ip=${1-ip}; shift
171462306a36Sopenharmony_ci
171562306a36Sopenharmony_ci	RET=0
171662306a36Sopenharmony_ci
171762306a36Sopenharmony_ci	# Expect a notification about enablement.
171862306a36Sopenharmony_ci	local ipmout=$(start_ip_monitor stats "$ip")
171962306a36Sopenharmony_ci	$ip stats set dev $dev ${type}_stats on
172062306a36Sopenharmony_ci	stop_ip_monitor $ipmout 1 "${type}_stats enablement"
172162306a36Sopenharmony_ci
172262306a36Sopenharmony_ci	# Expect a notification about offload.
172362306a36Sopenharmony_ci	local ipmout=$(start_ip_monitor stats "$ip")
172462306a36Sopenharmony_ci	$make_suitable
172562306a36Sopenharmony_ci	stop_ip_monitor $ipmout 1 "${type}_stats installation"
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_ci	# Expect a notification about loss of offload.
172862306a36Sopenharmony_ci	local ipmout=$(start_ip_monitor stats "$ip")
172962306a36Sopenharmony_ci	$make_unsuitable
173062306a36Sopenharmony_ci	stop_ip_monitor $ipmout 1 "${type}_stats deinstallation"
173162306a36Sopenharmony_ci
173262306a36Sopenharmony_ci	# Expect a notification about disablement
173362306a36Sopenharmony_ci	local ipmout=$(start_ip_monitor stats "$ip")
173462306a36Sopenharmony_ci	$ip stats set dev $dev ${type}_stats off
173562306a36Sopenharmony_ci	stop_ip_monitor $ipmout 1 "${type}_stats disablement"
173662306a36Sopenharmony_ci
173762306a36Sopenharmony_ci	log_test "${type}_stats notifications"
173862306a36Sopenharmony_ci}
173962306a36Sopenharmony_ci
174062306a36Sopenharmony_ciipv4_to_bytes()
174162306a36Sopenharmony_ci{
174262306a36Sopenharmony_ci	local IP=$1; shift
174362306a36Sopenharmony_ci
174462306a36Sopenharmony_ci	printf '%02x:' ${IP//./ } |
174562306a36Sopenharmony_ci	    sed 's/:$//'
174662306a36Sopenharmony_ci}
174762306a36Sopenharmony_ci
174862306a36Sopenharmony_ci# Convert a given IPv6 address, `IP' such that the :: token, if present, is
174962306a36Sopenharmony_ci# expanded, and each 16-bit group is padded with zeroes to be 4 hexadecimal
175062306a36Sopenharmony_ci# digits. An optional `BYTESEP' parameter can be given to further separate
175162306a36Sopenharmony_ci# individual bytes of each 16-bit group.
175262306a36Sopenharmony_ciexpand_ipv6()
175362306a36Sopenharmony_ci{
175462306a36Sopenharmony_ci	local IP=$1; shift
175562306a36Sopenharmony_ci	local bytesep=$1; shift
175662306a36Sopenharmony_ci
175762306a36Sopenharmony_ci	local cvt_ip=${IP/::/_}
175862306a36Sopenharmony_ci	local colons=${cvt_ip//[^:]/}
175962306a36Sopenharmony_ci	local allcol=:::::::
176062306a36Sopenharmony_ci	# IP where :: -> the appropriate number of colons:
176162306a36Sopenharmony_ci	local allcol_ip=${cvt_ip/_/${allcol:${#colons}}}
176262306a36Sopenharmony_ci
176362306a36Sopenharmony_ci	echo $allcol_ip | tr : '\n' |
176462306a36Sopenharmony_ci	    sed s/^/0000/ |
176562306a36Sopenharmony_ci	    sed 's/.*\(..\)\(..\)/\1'"$bytesep"'\2/' |
176662306a36Sopenharmony_ci	    tr '\n' : |
176762306a36Sopenharmony_ci	    sed 's/:$//'
176862306a36Sopenharmony_ci}
176962306a36Sopenharmony_ci
177062306a36Sopenharmony_ciipv6_to_bytes()
177162306a36Sopenharmony_ci{
177262306a36Sopenharmony_ci	local IP=$1; shift
177362306a36Sopenharmony_ci
177462306a36Sopenharmony_ci	expand_ipv6 "$IP" :
177562306a36Sopenharmony_ci}
177662306a36Sopenharmony_ci
177762306a36Sopenharmony_ciu16_to_bytes()
177862306a36Sopenharmony_ci{
177962306a36Sopenharmony_ci	local u16=$1; shift
178062306a36Sopenharmony_ci
178162306a36Sopenharmony_ci	printf "%04x" $u16 | sed 's/^/000/;s/^.*\(..\)\(..\)$/\1:\2/'
178262306a36Sopenharmony_ci}
178362306a36Sopenharmony_ci
178462306a36Sopenharmony_ci# Given a mausezahn-formatted payload (colon-separated bytes given as %02x),
178562306a36Sopenharmony_ci# possibly with a keyword CHECKSUM stashed where a 16-bit checksum should be,
178662306a36Sopenharmony_ci# calculate checksum as per RFC 1071, assuming the CHECKSUM field (if any)
178762306a36Sopenharmony_ci# stands for 00:00.
178862306a36Sopenharmony_cipayload_template_calc_checksum()
178962306a36Sopenharmony_ci{
179062306a36Sopenharmony_ci	local payload=$1; shift
179162306a36Sopenharmony_ci
179262306a36Sopenharmony_ci	(
179362306a36Sopenharmony_ci	    # Set input radix.
179462306a36Sopenharmony_ci	    echo "16i"
179562306a36Sopenharmony_ci	    # Push zero for the initial checksum.
179662306a36Sopenharmony_ci	    echo 0
179762306a36Sopenharmony_ci
179862306a36Sopenharmony_ci	    # Pad the payload with a terminating 00: in case we get an odd
179962306a36Sopenharmony_ci	    # number of bytes.
180062306a36Sopenharmony_ci	    echo "${payload%:}:00:" |
180162306a36Sopenharmony_ci		sed 's/CHECKSUM/00:00/g' |
180262306a36Sopenharmony_ci		tr '[:lower:]' '[:upper:]' |
180362306a36Sopenharmony_ci		# Add the word to the checksum.
180462306a36Sopenharmony_ci		sed 's/\(..\):\(..\):/\1\2+\n/g' |
180562306a36Sopenharmony_ci		# Strip the extra odd byte we pushed if left unconverted.
180662306a36Sopenharmony_ci		sed 's/\(..\):$//'
180762306a36Sopenharmony_ci
180862306a36Sopenharmony_ci	    echo "10000 ~ +"	# Calculate and add carry.
180962306a36Sopenharmony_ci	    echo "FFFF r - p"	# Bit-flip and print.
181062306a36Sopenharmony_ci	) |
181162306a36Sopenharmony_ci	    dc |
181262306a36Sopenharmony_ci	    tr '[:upper:]' '[:lower:]'
181362306a36Sopenharmony_ci}
181462306a36Sopenharmony_ci
181562306a36Sopenharmony_cipayload_template_expand_checksum()
181662306a36Sopenharmony_ci{
181762306a36Sopenharmony_ci	local payload=$1; shift
181862306a36Sopenharmony_ci	local checksum=$1; shift
181962306a36Sopenharmony_ci
182062306a36Sopenharmony_ci	local ckbytes=$(u16_to_bytes $checksum)
182162306a36Sopenharmony_ci
182262306a36Sopenharmony_ci	echo "$payload" | sed "s/CHECKSUM/$ckbytes/g"
182362306a36Sopenharmony_ci}
182462306a36Sopenharmony_ci
182562306a36Sopenharmony_cipayload_template_nbytes()
182662306a36Sopenharmony_ci{
182762306a36Sopenharmony_ci	local payload=$1; shift
182862306a36Sopenharmony_ci
182962306a36Sopenharmony_ci	payload_template_expand_checksum "${payload%:}" 0 |
183062306a36Sopenharmony_ci		sed 's/:/\n/g' | wc -l
183162306a36Sopenharmony_ci}
183262306a36Sopenharmony_ci
183362306a36Sopenharmony_ciigmpv3_is_in_get()
183462306a36Sopenharmony_ci{
183562306a36Sopenharmony_ci	local GRP=$1; shift
183662306a36Sopenharmony_ci	local sources=("$@")
183762306a36Sopenharmony_ci
183862306a36Sopenharmony_ci	local igmpv3
183962306a36Sopenharmony_ci	local nsources=$(u16_to_bytes ${#sources[@]})
184062306a36Sopenharmony_ci
184162306a36Sopenharmony_ci	# IS_IN ( $sources )
184262306a36Sopenharmony_ci	igmpv3=$(:
184362306a36Sopenharmony_ci		)"22:"$(			: Type - Membership Report
184462306a36Sopenharmony_ci		)"00:"$(			: Reserved
184562306a36Sopenharmony_ci		)"CHECKSUM:"$(			: Checksum
184662306a36Sopenharmony_ci		)"00:00:"$(			: Reserved
184762306a36Sopenharmony_ci		)"00:01:"$(			: Number of Group Records
184862306a36Sopenharmony_ci		)"01:"$(			: Record Type - IS_IN
184962306a36Sopenharmony_ci		)"00:"$(			: Aux Data Len
185062306a36Sopenharmony_ci		)"${nsources}:"$(		: Number of Sources
185162306a36Sopenharmony_ci		)"$(ipv4_to_bytes $GRP):"$(	: Multicast Address
185262306a36Sopenharmony_ci		)"$(for src in "${sources[@]}"; do
185362306a36Sopenharmony_ci			ipv4_to_bytes $src
185462306a36Sopenharmony_ci			echo -n :
185562306a36Sopenharmony_ci		    done)"$(			: Source Addresses
185662306a36Sopenharmony_ci		)
185762306a36Sopenharmony_ci	local checksum=$(payload_template_calc_checksum "$igmpv3")
185862306a36Sopenharmony_ci
185962306a36Sopenharmony_ci	payload_template_expand_checksum "$igmpv3" $checksum
186062306a36Sopenharmony_ci}
186162306a36Sopenharmony_ci
186262306a36Sopenharmony_ciigmpv2_leave_get()
186362306a36Sopenharmony_ci{
186462306a36Sopenharmony_ci	local GRP=$1; shift
186562306a36Sopenharmony_ci
186662306a36Sopenharmony_ci	local payload=$(:
186762306a36Sopenharmony_ci		)"17:"$(			: Type - Leave Group
186862306a36Sopenharmony_ci		)"00:"$(			: Max Resp Time - not meaningful
186962306a36Sopenharmony_ci		)"CHECKSUM:"$(			: Checksum
187062306a36Sopenharmony_ci		)"$(ipv4_to_bytes $GRP)"$(	: Group Address
187162306a36Sopenharmony_ci		)
187262306a36Sopenharmony_ci	local checksum=$(payload_template_calc_checksum "$payload")
187362306a36Sopenharmony_ci
187462306a36Sopenharmony_ci	payload_template_expand_checksum "$payload" $checksum
187562306a36Sopenharmony_ci}
187662306a36Sopenharmony_ci
187762306a36Sopenharmony_cimldv2_is_in_get()
187862306a36Sopenharmony_ci{
187962306a36Sopenharmony_ci	local SIP=$1; shift
188062306a36Sopenharmony_ci	local GRP=$1; shift
188162306a36Sopenharmony_ci	local sources=("$@")
188262306a36Sopenharmony_ci
188362306a36Sopenharmony_ci	local hbh
188462306a36Sopenharmony_ci	local icmpv6
188562306a36Sopenharmony_ci	local nsources=$(u16_to_bytes ${#sources[@]})
188662306a36Sopenharmony_ci
188762306a36Sopenharmony_ci	hbh=$(:
188862306a36Sopenharmony_ci		)"3a:"$(			: Next Header - ICMPv6
188962306a36Sopenharmony_ci		)"00:"$(			: Hdr Ext Len
189062306a36Sopenharmony_ci		)"00:00:00:00:00:00:"$(		: Options and Padding
189162306a36Sopenharmony_ci		)
189262306a36Sopenharmony_ci
189362306a36Sopenharmony_ci	icmpv6=$(:
189462306a36Sopenharmony_ci		)"8f:"$(			: Type - MLDv2 Report
189562306a36Sopenharmony_ci		)"00:"$(			: Code
189662306a36Sopenharmony_ci		)"CHECKSUM:"$(			: Checksum
189762306a36Sopenharmony_ci		)"00:00:"$(			: Reserved
189862306a36Sopenharmony_ci		)"00:01:"$(			: Number of Group Records
189962306a36Sopenharmony_ci		)"01:"$(			: Record Type - IS_IN
190062306a36Sopenharmony_ci		)"00:"$(			: Aux Data Len
190162306a36Sopenharmony_ci		)"${nsources}:"$(		: Number of Sources
190262306a36Sopenharmony_ci		)"$(ipv6_to_bytes $GRP):"$(	: Multicast address
190362306a36Sopenharmony_ci		)"$(for src in "${sources[@]}"; do
190462306a36Sopenharmony_ci			ipv6_to_bytes $src
190562306a36Sopenharmony_ci			echo -n :
190662306a36Sopenharmony_ci		    done)"$(			: Source Addresses
190762306a36Sopenharmony_ci		)
190862306a36Sopenharmony_ci
190962306a36Sopenharmony_ci	local len=$(u16_to_bytes $(payload_template_nbytes $icmpv6))
191062306a36Sopenharmony_ci	local sudohdr=$(:
191162306a36Sopenharmony_ci		)"$(ipv6_to_bytes $SIP):"$(	: SIP
191262306a36Sopenharmony_ci		)"$(ipv6_to_bytes $GRP):"$(	: DIP is multicast address
191362306a36Sopenharmony_ci	        )"${len}:"$(			: Upper-layer length
191462306a36Sopenharmony_ci	        )"00:3a:"$(			: Zero and next-header
191562306a36Sopenharmony_ci	        )
191662306a36Sopenharmony_ci	local checksum=$(payload_template_calc_checksum ${sudohdr}${icmpv6})
191762306a36Sopenharmony_ci
191862306a36Sopenharmony_ci	payload_template_expand_checksum "$hbh$icmpv6" $checksum
191962306a36Sopenharmony_ci}
192062306a36Sopenharmony_ci
192162306a36Sopenharmony_cimldv1_done_get()
192262306a36Sopenharmony_ci{
192362306a36Sopenharmony_ci	local SIP=$1; shift
192462306a36Sopenharmony_ci	local GRP=$1; shift
192562306a36Sopenharmony_ci
192662306a36Sopenharmony_ci	local hbh
192762306a36Sopenharmony_ci	local icmpv6
192862306a36Sopenharmony_ci
192962306a36Sopenharmony_ci	hbh=$(:
193062306a36Sopenharmony_ci		)"3a:"$(			: Next Header - ICMPv6
193162306a36Sopenharmony_ci		)"00:"$(			: Hdr Ext Len
193262306a36Sopenharmony_ci		)"00:00:00:00:00:00:"$(		: Options and Padding
193362306a36Sopenharmony_ci		)
193462306a36Sopenharmony_ci
193562306a36Sopenharmony_ci	icmpv6=$(:
193662306a36Sopenharmony_ci		)"84:"$(			: Type - MLDv1 Done
193762306a36Sopenharmony_ci		)"00:"$(			: Code
193862306a36Sopenharmony_ci		)"CHECKSUM:"$(			: Checksum
193962306a36Sopenharmony_ci		)"00:00:"$(			: Max Resp Delay - not meaningful
194062306a36Sopenharmony_ci		)"00:00:"$(			: Reserved
194162306a36Sopenharmony_ci		)"$(ipv6_to_bytes $GRP):"$(	: Multicast address
194262306a36Sopenharmony_ci		)
194362306a36Sopenharmony_ci
194462306a36Sopenharmony_ci	local len=$(u16_to_bytes $(payload_template_nbytes $icmpv6))
194562306a36Sopenharmony_ci	local sudohdr=$(:
194662306a36Sopenharmony_ci		)"$(ipv6_to_bytes $SIP):"$(	: SIP
194762306a36Sopenharmony_ci		)"$(ipv6_to_bytes $GRP):"$(	: DIP is multicast address
194862306a36Sopenharmony_ci	        )"${len}:"$(			: Upper-layer length
194962306a36Sopenharmony_ci	        )"00:3a:"$(			: Zero and next-header
195062306a36Sopenharmony_ci	        )
195162306a36Sopenharmony_ci	local checksum=$(payload_template_calc_checksum ${sudohdr}${icmpv6})
195262306a36Sopenharmony_ci
195362306a36Sopenharmony_ci	payload_template_expand_checksum "$hbh$icmpv6" $checksum
195462306a36Sopenharmony_ci}
195562306a36Sopenharmony_ci
195662306a36Sopenharmony_cibail_on_lldpad()
195762306a36Sopenharmony_ci{
195862306a36Sopenharmony_ci	local reason1="$1"; shift
195962306a36Sopenharmony_ci	local reason2="$1"; shift
196062306a36Sopenharmony_ci
196162306a36Sopenharmony_ci	if systemctl is-active --quiet lldpad; then
196262306a36Sopenharmony_ci
196362306a36Sopenharmony_ci		cat >/dev/stderr <<-EOF
196462306a36Sopenharmony_ci		WARNING: lldpad is running
196562306a36Sopenharmony_ci
196662306a36Sopenharmony_ci			lldpad will likely $reason1, and this test will
196762306a36Sopenharmony_ci			$reason2. Both are not supported at the same time,
196862306a36Sopenharmony_ci			one of them is arbitrarily going to overwrite the
196962306a36Sopenharmony_ci			other. That will cause spurious failures (or, unlikely,
197062306a36Sopenharmony_ci			passes) of this test.
197162306a36Sopenharmony_ci		EOF
197262306a36Sopenharmony_ci
197362306a36Sopenharmony_ci		if [[ -z $ALLOW_LLDPAD ]]; then
197462306a36Sopenharmony_ci			cat >/dev/stderr <<-EOF
197562306a36Sopenharmony_ci
197662306a36Sopenharmony_ci				If you want to run the test anyway, please set
197762306a36Sopenharmony_ci				an environment variable ALLOW_LLDPAD to a
197862306a36Sopenharmony_ci				non-empty string.
197962306a36Sopenharmony_ci			EOF
198062306a36Sopenharmony_ci			exit 1
198162306a36Sopenharmony_ci		else
198262306a36Sopenharmony_ci			return
198362306a36Sopenharmony_ci		fi
198462306a36Sopenharmony_ci	fi
198562306a36Sopenharmony_ci}
1986