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 169source lib.sh 170 171readonly VRF_TID=100 172readonly VRF_DEVNAME="vrf-${VRF_TID}" 173readonly RT2HS_DEVNAME="veth-t${VRF_TID}" 174readonly LOCALSID_TABLE_ID=90 175readonly IPv6_RT_NETWORK=fcf0:0 176readonly IPv6_HS_NETWORK=cafe 177readonly IPv4_HS_NETWORK=10.0.0 178readonly VPN_LOCATOR_SERVICE=fcff 179readonly END_FUNC=000e 180readonly DT46_FUNC=0d46 181 182PING_TIMEOUT_SEC=4 183PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no} 184 185# IDs of routers and hosts are initialized during the setup of the testing 186# network 187ROUTERS='' 188HOSTS='' 189 190SETUP_ERR=1 191 192ret=${ksft_skip} 193nsuccess=0 194nfail=0 195 196log_test() 197{ 198 local rc="$1" 199 local expected="$2" 200 local msg="$3" 201 202 if [ "${rc}" -eq "${expected}" ]; then 203 nsuccess=$((nsuccess+1)) 204 printf "\n TEST: %-60s [ OK ]\n" "${msg}" 205 else 206 ret=1 207 nfail=$((nfail+1)) 208 printf "\n TEST: %-60s [FAIL]\n" "${msg}" 209 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then 210 echo 211 echo "hit enter to continue, 'q' to quit" 212 read a 213 [ "$a" = "q" ] && exit 1 214 fi 215 fi 216} 217 218print_log_test_results() 219{ 220 printf "\nTests passed: %3d\n" "${nsuccess}" 221 printf "Tests failed: %3d\n" "${nfail}" 222 223 # when a test fails, the value of 'ret' is set to 1 (error code). 224 # Conversely, when all tests are passed successfully, the 'ret' value 225 # is set to 0 (success code). 226 if [ "${ret}" -ne 1 ]; then 227 ret=0 228 fi 229} 230 231log_section() 232{ 233 echo 234 echo "################################################################################" 235 echo "TEST SECTION: $*" 236 echo "################################################################################" 237} 238 239test_command_or_ksft_skip() 240{ 241 local cmd="$1" 242 243 if [ ! -x "$(command -v "${cmd}")" ]; then 244 echo "SKIP: Could not run test without \"${cmd}\" tool"; 245 exit "${ksft_skip}" 246 fi 247} 248 249get_rtname() 250{ 251 local rtid="$1" 252 253 echo "rt_${rtid}" 254} 255 256get_hsname() 257{ 258 local hsid="$1" 259 260 echo "hs_${hsid}" 261} 262 263create_router() 264{ 265 local rtid="$1" 266 local nsname 267 268 nsname="$(get_rtname "${rtid}")" 269 setup_ns "${nsname}" 270} 271 272create_host() 273{ 274 local hsid="$1" 275 local nsname 276 277 nsname="$(get_hsname "${hsid}")" 278 setup_ns "${nsname}" 279} 280 281cleanup() 282{ 283 cleanup_all_ns 284 # check whether the setup phase was completed successfully or not. In 285 # case of an error during the setup phase of the testing environment, 286 # the selftest is considered as "skipped". 287 if [ "${SETUP_ERR}" -ne 0 ]; then 288 echo "SKIP: Setting up the testing environment failed" 289 exit "${ksft_skip}" 290 fi 291 292 exit "${ret}" 293} 294 295add_link_rt_pairs() 296{ 297 local rt="$1" 298 local rt_neighs="$2" 299 local neigh 300 local nsname 301 local neigh_nsname 302 303 eval nsname=\${$(get_rtname "${rt}")} 304 305 for neigh in ${rt_neighs}; do 306 eval neigh_nsname=\${$(get_rtname "${neigh}")} 307 308 ip link add "veth-rt-${rt}-${neigh}" netns "${nsname}" \ 309 type veth peer name "veth-rt-${neigh}-${rt}" \ 310 netns "${neigh_nsname}" 311 done 312} 313 314get_network_prefix() 315{ 316 local rt="$1" 317 local neigh="$2" 318 local p="${rt}" 319 local q="${neigh}" 320 321 if [ "${p}" -gt "${q}" ]; then 322 p="${q}"; q="${rt}" 323 fi 324 325 echo "${IPv6_RT_NETWORK}:${p}:${q}" 326} 327 328# Setup the basic networking for the routers 329setup_rt_networking() 330{ 331 local rt="$1" 332 local rt_neighs="$2" 333 local nsname 334 local net_prefix 335 local devname 336 local neigh 337 338 eval nsname=\${$(get_rtname "${rt}")} 339 340 for neigh in ${rt_neighs}; do 341 devname="veth-rt-${rt}-${neigh}" 342 343 net_prefix="$(get_network_prefix "${rt}" "${neigh}")" 344 345 ip -netns "${nsname}" addr \ 346 add "${net_prefix}::${rt}/64" dev "${devname}" nodad 347 348 ip -netns "${nsname}" link set "${devname}" up 349 done 350 351 ip -netns "${nsname}" link set lo up 352 353 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0 354 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0 355 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.forwarding=1 356 ip netns exec "${nsname}" sysctl -wq net.ipv4.ip_forward=1 357} 358 359# Setup local SIDs for an SRv6 router 360setup_rt_local_sids() 361{ 362 local rt="$1" 363 local rt_neighs="$2" 364 local net_prefix 365 local devname 366 local nsname 367 local neigh 368 369 eval nsname=\${$(get_rtname "${rt}")} 370 371 for neigh in ${rt_neighs}; do 372 devname="veth-rt-${rt}-${neigh}" 373 374 net_prefix="$(get_network_prefix "${rt}" "${neigh}")" 375 376 # set underlay network routes for SIDs reachability 377 ip -netns "${nsname}" -6 route \ 378 add "${VPN_LOCATOR_SERVICE}:${neigh}::/32" \ 379 table "${LOCALSID_TABLE_ID}" \ 380 via "${net_prefix}::${neigh}" dev "${devname}" 381 done 382 383 # Local End behavior (note that "dev" is dummy and the VRF is chosen 384 # for the sake of simplicity). 385 ip -netns "${nsname}" -6 route \ 386 add "${VPN_LOCATOR_SERVICE}:${rt}::${END_FUNC}" \ 387 table "${LOCALSID_TABLE_ID}" \ 388 encap seg6local action End dev "${VRF_DEVNAME}" 389 390 # Local End.DT46 behavior 391 ip -netns "${nsname}" -6 route \ 392 add "${VPN_LOCATOR_SERVICE}:${rt}::${DT46_FUNC}" \ 393 table "${LOCALSID_TABLE_ID}" \ 394 encap seg6local action End.DT46 vrftable "${VRF_TID}" \ 395 dev "${VRF_DEVNAME}" 396 397 # all SIDs for VPNs start with a common locator. Routes and SRv6 398 # Endpoint behavior instances are grouped together in the 'localsid' 399 # table. 400 ip -netns "${nsname}" -6 rule \ 401 add to "${VPN_LOCATOR_SERVICE}::/16" \ 402 lookup "${LOCALSID_TABLE_ID}" prio 999 403 404 # set default routes to unreachable for both ipv4 and ipv6 405 ip -netns "${nsname}" -6 route \ 406 add unreachable default metric 4278198272 \ 407 vrf "${VRF_DEVNAME}" 408 409 ip -netns "${nsname}" -4 route \ 410 add unreachable default metric 4278198272 \ 411 vrf "${VRF_DEVNAME}" 412} 413 414# build and install the SRv6 policy into the ingress SRv6 router. 415# args: 416# $1 - destination host (i.e. cafe::x host) 417# $2 - SRv6 router configured for enforcing the SRv6 Policy 418# $3 - SRv6 routers configured for steering traffic (End behaviors) 419# $4 - SRv6 router configured for removing the SRv6 Policy (router connected 420# to the destination host) 421# $5 - encap mode (full or red) 422# $6 - traffic type (IPv6 or IPv4) 423__setup_rt_policy() 424{ 425 local dst="$1" 426 local encap_rt="$2" 427 local end_rts="$3" 428 local dec_rt="$4" 429 local mode="$5" 430 local traffic="$6" 431 local nsname 432 local policy='' 433 local n 434 435 eval nsname=\${$(get_rtname "${encap_rt}")} 436 437 for n in ${end_rts}; do 438 policy="${policy}${VPN_LOCATOR_SERVICE}:${n}::${END_FUNC}," 439 done 440 441 policy="${policy}${VPN_LOCATOR_SERVICE}:${dec_rt}::${DT46_FUNC}" 442 443 # add SRv6 policy to incoming traffic sent by connected hosts 444 if [ "${traffic}" -eq 6 ]; then 445 ip -netns "${nsname}" -6 route \ 446 add "${IPv6_HS_NETWORK}::${dst}" vrf "${VRF_DEVNAME}" \ 447 encap seg6 mode "${mode}" segs "${policy}" \ 448 dev "${VRF_DEVNAME}" 449 450 ip -netns "${nsname}" -6 neigh \ 451 add proxy "${IPv6_HS_NETWORK}::${dst}" \ 452 dev "${RT2HS_DEVNAME}" 453 else 454 # "dev" must be different from the one where the packet is 455 # received, otherwise the proxy arp does not work. 456 ip -netns "${nsname}" -4 route \ 457 add "${IPv4_HS_NETWORK}.${dst}" vrf "${VRF_DEVNAME}" \ 458 encap seg6 mode "${mode}" segs "${policy}" \ 459 dev "${VRF_DEVNAME}" 460 fi 461} 462 463# see __setup_rt_policy 464setup_rt_policy_ipv6() 465{ 466 __setup_rt_policy "$1" "$2" "$3" "$4" "$5" 6 467} 468 469#see __setup_rt_policy 470setup_rt_policy_ipv4() 471{ 472 __setup_rt_policy "$1" "$2" "$3" "$4" "$5" 4 473} 474 475setup_hs() 476{ 477 local hs="$1" 478 local rt="$2" 479 local hsname 480 local rtname 481 482 eval hsname=\${$(get_hsname "${hs}")} 483 eval rtname=\${$(get_rtname "${rt}")} 484 485 ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0 486 ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0 487 488 ip -netns "${hsname}" link add veth0 type veth \ 489 peer name "${RT2HS_DEVNAME}" netns "${rtname}" 490 491 ip -netns "${hsname}" addr \ 492 add "${IPv6_HS_NETWORK}::${hs}/64" dev veth0 nodad 493 ip -netns "${hsname}" addr add "${IPv4_HS_NETWORK}.${hs}/24" dev veth0 494 495 ip -netns "${hsname}" link set veth0 up 496 ip -netns "${hsname}" link set lo up 497 498 # configure the VRF on the router which is directly connected to the 499 # source host. 500 ip -netns "${rtname}" link \ 501 add "${VRF_DEVNAME}" type vrf table "${VRF_TID}" 502 ip -netns "${rtname}" link set "${VRF_DEVNAME}" up 503 504 # enslave the veth interface connecting the router with the host to the 505 # VRF in the access router 506 ip -netns "${rtname}" link \ 507 set "${RT2HS_DEVNAME}" master "${VRF_DEVNAME}" 508 509 ip -netns "${rtname}" addr \ 510 add "${IPv6_HS_NETWORK}::254/64" dev "${RT2HS_DEVNAME}" nodad 511 ip -netns "${rtname}" addr \ 512 add "${IPv4_HS_NETWORK}.254/24" dev "${RT2HS_DEVNAME}" 513 514 ip -netns "${rtname}" link set "${RT2HS_DEVNAME}" up 515 516 ip netns exec "${rtname}" \ 517 sysctl -wq net.ipv6.conf."${RT2HS_DEVNAME}".proxy_ndp=1 518 ip netns exec "${rtname}" \ 519 sysctl -wq net.ipv4.conf."${RT2HS_DEVNAME}".proxy_arp=1 520 521 ip netns exec "${rtname}" sh -c "echo 1 > /proc/sys/net/vrf/strict_mode" 522} 523 524setup() 525{ 526 local i 527 528 # create routers 529 ROUTERS="1 2 3 4"; readonly ROUTERS 530 for i in ${ROUTERS}; do 531 create_router "${i}" 532 done 533 534 # create hosts 535 HOSTS="1 2 3 4"; readonly HOSTS 536 for i in ${HOSTS}; do 537 create_host "${i}" 538 done 539 540 # set up the links for connecting routers 541 add_link_rt_pairs 1 "2 3 4" 542 add_link_rt_pairs 2 "3 4" 543 add_link_rt_pairs 3 "4" 544 545 # set up the basic connectivity of routers and routes required for 546 # reachability of SIDs. 547 setup_rt_networking 1 "2 3 4" 548 setup_rt_networking 2 "1 3 4" 549 setup_rt_networking 3 "1 2 4" 550 setup_rt_networking 4 "1 2 3" 551 552 # set up the hosts connected to routers 553 setup_hs 1 1 554 setup_hs 2 2 555 setup_hs 3 3 556 setup_hs 4 4 557 558 # set up default SRv6 Endpoints (i.e. SRv6 End and SRv6 End.DT46) 559 setup_rt_local_sids 1 "2 3 4" 560 setup_rt_local_sids 2 "1 3 4" 561 setup_rt_local_sids 3 "1 2 4" 562 setup_rt_local_sids 4 "1 2 3" 563 564 # set up SRv6 policies 565 566 # create an IPv6 VPN between hosts hs-1 and hs-2. 567 # the network path between hs-1 and hs-2 traverses several routers 568 # depending on the direction of traffic. 569 # 570 # Direction hs-1 -> hs-2 (H.Encaps.Red) 571 # - rt-3,rt-4 (SRv6 End behaviors) 572 # - rt-2 (SRv6 End.DT46 behavior) 573 # 574 # Direction hs-2 -> hs-1 (H.Encaps.Red) 575 # - rt-1 (SRv6 End.DT46 behavior) 576 setup_rt_policy_ipv6 2 1 "3 4" 2 encap.red 577 setup_rt_policy_ipv6 1 2 "" 1 encap.red 578 579 # create an IPv4 VPN between hosts hs-1 and hs-2 580 # the network path between hs-1 and hs-2 traverses several routers 581 # depending on the direction of traffic. 582 # 583 # Direction hs-1 -> hs-2 (H.Encaps.Red) 584 # - rt-2 (SRv6 End.DT46 behavior) 585 # 586 # Direction hs-2 -> hs-1 (H.Encaps.Red) 587 # - rt-4,rt-3 (SRv6 End behaviors) 588 # - rt-1 (SRv6 End.DT46 behavior) 589 setup_rt_policy_ipv4 2 1 "" 2 encap.red 590 setup_rt_policy_ipv4 1 2 "4 3" 1 encap.red 591 592 # create an IPv6 VPN between hosts hs-3 and hs-4 593 # the network path between hs-3 and hs-4 traverses several routers 594 # depending on the direction of traffic. 595 # 596 # Direction hs-3 -> hs-4 (H.Encaps.Red) 597 # - rt-2 (SRv6 End Behavior) 598 # - rt-4 (SRv6 End.DT46 behavior) 599 # 600 # Direction hs-4 -> hs-3 (H.Encaps.Red) 601 # - rt-1 (SRv6 End behavior) 602 # - rt-3 (SRv6 End.DT46 behavior) 603 setup_rt_policy_ipv6 4 3 "2" 4 encap.red 604 setup_rt_policy_ipv6 3 4 "1" 3 encap.red 605 606 # testing environment was set up successfully 607 SETUP_ERR=0 608} 609 610check_rt_connectivity() 611{ 612 local rtsrc="$1" 613 local rtdst="$2" 614 local prefix 615 local rtsrc_nsname 616 617 eval rtsrc_nsname=\${$(get_rtname "${rtsrc}")} 618 619 prefix="$(get_network_prefix "${rtsrc}" "${rtdst}")" 620 621 ip netns exec "${rtsrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \ 622 "${prefix}::${rtdst}" >/dev/null 2>&1 623} 624 625check_and_log_rt_connectivity() 626{ 627 local rtsrc="$1" 628 local rtdst="$2" 629 630 check_rt_connectivity "${rtsrc}" "${rtdst}" 631 log_test $? 0 "Routers connectivity: rt-${rtsrc} -> rt-${rtdst}" 632} 633 634check_hs_ipv6_connectivity() 635{ 636 local hssrc="$1" 637 local hsdst="$2" 638 local hssrc_nsname 639 640 eval hssrc_nsname=\${$(get_hsname "${hssrc}")} 641 642 ip netns exec "${hssrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \ 643 "${IPv6_HS_NETWORK}::${hsdst}" >/dev/null 2>&1 644} 645 646check_hs_ipv4_connectivity() 647{ 648 local hssrc="$1" 649 local hsdst="$2" 650 local hssrc_nsname 651 652 eval hssrc_nsname=\${$(get_hsname "${hssrc}")} 653 654 ip netns exec "${hssrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \ 655 "${IPv4_HS_NETWORK}.${hsdst}" >/dev/null 2>&1 656} 657 658check_and_log_hs2gw_connectivity() 659{ 660 local hssrc="$1" 661 662 check_hs_ipv6_connectivity "${hssrc}" 254 663 log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> gw" 664 665 check_hs_ipv4_connectivity "${hssrc}" 254 666 log_test $? 0 "IPv4 Hosts connectivity: hs-${hssrc} -> gw" 667} 668 669check_and_log_hs_ipv6_connectivity() 670{ 671 local hssrc="$1" 672 local hsdst="$2" 673 674 check_hs_ipv6_connectivity "${hssrc}" "${hsdst}" 675 log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> hs-${hsdst}" 676} 677 678check_and_log_hs_ipv4_connectivity() 679{ 680 local hssrc="$1" 681 local hsdst="$2" 682 683 check_hs_ipv4_connectivity "${hssrc}" "${hsdst}" 684 log_test $? 0 "IPv4 Hosts connectivity: hs-${hssrc} -> hs-${hsdst}" 685} 686 687check_and_log_hs_connectivity() 688{ 689 local hssrc="$1" 690 local hsdst="$2" 691 692 check_and_log_hs_ipv4_connectivity "${hssrc}" "${hsdst}" 693 check_and_log_hs_ipv6_connectivity "${hssrc}" "${hsdst}" 694} 695 696check_and_log_hs_ipv6_isolation() 697{ 698 local hssrc="$1" 699 local hsdst="$2" 700 701 # in this case, the connectivity test must fail 702 check_hs_ipv6_connectivity "${hssrc}" "${hsdst}" 703 log_test $? 1 "IPv6 Hosts isolation: hs-${hssrc} -X-> hs-${hsdst}" 704} 705 706check_and_log_hs_ipv4_isolation() 707{ 708 local hssrc="$1" 709 local hsdst="$2" 710 711 # in this case, the connectivity test must fail 712 check_hs_ipv4_connectivity "${hssrc}" "${hsdst}" 713 log_test $? 1 "IPv4 Hosts isolation: hs-${hssrc} -X-> hs-${hsdst}" 714} 715 716check_and_log_hs_isolation() 717{ 718 local hssrc="$1" 719 local hsdst="$2" 720 721 check_and_log_hs_ipv6_isolation "${hssrc}" "${hsdst}" 722 check_and_log_hs_ipv4_isolation "${hssrc}" "${hsdst}" 723} 724 725router_tests() 726{ 727 local i 728 local j 729 730 log_section "IPv6 routers connectivity test" 731 732 for i in ${ROUTERS}; do 733 for j in ${ROUTERS}; do 734 if [ "${i}" -eq "${j}" ]; then 735 continue 736 fi 737 738 check_and_log_rt_connectivity "${i}" "${j}" 739 done 740 done 741} 742 743host2gateway_tests() 744{ 745 local hs 746 747 log_section "IPv4/IPv6 connectivity test among hosts and gateways" 748 749 for hs in ${HOSTS}; do 750 check_and_log_hs2gw_connectivity "${hs}" 751 done 752} 753 754host_vpn_tests() 755{ 756 log_section "SRv6 VPN connectivity test hosts (h1 <-> h2, IPv4/IPv6)" 757 758 check_and_log_hs_connectivity 1 2 759 check_and_log_hs_connectivity 2 1 760 761 log_section "SRv6 VPN connectivity test hosts (h3 <-> h4, IPv6 only)" 762 763 check_and_log_hs_ipv6_connectivity 3 4 764 check_and_log_hs_ipv6_connectivity 4 3 765} 766 767host_vpn_isolation_tests() 768{ 769 local l1="1 2" 770 local l2="3 4" 771 local tmp 772 local i 773 local j 774 local k 775 776 log_section "SRv6 VPN isolation test among hosts" 777 778 for k in 0 1; do 779 for i in ${l1}; do 780 for j in ${l2}; do 781 check_and_log_hs_isolation "${i}" "${j}" 782 done 783 done 784 785 # let us test the reverse path 786 tmp="${l1}"; l1="${l2}"; l2="${tmp}" 787 done 788 789 log_section "SRv6 VPN isolation test among hosts (h2 <-> h4, IPv4 only)" 790 791 check_and_log_hs_ipv4_isolation 2 4 792 check_and_log_hs_ipv4_isolation 4 2 793} 794 795test_iproute2_supp_or_ksft_skip() 796{ 797 if ! ip route help 2>&1 | grep -qo "encap.red"; then 798 echo "SKIP: Missing SRv6 encap.red support in iproute2" 799 exit "${ksft_skip}" 800 fi 801} 802 803test_vrf_or_ksft_skip() 804{ 805 modprobe vrf &>/dev/null || true 806 if [ ! -e /proc/sys/net/vrf/strict_mode ]; then 807 echo "SKIP: vrf sysctl does not exist" 808 exit "${ksft_skip}" 809 fi 810} 811 812if [ "$(id -u)" -ne 0 ]; then 813 echo "SKIP: Need root privileges" 814 exit "${ksft_skip}" 815fi 816 817# required programs to carry out this selftest 818test_command_or_ksft_skip ip 819test_command_or_ksft_skip ping 820test_command_or_ksft_skip sysctl 821test_command_or_ksft_skip grep 822 823test_iproute2_supp_or_ksft_skip 824test_vrf_or_ksft_skip 825 826set -e 827trap cleanup EXIT 828 829setup 830set +e 831 832router_tests 833host2gateway_tests 834host_vpn_tests 835host_vpn_isolation_tests 836 837print_log_test_results 838