Skip to content

Commit

Permalink
selftests: Add FIB onlink tests
Browse files Browse the repository at this point in the history
Add test cases verifying FIB onlink commands work as expected in
various conditions - IPv4, IPv6, main table, and VRF.

Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David Ahern authored and David S. Miller committed Feb 13, 2018
1 parent b95367e commit 153e1b8
Showing 1 changed file with 375 additions and 0 deletions.
375 changes: 375 additions & 0 deletions tools/testing/selftests/net/fib-onlink-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,375 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0

# IPv4 and IPv6 onlink tests

PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}

# Network interfaces
# - odd in current namespace; even in peer ns
declare -A NETIFS
# default VRF
NETIFS[p1]=veth1
NETIFS[p2]=veth2
NETIFS[p3]=veth3
NETIFS[p4]=veth4
# VRF
NETIFS[p5]=veth5
NETIFS[p6]=veth6
NETIFS[p7]=veth7
NETIFS[p8]=veth8

# /24 network
declare -A V4ADDRS
V4ADDRS[p1]=169.254.1.1
V4ADDRS[p2]=169.254.1.2
V4ADDRS[p3]=169.254.3.1
V4ADDRS[p4]=169.254.3.2
V4ADDRS[p5]=169.254.5.1
V4ADDRS[p6]=169.254.5.2
V4ADDRS[p7]=169.254.7.1
V4ADDRS[p8]=169.254.7.2

# /64 network
declare -A V6ADDRS
V6ADDRS[p1]=2001:db8:101::1
V6ADDRS[p2]=2001:db8:101::2
V6ADDRS[p3]=2001:db8:301::1
V6ADDRS[p4]=2001:db8:301::2
V6ADDRS[p5]=2001:db8:501::1
V6ADDRS[p6]=2001:db8:501::2
V6ADDRS[p7]=2001:db8:701::1
V6ADDRS[p8]=2001:db8:701::2

# Test networks:
# [1] = default table
# [2] = VRF
#
# /32 host routes
declare -A TEST_NET4
TEST_NET4[1]=169.254.101
TEST_NET4[2]=169.254.102
# /128 host routes
declare -A TEST_NET6
TEST_NET6[1]=2001:db8:101
TEST_NET6[2]=2001:db8:102

# connected gateway
CONGW[1]=169.254.1.254
CONGW[2]=169.254.5.254

# recursive gateway
RECGW4[1]=169.254.11.254
RECGW4[2]=169.254.12.254
RECGW6[1]=2001:db8:11::64
RECGW6[2]=2001:db8:12::64

# for v4 mapped to v6
declare -A TEST_NET4IN6IN6
TEST_NET4IN6[1]=10.1.1.254
TEST_NET4IN6[2]=10.2.1.254

# mcast address
MCAST6=ff02::1


PEER_NS=bart
PEER_CMD="ip netns exec ${PEER_NS}"
VRF=lisa
VRF_TABLE=1101
PBR_TABLE=101

################################################################################
# utilities

log_test()
{
local rc=$1
local expected=$2
local msg="$3"

if [ ${rc} -eq ${expected} ]; then
nsuccess=$((nsuccess+1))
printf "\n TEST: %-50s [ OK ]\n" "${msg}"
else
nfail=$((nfail+1))
printf "\n TEST: %-50s [FAIL]\n" "${msg}"
if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
echo
echo "hit enter to continue, 'q' to quit"
read a
[ "$a" = "q" ] && exit 1
fi
fi
}

log_section()
{
echo
echo "######################################################################"
echo "TEST SECTION: $*"
echo "######################################################################"
}

log_subsection()
{
echo
echo "#########################################"
echo "TEST SUBSECTION: $*"
}

run_cmd()
{
echo
echo "COMMAND: $*"
eval $*
}

