xref: /linux/tools/testing/selftests/net/forwarding/vxlan_reserved.sh (revision 0ad9617c78acbc71373fb341a6f75d4012b01d69)
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	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
61switch_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
77vrp2_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
83setup_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
103vxlan_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
142neg_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
158vxlan_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
201vxlan_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
209vxlan_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
221vxlan_ping_vanilla()
222{
223	vxlan_ping_do 10 $rp2 $(mac_get $rp1) 192.0.2.17 $(mac_get $h1) 1000
224}
225
226vxlan_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
235vxlan_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
280default_test_do()
281{
282	vxlan_device_add
283	__default_test_do 0 "Default"
284}
285
286default_test()
287{
288	in_defer_scope \
289	    default_test_do
290}
291
292plain_test_do()
293{
294	vxlan_device_add reserved_bits 0xf7ffffff000000ff
295	__default_test_do 0 "reserved_bits 0xf7ffffff000000ff"
296}
297
298plain_test()
299{
300	in_defer_scope \
301	    plain_test_do
302}
303
304reserved_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
316reserved_0_test()
317{
318	in_defer_scope \
319	    reserved_test 0
320}
321
322reserved_10_test()
323{
324	in_defer_scope \
325	    reserved_test 10
326}
327
328reserved_31_test()
329{
330	in_defer_scope \
331	    reserved_test 31
332}
333
334reserved_56_test()
335{
336	in_defer_scope \
337	    reserved_test 56
338}
339
340reserved_63_test()
341{
342	in_defer_scope \
343	    reserved_test 63
344}
345
346trap cleanup EXIT
347
348setup_prepare
349setup_wait
350tests_run
351
352exit $EXIT_STATUS
353