18c2ecf20Sopenharmony_ci#!/bin/bash
28c2ecf20Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci##############################################################################
58c2ecf20Sopenharmony_ci# Defines
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci# Can be overridden by the configuration file.
88c2ecf20Sopenharmony_ciPING=${PING:=ping}
98c2ecf20Sopenharmony_ciPING6=${PING6:=ping6}
108c2ecf20Sopenharmony_ciMZ=${MZ:=mausezahn}
118c2ecf20Sopenharmony_ciARPING=${ARPING:=arping}
128c2ecf20Sopenharmony_ciTEAMD=${TEAMD:=teamd}
138c2ecf20Sopenharmony_ciWAIT_TIME=${WAIT_TIME:=5}
148c2ecf20Sopenharmony_ciPAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
158c2ecf20Sopenharmony_ciPAUSE_ON_CLEANUP=${PAUSE_ON_CLEANUP:=no}
168c2ecf20Sopenharmony_ciNETIF_TYPE=${NETIF_TYPE:=veth}
178c2ecf20Sopenharmony_ciNETIF_CREATE=${NETIF_CREATE:=yes}
188c2ecf20Sopenharmony_ciMCD=${MCD:=smcrouted}
198c2ecf20Sopenharmony_ciMC_CLI=${MC_CLI:=smcroutectl}
208c2ecf20Sopenharmony_ciPING_TIMEOUT=${PING_TIMEOUT:=5}
218c2ecf20Sopenharmony_ciWAIT_TIMEOUT=${WAIT_TIMEOUT:=20}
228c2ecf20Sopenharmony_ciINTERFACE_TIMEOUT=${INTERFACE_TIMEOUT:=600}
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_cirelative_path="${BASH_SOURCE%/*}"
258c2ecf20Sopenharmony_ciif [[ "$relative_path" == "${BASH_SOURCE}" ]]; then
268c2ecf20Sopenharmony_ci	relative_path="."
278c2ecf20Sopenharmony_cifi
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ciif [[ -f $relative_path/forwarding.config ]]; then
308c2ecf20Sopenharmony_ci	source "$relative_path/forwarding.config"
318c2ecf20Sopenharmony_cifi
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci##############################################################################
348c2ecf20Sopenharmony_ci# Sanity checks
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_cicheck_tc_version()
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	tc -j &> /dev/null
398c2ecf20Sopenharmony_ci	if [[ $? -ne 0 ]]; then
408c2ecf20Sopenharmony_ci		echo "SKIP: iproute2 too old; tc is missing JSON support"
418c2ecf20Sopenharmony_ci		exit 1
428c2ecf20Sopenharmony_ci	fi
438c2ecf20Sopenharmony_ci}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cicheck_tc_shblock_support()
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	tc filter help 2>&1 | grep block &> /dev/null
488c2ecf20Sopenharmony_ci	if [[ $? -ne 0 ]]; then
498c2ecf20Sopenharmony_ci		echo "SKIP: iproute2 too old; tc is missing shared block support"
508c2ecf20Sopenharmony_ci		exit 1
518c2ecf20Sopenharmony_ci	fi
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_cicheck_tc_chain_support()
558c2ecf20Sopenharmony_ci{
568c2ecf20Sopenharmony_ci	tc help 2>&1|grep chain &> /dev/null
578c2ecf20Sopenharmony_ci	if [[ $? -ne 0 ]]; then
588c2ecf20Sopenharmony_ci		echo "SKIP: iproute2 too old; tc is missing chain support"
598c2ecf20Sopenharmony_ci		exit 1
608c2ecf20Sopenharmony_ci	fi
618c2ecf20Sopenharmony_ci}
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cicheck_tc_action_hw_stats_support()
648c2ecf20Sopenharmony_ci{
658c2ecf20Sopenharmony_ci	tc actions help 2>&1 | grep -q hw_stats
668c2ecf20Sopenharmony_ci	if [[ $? -ne 0 ]]; then
678c2ecf20Sopenharmony_ci		echo "SKIP: iproute2 too old; tc is missing action hw_stats support"
688c2ecf20Sopenharmony_ci		exit 1
698c2ecf20Sopenharmony_ci	fi
708c2ecf20Sopenharmony_ci}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ciskip_on_veth()
738c2ecf20Sopenharmony_ci{
748c2ecf20Sopenharmony_ci	local kind=$(ip -j -d link show dev ${NETIFS[p1]} |
758c2ecf20Sopenharmony_ci		jq -r '.[].linkinfo.info_kind')
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	if [[ $kind == veth ]]; then
788c2ecf20Sopenharmony_ci		echo "SKIP: Test cannot be run with veth pairs"
798c2ecf20Sopenharmony_ci		exit $ksft_skip
808c2ecf20Sopenharmony_ci	fi
818c2ecf20Sopenharmony_ci}
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ciif [[ "$(id -u)" -ne 0 ]]; then
848c2ecf20Sopenharmony_ci	echo "SKIP: need root privileges"
858c2ecf20Sopenharmony_ci	exit 0
868c2ecf20Sopenharmony_cifi
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ciif [[ "$CHECK_TC" = "yes" ]]; then
898c2ecf20Sopenharmony_ci	check_tc_version
908c2ecf20Sopenharmony_cifi
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_cirequire_command()
938c2ecf20Sopenharmony_ci{
948c2ecf20Sopenharmony_ci	local cmd=$1; shift
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	if [[ ! -x "$(command -v "$cmd")" ]]; then
978c2ecf20Sopenharmony_ci		echo "SKIP: $cmd not installed"
988c2ecf20Sopenharmony_ci		exit 1
998c2ecf20Sopenharmony_ci	fi
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_cirequire_command jq
1038c2ecf20Sopenharmony_cirequire_command $MZ
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ciif [[ ! -v NUM_NETIFS ]]; then
1068c2ecf20Sopenharmony_ci	echo "SKIP: importer does not define \"NUM_NETIFS\""
1078c2ecf20Sopenharmony_ci	exit 1
1088c2ecf20Sopenharmony_cifi
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci##############################################################################
1118c2ecf20Sopenharmony_ci# Command line options handling
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cicount=0
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ciwhile [[ $# -gt 0 ]]; do
1168c2ecf20Sopenharmony_ci	if [[ "$count" -eq "0" ]]; then
1178c2ecf20Sopenharmony_ci		unset NETIFS
1188c2ecf20Sopenharmony_ci		declare -A NETIFS
1198c2ecf20Sopenharmony_ci	fi
1208c2ecf20Sopenharmony_ci	count=$((count + 1))
1218c2ecf20Sopenharmony_ci	NETIFS[p$count]="$1"
1228c2ecf20Sopenharmony_ci	shift
1238c2ecf20Sopenharmony_cidone
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci##############################################################################
1268c2ecf20Sopenharmony_ci# Network interfaces configuration
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_cicreate_netif_veth()
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	local i
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	for ((i = 1; i <= NUM_NETIFS; ++i)); do
1338c2ecf20Sopenharmony_ci		local j=$((i+1))
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci		if [ -z ${NETIFS[p$i]} ]; then
1368c2ecf20Sopenharmony_ci			echo "SKIP: Cannot create interface. Name not specified"
1378c2ecf20Sopenharmony_ci			exit $ksft_skip
1388c2ecf20Sopenharmony_ci		fi
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci		ip link show dev ${NETIFS[p$i]} &> /dev/null
1418c2ecf20Sopenharmony_ci		if [[ $? -ne 0 ]]; then
1428c2ecf20Sopenharmony_ci			ip link add ${NETIFS[p$i]} type veth \
1438c2ecf20Sopenharmony_ci				peer name ${NETIFS[p$j]}
1448c2ecf20Sopenharmony_ci			if [[ $? -ne 0 ]]; then
1458c2ecf20Sopenharmony_ci				echo "Failed to create netif"
1468c2ecf20Sopenharmony_ci				exit 1
1478c2ecf20Sopenharmony_ci			fi
1488c2ecf20Sopenharmony_ci		fi
1498c2ecf20Sopenharmony_ci		i=$j
1508c2ecf20Sopenharmony_ci	done
1518c2ecf20Sopenharmony_ci}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_cicreate_netif()
1548c2ecf20Sopenharmony_ci{
1558c2ecf20Sopenharmony_ci	case "$NETIF_TYPE" in
1568c2ecf20Sopenharmony_ci	veth) create_netif_veth
1578c2ecf20Sopenharmony_ci	      ;;
1588c2ecf20Sopenharmony_ci	*) echo "Can not create interfaces of type \'$NETIF_TYPE\'"
1598c2ecf20Sopenharmony_ci	   exit 1
1608c2ecf20Sopenharmony_ci	   ;;
1618c2ecf20Sopenharmony_ci	esac
1628c2ecf20Sopenharmony_ci}
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ciif [[ "$NETIF_CREATE" = "yes" ]]; then
1658c2ecf20Sopenharmony_ci	create_netif
1668c2ecf20Sopenharmony_cifi
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cifor ((i = 1; i <= NUM_NETIFS; ++i)); do
1698c2ecf20Sopenharmony_ci	ip link show dev ${NETIFS[p$i]} &> /dev/null
1708c2ecf20Sopenharmony_ci	if [[ $? -ne 0 ]]; then
1718c2ecf20Sopenharmony_ci		echo "SKIP: could not find all required interfaces"
1728c2ecf20Sopenharmony_ci		exit 1
1738c2ecf20Sopenharmony_ci	fi
1748c2ecf20Sopenharmony_cidone
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci##############################################################################
1778c2ecf20Sopenharmony_ci# Helpers
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci# Exit status to return at the end. Set in case one of the tests fails.
1808c2ecf20Sopenharmony_ciEXIT_STATUS=0
1818c2ecf20Sopenharmony_ci# Per-test return value. Clear at the beginning of each test.
1828c2ecf20Sopenharmony_ciRET=0
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_cicheck_err()
1858c2ecf20Sopenharmony_ci{
1868c2ecf20Sopenharmony_ci	local err=$1
1878c2ecf20Sopenharmony_ci	local msg=$2
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	if [[ $RET -eq 0 && $err -ne 0 ]]; then
1908c2ecf20Sopenharmony_ci		RET=$err
1918c2ecf20Sopenharmony_ci		retmsg=$msg
1928c2ecf20Sopenharmony_ci	fi
1938c2ecf20Sopenharmony_ci}
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_cicheck_fail()
1968c2ecf20Sopenharmony_ci{
1978c2ecf20Sopenharmony_ci	local err=$1
1988c2ecf20Sopenharmony_ci	local msg=$2
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	if [[ $RET -eq 0 && $err -eq 0 ]]; then
2018c2ecf20Sopenharmony_ci		RET=1
2028c2ecf20Sopenharmony_ci		retmsg=$msg
2038c2ecf20Sopenharmony_ci	fi
2048c2ecf20Sopenharmony_ci}
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_cicheck_err_fail()
2078c2ecf20Sopenharmony_ci{
2088c2ecf20Sopenharmony_ci	local should_fail=$1; shift
2098c2ecf20Sopenharmony_ci	local err=$1; shift
2108c2ecf20Sopenharmony_ci	local what=$1; shift
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	if ((should_fail)); then
2138c2ecf20Sopenharmony_ci		check_fail $err "$what succeeded, but should have failed"
2148c2ecf20Sopenharmony_ci	else
2158c2ecf20Sopenharmony_ci		check_err $err "$what failed"
2168c2ecf20Sopenharmony_ci	fi
2178c2ecf20Sopenharmony_ci}
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_cilog_test()
2208c2ecf20Sopenharmony_ci{
2218c2ecf20Sopenharmony_ci	local test_name=$1
2228c2ecf20Sopenharmony_ci	local opt_str=$2
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	if [[ $# -eq 2 ]]; then
2258c2ecf20Sopenharmony_ci		opt_str="($opt_str)"
2268c2ecf20Sopenharmony_ci	fi
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	if [[ $RET -ne 0 ]]; then
2298c2ecf20Sopenharmony_ci		EXIT_STATUS=1
2308c2ecf20Sopenharmony_ci		printf "TEST: %-60s  [FAIL]\n" "$test_name $opt_str"
2318c2ecf20Sopenharmony_ci		if [[ ! -z "$retmsg" ]]; then
2328c2ecf20Sopenharmony_ci			printf "\t%s\n" "$retmsg"
2338c2ecf20Sopenharmony_ci		fi
2348c2ecf20Sopenharmony_ci		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
2358c2ecf20Sopenharmony_ci			echo "Hit enter to continue, 'q' to quit"
2368c2ecf20Sopenharmony_ci			read a
2378c2ecf20Sopenharmony_ci			[ "$a" = "q" ] && exit 1
2388c2ecf20Sopenharmony_ci		fi
2398c2ecf20Sopenharmony_ci		return 1
2408c2ecf20Sopenharmony_ci	fi
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	printf "TEST: %-60s  [ OK ]\n" "$test_name $opt_str"
2438c2ecf20Sopenharmony_ci	return 0
2448c2ecf20Sopenharmony_ci}
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_cilog_info()
2478c2ecf20Sopenharmony_ci{
2488c2ecf20Sopenharmony_ci	local msg=$1
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	echo "INFO: $msg"
2518c2ecf20Sopenharmony_ci}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_cibusywait()
2548c2ecf20Sopenharmony_ci{
2558c2ecf20Sopenharmony_ci	local timeout=$1; shift
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	local start_time="$(date -u +%s%3N)"
2588c2ecf20Sopenharmony_ci	while true
2598c2ecf20Sopenharmony_ci	do
2608c2ecf20Sopenharmony_ci		local out
2618c2ecf20Sopenharmony_ci		out=$("$@")
2628c2ecf20Sopenharmony_ci		local ret=$?
2638c2ecf20Sopenharmony_ci		if ((!ret)); then
2648c2ecf20Sopenharmony_ci			echo -n "$out"
2658c2ecf20Sopenharmony_ci			return 0
2668c2ecf20Sopenharmony_ci		fi
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci		local current_time="$(date -u +%s%3N)"
2698c2ecf20Sopenharmony_ci		if ((current_time - start_time > timeout)); then
2708c2ecf20Sopenharmony_ci			echo -n "$out"
2718c2ecf20Sopenharmony_ci			return 1
2728c2ecf20Sopenharmony_ci		fi
2738c2ecf20Sopenharmony_ci	done
2748c2ecf20Sopenharmony_ci}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_cinot()
2778c2ecf20Sopenharmony_ci{
2788c2ecf20Sopenharmony_ci	"$@"
2798c2ecf20Sopenharmony_ci	[[ $? != 0 ]]
2808c2ecf20Sopenharmony_ci}
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_cigrep_bridge_fdb()
2838c2ecf20Sopenharmony_ci{
2848c2ecf20Sopenharmony_ci	local addr=$1; shift
2858c2ecf20Sopenharmony_ci	local word
2868c2ecf20Sopenharmony_ci	local flag
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	if [ "$1" == "self" ] || [ "$1" == "master" ]; then
2898c2ecf20Sopenharmony_ci		word=$1; shift
2908c2ecf20Sopenharmony_ci		if [ "$1" == "-v" ]; then
2918c2ecf20Sopenharmony_ci			flag=$1; shift
2928c2ecf20Sopenharmony_ci		fi
2938c2ecf20Sopenharmony_ci	fi
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	$@ | grep $addr | grep $flag "$word"
2968c2ecf20Sopenharmony_ci}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ciwait_for_offload()
2998c2ecf20Sopenharmony_ci{
3008c2ecf20Sopenharmony_ci	"$@" | grep -q offload
3018c2ecf20Sopenharmony_ci}
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ciuntil_counter_is()
3048c2ecf20Sopenharmony_ci{
3058c2ecf20Sopenharmony_ci	local expr=$1; shift
3068c2ecf20Sopenharmony_ci	local current=$("$@")
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	echo $((current))
3098c2ecf20Sopenharmony_ci	((current $expr))
3108c2ecf20Sopenharmony_ci}
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_cibusywait_for_counter()
3138c2ecf20Sopenharmony_ci{
3148c2ecf20Sopenharmony_ci	local timeout=$1; shift
3158c2ecf20Sopenharmony_ci	local delta=$1; shift
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	local base=$("$@")
3188c2ecf20Sopenharmony_ci	busywait "$timeout" until_counter_is ">= $((base + delta))" "$@"
3198c2ecf20Sopenharmony_ci}
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_cisetup_wait_dev()
3228c2ecf20Sopenharmony_ci{
3238c2ecf20Sopenharmony_ci	local dev=$1; shift
3248c2ecf20Sopenharmony_ci	local wait_time=${1:-$WAIT_TIME}; shift
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	setup_wait_dev_with_timeout "$dev" $INTERFACE_TIMEOUT $wait_time
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	if (($?)); then
3298c2ecf20Sopenharmony_ci		check_err 1
3308c2ecf20Sopenharmony_ci		log_test setup_wait_dev ": Interface $dev does not come up."
3318c2ecf20Sopenharmony_ci		exit 1
3328c2ecf20Sopenharmony_ci	fi
3338c2ecf20Sopenharmony_ci}
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_cisetup_wait_dev_with_timeout()
3368c2ecf20Sopenharmony_ci{
3378c2ecf20Sopenharmony_ci	local dev=$1; shift
3388c2ecf20Sopenharmony_ci	local max_iterations=${1:-$WAIT_TIMEOUT}; shift
3398c2ecf20Sopenharmony_ci	local wait_time=${1:-$WAIT_TIME}; shift
3408c2ecf20Sopenharmony_ci	local i
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	for ((i = 1; i <= $max_iterations; ++i)); do
3438c2ecf20Sopenharmony_ci		ip link show dev $dev up \
3448c2ecf20Sopenharmony_ci			| grep 'state UP' &> /dev/null
3458c2ecf20Sopenharmony_ci		if [[ $? -ne 0 ]]; then
3468c2ecf20Sopenharmony_ci			sleep 1
3478c2ecf20Sopenharmony_ci		else
3488c2ecf20Sopenharmony_ci			sleep $wait_time
3498c2ecf20Sopenharmony_ci			return 0
3508c2ecf20Sopenharmony_ci		fi
3518c2ecf20Sopenharmony_ci	done
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	return 1
3548c2ecf20Sopenharmony_ci}
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_cisetup_wait()
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	local num_netifs=${1:-$NUM_NETIFS}
3598c2ecf20Sopenharmony_ci	local i
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	for ((i = 1; i <= num_netifs; ++i)); do
3628c2ecf20Sopenharmony_ci		setup_wait_dev ${NETIFS[p$i]} 0
3638c2ecf20Sopenharmony_ci	done
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	# Make sure links are ready.
3668c2ecf20Sopenharmony_ci	sleep $WAIT_TIME
3678c2ecf20Sopenharmony_ci}
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_cicmd_jq()
3708c2ecf20Sopenharmony_ci{
3718c2ecf20Sopenharmony_ci	local cmd=$1
3728c2ecf20Sopenharmony_ci	local jq_exp=$2
3738c2ecf20Sopenharmony_ci	local jq_opts=$3
3748c2ecf20Sopenharmony_ci	local ret
3758c2ecf20Sopenharmony_ci	local output
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	output="$($cmd)"
3788c2ecf20Sopenharmony_ci	# it the command fails, return error right away
3798c2ecf20Sopenharmony_ci	ret=$?
3808c2ecf20Sopenharmony_ci	if [[ $ret -ne 0 ]]; then
3818c2ecf20Sopenharmony_ci		return $ret
3828c2ecf20Sopenharmony_ci	fi
3838c2ecf20Sopenharmony_ci	output=$(echo $output | jq -r $jq_opts "$jq_exp")
3848c2ecf20Sopenharmony_ci	ret=$?
3858c2ecf20Sopenharmony_ci	if [[ $ret -ne 0 ]]; then
3868c2ecf20Sopenharmony_ci		return $ret
3878c2ecf20Sopenharmony_ci	fi
3888c2ecf20Sopenharmony_ci	echo $output
3898c2ecf20Sopenharmony_ci	# return success only in case of non-empty output
3908c2ecf20Sopenharmony_ci	[ ! -z "$output" ]
3918c2ecf20Sopenharmony_ci}
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_cilldpad_app_wait_set()
3948c2ecf20Sopenharmony_ci{
3958c2ecf20Sopenharmony_ci	local dev=$1; shift
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	while lldptool -t -i $dev -V APP -c app | grep -Eq "pending|unknown"; do
3988c2ecf20Sopenharmony_ci		echo "$dev: waiting for lldpad to push pending APP updates"
3998c2ecf20Sopenharmony_ci		sleep 5
4008c2ecf20Sopenharmony_ci	done
4018c2ecf20Sopenharmony_ci}
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_cilldpad_app_wait_del()
4048c2ecf20Sopenharmony_ci{
4058c2ecf20Sopenharmony_ci	# Give lldpad a chance to push down the changes. If the device is downed
4068c2ecf20Sopenharmony_ci	# too soon, the updates will be left pending. However, they will have
4078c2ecf20Sopenharmony_ci	# been struck off the lldpad's DB already, so we won't be able to tell
4088c2ecf20Sopenharmony_ci	# they are pending. Then on next test iteration this would cause
4098c2ecf20Sopenharmony_ci	# weirdness as newly-added APP rules conflict with the old ones,
4108c2ecf20Sopenharmony_ci	# sometimes getting stuck in an "unknown" state.
4118c2ecf20Sopenharmony_ci	sleep 5
4128c2ecf20Sopenharmony_ci}
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_cipre_cleanup()
4158c2ecf20Sopenharmony_ci{
4168c2ecf20Sopenharmony_ci	if [ "${PAUSE_ON_CLEANUP}" = "yes" ]; then
4178c2ecf20Sopenharmony_ci		echo "Pausing before cleanup, hit any key to continue"
4188c2ecf20Sopenharmony_ci		read
4198c2ecf20Sopenharmony_ci	fi
4208c2ecf20Sopenharmony_ci}
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_civrf_prepare()
4238c2ecf20Sopenharmony_ci{
4248c2ecf20Sopenharmony_ci	ip -4 rule add pref 32765 table local
4258c2ecf20Sopenharmony_ci	ip -4 rule del pref 0
4268c2ecf20Sopenharmony_ci	ip -6 rule add pref 32765 table local
4278c2ecf20Sopenharmony_ci	ip -6 rule del pref 0
4288c2ecf20Sopenharmony_ci}
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_civrf_cleanup()
4318c2ecf20Sopenharmony_ci{
4328c2ecf20Sopenharmony_ci	ip -6 rule add pref 0 table local
4338c2ecf20Sopenharmony_ci	ip -6 rule del pref 32765
4348c2ecf20Sopenharmony_ci	ip -4 rule add pref 0 table local
4358c2ecf20Sopenharmony_ci	ip -4 rule del pref 32765
4368c2ecf20Sopenharmony_ci}
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci__last_tb_id=0
4398c2ecf20Sopenharmony_cideclare -A __TB_IDS
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci__vrf_td_id_assign()
4428c2ecf20Sopenharmony_ci{
4438c2ecf20Sopenharmony_ci	local vrf_name=$1
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci	__last_tb_id=$((__last_tb_id + 1))
4468c2ecf20Sopenharmony_ci	__TB_IDS[$vrf_name]=$__last_tb_id
4478c2ecf20Sopenharmony_ci	return $__last_tb_id
4488c2ecf20Sopenharmony_ci}
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci__vrf_td_id_lookup()
4518c2ecf20Sopenharmony_ci{
4528c2ecf20Sopenharmony_ci	local vrf_name=$1
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	return ${__TB_IDS[$vrf_name]}
4558c2ecf20Sopenharmony_ci}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_civrf_create()
4588c2ecf20Sopenharmony_ci{
4598c2ecf20Sopenharmony_ci	local vrf_name=$1
4608c2ecf20Sopenharmony_ci	local tb_id
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	__vrf_td_id_assign $vrf_name
4638c2ecf20Sopenharmony_ci	tb_id=$?
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	ip link add dev $vrf_name type vrf table $tb_id
4668c2ecf20Sopenharmony_ci	ip -4 route add table $tb_id unreachable default metric 4278198272
4678c2ecf20Sopenharmony_ci	ip -6 route add table $tb_id unreachable default metric 4278198272
4688c2ecf20Sopenharmony_ci}
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_civrf_destroy()
4718c2ecf20Sopenharmony_ci{
4728c2ecf20Sopenharmony_ci	local vrf_name=$1
4738c2ecf20Sopenharmony_ci	local tb_id
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	__vrf_td_id_lookup $vrf_name
4768c2ecf20Sopenharmony_ci	tb_id=$?
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	ip -6 route del table $tb_id unreachable default metric 4278198272
4798c2ecf20Sopenharmony_ci	ip -4 route del table $tb_id unreachable default metric 4278198272
4808c2ecf20Sopenharmony_ci	ip link del dev $vrf_name
4818c2ecf20Sopenharmony_ci}
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci__addr_add_del()
4848c2ecf20Sopenharmony_ci{
4858c2ecf20Sopenharmony_ci	local if_name=$1
4868c2ecf20Sopenharmony_ci	local add_del=$2
4878c2ecf20Sopenharmony_ci	local array
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci	shift
4908c2ecf20Sopenharmony_ci	shift
4918c2ecf20Sopenharmony_ci	array=("${@}")
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	for addrstr in "${array[@]}"; do
4948c2ecf20Sopenharmony_ci		ip address $add_del $addrstr dev $if_name
4958c2ecf20Sopenharmony_ci	done
4968c2ecf20Sopenharmony_ci}
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci__simple_if_init()
4998c2ecf20Sopenharmony_ci{
5008c2ecf20Sopenharmony_ci	local if_name=$1; shift
5018c2ecf20Sopenharmony_ci	local vrf_name=$1; shift
5028c2ecf20Sopenharmony_ci	local addrs=("${@}")
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci	ip link set dev $if_name master $vrf_name
5058c2ecf20Sopenharmony_ci	ip link set dev $if_name up
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	__addr_add_del $if_name add "${addrs[@]}"
5088c2ecf20Sopenharmony_ci}
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci__simple_if_fini()
5118c2ecf20Sopenharmony_ci{
5128c2ecf20Sopenharmony_ci	local if_name=$1; shift
5138c2ecf20Sopenharmony_ci	local addrs=("${@}")
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	__addr_add_del $if_name del "${addrs[@]}"
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	ip link set dev $if_name down
5188c2ecf20Sopenharmony_ci	ip link set dev $if_name nomaster
5198c2ecf20Sopenharmony_ci}
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_cisimple_if_init()
5228c2ecf20Sopenharmony_ci{
5238c2ecf20Sopenharmony_ci	local if_name=$1
5248c2ecf20Sopenharmony_ci	local vrf_name
5258c2ecf20Sopenharmony_ci	local array
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	shift
5288c2ecf20Sopenharmony_ci	vrf_name=v$if_name
5298c2ecf20Sopenharmony_ci	array=("${@}")
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	vrf_create $vrf_name
5328c2ecf20Sopenharmony_ci	ip link set dev $vrf_name up
5338c2ecf20Sopenharmony_ci	__simple_if_init $if_name $vrf_name "${array[@]}"
5348c2ecf20Sopenharmony_ci}
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_cisimple_if_fini()
5378c2ecf20Sopenharmony_ci{
5388c2ecf20Sopenharmony_ci	local if_name=$1
5398c2ecf20Sopenharmony_ci	local vrf_name
5408c2ecf20Sopenharmony_ci	local array
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	shift
5438c2ecf20Sopenharmony_ci	vrf_name=v$if_name
5448c2ecf20Sopenharmony_ci	array=("${@}")
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	__simple_if_fini $if_name "${array[@]}"
5478c2ecf20Sopenharmony_ci	vrf_destroy $vrf_name
5488c2ecf20Sopenharmony_ci}
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_citunnel_create()
5518c2ecf20Sopenharmony_ci{
5528c2ecf20Sopenharmony_ci	local name=$1; shift
5538c2ecf20Sopenharmony_ci	local type=$1; shift
5548c2ecf20Sopenharmony_ci	local local=$1; shift
5558c2ecf20Sopenharmony_ci	local remote=$1; shift
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	ip link add name $name type $type \
5588c2ecf20Sopenharmony_ci	   local $local remote $remote "$@"
5598c2ecf20Sopenharmony_ci	ip link set dev $name up
5608c2ecf20Sopenharmony_ci}
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_citunnel_destroy()
5638c2ecf20Sopenharmony_ci{
5648c2ecf20Sopenharmony_ci	local name=$1; shift
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	ip link del dev $name
5678c2ecf20Sopenharmony_ci}
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_civlan_create()
5708c2ecf20Sopenharmony_ci{
5718c2ecf20Sopenharmony_ci	local if_name=$1; shift
5728c2ecf20Sopenharmony_ci	local vid=$1; shift
5738c2ecf20Sopenharmony_ci	local vrf=$1; shift
5748c2ecf20Sopenharmony_ci	local ips=("${@}")
5758c2ecf20Sopenharmony_ci	local name=$if_name.$vid
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	ip link add name $name link $if_name type vlan id $vid
5788c2ecf20Sopenharmony_ci	if [ "$vrf" != "" ]; then
5798c2ecf20Sopenharmony_ci		ip link set dev $name master $vrf
5808c2ecf20Sopenharmony_ci	fi
5818c2ecf20Sopenharmony_ci	ip link set dev $name up
5828c2ecf20Sopenharmony_ci	__addr_add_del $name add "${ips[@]}"
5838c2ecf20Sopenharmony_ci}
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_civlan_destroy()
5868c2ecf20Sopenharmony_ci{
5878c2ecf20Sopenharmony_ci	local if_name=$1; shift
5888c2ecf20Sopenharmony_ci	local vid=$1; shift
5898c2ecf20Sopenharmony_ci	local name=$if_name.$vid
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci	ip link del dev $name
5928c2ecf20Sopenharmony_ci}
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_citeam_create()
5958c2ecf20Sopenharmony_ci{
5968c2ecf20Sopenharmony_ci	local if_name=$1; shift
5978c2ecf20Sopenharmony_ci	local mode=$1; shift
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	require_command $TEAMD
6008c2ecf20Sopenharmony_ci	$TEAMD -t $if_name -d -c '{"runner": {"name": "'$mode'"}}'
6018c2ecf20Sopenharmony_ci	for slave in "$@"; do
6028c2ecf20Sopenharmony_ci		ip link set dev $slave down
6038c2ecf20Sopenharmony_ci		ip link set dev $slave master $if_name
6048c2ecf20Sopenharmony_ci		ip link set dev $slave up
6058c2ecf20Sopenharmony_ci	done
6068c2ecf20Sopenharmony_ci	ip link set dev $if_name up
6078c2ecf20Sopenharmony_ci}
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_citeam_destroy()
6108c2ecf20Sopenharmony_ci{
6118c2ecf20Sopenharmony_ci	local if_name=$1; shift
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci	$TEAMD -t $if_name -k
6148c2ecf20Sopenharmony_ci}
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_cimaster_name_get()
6178c2ecf20Sopenharmony_ci{
6188c2ecf20Sopenharmony_ci	local if_name=$1
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	ip -j link show dev $if_name | jq -r '.[]["master"]'
6218c2ecf20Sopenharmony_ci}
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_cilink_stats_get()
6248c2ecf20Sopenharmony_ci{
6258c2ecf20Sopenharmony_ci	local if_name=$1; shift
6268c2ecf20Sopenharmony_ci	local dir=$1; shift
6278c2ecf20Sopenharmony_ci	local stat=$1; shift
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	ip -j -s link show dev $if_name \
6308c2ecf20Sopenharmony_ci		| jq '.[]["stats64"]["'$dir'"]["'$stat'"]'
6318c2ecf20Sopenharmony_ci}
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_cilink_stats_tx_packets_get()
6348c2ecf20Sopenharmony_ci{
6358c2ecf20Sopenharmony_ci	link_stats_get $1 tx packets
6368c2ecf20Sopenharmony_ci}
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_cilink_stats_rx_errors_get()
6398c2ecf20Sopenharmony_ci{
6408c2ecf20Sopenharmony_ci	link_stats_get $1 rx errors
6418c2ecf20Sopenharmony_ci}
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_citc_rule_stats_get()
6448c2ecf20Sopenharmony_ci{
6458c2ecf20Sopenharmony_ci	local dev=$1; shift
6468c2ecf20Sopenharmony_ci	local pref=$1; shift
6478c2ecf20Sopenharmony_ci	local dir=$1; shift
6488c2ecf20Sopenharmony_ci	local selector=${1:-.packets}; shift
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	tc -j -s filter show dev $dev ${dir:-ingress} pref $pref \
6518c2ecf20Sopenharmony_ci	    | jq ".[1].options.actions[].stats$selector"
6528c2ecf20Sopenharmony_ci}
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_citc_rule_handle_stats_get()
6558c2ecf20Sopenharmony_ci{
6568c2ecf20Sopenharmony_ci	local id=$1; shift
6578c2ecf20Sopenharmony_ci	local handle=$1; shift
6588c2ecf20Sopenharmony_ci	local selector=${1:-.packets}; shift
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	tc -j -s filter show $id \
6618c2ecf20Sopenharmony_ci	    | jq ".[] | select(.options.handle == $handle) | \
6628c2ecf20Sopenharmony_ci		  .options.actions[0].stats$selector"
6638c2ecf20Sopenharmony_ci}
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ciethtool_stats_get()
6668c2ecf20Sopenharmony_ci{
6678c2ecf20Sopenharmony_ci	local dev=$1; shift
6688c2ecf20Sopenharmony_ci	local stat=$1; shift
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci	ethtool -S $dev | grep "^ *$stat:" | head -n 1 | cut -d: -f2
6718c2ecf20Sopenharmony_ci}
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ciqdisc_stats_get()
6748c2ecf20Sopenharmony_ci{
6758c2ecf20Sopenharmony_ci	local dev=$1; shift
6768c2ecf20Sopenharmony_ci	local handle=$1; shift
6778c2ecf20Sopenharmony_ci	local selector=$1; shift
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ci	tc -j -s qdisc show dev "$dev" \
6808c2ecf20Sopenharmony_ci	    | jq '.[] | select(.handle == "'"$handle"'") | '"$selector"
6818c2ecf20Sopenharmony_ci}
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ciqdisc_parent_stats_get()
6848c2ecf20Sopenharmony_ci{
6858c2ecf20Sopenharmony_ci	local dev=$1; shift
6868c2ecf20Sopenharmony_ci	local parent=$1; shift
6878c2ecf20Sopenharmony_ci	local selector=$1; shift
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	tc -j -s qdisc show dev "$dev" invisible \
6908c2ecf20Sopenharmony_ci	    | jq '.[] | select(.parent == "'"$parent"'") | '"$selector"
6918c2ecf20Sopenharmony_ci}
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ciipv6_stats_get()
6948c2ecf20Sopenharmony_ci{
6958c2ecf20Sopenharmony_ci	local dev=$1; shift
6968c2ecf20Sopenharmony_ci	local stat=$1; shift
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	cat /proc/net/dev_snmp6/$dev | grep "^$stat" | cut -f2
6998c2ecf20Sopenharmony_ci}
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_cihumanize()
7028c2ecf20Sopenharmony_ci{
7038c2ecf20Sopenharmony_ci	local speed=$1; shift
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci	for unit in bps Kbps Mbps Gbps; do
7068c2ecf20Sopenharmony_ci		if (($(echo "$speed < 1024" | bc))); then
7078c2ecf20Sopenharmony_ci			break
7088c2ecf20Sopenharmony_ci		fi
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci		speed=$(echo "scale=1; $speed / 1024" | bc)
7118c2ecf20Sopenharmony_ci	done
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	echo "$speed${unit}"
7148c2ecf20Sopenharmony_ci}
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_cirate()
7178c2ecf20Sopenharmony_ci{
7188c2ecf20Sopenharmony_ci	local t0=$1; shift
7198c2ecf20Sopenharmony_ci	local t1=$1; shift
7208c2ecf20Sopenharmony_ci	local interval=$1; shift
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci	echo $((8 * (t1 - t0) / interval))
7238c2ecf20Sopenharmony_ci}
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_cimac_get()
7268c2ecf20Sopenharmony_ci{
7278c2ecf20Sopenharmony_ci	local if_name=$1
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	ip -j link show dev $if_name | jq -r '.[]["address"]'
7308c2ecf20Sopenharmony_ci}
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_cibridge_ageing_time_get()
7338c2ecf20Sopenharmony_ci{
7348c2ecf20Sopenharmony_ci	local bridge=$1
7358c2ecf20Sopenharmony_ci	local ageing_time
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci	# Need to divide by 100 to convert to seconds.
7388c2ecf20Sopenharmony_ci	ageing_time=$(ip -j -d link show dev $bridge \
7398c2ecf20Sopenharmony_ci		      | jq '.[]["linkinfo"]["info_data"]["ageing_time"]')
7408c2ecf20Sopenharmony_ci	echo $((ageing_time / 100))
7418c2ecf20Sopenharmony_ci}
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_cideclare -A SYSCTL_ORIG
7448c2ecf20Sopenharmony_cisysctl_set()
7458c2ecf20Sopenharmony_ci{
7468c2ecf20Sopenharmony_ci	local key=$1; shift
7478c2ecf20Sopenharmony_ci	local value=$1; shift
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci	SYSCTL_ORIG[$key]=$(sysctl -n $key)
7508c2ecf20Sopenharmony_ci	sysctl -qw $key="$value"
7518c2ecf20Sopenharmony_ci}
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_cisysctl_restore()
7548c2ecf20Sopenharmony_ci{
7558c2ecf20Sopenharmony_ci	local key=$1; shift
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	sysctl -qw $key="${SYSCTL_ORIG[$key]}"
7588c2ecf20Sopenharmony_ci}
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_ciforwarding_enable()
7618c2ecf20Sopenharmony_ci{
7628c2ecf20Sopenharmony_ci	sysctl_set net.ipv4.conf.all.forwarding 1
7638c2ecf20Sopenharmony_ci	sysctl_set net.ipv6.conf.all.forwarding 1
7648c2ecf20Sopenharmony_ci}
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ciforwarding_restore()
7678c2ecf20Sopenharmony_ci{
7688c2ecf20Sopenharmony_ci	sysctl_restore net.ipv6.conf.all.forwarding
7698c2ecf20Sopenharmony_ci	sysctl_restore net.ipv4.conf.all.forwarding
7708c2ecf20Sopenharmony_ci}
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_cideclare -A MTU_ORIG
7738c2ecf20Sopenharmony_cimtu_set()
7748c2ecf20Sopenharmony_ci{
7758c2ecf20Sopenharmony_ci	local dev=$1; shift
7768c2ecf20Sopenharmony_ci	local mtu=$1; shift
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	MTU_ORIG["$dev"]=$(ip -j link show dev $dev | jq -e '.[].mtu')
7798c2ecf20Sopenharmony_ci	ip link set dev $dev mtu $mtu
7808c2ecf20Sopenharmony_ci}
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_cimtu_restore()
7838c2ecf20Sopenharmony_ci{
7848c2ecf20Sopenharmony_ci	local dev=$1; shift
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci	ip link set dev $dev mtu ${MTU_ORIG["$dev"]}
7878c2ecf20Sopenharmony_ci}
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_citc_offload_check()
7908c2ecf20Sopenharmony_ci{
7918c2ecf20Sopenharmony_ci	local num_netifs=${1:-$NUM_NETIFS}
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci	for ((i = 1; i <= num_netifs; ++i)); do
7948c2ecf20Sopenharmony_ci		ethtool -k ${NETIFS[p$i]} \
7958c2ecf20Sopenharmony_ci			| grep "hw-tc-offload: on" &> /dev/null
7968c2ecf20Sopenharmony_ci		if [[ $? -ne 0 ]]; then
7978c2ecf20Sopenharmony_ci			return 1
7988c2ecf20Sopenharmony_ci		fi
7998c2ecf20Sopenharmony_ci	done
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	return 0
8028c2ecf20Sopenharmony_ci}
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_citrap_install()
8058c2ecf20Sopenharmony_ci{
8068c2ecf20Sopenharmony_ci	local dev=$1; shift
8078c2ecf20Sopenharmony_ci	local direction=$1; shift
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	# Some devices may not support or need in-hardware trapping of traffic
8108c2ecf20Sopenharmony_ci	# (e.g. the veth pairs that this library creates for non-existent
8118c2ecf20Sopenharmony_ci	# loopbacks). Use continue instead, so that there is a filter in there
8128c2ecf20Sopenharmony_ci	# (some tests check counters), and so that other filters are still
8138c2ecf20Sopenharmony_ci	# processed.
8148c2ecf20Sopenharmony_ci	tc filter add dev $dev $direction pref 1 \
8158c2ecf20Sopenharmony_ci		flower skip_sw action trap 2>/dev/null \
8168c2ecf20Sopenharmony_ci	    || tc filter add dev $dev $direction pref 1 \
8178c2ecf20Sopenharmony_ci		       flower action continue
8188c2ecf20Sopenharmony_ci}
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_citrap_uninstall()
8218c2ecf20Sopenharmony_ci{
8228c2ecf20Sopenharmony_ci	local dev=$1; shift
8238c2ecf20Sopenharmony_ci	local direction=$1; shift
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ci	tc filter del dev $dev $direction pref 1 flower
8268c2ecf20Sopenharmony_ci}
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_cislow_path_trap_install()
8298c2ecf20Sopenharmony_ci{
8308c2ecf20Sopenharmony_ci	# For slow-path testing, we need to install a trap to get to
8318c2ecf20Sopenharmony_ci	# slow path the packets that would otherwise be switched in HW.
8328c2ecf20Sopenharmony_ci	if [ "${tcflags/skip_hw}" != "$tcflags" ]; then
8338c2ecf20Sopenharmony_ci		trap_install "$@"
8348c2ecf20Sopenharmony_ci	fi
8358c2ecf20Sopenharmony_ci}
8368c2ecf20Sopenharmony_ci
8378c2ecf20Sopenharmony_cislow_path_trap_uninstall()
8388c2ecf20Sopenharmony_ci{
8398c2ecf20Sopenharmony_ci	if [ "${tcflags/skip_hw}" != "$tcflags" ]; then
8408c2ecf20Sopenharmony_ci		trap_uninstall "$@"
8418c2ecf20Sopenharmony_ci	fi
8428c2ecf20Sopenharmony_ci}
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci__icmp_capture_add_del()
8458c2ecf20Sopenharmony_ci{
8468c2ecf20Sopenharmony_ci	local add_del=$1; shift
8478c2ecf20Sopenharmony_ci	local pref=$1; shift
8488c2ecf20Sopenharmony_ci	local vsuf=$1; shift
8498c2ecf20Sopenharmony_ci	local tundev=$1; shift
8508c2ecf20Sopenharmony_ci	local filter=$1; shift
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	tc filter $add_del dev "$tundev" ingress \
8538c2ecf20Sopenharmony_ci	   proto ip$vsuf pref $pref \
8548c2ecf20Sopenharmony_ci	   flower ip_proto icmp$vsuf $filter \
8558c2ecf20Sopenharmony_ci	   action pass
8568c2ecf20Sopenharmony_ci}
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ciicmp_capture_install()
8598c2ecf20Sopenharmony_ci{
8608c2ecf20Sopenharmony_ci	__icmp_capture_add_del add 100 "" "$@"
8618c2ecf20Sopenharmony_ci}
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ciicmp_capture_uninstall()
8648c2ecf20Sopenharmony_ci{
8658c2ecf20Sopenharmony_ci	__icmp_capture_add_del del 100 "" "$@"
8668c2ecf20Sopenharmony_ci}
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ciicmp6_capture_install()
8698c2ecf20Sopenharmony_ci{
8708c2ecf20Sopenharmony_ci	__icmp_capture_add_del add 100 v6 "$@"
8718c2ecf20Sopenharmony_ci}
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ciicmp6_capture_uninstall()
8748c2ecf20Sopenharmony_ci{
8758c2ecf20Sopenharmony_ci	__icmp_capture_add_del del 100 v6 "$@"
8768c2ecf20Sopenharmony_ci}
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci__vlan_capture_add_del()
8798c2ecf20Sopenharmony_ci{
8808c2ecf20Sopenharmony_ci	local add_del=$1; shift
8818c2ecf20Sopenharmony_ci	local pref=$1; shift
8828c2ecf20Sopenharmony_ci	local dev=$1; shift
8838c2ecf20Sopenharmony_ci	local filter=$1; shift
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci	tc filter $add_del dev "$dev" ingress \
8868c2ecf20Sopenharmony_ci	   proto 802.1q pref $pref \
8878c2ecf20Sopenharmony_ci	   flower $filter \
8888c2ecf20Sopenharmony_ci	   action pass
8898c2ecf20Sopenharmony_ci}
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_civlan_capture_install()
8928c2ecf20Sopenharmony_ci{
8938c2ecf20Sopenharmony_ci	__vlan_capture_add_del add 100 "$@"
8948c2ecf20Sopenharmony_ci}
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_civlan_capture_uninstall()
8978c2ecf20Sopenharmony_ci{
8988c2ecf20Sopenharmony_ci	__vlan_capture_add_del del 100 "$@"
8998c2ecf20Sopenharmony_ci}
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci__dscp_capture_add_del()
9028c2ecf20Sopenharmony_ci{
9038c2ecf20Sopenharmony_ci	local add_del=$1; shift
9048c2ecf20Sopenharmony_ci	local dev=$1; shift
9058c2ecf20Sopenharmony_ci	local base=$1; shift
9068c2ecf20Sopenharmony_ci	local dscp;
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci	for prio in {0..7}; do
9098c2ecf20Sopenharmony_ci		dscp=$((base + prio))
9108c2ecf20Sopenharmony_ci		__icmp_capture_add_del $add_del $((dscp + 100)) "" $dev \
9118c2ecf20Sopenharmony_ci				       "skip_hw ip_tos $((dscp << 2))"
9128c2ecf20Sopenharmony_ci	done
9138c2ecf20Sopenharmony_ci}
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_cidscp_capture_install()
9168c2ecf20Sopenharmony_ci{
9178c2ecf20Sopenharmony_ci	local dev=$1; shift
9188c2ecf20Sopenharmony_ci	local base=$1; shift
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci	__dscp_capture_add_del add $dev $base
9218c2ecf20Sopenharmony_ci}
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_cidscp_capture_uninstall()
9248c2ecf20Sopenharmony_ci{
9258c2ecf20Sopenharmony_ci	local dev=$1; shift
9268c2ecf20Sopenharmony_ci	local base=$1; shift
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_ci	__dscp_capture_add_del del $dev $base
9298c2ecf20Sopenharmony_ci}
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_cidscp_fetch_stats()
9328c2ecf20Sopenharmony_ci{
9338c2ecf20Sopenharmony_ci	local dev=$1; shift
9348c2ecf20Sopenharmony_ci	local base=$1; shift
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_ci	for prio in {0..7}; do
9378c2ecf20Sopenharmony_ci		local dscp=$((base + prio))
9388c2ecf20Sopenharmony_ci		local t=$(tc_rule_stats_get $dev $((dscp + 100)))
9398c2ecf20Sopenharmony_ci		echo "[$dscp]=$t "
9408c2ecf20Sopenharmony_ci	done
9418c2ecf20Sopenharmony_ci}
9428c2ecf20Sopenharmony_ci
9438c2ecf20Sopenharmony_cimatchall_sink_create()
9448c2ecf20Sopenharmony_ci{
9458c2ecf20Sopenharmony_ci	local dev=$1; shift
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_ci	tc qdisc add dev $dev clsact
9488c2ecf20Sopenharmony_ci	tc filter add dev $dev ingress \
9498c2ecf20Sopenharmony_ci	   pref 10000 \
9508c2ecf20Sopenharmony_ci	   matchall \
9518c2ecf20Sopenharmony_ci	   action drop
9528c2ecf20Sopenharmony_ci}
9538c2ecf20Sopenharmony_ci
9548c2ecf20Sopenharmony_citests_run()
9558c2ecf20Sopenharmony_ci{
9568c2ecf20Sopenharmony_ci	local current_test
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	for current_test in ${TESTS:-$ALL_TESTS}; do
9598c2ecf20Sopenharmony_ci		$current_test
9608c2ecf20Sopenharmony_ci	done
9618c2ecf20Sopenharmony_ci}
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_cimultipath_eval()
9648c2ecf20Sopenharmony_ci{
9658c2ecf20Sopenharmony_ci	local desc="$1"
9668c2ecf20Sopenharmony_ci	local weight_rp12=$2
9678c2ecf20Sopenharmony_ci	local weight_rp13=$3
9688c2ecf20Sopenharmony_ci	local packets_rp12=$4
9698c2ecf20Sopenharmony_ci	local packets_rp13=$5
9708c2ecf20Sopenharmony_ci	local weights_ratio packets_ratio diff
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	RET=0
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci	if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
9758c2ecf20Sopenharmony_ci		weights_ratio=$(echo "scale=2; $weight_rp12 / $weight_rp13" \
9768c2ecf20Sopenharmony_ci				| bc -l)
9778c2ecf20Sopenharmony_ci	else
9788c2ecf20Sopenharmony_ci		weights_ratio=$(echo "scale=2; $weight_rp13 / $weight_rp12" \
9798c2ecf20Sopenharmony_ci				| bc -l)
9808c2ecf20Sopenharmony_ci	fi
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci	if [[ "$packets_rp12" -eq "0" || "$packets_rp13" -eq "0" ]]; then
9838c2ecf20Sopenharmony_ci	       check_err 1 "Packet difference is 0"
9848c2ecf20Sopenharmony_ci	       log_test "Multipath"
9858c2ecf20Sopenharmony_ci	       log_info "Expected ratio $weights_ratio"
9868c2ecf20Sopenharmony_ci	       return
9878c2ecf20Sopenharmony_ci	fi
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_ci	if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
9908c2ecf20Sopenharmony_ci		packets_ratio=$(echo "scale=2; $packets_rp12 / $packets_rp13" \
9918c2ecf20Sopenharmony_ci				| bc -l)
9928c2ecf20Sopenharmony_ci	else
9938c2ecf20Sopenharmony_ci		packets_ratio=$(echo "scale=2; $packets_rp13 / $packets_rp12" \
9948c2ecf20Sopenharmony_ci				| bc -l)
9958c2ecf20Sopenharmony_ci	fi
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_ci	diff=$(echo $weights_ratio - $packets_ratio | bc -l)
9988c2ecf20Sopenharmony_ci	diff=${diff#-}
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci	test "$(echo "$diff / $weights_ratio > 0.15" | bc -l)" -eq 0
10018c2ecf20Sopenharmony_ci	check_err $? "Too large discrepancy between expected and measured ratios"
10028c2ecf20Sopenharmony_ci	log_test "$desc"
10038c2ecf20Sopenharmony_ci	log_info "Expected ratio $weights_ratio Measured ratio $packets_ratio"
10048c2ecf20Sopenharmony_ci}
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_ciin_ns()
10078c2ecf20Sopenharmony_ci{
10088c2ecf20Sopenharmony_ci	local name=$1; shift
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_ci	ip netns exec $name bash <<-EOF
10118c2ecf20Sopenharmony_ci		NUM_NETIFS=0
10128c2ecf20Sopenharmony_ci		source lib.sh
10138c2ecf20Sopenharmony_ci		$(for a in "$@"; do printf "%q${IFS:0:1}" "$a"; done)
10148c2ecf20Sopenharmony_ci	EOF
10158c2ecf20Sopenharmony_ci}
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci##############################################################################
10188c2ecf20Sopenharmony_ci# Tests
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_ciping_do()
10218c2ecf20Sopenharmony_ci{
10228c2ecf20Sopenharmony_ci	local if_name=$1
10238c2ecf20Sopenharmony_ci	local dip=$2
10248c2ecf20Sopenharmony_ci	local args=$3
10258c2ecf20Sopenharmony_ci	local vrf_name
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci	vrf_name=$(master_name_get $if_name)
10288c2ecf20Sopenharmony_ci	ip vrf exec $vrf_name \
10298c2ecf20Sopenharmony_ci		$PING $args $dip -c 10 -i 0.1 -w $PING_TIMEOUT &> /dev/null
10308c2ecf20Sopenharmony_ci}
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ciping_test()
10338c2ecf20Sopenharmony_ci{
10348c2ecf20Sopenharmony_ci	RET=0
10358c2ecf20Sopenharmony_ci
10368c2ecf20Sopenharmony_ci	ping_do $1 $2
10378c2ecf20Sopenharmony_ci	check_err $?
10388c2ecf20Sopenharmony_ci	log_test "ping$3"
10398c2ecf20Sopenharmony_ci}
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ciping6_do()
10428c2ecf20Sopenharmony_ci{
10438c2ecf20Sopenharmony_ci	local if_name=$1
10448c2ecf20Sopenharmony_ci	local dip=$2
10458c2ecf20Sopenharmony_ci	local args=$3
10468c2ecf20Sopenharmony_ci	local vrf_name
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ci	vrf_name=$(master_name_get $if_name)
10498c2ecf20Sopenharmony_ci	ip vrf exec $vrf_name \
10508c2ecf20Sopenharmony_ci		$PING6 $args $dip -c 10 -i 0.1 -w $PING_TIMEOUT &> /dev/null
10518c2ecf20Sopenharmony_ci}
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ciping6_test()
10548c2ecf20Sopenharmony_ci{
10558c2ecf20Sopenharmony_ci	RET=0
10568c2ecf20Sopenharmony_ci
10578c2ecf20Sopenharmony_ci	ping6_do $1 $2
10588c2ecf20Sopenharmony_ci	check_err $?
10598c2ecf20Sopenharmony_ci	log_test "ping6$3"
10608c2ecf20Sopenharmony_ci}
10618c2ecf20Sopenharmony_ci
10628c2ecf20Sopenharmony_cilearning_test()
10638c2ecf20Sopenharmony_ci{
10648c2ecf20Sopenharmony_ci	local bridge=$1
10658c2ecf20Sopenharmony_ci	local br_port1=$2	# Connected to `host1_if`.
10668c2ecf20Sopenharmony_ci	local host1_if=$3
10678c2ecf20Sopenharmony_ci	local host2_if=$4
10688c2ecf20Sopenharmony_ci	local mac=de:ad:be:ef:13:37
10698c2ecf20Sopenharmony_ci	local ageing_time
10708c2ecf20Sopenharmony_ci
10718c2ecf20Sopenharmony_ci	RET=0
10728c2ecf20Sopenharmony_ci
10738c2ecf20Sopenharmony_ci	bridge -j fdb show br $bridge brport $br_port1 \
10748c2ecf20Sopenharmony_ci		| jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
10758c2ecf20Sopenharmony_ci	check_fail $? "Found FDB record when should not"
10768c2ecf20Sopenharmony_ci
10778c2ecf20Sopenharmony_ci	# Disable unknown unicast flooding on `br_port1` to make sure
10788c2ecf20Sopenharmony_ci	# packets are only forwarded through the port after a matching
10798c2ecf20Sopenharmony_ci	# FDB entry was installed.
10808c2ecf20Sopenharmony_ci	bridge link set dev $br_port1 flood off
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci	ip link set $host1_if promisc on
10838c2ecf20Sopenharmony_ci	tc qdisc add dev $host1_if ingress
10848c2ecf20Sopenharmony_ci	tc filter add dev $host1_if ingress protocol ip pref 1 handle 101 \
10858c2ecf20Sopenharmony_ci		flower dst_mac $mac action drop
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci	$MZ $host2_if -c 1 -p 64 -b $mac -t ip -q
10888c2ecf20Sopenharmony_ci	sleep 1
10898c2ecf20Sopenharmony_ci
10908c2ecf20Sopenharmony_ci	tc -j -s filter show dev $host1_if ingress \
10918c2ecf20Sopenharmony_ci		| jq -e ".[] | select(.options.handle == 101) \
10928c2ecf20Sopenharmony_ci		| select(.options.actions[0].stats.packets == 1)" &> /dev/null
10938c2ecf20Sopenharmony_ci	check_fail $? "Packet reached first host when should not"
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ci	$MZ $host1_if -c 1 -p 64 -a $mac -t ip -q
10968c2ecf20Sopenharmony_ci	sleep 1
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_ci	bridge -j fdb show br $bridge brport $br_port1 \
10998c2ecf20Sopenharmony_ci		| jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
11008c2ecf20Sopenharmony_ci	check_err $? "Did not find FDB record when should"
11018c2ecf20Sopenharmony_ci
11028c2ecf20Sopenharmony_ci	$MZ $host2_if -c 1 -p 64 -b $mac -t ip -q
11038c2ecf20Sopenharmony_ci	sleep 1
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci	tc -j -s filter show dev $host1_if ingress \
11068c2ecf20Sopenharmony_ci		| jq -e ".[] | select(.options.handle == 101) \
11078c2ecf20Sopenharmony_ci		| select(.options.actions[0].stats.packets == 1)" &> /dev/null
11088c2ecf20Sopenharmony_ci	check_err $? "Packet did not reach second host when should"
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci	# Wait for 10 seconds after the ageing time to make sure FDB
11118c2ecf20Sopenharmony_ci	# record was aged-out.
11128c2ecf20Sopenharmony_ci	ageing_time=$(bridge_ageing_time_get $bridge)
11138c2ecf20Sopenharmony_ci	sleep $((ageing_time + 10))
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_ci	bridge -j fdb show br $bridge brport $br_port1 \
11168c2ecf20Sopenharmony_ci		| jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
11178c2ecf20Sopenharmony_ci	check_fail $? "Found FDB record when should not"
11188c2ecf20Sopenharmony_ci
11198c2ecf20Sopenharmony_ci	bridge link set dev $br_port1 learning off
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_ci	$MZ $host1_if -c 1 -p 64 -a $mac -t ip -q
11228c2ecf20Sopenharmony_ci	sleep 1
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_ci	bridge -j fdb show br $bridge brport $br_port1 \
11258c2ecf20Sopenharmony_ci		| jq -e ".[] | select(.mac == \"$mac\")" &> /dev/null
11268c2ecf20Sopenharmony_ci	check_fail $? "Found FDB record when should not"
11278c2ecf20Sopenharmony_ci
11288c2ecf20Sopenharmony_ci	bridge link set dev $br_port1 learning on
11298c2ecf20Sopenharmony_ci
11308c2ecf20Sopenharmony_ci	tc filter del dev $host1_if ingress protocol ip pref 1 handle 101 flower
11318c2ecf20Sopenharmony_ci	tc qdisc del dev $host1_if ingress
11328c2ecf20Sopenharmony_ci	ip link set $host1_if promisc off
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci	bridge link set dev $br_port1 flood on
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_ci	log_test "FDB learning"
11378c2ecf20Sopenharmony_ci}
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_ciflood_test_do()
11408c2ecf20Sopenharmony_ci{
11418c2ecf20Sopenharmony_ci	local should_flood=$1
11428c2ecf20Sopenharmony_ci	local mac=$2
11438c2ecf20Sopenharmony_ci	local ip=$3
11448c2ecf20Sopenharmony_ci	local host1_if=$4
11458c2ecf20Sopenharmony_ci	local host2_if=$5
11468c2ecf20Sopenharmony_ci	local err=0
11478c2ecf20Sopenharmony_ci
11488c2ecf20Sopenharmony_ci	# Add an ACL on `host2_if` which will tell us whether the packet
11498c2ecf20Sopenharmony_ci	# was flooded to it or not.
11508c2ecf20Sopenharmony_ci	ip link set $host2_if promisc on
11518c2ecf20Sopenharmony_ci	tc qdisc add dev $host2_if ingress
11528c2ecf20Sopenharmony_ci	tc filter add dev $host2_if ingress protocol ip pref 1 handle 101 \
11538c2ecf20Sopenharmony_ci		flower dst_mac $mac action drop
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_ci	$MZ $host1_if -c 1 -p 64 -b $mac -B $ip -t ip -q
11568c2ecf20Sopenharmony_ci	sleep 1
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_ci	tc -j -s filter show dev $host2_if ingress \
11598c2ecf20Sopenharmony_ci		| jq -e ".[] | select(.options.handle == 101) \
11608c2ecf20Sopenharmony_ci		| select(.options.actions[0].stats.packets == 1)" &> /dev/null
11618c2ecf20Sopenharmony_ci	if [[ $? -ne 0 && $should_flood == "true" || \
11628c2ecf20Sopenharmony_ci	      $? -eq 0 && $should_flood == "false" ]]; then
11638c2ecf20Sopenharmony_ci		err=1
11648c2ecf20Sopenharmony_ci	fi
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci	tc filter del dev $host2_if ingress protocol ip pref 1 handle 101 flower
11678c2ecf20Sopenharmony_ci	tc qdisc del dev $host2_if ingress
11688c2ecf20Sopenharmony_ci	ip link set $host2_if promisc off
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_ci	return $err
11718c2ecf20Sopenharmony_ci}
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_ciflood_unicast_test()
11748c2ecf20Sopenharmony_ci{
11758c2ecf20Sopenharmony_ci	local br_port=$1
11768c2ecf20Sopenharmony_ci	local host1_if=$2
11778c2ecf20Sopenharmony_ci	local host2_if=$3
11788c2ecf20Sopenharmony_ci	local mac=de:ad:be:ef:13:37
11798c2ecf20Sopenharmony_ci	local ip=192.0.2.100
11808c2ecf20Sopenharmony_ci
11818c2ecf20Sopenharmony_ci	RET=0
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ci	bridge link set dev $br_port flood off
11848c2ecf20Sopenharmony_ci
11858c2ecf20Sopenharmony_ci	flood_test_do false $mac $ip $host1_if $host2_if
11868c2ecf20Sopenharmony_ci	check_err $? "Packet flooded when should not"
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci	bridge link set dev $br_port flood on
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_ci	flood_test_do true $mac $ip $host1_if $host2_if
11918c2ecf20Sopenharmony_ci	check_err $? "Packet was not flooded when should"
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_ci	log_test "Unknown unicast flood"
11948c2ecf20Sopenharmony_ci}
11958c2ecf20Sopenharmony_ci
11968c2ecf20Sopenharmony_ciflood_multicast_test()
11978c2ecf20Sopenharmony_ci{
11988c2ecf20Sopenharmony_ci	local br_port=$1
11998c2ecf20Sopenharmony_ci	local host1_if=$2
12008c2ecf20Sopenharmony_ci	local host2_if=$3
12018c2ecf20Sopenharmony_ci	local mac=01:00:5e:00:00:01
12028c2ecf20Sopenharmony_ci	local ip=239.0.0.1
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ci	RET=0
12058c2ecf20Sopenharmony_ci
12068c2ecf20Sopenharmony_ci	bridge link set dev $br_port mcast_flood off
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci	flood_test_do false $mac $ip $host1_if $host2_if
12098c2ecf20Sopenharmony_ci	check_err $? "Packet flooded when should not"
12108c2ecf20Sopenharmony_ci
12118c2ecf20Sopenharmony_ci	bridge link set dev $br_port mcast_flood on
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci	flood_test_do true $mac $ip $host1_if $host2_if
12148c2ecf20Sopenharmony_ci	check_err $? "Packet was not flooded when should"
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci	log_test "Unregistered multicast flood"
12178c2ecf20Sopenharmony_ci}
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ciflood_test()
12208c2ecf20Sopenharmony_ci{
12218c2ecf20Sopenharmony_ci	# `br_port` is connected to `host2_if`
12228c2ecf20Sopenharmony_ci	local br_port=$1
12238c2ecf20Sopenharmony_ci	local host1_if=$2
12248c2ecf20Sopenharmony_ci	local host2_if=$3
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci	flood_unicast_test $br_port $host1_if $host2_if
12278c2ecf20Sopenharmony_ci	flood_multicast_test $br_port $host1_if $host2_if
12288c2ecf20Sopenharmony_ci}
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci__start_traffic()
12318c2ecf20Sopenharmony_ci{
12328c2ecf20Sopenharmony_ci	local proto=$1; shift
12338c2ecf20Sopenharmony_ci	local h_in=$1; shift    # Where the traffic egresses the host
12348c2ecf20Sopenharmony_ci	local sip=$1; shift
12358c2ecf20Sopenharmony_ci	local dip=$1; shift
12368c2ecf20Sopenharmony_ci	local dmac=$1; shift
12378c2ecf20Sopenharmony_ci
12388c2ecf20Sopenharmony_ci	$MZ $h_in -p 8000 -A $sip -B $dip -c 0 \
12398c2ecf20Sopenharmony_ci		-a own -b $dmac -t "$proto" -q "$@" &
12408c2ecf20Sopenharmony_ci	sleep 1
12418c2ecf20Sopenharmony_ci}
12428c2ecf20Sopenharmony_ci
12438c2ecf20Sopenharmony_cistart_traffic()
12448c2ecf20Sopenharmony_ci{
12458c2ecf20Sopenharmony_ci	__start_traffic udp "$@"
12468c2ecf20Sopenharmony_ci}
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_cistart_tcp_traffic()
12498c2ecf20Sopenharmony_ci{
12508c2ecf20Sopenharmony_ci	__start_traffic tcp "$@"
12518c2ecf20Sopenharmony_ci}
12528c2ecf20Sopenharmony_ci
12538c2ecf20Sopenharmony_cistop_traffic()
12548c2ecf20Sopenharmony_ci{
12558c2ecf20Sopenharmony_ci	# Suppress noise from killing mausezahn.
12568c2ecf20Sopenharmony_ci	{ kill %% && wait %%; } 2>/dev/null
12578c2ecf20Sopenharmony_ci}
12588c2ecf20Sopenharmony_ci
12598c2ecf20Sopenharmony_citcpdump_start()
12608c2ecf20Sopenharmony_ci{
12618c2ecf20Sopenharmony_ci	local if_name=$1; shift
12628c2ecf20Sopenharmony_ci	local ns=$1; shift
12638c2ecf20Sopenharmony_ci
12648c2ecf20Sopenharmony_ci	capfile=$(mktemp)
12658c2ecf20Sopenharmony_ci	capout=$(mktemp)
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_ci	if [ -z $ns ]; then
12688c2ecf20Sopenharmony_ci		ns_cmd=""
12698c2ecf20Sopenharmony_ci	else
12708c2ecf20Sopenharmony_ci		ns_cmd="ip netns exec ${ns}"
12718c2ecf20Sopenharmony_ci	fi
12728c2ecf20Sopenharmony_ci
12738c2ecf20Sopenharmony_ci	if [ -z $SUDO_USER ] ; then
12748c2ecf20Sopenharmony_ci		capuser=""
12758c2ecf20Sopenharmony_ci	else
12768c2ecf20Sopenharmony_ci		capuser="-Z $SUDO_USER"
12778c2ecf20Sopenharmony_ci	fi
12788c2ecf20Sopenharmony_ci
12798c2ecf20Sopenharmony_ci	$ns_cmd tcpdump -e -n -Q in -i $if_name \
12808c2ecf20Sopenharmony_ci		-s 65535 -B 32768 $capuser -w $capfile > "$capout" 2>&1 &
12818c2ecf20Sopenharmony_ci	cappid=$!
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_ci	sleep 1
12848c2ecf20Sopenharmony_ci}
12858c2ecf20Sopenharmony_ci
12868c2ecf20Sopenharmony_citcpdump_stop()
12878c2ecf20Sopenharmony_ci{
12888c2ecf20Sopenharmony_ci	$ns_cmd kill $cappid
12898c2ecf20Sopenharmony_ci	sleep 1
12908c2ecf20Sopenharmony_ci}
12918c2ecf20Sopenharmony_ci
12928c2ecf20Sopenharmony_citcpdump_cleanup()
12938c2ecf20Sopenharmony_ci{
12948c2ecf20Sopenharmony_ci	rm $capfile $capout
12958c2ecf20Sopenharmony_ci}
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_citcpdump_show()
12988c2ecf20Sopenharmony_ci{
12998c2ecf20Sopenharmony_ci	tcpdump -e -n -r $capfile 2>&1
13008c2ecf20Sopenharmony_ci}
1301