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