1343171Sdim#!/bin/bash
2343171Sdim# SPDX-License-Identifier: GPL-2.0
3353358Sdim#
4353358Sdim# This test is for checking functionality of flushing FDB entries.
5353358Sdim# Check that flush works as expected with all the supported arguments and verify
6343171Sdim# some combinations of arguments.
7343171Sdim
8343171Sdimsource lib.sh
9343171Sdim
10343171SdimFLUSH_BY_STATE_TESTS="
11343171Sdim	vxlan_test_flush_by_permanent
12343171Sdim	vxlan_test_flush_by_nopermanent
13343171Sdim	vxlan_test_flush_by_static
14343171Sdim	vxlan_test_flush_by_nostatic
15343171Sdim	vxlan_test_flush_by_dynamic
16343171Sdim	vxlan_test_flush_by_nodynamic
17343171Sdim"
18343171Sdim
19343171SdimFLUSH_BY_FLAG_TESTS="
20343171Sdim	vxlan_test_flush_by_extern_learn
21343171Sdim	vxlan_test_flush_by_noextern_learn
22343171Sdim	vxlan_test_flush_by_router
23343171Sdim	vxlan_test_flush_by_norouter
24343171Sdim"
25343171Sdim
26343171SdimTESTS="
27343171Sdim	vxlan_test_flush_by_dev
28343171Sdim	vxlan_test_flush_by_vni
29343171Sdim	vxlan_test_flush_by_src_vni
30343171Sdim	vxlan_test_flush_by_port
31343171Sdim	vxlan_test_flush_by_dst_ip
32343171Sdim	vxlan_test_flush_by_nhid
33343171Sdim	$FLUSH_BY_STATE_TESTS
34343171Sdim	$FLUSH_BY_FLAG_TESTS
35343171Sdim	vxlan_test_flush_by_several_args
36343171Sdim	vxlan_test_flush_by_remote_attributes
37343171Sdim	bridge_test_flush_by_dev
38343171Sdim	bridge_test_flush_by_vlan
39343171Sdim	bridge_vxlan_test_flush
40343171Sdim"
41343171Sdim
42343171Sdim: ${VERBOSE:=0}
43343171Sdim: ${PAUSE_ON_FAIL:=no}
44343171Sdim: ${PAUSE:=no}
45343171Sdim: ${VXPORT:=4789}
46343171Sdim
47343171Sdimrun_cmd()
48343171Sdim{
49343171Sdim	local cmd="$1"
50343171Sdim	local out
51343171Sdim	local rc
52	local stderr="2>/dev/null"
53
54	if [ "$VERBOSE" = "1" ]; then
55		printf "COMMAND: $cmd\n"
56		stderr=
57	fi
58
59	out=$(eval $cmd $stderr)
60	rc=$?
61	if [ "$VERBOSE" = "1" -a -n "$out" ]; then
62		echo "    $out"
63	fi
64
65	return $rc
66}
67
68log_test()
69{
70	local rc=$1
71	local expected=$2
72	local msg="$3"
73	local nsuccess
74	local nfail
75	local ret
76
77	if [ ${rc} -eq ${expected} ]; then
78		printf "TEST: %-60s  [ OK ]\n" "${msg}"
79		nsuccess=$((nsuccess+1))
80	else
81		ret=1
82		nfail=$((nfail+1))
83		printf "TEST: %-60s  [FAIL]\n" "${msg}"
84		if [ "$VERBOSE" = "1" ]; then
85			echo "    rc=$rc, expected $expected"
86		fi
87
88		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
89		echo
90			echo "hit enter to continue, 'q' to quit"
91			read a
92			[ "$a" = "q" ] && exit 1
93		fi
94	fi
95
96	if [ "${PAUSE}" = "yes" ]; then
97		echo
98		echo "hit enter to continue, 'q' to quit"
99		read a
100		[ "$a" = "q" ] && exit 1
101	fi
102
103	[ "$VERBOSE" = "1" ] && echo
104}
105
106MAC_POOL_1="
107	de:ad:be:ef:13:10
108	de:ad:be:ef:13:11
109	de:ad:be:ef:13:12
110	de:ad:be:ef:13:13
111	de:ad:be:ef:13:14
112"
113mac_pool_1_len=$(echo "$MAC_POOL_1" | grep -c .)
114
115MAC_POOL_2="
116	ca:fe:be:ef:13:10
117	ca:fe:be:ef:13:11
118	ca:fe:be:ef:13:12
119	ca:fe:be:ef:13:13
120	ca:fe:be:ef:13:14
121"
122mac_pool_2_len=$(echo "$MAC_POOL_2" | grep -c .)
123
124fdb_add_mac_pool_1()
125{
126	local dev=$1; shift
127	local args="$@"
128
129	for mac in $MAC_POOL_1
130	do
131		$BRIDGE fdb add $mac dev $dev $args
132	done
133}
134
135fdb_add_mac_pool_2()
136{
137	local dev=$1; shift
138	local args="$@"
139
140	for mac in $MAC_POOL_2
141	do
142		$BRIDGE fdb add $mac dev $dev $args
143	done
144}
145
146fdb_check_n_entries_by_dev_filter()
147{
148	local dev=$1; shift
149	local exp_entries=$1; shift
150	local filter="$@"
151
152	local entries=$($BRIDGE fdb show dev $dev | grep "$filter" | wc -l)
153
154	[[ $entries -eq $exp_entries ]]
155	rc=$?
156
157	log_test $rc 0 "$dev: Expected $exp_entries FDB entries, got $entries"
158	return $rc
159}
160
161vxlan_test_flush_by_dev()
162{
163	local vni=3000
164	local dst_ip=192.0.2.1
165
166	fdb_add_mac_pool_1 vx10 vni $vni dst $dst_ip
167	fdb_add_mac_pool_2 vx20 vni $vni dst $dst_ip
168
169	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len
170	fdb_check_n_entries_by_dev_filter vx20 $mac_pool_2_len
171
172	run_cmd "$BRIDGE fdb flush dev vx10"
173	log_test $? 0 "Flush FDB by dev vx10"
174
175	fdb_check_n_entries_by_dev_filter vx10 0
176	log_test $? 0 "Flush FDB by dev vx10 - test vx10 entries"
177
178	fdb_check_n_entries_by_dev_filter vx20 $mac_pool_2_len
179	log_test $? 0 "Flush FDB by dev vx10 - test vx20 entries"
180}
181
182vxlan_test_flush_by_vni()
183{
184	local vni_1=3000
185	local vni_2=4000
186	local dst_ip=192.0.2.1
187
188	fdb_add_mac_pool_1 vx10 vni $vni_1 dst $dst_ip
189	fdb_add_mac_pool_2 vx10 vni $vni_2 dst $dst_ip
190
191	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len vni $vni_1
192	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len vni $vni_2
193
194	run_cmd "$BRIDGE fdb flush dev vx10 vni $vni_2"
195	log_test $? 0 "Flush FDB by dev vx10 and vni $vni_2"
196
197	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len vni $vni_1
198	log_test $? 0 "Test entries with vni $vni_1"
199
200	fdb_check_n_entries_by_dev_filter vx10 0 vni $vni_2
201	log_test $? 0 "Test entries with vni $vni_2"
202}
203
204vxlan_test_flush_by_src_vni()
205{
206	# Set some entries with {vni=x,src_vni=y} and some with the opposite -
207	# {vni=y,src_vni=x}, to verify that when we flush by src_vni=x, entries
208	# with vni=x are not flused.
209	local vni_1=3000
210	local vni_2=4000
211	local src_vni_1=4000
212	local src_vni_2=3000
213	local dst_ip=192.0.2.1
214
215	# Reconfigure vx10 with 'external' to get 'src_vni' details in
216	# 'bridge fdb' output
217	$IP link del dev vx10
218	$IP link add name vx10 type vxlan dstport "$VXPORT" external
219
220	fdb_add_mac_pool_1 vx10 vni $vni_1 src_vni $src_vni_1 dst $dst_ip
221	fdb_add_mac_pool_2 vx10 vni $vni_2 src_vni $src_vni_2 dst $dst_ip
222
223	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len \
224		src_vni $src_vni_1
225	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len \
226		src_vni $src_vni_2
227
228	run_cmd "$BRIDGE fdb flush dev vx10 src_vni $src_vni_2"
229	log_test $? 0 "Flush FDB by dev vx10 and src_vni $src_vni_2"
230
231	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len \
232		src_vni $src_vni_1
233	log_test $? 0 "Test entries with src_vni $src_vni_1"
234
235	fdb_check_n_entries_by_dev_filter vx10 0 src_vni $src_vni_2
236	log_test $? 0 "Test entries with src_vni $src_vni_2"
237}
238
239vxlan_test_flush_by_port()
240{
241	local port_1=1234
242	local port_2=4321
243	local dst_ip=192.0.2.1
244
245	fdb_add_mac_pool_1 vx10 port $port_1 dst $dst_ip
246	fdb_add_mac_pool_2 vx10 port $port_2 dst $dst_ip
247
248	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len port $port_1
249	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len port $port_2
250
251	run_cmd "$BRIDGE fdb flush dev vx10 port $port_2"
252	log_test $? 0 "Flush FDB by dev vx10 and port $port_2"
253
254	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len port $port_1
255	log_test $? 0 "Test entries with port $port_1"
256
257	fdb_check_n_entries_by_dev_filter vx10 0 port $port_2
258	log_test $? 0 "Test entries with port $port_2"
259}
260
261vxlan_test_flush_by_dst_ip()
262{
263	local dst_ip_1=192.0.2.1
264	local dst_ip_2=192.0.2.2
265
266	fdb_add_mac_pool_1 vx10 dst $dst_ip_1
267	fdb_add_mac_pool_2 vx10 dst $dst_ip_2
268
269	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
270	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len dst $dst_ip_2
271
272	run_cmd "$BRIDGE fdb flush dev vx10 dst $dst_ip_2"
273	log_test $? 0 "Flush FDB by dev vx10 and dst $dst_ip_2"
274
275	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
276	log_test $? 0 "Test entries with dst $dst_ip_1"
277
278	fdb_check_n_entries_by_dev_filter vx10 0 dst $dst_ip_2
279	log_test $? 0 "Test entries with dst $dst_ip_2"
280}
281
282nexthops_add()
283{
284	local nhid_1=$1; shift
285	local nhid_2=$1; shift
286
287	$IP nexthop add id 10 via 192.0.2.1 fdb
288	$IP nexthop add id $nhid_1 group 10 fdb
289
290	$IP nexthop add id 20 via 192.0.2.2 fdb
291	$IP nexthop add id $nhid_2 group 20 fdb
292}
293
294vxlan_test_flush_by_nhid()
295{
296	local nhid_1=100
297	local nhid_2=200
298
299	nexthops_add $nhid_1 $nhid_2
300
301	fdb_add_mac_pool_1 vx10 nhid $nhid_1
302	fdb_add_mac_pool_2 vx10 nhid $nhid_2
303
304	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len nhid $nhid_1
305	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len nhid $nhid_2
306
307	run_cmd "$BRIDGE fdb flush dev vx10 nhid $nhid_2"
308	log_test $? 0 "Flush FDB by dev vx10 and nhid $nhid_2"
309
310	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len nhid $nhid_1
311	log_test $? 0 "Test entries with nhid $nhid_1"
312
313	fdb_check_n_entries_by_dev_filter vx10 0 nhid $nhid_2
314	log_test $? 0 "Test entries with nhid $nhid_2"
315
316	# Flush also entries with $nhid_1, and then verify that flushing by
317	# 'nhid' does not return an error when there are no entries with
318	# nexthops.
319	run_cmd "$BRIDGE fdb flush dev vx10 nhid $nhid_1"
320	log_test $? 0 "Flush FDB by dev vx10 and nhid $nhid_1"
321
322	fdb_check_n_entries_by_dev_filter vx10 0 nhid
323	log_test $? 0 "Test entries with 'nhid' keyword"
324
325	run_cmd "$BRIDGE fdb flush dev vx10 nhid $nhid_1"
326	log_test $? 0 "Flush FDB by nhid when there are no entries with nexthop"
327}
328
329vxlan_test_flush_by_state()
330{
331	local flush_by_state=$1; shift
332	local state_1=$1; shift
333	local exp_state_1=$1; shift
334	local state_2=$1; shift
335	local exp_state_2=$1; shift
336
337	local dst_ip_1=192.0.2.1
338	local dst_ip_2=192.0.2.2
339
340	fdb_add_mac_pool_1 vx10 dst $dst_ip_1 $state_1
341	fdb_add_mac_pool_2 vx10 dst $dst_ip_2 $state_2
342
343	# Check the entries by dst_ip as not all states appear in 'bridge fdb'
344	# output.
345	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
346	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len dst $dst_ip_2
347
348	run_cmd "$BRIDGE fdb flush dev vx10 $flush_by_state"
349	log_test $? 0 "Flush FDB by dev vx10 and state $flush_by_state"
350
351	fdb_check_n_entries_by_dev_filter vx10 $exp_state_1 dst $dst_ip_1
352	log_test $? 0 "Test entries with state $state_1"
353
354	fdb_check_n_entries_by_dev_filter vx10 $exp_state_2 dst $dst_ip_2
355	log_test $? 0 "Test entries with state $state_2"
356}
357
358vxlan_test_flush_by_permanent()
359{
360	# Entries that are added without state get 'permanent' state by
361	# default, add some entries with flag 'extern_learn' instead of state,
362	# so they will be added with 'permanent' and should be flushed also.
363	local flush_by_state="permanent"
364	local state_1="permanent"
365	local exp_state_1=0
366	local state_2="extern_learn"
367	local exp_state_2=0
368
369	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
370		$state_2 $exp_state_2
371}
372
373vxlan_test_flush_by_nopermanent()
374{
375	local flush_by_state="nopermanent"
376	local state_1="permanent"
377	local exp_state_1=$mac_pool_1_len
378	local state_2="static"
379	local exp_state_2=0
380
381	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
382		$state_2 $exp_state_2
383}
384
385vxlan_test_flush_by_static()
386{
387	local flush_by_state="static"
388	local state_1="static"
389	local exp_state_1=0
390	local state_2="dynamic"
391	local exp_state_2=$mac_pool_2_len
392
393	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
394		$state_2 $exp_state_2
395}
396
397vxlan_test_flush_by_nostatic()
398{
399	local flush_by_state="nostatic"
400	local state_1="permanent"
401	local exp_state_1=$mac_pool_1_len
402	local state_2="dynamic"
403	local exp_state_2=0
404
405	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
406		$state_2 $exp_state_2
407}
408
409vxlan_test_flush_by_dynamic()
410{
411	local flush_by_state="dynamic"
412	local state_1="dynamic"
413	local exp_state_1=0
414	local state_2="static"
415	local exp_state_2=$mac_pool_2_len
416
417	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
418		$state_2 $exp_state_2
419}
420
421vxlan_test_flush_by_nodynamic()
422{
423	local flush_by_state="nodynamic"
424	local state_1="permanent"
425	local exp_state_1=0
426	local state_2="dynamic"
427	local exp_state_2=$mac_pool_2_len
428
429	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
430		$state_2 $exp_state_2
431}
432
433vxlan_test_flush_by_flag()
434{
435	local flush_by_flag=$1; shift
436	local flag_1=$1; shift
437	local exp_flag_1=$1; shift
438	local flag_2=$1; shift
439	local exp_flag_2=$1; shift
440
441	local dst_ip_1=192.0.2.1
442	local dst_ip_2=192.0.2.2
443
444	fdb_add_mac_pool_1 vx10 dst $dst_ip_1 $flag_1
445	fdb_add_mac_pool_2 vx10 dst $dst_ip_2 $flag_2
446
447	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len $flag_1
448	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len $flag_2
449
450	run_cmd "$BRIDGE fdb flush dev vx10 $flush_by_flag"
451	log_test $? 0 "Flush FDB by dev vx10 and flag $flush_by_flag"
452
453	fdb_check_n_entries_by_dev_filter vx10 $exp_flag_1 dst $dst_ip_1
454	log_test $? 0 "Test entries with flag $flag_1"
455
456	fdb_check_n_entries_by_dev_filter vx10 $exp_flag_2 dst $dst_ip_2
457	log_test $? 0 "Test entries with flag $flag_2"
458}
459
460vxlan_test_flush_by_extern_learn()
461{
462	local flush_by_flag="extern_learn"
463	local flag_1="extern_learn"
464	local exp_flag_1=0
465	local flag_2="router"
466	local exp_flag_2=$mac_pool_2_len
467
468	vxlan_test_flush_by_flag $flush_by_flag $flag_1 $exp_flag_1 \
469		$flag_2 $exp_flag_2
470}
471
472vxlan_test_flush_by_noextern_learn()
473{
474	local flush_by_flag="noextern_learn"
475	local flag_1="extern_learn"
476	local exp_flag_1=$mac_pool_1_len
477	local flag_2="router"
478	local exp_flag_2=0
479
480	vxlan_test_flush_by_flag $flush_by_flag $flag_1 $exp_flag_1 \
481		$flag_2 $exp_flag_2
482}
483
484vxlan_test_flush_by_router()
485{
486	local flush_by_flag="router"
487	local flag_1="router"
488	local exp_flag_1=0
489	local flag_2="extern_learn"
490	local exp_flag_2=$mac_pool_2_len
491
492	vxlan_test_flush_by_flag $flush_by_flag $flag_1 $exp_flag_1 \
493		$flag_2 $exp_flag_2
494}
495
496vxlan_test_flush_by_norouter()
497{
498
499	local flush_by_flag="norouter"
500	local flag_1="router"
501	local exp_flag_1=$mac_pool_1_len
502	local flag_2="extern_learn"
503	local exp_flag_2=0
504
505	vxlan_test_flush_by_flag $flush_by_flag $flag_1 $exp_flag_1 \
506		$flag_2 $exp_flag_2
507}
508
509vxlan_test_flush_by_several_args()
510{
511	local dst_ip_1=192.0.2.1
512	local dst_ip_2=192.0.2.2
513	local state_1=permanent
514	local state_2=static
515	local vni=3000
516	local port=1234
517	local nhid=100
518	local flag=router
519	local flush_args
520
521	################### Flush by 2 args - nhid and flag ####################
522	$IP nexthop add id 10 via 192.0.2.1 fdb
523	$IP nexthop add id $nhid group 10 fdb
524
525	fdb_add_mac_pool_1 vx10 nhid $nhid $flag $state_1
526	fdb_add_mac_pool_2 vx10 nhid $nhid $flag $state_2
527
528	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len $state_1
529	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len $state_2
530
531	run_cmd "$BRIDGE fdb flush dev vx10 nhid $nhid $flag"
532	log_test $? 0 "Flush FDB by dev vx10 nhid $nhid $flag"
533
534	# All entries should be flushed as 'state' is not an argument for flush
535	# filtering.
536	fdb_check_n_entries_by_dev_filter vx10 0 $state_1
537	log_test $? 0 "Test entries with state $state_1"
538
539	fdb_check_n_entries_by_dev_filter vx10 0 $state_2
540	log_test $? 0 "Test entries with state $state_2"
541
542	################ Flush by 3 args - VNI, port and dst_ip ################
543	fdb_add_mac_pool_1 vx10 vni $vni port $port dst $dst_ip_1
544	fdb_add_mac_pool_2 vx10 vni $vni port $port dst $dst_ip_2
545
546	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
547	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len dst $dst_ip_2
548
549	flush_args="vni $vni port $port dst $dst_ip_2"
550	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
551	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
552
553	# Only entries with $dst_ip_2 should be flushed, even the rest arguments
554	# match the filter, the flush should be AND of all the arguments.
555	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
556	log_test $? 0 "Test entries with dst $dst_ip_1"
557
558	fdb_check_n_entries_by_dev_filter vx10 0 dst $dst_ip_2
559	log_test $? 0 "Test entries with dst $dst_ip_2"
560}
561
562multicast_fdb_entries_add()
563{
564	mac=00:00:00:00:00:00
565	vnis=(2000 3000)
566
567	for vni in "${vnis[@]}"; do
568		$BRIDGE fdb append $mac dev vx10 dst 192.0.2.1 vni $vni \
569			src_vni 5000
570		$BRIDGE fdb append $mac dev vx10 dst 192.0.2.1 vni $vni \
571			port 1111
572		$BRIDGE fdb append $mac dev vx10 dst 192.0.2.2 vni $vni \
573			port 2222
574	done
575}
576
577vxlan_test_flush_by_remote_attributes()
578{
579	local flush_args
580
581	# Reconfigure vx10 with 'external' to get 'src_vni' details in
582	# 'bridge fdb' output
583	$IP link del dev vx10
584	$IP link add name vx10 type vxlan dstport "$VXPORT" external
585
586	# For multicat FDB entries, the VXLAN driver stores a linked list of
587	# remotes for a given key. Verify that only the expected remotes are
588	# flushed.
589	multicast_fdb_entries_add
590
591	## Flush by 3 remote's attributes - destination IP, port and VNI ##
592	flush_args="dst 192.0.2.1 port 1111 vni 2000"
593	fdb_check_n_entries_by_dev_filter vx10 1 $flush_args
594
595	t0_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
596	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
597	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
598
599	fdb_check_n_entries_by_dev_filter vx10 0 $flush_args
600
601	exp_n_entries=$((t0_n_entries - 1))
602	t1_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
603	[[ $t1_n_entries -eq $exp_n_entries ]]
604	log_test $? 0 "Check how many entries were flushed"
605
606	## Flush by 2 remote's attributes - destination IP and port ##
607	flush_args="dst 192.0.2.2 port 2222"
608
609	fdb_check_n_entries_by_dev_filter vx10 2 $flush_args
610
611	t0_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
612	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
613	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
614
615	fdb_check_n_entries_by_dev_filter vx10 0 $flush_args
616
617	exp_n_entries=$((t0_n_entries - 2))
618	t1_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
619	[[ $t1_n_entries -eq $exp_n_entries ]]
620	log_test $? 0 "Check how many entries were flushed"
621
622	## Flush by source VNI, which is not remote's attribute and VNI ##
623	flush_args="vni 3000 src_vni 5000"
624
625	fdb_check_n_entries_by_dev_filter vx10 1 $flush_args
626
627	t0_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
628	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
629	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
630
631	fdb_check_n_entries_by_dev_filter vx10 0 $flush_args
632
633	exp_n_entries=$((t0_n_entries -1))
634	t1_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
635	[[ $t1_n_entries -eq $exp_n_entries ]]
636	log_test $? 0 "Check how many entries were flushed"
637
638	# Flush by 1 remote's attribute - destination IP ##
639	flush_args="dst 192.0.2.1"
640
641	fdb_check_n_entries_by_dev_filter vx10 2 $flush_args
642
643	t0_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
644	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
645	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
646
647	fdb_check_n_entries_by_dev_filter vx10 0 $flush_args
648
649	exp_n_entries=$((t0_n_entries -2))
650	t1_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
651	[[ $t1_n_entries -eq $exp_n_entries ]]
652	log_test $? 0 "Check how many entries were flushed"
653}
654
655bridge_test_flush_by_dev()
656{
657	local dst_ip=192.0.2.1
658	local br0_n_ent_t0=$($BRIDGE fdb show dev br0 | wc -l)
659	local br1_n_ent_t0=$($BRIDGE fdb show dev br1 | wc -l)
660
661	fdb_add_mac_pool_1 br0 dst $dst_ip
662	fdb_add_mac_pool_2 br1 dst $dst_ip
663
664	# Each 'fdb add' command adds one extra entry in the bridge with the
665	# default vlan.
666	local exp_br0_n_ent=$(($br0_n_ent_t0 + 2 * $mac_pool_1_len))
667	local exp_br1_n_ent=$(($br1_n_ent_t0 + 2 * $mac_pool_2_len))
668
669	fdb_check_n_entries_by_dev_filter br0 $exp_br0_n_ent
670	fdb_check_n_entries_by_dev_filter br1 $exp_br1_n_ent
671
672	run_cmd "$BRIDGE fdb flush dev br0"
673	log_test $? 0 "Flush FDB by dev br0"
674
675	# The default entry should not be flushed
676	fdb_check_n_entries_by_dev_filter br0 1
677	log_test $? 0 "Flush FDB by dev br0 - test br0 entries"
678
679	fdb_check_n_entries_by_dev_filter br1 $exp_br1_n_ent
680	log_test $? 0 "Flush FDB by dev br0 - test br1 entries"
681}
682
683bridge_test_flush_by_vlan()
684{
685	local vlan_1=10
686	local vlan_2=20
687	local vlan_1_ent_t0
688	local vlan_2_ent_t0
689
690	$BRIDGE vlan add vid $vlan_1 dev br0 self
691	$BRIDGE vlan add vid $vlan_2 dev br0 self
692
693	vlan_1_ent_t0=$($BRIDGE fdb show dev br0 | grep "vlan $vlan_1" | wc -l)
694	vlan_2_ent_t0=$($BRIDGE fdb show dev br0 | grep "vlan $vlan_2" | wc -l)
695
696	fdb_add_mac_pool_1 br0 vlan $vlan_1
697	fdb_add_mac_pool_2 br0 vlan $vlan_2
698
699	local exp_vlan_1_ent=$(($vlan_1_ent_t0 + $mac_pool_1_len))
700	local exp_vlan_2_ent=$(($vlan_2_ent_t0 + $mac_pool_2_len))
701
702	fdb_check_n_entries_by_dev_filter br0 $exp_vlan_1_ent vlan $vlan_1
703	fdb_check_n_entries_by_dev_filter br0 $exp_vlan_2_ent vlan $vlan_2
704
705	run_cmd "$BRIDGE fdb flush dev br0 vlan $vlan_1"
706	log_test $? 0 "Flush FDB by dev br0 and vlan $vlan_1"
707
708	fdb_check_n_entries_by_dev_filter br0 0 vlan $vlan_1
709	log_test $? 0 "Test entries with vlan $vlan_1"
710
711	fdb_check_n_entries_by_dev_filter br0 $exp_vlan_2_ent vlan $vlan_2
712	log_test $? 0 "Test entries with vlan $vlan_2"
713}
714
715bridge_vxlan_test_flush()
716{
717	local vlan_1=10
718	local dst_ip=192.0.2.1
719
720	$IP link set dev vx10 master br0
721	$BRIDGE vlan add vid $vlan_1 dev br0 self
722	$BRIDGE vlan add vid $vlan_1 dev vx10
723
724	fdb_add_mac_pool_1 vx10 vni 3000 dst $dst_ip self master
725
726	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len vlan $vlan_1
727	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len vni 3000
728
729	# Such command should fail in VXLAN driver as vlan is not supported,
730	# but the command should flush the entries in the bridge
731	run_cmd "$BRIDGE fdb flush dev vx10 vlan $vlan_1 master self"
732	log_test $? 255 \
733		"Flush FDB by dev vx10, vlan $vlan_1, master and self"
734
735	fdb_check_n_entries_by_dev_filter vx10 0 vlan $vlan_1
736	log_test $? 0 "Test entries with vlan $vlan_1"
737
738	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip
739	log_test $? 0 "Test entries with dst $dst_ip"
740}
741
742setup()
743{
744	setup_ns NS
745	IP="ip -netns ${NS}"
746	BRIDGE="bridge -netns ${NS}"
747
748	$IP link add name vx10 type vxlan id 1000 dstport "$VXPORT"
749	$IP link add name vx20 type vxlan id 2000 dstport "$VXPORT"
750
751	$IP link add br0 type bridge vlan_filtering 1
752	$IP link add br1 type bridge vlan_filtering 1
753}
754
755cleanup()
756{
757	$IP link del dev br1
758	$IP link del dev br0
759
760	$IP link del dev vx20
761	$IP link del dev vx10
762
763	cleanup_ns ${NS}
764}
765
766################################################################################
767# main
768
769while getopts :t:pPhvw: o
770do
771	case $o in
772		t) TESTS=$OPTARG;;
773		p) PAUSE_ON_FAIL=yes;;
774		P) PAUSE=yes;;
775		v) VERBOSE=$(($VERBOSE + 1));;
776		w) PING_TIMEOUT=$OPTARG;;
777		h) usage; exit 0;;
778		*) usage; exit 1;;
779	esac
780done
781
782# make sure we don't pause twice
783[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
784
785if [ "$(id -u)" -ne 0 ];then
786	echo "SKIP: Need root privileges"
787	exit $ksft_skip;
788fi
789
790if [ ! -x "$(command -v ip)" ]; then
791	echo "SKIP: Could not run test without ip tool"
792	exit $ksft_skip
793fi
794
795# Check a flag that is added to flush command as part of VXLAN flush support
796bridge fdb help 2>&1 | grep -q "\[no\]router"
797if [ $? -ne 0 ]; then
798	echo "SKIP: iproute2 too old, missing flush command for VXLAN"
799	exit $ksft_skip
800fi
801
802ip link add dev vx10 type vxlan id 1000 2> /dev/null
803out=$(bridge fdb flush dev vx10 2>&1 | grep -q "Operation not supported")
804if [ $? -eq 0 ]; then
805	echo "SKIP: kernel lacks vxlan flush support"
806	exit $ksft_skip
807fi
808ip link del dev vx10
809
810for t in $TESTS
811do
812	setup; $t; cleanup;
813done
814