|
@@ -0,0 +1,282 @@
|
|
|
+#!/bin/bash
|
|
|
+# SPDX-License-Identifier: GPL-2.0
|
|
|
+
|
|
|
+##############################################################################
|
|
|
+# Defines
|
|
|
+
|
|
|
+# Can be overridden by the configuration file.
|
|
|
+PING=${PING:=ping}
|
|
|
+PING6=${PING6:=ping6}
|
|
|
+WAIT_TIME=${WAIT_TIME:=5}
|
|
|
+PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
|
|
|
+PAUSE_ON_CLEANUP=${PAUSE_ON_CLEANUP:=no}
|
|
|
+
|
|
|
+if [[ -f forwarding.config ]]; then
|
|
|
+ source forwarding.config
|
|
|
+fi
|
|
|
+
|
|
|
+##############################################################################
|
|
|
+# Sanity checks
|
|
|
+
|
|
|
+if [[ "$(id -u)" -ne 0 ]]; then
|
|
|
+ echo "SKIP: need root privileges"
|
|
|
+ exit 0
|
|
|
+fi
|
|
|
+
|
|
|
+tc -j &> /dev/null
|
|
|
+if [[ $? -ne 0 ]]; then
|
|
|
+ echo "SKIP: iproute2 too old, missing JSON support"
|
|
|
+ exit 0
|
|
|
+fi
|
|
|
+
|
|
|
+if [[ ! -x "$(command -v jq)" ]]; then
|
|
|
+ echo "SKIP: jq not installed"
|
|
|
+ exit 0
|
|
|
+fi
|
|
|
+
|
|
|
+if [[ ! -v NUM_NETIFS ]]; then
|
|
|
+ echo "SKIP: importer does not define \"NUM_NETIFS\""
|
|
|
+ exit 0
|
|
|
+fi
|
|
|
+
|
|
|
+##############################################################################
|
|
|
+# Network interfaces configuration
|
|
|
+
|
|
|
+for i in $(eval echo {1..$NUM_NETIFS}); do
|
|
|
+ ip link show dev ${NETIFS[p$i]} &> /dev/null
|
|
|
+ if [[ $? -ne 0 ]]; then
|
|
|
+ echo "SKIP: could not find all required interfaces"
|
|
|
+ exit 0
|
|
|
+ fi
|
|
|
+done
|
|
|
+
|
|
|
+##############################################################################
|
|
|
+# Helpers
|
|
|
+
|
|
|
+# Exit status to return at the end. Set in case one of the tests fails.
|
|
|
+EXIT_STATUS=0
|
|
|
+# Per-test return value. Clear at the beginning of each test.
|
|
|
+RET=0
|
|
|
+
|
|
|
+check_err()
|
|
|
+{
|
|
|
+ local err=$1
|
|
|
+ local msg=$2
|
|
|
+
|
|
|
+ if [[ $RET -eq 0 && $err -ne 0 ]]; then
|
|
|
+ RET=$err
|
|
|
+ retmsg=$msg
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+check_fail()
|
|
|
+{
|
|
|
+ local err=$1
|
|
|
+ local msg=$2
|
|
|
+
|
|
|
+ if [[ $RET -eq 0 && $err -eq 0 ]]; then
|
|
|
+ RET=1
|
|
|
+ retmsg=$msg
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+log_test()
|
|
|
+{
|
|
|
+ local test_name=$1
|
|
|
+ local opt_str=$2
|
|
|
+
|
|
|
+ if [[ $# -eq 2 ]]; then
|
|
|
+ opt_str="($opt_str)"
|
|
|
+ fi
|
|
|
+
|
|
|
+ if [[ $RET -ne 0 ]]; then
|
|
|
+ EXIT_STATUS=1
|
|
|
+ printf "TEST: %-60s [FAIL]\n" "$test_name $opt_str"
|
|
|
+ if [[ ! -z "$retmsg" ]]; then
|
|
|
+ printf "\t%s\n" "$retmsg"
|
|
|
+ fi
|
|
|
+ if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
|
|
|
+ echo "Hit enter to continue, 'q' to quit"
|
|
|
+ read a
|
|
|
+ [ "$a" = "q" ] && exit 1
|
|
|
+ fi
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+
|
|
|
+ printf "TEST: %-60s [PASS]\n" "$test_name $opt_str"
|
|
|
+ return 0
|
|
|
+}
|
|
|
+
|
|
|
+setup_wait()
|
|
|
+{
|
|
|
+ for i in $(eval echo {1..$NUM_NETIFS}); do
|
|
|
+ while true; do
|
|
|
+ ip link show dev ${NETIFS[p$i]} up \
|
|
|
+ | grep 'state UP' &> /dev/null
|
|
|
+ if [[ $? -ne 0 ]]; then
|
|
|
+ sleep 1
|
|
|
+ else
|
|
|
+ break
|
|
|
+ fi
|
|
|
+ done
|
|
|
+ done
|
|
|
+
|
|
|
+ # Make sure links are ready.
|
|
|
+ sleep $WAIT_TIME
|
|
|
+}
|
|
|
+
|
|
|
+pre_cleanup()
|
|
|
+{
|
|
|
+ if [ "${PAUSE_ON_CLEANUP}" = "yes" ]; then
|
|
|
+ echo "Pausing before cleanup, hit any key to continue"
|
|
|
+ read
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+vrf_prepare()
|
|
|
+{
|
|
|
+ ip -4 rule add pref 32765 table local
|
|
|
+ ip -4 rule del pref 0
|
|
|
+ ip -6 rule add pref 32765 table local
|
|
|
+ ip -6 rule del pref 0
|
|
|
+}
|
|
|
+
|
|
|
+vrf_cleanup()
|
|
|
+{
|
|
|
+ ip -6 rule add pref 0 table local
|
|
|
+ ip -6 rule del pref 32765
|
|
|
+ ip -4 rule add pref 0 table local
|
|
|
+ ip -4 rule del pref 32765
|
|
|
+}
|
|
|
+
|
|
|
+__last_tb_id=0
|
|
|
+declare -A __TB_IDS
|
|
|
+
|
|
|
+__vrf_td_id_assign()
|
|
|
+{
|
|
|
+ local vrf_name=$1
|
|
|
+
|
|
|
+ __last_tb_id=$((__last_tb_id + 1))
|
|
|
+ __TB_IDS[$vrf_name]=$__last_tb_id
|
|
|
+ return $__last_tb_id
|
|
|
+}
|
|
|
+
|
|
|
+__vrf_td_id_lookup()
|
|
|
+{
|
|
|
+ local vrf_name=$1
|
|
|
+
|
|
|
+ return ${__TB_IDS[$vrf_name]}
|
|
|
+}
|
|
|
+
|
|
|
+vrf_create()
|
|
|
+{
|
|
|
+ local vrf_name=$1
|
|
|
+ local tb_id
|
|
|
+
|
|
|
+ __vrf_td_id_assign $vrf_name
|
|
|
+ tb_id=$?
|
|
|
+
|
|
|
+ ip link add dev $vrf_name type vrf table $tb_id
|
|
|
+ ip -4 route add table $tb_id unreachable default metric 4278198272
|
|
|
+ ip -6 route add table $tb_id unreachable default metric 4278198272
|
|
|
+}
|
|
|
+
|
|
|
+vrf_destroy()
|
|
|
+{
|
|
|
+ local vrf_name=$1
|
|
|
+ local tb_id
|
|
|
+
|
|
|
+ __vrf_td_id_lookup $vrf_name
|
|
|
+ tb_id=$?
|
|
|
+
|
|
|
+ ip -6 route del table $tb_id unreachable default metric 4278198272
|
|
|
+ ip -4 route del table $tb_id unreachable default metric 4278198272
|
|
|
+ ip link del dev $vrf_name
|
|
|
+}
|
|
|
+
|
|
|
+__addr_add_del()
|
|
|
+{
|
|
|
+ local if_name=$1
|
|
|
+ local add_del=$2
|
|
|
+ local array
|
|
|
+
|
|
|
+ shift
|
|
|
+ shift
|
|
|
+ array=("${@}")
|
|
|
+
|
|
|
+ for addrstr in "${array[@]}"; do
|
|
|
+ ip address $add_del $addrstr dev $if_name
|
|
|
+ done
|
|
|
+}
|
|
|
+
|
|
|
+simple_if_init()
|
|
|
+{
|
|
|
+ local if_name=$1
|
|
|
+ local vrf_name
|
|
|
+ local array
|
|
|
+
|
|
|
+ shift
|
|
|
+ vrf_name=v$if_name
|
|
|
+ array=("${@}")
|
|
|
+
|
|
|
+ vrf_create $vrf_name
|
|
|
+ ip link set dev $if_name master $vrf_name
|
|
|
+ ip link set dev $vrf_name up
|
|
|
+ ip link set dev $if_name up
|
|
|
+
|
|
|
+ __addr_add_del $if_name add "${array[@]}"
|
|
|
+}
|
|
|
+
|
|
|
+simple_if_fini()
|
|
|
+{
|
|
|
+ local if_name=$1
|
|
|
+ local vrf_name
|
|
|
+ local array
|
|
|
+
|
|
|
+ shift
|
|
|
+ vrf_name=v$if_name
|
|
|
+ array=("${@}")
|
|
|
+
|
|
|
+ __addr_add_del $if_name del "${array[@]}"
|
|
|
+
|
|
|
+ ip link set dev $if_name down
|
|
|
+ vrf_destroy $vrf_name
|
|
|
+}
|
|
|
+
|
|
|
+master_name_get()
|
|
|
+{
|
|
|
+ local if_name=$1
|
|
|
+
|
|
|
+ ip -j link show dev $if_name | jq -r '.[]["master"]'
|
|
|
+}
|
|
|
+
|
|
|
+##############################################################################
|
|
|
+# Tests
|
|
|
+
|
|
|
+ping_test()
|
|
|
+{
|
|
|
+ local if_name=$1
|
|
|
+ local dip=$2
|
|
|
+ local vrf_name
|
|
|
+
|
|
|
+ RET=0
|
|
|
+
|
|
|
+ vrf_name=$(master_name_get $if_name)
|
|
|
+ ip vrf exec $vrf_name $PING $dip -c 10 -i 0.1 -w 2 &> /dev/null
|
|
|
+ check_err $?
|
|
|
+ log_test "ping"
|
|
|
+}
|
|
|
+
|
|
|
+ping6_test()
|
|
|
+{
|
|
|
+ local if_name=$1
|
|
|
+ local dip=$2
|
|
|
+ local vrf_name
|
|
|
+
|
|
|
+ RET=0
|
|
|
+
|
|
|
+ vrf_name=$(master_name_get $if_name)
|
|
|
+ ip vrf exec $vrf_name $PING6 $dip -c 10 -i 0.1 -w 2 &> /dev/null
|
|
|
+ check_err $?
|
|
|
+ log_test "ping6"
|
|
|
+}
|