brintos

brintos / linux-shallow public Read only

0
0
Text · 20.5 KiB · cb4177d Raw
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