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