brintos

brintos / linux-shallow public Read only

0
0
Text · 23.6 KiB · 5056344 Raw
870 lines · bash
1#!/bin/bash2# SPDX-License-Identifier: GPL-2.03#4# author: Andrea Mayer <andrea.mayer@uniroma2.it>5# author: Paolo Lungaroni <paolo.lungaroni@uniroma2.it>6#7# This script is designed to test the support for "flavors" in the SRv6 End8# behavior.9#10# Flavors defined in RFC8986 [1] represent additional operations that can modify11# or extend the existing SRv6 End, End.X and End.T behaviors. For the sake of12# convenience, we report the list of flavors described in [1] hereafter:13#   - Penultimate Segment Pop (PSP);14#   - Ultimate Segment Pop (USP);15#   - Ultimate Segment Decapsulation (USD).16#17# The End, End.X, and End.T behaviors can support these flavors either18# individually or in combinations.19# Currently in this selftest we consider only the PSP flavor for the SRv6 End20# behavior. However, it is possible to extend the script as soon as other21# flavors will be supported in the kernel.22#23# The purpose of the PSP flavor consists in instructing the penultimate node24# listed in the SRv6 policy to remove (i.e. pop) the outermost SRH from the IPv625# header.26# A PSP enabled SRv6 End behavior instance processes the SRH by:27#  - decrementing the Segment Left (SL) value from 1 to 0;28#  - copying the last SID from the SID List into the IPv6 Destination Address29#    (DA);30#  - removing the SRH from the extension headers following the IPv6 header.31#32# Once the SRH is removed, the IPv6 packet is forwarded to the destination using33# the IPv6 DA updated during the PSP operation (i.e. the IPv6 DA corresponding34# to the last SID carried by the removed SRH).35#36# Although the PSP flavor can be set for any SRv6 End behavior instance on any37# SR node, it will be active only on such behaviors bound to a penultimate SID38# for a given SRv6 policy.39#                                                SL=2 SL=1 SL=040#                                                  |    |    |41# For example, given the SRv6 policy (SID List := <X,   Y,   Z>):42#  - a PSP enabled SRv6 End behavior bound to SID Y will apply the PSP operation43#    as Segment Left (SL) is 1, corresponding to the Penultimate Segment of the44#    SID List;45#  - a PSP enabled SRv6 End behavior bound to SID X will *NOT* apply the PSP46#    operation as the Segment Left is 2. This behavior instance will apply the47#    "standard" End packet processing, ignoring the configured PSP flavor at48#    all.49#50# [1] RFC8986: https://datatracker.ietf.org/doc/html/rfc898651#52# Network topology53# ================54#55# The network topology used in this selftest is depicted hereafter, composed by56# two hosts (hs-1, hs-2) and four routers (rt-1, rt-2, rt-3, rt-4).57# Hosts hs-1 and hs-2 are connected to routers rt-1 and rt-2, respectively,58# allowing them to communicate with each other.59# Traffic exchanged between hs-1 and hs-2 can follow different network paths.60# The network operator, through specific SRv6 Policies can steer traffic to one61# path rather than another. In this selftest this is implemented as follows:62#63#   i) The SRv6 H.Insert behavior applies SRv6 Policies on traffic received by64#      connected hosts. It pushes the Segment Routing Header (SRH) after the65#      IPv6 header. The SRH contains the SID List (i.e. SRv6 Policy) needed for66#      steering traffic across the segments/waypoints specified in that list;67#68#  ii) The SRv6 End behavior advances the active SID in the SID List carried by69#      the SRH;70#71# iii) The PSP enabled SRv6 End behavior is used to remove the SRH when such72#      behavior is configured on a node bound to the Penultimate Segment carried73#      by the SID List.74#75#                cafe::1                      cafe::276#              +--------+                   +--------+77#              |        |                   |        |78#              |  hs-1  |                   |  hs-2  |79#              |        |                   |        |80#              +---+----+                   +--- +---+81#     cafe::/64    |                             |      cafe::/6482#                  |                             |83#              +---+----+                   +----+---+84#              |        |  fcf0:0:1:2::/64  |        |85#              |  rt-1  +-------------------+  rt-2  |86#              |        |                   |        |87#              +---+----+                   +----+---+88#                  |      .               .      |89#                  |  fcf0:0:1:3::/64   .        |90#                  |          .       .          |91#                  |            .   .            |92#  fcf0:0:1:4::/64 |              .              | fcf0:0:2:3::/6493#                  |            .   .            |94#                  |          .       .          |95#                  |  fcf0:0:2:4::/64   .        |96#                  |      .               .      |97#              +---+----+                   +----+---+98#              |        |                   |        |99#              |  rt-4  +-------------------+  rt-3  |100#              |        |  fcf0:0:3:4::/64  |        |101#              +---+----+                   +----+---+102#103# Every fcf0:0:x:y::/64 network interconnects the SRv6 routers rt-x with rt-y in104# the IPv6 operator network.105#106#107# Local SID table108# ===============109#110# Each SRv6 router is configured with a Local SID table in which SIDs are111# stored. Considering the given SRv6 router rt-x, at least two SIDs are112# configured in the Local SID table:113#114#   Local SID table for SRv6 router rt-x115#   +---------------------------------------------------------------------+116#   |fcff:x::e is associated with the SRv6 End behavior                   |117#   |fcff:x::ef1 is associated with the SRv6 End behavior with PSP flavor |118#   +---------------------------------------------------------------------+119#120# The fcff::/16 prefix is reserved by the operator for the SIDs. Reachability of121# SIDs is ensured by proper configuration of the IPv6 operator's network and122# SRv6 routers.123#124#125# SRv6 Policies126# =============127#128# An SRv6 ingress router applies different SRv6 Policies to the traffic received129# from connected hosts on the basis of the destination addresses.130# In case of SRv6 H.Insert behavior, the SRv6 Policy enforcement consists of131# pushing the SRH (carrying a given SID List) after the existing IPv6 header.132# Note that in the inserting mode, there is no encapsulation at all.133#134#   Before applying an SRv6 Policy using the SRv6 H.Insert behavior135#   +------+---------+136#   | IPv6 | Payload |137#   +------+---------+138#139#   After applying an SRv6 Policy using the SRv6 H.Insert behavior140#   +------+-----+---------+141#   | IPv6 | SRH | Payload |142#   +------+-----+---------+143#144# Traffic from hs-1 to hs-2145# -------------------------146#147# Packets generated from hs-1 and directed towards hs-2 are148# handled by rt-1 which applies the following SRv6 Policy:149#150#   i.a) IPv6 traffic, SID List=fcff:3::e,fcff:4::ef1,fcff:2::ef1,cafe::2151#152# Router rt-1 is configured to enforce the Policy (i.a) through the SRv6153# H.Insert behavior which pushes the SRH after the existing IPv6 header. This154# Policy steers the traffic from hs-1 across rt-3, rt-4, rt-2 and finally to the155# destination hs-2.156#157# As the packet reaches the router rt-3, the SRv6 End behavior bound to SID158# fcff:3::e is triggered. The behavior updates the Segment Left (from SL=3 to159# SL=2) in the SRH, the IPv6 DA with fcff:4::ef1 and forwards the packet to the160# next router on the path, i.e. rt-4.161#162# When router rt-4 receives the packet, the PSP enabled SRv6 End behavior bound163# to SID fcff:4::ef1 is executed. Since the SL=2, the PSP operation is *NOT*164# kicked in and the behavior applies the default End processing: the Segment165# Left is decreased (from SL=2 to SL=1), the IPv6 DA is updated with the SID166# fcff:2::ef1 and the packet is forwarded to router rt-2.167#168# The PSP enabled SRv6 End behavior on rt-2 is associated with SID fcff:2::ef1169# and is executed as the packet is received. Because SL=1, the behavior applies170# the PSP processing on the packet as follows: i) SL is decreased, i.e. from171# SL=1 to SL=0; ii) last SID (cafe::2) is copied into the IPv6 DA; iii) the172# outermost SRH is removed from the extension headers following the IPv6 header.173# Once the PSP processing is completed, the packet is forwarded to the host hs-2174# (destination).175#176# Traffic from hs-2 to hs-1177# -------------------------178#179# Packets generated from hs-2 and directed to hs-1 are handled by rt-2 which180# applies the following SRv6 Policy:181#182#   i.b) IPv6 traffic, SID List=fcff:1::ef1,cafe::1183#184# Router rt-2 is configured to enforce the Policy (i.b) through the SRv6185# H.Insert behavior which pushes the SRH after the existing IPv6 header. This186# Policy steers the traffic from hs-2 across rt-1 and finally to the187# destination hs-1188#189#190# When the router rt-1 receives the packet, the PSP enabled SRv6 End behavior191# associated with the SID fcff:1::ef1 is triggered. Since the SL=1,192# the PSP operation takes place: i) the SL is decremented; ii) the IPv6 DA is193# set with the last SID; iii) the SRH is removed from the extension headers194# after the IPv6 header. At this point, the packet with IPv6 DA=cafe::1 is sent195# to the destination, i.e. hs-1.196 197# Kselftest framework requirement - SKIP code is 4.198readonly ksft_skip=4199 200readonly RDMSUFF="$(mktemp -u XXXXXXXX)"201readonly DUMMY_DEVNAME="dum0"202readonly RT2HS_DEVNAME="veth1"203readonly LOCALSID_TABLE_ID=90204readonly IPv6_RT_NETWORK=fcf0:0205readonly IPv6_HS_NETWORK=cafe206readonly IPv6_TESTS_ADDR=2001:db8::1207readonly LOCATOR_SERVICE=fcff208readonly END_FUNC=000e209readonly END_PSP_FUNC=0ef1210 211PING_TIMEOUT_SEC=4212PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}213 214# IDs of routers and hosts are initialized during the setup of the testing215# network216ROUTERS=''217HOSTS=''218 219SETUP_ERR=1220 221ret=${ksft_skip}222nsuccess=0223nfail=0224 225log_test()226{227	local rc="$1"228	local expected="$2"229	local msg="$3"230 231	if [ "${rc}" -eq "${expected}" ]; then232		nsuccess=$((nsuccess+1))233		printf "\n    TEST: %-60s  [ OK ]\n" "${msg}"234	else235		ret=1236		nfail=$((nfail+1))237		printf "\n    TEST: %-60s  [FAIL]\n" "${msg}"238		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then239			echo240			echo "hit enter to continue, 'q' to quit"241			read a242			[ "$a" = "q" ] && exit 1243		fi244	fi245}246 247print_log_test_results()248{249	printf "\nTests passed: %3d\n" "${nsuccess}"250	printf "Tests failed: %3d\n"   "${nfail}"251 252	# when a test fails, the value of 'ret' is set to 1 (error code).253	# Conversely, when all tests are passed successfully, the 'ret' value254	# is set to 0 (success code).255	if [ "${ret}" -ne 1 ]; then256		ret=0257	fi258}259 260log_section()261{262	echo263	echo "################################################################################"264	echo "TEST SECTION: $*"265	echo "################################################################################"266}267 268test_command_or_ksft_skip()269{270	local cmd="$1"271 272	if [ ! -x "$(command -v "${cmd}")" ]; then273		echo "SKIP: Could not run test without \"${cmd}\" tool";274		exit "${ksft_skip}"275	fi276}277 278get_nodename()279{280	local name="$1"281 282	echo "${name}-${RDMSUFF}"283}284 285get_rtname()286{287	local rtid="$1"288 289	get_nodename "rt-${rtid}"290}291 292get_hsname()293{294	local hsid="$1"295 296	get_nodename "hs-${hsid}"297}298 299__create_namespace()300{301	local name="$1"302 303	ip netns add "${name}"304}305 306create_router()307{308	local rtid="$1"309	local nsname310 311	nsname="$(get_rtname "${rtid}")"312 313	__create_namespace "${nsname}"314}315 316create_host()317{318	local hsid="$1"319	local nsname320 321	nsname="$(get_hsname "${hsid}")"322 323	__create_namespace "${nsname}"324}325 326cleanup()327{328	local nsname329	local i330 331	# destroy routers332	for i in ${ROUTERS}; do333		nsname="$(get_rtname "${i}")"334 335		ip netns del "${nsname}" &>/dev/null || true336	done337 338	# destroy hosts339	for i in ${HOSTS}; do340		nsname="$(get_hsname "${i}")"341 342		ip netns del "${nsname}" &>/dev/null || true343	done344 345	# check whether the setup phase was completed successfully or not. In346	# case of an error during the setup phase of the testing environment,347	# the selftest is considered as "skipped".348	if [ "${SETUP_ERR}" -ne 0 ]; then349		echo "SKIP: Setting up the testing environment failed"350		exit "${ksft_skip}"351	fi352 353	exit "${ret}"354}355 356add_link_rt_pairs()357{358	local rt="$1"359	local rt_neighs="$2"360	local neigh361	local nsname362	local neigh_nsname363 364	nsname="$(get_rtname "${rt}")"365 366	for neigh in ${rt_neighs}; do367		neigh_nsname="$(get_rtname "${neigh}")"368 369		ip link add "veth-rt-${rt}-${neigh}" netns "${nsname}" \370			type veth peer name "veth-rt-${neigh}-${rt}" \371			netns "${neigh_nsname}"372	done373}374 375get_network_prefix()376{377	local rt="$1"378	local neigh="$2"379	local p="${rt}"380	local q="${neigh}"381 382	if [ "${p}" -gt "${q}" ]; then383		p="${q}"; q="${rt}"384	fi385 386	echo "${IPv6_RT_NETWORK}:${p}:${q}"387}388 389# Given the description of a router <id:op> as an input, the function returns390# the <id> token which represents the ID of the router.391# i.e. input: "12:psp"392#      output: "12"393__get_srv6_rtcfg_id()394{395	local element="$1"396 397	echo "${element}" | cut -d':' -f1398}399 400# Given the description of a router <id:op> as an input, the function returns401# the <op> token which represents the operation (e.g. End behavior with or402# withouth flavors) configured for the node.403 404# Note that when the operation represents an End behavior with a list of405# flavors, the output is the ordered version of that list.406# i.e. input: "5:usp,psp,usd"407#      output: "psp,usd,usp"408__get_srv6_rtcfg_op()409{410	local element="$1"411 412	# return the lexicographically ordered flavors413	echo "${element}" | cut -d':' -f2 | sed 's/,/\n/g' | sort | \414		xargs | sed 's/ /,/g'415}416 417# Setup the basic networking for the routers418setup_rt_networking()419{420	local rt="$1"421	local rt_neighs="$2"422	local nsname423	local net_prefix424	local devname425	local neigh426 427	nsname="$(get_rtname "${rt}")"428 429	for neigh in ${rt_neighs}; do430		devname="veth-rt-${rt}-${neigh}"431 432		net_prefix="$(get_network_prefix "${rt}" "${neigh}")"433 434		ip -netns "${nsname}" addr \435			add "${net_prefix}::${rt}/64" dev "${devname}" nodad436 437		ip -netns "${nsname}" link set "${devname}" up438	done439 440	ip -netns "${nsname}" link set lo up441 442	ip -netns "${nsname}" link add ${DUMMY_DEVNAME} type dummy443	ip -netns "${nsname}" link set ${DUMMY_DEVNAME} up444 445	ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0446	ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0447	ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.forwarding=1448}449 450# Setup local SIDs for an SRv6 router451setup_rt_local_sids()452{453	local rt="$1"454	local rt_neighs="$2"455	local net_prefix456	local devname457	local nsname458	local neigh459 460	nsname="$(get_rtname "${rt}")"461 462	for neigh in ${rt_neighs}; do463		devname="veth-rt-${rt}-${neigh}"464 465		net_prefix="$(get_network_prefix "${rt}" "${neigh}")"466 467		# set underlay network routes for SIDs reachability468		ip -netns "${nsname}" -6 route \469			add "${LOCATOR_SERVICE}:${neigh}::/32" \470			table "${LOCALSID_TABLE_ID}" \471			via "${net_prefix}::${neigh}" dev "${devname}"472	done473 474	# Local End behavior (note that "dev" is a dummy interface chosen for475	# the sake of simplicity).476	ip -netns "${nsname}" -6 route \477		add "${LOCATOR_SERVICE}:${rt}::${END_FUNC}" \478		table "${LOCALSID_TABLE_ID}" \479		encap seg6local action End dev "${DUMMY_DEVNAME}"480 481 482	# all SIDs start with a common locator. Routes and SRv6 Endpoint483	# behavior instaces are grouped together in the 'localsid' table.484	ip -netns "${nsname}" -6 rule \485		add to "${LOCATOR_SERVICE}::/16" \486		lookup "${LOCALSID_TABLE_ID}" prio 999487 488	# set default routes to unreachable489	ip -netns "${nsname}" -6 route \490		add unreachable default metric 4278198272 \491		dev "${DUMMY_DEVNAME}"492}493 494# This helper function builds and installs the SID List (i.e. SRv6 Policy)495# to be applied on incoming packets at the ingress node. Moreover, it496# configures the SRv6 nodes specified in the SID List to process the traffic497# according to the operations required by the Policy itself.498# args:499#  $1 - destination host (i.e. cafe::x host)500#  $2 - SRv6 router configured for enforcing the SRv6 Policy501#  $3 - compact way to represent a list of SRv6 routers with their operations502#       (i.e. behaviors) that each of them needs to perform. Every <nodeid:op>503#       element constructs a SID that is associated with the behavior <op> on504#       the <nodeid> node. The list of such elements forms an SRv6 Policy.505__setup_rt_policy()506{507	local dst="$1"508	local encap_rt="$2"509	local policy_rts="$3"510	local behavior_cfg511	local in_nsname512	local rt_nsname513	local policy=''514	local function515	local fullsid516	local op_type517	local node518	local n519 520	in_nsname="$(get_rtname "${encap_rt}")"521 522	for n in ${policy_rts}; do523		node="$(__get_srv6_rtcfg_id "${n}")"524		op_type="$(__get_srv6_rtcfg_op "${n}")"525		rt_nsname="$(get_rtname "${node}")"526 527		case "${op_type}" in528		"noflv")529			policy="${policy}${LOCATOR_SERVICE}:${node}::${END_FUNC},"530			function="${END_FUNC}"531			behavior_cfg="End"532			;;533 534		"psp")535			policy="${policy}${LOCATOR_SERVICE}:${node}::${END_PSP_FUNC},"536			function="${END_PSP_FUNC}"537			behavior_cfg="End flavors psp"538			;;539 540		*)541			break542			;;543		esac544 545		fullsid="${LOCATOR_SERVICE}:${node}::${function}"546 547		# add SRv6 Endpoint behavior to the selected router548		if ! ip -netns "${rt_nsname}" -6 route get "${fullsid}" \549			&>/dev/null; then550			ip -netns "${rt_nsname}" -6 route \551				add "${fullsid}" \552				table "${LOCALSID_TABLE_ID}" \553				encap seg6local action ${behavior_cfg} \554				dev "${DUMMY_DEVNAME}"555		fi556	done557 558	# we need to remove the trailing comma to avoid inserting an empty559	# address (::0) in the SID List.560	policy="${policy%,}"561 562	# add SRv6 policy to incoming traffic sent by connected hosts563	ip -netns "${in_nsname}" -6 route \564		add "${IPv6_HS_NETWORK}::${dst}" \565		encap seg6 mode inline segs "${policy}" \566		dev "${DUMMY_DEVNAME}"567 568	ip -netns "${in_nsname}" -6 neigh \569		add proxy "${IPv6_HS_NETWORK}::${dst}" \570		dev "${RT2HS_DEVNAME}"571}572 573# see __setup_rt_policy574setup_rt_policy_ipv6()575{576	__setup_rt_policy "$1" "$2" "$3"577}578 579setup_hs()580{581	local hs="$1"582	local rt="$2"583	local hsname584	local rtname585 586	hsname="$(get_hsname "${hs}")"587	rtname="$(get_rtname "${rt}")"588 589	ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0590	ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0591 592	ip -netns "${hsname}" link add veth0 type veth \593		peer name "${RT2HS_DEVNAME}" netns "${rtname}"594 595	ip -netns "${hsname}" addr \596		add "${IPv6_HS_NETWORK}::${hs}/64" dev veth0 nodad597 598	ip -netns "${hsname}" link set veth0 up599	ip -netns "${hsname}" link set lo up600 601	ip -netns "${rtname}" addr \602		add "${IPv6_HS_NETWORK}::254/64" dev "${RT2HS_DEVNAME}" nodad603 604	ip -netns "${rtname}" link set "${RT2HS_DEVNAME}" up605 606	ip netns exec "${rtname}" \607		sysctl -wq net.ipv6.conf."${RT2HS_DEVNAME}".proxy_ndp=1608}609 610setup()611{612	local i613 614	# create routers615	ROUTERS="1 2 3 4"; readonly ROUTERS616	for i in ${ROUTERS}; do617		create_router "${i}"618	done619 620	# create hosts621	HOSTS="1 2"; readonly HOSTS622	for i in ${HOSTS}; do623		create_host "${i}"624	done625 626	# set up the links for connecting routers627	add_link_rt_pairs 1 "2 3 4"628	add_link_rt_pairs 2 "3 4"629	add_link_rt_pairs 3 "4"630 631	# set up the basic connectivity of routers and routes required for632	# reachability of SIDs.633	setup_rt_networking 1 "2 3 4"634	setup_rt_networking 2 "1 3 4"635	setup_rt_networking 3 "1 2 4"636	setup_rt_networking 4 "1 2 3"637 638	# set up the hosts connected to routers639	setup_hs 1 1640	setup_hs 2 2641 642	# set up default SRv6 Endpoints (i.e. SRv6 End behavior)643	setup_rt_local_sids 1 "2 3 4"644	setup_rt_local_sids 2 "1 3 4"645	setup_rt_local_sids 3 "1 2 4"646	setup_rt_local_sids 4 "1 2 3"647 648	# set up SRv6 policies649	# create a connection between hosts hs-1 and hs-2.650	# The path between hs-1 and hs-2 traverses SRv6 aware routers.651	# For each direction two path are chosen:652	#653	# Direction hs-1 -> hs-2 (PSP flavor)654	#  - rt-1 (SRv6 H.Insert policy)655	#  - rt-3 (SRv6 End behavior)656	#  - rt-4 (SRv6 End flavor PSP with SL>1, acting as End behavior)657	#  - rt-2 (SRv6 End flavor PSP with SL=1)658	#659	# Direction hs-2 -> hs-1 (PSP flavor)660	#  - rt-2 (SRv6 H.Insert policy)661	#  - rt-1 (SRv6 End flavor PSP with SL=1)662	setup_rt_policy_ipv6 2 1 "3:noflv 4:psp 2:psp"663	setup_rt_policy_ipv6 1 2 "1:psp"664 665	# testing environment was set up successfully666	SETUP_ERR=0667}668 669check_rt_connectivity()670{671	local rtsrc="$1"672	local rtdst="$2"673	local prefix674	local rtsrc_nsname675 676	rtsrc_nsname="$(get_rtname "${rtsrc}")"677 678	prefix="$(get_network_prefix "${rtsrc}" "${rtdst}")"679 680	ip netns exec "${rtsrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \681		"${prefix}::${rtdst}" >/dev/null 2>&1682}683 684check_and_log_rt_connectivity()685{686	local rtsrc="$1"687	local rtdst="$2"688 689	check_rt_connectivity "${rtsrc}" "${rtdst}"690	log_test $? 0 "Routers connectivity: rt-${rtsrc} -> rt-${rtdst}"691}692 693check_hs_ipv6_connectivity()694{695	local hssrc="$1"696	local hsdst="$2"697	local hssrc_nsname698 699	hssrc_nsname="$(get_hsname "${hssrc}")"700 701	ip netns exec "${hssrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \702		"${IPv6_HS_NETWORK}::${hsdst}" >/dev/null 2>&1703}704 705check_and_log_hs2gw_connectivity()706{707	local hssrc="$1"708 709	check_hs_ipv6_connectivity "${hssrc}" 254710	log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> gw"711}712 713check_and_log_hs_ipv6_connectivity()714{715	local hssrc="$1"716	local hsdst="$2"717 718	check_hs_ipv6_connectivity "${hssrc}" "${hsdst}"719	log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> hs-${hsdst}"720}721 722check_and_log_hs_connectivity()723{724	local hssrc="$1"725	local hsdst="$2"726 727	check_and_log_hs_ipv6_connectivity "${hssrc}" "${hsdst}"728}729 730router_tests()731{732	local i733	local j734 735	log_section "IPv6 routers connectivity test"736 737	for i in ${ROUTERS}; do738		for j in ${ROUTERS}; do739			if [ "${i}" -eq "${j}" ]; then740				continue741			fi742 743			check_and_log_rt_connectivity "${i}" "${j}"744		done745	done746}747 748host2gateway_tests()749{750	local hs751 752	log_section "IPv6 connectivity test among hosts and gateways"753 754	for hs in ${HOSTS}; do755		check_and_log_hs2gw_connectivity "${hs}"756	done757}758 759host_srv6_end_flv_psp_tests()760{761	log_section "SRv6 connectivity test hosts (h1 <-> h2, PSP flavor)"762 763	check_and_log_hs_connectivity 1 2764	check_and_log_hs_connectivity 2 1765}766 767test_iproute2_supp_or_ksft_skip()768{769	local flavor="$1"770 771	if ! ip route help 2>&1 | grep -qo "${flavor}"; then772		echo "SKIP: Missing SRv6 ${flavor} flavor support in iproute2"773		exit "${ksft_skip}"774	fi775}776 777test_kernel_supp_or_ksft_skip()778{779	local flavor="$1"780	local test_netns781 782	test_netns="kflv-$(mktemp -u XXXXXXXX)"783 784	if ! ip netns add "${test_netns}"; then785		echo "SKIP: Cannot set up netns to test kernel support for flavors"786		exit "${ksft_skip}"787	fi788 789	if ! ip -netns "${test_netns}" link \790		add "${DUMMY_DEVNAME}" type dummy; then791		echo "SKIP: Cannot set up dummy dev to test kernel support for flavors"792 793		ip netns del "${test_netns}"794		exit "${ksft_skip}"795	fi796 797	if ! ip -netns "${test_netns}" link \798		set "${DUMMY_DEVNAME}" up; then799		echo "SKIP: Cannot activate dummy dev to test kernel support for flavors"800 801		ip netns del "${test_netns}"802		exit "${ksft_skip}"803	fi804 805	if ! ip -netns "${test_netns}" -6 route \806		add "${IPv6_TESTS_ADDR}" encap seg6local \807		action End flavors "${flavor}" dev "${DUMMY_DEVNAME}"; then808		echo "SKIP: ${flavor} flavor not supported in kernel"809 810		ip netns del "${test_netns}"811		exit "${ksft_skip}"812	fi813 814	ip netns del "${test_netns}"815}816 817test_dummy_dev_or_ksft_skip()818{819	local test_netns820 821	test_netns="dummy-$(mktemp -u XXXXXXXX)"822 823	if ! ip netns add "${test_netns}"; then824		echo "SKIP: Cannot set up netns for testing dummy dev support"825		exit "${ksft_skip}"826	fi827 828	modprobe dummy &>/dev/null || true829	if ! ip -netns "${test_netns}" link \830		add "${DUMMY_DEVNAME}" type dummy; then831		echo "SKIP: dummy dev not supported"832 833		ip netns del "${test_netns}"834		exit "${ksft_skip}"835	fi836 837	ip netns del "${test_netns}"838}839 840if [ "$(id -u)" -ne 0 ]; then841	echo "SKIP: Need root privileges"842	exit "${ksft_skip}"843fi844 845# required programs to carry out this selftest846test_command_or_ksft_skip ip847test_command_or_ksft_skip ping848test_command_or_ksft_skip sysctl849test_command_or_ksft_skip grep850test_command_or_ksft_skip cut851test_command_or_ksft_skip sed852test_command_or_ksft_skip sort853test_command_or_ksft_skip xargs854 855test_dummy_dev_or_ksft_skip856test_iproute2_supp_or_ksft_skip psp857test_kernel_supp_or_ksft_skip psp858 859set -e860trap cleanup EXIT861 862setup863set +e864 865router_tests866host2gateway_tests867host_srv6_end_flv_psp_tests868 869print_log_test_results870