1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# Test VxLAN flooding. The device stores flood records in a singly linked list
5# where each record stores up to five IPv6 addresses of remote VTEPs. The test
6# verifies that packets are correctly flooded in various cases such as deletion
7# of a record in the middle of the list.
8#
9# +-----------------------+
10# | H1 (vrf)              |
11# |    + $h1              |
12# |    | 2001:db8:1::1/64 |
13# +----|------------------+
14#      |
15# +----|----------------------------------------------------------------------+
16# | SW |                                                                      |
17# | +--|--------------------------------------------------------------------+ |
18# | |  + $swp1                   BR0 (802.1d)                               | |
19# | |                                                                       | |
20# | |  + vxlan0 (vxlan)                                                     | |
21# | |    local 2001:db8:2::1                                                | |
22# | |    remote 2001:db8:2::{2..21}                                         | |
23# | |    id 10 dstport 4789                                                 | |
24# | +-----------------------------------------------------------------------+ |
25# |                                                                           |
26# |  2001:db8:2::0/64 via 2001:db8:3::2                                       |
27# |                                                                           |
28# |    + $rp1                                                                 |
29# |    | 2001:db8:3::1/64                                                     |
30# +----|----------------------------------------------------------------------+
31#      |
32# +----|--------------------------------------------------------+
33# |    |                                               R2 (vrf) |
34# |    + $rp2                                                   |
35# |      2001:db8:3::2/64                                       |
36# |                                                             |
37# +-------------------------------------------------------------+
38
39lib_dir=$(dirname $0)/../../../../net/forwarding
40
41ALL_TESTS="flooding_test"
42NUM_NETIFS=4
43source $lib_dir/tc_common.sh
44source $lib_dir/lib.sh
45
46h1_create()
47{
48	simple_if_init $h1 2001:db8:1::1/64
49}
50
51h1_destroy()
52{
53	simple_if_fini $h1 2001:db8:1::1/64
54}
55
56switch_create()
57{
58	# Make sure the bridge uses the MAC address of the local port and
59	# not that of the VxLAN's device
60	ip link add dev br0 type bridge mcast_snooping 0
61	ip link set dev br0 address $(mac_get $swp1)
62
63	ip link add name vxlan0 type vxlan id 10 nolearning \
64		udp6zerocsumrx udp6zerocsumtx ttl 20 tos inherit \
65		local 2001:db8:2::1 dstport 4789
66
67	ip address add 2001:db8:2::1/128 dev lo
68
69	ip link set dev $swp1 master br0
70	ip link set dev vxlan0 master br0
71
72	ip link set dev br0 up
73	ip link set dev $swp1 up
74	ip link set dev vxlan0 up
75}
76
77switch_destroy()
78{
79	ip link set dev vxlan0 down
80	ip link set dev $swp1 down
81	ip link set dev br0 down
82
83	ip link set dev vxlan0 nomaster
84	ip link set dev $swp1 nomaster
85
86	ip address del 2001:db8:2::1/128 dev lo
87
88	ip link del dev vxlan0
89
90	ip link del dev br0
91}
92
93router1_create()
94{
95	# This router is in the default VRF, where the VxLAN device is
96	# performing the L3 lookup
97	ip link set dev $rp1 up
98	ip address add 2001:db8:3::1/64 dev $rp1
99	ip route add 2001:db8:2::0/64 via 2001:db8:3::2
100}
101
102router1_destroy()
103{
104	ip route del 2001:db8:2::0/64 via 2001:db8:3::2
105	ip address del 2001:db8:3::1/64 dev $rp1
106	ip link set dev $rp1 down
107}
108
109router2_create()
110{
111	# This router is not in the default VRF, so use simple_if_init()
112	simple_if_init $rp2 2001:db8:3::2/64
113}
114
115router2_destroy()
116{
117	simple_if_fini $rp2 2001:db8:3::2/64
118}
119
120setup_prepare()
121{
122	h1=${NETIFS[p1]}
123	swp1=${NETIFS[p2]}
124
125	rp1=${NETIFS[p3]}
126	rp2=${NETIFS[p4]}
127
128	vrf_prepare
129
130	h1_create
131
132	switch_create
133
134	router1_create
135	router2_create
136
137	forwarding_enable
138}
139
140cleanup()
141{
142	pre_cleanup
143
144	forwarding_restore
145
146	router2_destroy
147	router1_destroy
148
149	switch_destroy
150
151	h1_destroy
152
153	vrf_cleanup
154}
155
156flooding_remotes_add()
157{
158	local num_remotes=$1
159	local lsb
160	local i
161
162	for i in $(eval echo {1..$num_remotes}); do
163		lsb=$((i + 1))
164
165		bridge fdb append 00:00:00:00:00:00 dev vxlan0 self \
166			dst 2001:db8:2::$lsb
167	done
168}
169
170flooding_filters_add()
171{
172	local num_remotes=$1
173	local lsb
174	local i
175
176	tc qdisc add dev $rp2 clsact
177
178	for i in $(eval echo {1..$num_remotes}); do
179		lsb=$((i + 1))
180
181		tc filter add dev $rp2 ingress protocol ipv6 pref $i handle $i \
182			flower ip_proto udp dst_ip 2001:db8:2::$lsb \
183			dst_port 4789 skip_sw action drop
184	done
185}
186
187flooding_filters_del()
188{
189	local num_remotes=$1
190	local i
191
192	for i in $(eval echo {1..$num_remotes}); do
193		tc filter del dev $rp2 ingress protocol ipv6 pref $i \
194			handle $i flower
195	done
196
197	tc qdisc del dev $rp2 clsact
198}
199
200flooding_check_packets()
201{
202	local packets=("$@")
203	local num_remotes=${#packets[@]}
204	local i
205
206	for i in $(eval echo {1..$num_remotes}); do
207		tc_check_packets "dev $rp2 ingress" $i ${packets[i - 1]}
208		check_err $? "remote $i - did not get expected number of packets"
209	done
210}
211
212flooding_test()
213{
214	# Use 20 remote VTEPs that will be stored in 4 records. The array
215	# 'packets' will store how many packets are expected to be received
216	# by each remote VTEP at each stage of the test
217	declare -a packets=(1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
218	local num_remotes=20
219
220	RET=0
221
222	# Add FDB entries for remote VTEPs and corresponding tc filters on the
223	# ingress of the nexthop router. These filters will count how many
224	# packets were flooded to each remote VTEP
225	flooding_remotes_add $num_remotes
226	flooding_filters_add $num_remotes
227
228	# Send one packet and make sure it is flooded to all the remote VTEPs
229	$MZ -6 $h1 -q -p 64 -b de:ad:be:ef:13:37 -t ip -c 1
230	flooding_check_packets "${packets[@]}"
231	log_test "flood after 1 packet"
232
233	# Delete the third record which corresponds to VTEPs with LSB 12..16
234	# and check that packet is flooded correctly when we remove a record
235	# from the middle of the list
236	RET=0
237
238	packets=(2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 2 2 2 2 2)
239	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::12
240	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::13
241	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::14
242	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::15
243	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::16
244
245	$MZ -6 $h1 -q -p 64 -b de:ad:be:ef:13:37 -t ip -c 1
246	flooding_check_packets "${packets[@]}"
247	log_test "flood after 2 packets"
248
249	# Delete the first record and make sure the packet is flooded correctly
250	RET=0
251
252	packets=(2 2 2 2 2 3 3 3 3 3 1 1 1 1 1 3 3 3 3 3)
253	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::2
254	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::3
255	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::4
256	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::5
257	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::6
258
259	$MZ -6 $h1 -q -p 64 -b de:ad:be:ef:13:37 -t ip -c 1
260	flooding_check_packets "${packets[@]}"
261	log_test "flood after 3 packets"
262
263	# Delete the last record and make sure the packet is flooded correctly
264	RET=0
265
266	packets=(2 2 2 2 2 4 4 4 4 4 1 1 1 1 1 3 3 3 3 3)
267	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::17
268	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::18
269	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::19
270	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::20
271	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::21
272
273	$MZ -6 $h1 -q -p 64 -b de:ad:be:ef:13:37 -t ip -c 1
274	flooding_check_packets "${packets[@]}"
275	log_test "flood after 4 packets"
276
277	# Delete the last record, one entry at a time and make sure single
278	# entries are correctly removed
279	RET=0
280
281	packets=(2 2 2 2 2 4 5 5 5 5 1 1 1 1 1 3 3 3 3 3)
282	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::7
283
284	$MZ -6 $h1 -q -p 64 -b de:ad:be:ef:13:37 -t ip -c 1
285	flooding_check_packets "${packets[@]}"
286	log_test "flood after 5 packets"
287
288	RET=0
289
290	packets=(2 2 2 2 2 4 5 6 6 6 1 1 1 1 1 3 3 3 3 3)
291	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::8
292
293	$MZ -6 $h1 -q -p 64 -b de:ad:be:ef:13:37 -t ip -c 1
294	flooding_check_packets "${packets[@]}"
295	log_test "flood after 6 packets"
296
297	RET=0
298
299	packets=(2 2 2 2 2 4 5 6 7 7 1 1 1 1 1 3 3 3 3 3)
300	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::9
301
302	$MZ -6 $h1 -q -p 64 -b de:ad:be:ef:13:37 -t ip -c 1
303	flooding_check_packets "${packets[@]}"
304	log_test "flood after 7 packets"
305
306	RET=0
307
308	packets=(2 2 2 2 2 4 5 6 7 8 1 1 1 1 1 3 3 3 3 3)
309	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::10
310
311	$MZ -6 $h1 -q -p 64 -b de:ad:be:ef:13:37 -t ip -c 1
312	flooding_check_packets "${packets[@]}"
313	log_test "flood after 8 packets"
314
315	RET=0
316
317	packets=(2 2 2 2 2 4 5 6 7 8 1 1 1 1 1 3 3 3 3 3)
318	bridge fdb del 00:00:00:00:00:00 dev vxlan0 self dst 2001:db8:2::11
319
320	$MZ -6 $h1 -q -p 64 -b de:ad:be:ef:13:37 -t ip -c 1
321	flooding_check_packets "${packets[@]}"
322	log_test "flood after 9 packets"
323
324	flooding_filters_del $num_remotes
325}
326
327trap cleanup EXIT
328
329setup_prepare
330setup_wait
331
332tests_run
333
334exit $EXIT_STATUS
335