1*95baa4e8SAndrea Mayer#!/bin/bash
2*95baa4e8SAndrea Mayer# SPDX-License-Identifier: GPL-2.0
3*95baa4e8SAndrea Mayer#
4*95baa4e8SAndrea Mayer# author: Andrea Mayer <andrea.mayer@uniroma2.it>
5*95baa4e8SAndrea Mayer#
6*95baa4e8SAndrea Mayer# This script is designed for testing the SRv6 H.L2Encaps.Red behavior.
7*95baa4e8SAndrea Mayer#
8*95baa4e8SAndrea Mayer# Below is depicted the IPv6 network of an operator which offers L2 VPN
9*95baa4e8SAndrea Mayer# services to hosts, enabling them to communicate with each other.
10*95baa4e8SAndrea Mayer# In this example, hosts hs-1 and hs-2 are connected through an L2 VPN service.
11*95baa4e8SAndrea Mayer# Currently, the SRv6 subsystem in Linux allows hosts hs-1 and hs-2 to exchange
12*95baa4e8SAndrea Mayer# full L2 frames as long as they carry IPv4/IPv6.
13*95baa4e8SAndrea Mayer#
14*95baa4e8SAndrea Mayer# Routers rt-1,rt-2,rt-3 and rt-4 implement L2 VPN services
15*95baa4e8SAndrea Mayer# leveraging the SRv6 architecture. The key components for such VPNs are:
16*95baa4e8SAndrea Mayer#
17*95baa4e8SAndrea Mayer#   i) The SRv6 H.L2Encaps.Red behavior applies SRv6 Policies on traffic
18*95baa4e8SAndrea Mayer#      received by connected hosts, initiating the VPN tunnel. Such a behavior
19*95baa4e8SAndrea Mayer#      is an optimization of the SRv6 H.L2Encap aiming to reduce the
20*95baa4e8SAndrea Mayer#      length of the SID List carried in the pushed SRH. Specifically, the
21*95baa4e8SAndrea Mayer#      H.L2Encaps.Red removes the first SID contained in the SID List (i.e. SRv6
22*95baa4e8SAndrea Mayer#      Policy) by storing it into the IPv6 Destination Address. When a SRv6
23*95baa4e8SAndrea Mayer#      Policy is made of only one SID, the SRv6 H.L2Encaps.Red behavior omits
24*95baa4e8SAndrea Mayer#      the SRH at all and pushes that SID directly into the IPv6 DA;
25*95baa4e8SAndrea Mayer#
26*95baa4e8SAndrea Mayer#  ii) The SRv6 End behavior advances the active SID in the SID List
27*95baa4e8SAndrea Mayer#      carried by the SRH;
28*95baa4e8SAndrea Mayer#
29*95baa4e8SAndrea Mayer# iii) The SRv6 End.DX2 behavior is used for removing the SRv6 Policy
30*95baa4e8SAndrea Mayer#      and, thus, it terminates the VPN tunnel. The decapsulated L2 frame is
31*95baa4e8SAndrea Mayer#      sent over the interface connected with the destination host.
32*95baa4e8SAndrea Mayer#
33*95baa4e8SAndrea Mayer#               cafe::1                      cafe::2
34*95baa4e8SAndrea Mayer#              10.0.0.1                     10.0.0.2
35*95baa4e8SAndrea Mayer#             +--------+                   +--------+
36*95baa4e8SAndrea Mayer#             |        |                   |        |
37*95baa4e8SAndrea Mayer#             |  hs-1  |                   |  hs-2  |
38*95baa4e8SAndrea Mayer#             |        |                   |        |
39*95baa4e8SAndrea Mayer#             +---+----+                   +--- +---+
40*95baa4e8SAndrea Mayer#    cafe::/64    |                             |      cafe::/64
41*95baa4e8SAndrea Mayer#  10.0.0.0/24    |                             |    10.0.0.0/24
42*95baa4e8SAndrea Mayer#             +---+----+                   +----+---+
43*95baa4e8SAndrea Mayer#             |        |  fcf0:0:1:2::/64  |        |
44*95baa4e8SAndrea Mayer#             |  rt-1  +-------------------+  rt-2  |
45*95baa4e8SAndrea Mayer#             |        |                   |        |
46*95baa4e8SAndrea Mayer#             +---+----+                   +----+---+
47*95baa4e8SAndrea Mayer#                 |      .               .      |
48*95baa4e8SAndrea Mayer#                 |  fcf0:0:1:3::/64   .        |
49*95baa4e8SAndrea Mayer#                 |          .       .          |
50*95baa4e8SAndrea Mayer#                 |            .   .            |
51*95baa4e8SAndrea Mayer# fcf0:0:1:4::/64 |              .              | fcf0:0:2:3::/64
52*95baa4e8SAndrea Mayer#                 |            .   .            |
53*95baa4e8SAndrea Mayer#                 |          .       .          |
54*95baa4e8SAndrea Mayer#                 |  fcf0:0:2:4::/64   .        |
55*95baa4e8SAndrea Mayer#                 |      .               .      |
56*95baa4e8SAndrea Mayer#             +---+----+                   +----+---+
57*95baa4e8SAndrea Mayer#             |        |                   |        |
58*95baa4e8SAndrea Mayer#             |  rt-4  +-------------------+  rt-3  |
59*95baa4e8SAndrea Mayer#             |        |  fcf0:0:3:4::/64  |        |
60*95baa4e8SAndrea Mayer#             +---+----+                   +----+---+
61*95baa4e8SAndrea Mayer#
62*95baa4e8SAndrea Mayer#
63*95baa4e8SAndrea Mayer# Every fcf0:0:x:y::/64 network interconnects the SRv6 routers rt-x with rt-y
64*95baa4e8SAndrea Mayer# in the IPv6 operator network.
65*95baa4e8SAndrea Mayer#
66*95baa4e8SAndrea Mayer# Local SID table
67*95baa4e8SAndrea Mayer# ===============
68*95baa4e8SAndrea Mayer#
69*95baa4e8SAndrea Mayer# Each SRv6 router is configured with a Local SID table in which SIDs are
70*95baa4e8SAndrea Mayer# stored. Considering the given SRv6 router rt-x, at least two SIDs are
71*95baa4e8SAndrea Mayer# configured in the Local SID table:
72*95baa4e8SAndrea Mayer#
73*95baa4e8SAndrea Mayer#   Local SID table for SRv6 router rt-x
74*95baa4e8SAndrea Mayer#   +----------------------------------------------------------+
75*95baa4e8SAndrea Mayer#   |fcff:x::e is associated with the SRv6 End behavior        |
76*95baa4e8SAndrea Mayer#   |fcff:x::d2 is associated with the SRv6 End.DX2 behavior   |
77*95baa4e8SAndrea Mayer#   +----------------------------------------------------------+
78*95baa4e8SAndrea Mayer#
79*95baa4e8SAndrea Mayer# The fcff::/16 prefix is reserved by the operator for implementing SRv6 VPN
80*95baa4e8SAndrea Mayer# services. Reachability of SIDs is ensured by proper configuration of the IPv6
81*95baa4e8SAndrea Mayer# operator's network and SRv6 routers.
82*95baa4e8SAndrea Mayer#
83*95baa4e8SAndrea Mayer# SRv6 Policies
84*95baa4e8SAndrea Mayer# =============
85*95baa4e8SAndrea Mayer#
86*95baa4e8SAndrea Mayer# An SRv6 ingress router applies SRv6 policies to the traffic received from a
87*95baa4e8SAndrea Mayer# connected host. SRv6 policy enforcement consists of encapsulating the
88*95baa4e8SAndrea Mayer# received traffic into a new IPv6 packet with a given SID List contained in
89*95baa4e8SAndrea Mayer# the SRH.
90*95baa4e8SAndrea Mayer#
91*95baa4e8SAndrea Mayer# L2 VPN between hs-1 and hs-2
92*95baa4e8SAndrea Mayer# ----------------------------
93*95baa4e8SAndrea Mayer#
94*95baa4e8SAndrea Mayer# Hosts hs-1 and hs-2 are connected using a dedicated L2 VPN.
95*95baa4e8SAndrea Mayer# Specifically, packets generated from hs-1 and directed towards hs-2 are
96*95baa4e8SAndrea Mayer# handled by rt-1 which applies the following SRv6 Policies:
97*95baa4e8SAndrea Mayer#
98*95baa4e8SAndrea Mayer#   i.a) L2 traffic, SID List=fcff:2::d2
99*95baa4e8SAndrea Mayer#
100*95baa4e8SAndrea Mayer# Policy (i.a) steers tunneled L2 traffic through SRv6 router rt-2.
101*95baa4e8SAndrea Mayer# The H.L2Encaps.Red omits the presence of SRH at all, since the SID List
102*95baa4e8SAndrea Mayer# consists of only one SID (fcff:2::d2) that can be stored directly in the IPv6
103*95baa4e8SAndrea Mayer# DA.
104*95baa4e8SAndrea Mayer#
105*95baa4e8SAndrea Mayer# On the reverse path (i.e. from hs-2 to hs-1), rt-2 applies the following
106*95baa4e8SAndrea Mayer# policies:
107*95baa4e8SAndrea Mayer#
108*95baa4e8SAndrea Mayer#   i.b) L2 traffic, SID List=fcff:4::e,fcff:3::e,fcff:1::d2
109*95baa4e8SAndrea Mayer#
110*95baa4e8SAndrea Mayer# Policy (i.b) steers tunneled L2 traffic through the SRv6 routers
111*95baa4e8SAndrea Mayer# rt-4,rt-3,rt2. The H.L2Encaps.Red reduces the SID List in the SRH by removing
112*95baa4e8SAndrea Mayer# the first SID (fcff:4::e) and pushing it into the IPv6 DA.
113*95baa4e8SAndrea Mayer#
114*95baa4e8SAndrea Mayer# In summary:
115*95baa4e8SAndrea Mayer#  hs-1->hs-2 |IPv6 DA=fcff:2::d2|eth|...|                              (i.a)
116*95baa4e8SAndrea Mayer#  hs-2->hs-1 |IPv6 DA=fcff:4::e|SRH SIDs=fcff:3::e,fcff:1::d2|eth|...| (i.b)
117*95baa4e8SAndrea Mayer#
118*95baa4e8SAndrea Mayer
119*95baa4e8SAndrea Mayer# Kselftest framework requirement - SKIP code is 4.
120*95baa4e8SAndrea Mayerreadonly ksft_skip=4
121*95baa4e8SAndrea Mayer
122*95baa4e8SAndrea Mayerreadonly RDMSUFF="$(mktemp -u XXXXXXXX)"
123*95baa4e8SAndrea Mayerreadonly DUMMY_DEVNAME="dum0"
124*95baa4e8SAndrea Mayerreadonly RT2HS_DEVNAME="veth-hs"
125*95baa4e8SAndrea Mayerreadonly HS_VETH_NAME="veth0"
126*95baa4e8SAndrea Mayerreadonly LOCALSID_TABLE_ID=90
127*95baa4e8SAndrea Mayerreadonly IPv6_RT_NETWORK=fcf0:0
128*95baa4e8SAndrea Mayerreadonly IPv6_HS_NETWORK=cafe
129*95baa4e8SAndrea Mayerreadonly IPv4_HS_NETWORK=10.0.0
130*95baa4e8SAndrea Mayerreadonly VPN_LOCATOR_SERVICE=fcff
131*95baa4e8SAndrea Mayerreadonly MAC_PREFIX=00:00:00:c0:01
132*95baa4e8SAndrea Mayerreadonly END_FUNC=000e
133*95baa4e8SAndrea Mayerreadonly DX2_FUNC=00d2
134*95baa4e8SAndrea Mayer
135*95baa4e8SAndrea MayerPING_TIMEOUT_SEC=4
136*95baa4e8SAndrea MayerPAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
137*95baa4e8SAndrea Mayer
138*95baa4e8SAndrea Mayer# IDs of routers and hosts are initialized during the setup of the testing
139*95baa4e8SAndrea Mayer# network
140*95baa4e8SAndrea MayerROUTERS=''
141*95baa4e8SAndrea MayerHOSTS=''
142*95baa4e8SAndrea Mayer
143*95baa4e8SAndrea MayerSETUP_ERR=1
144*95baa4e8SAndrea Mayer
145*95baa4e8SAndrea Mayerret=${ksft_skip}
146*95baa4e8SAndrea Mayernsuccess=0
147*95baa4e8SAndrea Mayernfail=0
148*95baa4e8SAndrea Mayer
149*95baa4e8SAndrea Mayerlog_test()
150*95baa4e8SAndrea Mayer{
151*95baa4e8SAndrea Mayer	local rc="$1"
152*95baa4e8SAndrea Mayer	local expected="$2"
153*95baa4e8SAndrea Mayer	local msg="$3"
154*95baa4e8SAndrea Mayer
155*95baa4e8SAndrea Mayer	if [ "${rc}" -eq "${expected}" ]; then
156*95baa4e8SAndrea Mayer		nsuccess=$((nsuccess+1))
157*95baa4e8SAndrea Mayer		printf "\n    TEST: %-60s  [ OK ]\n" "${msg}"
158*95baa4e8SAndrea Mayer	else
159*95baa4e8SAndrea Mayer		ret=1
160*95baa4e8SAndrea Mayer		nfail=$((nfail+1))
161*95baa4e8SAndrea Mayer		printf "\n    TEST: %-60s  [FAIL]\n" "${msg}"
162*95baa4e8SAndrea Mayer		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
163*95baa4e8SAndrea Mayer			echo
164*95baa4e8SAndrea Mayer			echo "hit enter to continue, 'q' to quit"
165*95baa4e8SAndrea Mayer			read a
166*95baa4e8SAndrea Mayer			[ "$a" = "q" ] && exit 1
167*95baa4e8SAndrea Mayer		fi
168*95baa4e8SAndrea Mayer	fi
169*95baa4e8SAndrea Mayer}
170*95baa4e8SAndrea Mayer
171*95baa4e8SAndrea Mayerprint_log_test_results()
172*95baa4e8SAndrea Mayer{
173*95baa4e8SAndrea Mayer	printf "\nTests passed: %3d\n" "${nsuccess}"
174*95baa4e8SAndrea Mayer	printf "Tests failed: %3d\n"   "${nfail}"
175*95baa4e8SAndrea Mayer
176*95baa4e8SAndrea Mayer	# when a test fails, the value of 'ret' is set to 1 (error code).
177*95baa4e8SAndrea Mayer	# Conversely, when all tests are passed successfully, the 'ret' value
178*95baa4e8SAndrea Mayer	# is set to 0 (success code).
179*95baa4e8SAndrea Mayer	if [ "${ret}" -ne 1 ]; then
180*95baa4e8SAndrea Mayer		ret=0
181*95baa4e8SAndrea Mayer	fi
182*95baa4e8SAndrea Mayer}
183*95baa4e8SAndrea Mayer
184*95baa4e8SAndrea Mayerlog_section()
185*95baa4e8SAndrea Mayer{
186*95baa4e8SAndrea Mayer	echo
187*95baa4e8SAndrea Mayer	echo "################################################################################"
188*95baa4e8SAndrea Mayer	echo "TEST SECTION: $*"
189*95baa4e8SAndrea Mayer	echo "################################################################################"
190*95baa4e8SAndrea Mayer}
191*95baa4e8SAndrea Mayer
192*95baa4e8SAndrea Mayertest_command_or_ksft_skip()
193*95baa4e8SAndrea Mayer{
194*95baa4e8SAndrea Mayer	local cmd="$1"
195*95baa4e8SAndrea Mayer
196*95baa4e8SAndrea Mayer	if [ ! -x "$(command -v "${cmd}")" ]; then
197*95baa4e8SAndrea Mayer		echo "SKIP: Could not run test without \"${cmd}\" tool";
198*95baa4e8SAndrea Mayer		exit "${ksft_skip}"
199*95baa4e8SAndrea Mayer	fi
200*95baa4e8SAndrea Mayer}
201*95baa4e8SAndrea Mayer
202*95baa4e8SAndrea Mayerget_nodename()
203*95baa4e8SAndrea Mayer{
204*95baa4e8SAndrea Mayer	local name="$1"
205*95baa4e8SAndrea Mayer
206*95baa4e8SAndrea Mayer	echo "${name}-${RDMSUFF}"
207*95baa4e8SAndrea Mayer}
208*95baa4e8SAndrea Mayer
209*95baa4e8SAndrea Mayerget_rtname()
210*95baa4e8SAndrea Mayer{
211*95baa4e8SAndrea Mayer	local rtid="$1"
212*95baa4e8SAndrea Mayer
213*95baa4e8SAndrea Mayer	get_nodename "rt-${rtid}"
214*95baa4e8SAndrea Mayer}
215*95baa4e8SAndrea Mayer
216*95baa4e8SAndrea Mayerget_hsname()
217*95baa4e8SAndrea Mayer{
218*95baa4e8SAndrea Mayer	local hsid="$1"
219*95baa4e8SAndrea Mayer
220*95baa4e8SAndrea Mayer	get_nodename "hs-${hsid}"
221*95baa4e8SAndrea Mayer}
222*95baa4e8SAndrea Mayer
223*95baa4e8SAndrea Mayer__create_namespace()
224*95baa4e8SAndrea Mayer{
225*95baa4e8SAndrea Mayer	local name="$1"
226*95baa4e8SAndrea Mayer
227*95baa4e8SAndrea Mayer	ip netns add "${name}"
228*95baa4e8SAndrea Mayer}
229*95baa4e8SAndrea Mayer
230*95baa4e8SAndrea Mayercreate_router()
231*95baa4e8SAndrea Mayer{
232*95baa4e8SAndrea Mayer	local rtid="$1"
233*95baa4e8SAndrea Mayer	local nsname
234*95baa4e8SAndrea Mayer
235*95baa4e8SAndrea Mayer	nsname="$(get_rtname "${rtid}")"
236*95baa4e8SAndrea Mayer
237*95baa4e8SAndrea Mayer	__create_namespace "${nsname}"
238*95baa4e8SAndrea Mayer}
239*95baa4e8SAndrea Mayer
240*95baa4e8SAndrea Mayercreate_host()
241*95baa4e8SAndrea Mayer{
242*95baa4e8SAndrea Mayer	local hsid="$1"
243*95baa4e8SAndrea Mayer	local nsname
244*95baa4e8SAndrea Mayer
245*95baa4e8SAndrea Mayer	nsname="$(get_hsname "${hsid}")"
246*95baa4e8SAndrea Mayer
247*95baa4e8SAndrea Mayer	__create_namespace "${nsname}"
248*95baa4e8SAndrea Mayer}
249*95baa4e8SAndrea Mayer
250*95baa4e8SAndrea Mayercleanup()
251*95baa4e8SAndrea Mayer{
252*95baa4e8SAndrea Mayer	local nsname
253*95baa4e8SAndrea Mayer	local i
254*95baa4e8SAndrea Mayer
255*95baa4e8SAndrea Mayer	# destroy routers
256*95baa4e8SAndrea Mayer	for i in ${ROUTERS}; do
257*95baa4e8SAndrea Mayer		nsname="$(get_rtname "${i}")"
258*95baa4e8SAndrea Mayer
259*95baa4e8SAndrea Mayer		ip netns del "${nsname}" &>/dev/null || true
260*95baa4e8SAndrea Mayer	done
261*95baa4e8SAndrea Mayer
262*95baa4e8SAndrea Mayer	# destroy hosts
263*95baa4e8SAndrea Mayer	for i in ${HOSTS}; do
264*95baa4e8SAndrea Mayer		nsname="$(get_hsname "${i}")"
265*95baa4e8SAndrea Mayer
266*95baa4e8SAndrea Mayer		ip netns del "${nsname}" &>/dev/null || true
267*95baa4e8SAndrea Mayer	done
268*95baa4e8SAndrea Mayer
269*95baa4e8SAndrea Mayer	# check whether the setup phase was completed successfully or not. In
270*95baa4e8SAndrea Mayer	# case of an error during the setup phase of the testing environment,
271*95baa4e8SAndrea Mayer	# the selftest is considered as "skipped".
272*95baa4e8SAndrea Mayer	if [ "${SETUP_ERR}" -ne 0 ]; then
273*95baa4e8SAndrea Mayer		echo "SKIP: Setting up the testing environment failed"
274*95baa4e8SAndrea Mayer		exit "${ksft_skip}"
275*95baa4e8SAndrea Mayer	fi
276*95baa4e8SAndrea Mayer
277*95baa4e8SAndrea Mayer	exit "${ret}"
278*95baa4e8SAndrea Mayer}
279*95baa4e8SAndrea Mayer
280*95baa4e8SAndrea Mayeradd_link_rt_pairs()
281*95baa4e8SAndrea Mayer{
282*95baa4e8SAndrea Mayer	local rt="$1"
283*95baa4e8SAndrea Mayer	local rt_neighs="$2"
284*95baa4e8SAndrea Mayer	local neigh
285*95baa4e8SAndrea Mayer	local nsname
286*95baa4e8SAndrea Mayer	local neigh_nsname
287*95baa4e8SAndrea Mayer
288*95baa4e8SAndrea Mayer	nsname="$(get_rtname "${rt}")"
289*95baa4e8SAndrea Mayer
290*95baa4e8SAndrea Mayer	for neigh in ${rt_neighs}; do
291*95baa4e8SAndrea Mayer		neigh_nsname="$(get_rtname "${neigh}")"
292*95baa4e8SAndrea Mayer
293*95baa4e8SAndrea Mayer		ip link add "veth-rt-${rt}-${neigh}" netns "${nsname}" \
294*95baa4e8SAndrea Mayer			type veth peer name "veth-rt-${neigh}-${rt}" \
295*95baa4e8SAndrea Mayer			netns "${neigh_nsname}"
296*95baa4e8SAndrea Mayer	done
297*95baa4e8SAndrea Mayer}
298*95baa4e8SAndrea Mayer
299*95baa4e8SAndrea Mayerget_network_prefix()
300*95baa4e8SAndrea Mayer{
301*95baa4e8SAndrea Mayer	local rt="$1"
302*95baa4e8SAndrea Mayer	local neigh="$2"
303*95baa4e8SAndrea Mayer	local p="${rt}"
304*95baa4e8SAndrea Mayer	local q="${neigh}"
305*95baa4e8SAndrea Mayer
306*95baa4e8SAndrea Mayer	if [ "${p}" -gt "${q}" ]; then
307*95baa4e8SAndrea Mayer		p="${q}"; q="${rt}"
308*95baa4e8SAndrea Mayer	fi
309*95baa4e8SAndrea Mayer
310*95baa4e8SAndrea Mayer	echo "${IPv6_RT_NETWORK}:${p}:${q}"
311*95baa4e8SAndrea Mayer}
312*95baa4e8SAndrea Mayer
313*95baa4e8SAndrea Mayer# Setup the basic networking for the routers
314*95baa4e8SAndrea Mayersetup_rt_networking()
315*95baa4e8SAndrea Mayer{
316*95baa4e8SAndrea Mayer	local rt="$1"
317*95baa4e8SAndrea Mayer	local rt_neighs="$2"
318*95baa4e8SAndrea Mayer	local nsname
319*95baa4e8SAndrea Mayer	local net_prefix
320*95baa4e8SAndrea Mayer	local devname
321*95baa4e8SAndrea Mayer	local neigh
322*95baa4e8SAndrea Mayer
323*95baa4e8SAndrea Mayer	nsname="$(get_rtname "${rt}")"
324*95baa4e8SAndrea Mayer
325*95baa4e8SAndrea Mayer	for neigh in ${rt_neighs}; do
326*95baa4e8SAndrea Mayer		devname="veth-rt-${rt}-${neigh}"
327*95baa4e8SAndrea Mayer
328*95baa4e8SAndrea Mayer		net_prefix="$(get_network_prefix "${rt}" "${neigh}")"
329*95baa4e8SAndrea Mayer
330*95baa4e8SAndrea Mayer		ip -netns "${nsname}" addr \
331*95baa4e8SAndrea Mayer			add "${net_prefix}::${rt}/64" dev "${devname}" nodad
332*95baa4e8SAndrea Mayer
333*95baa4e8SAndrea Mayer		ip -netns "${nsname}" link set "${devname}" up
334*95baa4e8SAndrea Mayer	done
335*95baa4e8SAndrea Mayer
336*95baa4e8SAndrea Mayer	ip -netns "${nsname}" link add "${DUMMY_DEVNAME}" type dummy
337*95baa4e8SAndrea Mayer
338*95baa4e8SAndrea Mayer	ip -netns "${nsname}" link set "${DUMMY_DEVNAME}" up
339*95baa4e8SAndrea Mayer	ip -netns "${nsname}" link set lo up
340*95baa4e8SAndrea Mayer
341*95baa4e8SAndrea Mayer	ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0
342*95baa4e8SAndrea Mayer	ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0
343*95baa4e8SAndrea Mayer	ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.forwarding=1
344*95baa4e8SAndrea Mayer
345*95baa4e8SAndrea Mayer	ip netns exec "${nsname}" sysctl -wq net.ipv4.conf.all.rp_filter=0
346*95baa4e8SAndrea Mayer	ip netns exec "${nsname}" sysctl -wq net.ipv4.conf.default.rp_filter=0
347*95baa4e8SAndrea Mayer	ip netns exec "${nsname}" sysctl -wq net.ipv4.ip_forward=1
348*95baa4e8SAndrea Mayer}
349*95baa4e8SAndrea Mayer
350*95baa4e8SAndrea Mayer# Setup local SIDs for an SRv6 router
351*95baa4e8SAndrea Mayersetup_rt_local_sids()
352*95baa4e8SAndrea Mayer{
353*95baa4e8SAndrea Mayer	local rt="$1"
354*95baa4e8SAndrea Mayer	local rt_neighs="$2"
355*95baa4e8SAndrea Mayer	local net_prefix
356*95baa4e8SAndrea Mayer	local devname
357*95baa4e8SAndrea Mayer	local nsname
358*95baa4e8SAndrea Mayer	local neigh
359*95baa4e8SAndrea Mayer
360*95baa4e8SAndrea Mayer	nsname="$(get_rtname "${rt}")"
361*95baa4e8SAndrea Mayer
362*95baa4e8SAndrea Mayer	for neigh in ${rt_neighs}; do
363*95baa4e8SAndrea Mayer		devname="veth-rt-${rt}-${neigh}"
364*95baa4e8SAndrea Mayer
365*95baa4e8SAndrea Mayer		net_prefix="$(get_network_prefix "${rt}" "${neigh}")"
366*95baa4e8SAndrea Mayer
367*95baa4e8SAndrea Mayer		# set underlay network routes for SIDs reachability
368*95baa4e8SAndrea Mayer		ip -netns "${nsname}" -6 route \
369*95baa4e8SAndrea Mayer			add "${VPN_LOCATOR_SERVICE}:${neigh}::/32" \
370*95baa4e8SAndrea Mayer			table "${LOCALSID_TABLE_ID}" \
371*95baa4e8SAndrea Mayer			via "${net_prefix}::${neigh}" dev "${devname}"
372*95baa4e8SAndrea Mayer	done
373*95baa4e8SAndrea Mayer
374*95baa4e8SAndrea Mayer	# Local End behavior (note that dev "${DUMMY_DEVNAME}" is a dummy
375*95baa4e8SAndrea Mayer	# interface)
376*95baa4e8SAndrea Mayer	ip -netns "${nsname}" -6 route \
377*95baa4e8SAndrea Mayer		add "${VPN_LOCATOR_SERVICE}:${rt}::${END_FUNC}" \
378*95baa4e8SAndrea Mayer		table "${LOCALSID_TABLE_ID}" \
379*95baa4e8SAndrea Mayer		encap seg6local action End dev "${DUMMY_DEVNAME}"
380*95baa4e8SAndrea Mayer
381*95baa4e8SAndrea Mayer	# all SIDs for VPNs start with a common locator. Routes and SRv6
382*95baa4e8SAndrea Mayer	# Endpoint behaviors instaces are grouped together in the 'localsid'
383*95baa4e8SAndrea Mayer	# table.
384*95baa4e8SAndrea Mayer	ip -netns "${nsname}" -6 rule add \
385*95baa4e8SAndrea Mayer		to "${VPN_LOCATOR_SERVICE}::/16" \
386*95baa4e8SAndrea Mayer		lookup "${LOCALSID_TABLE_ID}" prio 999
387*95baa4e8SAndrea Mayer}
388*95baa4e8SAndrea Mayer
389*95baa4e8SAndrea Mayer# build and install the SRv6 policy into the ingress SRv6 router.
390*95baa4e8SAndrea Mayer# args:
391*95baa4e8SAndrea Mayer#  $1 - destination host (i.e. cafe::x host)
392*95baa4e8SAndrea Mayer#  $2 - SRv6 router configured for enforcing the SRv6 Policy
393*95baa4e8SAndrea Mayer#  $3 - SRv6 routers configured for steering traffic (End behaviors)
394*95baa4e8SAndrea Mayer#  $4 - SRv6 router configured for removing the SRv6 Policy (router connected
395*95baa4e8SAndrea Mayer#       to the destination host)
396*95baa4e8SAndrea Mayer#  $5 - encap mode (full or red)
397*95baa4e8SAndrea Mayer#  $6 - traffic type (IPv6 or IPv4)
398*95baa4e8SAndrea Mayer__setup_rt_policy()
399*95baa4e8SAndrea Mayer{
400*95baa4e8SAndrea Mayer	local dst="$1"
401*95baa4e8SAndrea Mayer	local encap_rt="$2"
402*95baa4e8SAndrea Mayer	local end_rts="$3"
403*95baa4e8SAndrea Mayer	local dec_rt="$4"
404*95baa4e8SAndrea Mayer	local mode="$5"
405*95baa4e8SAndrea Mayer	local traffic="$6"
406*95baa4e8SAndrea Mayer	local nsname
407*95baa4e8SAndrea Mayer	local policy=''
408*95baa4e8SAndrea Mayer	local n
409*95baa4e8SAndrea Mayer
410*95baa4e8SAndrea Mayer	nsname="$(get_rtname "${encap_rt}")"
411*95baa4e8SAndrea Mayer
412*95baa4e8SAndrea Mayer	for n in ${end_rts}; do
413*95baa4e8SAndrea Mayer		policy="${policy}${VPN_LOCATOR_SERVICE}:${n}::${END_FUNC},"
414*95baa4e8SAndrea Mayer	done
415*95baa4e8SAndrea Mayer
416*95baa4e8SAndrea Mayer	policy="${policy}${VPN_LOCATOR_SERVICE}:${dec_rt}::${DX2_FUNC}"
417*95baa4e8SAndrea Mayer
418*95baa4e8SAndrea Mayer	# add SRv6 policy to incoming traffic sent by connected hosts
419*95baa4e8SAndrea Mayer	if [ "${traffic}" -eq 6 ]; then
420*95baa4e8SAndrea Mayer		ip -netns "${nsname}" -6 route \
421*95baa4e8SAndrea Mayer			add "${IPv6_HS_NETWORK}::${dst}" \
422*95baa4e8SAndrea Mayer			encap seg6 mode "${mode}" segs "${policy}" \
423*95baa4e8SAndrea Mayer			dev dum0
424*95baa4e8SAndrea Mayer	else
425*95baa4e8SAndrea Mayer		ip -netns "${nsname}" -4 route \
426*95baa4e8SAndrea Mayer			add "${IPv4_HS_NETWORK}.${dst}" \
427*95baa4e8SAndrea Mayer			encap seg6 mode "${mode}" segs "${policy}" \
428*95baa4e8SAndrea Mayer			dev dum0
429*95baa4e8SAndrea Mayer	fi
430*95baa4e8SAndrea Mayer}
431*95baa4e8SAndrea Mayer
432*95baa4e8SAndrea Mayer# see __setup_rt_policy
433*95baa4e8SAndrea Mayersetup_rt_policy_ipv6()
434*95baa4e8SAndrea Mayer{
435*95baa4e8SAndrea Mayer	__setup_rt_policy "$1" "$2" "$3" "$4" "$5" 6
436*95baa4e8SAndrea Mayer}
437*95baa4e8SAndrea Mayer
438*95baa4e8SAndrea Mayer#see __setup_rt_policy
439*95baa4e8SAndrea Mayersetup_rt_policy_ipv4()
440*95baa4e8SAndrea Mayer{
441*95baa4e8SAndrea Mayer	__setup_rt_policy "$1" "$2" "$3" "$4" "$5" 4
442*95baa4e8SAndrea Mayer}
443*95baa4e8SAndrea Mayer
444*95baa4e8SAndrea Mayersetup_decap()
445*95baa4e8SAndrea Mayer{
446*95baa4e8SAndrea Mayer	local rt="$1"
447*95baa4e8SAndrea Mayer	local nsname
448*95baa4e8SAndrea Mayer
449*95baa4e8SAndrea Mayer	nsname="$(get_rtname "${rt}")"
450*95baa4e8SAndrea Mayer
451*95baa4e8SAndrea Mayer	# Local End.DX2 behavior
452*95baa4e8SAndrea Mayer	ip -netns "${nsname}" -6 route \
453*95baa4e8SAndrea Mayer		add "${VPN_LOCATOR_SERVICE}:${rt}::${DX2_FUNC}" \
454*95baa4e8SAndrea Mayer		table "${LOCALSID_TABLE_ID}" \
455*95baa4e8SAndrea Mayer		encap seg6local action End.DX2 oif "${RT2HS_DEVNAME}" \
456*95baa4e8SAndrea Mayer		dev "${RT2HS_DEVNAME}"
457*95baa4e8SAndrea Mayer}
458*95baa4e8SAndrea Mayer
459*95baa4e8SAndrea Mayersetup_hs()
460*95baa4e8SAndrea Mayer{
461*95baa4e8SAndrea Mayer	local hs="$1"
462*95baa4e8SAndrea Mayer	local rt="$2"
463*95baa4e8SAndrea Mayer	local hsname
464*95baa4e8SAndrea Mayer	local rtname
465*95baa4e8SAndrea Mayer
466*95baa4e8SAndrea Mayer	hsname="$(get_hsname "${hs}")"
467*95baa4e8SAndrea Mayer	rtname="$(get_rtname "${rt}")"
468*95baa4e8SAndrea Mayer
469*95baa4e8SAndrea Mayer	ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0
470*95baa4e8SAndrea Mayer	ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0
471*95baa4e8SAndrea Mayer
472*95baa4e8SAndrea Mayer	ip -netns "${hsname}" link add "${HS_VETH_NAME}" type veth \
473*95baa4e8SAndrea Mayer		peer name "${RT2HS_DEVNAME}" netns "${rtname}"
474*95baa4e8SAndrea Mayer
475*95baa4e8SAndrea Mayer	ip -netns "${hsname}" addr add "${IPv6_HS_NETWORK}::${hs}/64" \
476*95baa4e8SAndrea Mayer		dev "${HS_VETH_NAME}" nodad
477*95baa4e8SAndrea Mayer	ip -netns "${hsname}" addr add "${IPv4_HS_NETWORK}.${hs}/24" \
478*95baa4e8SAndrea Mayer		dev "${HS_VETH_NAME}"
479*95baa4e8SAndrea Mayer
480*95baa4e8SAndrea Mayer	ip -netns "${hsname}" link set "${HS_VETH_NAME}" up
481*95baa4e8SAndrea Mayer	ip -netns "${hsname}" link set lo up
482*95baa4e8SAndrea Mayer
483*95baa4e8SAndrea Mayer	ip -netns "${rtname}" addr add "${IPv6_HS_NETWORK}::254/64" \
484*95baa4e8SAndrea Mayer		dev "${RT2HS_DEVNAME}" nodad
485*95baa4e8SAndrea Mayer	ip -netns "${rtname}" addr \
486*95baa4e8SAndrea Mayer		add "${IPv4_HS_NETWORK}.254/24" dev "${RT2HS_DEVNAME}"
487*95baa4e8SAndrea Mayer
488*95baa4e8SAndrea Mayer	ip -netns "${rtname}" link set "${RT2HS_DEVNAME}" up
489*95baa4e8SAndrea Mayer
490*95baa4e8SAndrea Mayer	# disable the rp_filter otherwise the kernel gets confused about how
491*95baa4e8SAndrea Mayer	# to route decap ipv4 packets.
492*95baa4e8SAndrea Mayer	ip netns exec "${rtname}" \
493*95baa4e8SAndrea Mayer		sysctl -wq net.ipv4.conf."${RT2HS_DEVNAME}".rp_filter=0
494*95baa4e8SAndrea Mayer}
495*95baa4e8SAndrea Mayer
496*95baa4e8SAndrea Mayer# set an auto-generated mac address
497*95baa4e8SAndrea Mayer# args:
498*95baa4e8SAndrea Mayer#  $1 - name of the node (e.g.: hs-1, rt-3, etc)
499*95baa4e8SAndrea Mayer#  $2 - id of the node (e.g.: 1 for hs-1, 3 for rt-3, etc)
500*95baa4e8SAndrea Mayer#  $3 - host part of the IPv6 network address
501*95baa4e8SAndrea Mayer#  $4 - name of the network interface to which the generated mac address must
502*95baa4e8SAndrea Mayer#       be set.
503*95baa4e8SAndrea Mayerset_mac_address()
504*95baa4e8SAndrea Mayer{
505*95baa4e8SAndrea Mayer	local nodename="$1"
506*95baa4e8SAndrea Mayer	local nodeid="$2"
507*95baa4e8SAndrea Mayer	local host="$3"
508*95baa4e8SAndrea Mayer	local ifname="$4"
509*95baa4e8SAndrea Mayer	local nsname
510*95baa4e8SAndrea Mayer
511*95baa4e8SAndrea Mayer	nsname=$(get_nodename "${nodename}")
512*95baa4e8SAndrea Mayer
513*95baa4e8SAndrea Mayer	ip -netns "${nsname}" link set dev "${ifname}" down
514*95baa4e8SAndrea Mayer
515*95baa4e8SAndrea Mayer	ip -netns "${nsname}" link set address "${MAC_PREFIX}:${nodeid}" \
516*95baa4e8SAndrea Mayer		dev "${ifname}"
517*95baa4e8SAndrea Mayer
518*95baa4e8SAndrea Mayer	# the IPv6 address must be set once again after the MAC address has
519*95baa4e8SAndrea Mayer	# been changed.
520*95baa4e8SAndrea Mayer	ip -netns "${nsname}" addr add "${IPv6_HS_NETWORK}::${host}/64" \
521*95baa4e8SAndrea Mayer		dev "${ifname}" nodad
522*95baa4e8SAndrea Mayer
523*95baa4e8SAndrea Mayer	ip -netns "${nsname}" link set dev "${ifname}" up
524*95baa4e8SAndrea Mayer}
525*95baa4e8SAndrea Mayer
526*95baa4e8SAndrea Mayerset_host_l2peer()
527*95baa4e8SAndrea Mayer{
528*95baa4e8SAndrea Mayer	local hssrc="$1"
529*95baa4e8SAndrea Mayer	local hsdst="$2"
530*95baa4e8SAndrea Mayer	local ipprefix="$3"
531*95baa4e8SAndrea Mayer	local proto="$4"
532*95baa4e8SAndrea Mayer	local hssrc_name
533*95baa4e8SAndrea Mayer	local ipaddr
534*95baa4e8SAndrea Mayer
535*95baa4e8SAndrea Mayer	hssrc_name="$(get_hsname "${hssrc}")"
536*95baa4e8SAndrea Mayer
537*95baa4e8SAndrea Mayer	if [ "${proto}" -eq 6 ]; then
538*95baa4e8SAndrea Mayer		ipaddr="${ipprefix}::${hsdst}"
539*95baa4e8SAndrea Mayer	else
540*95baa4e8SAndrea Mayer		ipaddr="${ipprefix}.${hsdst}"
541*95baa4e8SAndrea Mayer	fi
542*95baa4e8SAndrea Mayer
543*95baa4e8SAndrea Mayer	ip -netns "${hssrc_name}" route add "${ipaddr}" dev "${HS_VETH_NAME}"
544*95baa4e8SAndrea Mayer
545*95baa4e8SAndrea Mayer	ip -netns "${hssrc_name}" neigh \
546*95baa4e8SAndrea Mayer		add "${ipaddr}" lladdr "${MAC_PREFIX}:${hsdst}" \
547*95baa4e8SAndrea Mayer		dev "${HS_VETH_NAME}"
548*95baa4e8SAndrea Mayer}
549*95baa4e8SAndrea Mayer
550*95baa4e8SAndrea Mayer# setup an SRv6 L2 VPN between host hs-x and hs-y (currently, the SRv6
551*95baa4e8SAndrea Mayer# subsystem only supports L2 frames whose layer-3 is IPv4/IPv6).
552*95baa4e8SAndrea Mayer# args:
553*95baa4e8SAndrea Mayer#  $1 - source host
554*95baa4e8SAndrea Mayer#  $2 - SRv6 routers configured for steering tunneled traffic
555*95baa4e8SAndrea Mayer#  $3 - destination host
556*95baa4e8SAndrea Mayersetup_l2vpn()
557*95baa4e8SAndrea Mayer{
558*95baa4e8SAndrea Mayer	local hssrc="$1"
559*95baa4e8SAndrea Mayer	local end_rts="$2"
560*95baa4e8SAndrea Mayer	local hsdst="$3"
561*95baa4e8SAndrea Mayer	local rtsrc="${hssrc}"
562*95baa4e8SAndrea Mayer	local rtdst="${hsdst}"
563*95baa4e8SAndrea Mayer
564*95baa4e8SAndrea Mayer	# set fixed mac for source node and the neigh MAC address
565*95baa4e8SAndrea Mayer	set_mac_address "hs-${hssrc}" "${hssrc}" "${hssrc}" "${HS_VETH_NAME}"
566*95baa4e8SAndrea Mayer	set_host_l2peer "${hssrc}" "${hsdst}" "${IPv6_HS_NETWORK}" 6
567*95baa4e8SAndrea Mayer	set_host_l2peer "${hssrc}" "${hsdst}" "${IPv4_HS_NETWORK}" 4
568*95baa4e8SAndrea Mayer
569*95baa4e8SAndrea Mayer	# we have to set the mac address of the veth-host (on ingress router)
570*95baa4e8SAndrea Mayer	# to the mac address of the remote peer (L2 VPN destination host).
571*95baa4e8SAndrea Mayer	# Otherwise, traffic coming from the source host is dropped at the
572*95baa4e8SAndrea Mayer	# ingress router.
573*95baa4e8SAndrea Mayer	set_mac_address "rt-${rtsrc}" "${hsdst}" 254 "${RT2HS_DEVNAME}"
574*95baa4e8SAndrea Mayer
575*95baa4e8SAndrea Mayer	# set the SRv6 Policies at the ingress router
576*95baa4e8SAndrea Mayer	setup_rt_policy_ipv6 "${hsdst}" "${rtsrc}" "${end_rts}" "${rtdst}" \
577*95baa4e8SAndrea Mayer		l2encap.red 6
578*95baa4e8SAndrea Mayer	setup_rt_policy_ipv4 "${hsdst}" "${rtsrc}" "${end_rts}" "${rtdst}" \
579*95baa4e8SAndrea Mayer		l2encap.red 4
580*95baa4e8SAndrea Mayer
581*95baa4e8SAndrea Mayer	# set the decap behavior
582*95baa4e8SAndrea Mayer	setup_decap "${rtsrc}"
583*95baa4e8SAndrea Mayer}
584*95baa4e8SAndrea Mayer
585*95baa4e8SAndrea Mayersetup()
586*95baa4e8SAndrea Mayer{
587*95baa4e8SAndrea Mayer	local i
588*95baa4e8SAndrea Mayer
589*95baa4e8SAndrea Mayer	# create routers
590*95baa4e8SAndrea Mayer	ROUTERS="1 2 3 4"; readonly ROUTERS
591*95baa4e8SAndrea Mayer	for i in ${ROUTERS}; do
592*95baa4e8SAndrea Mayer		create_router "${i}"
593*95baa4e8SAndrea Mayer	done
594*95baa4e8SAndrea Mayer
595*95baa4e8SAndrea Mayer	# create hosts
596*95baa4e8SAndrea Mayer	HOSTS="1 2"; readonly HOSTS
597*95baa4e8SAndrea Mayer	for i in ${HOSTS}; do
598*95baa4e8SAndrea Mayer		create_host "${i}"
599*95baa4e8SAndrea Mayer	done
600*95baa4e8SAndrea Mayer
601*95baa4e8SAndrea Mayer	# set up the links for connecting routers
602*95baa4e8SAndrea Mayer	add_link_rt_pairs 1 "2 3 4"
603*95baa4e8SAndrea Mayer	add_link_rt_pairs 2 "3 4"
604*95baa4e8SAndrea Mayer	add_link_rt_pairs 3 "4"
605*95baa4e8SAndrea Mayer
606*95baa4e8SAndrea Mayer	# set up the basic connectivity of routers and routes required for
607*95baa4e8SAndrea Mayer	# reachability of SIDs.
608*95baa4e8SAndrea Mayer	setup_rt_networking 1 "2 3 4"
609*95baa4e8SAndrea Mayer	setup_rt_networking 2 "1 3 4"
610*95baa4e8SAndrea Mayer	setup_rt_networking 3 "1 2 4"
611*95baa4e8SAndrea Mayer	setup_rt_networking 4 "1 2 3"
612*95baa4e8SAndrea Mayer
613*95baa4e8SAndrea Mayer	# set up the hosts connected to routers
614*95baa4e8SAndrea Mayer	setup_hs 1 1
615*95baa4e8SAndrea Mayer	setup_hs 2 2
616*95baa4e8SAndrea Mayer
617*95baa4e8SAndrea Mayer	# set up default SRv6 Endpoints (i.e. SRv6 End and SRv6 End.DX2)
618*95baa4e8SAndrea Mayer	setup_rt_local_sids 1 "2 3 4"
619*95baa4e8SAndrea Mayer	setup_rt_local_sids 2 "1 3 4"
620*95baa4e8SAndrea Mayer	setup_rt_local_sids 3 "1 2 4"
621*95baa4e8SAndrea Mayer	setup_rt_local_sids 4 "1 2 3"
622*95baa4e8SAndrea Mayer
623*95baa4e8SAndrea Mayer	# create a L2 VPN between hs-1 and hs-2.
624*95baa4e8SAndrea Mayer	# NB: currently, H.L2Encap* enables tunneling of L2 frames whose
625*95baa4e8SAndrea Mayer	# layer-3 is IPv4/IPv6.
626*95baa4e8SAndrea Mayer	#
627*95baa4e8SAndrea Mayer	# the network path between hs-1 and hs-2 traverses several routers
628*95baa4e8SAndrea Mayer	# depending on the direction of traffic.
629*95baa4e8SAndrea Mayer	#
630*95baa4e8SAndrea Mayer	# Direction hs-1 -> hs-2 (H.L2Encaps.Red)
631*95baa4e8SAndrea Mayer	# - rt-2 (SRv6 End.DX2 behavior)
632*95baa4e8SAndrea Mayer	#
633*95baa4e8SAndrea Mayer	# Direction hs-2 -> hs-1 (H.L2Encaps.Red)
634*95baa4e8SAndrea Mayer	#  - rt-4,rt-3 (SRv6 End behaviors)
635*95baa4e8SAndrea Mayer	#  - rt-1 (SRv6 End.DX2 behavior)
636*95baa4e8SAndrea Mayer	setup_l2vpn 1 "" 2
637*95baa4e8SAndrea Mayer	setup_l2vpn 2 "4 3" 1
638*95baa4e8SAndrea Mayer
639*95baa4e8SAndrea Mayer	# testing environment was set up successfully
640*95baa4e8SAndrea Mayer	SETUP_ERR=0
641*95baa4e8SAndrea Mayer}
642*95baa4e8SAndrea Mayer
643*95baa4e8SAndrea Mayercheck_rt_connectivity()
644*95baa4e8SAndrea Mayer{
645*95baa4e8SAndrea Mayer	local rtsrc="$1"
646*95baa4e8SAndrea Mayer	local rtdst="$2"
647*95baa4e8SAndrea Mayer	local prefix
648*95baa4e8SAndrea Mayer	local rtsrc_nsname
649*95baa4e8SAndrea Mayer
650*95baa4e8SAndrea Mayer	rtsrc_nsname="$(get_rtname "${rtsrc}")"
651*95baa4e8SAndrea Mayer
652*95baa4e8SAndrea Mayer	prefix="$(get_network_prefix "${rtsrc}" "${rtdst}")"
653*95baa4e8SAndrea Mayer
654*95baa4e8SAndrea Mayer	ip netns exec "${rtsrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \
655*95baa4e8SAndrea Mayer		"${prefix}::${rtdst}" >/dev/null 2>&1
656*95baa4e8SAndrea Mayer}
657*95baa4e8SAndrea Mayer
658*95baa4e8SAndrea Mayercheck_and_log_rt_connectivity()
659*95baa4e8SAndrea Mayer{
660*95baa4e8SAndrea Mayer	local rtsrc="$1"
661*95baa4e8SAndrea Mayer	local rtdst="$2"
662*95baa4e8SAndrea Mayer
663*95baa4e8SAndrea Mayer	check_rt_connectivity "${rtsrc}" "${rtdst}"
664*95baa4e8SAndrea Mayer	log_test $? 0 "Routers connectivity: rt-${rtsrc} -> rt-${rtdst}"
665*95baa4e8SAndrea Mayer}
666*95baa4e8SAndrea Mayer
667*95baa4e8SAndrea Mayercheck_hs_ipv6_connectivity()
668*95baa4e8SAndrea Mayer{
669*95baa4e8SAndrea Mayer	local hssrc="$1"
670*95baa4e8SAndrea Mayer	local hsdst="$2"
671*95baa4e8SAndrea Mayer	local hssrc_nsname
672*95baa4e8SAndrea Mayer
673*95baa4e8SAndrea Mayer	hssrc_nsname="$(get_hsname "${hssrc}")"
674*95baa4e8SAndrea Mayer
675*95baa4e8SAndrea Mayer	ip netns exec "${hssrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \
676*95baa4e8SAndrea Mayer		"${IPv6_HS_NETWORK}::${hsdst}" >/dev/null 2>&1
677*95baa4e8SAndrea Mayer}
678*95baa4e8SAndrea Mayer
679*95baa4e8SAndrea Mayercheck_hs_ipv4_connectivity()
680*95baa4e8SAndrea Mayer{
681*95baa4e8SAndrea Mayer	local hssrc="$1"
682*95baa4e8SAndrea Mayer	local hsdst="$2"
683*95baa4e8SAndrea Mayer	local hssrc_nsname
684*95baa4e8SAndrea Mayer
685*95baa4e8SAndrea Mayer	hssrc_nsname="$(get_hsname "${hssrc}")"
686*95baa4e8SAndrea Mayer
687*95baa4e8SAndrea Mayer	ip netns exec "${hssrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \
688*95baa4e8SAndrea Mayer		"${IPv4_HS_NETWORK}.${hsdst}" >/dev/null 2>&1
689*95baa4e8SAndrea Mayer}
690*95baa4e8SAndrea Mayer
691*95baa4e8SAndrea Mayercheck_and_log_hs2gw_connectivity()
692*95baa4e8SAndrea Mayer{
693*95baa4e8SAndrea Mayer	local hssrc="$1"
694*95baa4e8SAndrea Mayer
695*95baa4e8SAndrea Mayer	check_hs_ipv6_connectivity "${hssrc}" 254
696*95baa4e8SAndrea Mayer	log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> gw"
697*95baa4e8SAndrea Mayer
698*95baa4e8SAndrea Mayer	check_hs_ipv4_connectivity "${hssrc}" 254
699*95baa4e8SAndrea Mayer	log_test $? 0 "IPv4 Hosts connectivity: hs-${hssrc} -> gw"
700*95baa4e8SAndrea Mayer}
701*95baa4e8SAndrea Mayer
702*95baa4e8SAndrea Mayercheck_and_log_hs_ipv6_connectivity()
703*95baa4e8SAndrea Mayer{
704*95baa4e8SAndrea Mayer	local hssrc="$1"
705*95baa4e8SAndrea Mayer	local hsdst="$2"
706*95baa4e8SAndrea Mayer
707*95baa4e8SAndrea Mayer	check_hs_ipv6_connectivity "${hssrc}" "${hsdst}"
708*95baa4e8SAndrea Mayer	log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> hs-${hsdst}"
709*95baa4e8SAndrea Mayer}
710*95baa4e8SAndrea Mayer
711*95baa4e8SAndrea Mayercheck_and_log_hs_ipv4_connectivity()
712*95baa4e8SAndrea Mayer{
713*95baa4e8SAndrea Mayer	local hssrc="$1"
714*95baa4e8SAndrea Mayer	local hsdst="$2"
715*95baa4e8SAndrea Mayer
716*95baa4e8SAndrea Mayer	check_hs_ipv4_connectivity "${hssrc}" "${hsdst}"
717*95baa4e8SAndrea Mayer	log_test $? 0 "IPv4 Hosts connectivity: hs-${hssrc} -> hs-${hsdst}"
718*95baa4e8SAndrea Mayer}
719*95baa4e8SAndrea Mayer
720*95baa4e8SAndrea Mayercheck_and_log_hs_connectivity()
721*95baa4e8SAndrea Mayer{
722*95baa4e8SAndrea Mayer	local hssrc="$1"
723*95baa4e8SAndrea Mayer	local hsdst="$2"
724*95baa4e8SAndrea Mayer
725*95baa4e8SAndrea Mayer	check_and_log_hs_ipv4_connectivity "${hssrc}" "${hsdst}"
726*95baa4e8SAndrea Mayer	check_and_log_hs_ipv6_connectivity "${hssrc}" "${hsdst}"
727*95baa4e8SAndrea Mayer}
728*95baa4e8SAndrea Mayer
729*95baa4e8SAndrea Mayerrouter_tests()
730*95baa4e8SAndrea Mayer{
731*95baa4e8SAndrea Mayer	local i
732*95baa4e8SAndrea Mayer	local j
733*95baa4e8SAndrea Mayer
734*95baa4e8SAndrea Mayer	log_section "IPv6 routers connectivity test"
735*95baa4e8SAndrea Mayer
736*95baa4e8SAndrea Mayer	for i in ${ROUTERS}; do
737*95baa4e8SAndrea Mayer		for j in ${ROUTERS}; do
738*95baa4e8SAndrea Mayer			if [ "${i}" -eq "${j}" ]; then
739*95baa4e8SAndrea Mayer				continue
740*95baa4e8SAndrea Mayer			fi
741*95baa4e8SAndrea Mayer
742*95baa4e8SAndrea Mayer			check_and_log_rt_connectivity "${i}" "${j}"
743*95baa4e8SAndrea Mayer		done
744*95baa4e8SAndrea Mayer	done
745*95baa4e8SAndrea Mayer}
746*95baa4e8SAndrea Mayer
747*95baa4e8SAndrea Mayerhost2gateway_tests()
748*95baa4e8SAndrea Mayer{
749*95baa4e8SAndrea Mayer	local hs
750*95baa4e8SAndrea Mayer
751*95baa4e8SAndrea Mayer	log_section "IPv4/IPv6 connectivity test among hosts and gateways"
752*95baa4e8SAndrea Mayer
753*95baa4e8SAndrea Mayer	for hs in ${HOSTS}; do
754*95baa4e8SAndrea Mayer		check_and_log_hs2gw_connectivity "${hs}"
755*95baa4e8SAndrea Mayer	done
756*95baa4e8SAndrea Mayer}
757*95baa4e8SAndrea Mayer
758*95baa4e8SAndrea Mayerhost_vpn_tests()
759*95baa4e8SAndrea Mayer{
760*95baa4e8SAndrea Mayer	log_section "SRv6 L2 VPN connectivity test hosts (h1 <-> h2)"
761*95baa4e8SAndrea Mayer
762*95baa4e8SAndrea Mayer	check_and_log_hs_connectivity 1 2
763*95baa4e8SAndrea Mayer	check_and_log_hs_connectivity 2 1
764*95baa4e8SAndrea Mayer}
765*95baa4e8SAndrea Mayer
766*95baa4e8SAndrea Mayertest_dummy_dev_or_ksft_skip()
767*95baa4e8SAndrea Mayer{
768*95baa4e8SAndrea Mayer	local test_netns
769*95baa4e8SAndrea Mayer
770*95baa4e8SAndrea Mayer	test_netns="dummy-$(mktemp -u XXXXXXXX)"
771*95baa4e8SAndrea Mayer
772*95baa4e8SAndrea Mayer	if ! ip netns add "${test_netns}"; then
773*95baa4e8SAndrea Mayer		echo "SKIP: Cannot set up netns for testing dummy dev support"
774*95baa4e8SAndrea Mayer		exit "${ksft_skip}"
775*95baa4e8SAndrea Mayer	fi
776*95baa4e8SAndrea Mayer
777*95baa4e8SAndrea Mayer	modprobe dummy &>/dev/null || true
778*95baa4e8SAndrea Mayer	if ! ip -netns "${test_netns}" link \
779*95baa4e8SAndrea Mayer		add "${DUMMY_DEVNAME}" type dummy; then
780*95baa4e8SAndrea Mayer		echo "SKIP: dummy dev not supported"
781*95baa4e8SAndrea Mayer
782*95baa4e8SAndrea Mayer		ip netns del "${test_netns}"
783*95baa4e8SAndrea Mayer		exit "${ksft_skip}"
784*95baa4e8SAndrea Mayer	fi
785*95baa4e8SAndrea Mayer
786*95baa4e8SAndrea Mayer	ip netns del "${test_netns}"
787*95baa4e8SAndrea Mayer}
788*95baa4e8SAndrea Mayer
789*95baa4e8SAndrea Mayertest_iproute2_supp_or_ksft_skip()
790*95baa4e8SAndrea Mayer{
791*95baa4e8SAndrea Mayer	if ! ip route help 2>&1 | grep -qo "l2encap.red"; then
792*95baa4e8SAndrea Mayer		echo "SKIP: Missing SRv6 l2encap.red support in iproute2"
793*95baa4e8SAndrea Mayer		exit "${ksft_skip}"
794*95baa4e8SAndrea Mayer	fi
795*95baa4e8SAndrea Mayer}
796*95baa4e8SAndrea Mayer
797*95baa4e8SAndrea Mayerif [ "$(id -u)" -ne 0 ]; then
798*95baa4e8SAndrea Mayer	echo "SKIP: Need root privileges"
799*95baa4e8SAndrea Mayer	exit "${ksft_skip}"
800*95baa4e8SAndrea Mayerfi
801*95baa4e8SAndrea Mayer
802*95baa4e8SAndrea Mayer# required programs to carry out this selftest
803*95baa4e8SAndrea Mayertest_command_or_ksft_skip ip
804*95baa4e8SAndrea Mayertest_command_or_ksft_skip ping
805*95baa4e8SAndrea Mayertest_command_or_ksft_skip sysctl
806*95baa4e8SAndrea Mayertest_command_or_ksft_skip grep
807*95baa4e8SAndrea Mayer
808*95baa4e8SAndrea Mayertest_iproute2_supp_or_ksft_skip
809*95baa4e8SAndrea Mayertest_dummy_dev_or_ksft_skip
810*95baa4e8SAndrea Mayer
811*95baa4e8SAndrea Mayerset -e
812*95baa4e8SAndrea Mayertrap cleanup EXIT
813*95baa4e8SAndrea Mayer
814*95baa4e8SAndrea Mayersetup
815*95baa4e8SAndrea Mayerset +e
816*95baa4e8SAndrea Mayer
817*95baa4e8SAndrea Mayerrouter_tests
818*95baa4e8SAndrea Mayerhost2gateway_tests
819*95baa4e8SAndrea Mayerhost_vpn_tests
820*95baa4e8SAndrea Mayer
821*95baa4e8SAndrea Mayerprint_log_test_results
822