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
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
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
42 # +--------+ +--------+
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 |
53 # +---+----+ +----+---+
55 # | fcf0:0:1:3::/64 . |
58 # fcf0:0:1:4::/64 | . | fcf0:0:2:3::/64
61 # | fcf0:0:2:4::/64 . |
63 # +---+----+ +----+---+
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
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 |
162 # | Locator-Node Function |
163 # +---------------------------------------------------------------+
164 # | After applying the rt-4 enabled NEXT-C-SID SRv6 End behavior |
165 # +---------------------------------------------------------------+
166 # | +---------- Argument |
168 # | IPv6 DA fcbb:0:0300:0200:d46:: |
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
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
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:: |
209 # | Locator-Node Function |
210 # +---------------------------------------------------------------+
211 # | After applying the rt-3 enabled NEXT-C-SID SRv6 End behavior |
212 # +---------------------------------------------------------------+
214 # | IPv6 DA fcff:2::d46 |
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.
251 readonly RDMSUFF
="$(mktemp -u XXXXXXXX)"
252 readonly DUMMY_DEVNAME
="dum0"
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
=(
313 PAUSE_ON_FAIL
=${PAUSE_ON_FAIL:=no}
315 # IDs of routers and hosts are initialized during the setup of the testing
332 if [ "${rc}" -eq "${expected}" ]; then
333 nsuccess
=$
((nsuccess
+1))
334 printf "\n TEST: %-60s [ OK ]\n" "${msg}"
338 printf "\n TEST: %-60s [FAIL]\n" "${msg}"
339 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
341 echo "hit enter to continue, 'q' to quit"
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
364 echo "################################################################################"
365 echo "TEST SECTION: $*"
366 echo "################################################################################"
369 test_command_or_ksft_skip
()
373 if [ ! -x "$(command -v "${cmd}")" ]; then
374 echo "SKIP: Could not run test without \"${cmd}\" tool";
383 echo "${name}-${RDMSUFF}"
390 get_nodename
"rt-${rtid}"
397 get_nodename
"hs-${hsid}"
404 ip netns add
"${name}"
412 nsname
="$(get_rtname "${rtid}")"
414 __create_namespace
"${nsname}"
422 nsname
="$(get_hsname "${hsid}")"
424 __create_namespace
"${nsname}"
433 for i
in ${ROUTERS}; do
434 nsname
="$(get_rtname "${i}")"
436 ip netns del
"${nsname}" &>/dev
/null || true
440 for i
in ${HOSTS}; do
441 nsname
="$(get_hsname "${i}")"
443 ip netns del
"${nsname}" &>/dev
/null || true
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"
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}"
483 if [ "${p}" -gt "${q}" ]; then
487 echo "${IPv6_RT_NETWORK}:${p}:${q}"
490 # Setup the basic networking for the routers
491 setup_rt_networking
()
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
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
531 # - input: fbcc00000400300
532 # - output: fbcc:0000:0400:0300:0000:0000:0000:0000
533 # ^^^^^^^^^^^^^^^^^^^
534 # fill the address with 0s
539 local strlen
="${#addr}"
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
549 out
="${out}${addr:$i:1}"
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
569 printf "${LCNODEFUNC_FMT}" "${nodeid}"
572 build_lcnode_func_prefix
()
579 lcnodefunc
="$(build_csid "${nodeid}")"
580 prefix
="$(build_ipv6_addr "${LCBLOCK_ADDR}${lcnodefunc}")"
582 out
="${prefix}/${LCBLOCK_NODEFUNC_BLEN}"
587 # Setup local SIDs for an SRv6 router
588 setup_rt_local_sids
()
596 local lcnode_func_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}"
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'
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.
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)
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}"
683 if [ "${mode}" -eq 1 ]; then
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}")"
695 decapsid
="${VPN_LOCATOR_SERVICE}:${dst}::${DT46_FUNC}"
697 policy
="$(build_ipv6_addr "${container}"),${decapsid}"
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}" \
707 ip
-netns "${rtsrc_nsname}" -6 neigh \
708 add proxy
"${IPv6_HS_NETWORK}::${dst}" \
709 dev
"${RT2HS_DEVNAME}"
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}" \
720 # Local End.DT46 behavior (decap)
721 ip
-netns "${rtdst_nsname}" -6 route \
723 table
"${LOCALSID_TABLE_ID}" \
724 encap seg6local action End.DT46 vrftable
"${VRF_TID}" \
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
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
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 \
778 ip
-netns "${rtname}" -4 route \
779 add unreachable default metric
4278198272 \
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"
807 ROUTERS
="1 2 3 4"; readonly ROUTERS
808 for i
in ${ROUTERS}; do
813 HOSTS
="1 2"; readonly HOSTS
814 for i
in ${HOSTS}; do
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
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
876 check_rt_connectivity
()
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
()
896 check_rt_connectivity
"${rtsrc}" "${rtdst}"
897 log_test $?
0 "Routers connectivity: rt-${rtsrc} -> rt-${rtdst}"
900 check_hs_ipv6_connectivity
()
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
()
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
()
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
()
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
()
949 check_hs_ipv4_connectivity
"${hssrc}" "${hsdst}"
950 log_test $?
0 "IPv4 Hosts connectivity: hs-${hssrc} -> hs-${hsdst}"
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
966 check_and_log_rt_connectivity
"${i}" "${j}"
975 log_section
"IPv4/IPv6 connectivity test among hosts and gateways"
977 for hs
in ${HOSTS}; do
978 check_and_log_hs2gw_connectivity
"${hs}"
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
()
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
1020 rt_x_nextcsid_end_behavior_test
()
1028 nsname
="$(get_rtname "${rt}")"
1030 __nextcsid_end_behavior_test
"${nsname}" "add" "${blen}" "${flen}"
1032 __nextcsid_end_behavior_test
"${nsname}" "del" "${blen}" "${flen}"
1037 __parse_csid_container_cfg
()
1043 echo "${cfg}" | cut
-d',' -f"${index}"
1046 csid_container_cfg_tests
()
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}" \
1067 if [ "${valid}" == "y" ]; then
1068 log_test
"${ret}" 0 \
1069 "Accept valid C-SID container cfg (lblen=${blen}, nflen=${flen})"
1071 log_test
"${ret}" 2 \
1072 "Reject invalid C-SID container cfg (lblen=${blen}, nflen=${flen})"
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"
1085 test_dummy_dev_or_ksft_skip
()
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"
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}"
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"
1117 if [ "$(id -u)" -ne 0 ]; then
1118 echo "SKIP: Need root privileges"
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
1139 csid_container_cfg_tests
1145 print_log_test_results