0001
0002
0003
0004
0005
0006 PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
0007 VERBOSE=0
0008
0009
0010
0011 declare -A NETIFS
0012
0013 NETIFS[p1]=veth1
0014 NETIFS[p2]=veth2
0015 NETIFS[p3]=veth3
0016 NETIFS[p4]=veth4
0017
0018 NETIFS[p5]=veth5
0019 NETIFS[p6]=veth6
0020 NETIFS[p7]=veth7
0021 NETIFS[p8]=veth8
0022
0023
0024 declare -A V4ADDRS
0025 V4ADDRS[p1]=169.254.1.1
0026 V4ADDRS[p2]=169.254.1.2
0027 V4ADDRS[p3]=169.254.3.1
0028 V4ADDRS[p4]=169.254.3.2
0029 V4ADDRS[p5]=169.254.5.1
0030 V4ADDRS[p6]=169.254.5.2
0031 V4ADDRS[p7]=169.254.7.1
0032 V4ADDRS[p8]=169.254.7.2
0033
0034
0035 declare -A V6ADDRS
0036 V6ADDRS[p1]=2001:db8:101::1
0037 V6ADDRS[p2]=2001:db8:101::2
0038 V6ADDRS[p3]=2001:db8:301::1
0039 V6ADDRS[p4]=2001:db8:301::2
0040 V6ADDRS[p5]=2001:db8:501::1
0041 V6ADDRS[p6]=2001:db8:501::2
0042 V6ADDRS[p7]=2001:db8:701::1
0043 V6ADDRS[p8]=2001:db8:701::2
0044
0045
0046
0047
0048
0049
0050 declare -A TEST_NET4
0051 TEST_NET4[1]=169.254.101
0052 TEST_NET4[2]=169.254.102
0053
0054 declare -A TEST_NET6
0055 TEST_NET6[1]=2001:db8:101
0056 TEST_NET6[2]=2001:db8:102
0057
0058
0059 CONGW[1]=169.254.1.254
0060 CONGW[2]=169.254.3.254
0061 CONGW[3]=169.254.5.254
0062
0063
0064 RECGW4[1]=169.254.11.254
0065 RECGW4[2]=169.254.12.254
0066 RECGW6[1]=2001:db8:11::64
0067 RECGW6[2]=2001:db8:12::64
0068
0069
0070 declare -A TEST_NET4IN6IN6
0071 TEST_NET4IN6[1]=10.1.1.254
0072 TEST_NET4IN6[2]=10.2.1.254
0073
0074
0075 MCAST6=ff02::1
0076
0077
0078 PEER_NS=bart
0079 PEER_CMD="ip netns exec ${PEER_NS}"
0080 VRF=lisa
0081 VRF_TABLE=1101
0082 PBR_TABLE=101
0083
0084
0085
0086
0087 log_test()
0088 {
0089 local rc=$1
0090 local expected=$2
0091 local msg="$3"
0092
0093 if [ ${rc} -eq ${expected} ]; then
0094 nsuccess=$((nsuccess+1))
0095 printf " TEST: %-50s [ OK ]\n" "${msg}"
0096 else
0097 nfail=$((nfail+1))
0098 printf " TEST: %-50s [FAIL]\n" "${msg}"
0099 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
0100 echo
0101 echo "hit enter to continue, 'q' to quit"
0102 read a
0103 [ "$a" = "q" ] && exit 1
0104 fi
0105 fi
0106 }
0107
0108 log_section()
0109 {
0110 echo
0111 echo "######################################################################"
0112 echo "TEST SECTION: $*"
0113 echo "######################################################################"
0114 }
0115
0116 log_subsection()
0117 {
0118 echo
0119 echo "#########################################"
0120 echo "TEST SUBSECTION: $*"
0121 }
0122
0123 run_cmd()
0124 {
0125 local cmd="$*"
0126 local out
0127 local rc
0128
0129 if [ "$VERBOSE" = "1" ]; then
0130 printf " COMMAND: $cmd\n"
0131 fi
0132
0133 out=$(eval $cmd 2>&1)
0134 rc=$?
0135 if [ "$VERBOSE" = "1" -a -n "$out" ]; then
0136 echo " $out"
0137 fi
0138
0139 [ "$VERBOSE" = "1" ] && echo
0140
0141 return $rc
0142 }
0143
0144 get_linklocal()
0145 {
0146 local dev=$1
0147 local pfx
0148 local addr
0149
0150 addr=$(${pfx} ip -6 -br addr show dev ${dev} | \
0151 awk '{
0152 for (i = 3; i <= NF; ++i) {
0153 if ($i ~ /^fe80/)
0154 print $i
0155 }
0156 }'
0157 )
0158 addr=${addr/\/*}
0159
0160 [ -z "$addr" ] && return 1
0161
0162 echo $addr
0163
0164 return 0
0165 }
0166
0167
0168
0169
0170 setup()
0171 {
0172 echo
0173 echo "########################################"
0174 echo "Configuring interfaces"
0175
0176 set -e
0177
0178
0179 ip netns add ${PEER_NS}
0180 ip -netns ${PEER_NS} li set lo up
0181
0182
0183 ip li add ${VRF} type vrf table ${VRF_TABLE}
0184 ip li set ${VRF} up
0185 ip ro add table ${VRF_TABLE} unreachable default metric 8192
0186 ip -6 ro add table ${VRF_TABLE} unreachable default metric 8192
0187
0188
0189 ip li add ${NETIFS[p1]} type veth peer name ${NETIFS[p2]}
0190 ip li add ${NETIFS[p3]} type veth peer name ${NETIFS[p4]}
0191 ip li add ${NETIFS[p5]} type veth peer name ${NETIFS[p6]}
0192 ip li add ${NETIFS[p7]} type veth peer name ${NETIFS[p8]}
0193
0194
0195 for n in 5 7; do
0196 ip li set ${NETIFS[p${n}]} vrf ${VRF}
0197 done
0198
0199
0200 for n in 1 3 5 7; do
0201 ip li set ${NETIFS[p${n}]} up
0202 ip addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
0203 ip addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} nodad
0204 done
0205
0206
0207 for n in 2 4 6 8; do
0208 ip li set ${NETIFS[p${n}]} netns ${PEER_NS} up
0209 ip -netns ${PEER_NS} addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
0210 ip -netns ${PEER_NS} addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} nodad
0211 done
0212
0213 ip -6 ro add default via ${V6ADDRS[p3]/::[0-9]/::64}
0214 ip -6 ro add table ${VRF_TABLE} default via ${V6ADDRS[p7]/::[0-9]/::64}
0215
0216 set +e
0217 }
0218
0219 cleanup()
0220 {
0221
0222 ip netns del ${PEER_NS} 2>/dev/null
0223 for n in 1 3 5 7; do
0224 ip link del ${NETIFS[p${n}]} 2>/dev/null
0225 done
0226 ip link del ${VRF} 2>/dev/null
0227 ip ro flush table ${VRF_TABLE}
0228 ip -6 ro flush table ${VRF_TABLE}
0229 }
0230
0231
0232
0233
0234
0235 run_ip()
0236 {
0237 local table="$1"
0238 local prefix="$2"
0239 local gw="$3"
0240 local dev="$4"
0241 local exp_rc="$5"
0242 local desc="$6"
0243
0244
0245 [ -n "${dev}" ] && dev="dev ${dev}"
0246
0247 run_cmd ip ro add table "${table}" "${prefix}"/32 via "${gw}" "${dev}" onlink
0248 log_test $? ${exp_rc} "${desc}"
0249 }
0250
0251 run_ip_mpath()
0252 {
0253 local table="$1"
0254 local prefix="$2"
0255 local nh1="$3"
0256 local nh2="$4"
0257 local exp_rc="$5"
0258 local desc="$6"
0259
0260
0261 [ -n "${dev}" ] && dev="dev ${dev}"
0262
0263 run_cmd ip ro add table "${table}" "${prefix}"/32 \
0264 nexthop via ${nh1} nexthop via ${nh2}
0265 log_test $? ${exp_rc} "${desc}"
0266 }
0267
0268 valid_onlink_ipv4()
0269 {
0270
0271
0272 log_subsection "default VRF - main table"
0273
0274 run_ip 254 ${TEST_NET4[1]}.1 ${CONGW[1]} ${NETIFS[p1]} 0 "unicast connected"
0275 run_ip 254 ${TEST_NET4[1]}.2 ${RECGW4[1]} ${NETIFS[p1]} 0 "unicast recursive"
0276
0277 log_subsection "VRF ${VRF}"
0278
0279 run_ip ${VRF_TABLE} ${TEST_NET4[2]}.1 ${CONGW[3]} ${NETIFS[p5]} 0 "unicast connected"
0280 run_ip ${VRF_TABLE} ${TEST_NET4[2]}.2 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive"
0281
0282 log_subsection "VRF device, PBR table"
0283
0284 run_ip ${PBR_TABLE} ${TEST_NET4[2]}.3 ${CONGW[3]} ${NETIFS[p5]} 0 "unicast connected"
0285 run_ip ${PBR_TABLE} ${TEST_NET4[2]}.4 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive"
0286
0287
0288
0289 log_subsection "default VRF - main table - multipath"
0290
0291 run_ip_mpath 254 ${TEST_NET4[1]}.5 \
0292 "${CONGW[1]} dev ${NETIFS[p1]} onlink" \
0293 "${CONGW[2]} dev ${NETIFS[p3]} onlink" \
0294 0 "unicast connected - multipath"
0295
0296 run_ip_mpath 254 ${TEST_NET4[1]}.6 \
0297 "${RECGW4[1]} dev ${NETIFS[p1]} onlink" \
0298 "${RECGW4[2]} dev ${NETIFS[p3]} onlink" \
0299 0 "unicast recursive - multipath"
0300
0301 run_ip_mpath 254 ${TEST_NET4[1]}.7 \
0302 "${CONGW[1]} dev ${NETIFS[p1]}" \
0303 "${CONGW[2]} dev ${NETIFS[p3]} onlink" \
0304 0 "unicast connected - multipath onlink first only"
0305
0306 run_ip_mpath 254 ${TEST_NET4[1]}.8 \
0307 "${CONGW[1]} dev ${NETIFS[p1]} onlink" \
0308 "${CONGW[2]} dev ${NETIFS[p3]}" \
0309 0 "unicast connected - multipath onlink second only"
0310 }
0311
0312 invalid_onlink_ipv4()
0313 {
0314 run_ip 254 ${TEST_NET4[1]}.11 ${V4ADDRS[p1]} ${NETIFS[p1]} 2 \
0315 "Invalid gw - local unicast address"
0316
0317 run_ip ${VRF_TABLE} ${TEST_NET4[2]}.11 ${V4ADDRS[p5]} ${NETIFS[p5]} 2 \
0318 "Invalid gw - local unicast address, VRF"
0319
0320 run_ip 254 ${TEST_NET4[1]}.101 ${V4ADDRS[p1]} "" 2 "No nexthop device given"
0321
0322 run_ip 254 ${TEST_NET4[1]}.102 ${V4ADDRS[p3]} ${NETIFS[p1]} 2 \
0323 "Gateway resolves to wrong nexthop device"
0324
0325 run_ip ${VRF_TABLE} ${TEST_NET4[2]}.103 ${V4ADDRS[p7]} ${NETIFS[p5]} 2 \
0326 "Gateway resolves to wrong nexthop device - VRF"
0327 }
0328
0329
0330
0331
0332
0333 run_ip6()
0334 {
0335 local table="$1"
0336 local prefix="$2"
0337 local gw="$3"
0338 local dev="$4"
0339 local exp_rc="$5"
0340 local desc="$6"
0341
0342
0343 [ -n "${dev}" ] && dev="dev ${dev}"
0344
0345 run_cmd ip -6 ro add table "${table}" "${prefix}"/128 via "${gw}" "${dev}" onlink
0346 log_test $? ${exp_rc} "${desc}"
0347 }
0348
0349 run_ip6_mpath()
0350 {
0351 local table="$1"
0352 local prefix="$2"
0353 local opts="$3"
0354 local nh1="$4"
0355 local nh2="$5"
0356 local exp_rc="$6"
0357 local desc="$7"
0358
0359 run_cmd ip -6 ro add table "${table}" "${prefix}"/128 "${opts}" \
0360 nexthop via ${nh1} nexthop via ${nh2}
0361 log_test $? ${exp_rc} "${desc}"
0362 }
0363
0364 valid_onlink_ipv6()
0365 {
0366
0367
0368 log_subsection "default VRF - main table"
0369
0370 run_ip6 254 ${TEST_NET6[1]}::1 ${V6ADDRS[p1]/::*}::64 ${NETIFS[p1]} 0 "unicast connected"
0371 run_ip6 254 ${TEST_NET6[1]}::2 ${RECGW6[1]} ${NETIFS[p1]} 0 "unicast recursive"
0372 run_ip6 254 ${TEST_NET6[1]}::3 ::ffff:${TEST_NET4IN6[1]} ${NETIFS[p1]} 0 "v4-mapped"
0373
0374 log_subsection "VRF ${VRF}"
0375
0376 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::1 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected"
0377 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::2 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive"
0378 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::3 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped"
0379
0380 log_subsection "VRF device, PBR table"
0381
0382 run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::4 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected"
0383 run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::5 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive"
0384 run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::6 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped"
0385
0386
0387
0388 log_subsection "default VRF - main table - multipath"
0389
0390 run_ip6_mpath 254 ${TEST_NET6[1]}::4 "onlink" \
0391 "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]}" \
0392 "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]}" \
0393 0 "unicast connected - multipath onlink"
0394
0395 run_ip6_mpath 254 ${TEST_NET6[1]}::5 "onlink" \
0396 "${RECGW6[1]} dev ${NETIFS[p1]}" \
0397 "${RECGW6[2]} dev ${NETIFS[p3]}" \
0398 0 "unicast recursive - multipath onlink"
0399
0400 run_ip6_mpath 254 ${TEST_NET6[1]}::6 "onlink" \
0401 "::ffff:${TEST_NET4IN6[1]} dev ${NETIFS[p1]}" \
0402 "::ffff:${TEST_NET4IN6[2]} dev ${NETIFS[p3]}" \
0403 0 "v4-mapped - multipath onlink"
0404
0405 run_ip6_mpath 254 ${TEST_NET6[1]}::7 "" \
0406 "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]} onlink" \
0407 "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]} onlink" \
0408 0 "unicast connected - multipath onlink both nexthops"
0409
0410 run_ip6_mpath 254 ${TEST_NET6[1]}::8 "" \
0411 "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]} onlink" \
0412 "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]}" \
0413 0 "unicast connected - multipath onlink first only"
0414
0415 run_ip6_mpath 254 ${TEST_NET6[1]}::9 "" \
0416 "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]}" \
0417 "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]} onlink" \
0418 0 "unicast connected - multipath onlink second only"
0419 }
0420
0421 invalid_onlink_ipv6()
0422 {
0423 local lladdr
0424
0425 lladdr=$(get_linklocal ${NETIFS[p1]}) || return 1
0426
0427 run_ip6 254 ${TEST_NET6[1]}::11 ${V6ADDRS[p1]} ${NETIFS[p1]} 2 \
0428 "Invalid gw - local unicast address"
0429 run_ip6 254 ${TEST_NET6[1]}::12 ${lladdr} ${NETIFS[p1]} 2 \
0430 "Invalid gw - local linklocal address"
0431 run_ip6 254 ${TEST_NET6[1]}::12 ${MCAST6} ${NETIFS[p1]} 2 \
0432 "Invalid gw - multicast address"
0433
0434 lladdr=$(get_linklocal ${NETIFS[p5]}) || return 1
0435 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::11 ${V6ADDRS[p5]} ${NETIFS[p5]} 2 \
0436 "Invalid gw - local unicast address, VRF"
0437 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${lladdr} ${NETIFS[p5]} 2 \
0438 "Invalid gw - local linklocal address, VRF"
0439 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${MCAST6} ${NETIFS[p5]} 2 \
0440 "Invalid gw - multicast address, VRF"
0441
0442 run_ip6 254 ${TEST_NET6[1]}::101 ${V6ADDRS[p1]} "" 2 \
0443 "No nexthop device given"
0444
0445
0446
0447
0448
0449 run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::103 ${V6ADDRS[p7]/::[0-9]/::64} ${NETIFS[p5]} 2 \
0450 "Gateway resolves to wrong nexthop device - VRF"
0451 }
0452
0453 run_onlink_tests()
0454 {
0455 log_section "IPv4 onlink"
0456 log_subsection "Valid onlink commands"
0457 valid_onlink_ipv4
0458 log_subsection "Invalid onlink commands"
0459 invalid_onlink_ipv4
0460
0461 log_section "IPv6 onlink"
0462 log_subsection "Valid onlink commands"
0463 valid_onlink_ipv6
0464 log_subsection "Invalid onlink commands"
0465 invalid_onlink_ipv6
0466 }
0467
0468
0469
0470
0471 usage()
0472 {
0473 cat <<EOF
0474 usage: ${0
0475
0476 -p Pause on fail
0477 -v verbose mode (show commands and output)
0478 EOF
0479 }
0480
0481
0482
0483
0484 nsuccess=0
0485 nfail=0
0486
0487 while getopts :t:pPhv o
0488 do
0489 case $o in
0490 p) PAUSE_ON_FAIL=yes;;
0491 v) VERBOSE=$(($VERBOSE + 1));;
0492 h) usage; exit 0;;
0493 *) usage; exit 1;;
0494 esac
0495 done
0496
0497 cleanup
0498 setup
0499 run_onlink_tests
0500 cleanup
0501
0502 if [ "$TESTS" != "none" ]; then
0503 printf "\nTests passed: %3d\n" ${nsuccess}
0504 printf "Tests failed: %3d\n" ${nfail}
0505 fi