503 lines · bash
1#!/bin/bash2# SPDX-License-Identifier: GPL-2.03 4# IPv4 and IPv6 onlink tests5 6source lib.sh7PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}8VERBOSE=09 10# Network interfaces11# - odd in current namespace; even in peer ns12declare -A NETIFS13# default VRF14NETIFS[p1]=veth115NETIFS[p2]=veth216NETIFS[p3]=veth317NETIFS[p4]=veth418# VRF19NETIFS[p5]=veth520NETIFS[p6]=veth621NETIFS[p7]=veth722NETIFS[p8]=veth823 24# /24 network25declare -A V4ADDRS26V4ADDRS[p1]=169.254.1.127V4ADDRS[p2]=169.254.1.228V4ADDRS[p3]=169.254.3.129V4ADDRS[p4]=169.254.3.230V4ADDRS[p5]=169.254.5.131V4ADDRS[p6]=169.254.5.232V4ADDRS[p7]=169.254.7.133V4ADDRS[p8]=169.254.7.234 35# /64 network36declare -A V6ADDRS37V6ADDRS[p1]=2001:db8:101::138V6ADDRS[p2]=2001:db8:101::239V6ADDRS[p3]=2001:db8:301::140V6ADDRS[p4]=2001:db8:301::241V6ADDRS[p5]=2001:db8:501::142V6ADDRS[p6]=2001:db8:501::243V6ADDRS[p7]=2001:db8:701::144V6ADDRS[p8]=2001:db8:701::245 46# Test networks:47# [1] = default table48# [2] = VRF49#50# /32 host routes51declare -A TEST_NET452TEST_NET4[1]=169.254.10153TEST_NET4[2]=169.254.10254# /128 host routes55declare -A TEST_NET656TEST_NET6[1]=2001:db8:10157TEST_NET6[2]=2001:db8:10258 59# connected gateway60CONGW[1]=169.254.1.25461CONGW[2]=169.254.3.25462CONGW[3]=169.254.5.25463 64# recursive gateway65RECGW4[1]=169.254.11.25466RECGW4[2]=169.254.12.25467RECGW6[1]=2001:db8:11::6468RECGW6[2]=2001:db8:12::6469 70# for v4 mapped to v671declare -A TEST_NET4IN6IN672TEST_NET4IN6[1]=10.1.1.25473TEST_NET4IN6[2]=10.2.1.25474 75# mcast address76MCAST6=ff02::177 78VRF=lisa79VRF_TABLE=110180PBR_TABLE=10181 82################################################################################83# utilities84 85log_test()86{87 local rc=$188 local expected=$289 local msg="$3"90 91 if [ ${rc} -eq ${expected} ]; then92 nsuccess=$((nsuccess+1))93 printf " TEST: %-50s [ OK ]\n" "${msg}"94 else95 nfail=$((nfail+1))96 printf " TEST: %-50s [FAIL]\n" "${msg}"97 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then98 echo99 echo "hit enter to continue, 'q' to quit"100 read a101 [ "$a" = "q" ] && exit 1102 fi103 fi104}105 106log_section()107{108 echo109 echo "######################################################################"110 echo "TEST SECTION: $*"111 echo "######################################################################"112}113 114log_subsection()115{116 echo117 echo "#########################################"118 echo "TEST SUBSECTION: $*"119}120 121run_cmd()122{123 local cmd="$*"124 local out125 local rc126 127 if [ "$VERBOSE" = "1" ]; then128 printf " COMMAND: $cmd\n"129 fi130 131 out=$(eval $cmd 2>&1)132 rc=$?133 if [ "$VERBOSE" = "1" -a -n "$out" ]; then134 echo " $out"135 fi136 137 [ "$VERBOSE" = "1" ] && echo138 139 return $rc140}141 142get_linklocal()143{144 local dev=$1145 local pfx146 local addr147 148 addr=$(${pfx} ip -6 -br addr show dev ${dev} | \149 awk '{150 for (i = 3; i <= NF; ++i) {151 if ($i ~ /^fe80/)152 print $i153 }154 }'155 )156 addr=${addr/\/*}157 158 [ -z "$addr" ] && return 1159 160 echo $addr161 162 return 0163}164 165################################################################################166#167 168setup()169{170 echo171 echo "########################################"172 echo "Configuring interfaces"173 174 set -e175 176 # create namespace177 setup_ns PEER_NS178 179 # add vrf table180 ip li add ${VRF} type vrf table ${VRF_TABLE}181 ip li set ${VRF} up182 ip ro add table ${VRF_TABLE} unreachable default metric 8192183 ip -6 ro add table ${VRF_TABLE} unreachable default metric 8192184 185 # create test interfaces186 ip li add ${NETIFS[p1]} type veth peer name ${NETIFS[p2]}187 ip li add ${NETIFS[p3]} type veth peer name ${NETIFS[p4]}188 ip li add ${NETIFS[p5]} type veth peer name ${NETIFS[p6]}189 ip li add ${NETIFS[p7]} type veth peer name ${NETIFS[p8]}190 191 # enslave vrf interfaces192 for n in 5 7; do193 ip li set ${NETIFS[p${n}]} vrf ${VRF}194 done195 196 # add addresses197 for n in 1 3 5 7; do198 ip li set ${NETIFS[p${n}]} up199 ip addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}200 ip addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} nodad201 done202 203 # move peer interfaces to namespace and add addresses204 for n in 2 4 6 8; do205 ip li set ${NETIFS[p${n}]} netns ${PEER_NS} up206 ip -netns ${PEER_NS} addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}207 ip -netns ${PEER_NS} addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} nodad208 done209 210 ip -6 ro add default via ${V6ADDRS[p3]/::[0-9]/::64}211 ip -6 ro add table ${VRF_TABLE} default via ${V6ADDRS[p7]/::[0-9]/::64}212 213 set +e214}215 216cleanup()217{218 # make sure we start from a clean slate219 cleanup_ns ${PEER_NS} 2>/dev/null220 for n in 1 3 5 7; do221 ip link del ${NETIFS[p${n}]} 2>/dev/null222 done223 ip link del ${VRF} 2>/dev/null224 ip ro flush table ${VRF_TABLE}225 ip -6 ro flush table ${VRF_TABLE}226}227 228################################################################################229# IPv4 tests230#231 232run_ip()233{234 local table="$1"235 local prefix="$2"236 local gw="$3"237 local dev="$4"238 local exp_rc="$5"239 local desc="$6"240 241 # dev arg may be empty242 [ -n "${dev}" ] && dev="dev ${dev}"243 244 run_cmd ip ro add table "${table}" "${prefix}"/32 via "${gw}" "${dev}" onlink245 log_test $? ${exp_rc} "${desc}"246}247 248run_ip_mpath()249{250 local table="$1"251 local prefix="$2"252 local nh1="$3"253 local nh2="$4"254 local exp_rc="$5"255 local desc="$6"256 257 # dev arg may be empty258 [ -n "${dev}" ] && dev="dev ${dev}"259 260 run_cmd ip ro add table "${table}" "${prefix}"/32 \261 nexthop via ${nh1} nexthop via ${nh2}262 log_test $? ${exp_rc} "${desc}"263}264 265valid_onlink_ipv4()266{267 # - unicast connected, unicast recursive268 #269 log_subsection "default VRF - main table"270 271 run_ip 254 ${TEST_NET4[1]}.1 ${CONGW[1]} ${NETIFS[p1]} 0 "unicast connected"272 run_ip 254 ${TEST_NET4[1]}.2 ${RECGW4[1]} ${NETIFS[p1]} 0 "unicast recursive"273 274 log_subsection "VRF ${VRF}"275 276 run_ip ${VRF_TABLE} ${TEST_NET4[2]}.1 ${CONGW[3]} ${NETIFS[p5]} 0 "unicast connected"277 run_ip ${VRF_TABLE} ${TEST_NET4[2]}.2 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive"278 279 log_subsection "VRF device, PBR table"280 281 run_ip ${PBR_TABLE} ${TEST_NET4[2]}.3 ${CONGW[3]} ${NETIFS[p5]} 0 "unicast connected"282 run_ip ${PBR_TABLE} ${TEST_NET4[2]}.4 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive"283 284 # multipath version285 #286 log_subsection "default VRF - main table - multipath"287 288 run_ip_mpath 254 ${TEST_NET4[1]}.5 \289 "${CONGW[1]} dev ${NETIFS[p1]} onlink" \290 "${CONGW[2]} dev ${NETIFS[p3]} onlink" \291 0 "unicast connected - multipath"292 293 run_ip_mpath 254 ${TEST_NET4[1]}.6 \294 "${RECGW4[1]} dev ${NETIFS[p1]} onlink" \295 "${RECGW4[2]} dev ${NETIFS[p3]} onlink" \296 0 "unicast recursive - multipath"297 298 run_ip_mpath 254 ${TEST_NET4[1]}.7 \299 "${CONGW[1]} dev ${NETIFS[p1]}" \300 "${CONGW[2]} dev ${NETIFS[p3]} onlink" \301 0 "unicast connected - multipath onlink first only"302 303 run_ip_mpath 254 ${TEST_NET4[1]}.8 \304 "${CONGW[1]} dev ${NETIFS[p1]} onlink" \305 "${CONGW[2]} dev ${NETIFS[p3]}" \306 0 "unicast connected - multipath onlink second only"307}308 309invalid_onlink_ipv4()310{311 run_ip 254 ${TEST_NET4[1]}.11 ${V4ADDRS[p1]} ${NETIFS[p1]} 2 \312 "Invalid gw - local unicast address"313 314 run_ip ${VRF_TABLE} ${TEST_NET4[2]}.11 ${V4ADDRS[p5]} ${NETIFS[p5]} 2 \315 "Invalid gw - local unicast address, VRF"316 317 run_ip 254 ${TEST_NET4[1]}.101 ${V4ADDRS[p1]} "" 2 "No nexthop device given"318 319 run_ip 254 ${TEST_NET4[1]}.102 ${V4ADDRS[p3]} ${NETIFS[p1]} 2 \320 "Gateway resolves to wrong nexthop device"321 322 run_ip ${VRF_TABLE} ${TEST_NET4[2]}.103 ${V4ADDRS[p7]} ${NETIFS[p5]} 2 \323 "Gateway resolves to wrong nexthop device - VRF"324}325 326################################################################################327# IPv6 tests328#329 330run_ip6()331{332 local table="$1"333 local prefix="$2"334 local gw="$3"335 local dev="$4"336 local exp_rc="$5"337 local desc="$6"338 339 # dev arg may be empty340 [ -n "${dev}" ] && dev="dev ${dev}"341 342 run_cmd ip -6 ro add table "${table}" "${prefix}"/128 via "${gw}" "${dev}" onlink343 log_test $? ${exp_rc} "${desc}"344}345 346run_ip6_mpath()347{348 local table="$1"349 local prefix="$2"350 local opts="$3"351 local nh1="$4"352 local nh2="$5"353 local exp_rc="$6"354 local desc="$7"355 356 run_cmd ip -6 ro add table "${table}" "${prefix}"/128 "${opts}" \357 nexthop via ${nh1} nexthop via ${nh2}358 log_test $? ${exp_rc} "${desc}"359}360 361valid_onlink_ipv6()362{363 # - unicast connected, unicast recursive, v4-mapped364 #365 log_subsection "default VRF - main table"366 367 run_ip6 254 ${TEST_NET6[1]}::1 ${V6ADDRS[p1]/::*}::64 ${NETIFS[p1]} 0 "unicast connected"368 run_ip6 254 ${TEST_NET6[1]}::2 ${RECGW6[1]} ${NETIFS[p1]} 0 "unicast recursive"369 run_ip6 254 ${TEST_NET6[1]}::3 ::ffff:${TEST_NET4IN6[1]} ${NETIFS[p1]} 0 "v4-mapped"370 371 log_subsection "VRF ${VRF}"372 373 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::1 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected"374 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::2 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive"375 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::3 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped"376 377 log_subsection "VRF device, PBR table"378 379 run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::4 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected"380 run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::5 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive"381 run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::6 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped"382 383 # multipath version384 #385 log_subsection "default VRF - main table - multipath"386 387 run_ip6_mpath 254 ${TEST_NET6[1]}::4 "onlink" \388 "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]}" \389 "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]}" \390 0 "unicast connected - multipath onlink"391 392 run_ip6_mpath 254 ${TEST_NET6[1]}::5 "onlink" \393 "${RECGW6[1]} dev ${NETIFS[p1]}" \394 "${RECGW6[2]} dev ${NETIFS[p3]}" \395 0 "unicast recursive - multipath onlink"396 397 run_ip6_mpath 254 ${TEST_NET6[1]}::6 "onlink" \398 "::ffff:${TEST_NET4IN6[1]} dev ${NETIFS[p1]}" \399 "::ffff:${TEST_NET4IN6[2]} dev ${NETIFS[p3]}" \400 0 "v4-mapped - multipath onlink"401 402 run_ip6_mpath 254 ${TEST_NET6[1]}::7 "" \403 "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]} onlink" \404 "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]} onlink" \405 0 "unicast connected - multipath onlink both nexthops"406 407 run_ip6_mpath 254 ${TEST_NET6[1]}::8 "" \408 "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]} onlink" \409 "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]}" \410 0 "unicast connected - multipath onlink first only"411 412 run_ip6_mpath 254 ${TEST_NET6[1]}::9 "" \413 "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]}" \414 "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]} onlink" \415 0 "unicast connected - multipath onlink second only"416}417 418invalid_onlink_ipv6()419{420 local lladdr421 422 lladdr=$(get_linklocal ${NETIFS[p1]}) || return 1423 424 run_ip6 254 ${TEST_NET6[1]}::11 ${V6ADDRS[p1]} ${NETIFS[p1]} 2 \425 "Invalid gw - local unicast address"426 run_ip6 254 ${TEST_NET6[1]}::12 ${lladdr} ${NETIFS[p1]} 2 \427 "Invalid gw - local linklocal address"428 run_ip6 254 ${TEST_NET6[1]}::12 ${MCAST6} ${NETIFS[p1]} 2 \429 "Invalid gw - multicast address"430 431 lladdr=$(get_linklocal ${NETIFS[p5]}) || return 1432 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::11 ${V6ADDRS[p5]} ${NETIFS[p5]} 2 \433 "Invalid gw - local unicast address, VRF"434 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${lladdr} ${NETIFS[p5]} 2 \435 "Invalid gw - local linklocal address, VRF"436 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${MCAST6} ${NETIFS[p5]} 2 \437 "Invalid gw - multicast address, VRF"438 439 run_ip6 254 ${TEST_NET6[1]}::101 ${V6ADDRS[p1]} "" 2 \440 "No nexthop device given"441 442 # default VRF validation is done against LOCAL table443 # run_ip6 254 ${TEST_NET6[1]}::102 ${V6ADDRS[p3]/::[0-9]/::64} ${NETIFS[p1]} 2 \444 # "Gateway resolves to wrong nexthop device"445 446 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::103 ${V6ADDRS[p7]/::[0-9]/::64} ${NETIFS[p5]} 2 \447 "Gateway resolves to wrong nexthop device - VRF"448}449 450run_onlink_tests()451{452 log_section "IPv4 onlink"453 log_subsection "Valid onlink commands"454 valid_onlink_ipv4455 log_subsection "Invalid onlink commands"456 invalid_onlink_ipv4457 458 log_section "IPv6 onlink"459 log_subsection "Valid onlink commands"460 valid_onlink_ipv6461 log_subsection "Invalid onlink commands"462 invalid_onlink_ipv6463}464 465################################################################################466# usage467 468usage()469{470 cat <<EOF471usage: ${0##*/} OPTS472 473 -p Pause on fail474 -v verbose mode (show commands and output)475EOF476}477 478################################################################################479# main480 481nsuccess=0482nfail=0483 484while getopts :t:pPhv o485do486 case $o in487 p) PAUSE_ON_FAIL=yes;;488 v) VERBOSE=$(($VERBOSE + 1));;489 h) usage; exit 0;;490 *) usage; exit 1;;491 esac492done493 494cleanup495setup496run_onlink_tests497cleanup498 499if [ "$TESTS" != "none" ]; then500 printf "\nTests passed: %3d\n" ${nsuccess}501 printf "Tests failed: %3d\n" ${nfail}502fi503