get_linklocal()
{
local dev=$1
local pfx
local addr

addr=$(${pfx} ip -6 -br addr show dev ${dev} | \
awk '{
for (i = 3; i <= NF; ++i) {
if ($i ~ /^fe80/)
print $i
}
}'
)
addr=${addr/\/*}

[ -z "$addr" ] && return 1

echo $addr

return 0
}

################################################################################
#

setup()
{
echo
echo "########################################"
echo "Configuring interfaces"

set -e

# create namespace
ip netns add ${PEER_NS}
ip -netns ${PEER_NS} li set lo up

# add vrf table
ip li add ${VRF} type vrf table ${VRF_TABLE}
ip li set ${VRF} up
ip ro add table ${VRF_TABLE} unreachable default
ip -6 ro add table ${VRF_TABLE} unreachable default

# create test interfaces
ip li add ${NETIFS[p1]} type veth peer name ${NETIFS[p2]}
ip li add ${NETIFS[p3]} type veth peer name ${NETIFS[p4]}
ip li add ${NETIFS[p5]} type veth peer name ${NETIFS[p6]}
ip li add ${NETIFS[p7]} type veth peer name ${NETIFS[p8]}

# enslave vrf interfaces
for n in 5 7; do
ip li set ${NETIFS[p${n}]} vrf ${VRF}
done

# add addresses
for n in 1 3 5 7; do
ip li set ${NETIFS[p${n}]} up
ip addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
ip addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]}
done

# move peer interfaces to namespace and add addresses
for n in 2 4 6 8; do
ip li set ${NETIFS[p${n}]} netns ${PEER_NS} up
ip -netns ${PEER_NS} addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
ip -netns ${PEER_NS} addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]}
done

set +e

# let DAD complete - assume default of 1 probe
sleep 1
}

cleanup()
{
# make sure we start from a clean slate
ip netns del ${PEER_NS} 2>/dev/null
for n in 1 3 5 7; do
ip link del ${NETIFS[p${n}]} 2>/dev/null
done
ip link del ${VRF} 2>/dev/null
ip ro flush table ${VRF_TABLE}
ip -6 ro flush table ${VRF_TABLE}
}

################################################################################
# IPv4 tests
#

run_ip()
{
local table="$1"
local prefix="$2"
local gw="$3"
local dev="$4"
local exp_rc="$5"
local desc="$6"

# dev arg may be empty
[ -n "${dev}" ] && dev="dev ${dev}"

run_cmd ip ro add table "${table}" "${prefix}"/32 via "${gw}" "${dev}" onlink
log_test $? ${exp_rc} "${desc}"
}

valid_onlink_ipv4()
{
# - unicast connected, unicast recursive
#
log_subsection "default VRF - main table"

run_ip 254 ${TEST_NET4[1]}.1 ${CONGW[1]} ${NETIFS[p1]} 0 "unicast connected"
run_ip 254 ${TEST_NET4[1]}.2 ${RECGW4[1]} ${NETIFS[p1]} 0 "unicast recursive"

log_subsection "VRF ${VRF}"

run_ip ${VRF_TABLE} ${TEST_NET4[2]}.1 ${CONGW[2]} ${NETIFS[p5]} 0 "unicast connected"
run_ip ${VRF_TABLE} ${TEST_NET4[2]}.2 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive"

log_subsection "VRF device, PBR table"

run_ip ${PBR_TABLE} ${TEST_NET4[2]}.3 ${CONGW[2]} ${NETIFS[p5]} 0 "unicast connected"
run_ip ${PBR_TABLE} ${TEST_NET4[2]}.4 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive"
}

invalid_onlink_ipv4()
{
run_ip 254 ${TEST_NET4[1]}.11 ${V4ADDRS[p1]} ${NETIFS[p1]} 2 \
"Invalid gw - local unicast address"

run_ip ${VRF_TABLE} ${TEST_NET4[2]}.11 ${V4ADDRS[p5]} ${NETIFS[p5]} 2 \
"Invalid gw - local unicast address, VRF"

run_ip 254 ${TEST_NET4[1]}.101 ${V4ADDRS[p1]} "" 2 "No nexthop device given"

run_ip 254 ${TEST_NET4[1]}.102 ${V4ADDRS[p3]} ${NETIFS[p1]} 2 \
"Gateway resolves to wrong nexthop device"

run_ip ${VRF_TABLE} ${TEST_NET4[2]}.103 ${V4ADDRS[p7]} ${NETIFS[p5]} 2 \
"Gateway resolves to wrong nexthop device - VRF"
}

################################################################################
# IPv6 tests
#

run_ip6()
{
local table="$1"
local prefix="$2"
local gw="$3"
local dev="$4"
local exp_rc="$5"
local desc="$6"

# dev arg may be empty
[ -n "${dev}" ] && dev="dev ${dev}"

run_cmd ip -6 ro add table "${table}" "${prefix}"/128 via "${gw}" "${dev}" onlink
log_test $? ${exp_rc} "${desc}"
}

valid_onlink_ipv6()
{
# - unicast connected, unicast recursive, v4-mapped
#
log_subsection "default VRF - main table"

run_ip6 254 ${TEST_NET6[1]}::1 ${V6ADDRS[p1]/::*}::64 ${NETIFS[p1]} 0 "unicast connected"
run_ip6 254 ${TEST_NET6[1]}::2 ${RECGW6[1]} ${NETIFS[p1]} 0 "unicast recursive"
run_ip6 254 ${TEST_NET6[1]}::3 ::ffff:${TEST_NET4IN6[1]} ${NETIFS[p1]} 0 "v4-mapped"

log_subsection "VRF ${VRF}"

run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::1 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected"
run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::2 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive"
run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::3 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped"

log_subsection "VRF device, PBR table"

run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::4 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected"
run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::5 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive"
run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::6 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped"
}

invalid_onlink_ipv6()
{
local lladdr

lladdr=$(get_linklocal ${NETIFS[p1]}) || return 1

run_ip6 254 ${TEST_NET6[1]}::11 ${V6ADDRS[p1]} ${NETIFS[p1]} 2 \
"Invalid gw - local unicast address"
run_ip6 254 ${TEST_NET6[1]}::12 ${lladdr} ${NETIFS[p1]} 2 \
"Invalid gw - local linklocal address"
run_ip6 254 ${TEST_NET6[1]}::12 ${MCAST6} ${NETIFS[p1]} 2 \
"Invalid gw - multicast address"

lladdr=$(get_linklocal ${NETIFS[p5]}) || return 1
run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::11 ${V6ADDRS[p5]} ${NETIFS[p5]} 2 \
"Invalid gw - local unicast address, VRF"
run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${lladdr} ${NETIFS[p5]} 2 \
"Invalid gw - local linklocal address, VRF"
run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${MCAST6} ${NETIFS[p5]} 2 \
"Invalid gw - multicast address, VRF"

run_ip6 254 ${TEST_NET6[1]}::101 ${V6ADDRS[p1]} "" 2 \
"No nexthop device given"

# default VRF validation is done against LOCAL table
# run_ip6 254 ${TEST_NET6[1]}::102 ${V6ADDRS[p3]/::[0-9]/::64} ${NETIFS[p1]} 2 \
# "Gateway resolves to wrong nexthop device"

run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::103 ${V6ADDRS[p7]/::[0-9]/::64} ${NETIFS[p5]} 2 \
"Gateway resolves to wrong nexthop device - VRF"
}

run_onlink_tests()
{
log_section "IPv4 onlink"
log_subsection "Valid onlink commands"
valid_onlink_ipv4
log_subsection "Invalid onlink commands"
invalid_onlink_ipv4

log_section "IPv6 onlink"
log_subsection "Valid onlink commands"
valid_onlink_ipv6
invalid_onlink_ipv6
}

################################################################################
# main

nsuccess=0
nfail=0

cleanup
setup
run_onlink_tests
cleanup

if [ "$TESTS" != "none" ]; then
printf "\nTests passed: %3d\n" ${nsuccess}
printf "Tests failed: %3d\n" ${nfail}
fi

0 comments on commit 153e1b8

Please sign in to comment.