Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
169source lib.sh
170
171readonly VRF_TID=100
172readonly VRF_DEVNAME="vrf-${VRF_TID}"
173readonly RT2HS_DEVNAME="veth-t${VRF_TID}"
174readonly LOCALSID_TABLE_ID=90
175readonly IPv6_RT_NETWORK=fcf0:0
176readonly IPv6_HS_NETWORK=cafe
177readonly IPv4_HS_NETWORK=10.0.0
178readonly VPN_LOCATOR_SERVICE=fcff
179readonly END_FUNC=000e
180readonly DT46_FUNC=0d46
181
182PING_TIMEOUT_SEC=4
183PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
184
185# IDs of routers and hosts are initialized during the setup of the testing
186# network
187ROUTERS=''
188HOSTS=''
189
190SETUP_ERR=1
191
192ret=${ksft_skip}
193nsuccess=0
194nfail=0
195
196HAS_TUNSRC=false
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_rtname()
252{
253 local rtid="$1"
254
255 echo "rt_${rtid}"
256}
257
258get_hsname()
259{
260 local hsid="$1"
261
262 echo "hs_${hsid}"
263}
264
265create_router()
266{
267 local rtid="$1"
268 local nsname
269
270 nsname="$(get_rtname "${rtid}")"
271 setup_ns "${nsname}"
272}
273
274create_host()
275{
276 local hsid="$1"
277 local nsname
278
279 nsname="$(get_hsname "${hsid}")"
280 setup_ns "${nsname}"
281}
282
283cleanup()
284{
285 cleanup_all_ns
286 # check whether the setup phase was completed successfully or not. In
287 # case of an error during the setup phase of the testing environment,
288 # the selftest is considered as "skipped".
289 if [ "${SETUP_ERR}" -ne 0 ]; then
290 echo "SKIP: Setting up the testing environment failed"
291 exit "${ksft_skip}"
292 fi
293
294 exit "${ret}"
295}
296
297add_link_rt_pairs()
298{
299 local rt="$1"
300 local rt_neighs="$2"
301 local neigh
302 local nsname
303 local neigh_nsname
304
305 eval nsname=\${$(get_rtname "${rt}")}
306
307 for neigh in ${rt_neighs}; do
308 eval neigh_nsname=\${$(get_rtname "${neigh}")}
309
310 ip link add "veth-rt-${rt}-${neigh}" netns "${nsname}" \
311 type veth peer name "veth-rt-${neigh}-${rt}" \
312 netns "${neigh_nsname}"
313 done
314}
315
316get_network_prefix()
317{
318 local rt="$1"
319 local neigh="$2"
320 local p="${rt}"
321 local q="${neigh}"
322
323 if [ "${p}" -gt "${q}" ]; then
324 p="${q}"; q="${rt}"
325 fi
326
327 echo "${IPv6_RT_NETWORK}:${p}:${q}"
328}
329
330# Setup the basic networking for the routers
331setup_rt_networking()
332{
333 local rt="$1"
334 local rt_neighs="$2"
335 local nsname
336 local net_prefix
337 local devname
338 local neigh
339
340 eval nsname=\${$(get_rtname "${rt}")}
341
342 for neigh in ${rt_neighs}; do
343 devname="veth-rt-${rt}-${neigh}"
344
345 net_prefix="$(get_network_prefix "${rt}" "${neigh}")"
346
347 ip -netns "${nsname}" addr \
348 add "${net_prefix}::${rt}/64" dev "${devname}" nodad
349
350 # A dedicated ::dead:<rt> address (with preferred_lft 0, i.e.,
351 # deprecated) is added when there is support for tunsrc. Because
352 # it is deprecated, the kernel should never auto-select it as
353 # source with current config. Only an explicit tunsrc can place
354 # it in the outer header.
355 if $HAS_TUNSRC; then
356 ip -netns "${nsname}" addr \
357 add "${net_prefix}::dead:${rt}/64" \
358 dev "${devname}" nodad preferred_lft 0
359 fi
360
361 ip -netns "${nsname}" link set "${devname}" up
362 done
363
364 ip -netns "${nsname}" link set lo up
365
366 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0
367 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0
368 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.forwarding=1
369 ip netns exec "${nsname}" sysctl -wq net.ipv4.ip_forward=1
370}
371
372# Setup local SIDs for an SRv6 router
373setup_rt_local_sids()
374{
375 local rt="$1"
376 local rt_neighs="$2"
377 local net_prefix
378 local devname
379 local nsname
380 local neigh
381
382 eval nsname=\${$(get_rtname "${rt}")}
383
384 for neigh in ${rt_neighs}; do
385 devname="veth-rt-${rt}-${neigh}"
386
387 net_prefix="$(get_network_prefix "${rt}" "${neigh}")"
388
389 # set underlay network routes for SIDs reachability
390 ip -netns "${nsname}" -6 route \
391 add "${VPN_LOCATOR_SERVICE}:${neigh}::/32" \
392 table "${LOCALSID_TABLE_ID}" \
393 via "${net_prefix}::${neigh}" dev "${devname}"
394 done
395
396 # Local End behavior (note that "dev" is dummy and the VRF is chosen
397 # for the sake of simplicity).
398 ip -netns "${nsname}" -6 route \
399 add "${VPN_LOCATOR_SERVICE}:${rt}::${END_FUNC}" \
400 table "${LOCALSID_TABLE_ID}" \
401 encap seg6local action End dev "${VRF_DEVNAME}"
402
403 # Local End.DT46 behavior
404 ip -netns "${nsname}" -6 route \
405 add "${VPN_LOCATOR_SERVICE}:${rt}::${DT46_FUNC}" \
406 table "${LOCALSID_TABLE_ID}" \
407 encap seg6local action End.DT46 vrftable "${VRF_TID}" \
408 dev "${VRF_DEVNAME}"
409
410 # all SIDs for VPNs start with a common locator. Routes and SRv6
411 # Endpoint behavior instances are grouped together in the 'localsid'
412 # table.
413 ip -netns "${nsname}" -6 rule \
414 add to "${VPN_LOCATOR_SERVICE}::/16" \
415 lookup "${LOCALSID_TABLE_ID}" prio 999
416
417 # set default routes to unreachable for both ipv4 and ipv6
418 ip -netns "${nsname}" -6 route \
419 add unreachable default metric 4278198272 \
420 vrf "${VRF_DEVNAME}"
421
422 ip -netns "${nsname}" -4 route \
423 add unreachable default metric 4278198272 \
424 vrf "${VRF_DEVNAME}"
425}
426
427# build and install the SRv6 policy into the ingress SRv6 router.
428# args:
429# $1 - destination host (i.e. cafe::x host)
430# $2 - SRv6 router configured for enforcing the SRv6 Policy
431# $3 - SRv6 routers configured for steering traffic (End behaviors)
432# $4 - SRv6 router configured for removing the SRv6 Policy (router connected
433# to the destination host)
434# $5 - encap mode (full or red)
435# $6 - traffic type (IPv6 or IPv4)
436# $7 - force tunsrc (true or false)
437__setup_rt_policy()
438{
439 local dst="$1"
440 local encap_rt="$2"
441 local end_rts="$3"
442 local dec_rt="$4"
443 local mode="$5"
444 local traffic="$6"
445 local with_tunsrc="$7"
446 local nsname
447 local policy=''
448 local tunsrc=''
449 local n
450
451 # Verify the per-route tunnel source address ("tunsrc") feature.
452 # If it is not supported, fallback on encap config without tunsrc.
453 if $with_tunsrc && $HAS_TUNSRC; then
454 local net_prefix
455 local drule
456 local nxt
457
458 eval nsname=\${$(get_rtname "${dec_rt}")}
459
460 # Next SRv6 hop: first End router if any, or the decap router
461 [ -z "${end_rts}" ] && nxt="${dec_rt}" || nxt="${end_rts%% *}"
462
463 # Use the right prefix for tunsrc depending on the next SRv6 hop
464 net_prefix="$(get_network_prefix "${encap_rt}" "${nxt}")"
465 tunsrc="tunsrc ${net_prefix}::dead:${encap_rt}"
466
467 # To verify that the outer source address matches the one
468 # configured with tunsrc, the decap router discards packets
469 # with any other source address.
470 ip netns exec "${nsname}" ip6tables -t raw -I PREROUTING 1 \
471 -s "${net_prefix}::dead:${encap_rt}" \
472 -d "${VPN_LOCATOR_SERVICE}:${dec_rt}::${DT46_FUNC}" \
473 -j ACCEPT
474
475 drule="PREROUTING \
476 -d ${VPN_LOCATOR_SERVICE}:${dec_rt}::${DT46_FUNC} \
477 -j DROP"
478
479 if ! ip netns exec "${nsname}" \
480 ip6tables -t raw -C ${drule} &>/dev/null; then
481 ip netns exec "${nsname}" ip6tables -t raw -A ${drule}
482 fi
483 fi
484
485 eval nsname=\${$(get_rtname "${encap_rt}")}
486
487 for n in ${end_rts}; do
488 policy="${policy}${VPN_LOCATOR_SERVICE}:${n}::${END_FUNC},"
489 done
490
491 policy="${policy}${VPN_LOCATOR_SERVICE}:${dec_rt}::${DT46_FUNC}"
492
493 # add SRv6 policy to incoming traffic sent by connected hosts
494 if [ "${traffic}" -eq 6 ]; then
495 ip -netns "${nsname}" -6 route \
496 add "${IPv6_HS_NETWORK}::${dst}" vrf "${VRF_DEVNAME}" \
497 encap seg6 mode "${mode}" ${tunsrc} segs "${policy}" \
498 dev "${VRF_DEVNAME}"
499
500 ip -netns "${nsname}" -6 neigh \
501 add proxy "${IPv6_HS_NETWORK}::${dst}" \
502 dev "${RT2HS_DEVNAME}"
503 else
504 # "dev" must be different from the one where the packet is
505 # received, otherwise the proxy arp does not work.
506 ip -netns "${nsname}" -4 route \
507 add "${IPv4_HS_NETWORK}.${dst}" vrf "${VRF_DEVNAME}" \
508 encap seg6 mode "${mode}" ${tunsrc} segs "${policy}" \
509 dev "${VRF_DEVNAME}"
510 fi
511}
512
513# see __setup_rt_policy
514setup_rt_policy_ipv6()
515{
516 __setup_rt_policy "$1" "$2" "$3" "$4" "$5" 6 "$6"
517}
518
519#see __setup_rt_policy
520setup_rt_policy_ipv4()
521{
522 __setup_rt_policy "$1" "$2" "$3" "$4" "$5" 4 "$6"
523}
524
525setup_hs()
526{
527 local hs="$1"
528 local rt="$2"
529 local hsname
530 local rtname
531
532 eval hsname=\${$(get_hsname "${hs}")}
533 eval rtname=\${$(get_rtname "${rt}")}
534
535 ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0
536 ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0
537
538 ip -netns "${hsname}" link add veth0 type veth \
539 peer name "${RT2HS_DEVNAME}" netns "${rtname}"
540
541 ip -netns "${hsname}" addr \
542 add "${IPv6_HS_NETWORK}::${hs}/64" dev veth0 nodad
543 ip -netns "${hsname}" addr add "${IPv4_HS_NETWORK}.${hs}/24" dev veth0
544
545 ip -netns "${hsname}" link set veth0 up
546 ip -netns "${hsname}" link set lo up
547
548 # configure the VRF on the router which is directly connected to the
549 # source host.
550 ip -netns "${rtname}" link \
551 add "${VRF_DEVNAME}" type vrf table "${VRF_TID}"
552 ip -netns "${rtname}" link set "${VRF_DEVNAME}" up
553
554 # enslave the veth interface connecting the router with the host to the
555 # VRF in the access router
556 ip -netns "${rtname}" link \
557 set "${RT2HS_DEVNAME}" master "${VRF_DEVNAME}"
558
559 ip -netns "${rtname}" addr \
560 add "${IPv6_HS_NETWORK}::254/64" dev "${RT2HS_DEVNAME}" nodad
561 ip -netns "${rtname}" addr \
562 add "${IPv4_HS_NETWORK}.254/24" dev "${RT2HS_DEVNAME}"
563
564 ip -netns "${rtname}" link set "${RT2HS_DEVNAME}" up
565
566 ip netns exec "${rtname}" \
567 sysctl -wq net.ipv6.conf."${RT2HS_DEVNAME}".proxy_ndp=1
568 ip netns exec "${rtname}" \
569 sysctl -wq net.ipv4.conf."${RT2HS_DEVNAME}".proxy_arp=1
570
571 ip netns exec "${rtname}" sh -c "echo 1 > /proc/sys/net/vrf/strict_mode"
572}
573
574setup()
575{
576 local i
577
578 # create routers
579 ROUTERS="1 2 3 4"; readonly ROUTERS
580 for i in ${ROUTERS}; do
581 create_router "${i}"
582 done
583
584 # create hosts
585 HOSTS="1 2 3 4"; readonly HOSTS
586 for i in ${HOSTS}; do
587 create_host "${i}"
588 done
589
590 # set up the links for connecting routers
591 add_link_rt_pairs 1 "2 3 4"
592 add_link_rt_pairs 2 "3 4"
593 add_link_rt_pairs 3 "4"
594
595 # set up the basic connectivity of routers and routes required for
596 # reachability of SIDs.
597 setup_rt_networking 1 "2 3 4"
598 setup_rt_networking 2 "1 3 4"
599 setup_rt_networking 3 "1 2 4"
600 setup_rt_networking 4 "1 2 3"
601
602 # set up the hosts connected to routers
603 setup_hs 1 1
604 setup_hs 2 2
605 setup_hs 3 3
606 setup_hs 4 4
607
608 # set up default SRv6 Endpoints (i.e. SRv6 End and SRv6 End.DT46)
609 setup_rt_local_sids 1 "2 3 4"
610 setup_rt_local_sids 2 "1 3 4"
611 setup_rt_local_sids 3 "1 2 4"
612 setup_rt_local_sids 4 "1 2 3"
613
614 # set up SRv6 policies
615
616 # create an IPv6 VPN between hosts hs-1 and hs-2.
617 # the network path between hs-1 and hs-2 traverses several routers
618 # depending on the direction of traffic.
619 #
620 # Direction hs-1 -> hs-2 (H.Encaps.Red + tunsrc)
621 # - rt-3,rt-4 (SRv6 End behaviors)
622 # - rt-2 (SRv6 End.DT46 behavior)
623 #
624 # Direction hs-2 -> hs-1 (H.Encaps.Red)
625 # - rt-1 (SRv6 End.DT46 behavior)
626 setup_rt_policy_ipv6 2 1 "3 4" 2 encap.red true
627 setup_rt_policy_ipv6 1 2 "" 1 encap.red false
628
629 # create an IPv4 VPN between hosts hs-1 and hs-2
630 # the network path between hs-1 and hs-2 traverses several routers
631 # depending on the direction of traffic.
632 #
633 # Direction hs-1 -> hs-2 (H.Encaps.Red + tunsrc)
634 # - rt-2 (SRv6 End.DT46 behavior)
635 #
636 # Direction hs-2 -> hs-1 (H.Encaps.Red)
637 # - rt-4,rt-3 (SRv6 End behaviors)
638 # - rt-1 (SRv6 End.DT46 behavior)
639 setup_rt_policy_ipv4 2 1 "" 2 encap.red true
640 setup_rt_policy_ipv4 1 2 "4 3" 1 encap.red false
641
642 # create an IPv6 VPN between hosts hs-3 and hs-4
643 # the network path between hs-3 and hs-4 traverses several routers
644 # depending on the direction of traffic.
645 #
646 # Direction hs-3 -> hs-4 (H.Encaps.Red + tunsrc)
647 # - rt-2 (SRv6 End Behavior)
648 # - rt-4 (SRv6 End.DT46 behavior)
649 #
650 # Direction hs-4 -> hs-3 (H.Encaps.Red)
651 # - rt-1 (SRv6 End behavior)
652 # - rt-3 (SRv6 End.DT46 behavior)
653 setup_rt_policy_ipv6 4 3 "2" 4 encap.red true
654 setup_rt_policy_ipv6 3 4 "1" 3 encap.red false
655
656 # testing environment was set up successfully
657 SETUP_ERR=0
658}
659
660check_rt_connectivity()
661{
662 local rtsrc="$1"
663 local rtdst="$2"
664 local prefix
665 local rtsrc_nsname
666
667 eval rtsrc_nsname=\${$(get_rtname "${rtsrc}")}
668
669 prefix="$(get_network_prefix "${rtsrc}" "${rtdst}")"
670
671 ip netns exec "${rtsrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \
672 "${prefix}::${rtdst}" >/dev/null 2>&1
673}
674
675check_and_log_rt_connectivity()
676{
677 local rtsrc="$1"
678 local rtdst="$2"
679
680 check_rt_connectivity "${rtsrc}" "${rtdst}"
681 log_test $? 0 "Routers connectivity: rt-${rtsrc} -> rt-${rtdst}"
682}
683
684check_hs_ipv6_connectivity()
685{
686 local hssrc="$1"
687 local hsdst="$2"
688 local hssrc_nsname
689
690 eval hssrc_nsname=\${$(get_hsname "${hssrc}")}
691
692 ip netns exec "${hssrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \
693 "${IPv6_HS_NETWORK}::${hsdst}" >/dev/null 2>&1
694}
695
696check_hs_ipv4_connectivity()
697{
698 local hssrc="$1"
699 local hsdst="$2"
700 local hssrc_nsname
701
702 eval hssrc_nsname=\${$(get_hsname "${hssrc}")}
703
704 ip netns exec "${hssrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \
705 "${IPv4_HS_NETWORK}.${hsdst}" >/dev/null 2>&1
706}
707
708check_and_log_hs2gw_connectivity()
709{
710 local hssrc="$1"
711
712 check_hs_ipv6_connectivity "${hssrc}" 254
713 log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> gw"
714
715 check_hs_ipv4_connectivity "${hssrc}" 254
716 log_test $? 0 "IPv4 Hosts connectivity: hs-${hssrc} -> gw"
717}
718
719check_and_log_hs_ipv6_connectivity()
720{
721 local hssrc="$1"
722 local hsdst="$2"
723
724 check_hs_ipv6_connectivity "${hssrc}" "${hsdst}"
725 log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> hs-${hsdst}"
726}
727
728check_and_log_hs_ipv4_connectivity()
729{
730 local hssrc="$1"
731 local hsdst="$2"
732
733 check_hs_ipv4_connectivity "${hssrc}" "${hsdst}"
734 log_test $? 0 "IPv4 Hosts connectivity: hs-${hssrc} -> hs-${hsdst}"
735}
736
737check_and_log_hs_connectivity()
738{
739 local hssrc="$1"
740 local hsdst="$2"
741
742 check_and_log_hs_ipv4_connectivity "${hssrc}" "${hsdst}"
743 check_and_log_hs_ipv6_connectivity "${hssrc}" "${hsdst}"
744}
745
746check_and_log_hs_ipv6_isolation()
747{
748 local hssrc="$1"
749 local hsdst="$2"
750
751 # in this case, the connectivity test must fail
752 check_hs_ipv6_connectivity "${hssrc}" "${hsdst}"
753 log_test $? 1 "IPv6 Hosts isolation: hs-${hssrc} -X-> hs-${hsdst}"
754}
755
756check_and_log_hs_ipv4_isolation()
757{
758 local hssrc="$1"
759 local hsdst="$2"
760
761 # in this case, the connectivity test must fail
762 check_hs_ipv4_connectivity "${hssrc}" "${hsdst}"
763 log_test $? 1 "IPv4 Hosts isolation: hs-${hssrc} -X-> hs-${hsdst}"
764}
765
766check_and_log_hs_isolation()
767{
768 local hssrc="$1"
769 local hsdst="$2"
770
771 check_and_log_hs_ipv6_isolation "${hssrc}" "${hsdst}"
772 check_and_log_hs_ipv4_isolation "${hssrc}" "${hsdst}"
773}
774
775router_tests()
776{
777 local i
778 local j
779
780 log_section "IPv6 routers connectivity test"
781
782 for i in ${ROUTERS}; do
783 for j in ${ROUTERS}; do
784 if [ "${i}" -eq "${j}" ]; then
785 continue
786 fi
787
788 check_and_log_rt_connectivity "${i}" "${j}"
789 done
790 done
791}
792
793host2gateway_tests()
794{
795 local hs
796
797 log_section "IPv4/IPv6 connectivity test among hosts and gateways"
798
799 for hs in ${HOSTS}; do
800 check_and_log_hs2gw_connectivity "${hs}"
801 done
802}
803
804host_vpn_tests()
805{
806 log_section "SRv6 VPN connectivity test hosts (h1 <-> h2, IPv4/IPv6)"
807
808 check_and_log_hs_connectivity 1 2
809 check_and_log_hs_connectivity 2 1
810
811 log_section "SRv6 VPN connectivity test hosts (h3 <-> h4, IPv6 only)"
812
813 check_and_log_hs_ipv6_connectivity 3 4
814 check_and_log_hs_ipv6_connectivity 4 3
815}
816
817host_vpn_isolation_tests()
818{
819 local l1="1 2"
820 local l2="3 4"
821 local tmp
822 local i
823 local j
824 local k
825
826 log_section "SRv6 VPN isolation test among hosts"
827
828 for k in 0 1; do
829 for i in ${l1}; do
830 for j in ${l2}; do
831 check_and_log_hs_isolation "${i}" "${j}"
832 done
833 done
834
835 # let us test the reverse path
836 tmp="${l1}"; l1="${l2}"; l2="${tmp}"
837 done
838
839 log_section "SRv6 VPN isolation test among hosts (h2 <-> h4, IPv4 only)"
840
841 check_and_log_hs_ipv4_isolation 2 4
842 check_and_log_hs_ipv4_isolation 4 2
843}
844
845test_iproute2_supp_or_ksft_skip()
846{
847 if ! ip route help 2>&1 | grep -qo "encap.red"; then
848 echo "SKIP: Missing SRv6 encap.red support in iproute2"
849 exit "${ksft_skip}"
850 fi
851}
852
853test_vrf_or_ksft_skip()
854{
855 modprobe vrf &>/dev/null || true
856 if [ ! -e /proc/sys/net/vrf/strict_mode ]; then
857 echo "SKIP: vrf sysctl does not exist"
858 exit "${ksft_skip}"
859 fi
860}
861
862# Before enabling tunsrc tests, make sure tunsrc and ip6tables are supported.
863check_tunsrc_support()
864{
865 setup_ns tunsrc_ns
866
867 ip -netns "${tunsrc_ns}" link add veth0 type veth \
868 peer name veth1 netns "${tunsrc_ns}"
869
870 ip -netns "${tunsrc_ns}" link set veth0 up
871
872 if ! ip -netns "${tunsrc_ns}" -6 route add fc00::dead:beef/128 \
873 encap seg6 mode encap.red tunsrc fc00::1 segs fc00::2 \
874 dev veth0 &>/dev/null; then
875 cleanup_ns "${tunsrc_ns}"
876 return
877 fi
878
879 if ! ip -netns "${tunsrc_ns}" -6 route show | grep -q "tunsrc"; then
880 cleanup_ns "${tunsrc_ns}"
881 return
882 fi
883
884 if ! ip netns exec "${tunsrc_ns}" ip6tables -t raw -A PREROUTING \
885 -d fc00::dead:beef -j DROP &>/dev/null; then
886 cleanup_ns "${tunsrc_ns}"
887 return
888 fi
889
890 cleanup_ns "${tunsrc_ns}"
891 HAS_TUNSRC=true
892}
893
894if [ "$(id -u)" -ne 0 ]; then
895 echo "SKIP: Need root privileges"
896 exit "${ksft_skip}"
897fi
898
899# required programs to carry out this selftest
900test_command_or_ksft_skip ip
901test_command_or_ksft_skip ping
902test_command_or_ksft_skip sysctl
903test_command_or_ksft_skip grep
904
905test_iproute2_supp_or_ksft_skip
906test_vrf_or_ksft_skip
907
908set -e
909trap cleanup EXIT
910
911check_tunsrc_support
912setup
913set +e
914
915router_tests
916host2gateway_tests
917host_vpn_tests
918host_vpn_isolation_tests
919
920print_log_test_results