432 lines · bash
1#!/bin/bash2# SPDX-License-Identifier: GPL-2.03#4# Various combinations of VRF with xfrms and qdisc.5 6source lib.sh7PAUSE_ON_FAIL=no8VERBOSE=09ret=010 11HOST1_4=192.168.1.112HOST2_4=192.168.1.213HOST1_6=2001:db8:1::114HOST2_6=2001:db8:1::215 16XFRM1_4=10.0.1.117XFRM2_4=10.0.1.218XFRM1_6=fc00:1000::119XFRM2_6=fc00:1000::220IF_ID=12321 22VRF=red23TABLE=30024 25AUTH_1=0xd94fcfea65fddf21dc6e0d24a025350826AUTH_2=0xdc6e0d24a0253508d94fcfea65fddf2127ENC_1=0xfc46c20f8048be9725930ff3fb07ac2a91f0347dffeacf6228ENC_2=0x3fb07ac2a91f0347dffeacf62fc46c20f8048be9725930ff29SPI_1=0x02122b7730SPI_2=0x2b77021231 32which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping)33 34################################################################################35#36log_test()37{38 local rc=$139 local expected=$240 local msg="$3"41 42 if [ ${rc} -eq ${expected} ]; then43 printf "TEST: %-60s [ OK ]\n" "${msg}"44 nsuccess=$((nsuccess+1))45 else46 ret=147 nfail=$((nfail+1))48 printf "TEST: %-60s [FAIL]\n" "${msg}"49 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then50 echo51 echo "hit enter to continue, 'q' to quit"52 read a53 [ "$a" = "q" ] && exit 154 fi55 fi56}57 58run_cmd_host1()59{60 local cmd="$*"61 local out62 local rc63 64 if [ "$VERBOSE" = "1" ]; then65 printf " COMMAND: $cmd\n"66 fi67 68 out=$(eval ip netns exec $host1 $cmd 2>&1)69 rc=$?70 if [ "$VERBOSE" = "1" ]; then71 if [ -n "$out" ]; then72 echo73 echo " $out"74 fi75 echo76 fi77 78 return $rc79}80 81################################################################################82# create namespaces for hosts and sws83 84create_vrf()85{86 local ns=$187 local vrf=$288 local table=$389 90 if [ -n "${ns}" ]; then91 ns="-netns ${ns}"92 fi93 94 ip ${ns} link add ${vrf} type vrf table ${table}95 ip ${ns} link set ${vrf} up96 ip ${ns} route add vrf ${vrf} unreachable default metric 819297 ip ${ns} -6 route add vrf ${vrf} unreachable default metric 819298 99 ip ${ns} addr add 127.0.0.1/8 dev ${vrf}100 ip ${ns} -6 addr add ::1 dev ${vrf} nodad101 102 ip ${ns} ru del pref 0103 ip ${ns} ru add pref 32765 from all lookup local104 ip ${ns} -6 ru del pref 0105 ip ${ns} -6 ru add pref 32765 from all lookup local106}107 108create_ns()109{110 local ns=$1111 local addr=$2112 local addr6=$3113 114 [ -z "${addr}" ] && addr="-"115 [ -z "${addr6}" ] && addr6="-"116 117 if [ "${addr}" != "-" ]; then118 ip -netns ${ns} addr add dev lo ${addr}119 fi120 if [ "${addr6}" != "-" ]; then121 ip -netns ${ns} -6 addr add dev lo ${addr6}122 fi123 124 ip -netns ${ns} ro add unreachable default metric 8192125 ip -netns ${ns} -6 ro add unreachable default metric 8192126 127 ip netns exec ${ns} sysctl -qw net.ipv4.ip_forward=1128 ip netns exec ${ns} sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1129 ip netns exec ${ns} sysctl -qw net.ipv6.conf.all.forwarding=1130 ip netns exec ${ns} sysctl -qw net.ipv6.conf.default.forwarding=1131 ip netns exec ${ns} sysctl -qw net.ipv6.conf.default.accept_dad=0132}133 134# create veth pair to connect namespaces and apply addresses.135connect_ns()136{137 local ns1=$1138 local ns1_dev=$2139 local ns1_addr=$3140 local ns1_addr6=$4141 local ns2=$5142 local ns2_dev=$6143 local ns2_addr=$7144 local ns2_addr6=$8145 local ns1arg146 local ns2arg147 148 if [ -n "${ns1}" ]; then149 ns1arg="-netns ${ns1}"150 fi151 if [ -n "${ns2}" ]; then152 ns2arg="-netns ${ns2}"153 fi154 155 ip ${ns1arg} li add ${ns1_dev} type veth peer name tmp156 ip ${ns1arg} li set ${ns1_dev} up157 ip ${ns1arg} li set tmp netns ${ns2} name ${ns2_dev}158 ip ${ns2arg} li set ${ns2_dev} up159 160 if [ "${ns1_addr}" != "-" ]; then161 ip ${ns1arg} addr add dev ${ns1_dev} ${ns1_addr}162 ip ${ns2arg} addr add dev ${ns2_dev} ${ns2_addr}163 fi164 165 if [ "${ns1_addr6}" != "-" ]; then166 ip ${ns1arg} addr add dev ${ns1_dev} ${ns1_addr6} nodad167 ip ${ns2arg} addr add dev ${ns2_dev} ${ns2_addr6} nodad168 fi169}170 171################################################################################172 173cleanup()174{175 cleanup_ns $host1 $host2176}177 178setup()179{180 setup_ns host1 host2181 create_ns "$host1"182 create_ns "$host2"183 184 connect_ns "$host1" eth0 ${HOST1_4}/24 ${HOST1_6}/64 \185 "$host2" eth0 ${HOST2_4}/24 ${HOST2_6}/64186 187 create_vrf "$host1" ${VRF} ${TABLE}188 ip -netns $host1 link set dev eth0 master ${VRF}189}190 191cleanup_xfrm()192{193 for ns in $host1 $host2194 do195 for x in state policy196 do197 ip -netns ${ns} xfrm ${x} flush198 ip -6 -netns ${ns} xfrm ${x} flush199 done200 done201}202 203setup_xfrm()204{205 local h1_4=$1206 local h2_4=$2207 local h1_6=$3208 local h2_6=$4209 local devarg="$5"210 211 #212 # policy213 #214 215 # host1 - IPv4 out216 ip -netns $host1 xfrm policy add \217 src ${h1_4} dst ${h2_4} ${devarg} dir out \218 tmpl src ${HOST1_4} dst ${HOST2_4} proto esp mode tunnel219 220 # host2 - IPv4 in221 ip -netns $host2 xfrm policy add \222 src ${h1_4} dst ${h2_4} dir in \223 tmpl src ${HOST1_4} dst ${HOST2_4} proto esp mode tunnel224 225 # host1 - IPv4 in226 ip -netns $host1 xfrm policy add \227 src ${h2_4} dst ${h1_4} ${devarg} dir in \228 tmpl src ${HOST2_4} dst ${HOST1_4} proto esp mode tunnel229 230 # host2 - IPv4 out231 ip -netns $host2 xfrm policy add \232 src ${h2_4} dst ${h1_4} dir out \233 tmpl src ${HOST2_4} dst ${HOST1_4} proto esp mode tunnel234 235 236 # host1 - IPv6 out237 ip -6 -netns $host1 xfrm policy add \238 src ${h1_6} dst ${h2_6} ${devarg} dir out \239 tmpl src ${HOST1_6} dst ${HOST2_6} proto esp mode tunnel240 241 # host2 - IPv6 in242 ip -6 -netns $host2 xfrm policy add \243 src ${h1_6} dst ${h2_6} dir in \244 tmpl src ${HOST1_6} dst ${HOST2_6} proto esp mode tunnel245 246 # host1 - IPv6 in247 ip -6 -netns $host1 xfrm policy add \248 src ${h2_6} dst ${h1_6} ${devarg} dir in \249 tmpl src ${HOST2_6} dst ${HOST1_6} proto esp mode tunnel250 251 # host2 - IPv6 out252 ip -6 -netns $host2 xfrm policy add \253 src ${h2_6} dst ${h1_6} dir out \254 tmpl src ${HOST2_6} dst ${HOST1_6} proto esp mode tunnel255 256 #257 # state258 #259 ip -netns $host1 xfrm state add src ${HOST1_4} dst ${HOST2_4} \260 proto esp spi ${SPI_1} reqid 0 mode tunnel \261 replay-window 4 replay-oseq 0x4 \262 auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \263 enc 'cbc(aes)' ${ENC_1} \264 sel src ${h1_4} dst ${h2_4} ${devarg}265 266 ip -netns $host2 xfrm state add src ${HOST1_4} dst ${HOST2_4} \267 proto esp spi ${SPI_1} reqid 0 mode tunnel \268 replay-window 4 replay-oseq 0x4 \269 auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \270 enc 'cbc(aes)' ${ENC_1} \271 sel src ${h1_4} dst ${h2_4}272 273 274 ip -netns $host1 xfrm state add src ${HOST2_4} dst ${HOST1_4} \275 proto esp spi ${SPI_2} reqid 0 mode tunnel \276 replay-window 4 replay-oseq 0x4 \277 auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \278 enc 'cbc(aes)' ${ENC_2} \279 sel src ${h2_4} dst ${h1_4} ${devarg}280 281 ip -netns $host2 xfrm state add src ${HOST2_4} dst ${HOST1_4} \282 proto esp spi ${SPI_2} reqid 0 mode tunnel \283 replay-window 4 replay-oseq 0x4 \284 auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \285 enc 'cbc(aes)' ${ENC_2} \286 sel src ${h2_4} dst ${h1_4}287 288 289 ip -6 -netns $host1 xfrm state add src ${HOST1_6} dst ${HOST2_6} \290 proto esp spi ${SPI_1} reqid 0 mode tunnel \291 replay-window 4 replay-oseq 0x4 \292 auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \293 enc 'cbc(aes)' ${ENC_1} \294 sel src ${h1_6} dst ${h2_6} ${devarg}295 296 ip -6 -netns $host2 xfrm state add src ${HOST1_6} dst ${HOST2_6} \297 proto esp spi ${SPI_1} reqid 0 mode tunnel \298 replay-window 4 replay-oseq 0x4 \299 auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \300 enc 'cbc(aes)' ${ENC_1} \301 sel src ${h1_6} dst ${h2_6}302 303 304 ip -6 -netns $host1 xfrm state add src ${HOST2_6} dst ${HOST1_6} \305 proto esp spi ${SPI_2} reqid 0 mode tunnel \306 replay-window 4 replay-oseq 0x4 \307 auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \308 enc 'cbc(aes)' ${ENC_2} \309 sel src ${h2_6} dst ${h1_6} ${devarg}310 311 ip -6 -netns $host2 xfrm state add src ${HOST2_6} dst ${HOST1_6} \312 proto esp spi ${SPI_2} reqid 0 mode tunnel \313 replay-window 4 replay-oseq 0x4 \314 auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \315 enc 'cbc(aes)' ${ENC_2} \316 sel src ${h2_6} dst ${h1_6}317}318 319cleanup_xfrm_dev()320{321 ip -netns $host1 li del xfrm0322 ip -netns $host2 addr del ${XFRM2_4}/24 dev eth0323 ip -netns $host2 addr del ${XFRM2_6}/64 dev eth0324}325 326setup_xfrm_dev()327{328 local vrfarg="vrf ${VRF}"329 330 ip -netns $host1 li add type xfrm dev eth0 if_id ${IF_ID}331 ip -netns $host1 li set xfrm0 ${vrfarg} up332 ip -netns $host1 addr add ${XFRM1_4}/24 dev xfrm0333 ip -netns $host1 addr add ${XFRM1_6}/64 dev xfrm0334 335 ip -netns $host2 addr add ${XFRM2_4}/24 dev eth0336 ip -netns $host2 addr add ${XFRM2_6}/64 dev eth0337 338 setup_xfrm ${XFRM1_4} ${XFRM2_4} ${XFRM1_6} ${XFRM2_6} "if_id ${IF_ID}"339}340 341run_tests()342{343 cleanup_xfrm344 345 # no IPsec346 run_cmd_host1 ip vrf exec ${VRF} ping -c1 -w1 ${HOST2_4}347 log_test $? 0 "IPv4 no xfrm policy"348 run_cmd_host1 ip vrf exec ${VRF} ${ping6} -c1 -w1 ${HOST2_6}349 log_test $? 0 "IPv6 no xfrm policy"350 351 # xfrm without VRF in sel352 setup_xfrm ${HOST1_4} ${HOST2_4} ${HOST1_6} ${HOST2_6}353 run_cmd_host1 ip vrf exec ${VRF} ping -c1 -w1 ${HOST2_4}354 log_test $? 0 "IPv4 xfrm policy based on address"355 run_cmd_host1 ip vrf exec ${VRF} ${ping6} -c1 -w1 ${HOST2_6}356 log_test $? 0 "IPv6 xfrm policy based on address"357 cleanup_xfrm358 359 # xfrm with VRF in sel360 # Known failure: ipv4 resets the flow oif after the lookup. Fix is361 # not straightforward.362 # setup_xfrm ${HOST1_4} ${HOST2_4} ${HOST1_6} ${HOST2_6} "dev ${VRF}"363 # run_cmd_host1 ip vrf exec ${VRF} ping -c1 -w1 ${HOST2_4}364 # log_test $? 0 "IPv4 xfrm policy with VRF in selector"365 run_cmd_host1 ip vrf exec ${VRF} ${ping6} -c1 -w1 ${HOST2_6}366 log_test $? 0 "IPv6 xfrm policy with VRF in selector"367 cleanup_xfrm368 369 # xfrm with enslaved device in sel370 # Known failures: combined with the above, __xfrm{4,6}_selector_match371 # needs to consider both l3mdev and enslaved device index.372 # setup_xfrm ${HOST1_4} ${HOST2_4} ${HOST1_6} ${HOST2_6} "dev eth0"373 # run_cmd_host1 ip vrf exec ${VRF} ping -c1 -w1 ${HOST2_4}374 # log_test $? 0 "IPv4 xfrm policy with enslaved device in selector"375 # run_cmd_host1 ip vrf exec ${VRF} ${ping6} -c1 -w1 ${HOST2_6}376 # log_test $? 0 "IPv6 xfrm policy with enslaved device in selector"377 # cleanup_xfrm378 379 # xfrm device380 setup_xfrm_dev381 run_cmd_host1 ip vrf exec ${VRF} ping -c1 -w1 ${XFRM2_4}382 log_test $? 0 "IPv4 xfrm policy with xfrm device"383 run_cmd_host1 ip vrf exec ${VRF} ${ping6} -c1 -w1 ${XFRM2_6}384 log_test $? 0 "IPv6 xfrm policy with xfrm device"385 cleanup_xfrm_dev386}387 388################################################################################389# usage390 391usage()392{393 cat <<EOF394usage: ${0##*/} OPTS395 396 -p Pause on fail397 -v verbose mode (show commands and output)398 399done400EOF401}402 403################################################################################404# main405 406while getopts :pv o407do408 case $o in409 p) PAUSE_ON_FAIL=yes;;410 v) VERBOSE=$(($VERBOSE + 1));;411 h) usage; exit 0;;412 *) usage; exit 1;;413 esac414done415 416cleanup 2>/dev/null417setup418 419echo420echo "No qdisc on VRF device"421run_tests422 423run_cmd_host1 tc qdisc add dev ${VRF} root netem delay 100ms424echo425echo "netem qdisc on VRF device"426run_tests427 428printf "\nTests passed: %3d\n" ${nsuccess}429printf "Tests failed: %3d\n" ${nfail}430 431exit $ret432