822 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.L2Encaps.Red behavior.7#8# Below is depicted the IPv6 network of an operator which offers L2 VPN9# 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 exchange12# 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 services15# leveraging the SRv6 architecture. The key components for such VPNs are:16#17# i) The SRv6 H.L2Encaps.Red behavior applies SRv6 Policies on traffic18# received by connected hosts, initiating the VPN tunnel. Such a behavior19# is an optimization of the SRv6 H.L2Encap aiming to reduce the20# length of the SID List carried in the pushed SRH. Specifically, the21# H.L2Encaps.Red removes the first SID contained in the SID List (i.e. SRv622# Policy) by storing it into the IPv6 Destination Address. When a SRv623# Policy is made of only one SID, the SRv6 H.L2Encaps.Red behavior omits24# 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 List27# carried by the SRH;28#29# iii) The SRv6 End.DX2 behavior is used for removing the SRv6 Policy30# and, thus, it terminates the VPN tunnel. The decapsulated L2 frame is31# sent over the interface connected with the destination host.32#33# cafe::1 cafe::234# 10.0.0.1 10.0.0.235# +--------+ +--------+36# | | | |37# | hs-1 | | hs-2 |38# | | | |39# +---+----+ +--- +---+40# cafe::/64 | | cafe::/6441# 10.0.0.0/24 | | 10.0.0.0/2442# +---+----+ +----+---+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::/6452# | . . |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-y64# in the IPv6 operator network.65#66# Local SID table67# ===============68#69# Each SRv6 router is configured with a Local SID table in which SIDs are70# stored. Considering the given SRv6 router rt-x, at least two SIDs are71# configured in the Local SID table:72#73# Local SID table for SRv6 router rt-x74# +----------------------------------------------------------+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 VPN80# services. Reachability of SIDs is ensured by proper configuration of the IPv681# operator's network and SRv6 routers.82#83# SRv6 Policies84# =============85#86# An SRv6 ingress router applies SRv6 policies to the traffic received from a87# connected host. SRv6 policy enforcement consists of encapsulating the88# received traffic into a new IPv6 packet with a given SID List contained in89# the SRH.90#91# L2 VPN between hs-1 and hs-292# ----------------------------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 are96# handled by rt-1 which applies the following SRv6 Policies:97#98# i.a) L2 traffic, SID List=fcff:2::d299#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 List102# consists of only one SID (fcff:2::d2) that can be stored directly in the IPv6103# DA.104#105# On the reverse path (i.e. from hs-2 to hs-1), rt-2 applies the following106# policies:107#108# i.b) L2 traffic, SID List=fcff:4::e,fcff:3::e,fcff:1::d2109#110# Policy (i.b) steers tunneled L2 traffic through the SRv6 routers111# rt-4,rt-3,rt2. The H.L2Encaps.Red reduces the SID List in the SRH by removing112# 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=4121 122readonly RDMSUFF="$(mktemp -u XXXXXXXX)"123readonly DUMMY_DEVNAME="dum0"124readonly RT2HS_DEVNAME="veth-hs"125readonly HS_VETH_NAME="veth0"126readonly LOCALSID_TABLE_ID=90127readonly IPv6_RT_NETWORK=fcf0:0128readonly IPv6_HS_NETWORK=cafe129readonly IPv4_HS_NETWORK=10.0.0130readonly VPN_LOCATOR_SERVICE=fcff131readonly MAC_PREFIX=00:00:00:c0:01132readonly END_FUNC=000e133readonly DX2_FUNC=00d2134 135PING_TIMEOUT_SEC=4136PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}137 138# IDs of routers and hosts are initialized during the setup of the testing139# network140ROUTERS=''141HOSTS=''142 143SETUP_ERR=1144 145ret=${ksft_skip}146nsuccess=0147nfail=0148 149log_test()150{151 local rc="$1"152 local expected="$2"153 local msg="$3"154 155 if [ "${rc}" -eq "${expected}" ]; then156 nsuccess=$((nsuccess+1))157 printf "\n TEST: %-60s [ OK ]\n" "${msg}"158 else159 ret=1160 nfail=$((nfail+1))161 printf "\n TEST: %-60s [FAIL]\n" "${msg}"162 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then163 echo164 echo "hit enter to continue, 'q' to quit"165 read a166 [ "$a" = "q" ] && exit 1167 fi168 fi169}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' value178 # is set to 0 (success code).179 if [ "${ret}" -ne 1 ]; then180 ret=0181 fi182}183 184log_section()185{186 echo187 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}")" ]; then197 echo "SKIP: Could not run test without \"${cmd}\" tool";198 exit "${ksft_skip}"199 fi200}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 nsname234 235 nsname="$(get_rtname "${rtid}")"236 237 __create_namespace "${nsname}"238}239 240create_host()241{242 local hsid="$1"243 local nsname244 245 nsname="$(get_hsname "${hsid}")"246 247 __create_namespace "${nsname}"248}249 250cleanup()251{252 local nsname253 local i254 255 # destroy routers256 for i in ${ROUTERS}; do257 nsname="$(get_rtname "${i}")"258 259 ip netns del "${nsname}" &>/dev/null || true260 done261 262 # destroy hosts263 for i in ${HOSTS}; do264 nsname="$(get_hsname "${i}")"265 266 ip netns del "${nsname}" &>/dev/null || true267 done268 269 # check whether the setup phase was completed successfully or not. In270 # 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 ]; then273 echo "SKIP: Setting up the testing environment failed"274 exit "${ksft_skip}"275 fi276 277 exit "${ret}"278}279 280add_link_rt_pairs()281{282 local rt="$1"283 local rt_neighs="$2"284 local neigh285 local nsname286 local neigh_nsname287 288 nsname="$(get_rtname "${rt}")"289 290 for neigh in ${rt_neighs}; do291 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 done297}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}" ]; then307 p="${q}"; q="${rt}"308 fi309 310 echo "${IPv6_RT_NETWORK}:${p}:${q}"311}312 313# Setup the basic networking for the routers314setup_rt_networking()315{316 local rt="$1"317 local rt_neighs="$2"318 local nsname319 local net_prefix320 local devname321 local neigh322 323 nsname="$(get_rtname "${rt}")"324 325 for neigh in ${rt_neighs}; do326 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}" nodad332 333 ip -netns "${nsname}" link set "${devname}" up334 done335 336 ip -netns "${nsname}" link add "${DUMMY_DEVNAME}" type dummy337 338 ip -netns "${nsname}" link set "${DUMMY_DEVNAME}" up339 ip -netns "${nsname}" link set lo up340 341 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0342 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0343 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.forwarding=1344 345 ip netns exec "${nsname}" sysctl -wq net.ipv4.conf.all.rp_filter=0346 ip netns exec "${nsname}" sysctl -wq net.ipv4.conf.default.rp_filter=0347 ip netns exec "${nsname}" sysctl -wq net.ipv4.ip_forward=1348}349 350# Setup local SIDs for an SRv6 router351setup_rt_local_sids()352{353 local rt="$1"354 local rt_neighs="$2"355 local net_prefix356 local devname357 local nsname358 local neigh359 360 nsname="$(get_rtname "${rt}")"361 362 for neigh in ${rt_neighs}; do363 devname="veth-rt-${rt}-${neigh}"364 365 net_prefix="$(get_network_prefix "${rt}" "${neigh}")"366 367 # set underlay network routes for SIDs reachability368 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 done373 374 # Local End behavior (note that dev "${DUMMY_DEVNAME}" is a dummy375 # 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 SRv6382 # 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 999387}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 Policy393# $3 - SRv6 routers configured for steering traffic (End behaviors)394# $4 - SRv6 router configured for removing the SRv6 Policy (router connected395# 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 nsname407 local policy=''408 local n409 410 nsname="$(get_rtname "${encap_rt}")"411 412 for n in ${end_rts}; do413 policy="${policy}${VPN_LOCATOR_SERVICE}:${n}::${END_FUNC},"414 done415 416 policy="${policy}${VPN_LOCATOR_SERVICE}:${dec_rt}::${DX2_FUNC}"417 418 # add SRv6 policy to incoming traffic sent by connected hosts419 if [ "${traffic}" -eq 6 ]; then420 ip -netns "${nsname}" -6 route \421 add "${IPv6_HS_NETWORK}::${dst}" \422 encap seg6 mode "${mode}" segs "${policy}" \423 dev dum0424 else425 ip -netns "${nsname}" -4 route \426 add "${IPv4_HS_NETWORK}.${dst}" \427 encap seg6 mode "${mode}" segs "${policy}" \428 dev dum0429 fi430}431 432# see __setup_rt_policy433setup_rt_policy_ipv6()434{435 __setup_rt_policy "$1" "$2" "$3" "$4" "$5" 6436}437 438#see __setup_rt_policy439setup_rt_policy_ipv4()440{441 __setup_rt_policy "$1" "$2" "$3" "$4" "$5" 4442}443 444setup_decap()445{446 local rt="$1"447 local nsname448 449 nsname="$(get_rtname "${rt}")"450 451 # Local End.DX2 behavior452 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 hsname464 local rtname465 466 hsname="$(get_hsname "${hs}")"467 rtname="$(get_rtname "${rt}")"468 469 ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0470 ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0471 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}" nodad477 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}" up481 ip -netns "${hsname}" link set lo up482 483 ip -netns "${rtname}" addr add "${IPv6_HS_NETWORK}::254/64" \484 dev "${RT2HS_DEVNAME}" nodad485 ip -netns "${rtname}" addr \486 add "${IPv4_HS_NETWORK}.254/24" dev "${RT2HS_DEVNAME}"487 488 ip -netns "${rtname}" link set "${RT2HS_DEVNAME}" up489 490 # disable the rp_filter otherwise the kernel gets confused about how491 # to route decap ipv4 packets.492 ip netns exec "${rtname}" \493 sysctl -wq net.ipv4.conf."${RT2HS_DEVNAME}".rp_filter=0494}495 496# set an auto-generated mac address497# 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 address501# $4 - name of the network interface to which the generated mac address must502# be set.503set_mac_address()504{505 local nodename="$1"506 local nodeid="$2"507 local host="$3"508 local ifname="$4"509 local nsname510 511 nsname=$(get_nodename "${nodename}")512 513 ip -netns "${nsname}" link set dev "${ifname}" down514 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 has519 # been changed.520 ip -netns "${nsname}" addr add "${IPv6_HS_NETWORK}::${host}/64" \521 dev "${ifname}" nodad522 523 ip -netns "${nsname}" link set dev "${ifname}" up524}525 526set_host_l2peer()527{528 local hssrc="$1"529 local hsdst="$2"530 local ipprefix="$3"531 local proto="$4"532 local hssrc_name533 local ipaddr534 535 hssrc_name="$(get_hsname "${hssrc}")"536 537 if [ "${proto}" -eq 6 ]; then538 ipaddr="${ipprefix}::${hsdst}"539 else540 ipaddr="${ipprefix}.${hsdst}"541 fi542 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 SRv6551# subsystem only supports L2 frames whose layer-3 is IPv4/IPv6).552# args:553# $1 - source host554# $2 - SRv6 routers configured for steering tunneled traffic555# $3 - destination host556setup_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 address565 set_mac_address "hs-${hssrc}" "${hssrc}" "${hssrc}" "${HS_VETH_NAME}"566 set_host_l2peer "${hssrc}" "${hsdst}" "${IPv6_HS_NETWORK}" 6567 set_host_l2peer "${hssrc}" "${hsdst}" "${IPv4_HS_NETWORK}" 4568 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 the572 # ingress router.573 set_mac_address "rt-${rtsrc}" "${hsdst}" 254 "${RT2HS_DEVNAME}"574 575 # set the SRv6 Policies at the ingress router576 setup_rt_policy_ipv6 "${hsdst}" "${rtsrc}" "${end_rts}" "${rtdst}" \577 l2encap.red 6578 setup_rt_policy_ipv4 "${hsdst}" "${rtsrc}" "${end_rts}" "${rtdst}" \579 l2encap.red 4580 581 # set the decap behavior582 setup_decap "${rtsrc}"583}584 585setup()586{587 local i588 589 # create routers590 ROUTERS="1 2 3 4"; readonly ROUTERS591 for i in ${ROUTERS}; do592 create_router "${i}"593 done594 595 # create hosts596 HOSTS="1 2"; readonly HOSTS597 for i in ${HOSTS}; do598 create_host "${i}"599 done600 601 # set up the links for connecting routers602 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 for607 # 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 routers614 setup_hs 1 1615 setup_hs 2 2616 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 whose625 # layer-3 is IPv4/IPv6.626 #627 # the network path between hs-1 and hs-2 traverses several routers628 # 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 "" 2637 setup_l2vpn 2 "4 3" 1638 639 # testing environment was set up successfully640 SETUP_ERR=0641}642 643check_rt_connectivity()644{645 local rtsrc="$1"646 local rtdst="$2"647 local prefix648 local rtsrc_nsname649 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>&1656}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_nsname672 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>&1677}678 679check_hs_ipv4_connectivity()680{681 local hssrc="$1"682 local hsdst="$2"683 local hssrc_nsname684 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>&1689}690 691check_and_log_hs2gw_connectivity()692{693 local hssrc="$1"694 695 check_hs_ipv6_connectivity "${hssrc}" 254696 log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> gw"697 698 check_hs_ipv4_connectivity "${hssrc}" 254699 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 i732 local j733 734 log_section "IPv6 routers connectivity test"735 736 for i in ${ROUTERS}; do737 for j in ${ROUTERS}; do738 if [ "${i}" -eq "${j}" ]; then739 continue740 fi741 742 check_and_log_rt_connectivity "${i}" "${j}"743 done744 done745}746 747host2gateway_tests()748{749 local hs750 751 log_section "IPv4/IPv6 connectivity test among hosts and gateways"752 753 for hs in ${HOSTS}; do754 check_and_log_hs2gw_connectivity "${hs}"755 done756}757 758host_vpn_tests()759{760 log_section "SRv6 L2 VPN connectivity test hosts (h1 <-> h2)"761 762 check_and_log_hs_connectivity 1 2763 check_and_log_hs_connectivity 2 1764}765 766test_dummy_dev_or_ksft_skip()767{768 local test_netns769 770 test_netns="dummy-$(mktemp -u XXXXXXXX)"771 772 if ! ip netns add "${test_netns}"; then773 echo "SKIP: Cannot set up netns for testing dummy dev support"774 exit "${ksft_skip}"775 fi776 777 modprobe dummy &>/dev/null || true778 if ! ip -netns "${test_netns}" link \779 add "${DUMMY_DEVNAME}" type dummy; then780 echo "SKIP: dummy dev not supported"781 782 ip netns del "${test_netns}"783 exit "${ksft_skip}"784 fi785 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"; then792 echo "SKIP: Missing SRv6 l2encap.red support in iproute2"793 exit "${ksft_skip}"794 fi795}796 797if [ "$(id -u)" -ne 0 ]; then798 echo "SKIP: Need root privileges"799 exit "${ksft_skip}"800fi801 802# required programs to carry out this selftest803test_command_or_ksft_skip ip804test_command_or_ksft_skip ping805test_command_or_ksft_skip sysctl806test_command_or_ksft_skip grep807 808test_iproute2_supp_or_ksft_skip809test_dummy_dev_or_ksft_skip810 811set -e812trap cleanup EXIT813 814setup815set +e816 817router_tests818host2gateway_tests819host_vpn_tests820 821print_log_test_results822