Skip to content

Commit 72e50ef

Browse files
Jianguo Wuummakynes
authored andcommitted
selftests: add selftest for the SRv6 End.DX4 behavior with netfilter
this selftest is designed for evaluating the SRv6 End.DX4 behavior used with netfilter(rpfilter), in this example, for implementing IPv4 L3 VPN use cases. Signed-off-by: Jianguo Wu <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent a2225e0 commit 72e50ef

File tree

3 files changed

+337
-0
lines changed

3 files changed

+337
-0
lines changed

tools/testing/selftests/net/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ TEST_PROGS += srv6_hl2encap_red_l2vpn_test.sh
4343
TEST_PROGS += srv6_end_next_csid_l3vpn_test.sh
4444
TEST_PROGS += srv6_end_x_next_csid_l3vpn_test.sh
4545
TEST_PROGS += srv6_end_flavors_test.sh
46+
TEST_PROGS += srv6_end_dx4_netfilter_test.sh
4647
TEST_PROGS += vrf_strict_mode_test.sh
4748
TEST_PROGS += arp_ndisc_evict_nocarrier.sh
4849
TEST_PROGS += ndisc_unsolicited_na_test.sh

tools/testing/selftests/net/config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,4 @@ CONFIG_NETFILTER_XT_MATCH_POLICY=m
101101
CONFIG_CRYPTO_ARIA=y
102102
CONFIG_XFRM_INTERFACE=m
103103
CONFIG_XFRM_USER=m
104+
CONFIG_IP_NF_MATCH_RPFILTER=m
Lines changed: 335 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,335 @@
1+
#!/bin/bash
2+
# SPDX-License-Identifier: GPL-2.0
3+
#
4+
# author: Jianguo Wu <[email protected]>
5+
#
6+
# Mostly copied from tools/testing/selftests/net/srv6_end_dt4_l3vpn_test.sh.
7+
#
8+
# This script is designed for testing the support of netfilter hooks for
9+
# SRv6 End.DX4 behavior.
10+
#
11+
# Hereafter a network diagram is shown, where one tenants (named 100) offer
12+
# IPv4 L3 VPN services allowing hosts to communicate with each other across
13+
# an IPv6 network.
14+
#
15+
# Routers rt-1 and rt-2 implement IPv4 L3 VPN services leveraging the SRv6
16+
# architecture. The key components for such VPNs are: a) SRv6 Encap behavior,
17+
# b) SRv6 End.DX4 behavior.
18+
#
19+
# To explain how an IPv4 L3 VPN based on SRv6 works, let us briefly consider an
20+
# example where, within the same domain of tenant 100, the host hs-1 pings
21+
# the host hs-2.
22+
#
23+
# First of all, L2 reachability of the host hs-2 is taken into account by
24+
# the router rt-1 which acts as an arp proxy.
25+
#
26+
# When the host hs-1 sends an IPv4 packet destined to hs-2, the router rt-1
27+
# receives the packet on the internal veth-t100 interface, rt-1 contains the
28+
# SRv6 Encap route for encapsulating the IPv4 packet in a IPv6 plus the Segment
29+
# Routing Header (SRH) packet. This packet is sent through the (IPv6) core
30+
# network up to the router rt-2 that receives it on veth0 interface.
31+
#
32+
# The rt-2 router uses the 'localsid' routing table to process incoming
33+
# IPv6+SRH packets which belong to the VPN of the tenant 100. For each of these
34+
# packets, the SRv6 End.DX4 behavior removes the outer IPv6+SRH headers and
35+
# routs the packet to the specified nexthop. Afterwards, the packet is sent to
36+
# the host hs-2 through the veth-t100 interface.
37+
#
38+
# The ping response follows the same processing but this time the role of rt-1
39+
# and rt-2 are swapped.
40+
#
41+
# And when net.netfilter.nf_hooks_lwtunnel is set to 1 in rt-1 or rt-2, and a
42+
# rpfilter iptables rule is added, SRv6 packets will go through netfilter PREROUTING
43+
# hooks.
44+
#
45+
#
46+
# +-------------------+ +-------------------+
47+
# | | | |
48+
# | hs-1 netns | | hs-2 netns |
49+
# | | | |
50+
# | +-------------+ | | +-------------+ |
51+
# | | veth0 | | | | veth0 | |
52+
# | | 10.0.0.1/24 | | | | 10.0.0.2/24 | |
53+
# | +-------------+ | | +-------------+ |
54+
# | . | | . |
55+
# +-------------------+ +-------------------+
56+
# . .
57+
# . .
58+
# . .
59+
# +-----------------------------------+ +-----------------------------------+
60+
# | . | | . |
61+
# | +---------------+ | | +---------------- |
62+
# | | veth-t100 | | | | veth-t100 | |
63+
# | | 10.0.0.11/24 | +----------+ | | +----------+ | 10.0.0.22/24 | |
64+
# | +-------+-------+ | route | | | | route | +-------+-------- |
65+
# | | table | | | | table | |
66+
# | +----------+ | | +----------+ |
67+
# | +--------------+ | | +--------------+ |
68+
# | | veth0 | | | | veth0 | |
69+
# | | 2001:11::1/64 |.|...|.| 2001:11::2/64 | |
70+
# | +--------------+ | | +--------------+ |
71+
# | | | |
72+
# | rt-1 netns | | rt-2 netns |
73+
# | | | |
74+
# +-----------------------------------+ +-----------------------------------+
75+
#
76+
# ~~~~~~~~~~~~~~~~~~~~~~~~~
77+
# | Network configuration |
78+
# ~~~~~~~~~~~~~~~~~~~~~~~~~
79+
#
80+
# rt-1: localsid table
81+
# +----------------------------------------------------------------+
82+
# |SID |Action |
83+
# +----------------------------------------------------------------+
84+
# |fc00:21:100::6004|apply SRv6 End.DX4 nh4 10.0.0.1 dev veth-t100 |
85+
# +----------------------------------------------------------------+
86+
#
87+
# rt-1: route table
88+
# +---------------------------------------------------+
89+
# |host |Action |
90+
# +---------------------------------------------------+
91+
# |10.0.0.2 |apply seg6 encap segs fc00:12:100::6004|
92+
# +---------------------------------------------------+
93+
# |10.0.0.0/24|forward to dev veth_t100 |
94+
# +---------------------------------------------------+
95+
#
96+
#
97+
# rt-2: localsid table
98+
# +---------------------------------------------------------------+
99+
# |SID |Action |
100+
# +---------------------------------------------------------------+
101+
# |fc00:12:100::6004|apply SRv6 End.DX4 nh4 10.0.0.2 dev veth-t100|
102+
# +---------------------------------------------------------------+
103+
#
104+
# rt-2: route table
105+
# +---------------------------------------------------+
106+
# |host |Action |
107+
# +---------------------------------------------------+
108+
# |10.0.0.1 |apply seg6 encap segs fc00:21:100::6004|
109+
# +---------------------------------------------------+
110+
# |10.0.0.0/24|forward to dev veth_t100 |
111+
# +---------------------------------------------------+
112+
#
113+
114+
# Kselftest framework requirement - SKIP code is 4.
115+
ksft_skip=4
116+
117+
readonly IPv6_RT_NETWORK=2001:11
118+
readonly IPv4_HS_NETWORK=10.0.0
119+
readonly SID_LOCATOR=fc00
120+
121+
PING_TIMEOUT_SEC=4
122+
123+
ret=0
124+
125+
PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
126+
127+
log_test()
128+
{
129+
local rc=$1
130+
local expected=$2
131+
local msg="$3"
132+
133+
if [ ${rc} -eq ${expected} ]; then
134+
nsuccess=$((nsuccess+1))
135+
printf "\n TEST: %-60s [ OK ]\n" "${msg}"
136+
else
137+
ret=1
138+
nfail=$((nfail+1))
139+
printf "\n TEST: %-60s [FAIL]\n" "${msg}"
140+
if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
141+
echo
142+
echo "hit enter to continue, 'q' to quit"
143+
read a
144+
[ "$a" = "q" ] && exit 1
145+
fi
146+
fi
147+
}
148+
149+
print_log_test_results()
150+
{
151+
if [ "$TESTS" != "none" ]; then
152+
printf "\nTests passed: %3d\n" ${nsuccess}
153+
printf "Tests failed: %3d\n" ${nfail}
154+
fi
155+
}
156+
157+
log_section()
158+
{
159+
echo
160+
echo "################################################################################"
161+
echo "TEST SECTION: $*"
162+
echo "################################################################################"
163+
}
164+
165+
cleanup()
166+
{
167+
ip link del veth-rt-1 2>/dev/null || true
168+
ip link del veth-rt-2 2>/dev/null || true
169+
170+
# destroy routers rt-* and hosts hs-*
171+
for ns in $(ip netns show | grep -E 'rt-*|hs-*'); do
172+
ip netns del ${ns} || true
173+
done
174+
}
175+
176+
# Setup the basic networking for the routers
177+
setup_rt_networking()
178+
{
179+
local rt=$1
180+
local nsname=rt-${rt}
181+
182+
ip netns add ${nsname}
183+
184+
ip netns exec ${nsname} sysctl -wq net.ipv6.conf.all.accept_dad=0
185+
ip netns exec ${nsname} sysctl -wq net.ipv6.conf.default.accept_dad=0
186+
187+
ip link set veth-rt-${rt} netns ${nsname}
188+
ip -netns ${nsname} link set veth-rt-${rt} name veth0
189+
190+
ip -netns ${nsname} addr add ${IPv6_RT_NETWORK}::${rt}/64 dev veth0 nodad
191+
ip -netns ${nsname} link set veth0 up
192+
ip -netns ${nsname} link set lo up
193+
194+
ip netns exec ${nsname} sysctl -wq net.ipv4.ip_forward=1
195+
ip netns exec ${nsname} sysctl -wq net.ipv6.conf.all.forwarding=1
196+
}
197+
198+
setup_rt_netfilter()
199+
{
200+
local rt=$1
201+
local nsname=rt-${rt}
202+
203+
ip netns exec ${nsname} sysctl -wq net.netfilter.nf_hooks_lwtunnel=1
204+
ip netns exec ${nsname} iptables -t raw -A PREROUTING -m rpfilter --invert -j DROP
205+
}
206+
207+
setup_hs()
208+
{
209+
local hs=$1
210+
local rt=$2
211+
local tid=$3
212+
local hsname=hs-${hs}
213+
local rtname=rt-${rt}
214+
local rtveth=veth-t${tid}
215+
216+
# set the networking for the host
217+
ip netns add ${hsname}
218+
219+
ip -netns ${hsname} link add veth0 type veth peer name ${rtveth}
220+
ip -netns ${hsname} link set ${rtveth} netns ${rtname}
221+
ip -netns ${hsname} addr add ${IPv4_HS_NETWORK}.${hs}/24 dev veth0
222+
ip -netns ${hsname} link set veth0 up
223+
ip -netns ${hsname} link set lo up
224+
225+
ip -netns ${rtname} addr add ${IPv4_HS_NETWORK}.${rt}${hs}/24 dev ${rtveth}
226+
ip -netns ${rtname} link set ${rtveth} up
227+
228+
ip netns exec ${rtname} sysctl -wq net.ipv4.conf.${rtveth}.proxy_arp=1
229+
}
230+
231+
setup_vpn_config()
232+
{
233+
local hssrc=$1
234+
local rtsrc=$2
235+
local hsdst=$3
236+
local rtdst=$4
237+
local tid=$5
238+
239+
local hssrc_name=hs-t${tid}-${hssrc}
240+
local hsdst_name=hs-t${tid}-${hsdst}
241+
local rtsrc_name=rt-${rtsrc}
242+
local rtdst_name=rt-${rtdst}
243+
local vpn_sid=${SID_LOCATOR}:${hssrc}${hsdst}:${tid}::6004
244+
245+
# set the encap route for encapsulating packets which arrive from the
246+
# host hssrc and destined to the access router rtsrc.
247+
ip -netns ${rtsrc_name} -4 route add ${IPv4_HS_NETWORK}.${hsdst}/32 \
248+
encap seg6 mode encap segs ${vpn_sid} dev veth0
249+
ip -netns ${rtsrc_name} -6 route add ${vpn_sid}/128 \
250+
via 2001:11::${rtdst} dev veth0
251+
252+
# set the decap route for decapsulating packets which arrive from
253+
# the rtdst router and destined to the hsdst host.
254+
ip -netns ${rtdst_name} -6 route add ${vpn_sid}/128 \
255+
encap seg6local action End.DX4 nh4 ${IPv4_HS_NETWORK}.${hsdst} dev veth-t${tid}
256+
}
257+
258+
setup()
259+
{
260+
ip link add veth-rt-1 type veth peer name veth-rt-2
261+
# setup the networking for router rt-1 and router rt-2
262+
setup_rt_networking 1
263+
setup_rt_networking 2
264+
265+
# setup two hosts for the tenant 100.
266+
# - host hs-1 is directly connected to the router rt-1;
267+
# - host hs-2 is directly connected to the router rt-2.
268+
setup_hs 1 1 100
269+
setup_hs 2 2 100
270+
271+
# setup the IPv4 L3 VPN which connects the host hs-1 and host hs-2.
272+
setup_vpn_config 1 1 2 2 100 #args: src_host src_router dst_host dst_router tenant
273+
setup_vpn_config 2 2 1 1 100
274+
}
275+
276+
check_hs_connectivity()
277+
{
278+
local hssrc=$1
279+
local hsdst=$2
280+
local tid=$3
281+
282+
ip netns exec hs-${hssrc} ping -c 1 -W ${PING_TIMEOUT_SEC} \
283+
${IPv4_HS_NETWORK}.${hsdst} >/dev/null 2>&1
284+
}
285+
286+
check_and_log_hs_connectivity()
287+
{
288+
local hssrc=$1
289+
local hsdst=$2
290+
local tid=$3
291+
292+
check_hs_connectivity ${hssrc} ${hsdst} ${tid}
293+
log_test $? 0 "Hosts connectivity: hs-${hssrc} -> hs-${hsdst} (tenant ${tid})"
294+
}
295+
296+
host_tests()
297+
{
298+
log_section "SRv6 VPN connectivity test among hosts in the same tenant"
299+
300+
check_and_log_hs_connectivity 1 2 100
301+
check_and_log_hs_connectivity 2 1 100
302+
}
303+
304+
router_netfilter_tests()
305+
{
306+
log_section "SRv6 VPN connectivity test with netfilter enabled in routers"
307+
setup_rt_netfilter 1
308+
setup_rt_netfilter 2
309+
310+
check_and_log_hs_connectivity 1 2 100
311+
check_and_log_hs_connectivity 2 1 100
312+
}
313+
314+
if [ "$(id -u)" -ne 0 ];then
315+
echo "SKIP: Need root privileges"
316+
exit $ksft_skip
317+
fi
318+
319+
if [ ! -x "$(command -v ip)" ]; then
320+
echo "SKIP: Could not run test without ip tool"
321+
exit $ksft_skip
322+
fi
323+
324+
cleanup &>/dev/null
325+
326+
setup
327+
328+
host_tests
329+
router_netfilter_tests
330+
331+
print_log_test_results
332+
333+
cleanup &>/dev/null
334+
335+
exit ${ret}

0 commit comments

Comments
 (0)