Add initial framework to test packet forwarding functionality. The tests can run on actual devices using loop-backed cables or using veth pairs. Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
282 lines
4.8 KiB
Bash
282 lines
4.8 KiB
Bash
#!/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"
|
|
}
|