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