880 lines · bash
1#!/bin/bash2# SPDX-License-Identifier: GPL-2.03#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 advanced9# IPv4/IPv6 VPN services to hosts, enabling them to communicate with each10# other.11# In this example, hosts hs-1 and hs-2 are connected through an IPv4/IPv6 VPN12# 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 services15# 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 received18# by connected hosts, initiating the VPN tunnel. Such a behavior is an19# optimization of the SRv6 H.Encap aiming to reduce the length of the SID20# List carried in the pushed SRH. Specifically, the H.Encaps.Red removes21# the first SID contained in the SID List (i.e. SRv6 Policy) by storing it22# into the IPv6 Destination Address. When a SRv6 Policy is made of only one23# SID, the SRv6 H.Encaps.Red behavior omits the SRH at all and pushes that24# SID directly into the IPv6 DA;25#26# ii) The SRv6 End behavior advances the active SID in the SID List carried by27# 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 of31# handling, at the same time, both tunneled IPv4 and IPv6 traffic.32#33#34# cafe::1 cafe::235# 10.0.0.1 10.0.0.236# +--------+ +--------+37# | | | |38# | hs-1 | | hs-2 |39# | | | |40# +---+----+ +--- +---+41# cafe::/64 | | cafe::/6442# 10.0.0.0/24 | | 10.0.0.0/2443# +---+----+ +----+---+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::/6453# | . . |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::/6463# 10.0.0.0/24 | | 10.0.0.0/2464# +---+----+ +--- +---+65# | | | |66# | hs-4 | | hs-3 |67# | | | |68# +--------+ +--------+69# cafe::4 cafe::370# 10.0.0.4 10.0.0.371#72#73# Every fcf0:0:x:y::/64 network interconnects the SRv6 routers rt-x with rt-y74# in the IPv6 operator network.75#76# Local SID table77# ===============78#79# Each SRv6 router is configured with a Local SID table in which SIDs are80# stored. Considering the given SRv6 router rt-x, at least two SIDs are81# configured in the Local SID table:82#83# Local SID table for SRv6 router rt-x84# +----------------------------------------------------------+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 VPN90# services. Reachability of SIDs is ensured by proper configuration of the IPv691# operator's network and SRv6 routers.92#93# # SRv6 Policies94# ===============95#96# An SRv6 ingress router applies SRv6 policies to the traffic received from a97# connected host. SRv6 policy enforcement consists of encapsulating the98# received traffic into a new IPv6 packet with a given SID List contained in99# the SRH.100#101# IPv4/IPv6 VPN between hs-1 and hs-2102# -----------------------------------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 are106# 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::d46109# ii.a) IPv4 traffic, SID List=fcff:2::d46110#111# Policy (i.a) steers tunneled IPv6 traffic through SRv6 routers112# rt-3,rt-4,rt-2. Instead, Policy (ii.a) steers tunneled IPv4 traffic through113# rt-2.114# The H.Encaps.Red reduces the SID List (i.a) carried in SRH by removing the115# first SID (fcff:3::e) and pushing it into the IPv6 DA. In case of IPv4116# traffic, the H.Encaps.Red omits the presence of SRH at all, since the SID117# List (ii.a) consists of only one SID that can be stored directly in the IPv6118# DA.119#120# On the reverse path (i.e. from hs-2 to hs-1), rt-2 applies the following121# policies:122#123# i.b) IPv6 traffic, SID List=fcff:1::d46124# ii.b) IPv4 traffic, SID List=fcff:4::e,fcff:3::e,fcff:1::d46125#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 routers128# rt-4,rt-3,rt-1.129# The H.Encaps.Red omits the SRH at all in case of (i.b) by pushing the single130# 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 first132# 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-4143# ------------------------------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 are147# handled by rt-3 which applies the following SRv6 Policy:148#149# i.c) IPv6 traffic, SID List=fcff:2::e,fcff:4::d46150#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 the153# 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 the156# 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 the162# 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.170readonly ksft_skip=4171 172readonly RDMSUFF="$(mktemp -u XXXXXXXX)"173readonly VRF_TID=100174readonly VRF_DEVNAME="vrf-${VRF_TID}"175readonly RT2HS_DEVNAME="veth-t${VRF_TID}"176readonly LOCALSID_TABLE_ID=90177readonly IPv6_RT_NETWORK=fcf0:0178readonly IPv6_HS_NETWORK=cafe179readonly IPv4_HS_NETWORK=10.0.0180readonly VPN_LOCATOR_SERVICE=fcff181readonly END_FUNC=000e182readonly DT46_FUNC=0d46183 184PING_TIMEOUT_SEC=4185PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}186 187# IDs of routers and hosts are initialized during the setup of the testing188# network189ROUTERS=''190HOSTS=''191 192SETUP_ERR=1193 194ret=${ksft_skip}195nsuccess=0196nfail=0197 198log_test()199{200 local rc="$1"201 local expected="$2"202 local msg="$3"203 204 if [ "${rc}" -eq "${expected}" ]; then205 nsuccess=$((nsuccess+1))206 printf "\n TEST: %-60s [ OK ]\n" "${msg}"207 else208 ret=1209 nfail=$((nfail+1))210 printf "\n TEST: %-60s [FAIL]\n" "${msg}"211 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then212 echo213 echo "hit enter to continue, 'q' to quit"214 read a215 [ "$a" = "q" ] && exit 1216 fi217 fi218}219 220print_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' value227 # is set to 0 (success code).228 if [ "${ret}" -ne 1 ]; then229 ret=0230 fi231}232 233log_section()234{235 echo236 echo "################################################################################"237 echo "TEST SECTION: $*"238 echo "################################################################################"239}240 241test_command_or_ksft_skip()242{243 local cmd="$1"244 245 if [ ! -x "$(command -v "${cmd}")" ]; then246 echo "SKIP: Could not run test without \"${cmd}\" tool";247 exit "${ksft_skip}"248 fi249}250 251get_nodename()252{253 local name="$1"254 255 echo "${name}-${RDMSUFF}"256}257 258get_rtname()259{260 local rtid="$1"261 262 get_nodename "rt-${rtid}"263}264 265get_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 279create_router()280{281 local rtid="$1"282 local nsname283 284 nsname="$(get_rtname "${rtid}")"285 286 __create_namespace "${nsname}"287}288 289create_host()290{291 local hsid="$1"292 local nsname293 294 nsname="$(get_hsname "${hsid}")"295 296 __create_namespace "${nsname}"297}298 299cleanup()300{301 local nsname302 local i303 304 # destroy routers305 for i in ${ROUTERS}; do306 nsname="$(get_rtname "${i}")"307 308 ip netns del "${nsname}" &>/dev/null || true309 done310 311 # destroy hosts312 for i in ${HOSTS}; do313 nsname="$(get_hsname "${i}")"314 315 ip netns del "${nsname}" &>/dev/null || true316 done317 318 # check whether the setup phase was completed successfully or not. In319 # 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 ]; then322 echo "SKIP: Setting up the testing environment failed"323 exit "${ksft_skip}"324 fi325 326 exit "${ret}"327}328 329add_link_rt_pairs()330{331 local rt="$1"332 local rt_neighs="$2"333 local neigh334 local nsname335 local neigh_nsname336 337 nsname="$(get_rtname "${rt}")"338 339 for neigh in ${rt_neighs}; do340 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 done346}347 348get_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}" ]; then356 p="${q}"; q="${rt}"357 fi358 359 echo "${IPv6_RT_NETWORK}:${p}:${q}"360}361 362# Setup the basic networking for the routers363setup_rt_networking()364{365 local rt="$1"366 local rt_neighs="$2"367 local nsname368 local net_prefix369 local devname370 local neigh371 372 nsname="$(get_rtname "${rt}")"373 374 for neigh in ${rt_neighs}; do375 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}" nodad381 382 ip -netns "${nsname}" link set "${devname}" up383 done384 385 ip -netns "${nsname}" link set lo up386 387 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0388 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0389 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.forwarding=1390 391 ip netns exec "${nsname}" sysctl -wq net.ipv4.conf.all.rp_filter=0392 ip netns exec "${nsname}" sysctl -wq net.ipv4.conf.default.rp_filter=0393 ip netns exec "${nsname}" sysctl -wq net.ipv4.ip_forward=1394}395 396# Setup local SIDs for an SRv6 router397setup_rt_local_sids()398{399 local rt="$1"400 local rt_neighs="$2"401 local net_prefix402 local devname403 local nsname404 local neigh405 406 nsname="$(get_rtname "${rt}")"407 408 for neigh in ${rt_neighs}; do409 devname="veth-rt-${rt}-${neigh}"410 411 net_prefix="$(get_network_prefix "${rt}" "${neigh}")"412 413 # set underlay network routes for SIDs reachability414 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 done419 420 # Local End behavior (note that "dev" is dummy and the VRF is chosen421 # 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 behavior428 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 SRv6435 # 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 999440 441 # set default routes to unreachable for both ipv4 and ipv6442 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 Policy455# $3 - SRv6 routers configured for steering traffic (End behaviors)456# $4 - SRv6 router configured for removing the SRv6 Policy (router connected457# 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 nsname469 local policy=''470 local n471 472 nsname="$(get_rtname "${encap_rt}")"473 474 for n in ${end_rts}; do475 policy="${policy}${VPN_LOCATOR_SERVICE}:${n}::${END_FUNC},"476 done477 478 policy="${policy}${VPN_LOCATOR_SERVICE}:${dec_rt}::${DT46_FUNC}"479 480 # add SRv6 policy to incoming traffic sent by connected hosts481 if [ "${traffic}" -eq 6 ]; then482 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 else491 # "dev" must be different from the one where the packet is492 # 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 fi498}499 500# see __setup_rt_policy501setup_rt_policy_ipv6()502{503 __setup_rt_policy "$1" "$2" "$3" "$4" "$5" 6504}505 506#see __setup_rt_policy507setup_rt_policy_ipv4()508{509 __setup_rt_policy "$1" "$2" "$3" "$4" "$5" 4510}511 512setup_hs()513{514 local hs="$1"515 local rt="$2"516 local hsname517 local rtname518 519 hsname="$(get_hsname "${hs}")"520 rtname="$(get_rtname "${rt}")"521 522 ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0523 ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0524 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 nodad530 ip -netns "${hsname}" addr add "${IPv4_HS_NETWORK}.${hs}/24" dev veth0531 532 ip -netns "${hsname}" link set veth0 up533 ip -netns "${hsname}" link set lo up534 535 # configure the VRF on the router which is directly connected to the536 # source host.537 ip -netns "${rtname}" link \538 add "${VRF_DEVNAME}" type vrf table "${VRF_TID}"539 ip -netns "${rtname}" link set "${VRF_DEVNAME}" up540 541 # enslave the veth interface connecting the router with the host to the542 # VRF in the access router543 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}" nodad548 ip -netns "${rtname}" addr \549 add "${IPv4_HS_NETWORK}.254/24" dev "${RT2HS_DEVNAME}"550 551 ip -netns "${rtname}" link set "${RT2HS_DEVNAME}" up552 553 ip netns exec "${rtname}" \554 sysctl -wq net.ipv6.conf."${RT2HS_DEVNAME}".proxy_ndp=1555 ip netns exec "${rtname}" \556 sysctl -wq net.ipv4.conf."${RT2HS_DEVNAME}".proxy_arp=1557 558 # disable the rp_filter otherwise the kernel gets confused about how559 # to route decap ipv4 packets.560 ip netns exec "${rtname}" \561 sysctl -wq net.ipv4.conf."${RT2HS_DEVNAME}".rp_filter=0562 563 ip netns exec "${rtname}" sh -c "echo 1 > /proc/sys/net/vrf/strict_mode"564}565 566setup()567{568 local i569 570 # create routers571 ROUTERS="1 2 3 4"; readonly ROUTERS572 for i in ${ROUTERS}; do573 create_router "${i}"574 done575 576 # create hosts577 HOSTS="1 2 3 4"; readonly HOSTS578 for i in ${HOSTS}; do579 create_host "${i}"580 done581 582 # set up the links for connecting routers583 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 for588 # 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 routers595 setup_hs 1 1596 setup_hs 2 2597 setup_hs 3 3598 setup_hs 4 4599 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 policies607 608 # create an IPv6 VPN between hosts hs-1 and hs-2.609 # the network path between hs-1 and hs-2 traverses several routers610 # 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.red619 setup_rt_policy_ipv6 1 2 "" 1 encap.red620 621 # create an IPv4 VPN between hosts hs-1 and hs-2622 # the network path between hs-1 and hs-2 traverses several routers623 # 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.red632 setup_rt_policy_ipv4 1 2 "4 3" 1 encap.red633 634 # create an IPv6 VPN between hosts hs-3 and hs-4635 # the network path between hs-3 and hs-4 traverses several routers636 # 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.red646 setup_rt_policy_ipv6 3 4 "1" 3 encap.red647 648 # testing environment was set up successfully649 SETUP_ERR=0650}651 652check_rt_connectivity()653{654 local rtsrc="$1"655 local rtdst="$2"656 local prefix657 local rtsrc_nsname658 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>&1665}666 667check_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 676check_hs_ipv6_connectivity()677{678 local hssrc="$1"679 local hsdst="$2"680 local hssrc_nsname681 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>&1686}687 688check_hs_ipv4_connectivity()689{690 local hssrc="$1"691 local hsdst="$2"692 local hssrc_nsname693 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>&1698}699 700check_and_log_hs2gw_connectivity()701{702 local hssrc="$1"703 704 check_hs_ipv6_connectivity "${hssrc}" 254705 log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> gw"706 707 check_hs_ipv4_connectivity "${hssrc}" 254708 log_test $? 0 "IPv4 Hosts connectivity: hs-${hssrc} -> gw"709}710 711check_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 720check_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 729check_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 738check_and_log_hs_ipv6_isolation()739{740 local hssrc="$1"741 local hsdst="$2"742 743 # in this case, the connectivity test must fail744 check_hs_ipv6_connectivity "${hssrc}" "${hsdst}"745 log_test $? 1 "IPv6 Hosts isolation: hs-${hssrc} -X-> hs-${hsdst}"746}747 748check_and_log_hs_ipv4_isolation()749{750 local hssrc="$1"751 local hsdst="$2"752 753 # in this case, the connectivity test must fail754 check_hs_ipv4_connectivity "${hssrc}" "${hsdst}"755 log_test $? 1 "IPv4 Hosts isolation: hs-${hssrc} -X-> hs-${hsdst}"756}757 758check_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 767router_tests()768{769 local i770 local j771 772 log_section "IPv6 routers connectivity test"773 774 for i in ${ROUTERS}; do775 for j in ${ROUTERS}; do776 if [ "${i}" -eq "${j}" ]; then777 continue778 fi779 780 check_and_log_rt_connectivity "${i}" "${j}"781 done782 done783}784 785host2gateway_tests()786{787 local hs788 789 log_section "IPv4/IPv6 connectivity test among hosts and gateways"790 791 for hs in ${HOSTS}; do792 check_and_log_hs2gw_connectivity "${hs}"793 done794}795 796host_vpn_tests()797{798 log_section "SRv6 VPN connectivity test hosts (h1 <-> h2, IPv4/IPv6)"799 800 check_and_log_hs_connectivity 1 2801 check_and_log_hs_connectivity 2 1802 803 log_section "SRv6 VPN connectivity test hosts (h3 <-> h4, IPv6 only)"804 805 check_and_log_hs_ipv6_connectivity 3 4806 check_and_log_hs_ipv6_connectivity 4 3807}808 809host_vpn_isolation_tests()810{811 local l1="1 2"812 local l2="3 4"813 local tmp814 local i815 local j816 local k817 818 log_section "SRv6 VPN isolation test among hosts"819 820 for k in 0 1; do821 for i in ${l1}; do822 for j in ${l2}; do823 check_and_log_hs_isolation "${i}" "${j}"824 done825 done826 827 # let us test the reverse path828 tmp="${l1}"; l1="${l2}"; l2="${tmp}"829 done830 831 log_section "SRv6 VPN isolation test among hosts (h2 <-> h4, IPv4 only)"832 833 check_and_log_hs_ipv4_isolation 2 4834 check_and_log_hs_ipv4_isolation 4 2835}836 837test_iproute2_supp_or_ksft_skip()838{839 if ! ip route help 2>&1 | grep -qo "encap.red"; then840 echo "SKIP: Missing SRv6 encap.red support in iproute2"841 exit "${ksft_skip}"842 fi843}844 845test_vrf_or_ksft_skip()846{847 modprobe vrf &>/dev/null || true848 if [ ! -e /proc/sys/net/vrf/strict_mode ]; then849 echo "SKIP: vrf sysctl does not exist"850 exit "${ksft_skip}"851 fi852}853 854if [ "$(id -u)" -ne 0 ]; then855 echo "SKIP: Need root privileges"856 exit "${ksft_skip}"857fi858 859# required programs to carry out this selftest860test_command_or_ksft_skip ip861test_command_or_ksft_skip ping862test_command_or_ksft_skip sysctl863test_command_or_ksft_skip grep864 865test_iproute2_supp_or_ksft_skip866test_vrf_or_ksft_skip867 868set -e869trap cleanup EXIT870 871setup872set +e873 874router_tests875host2gateway_tests876host_vpn_tests877host_vpn_isolation_tests878 879print_log_test_results880