accel/qaic: Add AIC200 support
[drm/drm-misc.git] / tools / testing / selftests / net / srv6_end_next_csid_l3vpn_test.sh
blob87e414cc417c498bb8942ba2151d01a368dfa06a
1 #!/bin/bash
2 # SPDX-License-Identifier: GPL-2.0
4 # author: Andrea Mayer <andrea.mayer@uniroma2.it>
6 # This script is designed for testing the support of NEXT-C-SID flavor for SRv6
7 # End behavior.
8 # A basic knowledge of SRv6 architecture [1] and of the compressed SID approach
9 # [2] is assumed for the reader.
11 # The network topology used in the selftest is depicted hereafter, composed by
12 # two hosts and four routers. Hosts hs-1 and hs-2 are connected through an
13 # IPv4/IPv6 L3 VPN service, offered by routers rt-1, rt-2, rt-3 and rt-4 using
14 # the NEXT-C-SID flavor. The key components for such VPNs are:
16 # i) The SRv6 H.Encaps/H.Encaps.Red behaviors [1] apply SRv6 Policies on
17 # traffic received by connected hosts, initiating the VPN tunnel;
19 # ii) The SRv6 End behavior [1] advances the active SID in the SID List
20 # carried by the SRH;
22 # iii) The NEXT-C-SID mechanism [2] offers the possibility of encoding several
23 # SRv6 segments within a single 128-bit SID address, referred to as a
24 # Compressed SID (C-SID) container. In this way, the length of the SID
25 # List can be drastically reduced.
26 # The NEXT-C-SID is provided as a "flavor" of the SRv6 End behavior
27 # which advances the current C-SID (i.e. the Locator-Node Function defined
28 # in [2]) with the next one carried in the Argument, if available.
29 # When no more C-SIDs are available in the Argument, the SRv6 End behavior
30 # will apply the End function selecting the next SID in the SID List.
32 # iv) The SRv6 End.DT46 behavior [1] is used for removing the SRv6 Policy and,
33 # thus, it terminates the VPN tunnel. Such a behavior is capable of
34 # handling, at the same time, both tunneled IPv4 and IPv6 traffic.
36 # [1] https://datatracker.ietf.org/doc/html/rfc8986
37 # [2] https://datatracker.ietf.org/doc/html/draft-ietf-spring-srv6-srh-compression
40 # cafe::1 cafe::2
41 # 10.0.0.1 10.0.0.2
42 # +--------+ +--------+
43 # | | | |
44 # | hs-1 | | hs-2 |
45 # | | | |
46 # +---+----+ +----+---+
47 # cafe::/64 | | cafe::/64
48 # 10.0.0.0/24 | | 10.0.0.0/24
49 # +---+----+ +----+---+
50 # | | fcf0:0:1:2::/64 | |
51 # | rt-1 +-------------------+ rt-2 |
52 # | | | |
53 # +---+----+ +----+---+
54 # | . . |
55 # | fcf0:0:1:3::/64 . |
56 # | . . |
57 # | . . |
58 # fcf0:0:1:4::/64 | . | fcf0:0:2:3::/64
59 # | . . |
60 # | . . |
61 # | fcf0:0:2:4::/64 . |
62 # | . . |
63 # +---+----+ +----+---+
64 # | | | |
65 # | rt-4 +-------------------+ rt-3 |
66 # | | fcf0:0:3:4::/64 | |
67 # +---+----+ +----+---+
69 # Every fcf0:0:x:y::/64 network interconnects the SRv6 routers rt-x with rt-y in
70 # the selftest network.
72 # Local SID/C-SID table
73 # =====================
75 # Each SRv6 router is configured with a Local SID/C-SID table in which
76 # SIDs/C-SIDs are stored. Considering an SRv6 router rt-x, SIDs/C-SIDs are
77 # configured in the Local SID/C-SIDs table as follows:
79 # Local SID/C-SID table for SRv6 router rt-x
80 # +-----------------------------------------------------------+
81 # |fcff:x::d46 is associated with the non-compressed SRv6 |
82 # | End.DT46 behavior |
83 # +-----------------------------------------------------------+
84 # |fcbb:0:0x00::/48 is associated with the NEXT-C-SID flavor |
85 # | of SRv6 End behavior |
86 # +-----------------------------------------------------------+
87 # |fcbb:0:0x00:d46::/64 is associated with the SRv6 End.DT46 |
88 # | behavior when NEXT-C-SID compression is turned on |
89 # +-----------------------------------------------------------+
91 # The fcff::/16 prefix is reserved for implementing SRv6 services with regular
92 # (non compressed) SIDs. Reachability of SIDs is ensured by proper configuration
93 # of the IPv6 routing tables in the routers.
94 # Similarly, the fcbb:0::/32 prefix is reserved for implementing SRv6 VPN
95 # services leveraging the NEXT-C-SID compression mechanism. Indeed, the
96 # fcbb:0::/32 is used for encoding the Locator-Block while the Locator-Node
97 # Function is encoded with 16 bits.
99 # Incoming traffic classification and application of SRv6 Policies
100 # ================================================================
102 # An SRv6 ingress router applies different SRv6 Policies to the traffic received
103 # from a connected host, considering the IPv4 or IPv6 destination address.
104 # SRv6 policy enforcement consists of encapsulating the received traffic into a
105 # new IPv6 packet with a given SID List contained in the SRH.
106 # When the SID List contains only one SID, the SRH could be omitted completely
107 # and that SID is stored directly in the IPv6 Destination Address (DA) (this is
108 # called "reduced" encapsulation).
110 # Test cases for NEXT-C-SID
111 # =========================
113 # We consider two test cases for NEXT-C-SID: i) single SID and ii) double SID.
115 # In the single SID test case we have a number of segments that are all
116 # contained in a single Compressed SID (C-SID) container. Therefore the
117 # resulting SID List has only one SID. Using the reduced encapsulation format
118 # this will result in a packet with no SRH.
120 # In the double SID test case we have one segment carried in a Compressed SID
121 # (C-SID) container, followed by a regular (non compressed) SID. The resulting
122 # SID List has two segments and it is possible to test the advance to the next
123 # SID when all the C-SIDs in a C-SID container have been processed. Using the
124 # reduced encapsulation format this will result in a packet with an SRH
125 # containing 1 segment.
127 # For the single SID test case, we use the IPv4 addresses of hs-1 and hs-2, for
128 # the double SID test case, we use their IPv6 addresses. This is only done to
129 # simplify the test setup and avoid adding other hosts or multiple addresses on
130 # the same interface of a host.
132 # Traffic from hs-1 to hs-2
133 # -------------------------
135 # Packets generated from hs-1 and directed towards hs-2 are handled by rt-1
136 # which applies the SRv6 Policies as follows:
138 # i) IPv6 DA=cafe::2, H.Encaps.Red with SID List=fcbb:0:0400:0300:0200:d46::
139 # ii) IPv4 DA=10.0.0.2, H.Encaps.Red with SID List=fcbb:0:0300::,fcff:2::d46
141 # ### i) single SID
143 # The router rt-1 is configured to enforce the given Policy through the SRv6
144 # H.Encaps.Red behavior which avoids the presence of the SRH at all, since it
145 # pushes the single SID directly in the IPv6 DA. Such a SID encodes a whole
146 # C-SID container carrying several C-SIDs (e.g. 0400, 0300, etc).
148 # As the packet reaches the router rt-4, the enabled NEXT-C-SID SRv6 End
149 # behavior (associated with fcbb:0:0400::/48) is triggered. This behavior
150 # analyzes the IPv6 DA and checks whether the Argument of the C-SID container
151 # is zero or not. In this case, the Argument is *NOT* zero and the IPv6 DA is
152 # updated as follows:
154 # +---------------------------------------------------------------+
155 # | Before applying the rt-4 enabled NEXT-C-SID SRv6 End behavior |
156 # +---------------------------------------------------------------+
157 # | +---------- Argument |
158 # | vvvvvvvvvvvvvvvv |
159 # | IPv6 DA fcbb:0:0400:0300:0200:d46:: |
160 # | ^^^^ <-- shifting |
161 # | | |
162 # | Locator-Node Function |
163 # +---------------------------------------------------------------+
164 # | After applying the rt-4 enabled NEXT-C-SID SRv6 End behavior |
165 # +---------------------------------------------------------------+
166 # | +---------- Argument |
167 # | vvvvvvvvvvvv |
168 # | IPv6 DA fcbb:0:0300:0200:d46:: |
169 # | ^^^^ |
170 # | | |
171 # | Locator-Node Function |
172 # +---------------------------------------------------------------+
174 # After having applied the enabled NEXT-C-SID SRv6 End behavior, the packet is
175 # sent to the next node, i.e. rt-3.
177 # The enabled NEXT-C-SID SRv6 End behavior on rt-3 is executed as the packet is
178 # received. This behavior processes the packet and updates the IPv6 DA with
179 # fcbb:0:0200:d46::, since the Argument is *NOT* zero. Then, the packet is sent
180 # to the router rt-2.
182 # The router rt-2 is configured for decapsulating the inner IPv6 packet and,
183 # for this reason, it applies the SRv6 End.DT46 behavior on the received
184 # packet. It is worth noting that the SRv6 End.DT46 behavior does not require
185 # the presence of the SRH: it is fully capable to operate properly on
186 # IPv4/IPv6-in-IPv6 encapsulations.
187 # At the end of the decap operation, the packet is sent to the
188 # host hs-2.
190 # ### ii) double SID
192 # The router rt-1 is configured to enforce the given Policy through the SRv6
193 # H.Encaps.Red. As a result, the first SID fcbb:0:0300:: is stored into the
194 # IPv6 DA, while the SRH pushed into the packet is made of only one SID, i.e.
195 # fcff:2::d46. Hence, the packet sent by hs-1 to hs-2 is encapsulated in an
196 # outer IPv6 header plus the SRH.
198 # As the packet reaches the node rt-3, the router applies the enabled NEXT-C-SID
199 # SRv6 End behavior.
201 # +---------------------------------------------------------------+
202 # | Before applying the rt-3 enabled NEXT-C-SID SRv6 End behavior |
203 # +---------------------------------------------------------------+
204 # | +---------- Argument |
205 # | vvvv (Argument is all filled with zeros) |
206 # | IPv6 DA fcbb:0:0300:: |
207 # | ^^^^ |
208 # | | |
209 # | Locator-Node Function |
210 # +---------------------------------------------------------------+
211 # | After applying the rt-3 enabled NEXT-C-SID SRv6 End behavior |
212 # +---------------------------------------------------------------+
213 # | |
214 # | IPv6 DA fcff:2::d46 |
215 # | ^^^^^^^^^^^ |
216 # | | |
217 # | SID copied from the SID List contained in the SRH |
218 # +---------------------------------------------------------------+
220 # Since the Argument of the C-SID container is zero, the behavior can not
221 # update the Locator-Node function with the next C-SID carried in the Argument
222 # itself. Thus, the enabled NEXT-C-SID SRv6 End behavior operates as the
223 # traditional End behavior: it updates the IPv6 DA by copying the next
224 # available SID in the SID List carried by the SRH. After that, the packet is
225 # sent to the node rt-2.
227 # Once the packet is received by rt-2, the router decapsulates the inner IPv6
228 # packet using the SRv6 End.DT46 behavior (associated with the SID fcff:2::d46)
229 # and sends it to the host hs-2.
231 # Traffic from hs-2 to hs-1
232 # -------------------------
234 # Packets generated from hs-2 and directed towards hs-1 are handled by rt-2
235 # which applies the SRv6 Policies as follows:
237 # i) IPv6 DA=cafe::1, SID List=fcbb:0:0300:0400:0100:d46::
238 # ii) IPv4 DA=10.0.0.1, SID List=fcbb:0:0300::,fcff:1::d46
240 # For simplicity, such SRv6 Policies were chosen so that, in both use cases (i)
241 # and (ii), the network paths crossed by traffic from hs-2 to hs-1 are the same
242 # as those taken by traffic from hs-1 to hs-2.
243 # In this way, traffic from hs-2 to hs-1 is processed similarly to traffic from
244 # hs-1 to hs-2. So, the traffic processing scheme turns out to be the same as
245 # that adopted in the use cases already examined (of course, it is necessary to
246 # consider the different SIDs/C-SIDs).
248 # Kselftest framework requirement - SKIP code is 4.
249 readonly ksft_skip=4
251 readonly RDMSUFF="$(mktemp -u XXXXXXXX)"
252 readonly DUMMY_DEVNAME="dum0"
253 readonly VRF_TID=100
254 readonly VRF_DEVNAME="vrf-${VRF_TID}"
255 readonly RT2HS_DEVNAME="veth-t${VRF_TID}"
256 readonly LOCALSID_TABLE_ID=90
257 readonly IPv6_RT_NETWORK=fcf0:0
258 readonly IPv6_HS_NETWORK=cafe
259 readonly IPv4_HS_NETWORK=10.0.0
260 readonly VPN_LOCATOR_SERVICE=fcff
261 readonly DT46_FUNC=0d46
262 readonly HEADEND_ENCAP="encap.red"
264 # do not add ':' as separator
265 readonly LCBLOCK_ADDR=fcbb0000
266 readonly LCBLOCK_BLEN=32
267 # do not add ':' as separator
268 readonly LCNODEFUNC_FMT="0%d00"
269 readonly LCNODEFUNC_BLEN=16
271 readonly LCBLOCK_NODEFUNC_BLEN=$((LCBLOCK_BLEN + LCNODEFUNC_BLEN))
273 readonly CSID_CNTR_PREFIX="dead:beaf::/32"
274 # ID of the router used for testing the C-SID container cfgs
275 readonly CSID_CNTR_RT_ID_TEST=1
276 # Routing table used for testing the C-SID container cfgs
277 readonly CSID_CNTR_RT_TABLE=91
279 # C-SID container configurations to be tested
281 # An entry of the array is defined as "a,b,c" where:
282 # - 'a' and 'b' elements represent respectively the Locator-Block length
283 # (lblen) in bits and the Locator-Node Function length (nflen) in bits.
284 # 'a' and 'b' can be set to default values using the placeholder "d" which
285 # indicates the default kernel values (32 for lblen and 16 for nflen);
286 # otherwise, any numeric value is accepted;
287 # - 'c' indicates whether the C-SID configuration provided by the values 'a'
288 # and 'b' should be considered valid ("y") or invalid ("n").
289 declare -ra CSID_CONTAINER_CFGS=(
290 "d,d,y"
291 "d,16,y"
292 "16,d,y"
293 "16,32,y"
294 "32,16,y"
295 "48,8,y"
296 "8,48,y"
297 "d,0,n"
298 "0,d,n"
299 "32,0,n"
300 "0,32,n"
301 "17,d,n"
302 "d,17,n"
303 "120,16,n"
304 "16,120,n"
305 "0,128,n"
306 "128,0,n"
307 "130,0,n"
308 "0,130,n"
309 "0,0,n"
312 PING_TIMEOUT_SEC=4
313 PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
315 # IDs of routers and hosts are initialized during the setup of the testing
316 # network
317 ROUTERS=''
318 HOSTS=''
320 SETUP_ERR=1
322 ret=${ksft_skip}
323 nsuccess=0
324 nfail=0
326 log_test()
328 local rc="$1"
329 local expected="$2"
330 local msg="$3"
332 if [ "${rc}" -eq "${expected}" ]; then
333 nsuccess=$((nsuccess+1))
334 printf "\n TEST: %-60s [ OK ]\n" "${msg}"
335 else
336 ret=1
337 nfail=$((nfail+1))
338 printf "\n TEST: %-60s [FAIL]\n" "${msg}"
339 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
340 echo
341 echo "hit enter to continue, 'q' to quit"
342 read a
343 [ "$a" = "q" ] && exit 1
348 print_log_test_results()
350 printf "\nTests passed: %3d\n" "${nsuccess}"
351 printf "Tests failed: %3d\n" "${nfail}"
353 # when a test fails, the value of 'ret' is set to 1 (error code).
354 # Conversely, when all tests are passed successfully, the 'ret' value
355 # is set to 0 (success code).
356 if [ "${ret}" -ne 1 ]; then
357 ret=0
361 log_section()
363 echo
364 echo "################################################################################"
365 echo "TEST SECTION: $*"
366 echo "################################################################################"
369 test_command_or_ksft_skip()
371 local cmd="$1"
373 if [ ! -x "$(command -v "${cmd}")" ]; then
374 echo "SKIP: Could not run test without \"${cmd}\" tool";
375 exit "${ksft_skip}"
379 get_nodename()
381 local name="$1"
383 echo "${name}-${RDMSUFF}"
386 get_rtname()
388 local rtid="$1"
390 get_nodename "rt-${rtid}"
393 get_hsname()
395 local hsid="$1"
397 get_nodename "hs-${hsid}"
400 __create_namespace()
402 local name="$1"
404 ip netns add "${name}"
407 create_router()
409 local rtid="$1"
410 local nsname
412 nsname="$(get_rtname "${rtid}")"
414 __create_namespace "${nsname}"
417 create_host()
419 local hsid="$1"
420 local nsname
422 nsname="$(get_hsname "${hsid}")"
424 __create_namespace "${nsname}"
427 cleanup()
429 local nsname
430 local i
432 # destroy routers
433 for i in ${ROUTERS}; do
434 nsname="$(get_rtname "${i}")"
436 ip netns del "${nsname}" &>/dev/null || true
437 done
439 # destroy hosts
440 for i in ${HOSTS}; do
441 nsname="$(get_hsname "${i}")"
443 ip netns del "${nsname}" &>/dev/null || true
444 done
446 # check whether the setup phase was completed successfully or not. In
447 # case of an error during the setup phase of the testing environment,
448 # the selftest is considered as "skipped".
449 if [ "${SETUP_ERR}" -ne 0 ]; then
450 echo "SKIP: Setting up the testing environment failed"
451 exit "${ksft_skip}"
454 exit "${ret}"
457 add_link_rt_pairs()
459 local rt="$1"
460 local rt_neighs="$2"
461 local neigh
462 local nsname
463 local neigh_nsname
465 nsname="$(get_rtname "${rt}")"
467 for neigh in ${rt_neighs}; do
468 neigh_nsname="$(get_rtname "${neigh}")"
470 ip link add "veth-rt-${rt}-${neigh}" netns "${nsname}" \
471 type veth peer name "veth-rt-${neigh}-${rt}" \
472 netns "${neigh_nsname}"
473 done
476 get_network_prefix()
478 local rt="$1"
479 local neigh="$2"
480 local p="${rt}"
481 local q="${neigh}"
483 if [ "${p}" -gt "${q}" ]; then
484 p="${q}"; q="${rt}"
487 echo "${IPv6_RT_NETWORK}:${p}:${q}"
490 # Setup the basic networking for the routers
491 setup_rt_networking()
493 local rt="$1"
494 local rt_neighs="$2"
495 local nsname
496 local net_prefix
497 local devname
498 local neigh
500 nsname="$(get_rtname "${rt}")"
502 for neigh in ${rt_neighs}; do
503 devname="veth-rt-${rt}-${neigh}"
505 net_prefix="$(get_network_prefix "${rt}" "${neigh}")"
507 ip -netns "${nsname}" addr \
508 add "${net_prefix}::${rt}/64" dev "${devname}" nodad
510 ip -netns "${nsname}" link set "${devname}" up
511 done
513 ip -netns "${nsname}" link add "${DUMMY_DEVNAME}" type dummy
515 ip -netns "${nsname}" link set "${DUMMY_DEVNAME}" up
516 ip -netns "${nsname}" link set lo up
518 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0
519 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0
520 ip netns exec "${nsname}" sysctl -wq net.ipv6.conf.all.forwarding=1
522 ip netns exec "${nsname}" sysctl -wq net.ipv4.conf.all.rp_filter=0
523 ip netns exec "${nsname}" sysctl -wq net.ipv4.conf.default.rp_filter=0
524 ip netns exec "${nsname}" sysctl -wq net.ipv4.ip_forward=1
527 # build an ipv6 prefix/address based on the input string
528 # Note that the input string does not contain ':' and '::' which are considered
529 # to be implicit.
530 # e.g.:
531 # - input: fbcc00000400300
532 # - output: fbcc:0000:0400:0300:0000:0000:0000:0000
533 # ^^^^^^^^^^^^^^^^^^^
534 # fill the address with 0s
535 build_ipv6_addr()
537 local addr="$1"
538 local out=""
539 local strlen="${#addr}"
540 local padn
541 local i
543 # add ":" every 4 digits (16 bits)
544 for (( i = 0; i < strlen; i++ )); do
545 if (( i > 0 && i < 32 && (i % 4) == 0 )); then
546 out="${out}:"
549 out="${out}${addr:$i:1}"
550 done
552 # fill the remaining bits of the address with 0s
553 padn=$((32 - strlen))
554 for (( i = padn; i > 0; i-- )); do
555 if (( i > 0 && i < 32 && (i % 4) == 0 )); then
556 out="${out}:"
559 out="${out}0"
560 done
562 printf "${out}"
565 build_csid()
567 local nodeid="$1"
569 printf "${LCNODEFUNC_FMT}" "${nodeid}"
572 build_lcnode_func_prefix()
574 local nodeid="$1"
575 local lcnodefunc
576 local prefix
577 local out
579 lcnodefunc="$(build_csid "${nodeid}")"
580 prefix="$(build_ipv6_addr "${LCBLOCK_ADDR}${lcnodefunc}")"
582 out="${prefix}/${LCBLOCK_NODEFUNC_BLEN}"
584 echo "${out}"
587 # Setup local SIDs for an SRv6 router
588 setup_rt_local_sids()
590 local rt="$1"
591 local rt_neighs="$2"
592 local net_prefix
593 local devname
594 local nsname
595 local neigh
596 local lcnode_func_prefix
597 local lcblock_prefix
599 nsname="$(get_rtname "${rt}")"
601 for neigh in ${rt_neighs}; do
602 devname="veth-rt-${rt}-${neigh}"
604 net_prefix="$(get_network_prefix "${rt}" "${neigh}")"
606 # set underlay network routes for SIDs reachability
607 ip -netns "${nsname}" -6 route \
608 add "${VPN_LOCATOR_SERVICE}:${neigh}::/32" \
609 table "${LOCALSID_TABLE_ID}" \
610 via "${net_prefix}::${neigh}" dev "${devname}"
612 # set the underlay network for C-SIDs reachability
613 lcnode_func_prefix="$(build_lcnode_func_prefix "${neigh}")"
615 ip -netns "${nsname}" -6 route \
616 add "${lcnode_func_prefix}" \
617 table "${LOCALSID_TABLE_ID}" \
618 via "${net_prefix}::${neigh}" dev "${devname}"
619 done
621 lcnode_func_prefix="$(build_lcnode_func_prefix "${rt}")"
623 # enabled NEXT-C-SID SRv6 End behavior (note that "dev" is the dummy
624 # dum0 device chosen for the sake of simplicity).
625 ip -netns "${nsname}" -6 route \
626 add "${lcnode_func_prefix}" \
627 table "${LOCALSID_TABLE_ID}" \
628 encap seg6local action End flavors next-csid \
629 lblen "${LCBLOCK_BLEN}" nflen "${LCNODEFUNC_BLEN}" \
630 dev "${DUMMY_DEVNAME}"
632 # all SIDs for VPNs start with a common locator. Routes and SRv6
633 # Endpoint behavior instaces are grouped together in the 'localsid'
634 # table.
635 ip -netns "${nsname}" -6 rule \
636 add to "${VPN_LOCATOR_SERVICE}::/16" \
637 lookup "${LOCALSID_TABLE_ID}" prio 999
639 # common locator block for NEXT-C-SIDS compression mechanism.
640 lcblock_prefix="$(build_ipv6_addr "${LCBLOCK_ADDR}")"
641 ip -netns "${nsname}" -6 rule \
642 add to "${lcblock_prefix}/${LCBLOCK_BLEN}" \
643 lookup "${LOCALSID_TABLE_ID}" prio 999
646 # build and install the SRv6 policy into the ingress SRv6 router as well as the
647 # decap SID in the egress one.
648 # args:
649 # $1 - src host (evaluate automatically the ingress router)
650 # $2 - dst host (evaluate automatically the egress router)
651 # $3 - SRv6 routers configured for steering traffic (End behaviors)
652 # $4 - single SID or double SID
653 # $5 - traffic type (IPv6 or IPv4)
654 __setup_l3vpn()
656 local src="$1"
657 local dst="$2"
658 local end_rts="$3"
659 local mode="$4"
660 local traffic="$5"
661 local nsname
662 local policy
663 local container
664 local decapsid
665 local lcnfunc
666 local dt
667 local n
668 local rtsrc_nsname
669 local rtdst_nsname
671 rtsrc_nsname="$(get_rtname "${src}")"
672 rtdst_nsname="$(get_rtname "${dst}")"
674 container="${LCBLOCK_ADDR}"
676 # build first SID (C-SID container)
677 for n in ${end_rts}; do
678 lcnfunc="$(build_csid "${n}")"
680 container="${container}${lcnfunc}"
681 done
683 if [ "${mode}" -eq 1 ]; then
684 # single SID policy
685 dt="$(build_csid "${dst}")${DT46_FUNC}"
686 container="${container}${dt}"
687 # build the full ipv6 address for the container
688 policy="$(build_ipv6_addr "${container}")"
690 # build the decap SID used in the decap node
691 container="${LCBLOCK_ADDR}${dt}"
692 decapsid="$(build_ipv6_addr "${container}")"
693 else
694 # double SID policy
695 decapsid="${VPN_LOCATOR_SERVICE}:${dst}::${DT46_FUNC}"
697 policy="$(build_ipv6_addr "${container}"),${decapsid}"
700 # apply encap policy
701 if [ "${traffic}" -eq 6 ]; then
702 ip -netns "${rtsrc_nsname}" -6 route \
703 add "${IPv6_HS_NETWORK}::${dst}" vrf "${VRF_DEVNAME}" \
704 encap seg6 mode "${HEADEND_ENCAP}" segs "${policy}" \
705 dev "${VRF_DEVNAME}"
707 ip -netns "${rtsrc_nsname}" -6 neigh \
708 add proxy "${IPv6_HS_NETWORK}::${dst}" \
709 dev "${RT2HS_DEVNAME}"
710 else
711 # "dev" must be different from the one where the packet is
712 # received, otherwise the proxy arp does not work.
713 ip -netns "${rtsrc_nsname}" -4 route \
714 add "${IPv4_HS_NETWORK}.${dst}" vrf "${VRF_DEVNAME}" \
715 encap seg6 mode "${HEADEND_ENCAP}" segs "${policy}" \
716 dev "${VRF_DEVNAME}"
719 # apply decap
720 # Local End.DT46 behavior (decap)
721 ip -netns "${rtdst_nsname}" -6 route \
722 add "${decapsid}" \
723 table "${LOCALSID_TABLE_ID}" \
724 encap seg6local action End.DT46 vrftable "${VRF_TID}" \
725 dev "${VRF_DEVNAME}"
728 # see __setup_l3vpn()
729 setup_ipv4_vpn_2sids()
731 __setup_l3vpn "$1" "$2" "$3" 2 4
734 # see __setup_l3vpn()
735 setup_ipv6_vpn_1sid()
737 __setup_l3vpn "$1" "$2" "$3" 1 6
740 setup_hs()
742 local hs="$1"
743 local rt="$2"
744 local hsname
745 local rtname
747 hsname="$(get_hsname "${hs}")"
748 rtname="$(get_rtname "${rt}")"
750 ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.all.accept_dad=0
751 ip netns exec "${hsname}" sysctl -wq net.ipv6.conf.default.accept_dad=0
753 ip -netns "${hsname}" link add veth0 type veth \
754 peer name "${RT2HS_DEVNAME}" netns "${rtname}"
756 ip -netns "${hsname}" addr \
757 add "${IPv6_HS_NETWORK}::${hs}/64" dev veth0 nodad
758 ip -netns "${hsname}" addr add "${IPv4_HS_NETWORK}.${hs}/24" dev veth0
760 ip -netns "${hsname}" link set veth0 up
761 ip -netns "${hsname}" link set lo up
763 # configure the VRF on the router which is directly connected to the
764 # source host.
765 ip -netns "${rtname}" link \
766 add "${VRF_DEVNAME}" type vrf table "${VRF_TID}"
767 ip -netns "${rtname}" link set "${VRF_DEVNAME}" up
769 # enslave the veth interface connecting the router with the host to the
770 # VRF in the access router
771 ip -netns "${rtname}" link \
772 set "${RT2HS_DEVNAME}" master "${VRF_DEVNAME}"
774 # set default routes to unreachable for both ipv6 and ipv4
775 ip -netns "${rtname}" -6 route \
776 add unreachable default metric 4278198272 \
777 vrf "${VRF_DEVNAME}"
778 ip -netns "${rtname}" -4 route \
779 add unreachable default metric 4278198272 \
780 vrf "${VRF_DEVNAME}"
782 ip -netns "${rtname}" addr \
783 add "${IPv6_HS_NETWORK}::254/64" dev "${RT2HS_DEVNAME}" nodad
784 ip -netns "${rtname}" addr \
785 add "${IPv4_HS_NETWORK}.254/24" dev "${RT2HS_DEVNAME}"
787 ip -netns "${rtname}" link set "${RT2HS_DEVNAME}" up
789 ip netns exec "${rtname}" \
790 sysctl -wq net.ipv6.conf."${RT2HS_DEVNAME}".proxy_ndp=1
791 ip netns exec "${rtname}" \
792 sysctl -wq net.ipv4.conf."${RT2HS_DEVNAME}".proxy_arp=1
794 # disable the rp_filter otherwise the kernel gets confused about how
795 # to route decap ipv4 packets.
796 ip netns exec "${rtname}" \
797 sysctl -wq net.ipv4.conf."${RT2HS_DEVNAME}".rp_filter=0
799 ip netns exec "${rtname}" sh -c "echo 1 > /proc/sys/net/vrf/strict_mode"
802 setup()
804 local i
806 # create routers
807 ROUTERS="1 2 3 4"; readonly ROUTERS
808 for i in ${ROUTERS}; do
809 create_router "${i}"
810 done
812 # create hosts
813 HOSTS="1 2"; readonly HOSTS
814 for i in ${HOSTS}; do
815 create_host "${i}"
816 done
818 # set up the links for connecting routers
819 add_link_rt_pairs 1 "2 3 4"
820 add_link_rt_pairs 2 "3 4"
821 add_link_rt_pairs 3 "4"
823 # set up the basic connectivity of routers and routes required for
824 # reachability of SIDs.
825 setup_rt_networking 1 "2 3 4"
826 setup_rt_networking 2 "1 3 4"
827 setup_rt_networking 3 "1 2 4"
828 setup_rt_networking 4 "1 2 3"
830 # set up the hosts connected to routers
831 setup_hs 1 1
832 setup_hs 2 2
834 # set up default SRv6 Endpoints (i.e. SRv6 End and SRv6 End.DT46)
835 setup_rt_local_sids 1 "2 3 4"
836 setup_rt_local_sids 2 "1 3 4"
837 setup_rt_local_sids 3 "1 2 4"
838 setup_rt_local_sids 4 "1 2 3"
840 # set up SRv6 Policies
842 # create an IPv6 VPN between hosts hs-1 and hs-2.
844 # Direction hs-1 -> hs-2
845 # - rt-1 encap (H.Encaps.Red)
846 # - rt-4 SRv6 End behavior (NEXT-C-SID flavor)
847 # - rt-3 SRv6 End behavior (NEXT-C-SID flavor)
848 # - rt-2 SRv6 End.DT46 behavior
849 setup_ipv6_vpn_1sid 1 2 "4 3"
851 # Direction hs2 -> hs-1
852 # - rt-2 encap (H.Encaps.Red)
853 # - rt-3 SRv6 End behavior (NEXT-C-SID flavor)
854 # - rt-4 SRv6 End behavior (NEXT-C-SID flavor)
855 # - rt-1 SRv6 End.DT46 behavior
856 setup_ipv6_vpn_1sid 2 1 "3 4"
858 # create an IPv4 VPN between hosts hs-1 and hs-2
860 # Direction hs-1 -> hs-2
861 # - rt-1 encap (H.Encaps.Red)
862 # - rt-3 SRv6 End behavior (NEXT-C-SID flavor)
863 # - rt-2 SRv6 End.DT46 behavior
864 setup_ipv4_vpn_2sids 1 2 "3"
866 # Direction hs-2 -> hs-1
867 # - rt-2 encap (H.Encaps.Red)
868 # - rt-3 SRv6 End behavior (NEXT-C-SID flavor)
869 # - rt-1 SRv6 End.DT46 behavior
870 setup_ipv4_vpn_2sids 2 1 "3"
872 # testing environment was set up successfully
873 SETUP_ERR=0
876 check_rt_connectivity()
878 local rtsrc="$1"
879 local rtdst="$2"
880 local prefix
881 local rtsrc_nsname
883 rtsrc_nsname="$(get_rtname "${rtsrc}")"
885 prefix="$(get_network_prefix "${rtsrc}" "${rtdst}")"
887 ip netns exec "${rtsrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \
888 "${prefix}::${rtdst}" >/dev/null 2>&1
891 check_and_log_rt_connectivity()
893 local rtsrc="$1"
894 local rtdst="$2"
896 check_rt_connectivity "${rtsrc}" "${rtdst}"
897 log_test $? 0 "Routers connectivity: rt-${rtsrc} -> rt-${rtdst}"
900 check_hs_ipv6_connectivity()
902 local hssrc="$1"
903 local hsdst="$2"
904 local hssrc_nsname
906 hssrc_nsname="$(get_hsname "${hssrc}")"
908 ip netns exec "${hssrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \
909 "${IPv6_HS_NETWORK}::${hsdst}" >/dev/null 2>&1
912 check_hs_ipv4_connectivity()
914 local hssrc="$1"
915 local hsdst="$2"
916 local hssrc_nsname
918 hssrc_nsname="$(get_hsname "${hssrc}")"
920 ip netns exec "${hssrc_nsname}" ping -c 1 -W "${PING_TIMEOUT_SEC}" \
921 "${IPv4_HS_NETWORK}.${hsdst}" >/dev/null 2>&1
924 check_and_log_hs2gw_connectivity()
926 local hssrc="$1"
928 check_hs_ipv6_connectivity "${hssrc}" 254
929 log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> gw"
931 check_hs_ipv4_connectivity "${hssrc}" 254
932 log_test $? 0 "IPv4 Hosts connectivity: hs-${hssrc} -> gw"
935 check_and_log_hs_ipv6_connectivity()
937 local hssrc="$1"
938 local hsdst="$2"
940 check_hs_ipv6_connectivity "${hssrc}" "${hsdst}"
941 log_test $? 0 "IPv6 Hosts connectivity: hs-${hssrc} -> hs-${hsdst}"
944 check_and_log_hs_ipv4_connectivity()
946 local hssrc="$1"
947 local hsdst="$2"
949 check_hs_ipv4_connectivity "${hssrc}" "${hsdst}"
950 log_test $? 0 "IPv4 Hosts connectivity: hs-${hssrc} -> hs-${hsdst}"
953 router_tests()
955 local i
956 local j
958 log_section "IPv6 routers connectivity test"
960 for i in ${ROUTERS}; do
961 for j in ${ROUTERS}; do
962 if [ "${i}" -eq "${j}" ]; then
963 continue
966 check_and_log_rt_connectivity "${i}" "${j}"
967 done
968 done
971 host2gateway_tests()
973 local hs
975 log_section "IPv4/IPv6 connectivity test among hosts and gateways"
977 for hs in ${HOSTS}; do
978 check_and_log_hs2gw_connectivity "${hs}"
979 done
982 host_vpn_tests()
984 log_section "SRv6 VPN connectivity test hosts (h1 <-> h2, IPv6)"
986 check_and_log_hs_ipv6_connectivity 1 2
987 check_and_log_hs_ipv6_connectivity 2 1
989 log_section "SRv6 VPN connectivity test hosts (h1 <-> h2, IPv4)"
991 check_and_log_hs_ipv4_connectivity 1 2
992 check_and_log_hs_ipv4_connectivity 2 1
995 __nextcsid_end_behavior_test()
997 local nsname="$1"
998 local cmd="$2"
999 local blen="$3"
1000 local flen="$4"
1001 local layout=""
1003 if [ "${blen}" != "d" ]; then
1004 layout="${layout} lblen ${blen}"
1007 if [ "${flen}" != "d" ]; then
1008 layout="${layout} nflen ${flen}"
1011 ip -netns "${nsname}" -6 route \
1012 "${cmd}" "${CSID_CNTR_PREFIX}" \
1013 table "${CSID_CNTR_RT_TABLE}" \
1014 encap seg6local action End flavors next-csid ${layout} \
1015 dev "${DUMMY_DEVNAME}" &>/dev/null
1017 return "$?"
1020 rt_x_nextcsid_end_behavior_test()
1022 local rt="$1"
1023 local blen="$2"
1024 local flen="$3"
1025 local nsname
1026 local ret
1028 nsname="$(get_rtname "${rt}")"
1030 __nextcsid_end_behavior_test "${nsname}" "add" "${blen}" "${flen}"
1031 ret="$?"
1032 __nextcsid_end_behavior_test "${nsname}" "del" "${blen}" "${flen}"
1034 return "${ret}"
1037 __parse_csid_container_cfg()
1039 local cfg="$1"
1040 local index="$2"
1041 local out
1043 echo "${cfg}" | cut -d',' -f"${index}"
1046 csid_container_cfg_tests()
1048 local valid
1049 local blen
1050 local flen
1051 local cfg
1052 local ret
1054 log_section "C-SID Container config tests (legend: d='kernel default')"
1056 for cfg in "${CSID_CONTAINER_CFGS[@]}"; do
1057 blen="$(__parse_csid_container_cfg "${cfg}" 1)"
1058 flen="$(__parse_csid_container_cfg "${cfg}" 2)"
1059 valid="$(__parse_csid_container_cfg "${cfg}" 3)"
1061 rt_x_nextcsid_end_behavior_test \
1062 "${CSID_CNTR_RT_ID_TEST}" \
1063 "${blen}" \
1064 "${flen}"
1065 ret="$?"
1067 if [ "${valid}" == "y" ]; then
1068 log_test "${ret}" 0 \
1069 "Accept valid C-SID container cfg (lblen=${blen}, nflen=${flen})"
1070 else
1071 log_test "${ret}" 2 \
1072 "Reject invalid C-SID container cfg (lblen=${blen}, nflen=${flen})"
1074 done
1077 test_iproute2_supp_or_ksft_skip()
1079 if ! ip route help 2>&1 | grep -qo "next-csid"; then
1080 echo "SKIP: Missing SRv6 NEXT-C-SID flavor support in iproute2"
1081 exit "${ksft_skip}"
1085 test_dummy_dev_or_ksft_skip()
1087 local test_netns
1089 test_netns="dummy-$(mktemp -u XXXXXXXX)"
1091 if ! ip netns add "${test_netns}"; then
1092 echo "SKIP: Cannot set up netns for testing dummy dev support"
1093 exit "${ksft_skip}"
1096 modprobe dummy &>/dev/null || true
1097 if ! ip -netns "${test_netns}" link \
1098 add "${DUMMY_DEVNAME}" type dummy; then
1099 echo "SKIP: dummy dev not supported"
1101 ip netns del "${test_netns}"
1102 exit "${ksft_skip}"
1105 ip netns del "${test_netns}"
1108 test_vrf_or_ksft_skip()
1110 modprobe vrf &>/dev/null || true
1111 if [ ! -e /proc/sys/net/vrf/strict_mode ]; then
1112 echo "SKIP: vrf sysctl does not exist"
1113 exit "${ksft_skip}"
1117 if [ "$(id -u)" -ne 0 ]; then
1118 echo "SKIP: Need root privileges"
1119 exit "${ksft_skip}"
1122 # required programs to carry out this selftest
1123 test_command_or_ksft_skip ip
1124 test_command_or_ksft_skip ping
1125 test_command_or_ksft_skip sysctl
1126 test_command_or_ksft_skip grep
1127 test_command_or_ksft_skip cut
1129 test_iproute2_supp_or_ksft_skip
1130 test_dummy_dev_or_ksft_skip
1131 test_vrf_or_ksft_skip
1133 set -e
1134 trap cleanup EXIT
1136 setup
1137 set +e
1139 csid_container_cfg_tests
1141 router_tests
1142 host2gateway_tests
1143 host_vpn_tests
1145 print_log_test_results