summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/net/forwarding/lib.sh
diff options
context:
space:
mode:
Diffstat (limited to 'tools/testing/selftests/net/forwarding/lib.sh')
-rw-r--r--tools/testing/selftests/net/forwarding/lib.sh296
1 files changed, 250 insertions, 46 deletions
diff --git a/tools/testing/selftests/net/forwarding/lib.sh b/tools/testing/selftests/net/forwarding/lib.sh
index 508f3c700d71..ac8358bcb22c 100644
--- a/tools/testing/selftests/net/forwarding/lib.sh
+++ b/tools/testing/selftests/net/forwarding/lib.sh
@@ -1,5 +1,6 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
+#shellcheck disable=SC2034 # SC doesn't see our uses of global variables
##############################################################################
# Topology description. p1 looped back to p2, p3 to p4 and so on.
@@ -37,6 +38,7 @@ declare -A NETIFS=(
: "${TEAMD:=teamd}"
: "${MCD:=smcrouted}"
: "${MC_CLI:=smcroutectl}"
+: "${MCD_TABLE_NAME:=selftests}"
# Constants for netdevice bring-up:
# Default time in seconds to wait for an interface to come up before giving up
@@ -141,6 +143,20 @@ check_tc_version()
fi
}
+check_tc_erspan_support()
+{
+ local dev=$1; shift
+
+ tc filter add dev $dev ingress pref 1 handle 1 flower \
+ erspan_opts 1:0:0:0 &> /dev/null
+ if [[ $? -ne 0 ]]; then
+ echo "SKIP: iproute2 too old; tc is missing erspan support"
+ return $ksft_skip
+ fi
+ tc filter del dev $dev ingress pref 1 handle 1 flower \
+ erspan_opts 1:0:0:0 &> /dev/null
+}
+
# Old versions of tc don't understand "mpls_uc"
check_tc_mpls_support()
{
@@ -325,17 +341,145 @@ fi
##############################################################################
# Command line options handling
-count=0
+check_env() {
+ if [[ ! (( -n "$LOCAL_V4" && -n "$REMOTE_V4") ||
+ ( -n "$LOCAL_V6" && -n "$REMOTE_V6" )) ]]; then
+ echo "SKIP: Invalid environment, missing or inconsistent LOCAL_V4/REMOTE_V4/LOCAL_V6/REMOTE_V6"
+ echo "Please see tools/testing/selftests/drivers/net/README.rst"
+ exit "$ksft_skip"
+ fi
+
+ if [[ -z "$REMOTE_TYPE" ]]; then
+ echo "SKIP: Invalid environment, missing REMOTE_TYPE"
+ exit "$ksft_skip"
+ fi
+
+ if [[ -z "$REMOTE_ARGS" ]]; then
+ echo "SKIP: Invalid environment, missing REMOTE_ARGS"
+ exit "$ksft_skip"
+ fi
+}
+
+__run_on()
+{
+ local target=$1; shift
+ local type args
+
+ IFS=':' read -r type args <<< "$target"
+
+ case "$type" in
+ netns)
+ # Execute command in network namespace
+ # args contains the namespace name
+ ip netns exec "$args" "$@"
+ ;;
+ ssh)
+ # Execute command via SSH args contains user@host
+ ssh -n "$args" "$@"
+ ;;
+ local|*)
+ # Execute command locally. This is also the fallback
+ # case for when the interface's target is not found in
+ # the TARGETS array.
+ "$@"
+ ;;
+ esac
+}
-while [[ $# -gt 0 ]]; do
- if [[ "$count" -eq "0" ]]; then
+run_on()
+{
+ local iface=$1; shift
+ local target="local:"
+
+ if [ "${DRIVER_TEST_CONFORMANT}" = "yes" ]; then
+ target="${TARGETS[$iface]}"
+ fi
+
+ __run_on "$target" "$@"
+}
+
+get_ifname_by_ip()
+{
+ local target=$1; shift
+ local ip_addr=$1; shift
+
+ __run_on "$target" ip -j addr show to "$ip_addr" | jq -r '.[].ifname'
+}
+
+# Whether the test is conforming to the requirements and usage described in
+# drivers/net/README.rst.
+: "${DRIVER_TEST_CONFORMANT:=no}"
+
+declare -A TARGETS
+
+# Based on DRIVER_TEST_CONFORMANT, decide if to source drivers/net/net.config
+# or not. In the "yes" case, the test expects to pass the arguments through the
+# variables specified in drivers/net/README.rst file. If not, fallback on
+# parsing the script arguments for interface names.
+if [ "${DRIVER_TEST_CONFORMANT}" = "yes" ]; then
+ if [[ -f $net_forwarding_dir/../../drivers/net/net.config ]]; then
+ source "$net_forwarding_dir/../../drivers/net/net.config"
+ fi
+
+ if (( NUM_NETIFS > 2)); then
+ echo "SKIP: DRIVER_TEST_CONFORMANT=yes and NUM_NETIFS is bigger than 2"
+ exit "$ksft_skip"
+ fi
+
+ check_env
+
+ # Populate the NETIFS and TARGETS arrays automatically based on the
+ # environment variables. The TARGETS array is indexed by the network
+ # interface name keeping track of the target on which the interface
+ # resides. Values will be strings of the following format -
+ # <type>:<args>.
+ #
+ # TARGETS[eth0]="local:" - meaning that the eth0 interface is
+ # accessible locally
+ # TARGETS[eth1]="netns:foo" - eth1 is in the foo netns
+ # TARGETS[eth2]="ssh:root@10.0.0.2" - eth2 is accessible through
+ # running the 'ssh root@10.0.0.2' command.
+
+ unset NETIFS
+ declare -A NETIFS
+
+ NETIFS[p1]="$NETIF"
+ TARGETS[$NETIF]="local:"
+
+ # Locate the name of the remote interface
+ remote_target="$REMOTE_TYPE:$REMOTE_ARGS"
+ if [[ -v REMOTE_V4 ]]; then
+ remote_netif=$(get_ifname_by_ip "$remote_target" "$REMOTE_V4")
+ else
+ remote_netif=$(get_ifname_by_ip "$remote_target" "$REMOTE_V6")
+ fi
+ if [[ ! -n "$remote_netif" ]]; then
+ echo "SKIP: cannot find remote interface"
+ exit "$ksft_skip"
+ fi
+
+ if [[ "$NETIF" == "$remote_netif" ]]; then
+ echo "SKIP: local and remote interfaces cannot have the same name"
+ exit "$ksft_skip"
+ fi
+
+ NETIFS[p2]="$remote_netif"
+ TARGETS[$remote_netif]="$REMOTE_TYPE:$REMOTE_ARGS"
+else
+ count=0
+ # Prime NETIFS from the command line, but retain if none given.
+ if [[ $# -gt 0 ]]; then
unset NETIFS
declare -A NETIFS
+
+ while [[ $# -gt 0 ]]; do
+ count=$((count + 1))
+ NETIFS[p$count]="$1"
+ TARGETS[$1]="local:"
+ shift
+ done
fi
- count=$((count + 1))
- NETIFS[p$count]="$1"
- shift
-done
+fi
##############################################################################
# Network interfaces configuration
@@ -403,10 +547,11 @@ mac_addr_prepare()
dev=${NETIFS[p$i]}
new_addr=$(printf "00:01:02:03:04:%02x" $i)
- MAC_ADDR_ORIG["$dev"]=$(ip -j link show dev $dev | jq -e '.[].address')
+ MAC_ADDR_ORIG["$dev"]=$(run_on "$dev" \
+ ip -j link show dev "$dev" | jq -e '.[].address')
# Strip quotes
MAC_ADDR_ORIG["$dev"]=${MAC_ADDR_ORIG["$dev"]//\"/}
- ip link set dev $dev address $new_addr
+ run_on "$dev" ip link set dev "$dev" address $new_addr
done
}
@@ -416,7 +561,8 @@ mac_addr_restore()
for ((i = 1; i <= NUM_NETIFS; ++i)); do
dev=${NETIFS[p$i]}
- ip link set dev $dev address ${MAC_ADDR_ORIG["$dev"]}
+ run_on "$dev" \
+ ip link set dev "$dev" address ${MAC_ADDR_ORIG["$dev"]}
done
}
@@ -429,7 +575,9 @@ if [[ "$STABLE_MAC_ADDRS" = "yes" ]]; then
fi
for ((i = 1; i <= NUM_NETIFS; ++i)); do
- ip link show dev ${NETIFS[p$i]} &> /dev/null
+ int="${NETIFS[p$i]}"
+
+ run_on "$int" ip link show dev "$int" &> /dev/null
if [[ $? -ne 0 ]]; then
echo "SKIP: could not find all required interfaces"
exit $ksft_skip
@@ -512,7 +660,7 @@ setup_wait_dev_with_timeout()
local i
for ((i = 1; i <= $max_iterations; ++i)); do
- ip link show dev $dev up \
+ run_on "$dev" ip link show dev "$dev" up \
| grep 'state UP' &> /dev/null
if [[ $? -ne 0 ]]; then
sleep 1
@@ -525,9 +673,9 @@ setup_wait_dev_with_timeout()
return 1
}
-setup_wait()
+setup_wait_n()
{
- local num_netifs=${1:-$NUM_NETIFS}
+ local num_netifs=$1; shift
local i
for ((i = 1; i <= num_netifs; ++i)); do
@@ -538,6 +686,11 @@ setup_wait()
sleep $WAIT_TIME
}
+setup_wait()
+{
+ setup_wait_n "$NUM_NETIFS"
+}
+
wait_for_dev()
{
local dev=$1; shift
@@ -551,30 +704,6 @@ wait_for_dev()
fi
}
-cmd_jq()
-{
- local cmd=$1
- local jq_exp=$2
- local jq_opts=$3
- local ret
- local output
-
- output="$($cmd)"
- # it the command fails, return error right away
- ret=$?
- if [[ $ret -ne 0 ]]; then
- return $ret
- fi
- output=$(echo $output | jq -r $jq_opts "$jq_exp")
- ret=$?
- if [[ $ret -ne 0 ]]; then
- return $ret
- fi
- echo $output
- # return success only in case of non-empty output
- [ ! -z "$output" ]
-}
-
pre_cleanup()
{
if [ "${PAUSE_ON_CLEANUP}" = "yes" ]; then
@@ -603,6 +732,12 @@ vrf_cleanup()
ip -4 rule del pref 32765
}
+adf_vrf_prepare()
+{
+ vrf_prepare
+ defer vrf_cleanup
+}
+
__last_tb_id=0
declare -A __TB_IDS
@@ -715,6 +850,12 @@ simple_if_fini()
vrf_destroy $vrf_name
}
+adf_simple_if_init()
+{
+ simple_if_init "$@"
+ defer simple_if_fini "$@"
+}
+
tunnel_create()
{
local name=$1; shift
@@ -823,8 +964,15 @@ ethtool_std_stats_get()
local name=$1; shift
local src=$1; shift
- ethtool --json -S $dev --groups $grp -- --src $src | \
- jq '.[]."'"$grp"'"."'$name'"'
+ if [[ "$grp" == "pause" ]]; then
+ run_on "$dev" ethtool -I --json -a "$dev" --src "$src" | \
+ jq --arg name "$name" '.[].statistics[$name]'
+ return
+ fi
+
+ run_on "$dev" \
+ ethtool --json -S "$dev" --groups "$grp" -- --src "$src" | \
+ jq --arg grp "$grp" --arg name "$name" '.[][$grp][$name]'
}
qdisc_stats_get()
@@ -1015,6 +1163,12 @@ forwarding_restore()
sysctl_restore net.ipv4.conf.all.forwarding
}
+adf_forwarding_enable()
+{
+ forwarding_enable
+ defer forwarding_restore
+}
+
declare -A MTU_ORIG
mtu_set()
{
@@ -1271,8 +1425,8 @@ ping_do()
vrf_name=$(master_name_get $if_name)
ip vrf exec $vrf_name \
- $PING $args $dip -c $PING_COUNT -i 0.1 \
- -w $PING_TIMEOUT &> /dev/null
+ $PING $args -c $PING_COUNT -i 0.1 \
+ -w $PING_TIMEOUT $dip &> /dev/null
}
ping_test()
@@ -1302,8 +1456,8 @@ ping6_do()
vrf_name=$(master_name_get $if_name)
ip vrf exec $vrf_name \
- $PING6 $args $dip -c $PING_COUNT -i 0.1 \
- -w $PING_TIMEOUT &> /dev/null
+ $PING6 $args -c $PING_COUNT -i 0.1 \
+ -w $PING_TIMEOUT $dip &> /dev/null
}
ping6_test()
@@ -1596,12 +1750,17 @@ tcpdump_start()
sleep 1
}
-tcpdump_stop()
+tcpdump_stop_nosleep()
{
local if_name=$1
local pid=${cappid[$if_name]}
$ns_cmd kill "$pid" && wait "$pid"
+}
+
+tcpdump_stop()
+{
+ tcpdump_stop_nosleep "$1"
sleep 1
}
@@ -1616,7 +1775,7 @@ tcpdump_show()
{
local if_name=$1
- tcpdump -e -n -r ${capfile[$if_name]} 2>&1
+ tcpdump -e -nn -r ${capfile[$if_name]} 2>&1
}
# return 0 if the packet wasn't seen on host2_if or 1 if it was
@@ -1757,6 +1916,51 @@ mc_send()
msend -g $groups -I $if_name -c 1 > /dev/null 2>&1
}
+adf_mcd_start()
+{
+ local ifs=("$@")
+
+ local table_name="$MCD_TABLE_NAME"
+ local smcroutedir
+ local pid
+ local if
+ local i
+
+ check_command "$MCD" || return 1
+ check_command "$MC_CLI" || return 1
+
+ smcroutedir=$(mktemp -d)
+ defer rm -rf "$smcroutedir"
+
+ for ((i = 1; i <= NUM_NETIFS; ++i)); do
+ echo "phyint ${NETIFS[p$i]} enable" >> \
+ "$smcroutedir/$table_name.conf"
+ done
+
+ for if in "${ifs[@]}"; do
+ if ! ip_link_has_flag "$if" MULTICAST; then
+ ip link set dev "$if" multicast on
+ defer ip link set dev "$if" multicast off
+ fi
+
+ echo "phyint $if enable" >> \
+ "$smcroutedir/$table_name.conf"
+ done
+
+ "$MCD" -N -I "$table_name" -f "$smcroutedir/$table_name.conf" \
+ -P "$smcroutedir/$table_name.pid"
+ busywait "$BUSYWAIT_TIMEOUT" test -e "$smcroutedir/$table_name.pid"
+ pid=$(cat "$smcroutedir/$table_name.pid")
+ defer kill_process "$pid"
+}
+
+mc_cli()
+{
+ local table_name="$MCD_TABLE_NAME"
+
+ "$MC_CLI" -I "$table_name" "$@"
+}
+
start_ip_monitor()
{
local mtype=$1; shift