1*5198cb40SAndrea Mayer#!/bin/bash
2*5198cb40SAndrea Mayer# SPDX-License-Identifier: GPL-2.0
3*5198cb40SAndrea Mayer#
4*5198cb40SAndrea Mayer# author: Andrea Mayer <andrea.mayer@uniroma2.it>
5*5198cb40SAndrea Mayer# author: Paolo Lungaroni <paolo.lungaroni@uniroma2.it>
6*5198cb40SAndrea Mayer#
7*5198cb40SAndrea Mayer# This script is designed to test the support for "flavors" in the SRv6 End
8*5198cb40SAndrea Mayer# behavior.
9*5198cb40SAndrea Mayer#
10*5198cb40SAndrea Mayer# Flavors defined in RFC8986 [1] represent additional operations that can modify
11*5198cb40SAndrea Mayer# or extend the existing SRv6 End, End.X and End.T behaviors. For the sake of
12*5198cb40SAndrea Mayer# convenience, we report the list of flavors described in [1] hereafter:
13*5198cb40SAndrea Mayer#   - Penultimate Segment Pop (PSP);
14*5198cb40SAndrea Mayer#   - Ultimate Segment Pop (USP);
15*5198cb40SAndrea Mayer#   - Ultimate Segment Decapsulation (USD).
16*5198cb40SAndrea Mayer#
17*5198cb40SAndrea Mayer# The End, End.X, and End.T behaviors can support these flavors either
18*5198cb40SAndrea Mayer# individually or in combinations.
19*5198cb40SAndrea Mayer# Currently in this selftest we consider only the PSP flavor for the SRv6 End
20*5198cb40SAndrea Mayer# behavior. However, it is possible to extend the script as soon as other
21*5198cb40SAndrea Mayer# flavors will be supported in the kernel.
22*5198cb40SAndrea Mayer#
23*5198cb40SAndrea Mayer# The purpose of the PSP flavor consists in instructing the penultimate node
24*5198cb40SAndrea Mayer# listed in the SRv6 policy to remove (i.e. pop) the outermost SRH from the IPv6
25*5198cb40SAndrea Mayer# header.
26*5198cb40SAndrea Mayer# A PSP enabled SRv6 End behavior instance processes the SRH by:
27*5198cb40SAndrea Mayer#  - decrementing the Segment Left (SL) value from 1 to 0;
28*5198cb40SAndrea Mayer#  - copying the last SID from the SID List into the IPv6 Destination Address
29*5198cb40SAndrea Mayer#    (DA);
30*5198cb40SAndrea Mayer#  - removing the SRH from the extension headers following the IPv6 header.
31*5198cb40SAndrea Mayer#
32*5198cb40SAndrea Mayer# Once the SRH is removed, the IPv6 packet is forwarded to the destination using
33*5198cb40SAndrea Mayer# the IPv6 DA updated during the PSP operation (i.e. the IPv6 DA corresponding
34*5198cb40SAndrea Mayer# to the last SID carried by the removed SRH).
35*5198cb40SAndrea Mayer#
36*5198cb40SAndrea Mayer# Although the PSP flavor can be set for any SRv6 End behavior instance on any
37*5198cb40SAndrea Mayer# SR node, it will be active only on such behaviors bound to a penultimate SID
38*5198cb40SAndrea Mayer# for a given SRv6 policy.
39*5198cb40SAndrea Mayer#                                                SL=2 SL=1 SL=0
40*5198cb40SAndrea Mayer#                                                  |    |    |
41*5198cb40SAndrea Mayer# For example, given the SRv6 policy (SID List := <X,   Y,   Z>):
42*5198cb40SAndrea Mayer#  - a PSP enabled SRv6 End behavior bound to SID Y will apply the PSP operation
43*5198cb40SAndrea Mayer#    as Segment Left (SL) is 1, corresponding to the Penultimate Segment of the
44*5198cb40SAndrea Mayer#    SID List;
45*5198cb40SAndrea Mayer#  - a PSP enabled SRv6 End behavior bound to SID X will *NOT* apply the PSP
46*5198cb40SAndrea Mayer#    operation as the Segment Left is 2. This behavior instance will apply the
47*5198cb40SAndrea Mayer#    "standard" End packet processing, ignoring the configured PSP flavor at
48*5198cb40SAndrea Mayer#    all.
49*5198cb40SAndrea Mayer#
50*5198cb40SAndrea Mayer# [1] RFC8986: https://datatracker.ietf.org/doc/html/rfc8986
51*5198cb40SAndrea Mayer#
52*5198cb40SAndrea Mayer# Network topology
53*5198cb40SAndrea Mayer# ================
54*5198cb40SAndrea Mayer#
55*5198cb40SAndrea Mayer# The network topology used in this selftest is depicted hereafter, composed by
56*5198cb40SAndrea Mayer# two hosts (hs-1, hs-2) and four routers (rt-1, rt-2, rt-3, rt-4).
57*5198cb40SAndrea Mayer# Hosts hs-1 and hs-2 are connected to routers rt-1 and rt-2, respectively,
58*5198cb40SAndrea Mayer# allowing them to communicate with each other.
59*5198cb40SAndrea Mayer# Traffic exchanged between hs-1 and hs-2 can follow different network paths.
60*5198cb40SAndrea Mayer# The network operator, through specific SRv6 Policies can steer traffic to one
61*5198cb40SAndrea Mayer# path rather than another. In this selftest this is implemented as follows:
62*5198cb40SAndrea Mayer#
63*5198cb40SAndrea Mayer#   i) The SRv6 H.Insert behavior applies SRv6 Policies on traffic received by
64*5198cb40SAndrea Mayer#      connected hosts. It pushes the Segment Routing Header (SRH) after the
65*5198cb40SAndrea Mayer#      IPv6 header. The SRH contains the SID List (i.e. SRv6 Policy) needed for
66*5198cb40SAndrea Mayer#      steering traffic across the segments/waypoints specified in that list;
67*5198cb40SAndrea Mayer#
68*5198cb40SAndrea Mayer#  ii) The SRv6 End behavior advances the active SID in the SID List carried by
69*5198cb40SAndrea Mayer#      the SRH;
70*5198cb40SAndrea Mayer#
71*5198cb40SAndrea Mayer# iii) The PSP enabled SRv6 End behavior is used to remove the SRH when such
72*5198cb40SAndrea Mayer#      behavior is configured on a node bound to the Penultimate Segment carried
73*5198cb40SAndrea Mayer#      by the SID List.
74*5198cb40SAndrea Mayer#
75*5198cb40SAndrea Mayer#                cafe::1                      cafe::2
76*5198cb40SAndrea Mayer#              +--------+                   +--------+
77*5198cb40SAndrea Mayer#              |        |                   |        |
78*5198cb40SAndrea Mayer#              |  hs-1  |                   |  hs-2  |
79*5198cb40SAndrea Mayer#              |        |                   |        |
80*5198cb40SAndrea Mayer#              +---+----+                   +--- +---+
81*5198cb40SAndrea Mayer#     cafe::/64    |                             |      cafe::/64
82*5198cb40SAndrea Mayer#                  |                             |
83*5198cb40SAndrea Mayer#              +---+----+                   +----+---+
84*5198cb40SAndrea Mayer#              |        |  fcf0:0:1:2::/64  |        |
85*5198cb40SAndrea Mayer#              |  rt-1  +-------------------+  rt-2  |
86*5198cb40SAndrea Mayer#              |        |                   |        |
87*5198cb40SAndrea Mayer#              +---+----+                   +----+---+
88*5198cb40SAndrea Mayer#                  |      .               .      |
89*5198cb40SAndrea Mayer#                  |  fcf0:0:1:3::/64   .        |
90*5198cb40SAndrea Mayer#                  |          .       .          |
91*5198cb40SAndrea Mayer#                  |            .   .            |
92*5198cb40SAndrea Mayer#  fcf0:0:1:4::/64 |              .              | fcf0:0:2:3::/64
93*5198cb40SAndrea Mayer#                  |            .   .            |
94*5198cb40SAndrea Mayer#                  |          .       .          |
95*5198cb40SAndrea Mayer#                  |  fcf0:0:2:4::/64   .        |
96*5198cb40SAndrea Mayer#                  |      .               .      |
97*5198cb40SAndrea Mayer#              +---+----+                   +----+---+
98*5198cb40SAndrea Mayer#              |        |                   |        |
99*5198cb40SAndrea Mayer#              |  rt-4  +-------------------+  rt-3  |
100*5198cb40SAndrea Mayer#              |        |  fcf0:0:3:4::/64  |        |
101*5198cb40SAndrea Mayer#              +---+----+                   +----+---+
102*5198cb40SAndrea Mayer#
103*5198cb40SAndrea Mayer# Every fcf0:0:x:y::/64 network interconnects the SRv6 routers rt-x with rt-y in
104*5198cb40SAndrea Mayer# the IPv6 operator network.
105*5198cb40SAndrea Mayer#
106*5198cb40SAndrea Mayer#
107*5198cb40SAndrea Mayer# Local SID table
108*5198cb40SAndrea Mayer# ===============
109*5198cb40SAndrea Mayer#
110*5198cb40SAndrea Mayer# Each SRv6 router is configured with a Local SID table in which SIDs are
111*5198cb40SAndrea Mayer# stored. Considering the given SRv6 router rt-x, at least two SIDs are
112*5198cb40SAndrea Mayer# configured in the Local SID table:
113*5198cb40SAndrea Mayer#
114*5198cb40SAndrea Mayer#   Local SID table for SRv6 router rt-x
115*5198cb40SAndrea Mayer#   +---------------------------------------------------------------------+
116*5198cb40SAndrea Mayer#   |fcff:x::e is associated with the SRv6 End behavior                   |
117*5198cb40SAndrea Mayer#   |fcff:x::ef1 is associated with the SRv6 End behavior with PSP flavor |
118*5198cb40SAndrea Mayer#   +---------------------------------------------------------------------+
119*5198cb40SAndrea Mayer#
120*5198cb40SAndrea Mayer# The fcff::/16 prefix is reserved by the operator for the SIDs. Reachability of
121*5198cb40SAndrea Mayer# SIDs is ensured by proper configuration of the IPv6 operator's network and
122*5198cb40SAndrea Mayer# SRv6 routers.
123*5198cb40SAndrea Mayer#
124*5198cb40SAndrea Mayer#
125*5198cb40SAndrea Mayer# SRv6 Policies
126*5198cb40SAndrea Mayer# =============
127*5198cb40SAndrea Mayer#
128*5198cb40SAndrea Mayer# An SRv6 ingress router applies different SRv6 Policies to the traffic received
129*5198cb40SAndrea Mayer# from connected hosts on the basis of the destination addresses.
130*5198cb40SAndrea Mayer# In case of SRv6 H.Insert behavior, the SRv6 Policy enforcement consists of
131*5198cb40SAndrea Mayer# pushing the SRH (carrying a given SID List) after the existing IPv6 header.
132*5198cb40SAndrea Mayer# Note that in the inserting mode, there is no encapsulation at all.
133*5198cb40SAndrea Mayer#
134*5198cb40SAndrea Mayer#   Before applying an SRv6 Policy using the SRv6 H.Insert behavior
135*5198cb40SAndrea Mayer#   +------+---------+
136*5198cb40SAndrea Mayer#   | IPv6 | Payload |
137*5198cb40SAndrea Mayer#   +------+---------+
138*5198cb40SAndrea Mayer#
139*5198cb40SAndrea Mayer#   After applying an SRv6 Policy using the SRv6 H.Insert behavior
140*5198cb40SAndrea Mayer#   +------+-----+---------+
141*5198cb40SAndrea Mayer#   | IPv6 | SRH | Payload |
142*5198cb40SAndrea Mayer#   +------+-----+---------+
143*5198cb40SAndrea Mayer#
144*5198cb40SAndrea Mayer# Traffic from hs-1 to hs-2
145*5198cb40SAndrea Mayer# -------------------------
146*5198cb40SAndrea Mayer#
147*5198cb40SAndrea Mayer# Packets generated from hs-1 and directed towards hs-2 are
148*5198cb40SAndrea Mayer# handled by rt-1 which applies the following SRv6 Policy:
149*5198cb40SAndrea Mayer#
150*5198cb40SAndrea Mayer#   i.a) IPv6 traffic, SID List=fcff:3::e,fcff:4::ef1,fcff:2::ef1,cafe::2
151*5198cb40SAndrea Mayer#
152*5198cb40SAndrea Mayer# Router rt-1 is configured to enforce the Policy (i.a) through the SRv6
153*5198cb40SAndrea Mayer# H.Insert behavior which pushes the SRH after the existing IPv6 header. This
154*5198cb40SAndrea Mayer# Policy steers the traffic from hs-1 across rt-3, rt-4, rt-2 and finally to the
155*5198cb40SAndrea Mayer# destination hs-2.
156*5198cb40SAndrea Mayer#
157*5198cb40SAndrea Mayer# As the packet reaches the router rt-3, the SRv6 End behavior bound to SID
158*5198cb40SAndrea Mayer# fcff:3::e is triggered. The behavior updates the Segment Left (from SL=3 to
159*5198cb40SAndrea Mayer# SL=2) in the SRH, the IPv6 DA with fcff:4::ef1 and forwards the packet to the
160*5198cb40SAndrea Mayer# next router on the path, i.e. rt-4.
161*5198cb40SAndrea Mayer#
162*5198cb40SAndrea Mayer# When router rt-4 receives the packet, the PSP enabled SRv6 End behavior bound
163*5198cb40SAndrea Mayer# to SID fcff:4::ef1 is executed. Since the SL=2, the PSP operation is *NOT*
164*5198cb40SAndrea Mayer# kicked in and the behavior applies the default End processing: the Segment
165*5198cb40SAndrea Mayer# Left is decreased (from SL=2 to SL=1), the IPv6 DA is updated with the SID
166*5198cb40SAndrea Mayer# fcff:2::ef1 and the packet is forwarded to router rt-2.
167*5198cb40SAndrea Mayer#
168*5198cb40SAndrea Mayer# The PSP enabled SRv6 End behavior on rt-2 is associated with SID fcff:2::ef1
169*5198cb40SAndrea Mayer# and is executed as the packet is received. Because SL=1, the behavior applies
170*5198cb40SAndrea Mayer# the PSP processing on the packet as follows: i) SL is decreased, i.e. from
171*5198cb40SAndrea Mayer# SL=1 to SL=0; ii) last SID (cafe::2) is copied into the IPv6 DA; iii) the
172*5198cb40SAndrea Mayer# outermost SRH is removed from the extension headers following the IPv6 header.
173*5198cb40SAndrea Mayer# Once the PSP processing is completed, the packet is forwarded to the host hs-2
174*5198cb40SAndrea Mayer# (destination).
175*5198cb40SAndrea Mayer#
176*5198cb40SAndrea Mayer# Traffic from hs-2 to hs-1
177*5198cb40SAndrea Mayer# -------------------------
178*5198cb40SAndrea Mayer#
179*5198cb40SAndrea Mayer# Packets generated from hs-2 and directed to hs-1 are handled by rt-2 which
180*5198cb40SAndrea Mayer# applies the following SRv6 Policy:
181*5198cb40SAndrea Mayer#
182*5198cb40SAndrea Mayer#   i.b) IPv6 traffic, SID List=fcff:1::ef1,cafe::1
183*5198cb40SAndrea Mayer#
184*5198cb40SAndrea Mayer# Router rt-2 is configured to enforce the Policy (i.b) through the SRv6
185*5198cb40SAndrea Mayer# H.Insert behavior which pushes the SRH after the existing IPv6 header. This
186*5198cb40SAndrea Mayer# Policy steers the traffic from hs-2 across rt-1 and finally to the
187*5198cb40SAndrea Mayer# destination hs-1
188*5198cb40SAndrea Mayer#
189*5198cb40SAndrea Mayer#
190*5198cb40SAndrea Mayer# When the router rt-1 receives the packet, the PSP enabled SRv6 End behavior
191*5198cb40SAndrea Mayer# associated with the SID fcff:1::ef1 is triggered. Since the SL=1,
192*5198cb40SAndrea Mayer# the PSP operation takes place: i) the SL is decremented; ii) the IPv6 DA is
193*5198cb40SAndrea Mayer# set with the last SID; iii) the SRH is removed from the extension headers
194*5198cb40SAndrea Mayer# after the IPv6 header. At this point, the packet with IPv6 DA=cafe::1 is sent
195*5198cb40SAndrea Mayer# to the destination, i.e. hs-1.
196*5198cb40SAndrea Mayer
197*5198cb40SAndrea Mayer# Kselftest framework requirement - SKIP code is 4.
198*5198cb40SAndrea Mayerreadonly ksft_skip=4
199*5198cb40SAndrea Mayer
200*5198cb40SAndrea Mayerreadonly RDMSUFF="$(mktemp -u XXXXXXXX)"
201*5198cb40SAndrea Mayerreadonly DUMMY_DEVNAME="dum0"
202*5198cb40SAndrea Mayerreadonly RT2HS_DEVNAME="veth1"
203*5198cb40SAndrea Mayerreadonly LOCALSID_TABLE_ID=90
204*5198cb40SAndrea Mayerreadonly IPv6_RT_NETWORK=fcf0:0
205*5198cb40SAndrea Mayerreadonly IPv6_HS_NETWORK=cafe
206*5198cb40SAndrea Mayerreadonly IPv6_TESTS_ADDR=2001:db8::1
207*5198cb40SAndrea Mayerreadonly LOCATOR_SERVICE=fcff
208*5198cb40SAndrea Mayerreadonly END_FUNC=000e
209*5198cb40SAndrea Mayerreadonly END_PSP_FUNC=0ef1
210*5198cb40SAndrea Mayer
211*5198cb40SAndrea MayerPING_TIMEOUT_SEC=4
212*5198cb40SAndrea MayerPAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
213*5198cb40SAndrea Mayer
214*5198cb40SAndrea Mayer# IDs of routers and hosts are initialized during the setup of the testing
215*5198cb40SAndrea Mayer# network
216*5198cb40SAndrea MayerROUTERS=''
217*5198cb40SAndrea MayerHOSTS=''
218*5198cb40SAndrea Mayer
219*5198cb40SAndrea MayerSETUP_ERR=1
220*5198cb40SAndrea Mayer
221*5198cb40SAndrea Mayerret=${ksft_skip}
222*5198cb40SAndrea Mayernsuccess=0
223*5198cb40SAndrea Mayernfail=0
224*5198cb40SAndrea Mayer
225*5198cb40SAndrea Mayerlog_test()
226*5198cb40SAndrea Mayer{
227*5198cb40SAndrea Mayer	local rc="$1"
228*5198cb40SAndrea Mayer	local expected="$2"
229*5198cb40SAndrea Mayer	local msg="$3"
230*5198cb40SAndrea Mayer
231*5198cb40SAndrea Mayer	if [ "${rc}" -eq "${expected}" ]; then
232*5198cb40SAndrea Mayer		nsuccess=$((nsuccess+1))
233*5198cb40SAndrea Mayer		printf "\n    TEST: %-60s  [ OK ]\n" "${msg}"
234*5198cb40SAndrea Mayer	else
235*5198cb40SAndrea Mayer		ret=1
236*5198cb40SAndrea Mayer		nfail=$((nfail+1))
237*5198cb40SAndrea Mayer		printf "\n    TEST: %-60s  [FAIL]\n" "${msg}"
238*5198cb40SAndrea Mayer		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
239*5198cb40SAndrea Mayer			echo
240*5198cb40SAndrea Mayer			echo "hit enter to continue, 'q' to quit"
241*5198cb40SAndrea Mayer			read a
242*5198cb40SAndrea Mayer			[ "$a" = "q" ] && exit 1
243*5198cb40SAndrea Mayer		fi
244*5198cb40SAndrea Mayer	fi
245*5198cb40SAndrea Mayer}
246*5198cb40SAndrea Mayer
247*5198cb40SAndrea Mayerprint_log_test_results()
248*5198cb40SAndrea Mayer{
249*5198cb40SAndrea Mayer	printf "\nTests passed: %3d\n" "${nsuccess}"
250*5198cb40SAndrea Mayer	printf "Tests failed: %3d\n"   "${nfail}"
251*5198cb40SAndrea Mayer
252*5198cb40SAndrea Mayer	# when a test fails, the value of 'ret' is set to 1 (error code).
253*5198cb40SAndrea Mayer	# Conversely, when all tests are passed successfully, the 'ret' value
254*5198cb40SAndrea Mayer	# is set to 0 (success code).
255*5198cb40SAndrea Mayer	if [ "${ret}" -ne 1 ]; then
256*5198cb40SAndrea Mayer		ret=0
257*5198cb40SAndrea Mayer	fi
258*5198cb40SAndrea Mayer}
259*5198cb40SAndrea Mayer
260*5198cb40SAndrea Mayerlog_section()
261*5198cb40SAndrea Mayer{
262*5198cb40SAndrea Mayer	echo
263*5198cb40SAndrea Mayer	echo "################################################################################"
264*5198cb40SAndrea Mayer	echo "TEST SECTION: $*"
265*5198cb40SAndrea Mayer	echo "################################################################################"
266*5198cb40SAndrea Mayer}
267*5198cb40SAndrea Mayer
268*5198cb40SAndrea Mayertest_command_or_ksft_skip()
269*5198cb40SAndrea Mayer{
270*5198cb40SAndrea Mayer	local cmd="$1"
271*5198cb40SAndrea Mayer
272*5198cb40SAndrea Mayer	if [ ! -x "$(command -v "${cmd}")" ]; then
273*5198cb40SAndrea Mayer		echo "SKIP: Could not run test without \"${cmd}\" tool";
274*5198cb40SAndrea Mayer		exit "${ksft_skip}"
275*5198cb40SAndrea Mayer	fi
276*5198cb40SAndrea Mayer}
277*5198cb40SAndrea Mayer
278*5198cb40SAndrea Mayerget_nodename()
279*5198cb40SAndrea Mayer{
280*5198cb40SAndrea Mayer	local name="$1"
281*5198cb40SAndrea Mayer
282*5198cb40SAndrea Mayer	echo "${name}-${RDMSUFF}"
283*5198cb40SAndrea Mayer}
284*5198cb40SAndrea Mayer
285*5198cb40SAndrea Mayerget_rtname()
286*5198cb40SAndrea Mayer{
287*5198cb40SAndrea Mayer	local rtid="$1"
288*5198cb40SAndrea Mayer
289*5198cb40SAndrea Mayer	get_nodename "rt-${rtid}"
290*5198cb40SAndrea Mayer}
291*5198cb40SAndrea Mayer
292*5198cb40SAndrea Mayerget_hsname()
293*5198cb40SAndrea Mayer{
294*5198cb40SAndrea Mayer	local hsid="$1"
295*5198cb40SAndrea Mayer
296*5198cb40SAndrea Mayer	get_nodename "hs-${hsid}"
297*5198cb40SAndrea Mayer}
298*5198cb40SAndrea Mayer
299*5198cb40SAndrea Mayer__create_namespace()
300*5198cb40SAndrea Mayer{
301*5198cb40SAndrea Mayer	local name="$1"
302*5198cb40SAndrea Mayer
303*5198cb40SAndrea Mayer	ip netns add "${name}"
304*5198cb40SAndrea Mayer}
305*5198cb40SAndrea Mayer
306*5198cb40SAndrea Mayercreate_router()
307*5198cb40SAndrea Mayer{
308*5198cb40SAndrea Mayer	local rtid="$1"
309*5198cb40SAndrea Mayer	local nsname
310*5198cb40SAndrea Mayer
311*5198cb40SAndrea Mayer	nsname="$(get_rtname "${rtid}")"
312*5198cb40SAndrea Mayer
313*5198cb40SAndrea Mayer	__create_namespace "${nsname}"
314*5198cb40SAndrea Mayer}
315*5198cb40SAndrea Mayer
316*5198cb40SAndrea Mayercreate_host()
317*5198cb40SAndrea Mayer{
318*5198cb40SAndrea Mayer	local hsid="$1"
319*5198cb40SAndrea Mayer	local nsname
320*5198cb40SAndrea Mayer
321*5198cb40SAndrea Mayer	nsname="$(get_hsname "${hsid}")"
322*5198cb40SAndrea Mayer
323*5198cb40SAndrea Mayer	__create_namespace "${nsname}"
324*5198cb40SAndrea Mayer}
325*5198cb40SAndrea Mayer
326*5198cb40SAndrea Mayercleanup()
327*5198cb40SAndrea Mayer{
328*5198cb40SAndrea Mayer	local nsname
329*5198cb40SAndrea Mayer	local i
330*5198cb40SAndrea Mayer
331*5198cb40SAndrea Mayer	# destroy routers
332*5198cb40SAndrea Mayer	for i in ${ROUTERS}; do
333*5198cb40SAndrea Mayer		nsname="$(get_rtname "${i}")"
334*5198cb40SAndrea Mayer
335*5198cb40SAndrea Mayer		ip netns del "${nsname}" &>/dev/null || true
336*5198cb40SAndrea Mayer	done
337*5198cb40SAndrea Mayer
338*5198cb40SAndrea Mayer	# destroy hosts
339*5198cb40SAndrea Mayer	for i in ${HOSTS}; do
340*5198cb40SAndrea Mayer		nsname="$(get_hsname "${i}")"
341*5198cb40SAndrea Mayer
342*5198cb40SAndrea Mayer		ip netns del "${nsname}" &>/dev/null || true
343*5198cb40SAndrea Mayer	done
344*5198cb40SAndrea Mayer
345*5198cb40SAndrea Mayer	# check whether the setup phase was completed successfully or not. In
346*5198cb40SAndrea Mayer	# case of an error during the setup phase of the testing environment,
347*5198cb40SAndrea Mayer	# the selftest is considered as "skipped".
348*5198cb40SAndrea Mayer	if [ "${SETUP_ERR}" -ne 0 ]; then
349*5198cb40SAndrea Mayer		echo "SKIP: Setting up the testing environment failed"
350*5198cb40SAndrea Mayer		exit "${ksft_skip}"
351*5198cb40SAndrea Mayer	fi
352*5198cb40SAndrea Mayer
353*5198cb40SAndrea Mayer	exit "${ret}"
354*5198cb40SAndrea Mayer}
355*5198cb40SAndrea Mayer
356*5198cb40SAndrea Mayeradd_link_rt_pairs()
357*5198cb40SAndrea Mayer{
358*5198cb40SAndrea Mayer	local rt="$1"
359*5198cb40SAndrea Mayer	local rt_neighs="$2"
360*5198cb40SAndrea Mayer	local neigh
361*5198cb40SAndrea Mayer	local nsname
362*5198cb40SAndrea Mayer	local neigh_nsname
363*5198cb40SAndrea Mayer
364*5198cb40SAndrea Mayer	nsname="$(get_rtname "${rt}")"
365*5198cb40SAndrea Mayer
366*5198cb40SAndrea Mayer	for neigh in ${rt_neighs}; do
367*5198cb40SAndrea Mayer		neigh_nsname="$(get_rtname "${neigh}")"
368*5198cb40SAndrea Mayer
369*5198cb40SAndrea Mayer		ip link add "veth-rt-${rt}-${neigh}" netns "${nsname}" \
370*5198cb40SAndrea Mayer			type veth peer name "veth-rt-${neigh}-${rt}" \
371*5198cb40SAndrea Mayer			netns "${neigh_nsname}"
372*5198cb40SAndrea Mayer	done
373*5198cb40SAndrea Mayer}
374*5198cb40SAndrea Mayer
375*5198cb40SAndrea Mayerget_network_prefix()
376*5198cb40SAndrea Mayer{
377*5198cb40SAndrea Mayer	local rt="$1"
378*5198cb40SAndrea Mayer	local neigh="$2"
379*5198cb40SAndrea Mayer	local p="${rt}"
380*5198cb40SAndrea Mayer	local q="${neigh}"
381*5198cb40SAndrea Mayer
382*5198cb40SAndrea Mayer	if [ "${p}" -gt "${q}" ]; then
383*5198cb40SAndrea Mayer		p="${q}"; q="${rt}"
384*5198cb40SAndrea Mayer	fi
385*5198cb40SAndrea Mayer
386*5198cb40SAndrea Mayer	echo "${IPv6_RT_NETWORK}:${p}:${q}"
387*5198cb40SAndrea Mayer}
388*5198cb40SAndrea Mayer
389*5198cb40SAndrea Mayer# Given the description of a router <id:op> as an input, the function returns
390*5198cb40SAndrea Mayer# the <id> token which represents the ID of the router.
391*5198cb40SAndrea Mayer# i.e. input: "12:psp"
392*5198cb40SAndrea Mayer#      output: "12"
393*5198cb40SAndrea Mayer__get_srv6_rtcfg_id()
394*5198cb40SAndrea Mayer{
395*5198cb40SAndrea Mayer	local element="$1"
396*5198cb40SAndrea Mayer
397*5198cb40SAndrea Mayer	echo "${element}" | cut -d':' -f1
398*5198cb40SAndrea Mayer}
399*5198cb40SAndrea Mayer
400*5198cb40SAndrea Mayer# Given the description of a router <id:op> as an input, the function returns
401*5198cb40SAndrea Mayer# the <op> token which represents the operation (e.g. End behavior with or
402*5198cb40SAndrea Mayer# withouth flavors) configured for the node.
403*5198cb40SAndrea Mayer
404*5198cb40SAndrea Mayer# Note that when the operation represents an End behavior with a list of
405*5198cb40SAndrea Mayer# flavors, the output is the ordered version of that list.
406*5198cb40SAndrea Mayer# i.e. input: "5:usp,psp,usd"
407*5198cb40SAndrea Mayer#      output: "psp,usd,usp"
408*5198cb40SAndrea Mayer__get_srv6_rtcfg_op()
409*5198cb40SAndrea Mayer{
410*5198cb40SAndrea Mayer	local element="$1"
411*5198cb40SAndrea Mayer
412*5198cb40SAndrea Mayer	# return the lexicographically ordered flavors
413*5198cb40SAndrea Mayer	echo "${element}" | cut -d':' -f2 | sed 's/,/\n/g' | sort | \
414*5198cb40SAndrea Mayer		xargs | sed 's/ /,/g'
415*5198cb40SAndrea Mayer}
416*5198cb40SAndrea Mayer
417*5198cb40SAndrea Mayer# Setup the basic networking for the routers
418*5198cb40SAndrea Mayersetup_rt_networking()
419*5198cb40SAndrea Mayer{
420*5198cb40SAndrea Mayer	local rt="$1"
421*5198cb40SAndrea Mayer	local rt_neighs="$2"
422*5198cb40SAndrea Mayer	local nsname
423*5198cb40SAndrea Mayer	local net_prefix
424*5198cb40SAndrea Mayer	local devname
425*5198cb40SAndrea Mayer	local neigh
426*5198cb40SAndrea Mayer
427*5198cb40SAndrea Mayer	nsname="$(get_rtname "${rt}")"
428*5198cb40SAndrea Mayer
429*5198cb40SAndrea Mayer	for neigh in ${rt_neighs}; do
430*5198cb40SAndrea Mayer		devname="veth-rt-${rt}-${neigh}"
431*5198cb40SAndrea Mayer
432*5198cb40SAndrea Mayer		net_prefix="$(get_network_prefix "${rt}" "${neigh}")"
433*5198cb40SAndrea Mayer
434*5198cb40SAndrea Mayer		ip -netns "${nsname}" addr \
435*5198cb40SAndrea Mayer			add "${net_prefix}::${rt}/64" dev "${devname}" nodad
436*5198cb40SAndrea Mayer
437*5198cb40SAndrea Mayer		ip -netns "${nsname}" link set "${devname}" up
438*5198cb40SAndrea Mayer	done
439*5198cb40SAndrea Mayer
440*5198cb40SAndrea Mayer	ip -netns "${nsname}" link set lo up
441*5198cb40SAndrea Mayer
442*5198cb40SAndrea Mayer	ip -netns "${nsname}" link add ${DUMMY_DEVNAME} type dummy
443*5198cb40SAndrea Mayer	ip -netns "${nsname}" link set ${DUMMY_DEVNAME} up
444*5198cb40SAndrea Mayer
445*5198cb40SAndrea Mayer	ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0
446*5198cb40SAndrea Mayer	ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0
447*5198cb40SAndrea Mayer	ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.forwarding=1
448*5198cb40SAndrea Mayer}
449*5198cb40SAndrea Mayer
450*5198cb40SAndrea Mayer# Setup local SIDs for an SRv6 router
451*5198cb40SAndrea Mayersetup_rt_local_sids()
452*5198cb40SAndrea Mayer{
453*5198cb40SAndrea Mayer	local rt="$1"
454*5198cb40SAndrea Mayer	local rt_neighs="$2"
455*5198cb40SAndrea Mayer	local net_prefix
456*5198cb40SAndrea Mayer	local devname
457*5198cb40SAndrea Mayer	local nsname
458*5198cb40SAndrea Mayer	local neigh
459*5198cb40SAndrea Mayer
460*5198cb40SAndrea Mayer	nsname="$(get_rtname "${rt}")"
461*5198cb40SAndrea Mayer
462*5198cb40SAndrea Mayer	for neigh in ${rt_neighs}; do
463*5198cb40SAndrea Mayer		devname="veth-rt-${rt}-${neigh}"
464*5198cb40SAndrea Mayer
465*5198cb40SAndrea Mayer		net_prefix="$(get_network_prefix "${rt}" "${neigh}")"
466*5198cb40SAndrea Mayer
467*5198cb40SAndrea Mayer		# set underlay network routes for SIDs reachability
468*5198cb40SAndrea Mayer		ip -netns "${nsname}" -6 route \
469*5198cb40SAndrea Mayer			add "${LOCATOR_SERVICE}:${neigh}::/32" \
470*5198cb40SAndrea Mayer			table "${LOCALSID_TABLE_ID}" \
471*5198cb40SAndrea Mayer			via "${net_prefix}::${neigh}" dev "${devname}"
472*5198cb40SAndrea Mayer	done
473*5198cb40SAndrea Mayer
474*5198cb40SAndrea Mayer	# Local End behavior (note that "dev" is a dummy interface chosen for
475*5198cb40SAndrea Mayer	# the sake of simplicity).
476*5198cb40SAndrea Mayer	ip -netns "${nsname}" -6 route \
477*5198cb40SAndrea Mayer		add "${LOCATOR_SERVICE}:${rt}::${END_FUNC}" \
478*5198cb40SAndrea Mayer		table "${LOCALSID_TABLE_ID}" \
479*5198cb40SAndrea Mayer		encap seg6local action End dev "${DUMMY_DEVNAME}"
480*5198cb40SAndrea Mayer
481*5198cb40SAndrea Mayer
482*5198cb40SAndrea Mayer	# all SIDs start with a common locator. Routes and SRv6 Endpoint
483*5198cb40SAndrea Mayer	# behavior instaces are grouped together in the 'localsid' table.
484*5198cb40SAndrea Mayer	ip -netns "${nsname}" -6 rule \
485*5198cb40SAndrea Mayer		add to "${LOCATOR_SERVICE}::/16" \
486*5198cb40SAndrea Mayer		lookup "${LOCALSID_TABLE_ID}" prio 999
487*5198cb40SAndrea Mayer
488*5198cb40SAndrea Mayer	# set default routes to unreachable
489*5198cb40SAndrea Mayer	ip -netns "${nsname}" -6 route \
490*5198cb40SAndrea Mayer		add unreachable default metric 4278198272 \
491*5198cb40SAndrea Mayer		dev "${DUMMY_DEVNAME}"
492*5198cb40SAndrea Mayer}
493*5198cb40SAndrea Mayer
494*5198cb40SAndrea Mayer# This helper function builds and installs the SID List (i.e. SRv6 Policy)
495*5198cb40SAndrea Mayer# to be applied on incoming packets at the ingress node. Moreover, it
496*5198cb40SAndrea Mayer# configures the SRv6 nodes specified in the SID List to process the traffic
497*5198cb40SAndrea Mayer# according to the operations required by the Policy itself.
498*5198cb40SAndrea Mayer# args:
499*5198cb40SAndrea Mayer#  $1 - destination host (i.e. cafe::x host)
500*5198cb40SAndrea Mayer#  $2 - SRv6 router configured for enforcing the SRv6 Policy
501*5198cb40SAndrea Mayer#  $3 - compact way to represent a list of SRv6 routers with their operations
502*5198cb40SAndrea Mayer#       (i.e. behaviors) that each of them needs to perform. Every <nodeid:op>
503*5198cb40SAndrea Mayer#       element constructs a SID that is associated with the behavior <op> on
504*5198cb40SAndrea Mayer#       the <nodeid> node. The list of such elements forms an SRv6 Policy.
505*5198cb40SAndrea Mayer__setup_rt_policy()
506*5198cb40SAndrea Mayer{
507*5198cb40SAndrea Mayer	local dst="$1"
508*5198cb40SAndrea Mayer	local encap_rt="$2"
509*5198cb40SAndrea Mayer	local policy_rts="$3"
510*5198cb40SAndrea Mayer	local behavior_cfg
511*5198cb40SAndrea Mayer	local in_nsname
512*5198cb40SAndrea Mayer	local rt_nsname
513*5198cb40SAndrea Mayer	local policy=''
514*5198cb40SAndrea Mayer	local function
515*5198cb40SAndrea Mayer	local fullsid
516*5198cb40SAndrea Mayer	local op_type
517*5198cb40SAndrea Mayer	local node
518*5198cb40SAndrea Mayer	local n
519*5198cb40SAndrea Mayer
520*5198cb40SAndrea Mayer	in_nsname="$(get_rtname "${encap_rt}")"
521*5198cb40SAndrea Mayer
522*5198cb40SAndrea Mayer	for n in ${policy_rts}; do
523*5198cb40SAndrea Mayer		node="$(__get_srv6_rtcfg_id "${n}")"
524*5198cb40SAndrea Mayer		op_type="$(__get_srv6_rtcfg_op "${n}")"
525*5198cb40SAndrea Mayer		rt_nsname="$(get_rtname "${node}")"
526*5198cb40SAndrea Mayer
527*5198cb40SAndrea Mayer		case "${op_type}" in
528*5198cb40SAndrea Mayer		"noflv")
529*5198cb40SAndrea Mayer			policy="${policy}${LOCATOR_SERVICE}:${node}::${END_FUNC},"
530*5198cb40SAndrea Mayer			function="${END_FUNC}"
531*5198cb40SAndrea Mayer			behavior_cfg="End"
532*5198cb40SAndrea Mayer			;;
533*5198cb40SAndrea Mayer
534*5198cb40SAndrea Mayer		"psp")
535*5198cb40SAndrea Mayer			policy="${policy}${LOCATOR_SERVICE}:${node}::${END_PSP_FUNC},"
536*5198cb40SAndrea Mayer			function="${END_PSP_FUNC}"
537*5198cb40SAndrea Mayer			behavior_cfg="End flavors psp"
538*5198cb40SAndrea Mayer			;;
539*5198cb40SAndrea Mayer
540*5198cb40SAndrea Mayer		*)
541*5198cb40SAndrea Mayer			break
542*5198cb40SAndrea Mayer			;;
543*5198cb40SAndrea Mayer		esac
544*5198cb40SAndrea Mayer
545*5198cb40SAndrea Mayer		fullsid="${LOCATOR_SERVICE}:${node}::${function}"
546*5198cb40SAndrea Mayer
547*5198cb40SAndrea Mayer		# add SRv6 Endpoint behavior to the selected router
548*5198cb40SAndrea Mayer		if ! ip -netns "${rt_nsname}" -6 route get "${fullsid}" \
549*5198cb40SAndrea Mayer			&>/dev/null; then
550*5198cb40SAndrea Mayer			ip -netns "${rt_nsname}" -6 route \
551*5198cb40SAndrea Mayer				add "${fullsid}" \
552*5198cb40SAndrea Mayer				table "${LOCALSID_TABLE_ID}" \
553*5198cb40SAndrea Mayer				encap seg6local action ${behavior_cfg} \
554*5198cb40SAndrea Mayer				dev "${DUMMY_DEVNAME}"
555*5198cb40SAndrea Mayer		fi
556*5198cb40SAndrea Mayer	done
557*5198cb40SAndrea Mayer
558*5198cb40SAndrea Mayer	# we need to remove the trailing comma to avoid inserting an empty
559*5198cb40SAndrea Mayer	# address (::0) in the SID List.
560*5198cb40SAndrea Mayer	policy="${policy%,}"
561*5198cb40SAndrea Mayer
562*5198cb40SAndrea Mayer	# add SRv6 policy to incoming traffic sent by connected hosts
563*5198cb40SAndrea Mayer	ip -netns "${in_nsname}" -6 route \
564*5198cb40SAndrea Mayer		add "${IPv6_HS_NETWORK}::${dst}" \
565*5198cb40SAndrea Mayer		encap seg6 mode inline segs "${policy}" \
566*5198cb40SAndrea Mayer		dev "${DUMMY_DEVNAME}"
567*5198cb40SAndrea Mayer
568*5198cb40SAndrea Mayer	ip -netns "${in_nsname}" -6 neigh \
569*5198cb40SAndrea Mayer		add proxy "${IPv6_HS_NETWORK}::${dst}" \
570*5198cb40SAndrea Mayer		dev "${RT2HS_DEVNAME}"
571*5198cb40SAndrea Mayer}
572*5198cb40SAndrea Mayer
573*5198cb40SAndrea Mayer# see __setup_rt_policy
574*5198cb40SAndrea Mayersetup_rt_policy_ipv6()
575*5198cb40SAndrea Mayer{
576*5198cb40SAndrea Mayer	__setup_rt_policy "$1" "$2" "$3"
577*5198cb40SAndrea Mayer}
578*5198cb40SAndrea Mayer
579*5198cb40SAndrea Mayersetup_hs()
580*5198cb40SAndrea Mayer{
581*5198cb40SAndrea Mayer	local hs="$1"
582*5198cb40SAndrea Mayer	local rt="$2"
583*5198cb40SAndrea Mayer	local hsname
584*5198cb40SAndrea Mayer	local rtname
585*5198cb40SAndrea Mayer
586*5198cb40SAndrea Mayer	hsname="$(get_hsname "${hs}")"
587*5198cb40SAndrea Mayer	rtname="$(get_rtname "${rt}")"
588*5198cb40SAndrea Mayer
589*5198cb40SAndrea Mayer	ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0
590*5198cb40SAndrea Mayer	ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0
591*5198cb40SAndrea Mayer
592*5198cb40SAndrea Mayer	ip -netns "${hsname}" link add veth0 type veth \
593*5198cb40SAndrea Mayer		peer name "${RT2HS_DEVNAME}" netns "${rtname}"
594*5198cb40SAndrea Mayer
595*5198cb40SAndrea Mayer	ip -netns "${hsname}" addr \
596*5198cb40SAndrea Mayer		add "${IPv6_HS_NETWORK}::${hs}/64" dev veth0 nodad
597*5198cb40SAndrea Mayer
598*5198cb40SAndrea Mayer	ip -netns "${hsname}" link set veth0 up
599*5198cb40SAndrea Mayer	ip -netns "${hsname}" link set lo up
600*5198cb40SAndrea Mayer
601*5198cb40SAndrea Mayer	ip -netns "${rtname}" addr \
602*5198cb40SAndrea Mayer		add "${IPv6_HS_NETWORK}::254/64" dev "${RT2HS_DEVNAME}" nodad
603*5198cb40SAndrea Mayer
604*5198cb40SAndrea Mayer	ip -netns "${rtname}" link set "${RT2HS_DEVNAME}" up
605*5198cb40SAndrea Mayer
606*5198cb40SAndrea Mayer	ip netns exec "${rtname}" \
607*5198cb40SAndrea Mayer		sysctl -wq net.ipv6.conf."${RT2HS_DEVNAME}".proxy_ndp=1
608*5198cb40SAndrea Mayer}
609*5198cb40SAndrea Mayer
610*5198cb40SAndrea Mayersetup()
611*5198cb40SAndrea Mayer{
612*5198cb40SAndrea Mayer	local i
613*5198cb40SAndrea Mayer
614*5198cb40SAndrea Mayer	# create routers
615*5198cb40SAndrea Mayer	ROUTERS="1 2 3 4"; readonly ROUTERS
616*5198cb40SAndrea Mayer	for i in ${ROUTERS}; do
617*5198cb40SAndrea Mayer		create_router "${i}"
618*5198cb40SAndrea Mayer	done
619*5198cb40SAndrea Mayer
620*5198cb40SAndrea Mayer	# create hosts
621*5198cb40SAndrea Mayer	HOSTS="1 2"; readonly HOSTS
622*5198cb40SAndrea Mayer	for i in ${HOSTS}; do
623*5198cb40SAndrea Mayer		create_host "${i}"
624*5198cb40SAndrea Mayer	done
625*5198cb40SAndrea Mayer
626*5198cb40SAndrea Mayer	# set up the links for connecting routers
627*5198cb40SAndrea Mayer	add_link_rt_pairs 1 "2 3 4"
628*5198cb40SAndrea Mayer	add_link_rt_pairs 2 "3 4"
629*5198cb40SAndrea Mayer	add_link_rt_pairs 3 "4"
630*5198cb40SAndrea Mayer
631*5198cb40SAndrea Mayer	# set up the basic connectivity of routers and routes required for
632*5198cb40SAndrea Mayer	# reachability of SIDs.
633*5198cb40SAndrea Mayer	setup_rt_networking 1 "2 3 4"
634*5198cb40SAndrea Mayer	setup_rt_networking 2 "1 3 4"
635*5198cb40SAndrea Mayer	setup_rt_networking 3 "1 2 4"
636*5198cb40SAndrea Mayer	setup_rt_networking 4 "1 2 3"
637*5198cb40SAndrea Mayer
638*5198cb40SAndrea Mayer	# set up the hosts connected to routers
639*5198cb40SAndrea Mayer	setup_hs 1 1
640*5198cb40SAndrea Mayer	setup_hs 2 2
641*5198cb40SAndrea Mayer
642*5198cb40SAndrea Mayer	# set up default SRv6 Endpoints (i.e. SRv6 End behavior)
643*5198cb40SAndrea Mayer	setup_rt_local_sids 1 "2 3 4"
644*5198cb40SAndrea Mayer	setup_rt_local_sids 2 "1 3 4"
645*5198cb40SAndrea Mayer	setup_rt_local_sids 3 "1 2 4"
646*5198cb40SAndrea Mayer	setup_rt_local_sids 4 "1 2 3"
647*5198cb40SAndrea Mayer
648*5198cb40SAndrea Mayer	# set up SRv6 policies
649*5198cb40SAndrea Mayer	# create a connection between hosts hs-1 and hs-2.
650*5198cb40SAndrea Mayer	# The path between hs-1 and hs-2 traverses SRv6 aware routers.
651*5198cb40SAndrea Mayer	# For each direction two path are chosen:
652*5198cb40SAndrea Mayer	#
653*5198cb40SAndrea Mayer	# Direction hs-1 -> hs-2 (PSP flavor)
654*5198cb40SAndrea Mayer	#  - rt-1 (SRv6 H.Insert policy)
655*5198cb40SAndrea Mayer	#  - rt-3 (SRv6 End behavior)
656*5198cb40SAndrea Mayer	#  - rt-4 (SRv6 End flavor PSP with SL>1, acting as End behavior)
657*5198cb40SAndrea Mayer	#  - rt-2 (SRv6 End flavor PSP with SL=1)
658*5198cb40SAndrea Mayer	#
659*5198cb40SAndrea Mayer	# Direction hs-2 -> hs-1 (PSP flavor)
660*5198cb40SAndrea Mayer	#  - rt-2 (SRv6 H.Insert policy)
661*5198cb40SAndrea Mayer	#  - rt-1 (SRv6 End flavor PSP with SL=1)
662*5198cb40SAndrea Mayer	setup_rt_policy_ipv6 2 1 "3:noflv 4:psp 2:psp"
663*5198cb40SAndrea Mayer	setup_rt_policy_ipv6 1 2 "1:psp"
664*5198cb40SAndrea Mayer
665*5198cb40SAndrea Mayer	# testing environment was set up successfully
666*5198cb40SAndrea Mayer	SETUP_ERR=0
667*5198cb40SAndrea Mayer}
668*5198cb40SAndrea Mayer
669*5198cb40SAndrea Mayercheck_rt_connectivity()
670*5198cb40SAndrea Mayer{
671*5198cb40SAndrea Mayer	local rtsrc="$1"
672*5198cb40SAndrea Mayer	local rtdst="$2"
673*5198cb40SAndrea Mayer	local prefix
674*5198cb40SAndrea Mayer	local rtsrc_nsname
675*5198cb40SAndrea Mayer
676*5198cb40SAndrea Mayer	rtsrc_nsname="$(get_rtname "${rtsrc}")"
677*5198cb40SAndrea Mayer
678*5198cb40SAndrea Mayer	prefix="$(get_network_prefix "${rtsrc}" "${rtdst}")"
679*5198cb40SAndrea Mayer
680*5198cb40SAndrea Mayer	ip netns exec "${rtsrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \
681*5198cb40SAndrea Mayer		"${prefix}::${rtdst}" >/dev/null 2>&1
682*5198cb40SAndrea Mayer}
683*5198cb40SAndrea Mayer
684*5198cb40SAndrea Mayercheck_and_log_rt_connectivity()
685*5198cb40SAndrea Mayer{
686*5198cb40SAndrea Mayer	local rtsrc="$1"
687*5198cb40SAndrea Mayer	local rtdst="$2"
688*5198cb40SAndrea Mayer
689*5198cb40SAndrea Mayer	check_rt_connectivity "${rtsrc}" "${rtdst}"
690*5198cb40SAndrea Mayer	log_test $? 0 "Routers connectivity: rt-${rtsrc} -> rt-${rtdst}"
691*5198cb40SAndrea Mayer}
692*5198cb40SAndrea Mayer
693*5198cb40SAndrea Mayercheck_hs_ipv6_connectivity()
694*5198cb40SAndrea Mayer{
695*5198cb40SAndrea Mayer	local hssrc="$1"
696*5198cb40SAndrea Mayer	local hsdst="$2"
697*5198cb40SAndrea Mayer	local hssrc_nsname
698*5198cb40SAndrea Mayer
699*5198cb40SAndrea Mayer	hssrc_nsname="$(get_hsname "${hssrc}")"
700*5198cb40SAndrea Mayer
701*5198cb40SAndrea Mayer	ip netns exec "${hssrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \
702*5198cb40SAndrea Mayer		"${IPv6_HS_NETWORK}::${hsdst}" >/dev/null 2>&1
703*5198cb40SAndrea Mayer}
704*5198cb40SAndrea Mayer
705*5198cb40SAndrea Mayercheck_and_log_hs2gw_connectivity()
706*5198cb40SAndrea Mayer{
707*5198cb40SAndrea Mayer	local hssrc="$1"
708*5198cb40SAndrea Mayer
709*5198cb40SAndrea Mayer	check_hs_ipv6_connectivity "${hssrc}" 254
710*5198cb40SAndrea Mayer	log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> gw"
711*5198cb40SAndrea Mayer}
712*5198cb40SAndrea Mayer
713*5198cb40SAndrea Mayercheck_and_log_hs_ipv6_connectivity()
714*5198cb40SAndrea Mayer{
715*5198cb40SAndrea Mayer	local hssrc="$1"
716*5198cb40SAndrea Mayer	local hsdst="$2"
717*5198cb40SAndrea Mayer
718*5198cb40SAndrea Mayer	check_hs_ipv6_connectivity "${hssrc}" "${hsdst}"
719*5198cb40SAndrea Mayer	log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> hs-${hsdst}"
720*5198cb40SAndrea Mayer}
721*5198cb40SAndrea Mayer
722*5198cb40SAndrea Mayercheck_and_log_hs_connectivity()
723*5198cb40SAndrea Mayer{
724*5198cb40SAndrea Mayer	local hssrc="$1"
725*5198cb40SAndrea Mayer	local hsdst="$2"
726*5198cb40SAndrea Mayer
727*5198cb40SAndrea Mayer	check_and_log_hs_ipv6_connectivity "${hssrc}" "${hsdst}"
728*5198cb40SAndrea Mayer}
729*5198cb40SAndrea Mayer
730*5198cb40SAndrea Mayerrouter_tests()
731*5198cb40SAndrea Mayer{
732*5198cb40SAndrea Mayer	local i
733*5198cb40SAndrea Mayer	local j
734*5198cb40SAndrea Mayer
735*5198cb40SAndrea Mayer	log_section "IPv6 routers connectivity test"
736*5198cb40SAndrea Mayer
737*5198cb40SAndrea Mayer	for i in ${ROUTERS}; do
738*5198cb40SAndrea Mayer		for j in ${ROUTERS}; do
739*5198cb40SAndrea Mayer			if [ "${i}" -eq "${j}" ]; then
740*5198cb40SAndrea Mayer				continue
741*5198cb40SAndrea Mayer			fi
742*5198cb40SAndrea Mayer
743*5198cb40SAndrea Mayer			check_and_log_rt_connectivity "${i}" "${j}"
744*5198cb40SAndrea Mayer		done
745*5198cb40SAndrea Mayer	done
746*5198cb40SAndrea Mayer}
747*5198cb40SAndrea Mayer
748*5198cb40SAndrea Mayerhost2gateway_tests()
749*5198cb40SAndrea Mayer{
750*5198cb40SAndrea Mayer	local hs
751*5198cb40SAndrea Mayer
752*5198cb40SAndrea Mayer	log_section "IPv6 connectivity test among hosts and gateways"
753*5198cb40SAndrea Mayer
754*5198cb40SAndrea Mayer	for hs in ${HOSTS}; do
755*5198cb40SAndrea Mayer		check_and_log_hs2gw_connectivity "${hs}"
756*5198cb40SAndrea Mayer	done
757*5198cb40SAndrea Mayer}
758*5198cb40SAndrea Mayer
759*5198cb40SAndrea Mayerhost_srv6_end_flv_psp_tests()
760*5198cb40SAndrea Mayer{
761*5198cb40SAndrea Mayer	log_section "SRv6 connectivity test hosts (h1 <-> h2, PSP flavor)"
762*5198cb40SAndrea Mayer
763*5198cb40SAndrea Mayer	check_and_log_hs_connectivity 1 2
764*5198cb40SAndrea Mayer	check_and_log_hs_connectivity 2 1
765*5198cb40SAndrea Mayer}
766*5198cb40SAndrea Mayer
767*5198cb40SAndrea Mayertest_iproute2_supp_or_ksft_skip()
768*5198cb40SAndrea Mayer{
769*5198cb40SAndrea Mayer	local flavor="$1"
770*5198cb40SAndrea Mayer
771*5198cb40SAndrea Mayer	if ! ip route help 2>&1 | grep -qo "${flavor}"; then
772*5198cb40SAndrea Mayer		echo "SKIP: Missing SRv6 ${flavor} flavor support in iproute2"
773*5198cb40SAndrea Mayer		exit "${ksft_skip}"
774*5198cb40SAndrea Mayer	fi
775*5198cb40SAndrea Mayer}
776*5198cb40SAndrea Mayer
777*5198cb40SAndrea Mayertest_kernel_supp_or_ksft_skip()
778*5198cb40SAndrea Mayer{
779*5198cb40SAndrea Mayer	local flavor="$1"
780*5198cb40SAndrea Mayer	local test_netns
781*5198cb40SAndrea Mayer
782*5198cb40SAndrea Mayer	test_netns="kflv-$(mktemp -u XXXXXXXX)"
783*5198cb40SAndrea Mayer
784*5198cb40SAndrea Mayer	if ! ip netns add "${test_netns}"; then
785*5198cb40SAndrea Mayer		echo "SKIP: Cannot set up netns to test kernel support for flavors"
786*5198cb40SAndrea Mayer		exit "${ksft_skip}"
787*5198cb40SAndrea Mayer	fi
788*5198cb40SAndrea Mayer
789*5198cb40SAndrea Mayer	if ! ip -netns "${test_netns}" link \
790*5198cb40SAndrea Mayer		add "${DUMMY_DEVNAME}" type dummy; then
791*5198cb40SAndrea Mayer		echo "SKIP: Cannot set up dummy dev to test kernel support for flavors"
792*5198cb40SAndrea Mayer
793*5198cb40SAndrea Mayer		ip netns del "${test_netns}"
794*5198cb40SAndrea Mayer		exit "${ksft_skip}"
795*5198cb40SAndrea Mayer	fi
796*5198cb40SAndrea Mayer
797*5198cb40SAndrea Mayer	if ! ip -netns "${test_netns}" link \
798*5198cb40SAndrea Mayer		set "${DUMMY_DEVNAME}" up; then
799*5198cb40SAndrea Mayer		echo "SKIP: Cannot activate dummy dev to test kernel support for flavors"
800*5198cb40SAndrea Mayer
801*5198cb40SAndrea Mayer		ip netns del "${test_netns}"
802*5198cb40SAndrea Mayer		exit "${ksft_skip}"
803*5198cb40SAndrea Mayer	fi
804*5198cb40SAndrea Mayer
805*5198cb40SAndrea Mayer	if ! ip -netns "${test_netns}" -6 route \
806*5198cb40SAndrea Mayer		add "${IPv6_TESTS_ADDR}" encap seg6local \
807*5198cb40SAndrea Mayer		action End flavors "${flavor}" dev "${DUMMY_DEVNAME}"; then
808*5198cb40SAndrea Mayer		echo "SKIP: ${flavor} flavor not supported in kernel"
809*5198cb40SAndrea Mayer
810*5198cb40SAndrea Mayer		ip netns del "${test_netns}"
811*5198cb40SAndrea Mayer		exit "${ksft_skip}"
812*5198cb40SAndrea Mayer	fi
813*5198cb40SAndrea Mayer
814*5198cb40SAndrea Mayer	ip netns del "${test_netns}"
815*5198cb40SAndrea Mayer}
816*5198cb40SAndrea Mayer
817*5198cb40SAndrea Mayertest_dummy_dev_or_ksft_skip()
818*5198cb40SAndrea Mayer{
819*5198cb40SAndrea Mayer	local test_netns
820*5198cb40SAndrea Mayer
821*5198cb40SAndrea Mayer	test_netns="dummy-$(mktemp -u XXXXXXXX)"
822*5198cb40SAndrea Mayer
823*5198cb40SAndrea Mayer	if ! ip netns add "${test_netns}"; then
824*5198cb40SAndrea Mayer		echo "SKIP: Cannot set up netns for testing dummy dev support"
825*5198cb40SAndrea Mayer		exit "${ksft_skip}"
826*5198cb40SAndrea Mayer	fi
827*5198cb40SAndrea Mayer
828*5198cb40SAndrea Mayer	modprobe dummy &>/dev/null || true
829*5198cb40SAndrea Mayer	if ! ip -netns "${test_netns}" link \
830*5198cb40SAndrea Mayer		add "${DUMMY_DEVNAME}" type dummy; then
831*5198cb40SAndrea Mayer		echo "SKIP: dummy dev not supported"
832*5198cb40SAndrea Mayer
833*5198cb40SAndrea Mayer		ip netns del "${test_netns}"
834*5198cb40SAndrea Mayer		exit "${ksft_skip}"
835*5198cb40SAndrea Mayer	fi
836*5198cb40SAndrea Mayer
837*5198cb40SAndrea Mayer	ip netns del "${test_netns}"
838*5198cb40SAndrea Mayer}
839*5198cb40SAndrea Mayer
840*5198cb40SAndrea Mayerif [ "$(id -u)" -ne 0 ]; then
841*5198cb40SAndrea Mayer	echo "SKIP: Need root privileges"
842*5198cb40SAndrea Mayer	exit "${ksft_skip}"
843*5198cb40SAndrea Mayerfi
844*5198cb40SAndrea Mayer
845*5198cb40SAndrea Mayer# required programs to carry out this selftest
846*5198cb40SAndrea Mayertest_command_or_ksft_skip ip
847*5198cb40SAndrea Mayertest_command_or_ksft_skip ping
848*5198cb40SAndrea Mayertest_command_or_ksft_skip sysctl
849*5198cb40SAndrea Mayertest_command_or_ksft_skip grep
850*5198cb40SAndrea Mayertest_command_or_ksft_skip cut
851*5198cb40SAndrea Mayertest_command_or_ksft_skip sed
852*5198cb40SAndrea Mayertest_command_or_ksft_skip sort
853*5198cb40SAndrea Mayertest_command_or_ksft_skip xargs
854*5198cb40SAndrea Mayer
855*5198cb40SAndrea Mayertest_dummy_dev_or_ksft_skip
856*5198cb40SAndrea Mayertest_iproute2_supp_or_ksft_skip psp
857*5198cb40SAndrea Mayertest_kernel_supp_or_ksft_skip psp
858*5198cb40SAndrea Mayer
859*5198cb40SAndrea Mayerset -e
860*5198cb40SAndrea Mayertrap cleanup EXIT
861*5198cb40SAndrea Mayer
862*5198cb40SAndrea Mayersetup
863*5198cb40SAndrea Mayerset +e
864*5198cb40SAndrea Mayer
865*5198cb40SAndrea Mayerrouter_tests
866*5198cb40SAndrea Mayerhost2gateway_tests
867*5198cb40SAndrea Mayerhost_srv6_end_flv_psp_tests
868*5198cb40SAndrea Mayer
869*5198cb40SAndrea Mayerprint_log_test_results
870