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