1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# 4# Various combinations of VRF with xfrms and qdisc. 5 6source lib.sh 7PAUSE_ON_FAIL=no 8VERBOSE=0 9ret=0 10 11HOST1_4=192.168.1.1 12HOST2_4=192.168.1.2 13HOST1_6=2001:db8:1::1 14HOST2_6=2001:db8:1::2 15 16XFRM1_4=10.0.1.1 17XFRM2_4=10.0.1.2 18XFRM1_6=fc00:1000::1 19XFRM2_6=fc00:1000::2 20IF_ID=123 21 22VRF=red 23TABLE=300 24 25AUTH_1=0xd94fcfea65fddf21dc6e0d24a0253508 26AUTH_2=0xdc6e0d24a0253508d94fcfea65fddf21 27ENC_1=0xfc46c20f8048be9725930ff3fb07ac2a91f0347dffeacf62 28ENC_2=0x3fb07ac2a91f0347dffeacf62fc46c20f8048be9725930ff 29SPI_1=0x02122b77 30SPI_2=0x2b770212 31 32which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping) 33 34################################################################################ 35# 36log_test() 37{ 38 local rc=$1 39 local expected=$2 40 local msg="$3" 41 42 if [ ${rc} -eq ${expected} ]; then 43 printf "TEST: %-60s [ OK ]\n" "${msg}" 44 nsuccess=$((nsuccess+1)) 45 else 46 ret=1 47 nfail=$((nfail+1)) 48 printf "TEST: %-60s [FAIL]\n" "${msg}" 49 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then 50 echo 51 echo "hit enter to continue, 'q' to quit" 52 read a 53 [ "$a" = "q" ] && exit 1 54 fi 55 fi 56} 57 58run_cmd_host1() 59{ 60 local cmd="$*" 61 local out 62 local rc 63 64 if [ "$VERBOSE" = "1" ]; then 65 printf " COMMAND: $cmd\n" 66 fi 67 68 out=$(eval ip netns exec $host1 $cmd 2>&1) 69 rc=$? 70 if [ "$VERBOSE" = "1" ]; then 71 if [ -n "$out" ]; then 72 echo 73 echo " $out" 74 fi 75 echo 76 fi 77 78 return $rc 79} 80 81################################################################################ 82# create namespaces for hosts and sws 83 84create_vrf() 85{ 86 local ns=$1 87 local vrf=$2 88 local table=$3 89 90 if [ -n "${ns}" ]; then 91 ns="-netns ${ns}" 92 fi 93 94 ip ${ns} link add ${vrf} type vrf table ${table} 95 ip ${ns} link set ${vrf} up 96 ip ${ns} route add vrf ${vrf} unreachable default metric 8192 97 ip ${ns} -6 route add vrf ${vrf} unreachable default metric 8192 98 99 ip ${ns} addr add 127.0.0.1/8 dev ${vrf} 100 ip ${ns} -6 addr add ::1 dev ${vrf} nodad 101 102 ip ${ns} ru del pref 0 103 ip ${ns} ru add pref 32765 from all lookup local 104 ip ${ns} -6 ru del pref 0 105 ip ${ns} -6 ru add pref 32765 from all lookup local 106} 107 108create_ns() 109{ 110 local ns=$1 111 local addr=$2 112 local addr6=$3 113 114 [ -z "${addr}" ] && addr="-" 115 [ -z "${addr6}" ] && addr6="-" 116 117 if [ "${addr}" != "-" ]; then 118 ip -netns ${ns} addr add dev lo ${addr} 119 fi 120 if [ "${addr6}" != "-" ]; then 121 ip -netns ${ns} -6 addr add dev lo ${addr6} 122 fi 123 124 ip -netns ${ns} ro add unreachable default metric 8192 125 ip -netns ${ns} -6 ro add unreachable default metric 8192 126 127 ip netns exec ${ns} sysctl -qw net.ipv4.ip_forward=1 128 ip netns exec ${ns} sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1 129 ip netns exec ${ns} sysctl -qw net.ipv6.conf.all.forwarding=1 130 ip netns exec ${ns} sysctl -qw net.ipv6.conf.default.forwarding=1 131 ip netns exec ${ns} sysctl -qw net.ipv6.conf.default.accept_dad=0 132} 133 134# create veth pair to connect namespaces and apply addresses. 135connect_ns() 136{ 137 local ns1=$1 138 local ns1_dev=$2 139 local ns1_addr=$3 140 local ns1_addr6=$4 141 local ns2=$5 142 local ns2_dev=$6 143 local ns2_addr=$7 144 local ns2_addr6=$8 145 local ns1arg 146 local ns2arg 147 148 if [ -n "${ns1}" ]; then 149 ns1arg="-netns ${ns1}" 150 fi 151 if [ -n "${ns2}" ]; then 152 ns2arg="-netns ${ns2}" 153 fi 154 155 ip ${ns1arg} li add ${ns1_dev} type veth peer name tmp 156 ip ${ns1arg} li set ${ns1_dev} up 157 ip ${ns1arg} li set tmp netns ${ns2} name ${ns2_dev} 158 ip ${ns2arg} li set ${ns2_dev} up 159 160 if [ "${ns1_addr}" != "-" ]; then 161 ip ${ns1arg} addr add dev ${ns1_dev} ${ns1_addr} 162 ip ${ns2arg} addr add dev ${ns2_dev} ${ns2_addr} 163 fi 164 165 if [ "${ns1_addr6}" != "-" ]; then 166 ip ${ns1arg} addr add dev ${ns1_dev} ${ns1_addr6} nodad 167 ip ${ns2arg} addr add dev ${ns2_dev} ${ns2_addr6} nodad 168 fi 169} 170 171################################################################################ 172 173cleanup() 174{ 175 cleanup_ns $host1 $host2 176} 177 178setup() 179{ 180 setup_ns host1 host2 181 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}/64 186 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 $host2 194 do 195 for x in state policy 196 do 197 ip -netns ${ns} xfrm ${x} flush 198 ip -6 -netns ${ns} xfrm ${x} flush 199 done 200 done 201} 202 203setup_xfrm() 204{ 205 local h1_4=$1 206 local h2_4=$2 207 local h1_6=$3 208 local h2_6=$4 209 local devarg="$5" 210 211 # 212 # policy 213 # 214 215 # host1 - IPv4 out 216 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 tunnel 219 220 # host2 - IPv4 in 221 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 tunnel 224 225 # host1 - IPv4 in 226 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 tunnel 229 230 # host2 - IPv4 out 231 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 tunnel 234 235 236 # host1 - IPv6 out 237 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 tunnel 240 241 # host2 - IPv6 in 242 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 tunnel 245 246 # host1 - IPv6 in 247 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 tunnel 250 251 # host2 - IPv6 out 252 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 tunnel 255 256 # 257 # state 258 # 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 xfrm0 322 ip -netns $host2 addr del ${XFRM2_4}/24 dev eth0 323 ip -netns $host2 addr del ${XFRM2_6}/64 dev eth0 324} 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} up 332 ip -netns $host1 addr add ${XFRM1_4}/24 dev xfrm0 333 ip -netns $host1 addr add ${XFRM1_6}/64 dev xfrm0 334 335 ip -netns $host2 addr add ${XFRM2_4}/24 dev eth0 336 ip -netns $host2 addr add ${XFRM2_6}/64 dev eth0 337 338 setup_xfrm ${XFRM1_4} ${XFRM2_4} ${XFRM1_6} ${XFRM2_6} "if_id ${IF_ID}" 339} 340 341run_tests() 342{ 343 cleanup_xfrm 344 345 # no IPsec 346 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 sel 352 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_xfrm 358 359 # xfrm with VRF in sel 360 # Known failure: ipv4 resets the flow oif after the lookup. Fix is 361 # 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_xfrm 368 369 # xfrm with enslaved device in sel 370 # Known failures: combined with the above, __xfrm{4,6}_selector_match 371 # 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_xfrm 378 379 # xfrm device 380 setup_xfrm_dev 381 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_dev 386} 387 388################################################################################ 389# usage 390 391usage() 392{ 393 cat <<EOF 394usage: ${0##*/} OPTS 395 396 -p Pause on fail 397 -v verbose mode (show commands and output) 398 399done 400EOF 401} 402 403################################################################################ 404# main 405 406while getopts :pv o 407do 408 case $o in 409 p) PAUSE_ON_FAIL=yes;; 410 v) VERBOSE=$(($VERBOSE + 1));; 411 h) usage; exit 0;; 412 *) usage; exit 1;; 413 esac 414done 415 416cleanup 2>/dev/null 417setup 418 419echo 420echo "No qdisc on VRF device" 421run_tests 422 423run_cmd_host1 tc qdisc add dev ${VRF} root netem delay 100ms 424echo 425echo "netem qdisc on VRF device" 426run_tests 427 428printf "\nTests passed: %3d\n" ${nsuccess} 429printf "Tests failed: %3d\n" ${nfail} 430 431exit $ret 432