Skip to content

Commit d84b5dc

Browse files
pmachatakuba-moo
authored andcommitted
selftests: forwarding: Add a selftest for the new reserved_bits UAPI
Run VXLAN packets through a gateway. Flip individual bits of the packet and/or reserved bits of the gateway, and check that the gateway treats the packets as expected. Signed-off-by: Petr Machata <[email protected]> Reviewed-by: Ido Schimmel <[email protected]> Reviewed-by: Nikolay Aleksandrov <[email protected]> Link: https://patch.msgid.link/388bef3c30ebc887d4e64cd86a362e2df2f2d2e1.1733412063.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski <[email protected]>
1 parent d76ccb2 commit d84b5dc

File tree

2 files changed

+353
-0
lines changed

2 files changed

+353
-0
lines changed

tools/testing/selftests/net/forwarding/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ TEST_PROGS = bridge_fdb_learning_limit.sh \
105105
vxlan_bridge_1q_port_8472_ipv6.sh \
106106
vxlan_bridge_1q_port_8472.sh \
107107
vxlan_bridge_1q.sh \
108+
vxlan_reserved.sh \
108109
vxlan_symmetric_ipv6.sh \
109110
vxlan_symmetric.sh
110111

Lines changed: 352 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,352 @@
1+
#!/bin/bash
2+
# SPDX-License-Identifier: GPL-2.0
3+
4+
# +--------------------+
5+
# | H1 (vrf) |
6+
# | + $h1 |
7+
# | | 192.0.2.1/28 |
8+
# +----|---------------+
9+
# |
10+
# +----|--------------------------------+
11+
# | SW | |
12+
# | +--|------------------------------+ |
13+
# | | + $swp1 BR1 (802.1d) | |
14+
# | | | |
15+
# | | + vx1 (vxlan) | |
16+
# | | local 192.0.2.17 | |
17+
# | | id 1000 dstport $VXPORT | |
18+
# | +---------------------------------+ |
19+
# | |
20+
# | 192.0.2.32/28 via 192.0.2.18 |
21+
# | |
22+
# | + $rp1 |
23+
# | | 192.0.2.17/28 |
24+
# +--|----------------------------------+
25+
# |
26+
# +--|----------------------------------+
27+
# | | |
28+
# | + $rp2 |
29+
# | 192.0.2.18/28 |
30+
# | |
31+
# | VRP2 (vrf) |
32+
# +-------------------------------------+
33+
34+
: ${VXPORT:=4789}
35+
: ${ALL_TESTS:="
36+
default_test
37+
plain_test
38+
reserved_0_test
39+
reserved_10_test
40+
reserved_31_test
41+
reserved_56_test
42+
reserved_63_test
43+
"}
44+
45+
NUM_NETIFS=4
46+
source lib.sh
47+
48+
h1_create()
49+
{
50+
simple_if_init $h1 192.0.2.1/28
51+
defer simple_if_fini $h1 192.0.2.1/28
52+
53+
tc qdisc add dev $h1 clsact
54+
defer tc qdisc del dev $h1 clsact
55+
56+
tc filter add dev $h1 ingress pref 77 \
57+
prot ip flower skip_hw ip_proto icmp action drop
58+
defer tc filter del dev $h1 ingress pref 77
59+
}
60+
61+
switch_create()
62+
{
63+
ip_link_add br1 type bridge vlan_filtering 0 mcast_snooping 0
64+
# Make sure the bridge uses the MAC address of the local port and not
65+
# that of the VxLAN's device.
66+
ip_link_set_addr br1 $(mac_get $swp1)
67+
ip_link_set_up br1
68+
69+
ip_link_set_up $rp1
70+
ip_addr_add $rp1 192.0.2.17/28
71+
ip_route_add 192.0.2.32/28 nexthop via 192.0.2.18
72+
73+
ip_link_set_master $swp1 br1
74+
ip_link_set_up $swp1
75+
}
76+
77+
vrp2_create()
78+
{
79+
simple_if_init $rp2 192.0.2.18/28
80+
defer simple_if_fini $rp2 192.0.2.18/28
81+
}
82+
83+
setup_prepare()
84+
{
85+
h1=${NETIFS[p1]}
86+
swp1=${NETIFS[p2]}
87+
88+
rp1=${NETIFS[p3]}
89+
rp2=${NETIFS[p4]}
90+
91+
vrf_prepare
92+
defer vrf_cleanup
93+
94+
forwarding_enable
95+
defer forwarding_restore
96+
97+
h1_create
98+
switch_create
99+
100+
vrp2_create
101+
}
102+
103+
vxlan_header_bytes()
104+
{
105+
local vni=$1; shift
106+
local -a extra_bits=("$@")
107+
local -a bits
108+
local i
109+
110+
for ((i=0; i < 64; i++)); do
111+
bits[i]=0
112+
done
113+
114+
# Bit 4 is the I flag and is always on.
115+
bits[4]=1
116+
117+
for i in ${extra_bits[@]}; do
118+
bits[i]=1
119+
done
120+
121+
# Bits 32..55 carry the VNI
122+
local mask=0x800000
123+
for ((i=0; i < 24; i++)); do
124+
bits[$((i + 32))]=$(((vni & mask) != 0))
125+
((mask >>= 1))
126+
done
127+
128+
local bytes
129+
for ((i=0; i < 8; i++)); do
130+
local byte=0
131+
local j
132+
for ((j=0; j < 8; j++)); do
133+
local bit=${bits[8 * i + j]}
134+
((byte += bit << (7 - j)))
135+
done
136+
bytes+=$(printf %02x $byte):
137+
done
138+
139+
echo ${bytes%:}
140+
}
141+
142+
neg_bytes()
143+
{
144+
local bytes=$1; shift
145+
146+
local -A neg=([0]=f [1]=e [2]=d [3]=c [4]=b [5]=a [6]=9 [7]=8
147+
[8]=7 [9]=6 [a]=5 [b]=4 [c]=3 [d]=2 [e]=1 [f]=0 [:]=:)
148+
local out
149+
local i
150+
151+
for ((i=0; i < ${#bytes}; i++)); do
152+
local c=${bytes:$i:1}
153+
out+=${neg[$c]}
154+
done
155+
echo $out
156+
}
157+
158+
vxlan_ping_do()
159+
{
160+
local count=$1; shift
161+
local dev=$1; shift
162+
local next_hop_mac=$1; shift
163+
local dest_ip=$1; shift
164+
local dest_mac=$1; shift
165+
local vni=$1; shift
166+
local reserved_bits=$1; shift
167+
168+
local vxlan_header=$(vxlan_header_bytes $vni $reserved_bits)
169+
170+
$MZ $dev -c $count -d 100msec -q \
171+
-b $next_hop_mac -B $dest_ip \
172+
-t udp sp=23456,dp=$VXPORT,p=$(:
173+
)"$vxlan_header:"$( : VXLAN
174+
)"$dest_mac:"$( : ETH daddr
175+
)"00:11:22:33:44:55:"$( : ETH saddr
176+
)"08:00:"$( : ETH type
177+
)"45:"$( : IP version + IHL
178+
)"00:"$( : IP TOS
179+
)"00:54:"$( : IP total length
180+
)"99:83:"$( : IP identification
181+
)"40:00:"$( : IP flags + frag off
182+
)"40:"$( : IP TTL
183+
)"01:"$( : IP proto
184+
)"00:00:"$( : IP header csum
185+
)"$(ipv4_to_bytes 192.0.2.3):"$( : IP saddr
186+
)"$(ipv4_to_bytes 192.0.2.1):"$( : IP daddr
187+
)"08:"$( : ICMP type
188+
)"00:"$( : ICMP code
189+
)"8b:f2:"$( : ICMP csum
190+
)"1f:6a:"$( : ICMP request identifier
191+
)"00:01:"$( : ICMP request seq. number
192+
)"4f:ff:c5:5b:00:00:00:00:"$( : ICMP payload
193+
)"6d:74:0b:00:00:00:00:00:"$( :
194+
)"10:11:12:13:14:15:16:17:"$( :
195+
)"18:19:1a:1b:1c:1d:1e:1f:"$( :
196+
)"20:21:22:23:24:25:26:27:"$( :
197+
)"28:29:2a:2b:2c:2d:2e:2f:"$( :
198+
)"30:31:32:33:34:35:36:37"
199+
}
200+
201+
vxlan_device_add()
202+
{
203+
ip_link_add vx1 up type vxlan id 1000 \
204+
local 192.0.2.17 dstport "$VXPORT" \
205+
nolearning noudpcsum tos inherit ttl 100 "$@"
206+
ip_link_set_master vx1 br1
207+
}
208+
209+
vxlan_all_reserved_bits()
210+
{
211+
local i
212+
213+
for ((i=0; i < 64; i++)); do
214+
if ((i == 4 || i >= 32 && i < 56)); then
215+
continue
216+
fi
217+
echo $i
218+
done
219+
}
220+
221+
vxlan_ping_vanilla()
222+
{
223+
vxlan_ping_do 10 $rp2 $(mac_get $rp1) 192.0.2.17 $(mac_get $h1) 1000
224+
}
225+
226+
vxlan_ping_reserved()
227+
{
228+
for bit in $(vxlan_all_reserved_bits); do
229+
vxlan_ping_do 1 $rp2 $(mac_get $rp1) \
230+
192.0.2.17 $(mac_get $h1) 1000 "$bit"
231+
((n++))
232+
done
233+
}
234+
235+
vxlan_ping_test()
236+
{
237+
local what=$1; shift
238+
local get_stat=$1; shift
239+
local expect=$1; shift
240+
241+
RET=0
242+
243+
local t0=$($get_stat)
244+
245+
"$@"
246+
check_err $? "Failure when running $@"
247+
248+
local t1=$($get_stat)
249+
local delta=$((t1 - t0))
250+
251+
((expect == delta))
252+
check_err $? "Expected to capture $expect packets, got $delta."
253+
254+
log_test "$what"
255+
}
256+
257+
__default_test_do()
258+
{
259+
local n_allowed_bits=$1; shift
260+
local what=$1; shift
261+
262+
vxlan_ping_test "$what: clean packets" \
263+
"tc_rule_stats_get $h1 77 ingress" \
264+
10 vxlan_ping_vanilla
265+
266+
local t0=$(link_stats_get vx1 rx errors)
267+
vxlan_ping_test "$what: mangled packets" \
268+
"tc_rule_stats_get $h1 77 ingress" \
269+
$n_allowed_bits vxlan_ping_reserved
270+
local t1=$(link_stats_get vx1 rx errors)
271+
272+
RET=0
273+
local expect=$((39 - n_allowed_bits))
274+
local delta=$((t1 - t0))
275+
((expect == delta))
276+
check_err $? "Expected $expect error packets, got $delta."
277+
log_test "$what: drops reported"
278+
}
279+
280+
default_test_do()
281+
{
282+
vxlan_device_add
283+
__default_test_do 0 "Default"
284+
}
285+
286+
default_test()
287+
{
288+
in_defer_scope \
289+
default_test_do
290+
}
291+
292+
plain_test_do()
293+
{
294+
vxlan_device_add reserved_bits 0xf7ffffff000000ff
295+
__default_test_do 0 "reserved_bits 0xf7ffffff000000ff"
296+
}
297+
298+
plain_test()
299+
{
300+
in_defer_scope \
301+
plain_test_do
302+
}
303+
304+
reserved_test()
305+
{
306+
local bit=$1; shift
307+
308+
local allowed_bytes=$(vxlan_header_bytes 0xffffff $bit)
309+
local reserved_bytes=$(neg_bytes $allowed_bytes)
310+
local reserved_bits=${reserved_bytes//:/}
311+
312+
vxlan_device_add reserved_bits 0x$reserved_bits
313+
__default_test_do 1 "reserved_bits 0x$reserved_bits"
314+
}
315+
316+
reserved_0_test()
317+
{
318+
in_defer_scope \
319+
reserved_test 0
320+
}
321+
322+
reserved_10_test()
323+
{
324+
in_defer_scope \
325+
reserved_test 10
326+
}
327+
328+
reserved_31_test()
329+
{
330+
in_defer_scope \
331+
reserved_test 31
332+
}
333+
334+
reserved_56_test()
335+
{
336+
in_defer_scope \
337+
reserved_test 56
338+
}
339+
340+
reserved_63_test()
341+
{
342+
in_defer_scope \
343+
reserved_test 63
344+
}
345+
346+
trap cleanup EXIT
347+
348+
setup_prepare
349+
setup_wait
350+
tests_run
351+
352+
exit $EXIT_STATUS

0 commit comments

Comments
 (0)