1 #!/bin/bash 2 # SPDX-License-Identifier: GPL-2.0 3 # 4 # author: Andrea Mayer <andrea.mayer@uniroma2.it> 5 # 6 # This script is designed for testing the SRv6 H.Encaps.Red behavior. 7 # 8 # Below is depicted the IPv6 network of an operator which offers advanced 9 # IPv4/IPv6 VPN services to hosts, enabling them to communicate with each 10 # other. 11 # In this example, hosts hs-1 and hs-2 are connected through an IPv4/IPv6 VPN 12 # service, while hs-3 and hs-4 are connected using an IPv6 only VPN. 13 # 14 # Routers rt-1,rt-2,rt-3 and rt-4 implement IPv4/IPv6 L3 VPN services 15 # leveraging the SRv6 architecture. The key components for such VPNs are: 16 # 17 # i) The SRv6 H.Encaps.Red behavior applies SRv6 Policies on traffic received 18 # by connected hosts, initiating the VPN tunnel. Such a behavior is an 19 # optimization of the SRv6 H.Encap aiming to reduce the length of the SID 20 # List carried in the pushed SRH. Specifically, the H.Encaps.Red removes 21 # the first SID contained in the SID List (i.e. SRv6 Policy) by storing it 22 # into the IPv6 Destination Address. When a SRv6 Policy is made of only one 23 # SID, the SRv6 H.Encaps.Red behavior omits the SRH at all and pushes that 24 # SID directly into the IPv6 DA; 25 # 26 # ii) The SRv6 End behavior advances the active SID in the SID List carried by 27 # the SRH; 28 # 29 # iii) The SRv6 End.DT46 behavior is used for removing the SRv6 Policy and, 30 # thus, it terminates the VPN tunnel. Such a behavior is capable of 31 # handling, at the same time, both tunneled IPv4 and IPv6 traffic. 32 # 33 # 34 # cafe::1 cafe::2 35 # 10.0.0.1 10.0.0.2 36 # +--------+ +--------+ 37 # | | | | 38 # | hs-1 | | hs-2 | 39 # | | | | 40 # +---+----+ +--- +---+ 41 # cafe::/64 | | cafe::/64 42 # 10.0.0.0/24 | | 10.0.0.0/24 43 # +---+----+ +----+---+ 44 # | | fcf0:0:1:2::/64 | | 45 # | rt-1 +-------------------+ rt-2 | 46 # | | | | 47 # +---+----+ +----+---+ 48 # | . . | 49 # | fcf0:0:1:3::/64 . | 50 # | . . | 51 # | . . | 52 # fcf0:0:1:4::/64 | . | fcf0:0:2:3::/64 53 # | . . | 54 # | . . | 55 # | fcf0:0:2:4::/64 . | 56 # | . . | 57 # +---+----+ +----+---+ 58 # | | | | 59 # | rt-4 +-------------------+ rt-3 | 60 # | | fcf0:0:3:4::/64 | | 61 # +---+----+ +----+---+ 62 # cafe::/64 | | cafe::/64 63 # 10.0.0.0/24 | | 10.0.0.0/24 64 # +---+----+ +--- +---+ 65 # | | | | 66 # | hs-4 | | hs-3 | 67 # | | | | 68 # +--------+ +--------+ 69 # cafe::4 cafe::3 70 # 10.0.0.4 10.0.0.3 71 # 72 # 73 # Every fcf0:0:x:y::/64 network interconnects the SRv6 routers rt-x with rt-y 74 # in the IPv6 operator network. 75 # 76 # Local SID table 77 # =============== 78 # 79 # Each SRv6 router is configured with a Local SID table in which SIDs are 80 # stored. Considering the given SRv6 router rt-x, at least two SIDs are 81 # configured in the Local SID table: 82 # 83 # Local SID table for SRv6 router rt-x 84 # +----------------------------------------------------------+ 85 # |fcff:x::e is associated with the SRv6 End behavior | 86 # |fcff:x::d46 is associated with the SRv6 End.DT46 behavior | 87 # +----------------------------------------------------------+ 88 # 89 # The fcff::/16 prefix is reserved by the operator for implementing SRv6 VPN 90 # services. Reachability of SIDs is ensured by proper configuration of the IPv6 91 # operator's network and SRv6 routers. 92 # 93 # # SRv6 Policies 94 # =============== 95 # 96 # An SRv6 ingress router applies SRv6 policies to the traffic received from a 97 # connected host. SRv6 policy enforcement consists of encapsulating the 98 # received traffic into a new IPv6 packet with a given SID List contained in 99 # the SRH. 100 # 101 # IPv4/IPv6 VPN between hs-1 and hs-2 102 # ----------------------------------- 103 # 104 # Hosts hs-1 and hs-2 are connected using dedicated IPv4/IPv6 VPNs. 105 # Specifically, packets generated from hs-1 and directed towards hs-2 are 106 # handled by rt-1 which applies the following SRv6 Policies: 107 # 108 # i.a) IPv6 traffic, SID List=fcff:3::e,fcff:4::e,fcff:2::d46 109 # ii.a) IPv4 traffic, SID List=fcff:2::d46 110 # 111 # Policy (i.a) steers tunneled IPv6 traffic through SRv6 routers 112 # rt-3,rt-4,rt-2. Instead, Policy (ii.a) steers tunneled IPv4 traffic through 113 # rt-2. 114 # The H.Encaps.Red reduces the SID List (i.a) carried in SRH by removing the 115 # first SID (fcff:3::e) and pushing it into the IPv6 DA. In case of IPv4 116 # traffic, the H.Encaps.Red omits the presence of SRH at all, since the SID 117 # List (ii.a) consists of only one SID that can be stored directly in the IPv6 118 # DA. 119 # 120 # On the reverse path (i.e. from hs-2 to hs-1), rt-2 applies the following 121 # policies: 122 # 123 # i.b) IPv6 traffic, SID List=fcff:1::d46 124 # ii.b) IPv4 traffic, SID List=fcff:4::e,fcff:3::e,fcff:1::d46 125 # 126 # Policy (i.b) steers tunneled IPv6 traffic through the SRv6 router rt-1. 127 # Conversely, Policy (ii.b) steers tunneled IPv4 traffic through SRv6 routers 128 # rt-4,rt-3,rt-1. 129 # The H.Encaps.Red omits the SRH at all in case of (i.b) by pushing the single 130 # SID (fcff::1::d46) inside the IPv6 DA. 131 # The H.Encaps.Red reduces the SID List (ii.b) in the SRH by removing the first 132 # SID (fcff:4::e) and pushing it into the IPv6 DA. 133 # 134 # In summary: 135 # hs-1->hs-2 |IPv6 DA=fcff:3::e|SRH SIDs=fcff:4::e,fcff:2::d46|IPv6|...| (i.a) 136 # hs-1->hs-2 |IPv6 DA=fcff:2::d46|IPv4|...| (ii.a) 137 # 138 # hs-2->hs-1 |IPv6 DA=fcff:1::d46|IPv6|...| (i.b) 139 # hs-2->hs-1 |IPv6 DA=fcff:4::e|SRH SIDs=fcff:3::e,fcff:1::d46|IPv4|...| (ii.b) 140 # 141 # 142 # IPv6 VPN between hs-3 and hs-4 143 # ------------------------------ 144 # 145 # Hosts hs-3 and hs-4 are connected using a dedicated IPv6 only VPN. 146 # Specifically, packets generated from hs-3 and directed towards hs-4 are 147 # handled by rt-3 which applies the following SRv6 Policy: 148 # 149 # i.c) IPv6 traffic, SID List=fcff:2::e,fcff:4::d46 150 # 151 # Policy (i.c) steers tunneled IPv6 traffic through SRv6 routers rt-2,rt-4. 152 # The H.Encaps.Red reduces the SID List (i.c) carried in SRH by pushing the 153 # first SID (fcff:2::e) in the IPv6 DA. 154 # 155 # On the reverse path (i.e. from hs-4 to hs-3) the router rt-4 applies the 156 # following SRv6 Policy: 157 # 158 # i.d) IPv6 traffic, SID List=fcff:1::e,fcff:3::d46. 159 # 160 # Policy (i.d) steers tunneled IPv6 traffic through SRv6 routers rt-1,rt-3. 161 # The H.Encaps.Red reduces the SID List (i.d) carried in SRH by pushing the 162 # first SID (fcff:1::e) in the IPv6 DA. 163 # 164 # In summary: 165 # hs-3->hs-4 |IPv6 DA=fcff:2::e|SRH SIDs=fcff:4::d46|IPv6|...| (i.c) 166 # hs-4->hs-3 |IPv6 DA=fcff:1::e|SRH SIDs=fcff:3::d46|IPv6|...| (i.d) 167 # 168 169 # Kselftest framework requirement - SKIP code is 4. 170 readonly ksft_skip=4 171 172 readonly RDMSUFF="$(mktemp -u XXXXXXXX)" 173 readonly VRF_TID=100 174 readonly VRF_DEVNAME="vrf-${VRF_TID}" 175 readonly RT2HS_DEVNAME="veth-t${VRF_TID}" 176 readonly LOCALSID_TABLE_ID=90 177 readonly IPv6_RT_NETWORK=fcf0:0 178 readonly IPv6_HS_NETWORK=cafe 179 readonly IPv4_HS_NETWORK=10.0.0 180 readonly VPN_LOCATOR_SERVICE=fcff 181 readonly END_FUNC=000e 182 readonly DT46_FUNC=0d46 183 184 PING_TIMEOUT_SEC=4 185 PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no} 186 187 # IDs of routers and hosts are initialized during the setup of the testing 188 # network 189 ROUTERS='' 190 HOSTS='' 191 192 SETUP_ERR=1 193 194 ret=${ksft_skip} 195 nsuccess=0 196 nfail=0 197 198 log_test() 199 { 200 local rc="$1" 201 local expected="$2" 202 local msg="$3" 203 204 if [ "${rc}" -eq "${expected}" ]; then 205 nsuccess=$((nsuccess+1)) 206 printf "\n TEST: %-60s [ OK ]\n" "${msg}" 207 else 208 ret=1 209 nfail=$((nfail+1)) 210 printf "\n TEST: %-60s [FAIL]\n" "${msg}" 211 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then 212 echo 213 echo "hit enter to continue, 'q' to quit" 214 read a 215 [ "$a" = "q" ] && exit 1 216 fi 217 fi 218 } 219 220 print_log_test_results() 221 { 222 printf "\nTests passed: %3d\n" "${nsuccess}" 223 printf "Tests failed: %3d\n" "${nfail}" 224 225 # when a test fails, the value of 'ret' is set to 1 (error code). 226 # Conversely, when all tests are passed successfully, the 'ret' value 227 # is set to 0 (success code). 228 if [ "${ret}" -ne 1 ]; then 229 ret=0 230 fi 231 } 232 233 log_section() 234 { 235 echo 236 echo "################################################################################" 237 echo "TEST SECTION: $*" 238 echo "################################################################################" 239 } 240 241 test_command_or_ksft_skip() 242 { 243 local cmd="$1" 244 245 if [ ! -x "$(command -v "${cmd}")" ]; then 246 echo "SKIP: Could not run test without \"${cmd}\" tool"; 247 exit "${ksft_skip}" 248 fi 249 } 250 251 get_nodename() 252 { 253 local name="$1" 254 255 echo "${name}-${RDMSUFF}" 256 } 257 258 get_rtname() 259 { 260 local rtid="$1" 261 262 get_nodename "rt-${rtid}" 263 } 264 265 get_hsname() 266 { 267 local hsid="$1" 268 269 get_nodename "hs-${hsid}" 270 } 271 272 __create_namespace() 273 { 274 local name="$1" 275 276 ip netns add "${name}" 277 } 278 279 create_router() 280 { 281 local rtid="$1" 282 local nsname 283 284 nsname="$(get_rtname "${rtid}")" 285 286 __create_namespace "${nsname}" 287 } 288 289 create_host() 290 { 291 local hsid="$1" 292 local nsname 293 294 nsname="$(get_hsname "${hsid}")" 295 296 __create_namespace "${nsname}" 297 } 298 299 cleanup() 300 { 301 local nsname 302 local i 303 304 # destroy routers 305 for i in ${ROUTERS}; do 306 nsname="$(get_rtname "${i}")" 307 308 ip netns del "${nsname}" &>/dev/null || true 309 done 310 311 # destroy hosts 312 for i in ${HOSTS}; do 313 nsname="$(get_hsname "${i}")" 314 315 ip netns del "${nsname}" &>/dev/null || true 316 done 317 318 # check whether the setup phase was completed successfully or not. In 319 # case of an error during the setup phase of the testing environment, 320 # the selftest is considered as "skipped". 321 if [ "${SETUP_ERR}" -ne 0 ]; then 322 echo "SKIP: Setting up the testing environment failed" 323 exit "${ksft_skip}" 324 fi 325 326 exit "${ret}" 327 } 328 329 add_link_rt_pairs() 330 { 331 local rt="$1" 332 local rt_neighs="$2" 333 local neigh 334 local nsname 335 local neigh_nsname 336 337 nsname="$(get_rtname "${rt}")" 338 339 for neigh in ${rt_neighs}; do 340 neigh_nsname="$(get_rtname "${neigh}")" 341 342 ip link add "veth-rt-${rt}-${neigh}" netns "${nsname}" \ 343 type veth peer name "veth-rt-${neigh}-${rt}" \ 344 netns "${neigh_nsname}" 345 done 346 } 347 348 get_network_prefix() 349 { 350 local rt="$1" 351 local neigh="$2" 352 local p="${rt}" 353 local q="${neigh}" 354 355 if [ "${p}" -gt "${q}" ]; then 356 p="${q}"; q="${rt}" 357 fi 358 359 echo "${IPv6_RT_NETWORK}:${p}:${q}" 360 } 361 362 # Setup the basic networking for the routers 363 setup_rt_networking() 364 { 365 local rt="$1" 366 local rt_neighs="$2" 367 local nsname 368 local net_prefix 369 local devname 370 local neigh 371 372 nsname="$(get_rtname "${rt}")" 373 374 for neigh in ${rt_neighs}; do 375 devname="veth-rt-${rt}-${neigh}" 376 377 net_prefix="$(get_network_prefix "${rt}" "${neigh}")" 378 379 ip -netns "${nsname}" addr \ 380 add "${net_prefix}::${rt}/64" dev "${devname}" nodad 381 382 ip -netns "${nsname}" link set "${devname}" up 383 done 384 385 ip -netns "${nsname}" link set lo up 386 387 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0 388 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0 389 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.forwarding=1 390 391 ip netns exec "${nsname}" sysctl -wq net.ipv4.conf.all.rp_filter=0 392 ip netns exec "${nsname}" sysctl -wq net.ipv4.conf.default.rp_filter=0 393 ip netns exec "${nsname}" sysctl -wq net.ipv4.ip_forward=1 394 } 395 396 # Setup local SIDs for an SRv6 router 397 setup_rt_local_sids() 398 { 399 local rt="$1" 400 local rt_neighs="$2" 401 local net_prefix 402 local devname 403 local nsname 404 local neigh 405 406 nsname="$(get_rtname "${rt}")" 407 408 for neigh in ${rt_neighs}; do 409 devname="veth-rt-${rt}-${neigh}" 410 411 net_prefix="$(get_network_prefix "${rt}" "${neigh}")" 412 413 # set underlay network routes for SIDs reachability 414 ip -netns "${nsname}" -6 route \ 415 add "${VPN_LOCATOR_SERVICE}:${neigh}::/32" \ 416 table "${LOCALSID_TABLE_ID}" \ 417 via "${net_prefix}::${neigh}" dev "${devname}" 418 done 419 420 # Local End behavior (note that "dev" is dummy and the VRF is chosen 421 # for the sake of simplicity). 422 ip -netns "${nsname}" -6 route \ 423 add "${VPN_LOCATOR_SERVICE}:${rt}::${END_FUNC}" \ 424 table "${LOCALSID_TABLE_ID}" \ 425 encap seg6local action End dev "${VRF_DEVNAME}" 426 427 # Local End.DT46 behavior 428 ip -netns "${nsname}" -6 route \ 429 add "${VPN_LOCATOR_SERVICE}:${rt}::${DT46_FUNC}" \ 430 table "${LOCALSID_TABLE_ID}" \ 431 encap seg6local action End.DT46 vrftable "${VRF_TID}" \ 432 dev "${VRF_DEVNAME}" 433 434 # all SIDs for VPNs start with a common locator. Routes and SRv6 435 # Endpoint behavior instaces are grouped together in the 'localsid' 436 # table. 437 ip -netns "${nsname}" -6 rule \ 438 add to "${VPN_LOCATOR_SERVICE}::/16" \ 439 lookup "${LOCALSID_TABLE_ID}" prio 999 440 441 # set default routes to unreachable for both ipv4 and ipv6 442 ip -netns "${nsname}" -6 route \ 443 add unreachable default metric 4278198272 \ 444 vrf "${VRF_DEVNAME}" 445 446 ip -netns "${nsname}" -4 route \ 447 add unreachable default metric 4278198272 \ 448 vrf "${VRF_DEVNAME}" 449 } 450 451 # build and install the SRv6 policy into the ingress SRv6 router. 452 # args: 453 # $1 - destination host (i.e. cafe::x host) 454 # $2 - SRv6 router configured for enforcing the SRv6 Policy 455 # $3 - SRv6 routers configured for steering traffic (End behaviors) 456 # $4 - SRv6 router configured for removing the SRv6 Policy (router connected 457 # to the destination host) 458 # $5 - encap mode (full or red) 459 # $6 - traffic type (IPv6 or IPv4) 460 __setup_rt_policy() 461 { 462 local dst="$1" 463 local encap_rt="$2" 464 local end_rts="$3" 465 local dec_rt="$4" 466 local mode="$5" 467 local traffic="$6" 468 local nsname 469 local policy='' 470 local n 471 472 nsname="$(get_rtname "${encap_rt}")" 473 474 for n in ${end_rts}; do 475 policy="${policy}${VPN_LOCATOR_SERVICE}:${n}::${END_FUNC}," 476 done 477 478 policy="${policy}${VPN_LOCATOR_SERVICE}:${dec_rt}::${DT46_FUNC}" 479 480 # add SRv6 policy to incoming traffic sent by connected hosts 481 if [ "${traffic}" -eq 6 ]; then 482 ip -netns "${nsname}" -6 route \ 483 add "${IPv6_HS_NETWORK}::${dst}" vrf "${VRF_DEVNAME}" \ 484 encap seg6 mode "${mode}" segs "${policy}" \ 485 dev "${VRF_DEVNAME}" 486 487 ip -netns "${nsname}" -6 neigh \ 488 add proxy "${IPv6_HS_NETWORK}::${dst}" \ 489 dev "${RT2HS_DEVNAME}" 490 else 491 # "dev" must be different from the one where the packet is 492 # received, otherwise the proxy arp does not work. 493 ip -netns "${nsname}" -4 route \ 494 add "${IPv4_HS_NETWORK}.${dst}" vrf "${VRF_DEVNAME}" \ 495 encap seg6 mode "${mode}" segs "${policy}" \ 496 dev "${VRF_DEVNAME}" 497 fi 498 } 499 500 # see __setup_rt_policy 501 setup_rt_policy_ipv6() 502 { 503 __setup_rt_policy "$1" "$2" "$3" "$4" "$5" 6 504 } 505 506 #see __setup_rt_policy 507 setup_rt_policy_ipv4() 508 { 509 __setup_rt_policy "$1" "$2" "$3" "$4" "$5" 4 510 } 511 512 setup_hs() 513 { 514 local hs="$1" 515 local rt="$2" 516 local hsname 517 local rtname 518 519 hsname="$(get_hsname "${hs}")" 520 rtname="$(get_rtname "${rt}")" 521 522 ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0 523 ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0 524 525 ip -netns "${hsname}" link add veth0 type veth \ 526 peer name "${RT2HS_DEVNAME}" netns "${rtname}" 527 528 ip -netns "${hsname}" addr \ 529 add "${IPv6_HS_NETWORK}::${hs}/64" dev veth0 nodad 530 ip -netns "${hsname}" addr add "${IPv4_HS_NETWORK}.${hs}/24" dev veth0 531 532 ip -netns "${hsname}" link set veth0 up 533 ip -netns "${hsname}" link set lo up 534 535 # configure the VRF on the router which is directly connected to the 536 # source host. 537 ip -netns "${rtname}" link \ 538 add "${VRF_DEVNAME}" type vrf table "${VRF_TID}" 539 ip -netns "${rtname}" link set "${VRF_DEVNAME}" up 540 541 # enslave the veth interface connecting the router with the host to the 542 # VRF in the access router 543 ip -netns "${rtname}" link \ 544 set "${RT2HS_DEVNAME}" master "${VRF_DEVNAME}" 545 546 ip -netns "${rtname}" addr \ 547 add "${IPv6_HS_NETWORK}::254/64" dev "${RT2HS_DEVNAME}" nodad 548 ip -netns "${rtname}" addr \ 549 add "${IPv4_HS_NETWORK}.254/24" dev "${RT2HS_DEVNAME}" 550 551 ip -netns "${rtname}" link set "${RT2HS_DEVNAME}" up 552 553 ip netns exec "${rtname}" \ 554 sysctl -wq net.ipv6.conf."${RT2HS_DEVNAME}".proxy_ndp=1 555 ip netns exec "${rtname}" \ 556 sysctl -wq net.ipv4.conf."${RT2HS_DEVNAME}".proxy_arp=1 557 558 # disable the rp_filter otherwise the kernel gets confused about how 559 # to route decap ipv4 packets. 560 ip netns exec "${rtname}" \ 561 sysctl -wq net.ipv4.conf."${RT2HS_DEVNAME}".rp_filter=0 562 563 ip netns exec "${rtname}" sh -c "echo 1 > /proc/sys/net/vrf/strict_mode" 564 } 565 566 setup() 567 { 568 local i 569 570 # create routers 571 ROUTERS="1 2 3 4"; readonly ROUTERS 572 for i in ${ROUTERS}; do 573 create_router "${i}" 574 done 575 576 # create hosts 577 HOSTS="1 2 3 4"; readonly HOSTS 578 for i in ${HOSTS}; do 579 create_host "${i}" 580 done 581 582 # set up the links for connecting routers 583 add_link_rt_pairs 1 "2 3 4" 584 add_link_rt_pairs 2 "3 4" 585 add_link_rt_pairs 3 "4" 586 587 # set up the basic connectivity of routers and routes required for 588 # reachability of SIDs. 589 setup_rt_networking 1 "2 3 4" 590 setup_rt_networking 2 "1 3 4" 591 setup_rt_networking 3 "1 2 4" 592 setup_rt_networking 4 "1 2 3" 593 594 # set up the hosts connected to routers 595 setup_hs 1 1 596 setup_hs 2 2 597 setup_hs 3 3 598 setup_hs 4 4 599 600 # set up default SRv6 Endpoints (i.e. SRv6 End and SRv6 End.DT46) 601 setup_rt_local_sids 1 "2 3 4" 602 setup_rt_local_sids 2 "1 3 4" 603 setup_rt_local_sids 3 "1 2 4" 604 setup_rt_local_sids 4 "1 2 3" 605 606 # set up SRv6 policies 607 608 # create an IPv6 VPN between hosts hs-1 and hs-2. 609 # the network path between hs-1 and hs-2 traverses several routers 610 # depending on the direction of traffic. 611 # 612 # Direction hs-1 -> hs-2 (H.Encaps.Red) 613 # - rt-3,rt-4 (SRv6 End behaviors) 614 # - rt-2 (SRv6 End.DT46 behavior) 615 # 616 # Direction hs-2 -> hs-1 (H.Encaps.Red) 617 # - rt-1 (SRv6 End.DT46 behavior) 618 setup_rt_policy_ipv6 2 1 "3 4" 2 encap.red 619 setup_rt_policy_ipv6 1 2 "" 1 encap.red 620 621 # create an IPv4 VPN between hosts hs-1 and hs-2 622 # the network path between hs-1 and hs-2 traverses several routers 623 # depending on the direction of traffic. 624 # 625 # Direction hs-1 -> hs-2 (H.Encaps.Red) 626 # - rt-2 (SRv6 End.DT46 behavior) 627 # 628 # Direction hs-2 -> hs-1 (H.Encaps.Red) 629 # - rt-4,rt-3 (SRv6 End behaviors) 630 # - rt-1 (SRv6 End.DT46 behavior) 631 setup_rt_policy_ipv4 2 1 "" 2 encap.red 632 setup_rt_policy_ipv4 1 2 "4 3" 1 encap.red 633 634 # create an IPv6 VPN between hosts hs-3 and hs-4 635 # the network path between hs-3 and hs-4 traverses several routers 636 # depending on the direction of traffic. 637 # 638 # Direction hs-3 -> hs-4 (H.Encaps.Red) 639 # - rt-2 (SRv6 End Behavior) 640 # - rt-4 (SRv6 End.DT46 behavior) 641 # 642 # Direction hs-4 -> hs-3 (H.Encaps.Red) 643 # - rt-1 (SRv6 End behavior) 644 # - rt-3 (SRv6 End.DT46 behavior) 645 setup_rt_policy_ipv6 4 3 "2" 4 encap.red 646 setup_rt_policy_ipv6 3 4 "1" 3 encap.red 647 648 # testing environment was set up successfully 649 SETUP_ERR=0 650 } 651 652 check_rt_connectivity() 653 { 654 local rtsrc="$1" 655 local rtdst="$2" 656 local prefix 657 local rtsrc_nsname 658 659 rtsrc_nsname="$(get_rtname "${rtsrc}")" 660 661 prefix="$(get_network_prefix "${rtsrc}" "${rtdst}")" 662 663 ip netns exec "${rtsrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \ 664 "${prefix}::${rtdst}" >/dev/null 2>&1 665 } 666 667 check_and_log_rt_connectivity() 668 { 669 local rtsrc="$1" 670 local rtdst="$2" 671 672 check_rt_connectivity "${rtsrc}" "${rtdst}" 673 log_test $? 0 "Routers connectivity: rt-${rtsrc} -> rt-${rtdst}" 674 } 675 676 check_hs_ipv6_connectivity() 677 { 678 local hssrc="$1" 679 local hsdst="$2" 680 local hssrc_nsname 681 682 hssrc_nsname="$(get_hsname "${hssrc}")" 683 684 ip netns exec "${hssrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \ 685 "${IPv6_HS_NETWORK}::${hsdst}" >/dev/null 2>&1 686 } 687 688 check_hs_ipv4_connectivity() 689 { 690 local hssrc="$1" 691 local hsdst="$2" 692 local hssrc_nsname 693 694 hssrc_nsname="$(get_hsname "${hssrc}")" 695 696 ip netns exec "${hssrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \ 697 "${IPv4_HS_NETWORK}.${hsdst}" >/dev/null 2>&1 698 } 699 700 check_and_log_hs2gw_connectivity() 701 { 702 local hssrc="$1" 703 704 check_hs_ipv6_connectivity "${hssrc}" 254 705 log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> gw" 706 707 check_hs_ipv4_connectivity "${hssrc}" 254 708 log_test $? 0 "IPv4 Hosts connectivity: hs-${hssrc} -> gw" 709 } 710 711 check_and_log_hs_ipv6_connectivity() 712 { 713 local hssrc="$1" 714 local hsdst="$2" 715 716 check_hs_ipv6_connectivity "${hssrc}" "${hsdst}" 717 log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> hs-${hsdst}" 718 } 719 720 check_and_log_hs_ipv4_connectivity() 721 { 722 local hssrc="$1" 723 local hsdst="$2" 724 725 check_hs_ipv4_connectivity "${hssrc}" "${hsdst}" 726 log_test $? 0 "IPv4 Hosts connectivity: hs-${hssrc} -> hs-${hsdst}" 727 } 728 729 check_and_log_hs_connectivity() 730 { 731 local hssrc="$1" 732 local hsdst="$2" 733 734 check_and_log_hs_ipv4_connectivity "${hssrc}" "${hsdst}" 735 check_and_log_hs_ipv6_connectivity "${hssrc}" "${hsdst}" 736 } 737 738 check_and_log_hs_ipv6_isolation() 739 { 740 local hssrc="$1" 741 local hsdst="$2" 742 743 # in this case, the connectivity test must fail 744 check_hs_ipv6_connectivity "${hssrc}" "${hsdst}" 745 log_test $? 1 "IPv6 Hosts isolation: hs-${hssrc} -X-> hs-${hsdst}" 746 } 747 748 check_and_log_hs_ipv4_isolation() 749 { 750 local hssrc="$1" 751 local hsdst="$2" 752 753 # in this case, the connectivity test must fail 754 check_hs_ipv4_connectivity "${hssrc}" "${hsdst}" 755 log_test $? 1 "IPv4 Hosts isolation: hs-${hssrc} -X-> hs-${hsdst}" 756 } 757 758 check_and_log_hs_isolation() 759 { 760 local hssrc="$1" 761 local hsdst="$2" 762 763 check_and_log_hs_ipv6_isolation "${hssrc}" "${hsdst}" 764 check_and_log_hs_ipv4_isolation "${hssrc}" "${hsdst}" 765 } 766 767 router_tests() 768 { 769 local i 770 local j 771 772 log_section "IPv6 routers connectivity test" 773 774 for i in ${ROUTERS}; do 775 for j in ${ROUTERS}; do 776 if [ "${i}" -eq "${j}" ]; then 777 continue 778 fi 779 780 check_and_log_rt_connectivity "${i}" "${j}" 781 done 782 done 783 } 784 785 host2gateway_tests() 786 { 787 local hs 788 789 log_section "IPv4/IPv6 connectivity test among hosts and gateways" 790 791 for hs in ${HOSTS}; do 792 check_and_log_hs2gw_connectivity "${hs}" 793 done 794 } 795 796 host_vpn_tests() 797 { 798 log_section "SRv6 VPN connectivity test hosts (h1 <-> h2, IPv4/IPv6)" 799 800 check_and_log_hs_connectivity 1 2 801 check_and_log_hs_connectivity 2 1 802 803 log_section "SRv6 VPN connectivity test hosts (h3 <-> h4, IPv6 only)" 804 805 check_and_log_hs_ipv6_connectivity 3 4 806 check_and_log_hs_ipv6_connectivity 4 3 807 } 808 809 host_vpn_isolation_tests() 810 { 811 local l1="1 2" 812 local l2="3 4" 813 local tmp 814 local i 815 local j 816 local k 817 818 log_section "SRv6 VPN isolation test among hosts" 819 820 for k in 0 1; do 821 for i in ${l1}; do 822 for j in ${l2}; do 823 check_and_log_hs_isolation "${i}" "${j}" 824 done 825 done 826 827 # let us test the reverse path 828 tmp="${l1}"; l1="${l2}"; l2="${tmp}" 829 done 830 831 log_section "SRv6 VPN isolation test among hosts (h2 <-> h4, IPv4 only)" 832 833 check_and_log_hs_ipv4_isolation 2 4 834 check_and_log_hs_ipv4_isolation 4 2 835 } 836 837 test_iproute2_supp_or_ksft_skip() 838 { 839 if ! ip route help 2>&1 | grep -qo "encap.red"; then 840 echo "SKIP: Missing SRv6 encap.red support in iproute2" 841 exit "${ksft_skip}" 842 fi 843 } 844 845 test_vrf_or_ksft_skip() 846 { 847 modprobe vrf &>/dev/null || true 848 if [ ! -e /proc/sys/net/vrf/strict_mode ]; then 849 echo "SKIP: vrf sysctl does not exist" 850 exit "${ksft_skip}" 851 fi 852 } 853 854 if [ "$(id -u)" -ne 0 ]; then 855 echo "SKIP: Need root privileges" 856 exit "${ksft_skip}" 857 fi 858 859 # required programs to carry out this selftest 860 test_command_or_ksft_skip ip 861 test_command_or_ksft_skip ping 862 test_command_or_ksft_skip sysctl 863 test_command_or_ksft_skip grep 864 865 test_iproute2_supp_or_ksft_skip 866 test_vrf_or_ksft_skip 867 868 set -e 869 trap cleanup EXIT 870 871 setup 872 set +e 873 874 router_tests 875 host2gateway_tests 876 host_vpn_tests 877 host_vpn_isolation_tests 878 879 print_log_test_results
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.