1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4# IPv4 and IPv6 onlink tests 5 6PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no} 7 8# Network interfaces 9# - odd in current namespace; even in peer ns 10declare -A NETIFS 11# default VRF 12NETIFS[p1]=veth1 13NETIFS[p2]=veth2 14NETIFS[p3]=veth3 15NETIFS[p4]=veth4 16# VRF 17NETIFS[p5]=veth5 18NETIFS[p6]=veth6 19NETIFS[p7]=veth7 20NETIFS[p8]=veth8 21 22# /24 network 23declare -A V4ADDRS 24V4ADDRS[p1]=169.254.1.1 25V4ADDRS[p2]=169.254.1.2 26V4ADDRS[p3]=169.254.3.1 27V4ADDRS[p4]=169.254.3.2 28V4ADDRS[p5]=169.254.5.1 29V4ADDRS[p6]=169.254.5.2 30V4ADDRS[p7]=169.254.7.1 31V4ADDRS[p8]=169.254.7.2 32 33# /64 network 34declare -A V6ADDRS 35V6ADDRS[p1]=2001:db8:101::1 36V6ADDRS[p2]=2001:db8:101::2 37V6ADDRS[p3]=2001:db8:301::1 38V6ADDRS[p4]=2001:db8:301::2 39V6ADDRS[p5]=2001:db8:501::1 40V6ADDRS[p6]=2001:db8:501::2 41V6ADDRS[p7]=2001:db8:701::1 42V6ADDRS[p8]=2001:db8:701::2 43 44# Test networks: 45# [1] = default table 46# [2] = VRF 47# 48# /32 host routes 49declare -A TEST_NET4 50TEST_NET4[1]=169.254.101 51TEST_NET4[2]=169.254.102 52# /128 host routes 53declare -A TEST_NET6 54TEST_NET6[1]=2001:db8:101 55TEST_NET6[2]=2001:db8:102 56 57# connected gateway 58CONGW[1]=169.254.1.254 59CONGW[2]=169.254.5.254 60 61# recursive gateway 62RECGW4[1]=169.254.11.254 63RECGW4[2]=169.254.12.254 64RECGW6[1]=2001:db8:11::64 65RECGW6[2]=2001:db8:12::64 66 67# for v4 mapped to v6 68declare -A TEST_NET4IN6IN6 69TEST_NET4IN6[1]=10.1.1.254 70TEST_NET4IN6[2]=10.2.1.254 71 72# mcast address 73MCAST6=ff02::1 74 75 76PEER_NS=bart 77PEER_CMD="ip netns exec ${PEER_NS}" 78VRF=lisa 79VRF_TABLE=1101 80PBR_TABLE=101 81 82################################################################################ 83# utilities 84 85log_test() 86{ 87 local rc=$1 88 local expected=$2 89 local msg="$3" 90 91 if [ ${rc} -eq ${expected} ]; then 92 nsuccess=$((nsuccess+1)) 93 printf "\n TEST: %-50s [ OK ]\n" "${msg}" 94 else 95 nfail=$((nfail+1)) 96 printf "\n TEST: %-50s [FAIL]\n" "${msg}" 97 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then 98 echo 99 echo "hit enter to continue, 'q' to quit" 100 read a 101 [ "$a" = "q" ] && exit 1 102 fi 103 fi 104} 105 106log_section() 107{ 108 echo 109 echo "######################################################################" 110 echo "TEST SECTION: $*" 111 echo "######################################################################" 112} 113 114log_subsection() 115{ 116 echo 117 echo "#########################################" 118 echo "TEST SUBSECTION: $*" 119} 120 121run_cmd() 122{ 123 echo 124 echo "COMMAND: $*" 125 eval $* 126} 127 128get_linklocal() 129{ 130 local dev=$1 131 local pfx 132 local addr 133 134 addr=$(${pfx} ip -6 -br addr show dev ${dev} | \ 135 awk '{ 136 for (i = 3; i <= NF; ++i) { 137 if ($i ~ /^fe80/) 138 print $i 139 } 140 }' 141 ) 142 addr=${addr/\/*} 143 144 [ -z "$addr" ] && return 1 145 146 echo $addr 147 148 return 0 149} 150 151################################################################################ 152# 153 154setup() 155{ 156 echo 157 echo "########################################" 158 echo "Configuring interfaces" 159 160 set -e 161 162 # create namespace 163 ip netns add ${PEER_NS} 164 ip -netns ${PEER_NS} li set lo up 165 166 # add vrf table 167 ip li add ${VRF} type vrf table ${VRF_TABLE} 168 ip li set ${VRF} up 169 ip ro add table ${VRF_TABLE} unreachable default 170 ip -6 ro add table ${VRF_TABLE} unreachable default 171 172 # create test interfaces 173 ip li add ${NETIFS[p1]} type veth peer name ${NETIFS[p2]} 174 ip li add ${NETIFS[p3]} type veth peer name ${NETIFS[p4]} 175 ip li add ${NETIFS[p5]} type veth peer name ${NETIFS[p6]} 176 ip li add ${NETIFS[p7]} type veth peer name ${NETIFS[p8]} 177 178 # enslave vrf interfaces 179 for n in 5 7; do 180 ip li set ${NETIFS[p${n}]} vrf ${VRF} 181 done 182 183 # add addresses 184 for n in 1 3 5 7; do 185 ip li set ${NETIFS[p${n}]} up 186 ip addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]} 187 ip addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} 188 done 189 190 # move peer interfaces to namespace and add addresses 191 for n in 2 4 6 8; do 192 ip li set ${NETIFS[p${n}]} netns ${PEER_NS} up 193 ip -netns ${PEER_NS} addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]} 194 ip -netns ${PEER_NS} addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} 195 done 196 197 set +e 198 199 # let DAD complete - assume default of 1 probe 200 sleep 1 201} 202 203cleanup() 204{ 205 # make sure we start from a clean slate 206 ip netns del ${PEER_NS} 2>/dev/null 207 for n in 1 3 5 7; do 208 ip link del ${NETIFS[p${n}]} 2>/dev/null 209 done 210 ip link del ${VRF} 2>/dev/null 211 ip ro flush table ${VRF_TABLE} 212 ip -6 ro flush table ${VRF_TABLE} 213} 214 215################################################################################ 216# IPv4 tests 217# 218 219run_ip() 220{ 221 local table="$1" 222 local prefix="$2" 223 local gw="$3" 224 local dev="$4" 225 local exp_rc="$5" 226 local desc="$6" 227 228 # dev arg may be empty 229 [ -n "${dev}" ] && dev="dev ${dev}" 230 231 run_cmd ip ro add table "${table}" "${prefix}"/32 via "${gw}" "${dev}" onlink 232 log_test $? ${exp_rc} "${desc}" 233} 234 235valid_onlink_ipv4() 236{ 237 # - unicast connected, unicast recursive 238 # 239 log_subsection "default VRF - main table" 240 241 run_ip 254 ${TEST_NET4[1]}.1 ${CONGW[1]} ${NETIFS[p1]} 0 "unicast connected" 242 run_ip 254 ${TEST_NET4[1]}.2 ${RECGW4[1]} ${NETIFS[p1]} 0 "unicast recursive" 243 244 log_subsection "VRF ${VRF}" 245 246 run_ip ${VRF_TABLE} ${TEST_NET4[2]}.1 ${CONGW[2]} ${NETIFS[p5]} 0 "unicast connected" 247 run_ip ${VRF_TABLE} ${TEST_NET4[2]}.2 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive" 248 249 log_subsection "VRF device, PBR table" 250 251 run_ip ${PBR_TABLE} ${TEST_NET4[2]}.3 ${CONGW[2]} ${NETIFS[p5]} 0 "unicast connected" 252 run_ip ${PBR_TABLE} ${TEST_NET4[2]}.4 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive" 253} 254 255invalid_onlink_ipv4() 256{ 257 run_ip 254 ${TEST_NET4[1]}.11 ${V4ADDRS[p1]} ${NETIFS[p1]} 2 \ 258 "Invalid gw - local unicast address" 259 260 run_ip ${VRF_TABLE} ${TEST_NET4[2]}.11 ${V4ADDRS[p5]} ${NETIFS[p5]} 2 \ 261 "Invalid gw - local unicast address, VRF" 262 263 run_ip 254 ${TEST_NET4[1]}.101 ${V4ADDRS[p1]} "" 2 "No nexthop device given" 264 265 run_ip 254 ${TEST_NET4[1]}.102 ${V4ADDRS[p3]} ${NETIFS[p1]} 2 \ 266 "Gateway resolves to wrong nexthop device" 267 268 run_ip ${VRF_TABLE} ${TEST_NET4[2]}.103 ${V4ADDRS[p7]} ${NETIFS[p5]} 2 \ 269 "Gateway resolves to wrong nexthop device - VRF" 270} 271 272################################################################################ 273# IPv6 tests 274# 275 276run_ip6() 277{ 278 local table="$1" 279 local prefix="$2" 280 local gw="$3" 281 local dev="$4" 282 local exp_rc="$5" 283 local desc="$6" 284 285 # dev arg may be empty 286 [ -n "${dev}" ] && dev="dev ${dev}" 287 288 run_cmd ip -6 ro add table "${table}" "${prefix}"/128 via "${gw}" "${dev}" onlink 289 log_test $? ${exp_rc} "${desc}" 290} 291 292valid_onlink_ipv6() 293{ 294 # - unicast connected, unicast recursive, v4-mapped 295 # 296 log_subsection "default VRF - main table" 297 298 run_ip6 254 ${TEST_NET6[1]}::1 ${V6ADDRS[p1]/::*}::64 ${NETIFS[p1]} 0 "unicast connected" 299 run_ip6 254 ${TEST_NET6[1]}::2 ${RECGW6[1]} ${NETIFS[p1]} 0 "unicast recursive" 300 run_ip6 254 ${TEST_NET6[1]}::3 ::ffff:${TEST_NET4IN6[1]} ${NETIFS[p1]} 0 "v4-mapped" 301 302 log_subsection "VRF ${VRF}" 303 304 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::1 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected" 305 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::2 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive" 306 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::3 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped" 307 308 log_subsection "VRF device, PBR table" 309 310 run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::4 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected" 311 run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::5 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive" 312 run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::6 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped" 313} 314 315invalid_onlink_ipv6() 316{ 317 local lladdr 318 319 lladdr=$(get_linklocal ${NETIFS[p1]}) || return 1 320 321 run_ip6 254 ${TEST_NET6[1]}::11 ${V6ADDRS[p1]} ${NETIFS[p1]} 2 \ 322 "Invalid gw - local unicast address" 323 run_ip6 254 ${TEST_NET6[1]}::12 ${lladdr} ${NETIFS[p1]} 2 \ 324 "Invalid gw - local linklocal address" 325 run_ip6 254 ${TEST_NET6[1]}::12 ${MCAST6} ${NETIFS[p1]} 2 \ 326 "Invalid gw - multicast address" 327 328 lladdr=$(get_linklocal ${NETIFS[p5]}) || return 1 329 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::11 ${V6ADDRS[p5]} ${NETIFS[p5]} 2 \ 330 "Invalid gw - local unicast address, VRF" 331 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${lladdr} ${NETIFS[p5]} 2 \ 332 "Invalid gw - local linklocal address, VRF" 333 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${MCAST6} ${NETIFS[p5]} 2 \ 334 "Invalid gw - multicast address, VRF" 335 336 run_ip6 254 ${TEST_NET6[1]}::101 ${V6ADDRS[p1]} "" 2 \ 337 "No nexthop device given" 338 339 # default VRF validation is done against LOCAL table 340 # run_ip6 254 ${TEST_NET6[1]}::102 ${V6ADDRS[p3]/::[0-9]/::64} ${NETIFS[p1]} 2 \ 341 # "Gateway resolves to wrong nexthop device" 342 343 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::103 ${V6ADDRS[p7]/::[0-9]/::64} ${NETIFS[p5]} 2 \ 344 "Gateway resolves to wrong nexthop device - VRF" 345} 346 347run_onlink_tests() 348{ 349 log_section "IPv4 onlink" 350 log_subsection "Valid onlink commands" 351 valid_onlink_ipv4 352 log_subsection "Invalid onlink commands" 353 invalid_onlink_ipv4 354 355 log_section "IPv6 onlink" 356 log_subsection "Valid onlink commands" 357 valid_onlink_ipv6 358 invalid_onlink_ipv6 359} 360 361################################################################################ 362# main 363 364nsuccess=0 365nfail=0 366 367cleanup 368setup 369run_onlink_tests 370cleanup 371 372if [ "$TESTS" != "none" ]; then 373 printf "\nTests passed: %3d\n" ${nsuccess} 374 printf "Tests failed: %3d\n" ${nfail} 375fi 376