1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# +-----------------------+                          +------------------------+
5# | H1 (vrf)              |                          | H2 (vrf)               |
6# | + $h1.10              |                          | + $h2.10               |
7# | | 192.0.2.1/28        |                          | | 192.0.2.2/28         |
8# | | 2001:db8:1::1/64    |                          | | 2001:db8:1::2/64     |
9# | |                     |                          | |                      |
10# | |  + $h1.20           |                          | |  + $h2.20            |
11# | \  | 198.51.100.1/24  |                          | \  | 198.51.100.2/24   |
12# |  \ | 2001:db8:2::1/64 |                          |  \ | 2001:db8:2::2/64  |
13# |   \|                  |                          |   \|                   |
14# |    + $h1              |                          |    + $h2               |
15# +----|------------------+                          +----|-------------------+
16#      |                                                  |
17# +----|--------------------------------------------------|-------------------+
18# | SW |                                                  |                   |
19# | +--|--------------------------------------------------|-----------------+ |
20# | |  + $swp1                   BR0 (802.1q)             + $swp2           | |
21# | |     vid 10                                             vid 10         | |
22# | |     vid 20                                             vid 20         | |
23# | |                                                                       | |
24# | +-----------------------------------------------------------------------+ |
25# +---------------------------------------------------------------------------+
26
27ALL_TESTS="
28	test_8021d
29	test_8021q
30	test_8021qvs
31"
32
33NUM_NETIFS=4
34source lib.sh
35source tc_common.sh
36
37h1_create()
38{
39	simple_if_init $h1
40	vlan_create $h1 10 v$h1 192.0.2.1/28 2001:db8:1::1/64
41	vlan_create $h1 20 v$h1 198.51.100.1/24 2001:db8:2::1/64
42}
43
44h1_destroy()
45{
46	vlan_destroy $h1 20
47	vlan_destroy $h1 10
48	simple_if_fini $h1
49}
50
51h2_create()
52{
53	simple_if_init $h2
54	vlan_create $h2 10 v$h2 192.0.2.2/28
55	vlan_create $h2 20 v$h2 198.51.100.2/24
56}
57
58h2_destroy()
59{
60	vlan_destroy $h2 20
61	vlan_destroy $h2 10
62	simple_if_fini $h2
63}
64
65switch_create_8021d()
66{
67	log_info "802.1d tests"
68
69	ip link add name br0 type bridge vlan_filtering 0 \
70		mcast_snooping 1 \
71		mcast_igmp_version 3 mcast_mld_version 2
72	ip link set dev br0 up
73
74	ip link set dev $swp1 master br0
75	ip link set dev $swp1 up
76	bridge link set dev $swp1 fastleave on
77
78	ip link set dev $swp2 master br0
79	ip link set dev $swp2 up
80}
81
82switch_create_8021q()
83{
84	local br_flags=$1; shift
85
86	log_info "802.1q $br_flags${br_flags:+ }tests"
87
88	ip link add name br0 type bridge vlan_filtering 1 vlan_default_pvid 0 \
89		mcast_snooping 1 $br_flags \
90		mcast_igmp_version 3 mcast_mld_version 2
91	bridge vlan add vid 10 dev br0 self
92	bridge vlan add vid 20 dev br0 self
93	ip link set dev br0 up
94
95	ip link set dev $swp1 master br0
96	ip link set dev $swp1 up
97	bridge link set dev $swp1 fastleave on
98	bridge vlan add vid 10 dev $swp1
99	bridge vlan add vid 20 dev $swp1
100
101	ip link set dev $swp2 master br0
102	ip link set dev $swp2 up
103	bridge vlan add vid 10 dev $swp2
104	bridge vlan add vid 20 dev $swp2
105}
106
107switch_create_8021qvs()
108{
109	switch_create_8021q "mcast_vlan_snooping 1"
110	bridge vlan global set dev br0 vid 10 mcast_igmp_version 3
111	bridge vlan global set dev br0 vid 10 mcast_mld_version 2
112	bridge vlan global set dev br0 vid 20 mcast_igmp_version 3
113	bridge vlan global set dev br0 vid 20 mcast_mld_version 2
114}
115
116switch_destroy()
117{
118	ip link set dev $swp2 down
119	ip link set dev $swp2 nomaster
120
121	ip link set dev $swp1 down
122	ip link set dev $swp1 nomaster
123
124	ip link set dev br0 down
125	ip link del dev br0
126}
127
128setup_prepare()
129{
130	h1=${NETIFS[p1]}
131	swp1=${NETIFS[p2]}
132
133	swp2=${NETIFS[p3]}
134	h2=${NETIFS[p4]}
135
136	vrf_prepare
137	forwarding_enable
138
139	h1_create
140	h2_create
141}
142
143cleanup()
144{
145	pre_cleanup
146
147	switch_destroy 2>/dev/null
148	h2_destroy
149	h1_destroy
150
151	forwarding_restore
152	vrf_cleanup
153}
154
155cfg_src_list()
156{
157	local IPs=("$@")
158	local IPstr=$(echo ${IPs[@]} | tr '[:space:]' , | sed 's/,$//')
159
160	echo ${IPstr:+source_list }${IPstr}
161}
162
163cfg_group_op()
164{
165	local op=$1; shift
166	local locus=$1; shift
167	local GRP=$1; shift
168	local state=$1; shift
169	local IPs=("$@")
170
171	local source_list=$(cfg_src_list ${IPs[@]})
172
173	# Everything besides `bridge mdb' uses the "dev X vid Y" syntax,
174	# so we use it here as well and convert.
175	local br_locus=$(echo "$locus" | sed 's/^dev /port /')
176
177	bridge mdb $op dev br0 $br_locus grp $GRP $state \
178	       filter_mode include $source_list
179}
180
181cfg4_entries_op()
182{
183	local op=$1; shift
184	local locus=$1; shift
185	local state=$1; shift
186	local n=$1; shift
187	local grp=${1:-1}; shift
188
189	local GRP=239.1.1.${grp}
190	local IPs=$(seq -f 192.0.2.%g 1 $((n - 1)))
191	cfg_group_op "$op" "$locus" "$GRP" "$state" ${IPs[@]}
192}
193
194cfg4_entries_add()
195{
196	cfg4_entries_op add "$@"
197}
198
199cfg4_entries_del()
200{
201	cfg4_entries_op del "$@"
202}
203
204cfg6_entries_op()
205{
206	local op=$1; shift
207	local locus=$1; shift
208	local state=$1; shift
209	local n=$1; shift
210	local grp=${1:-1}; shift
211
212	local GRP=ff0e::${grp}
213	local IPs=$(printf "2001:db8:1::%x\n" $(seq 1 $((n - 1))))
214	cfg_group_op "$op" "$locus" "$GRP" "$state" ${IPs[@]}
215}
216
217cfg6_entries_add()
218{
219	cfg6_entries_op add "$@"
220}
221
222cfg6_entries_del()
223{
224	cfg6_entries_op del "$@"
225}
226
227locus_dev_peer()
228{
229	local dev_kw=$1; shift
230	local dev=$1; shift
231	local vid_kw=$1; shift
232	local vid=$1; shift
233
234	echo "$h1.${vid:-10}"
235}
236
237locus_dev()
238{
239	local dev_kw=$1; shift
240	local dev=$1; shift
241
242	echo $dev
243}
244
245ctl4_entries_add()
246{
247	local locus=$1; shift
248	local state=$1; shift
249	local n=$1; shift
250	local grp=${1:-1}; shift
251
252	local IPs=$(seq -f 192.0.2.%g 1 $((n - 1)))
253	local peer=$(locus_dev_peer $locus)
254	local GRP=239.1.1.${grp}
255	local dmac=01:00:5e:01:01:$(printf "%02x" $grp)
256	$MZ $peer -a own -b $dmac -c 1 -A 192.0.2.1 -B $GRP \
257		-t ip proto=2,p=$(igmpv3_is_in_get $GRP $IPs) -q
258	sleep 1
259
260	local nn=$(bridge mdb show dev br0 | grep $GRP | wc -l)
261	if ((nn != n)); then
262		echo mcast_max_groups > /dev/stderr
263		false
264	fi
265}
266
267ctl4_entries_del()
268{
269	local locus=$1; shift
270	local state=$1; shift
271	local n=$1; shift
272	local grp=${1:-1}; shift
273
274	local peer=$(locus_dev_peer $locus)
275	local GRP=239.1.1.${grp}
276	local dmac=01:00:5e:00:00:02
277	$MZ $peer -a own -b $dmac -c 1 -A 192.0.2.1 -B 224.0.0.2 \
278		-t ip proto=2,p=$(igmpv2_leave_get $GRP) -q
279	sleep 1
280	! bridge mdb show dev br0 | grep -q $GRP
281}
282
283ctl6_entries_add()
284{
285	local locus=$1; shift
286	local state=$1; shift
287	local n=$1; shift
288	local grp=${1:-1}; shift
289
290	local IPs=$(printf "2001:db8:1::%x\n" $(seq 1 $((n - 1))))
291	local peer=$(locus_dev_peer $locus)
292	local SIP=fe80::1
293	local GRP=ff0e::${grp}
294	local dmac=33:33:00:00:00:$(printf "%02x" $grp)
295	local p=$(mldv2_is_in_get $SIP $GRP $IPs)
296	$MZ -6 $peer -a own -b $dmac -c 1 -A $SIP -B $GRP \
297		-t ip hop=1,next=0,p="$p" -q
298	sleep 1
299
300	local nn=$(bridge mdb show dev br0 | grep $GRP | wc -l)
301	if ((nn != n)); then
302		echo mcast_max_groups > /dev/stderr
303		false
304	fi
305}
306
307ctl6_entries_del()
308{
309	local locus=$1; shift
310	local state=$1; shift
311	local n=$1; shift
312	local grp=${1:-1}; shift
313
314	local peer=$(locus_dev_peer $locus)
315	local SIP=fe80::1
316	local GRP=ff0e::${grp}
317	local dmac=33:33:00:00:00:$(printf "%02x" $grp)
318	local p=$(mldv1_done_get $SIP $GRP)
319	$MZ -6 $peer -a own -b $dmac -c 1 -A $SIP -B $GRP \
320		-t ip hop=1,next=0,p="$p" -q
321	sleep 1
322	! bridge mdb show dev br0 | grep -q $GRP
323}
324
325bridge_maxgroups_errmsg_check_cfg()
326{
327	local msg=$1; shift
328	local needle=$1; shift
329
330	echo "$msg" | grep -q mcast_max_groups
331	check_err $? "Adding MDB entries failed for the wrong reason: $msg"
332}
333
334bridge_maxgroups_errmsg_check_cfg4()
335{
336	bridge_maxgroups_errmsg_check_cfg "$@"
337}
338
339bridge_maxgroups_errmsg_check_cfg6()
340{
341	bridge_maxgroups_errmsg_check_cfg "$@"
342}
343
344bridge_maxgroups_errmsg_check_ctl4()
345{
346	:
347}
348
349bridge_maxgroups_errmsg_check_ctl6()
350{
351	:
352}
353
354bridge_port_ngroups_get()
355{
356	local locus=$1; shift
357
358	bridge -j -d link show $locus |
359	    jq '.[].mcast_n_groups'
360}
361
362bridge_port_maxgroups_get()
363{
364	local locus=$1; shift
365
366	bridge -j -d link show $locus |
367	    jq '.[].mcast_max_groups'
368}
369
370bridge_port_maxgroups_set()
371{
372	local locus=$1; shift
373	local max=$1; shift
374
375	bridge link set dev $(locus_dev $locus) mcast_max_groups $max
376}
377
378bridge_port_vlan_ngroups_get()
379{
380	local locus=$1; shift
381
382	bridge -j -d vlan show $locus |
383	    jq '.[].vlans[].mcast_n_groups'
384}
385
386bridge_port_vlan_maxgroups_get()
387{
388	local locus=$1; shift
389
390	bridge -j -d vlan show $locus |
391	    jq '.[].vlans[].mcast_max_groups'
392}
393
394bridge_port_vlan_maxgroups_set()
395{
396	local locus=$1; shift
397	local max=$1; shift
398
399	bridge vlan set $locus mcast_max_groups $max
400}
401
402test_ngroups_reporting()
403{
404	local CFG=$1; shift
405	local context=$1; shift
406	local locus=$1; shift
407
408	RET=0
409
410	local n0=$(bridge_${context}_ngroups_get "$locus")
411	${CFG}_entries_add "$locus" temp 5
412	check_err $? "Couldn't add MDB entries"
413	local n1=$(bridge_${context}_ngroups_get "$locus")
414
415	((n1 == n0 + 5))
416	check_err $? "Number of groups was $n0, now is $n1, but $((n0 + 5)) expected"
417
418	${CFG}_entries_del "$locus" temp 5
419	check_err $? "Couldn't delete MDB entries"
420	local n2=$(bridge_${context}_ngroups_get "$locus")
421
422	((n2 == n0))
423	check_err $? "Number of groups was $n0, now is $n2, but should be back to $n0"
424
425	log_test "$CFG: $context: ngroups reporting"
426}
427
428test_8021d_ngroups_reporting_cfg4()
429{
430	test_ngroups_reporting cfg4 port "dev $swp1"
431}
432
433test_8021d_ngroups_reporting_ctl4()
434{
435	test_ngroups_reporting ctl4 port "dev $swp1"
436}
437
438test_8021d_ngroups_reporting_cfg6()
439{
440	test_ngroups_reporting cfg6 port "dev $swp1"
441}
442
443test_8021d_ngroups_reporting_ctl6()
444{
445	test_ngroups_reporting ctl6 port "dev $swp1"
446}
447
448test_8021q_ngroups_reporting_cfg4()
449{
450	test_ngroups_reporting cfg4 port "dev $swp1 vid 10"
451}
452
453test_8021q_ngroups_reporting_ctl4()
454{
455	test_ngroups_reporting ctl4 port "dev $swp1 vid 10"
456}
457
458test_8021q_ngroups_reporting_cfg6()
459{
460	test_ngroups_reporting cfg6 port "dev $swp1 vid 10"
461}
462
463test_8021q_ngroups_reporting_ctl6()
464{
465	test_ngroups_reporting ctl6 port "dev $swp1 vid 10"
466}
467
468test_8021qvs_ngroups_reporting_cfg4()
469{
470	test_ngroups_reporting cfg4 port_vlan "dev $swp1 vid 10"
471}
472
473test_8021qvs_ngroups_reporting_ctl4()
474{
475	test_ngroups_reporting ctl4 port_vlan "dev $swp1 vid 10"
476}
477
478test_8021qvs_ngroups_reporting_cfg6()
479{
480	test_ngroups_reporting cfg6 port_vlan "dev $swp1 vid 10"
481}
482
483test_8021qvs_ngroups_reporting_ctl6()
484{
485	test_ngroups_reporting ctl6 port_vlan "dev $swp1 vid 10"
486}
487
488test_ngroups_cross_vlan()
489{
490	local CFG=$1; shift
491
492	local locus1="dev $swp1 vid 10"
493	local locus2="dev $swp1 vid 20"
494
495	RET=0
496
497	local n10=$(bridge_port_vlan_ngroups_get "$locus1")
498	local n20=$(bridge_port_vlan_ngroups_get "$locus2")
499	${CFG}_entries_add "$locus1" temp 5 111
500	check_err $? "Couldn't add MDB entries to VLAN 10"
501	local n11=$(bridge_port_vlan_ngroups_get "$locus1")
502	local n21=$(bridge_port_vlan_ngroups_get "$locus2")
503
504	((n11 == n10 + 5))
505	check_err $? "Number of groups at VLAN 10 was $n10, now is $n11, but 5 entries added on VLAN 10, $((n10 + 5)) expected"
506
507	((n21 == n20))
508	check_err $? "Number of groups at VLAN 20 was $n20, now is $n21, but no change expected on VLAN 20"
509
510	${CFG}_entries_add "$locus2" temp 5 112
511	check_err $? "Couldn't add MDB entries to VLAN 20"
512	local n12=$(bridge_port_vlan_ngroups_get "$locus1")
513	local n22=$(bridge_port_vlan_ngroups_get "$locus2")
514
515	((n12 == n11))
516	check_err $? "Number of groups at VLAN 10 was $n11, now is $n12, but no change expected on VLAN 10"
517
518	((n22 == n21 + 5))
519	check_err $? "Number of groups at VLAN 20 was $n21, now is $n22, but 5 entries added on VLAN 20, $((n21 + 5)) expected"
520
521	${CFG}_entries_del "$locus1" temp 5 111
522	check_err $? "Couldn't delete MDB entries from VLAN 10"
523	${CFG}_entries_del "$locus2" temp 5 112
524	check_err $? "Couldn't delete MDB entries from VLAN 20"
525	local n13=$(bridge_port_vlan_ngroups_get "$locus1")
526	local n23=$(bridge_port_vlan_ngroups_get "$locus2")
527
528	((n13 == n10))
529	check_err $? "Number of groups at VLAN 10 was $n10, now is $n13, but should be back to $n10"
530
531	((n23 == n20))
532	check_err $? "Number of groups at VLAN 20 was $n20, now is $n23, but should be back to $n20"
533
534	log_test "$CFG: port_vlan: isolation of port and per-VLAN ngroups"
535}
536
537test_8021qvs_ngroups_cross_vlan_cfg4()
538{
539	test_ngroups_cross_vlan cfg4
540}
541
542test_8021qvs_ngroups_cross_vlan_ctl4()
543{
544	test_ngroups_cross_vlan ctl4
545}
546
547test_8021qvs_ngroups_cross_vlan_cfg6()
548{
549	test_ngroups_cross_vlan cfg6
550}
551
552test_8021qvs_ngroups_cross_vlan_ctl6()
553{
554	test_ngroups_cross_vlan ctl6
555}
556
557test_maxgroups_zero()
558{
559	local CFG=$1; shift
560	local context=$1; shift
561	local locus=$1; shift
562
563	RET=0
564	local max
565
566	max=$(bridge_${context}_maxgroups_get "$locus")
567	((max == 0))
568	check_err $? "Max groups on $locus should be 0, but $max reported"
569
570	bridge_${context}_maxgroups_set "$locus" 100
571	check_err $? "Failed to set max to 100"
572	max=$(bridge_${context}_maxgroups_get "$locus")
573	((max == 100))
574	check_err $? "Max groups expected to be 100, but $max reported"
575
576	bridge_${context}_maxgroups_set "$locus" 0
577	check_err $? "Couldn't set maximum to 0"
578
579	# Test that setting 0 explicitly still serves as infinity.
580	${CFG}_entries_add "$locus" temp 5
581	check_err $? "Adding 5 MDB entries failed but should have passed"
582	${CFG}_entries_del "$locus" temp 5
583	check_err $? "Couldn't delete MDB entries"
584
585	log_test "$CFG: $context maxgroups: reporting and treatment of 0"
586}
587
588test_8021d_maxgroups_zero_cfg4()
589{
590	test_maxgroups_zero cfg4 port "dev $swp1"
591}
592
593test_8021d_maxgroups_zero_ctl4()
594{
595	test_maxgroups_zero ctl4 port "dev $swp1"
596}
597
598test_8021d_maxgroups_zero_cfg6()
599{
600	test_maxgroups_zero cfg6 port "dev $swp1"
601}
602
603test_8021d_maxgroups_zero_ctl6()
604{
605	test_maxgroups_zero ctl6 port "dev $swp1"
606}
607
608test_8021q_maxgroups_zero_cfg4()
609{
610	test_maxgroups_zero cfg4 port "dev $swp1 vid 10"
611}
612
613test_8021q_maxgroups_zero_ctl4()
614{
615	test_maxgroups_zero ctl4 port "dev $swp1 vid 10"
616}
617
618test_8021q_maxgroups_zero_cfg6()
619{
620	test_maxgroups_zero cfg6 port "dev $swp1 vid 10"
621}
622
623test_8021q_maxgroups_zero_ctl6()
624{
625	test_maxgroups_zero ctl6 port "dev $swp1 vid 10"
626}
627
628test_8021qvs_maxgroups_zero_cfg4()
629{
630	test_maxgroups_zero cfg4 port_vlan "dev $swp1 vid 10"
631}
632
633test_8021qvs_maxgroups_zero_ctl4()
634{
635	test_maxgroups_zero ctl4 port_vlan "dev $swp1 vid 10"
636}
637
638test_8021qvs_maxgroups_zero_cfg6()
639{
640	test_maxgroups_zero cfg6 port_vlan "dev $swp1 vid 10"
641}
642
643test_8021qvs_maxgroups_zero_ctl6()
644{
645	test_maxgroups_zero ctl6 port_vlan "dev $swp1 vid 10"
646}
647
648test_maxgroups_zero_cross_vlan()
649{
650	local CFG=$1; shift
651
652	local locus0="dev $swp1"
653	local locus1="dev $swp1 vid 10"
654	local locus2="dev $swp1 vid 20"
655	local max
656
657	RET=0
658
659	bridge_port_vlan_maxgroups_set "$locus1" 100
660	check_err $? "$locus1: Failed to set max to 100"
661
662	max=$(bridge_port_maxgroups_get "$locus0")
663	((max == 0))
664	check_err $? "$locus0: Max groups expected to be 0, but $max reported"
665
666	max=$(bridge_port_vlan_maxgroups_get "$locus2")
667	((max == 0))
668	check_err $? "$locus2: Max groups expected to be 0, but $max reported"
669
670	bridge_port_vlan_maxgroups_set "$locus2" 100
671	check_err $? "$locus2: Failed to set max to 100"
672
673	max=$(bridge_port_maxgroups_get "$locus0")
674	((max == 0))
675	check_err $? "$locus0: Max groups expected to be 0, but $max reported"
676
677	max=$(bridge_port_vlan_maxgroups_get "$locus2")
678	((max == 100))
679	check_err $? "$locus2: Max groups expected to be 100, but $max reported"
680
681	bridge_port_maxgroups_set "$locus0" 100
682	check_err $? "$locus0: Failed to set max to 100"
683
684	max=$(bridge_port_maxgroups_get "$locus0")
685	((max == 100))
686	check_err $? "$locus0: Max groups expected to be 100, but $max reported"
687
688	max=$(bridge_port_vlan_maxgroups_get "$locus2")
689	((max == 100))
690	check_err $? "$locus2: Max groups expected to be 100, but $max reported"
691
692	bridge_port_vlan_maxgroups_set "$locus1" 0
693	check_err $? "$locus1: Failed to set max to 0"
694
695	max=$(bridge_port_maxgroups_get "$locus0")
696	((max == 100))
697	check_err $? "$locus0: Max groups expected to be 100, but $max reported"
698
699	max=$(bridge_port_vlan_maxgroups_get "$locus2")
700	((max == 100))
701	check_err $? "$locus2: Max groups expected to be 100, but $max reported"
702
703	bridge_port_vlan_maxgroups_set "$locus2" 0
704	check_err $? "$locus2: Failed to set max to 0"
705
706	max=$(bridge_port_maxgroups_get "$locus0")
707	((max == 100))
708	check_err $? "$locus0: Max groups expected to be 100, but $max reported"
709
710	max=$(bridge_port_vlan_maxgroups_get "$locus2")
711	((max == 0))
712	check_err $? "$locus2: Max groups expected to be 0 but $max reported"
713
714	bridge_port_maxgroups_set "$locus0" 0
715	check_err $? "$locus0: Failed to set max to 0"
716
717	max=$(bridge_port_maxgroups_get "$locus0")
718	((max == 0))
719	check_err $? "$locus0: Max groups expected to be 0, but $max reported"
720
721	max=$(bridge_port_vlan_maxgroups_get "$locus2")
722	((max == 0))
723	check_err $? "$locus2: Max groups expected to be 0, but $max reported"
724
725	log_test "$CFG: port_vlan maxgroups: isolation of port and per-VLAN maximums"
726}
727
728test_8021qvs_maxgroups_zero_cross_vlan_cfg4()
729{
730	test_maxgroups_zero_cross_vlan cfg4
731}
732
733test_8021qvs_maxgroups_zero_cross_vlan_ctl4()
734{
735	test_maxgroups_zero_cross_vlan ctl4
736}
737
738test_8021qvs_maxgroups_zero_cross_vlan_cfg6()
739{
740	test_maxgroups_zero_cross_vlan cfg6
741}
742
743test_8021qvs_maxgroups_zero_cross_vlan_ctl6()
744{
745	test_maxgroups_zero_cross_vlan ctl6
746}
747
748test_maxgroups_too_low()
749{
750	local CFG=$1; shift
751	local context=$1; shift
752	local locus=$1; shift
753
754	RET=0
755
756	local n=$(bridge_${context}_ngroups_get "$locus")
757	local msg
758
759	${CFG}_entries_add "$locus" temp 5 111
760	check_err $? "$locus: Couldn't add MDB entries"
761
762	bridge_${context}_maxgroups_set "$locus" $((n+2))
763	check_err $? "$locus: Setting maxgroups to $((n+2)) failed"
764
765	msg=$(${CFG}_entries_add "$locus" temp 2 112 2>&1)
766	check_fail $? "$locus: Adding more entries passed when max<n"
767	bridge_maxgroups_errmsg_check_cfg "$msg"
768
769	${CFG}_entries_del "$locus" temp 5 111
770	check_err $? "$locus: Couldn't delete MDB entries"
771
772	${CFG}_entries_add "$locus" temp 2 112
773	check_err $? "$locus: Adding more entries failed"
774
775	${CFG}_entries_del "$locus" temp 2 112
776	check_err $? "$locus: Deleting more entries failed"
777
778	bridge_${context}_maxgroups_set "$locus" 0
779	check_err $? "$locus: Couldn't set maximum to 0"
780
781	log_test "$CFG: $context maxgroups: configure below ngroups"
782}
783
784test_8021d_maxgroups_too_low_cfg4()
785{
786	test_maxgroups_too_low cfg4 port "dev $swp1"
787}
788
789test_8021d_maxgroups_too_low_ctl4()
790{
791	test_maxgroups_too_low ctl4 port "dev $swp1"
792}
793
794test_8021d_maxgroups_too_low_cfg6()
795{
796	test_maxgroups_too_low cfg6 port "dev $swp1"
797}
798
799test_8021d_maxgroups_too_low_ctl6()
800{
801	test_maxgroups_too_low ctl6 port "dev $swp1"
802}
803
804test_8021q_maxgroups_too_low_cfg4()
805{
806	test_maxgroups_too_low cfg4 port "dev $swp1 vid 10"
807}
808
809test_8021q_maxgroups_too_low_ctl4()
810{
811	test_maxgroups_too_low ctl4 port "dev $swp1 vid 10"
812}
813
814test_8021q_maxgroups_too_low_cfg6()
815{
816	test_maxgroups_too_low cfg6 port "dev $swp1 vid 10"
817}
818
819test_8021q_maxgroups_too_low_ctl6()
820{
821	test_maxgroups_too_low ctl6 port "dev $swp1 vid 10"
822}
823
824test_8021qvs_maxgroups_too_low_cfg4()
825{
826	test_maxgroups_too_low cfg4 port_vlan "dev $swp1 vid 10"
827}
828
829test_8021qvs_maxgroups_too_low_ctl4()
830{
831	test_maxgroups_too_low ctl4 port_vlan "dev $swp1 vid 10"
832}
833
834test_8021qvs_maxgroups_too_low_cfg6()
835{
836	test_maxgroups_too_low cfg6 port_vlan "dev $swp1 vid 10"
837}
838
839test_8021qvs_maxgroups_too_low_ctl6()
840{
841	test_maxgroups_too_low ctl6 port_vlan "dev $swp1 vid 10"
842}
843
844test_maxgroups_too_many_entries()
845{
846	local CFG=$1; shift
847	local context=$1; shift
848	local locus=$1; shift
849
850	RET=0
851
852	local n=$(bridge_${context}_ngroups_get "$locus")
853	local msg
854
855	# Configure a low maximum
856	bridge_${context}_maxgroups_set "$locus" $((n+1))
857	check_err $? "$locus: Couldn't set maximum"
858
859	# Try to add more entries than the configured maximum
860	msg=$(${CFG}_entries_add "$locus" temp 5 2>&1)
861	check_fail $? "Adding 5 MDB entries passed, but should have failed"
862	bridge_maxgroups_errmsg_check_${CFG} "$msg"
863
864	# When adding entries through the control path, as many as possible
865	# get created. That's consistent with the mcast_hash_max behavior.
866	# So there, drop the entries explicitly.
867	if [[ ${CFG%[46]} == ctl ]]; then
868		${CFG}_entries_del "$locus" temp 17 2>&1
869	fi
870
871	local n2=$(bridge_${context}_ngroups_get "$locus")
872	((n2 == n))
873	check_err $? "Number of groups was $n, but after a failed attempt to add MDB entries it changed to $n2"
874
875	bridge_${context}_maxgroups_set "$locus" 0
876	check_err $? "$locus: Couldn't set maximum to 0"
877
878	log_test "$CFG: $context maxgroups: add too many MDB entries"
879}
880
881test_8021d_maxgroups_too_many_entries_cfg4()
882{
883	test_maxgroups_too_many_entries cfg4 port "dev $swp1"
884}
885
886test_8021d_maxgroups_too_many_entries_ctl4()
887{
888	test_maxgroups_too_many_entries ctl4 port "dev $swp1"
889}
890
891test_8021d_maxgroups_too_many_entries_cfg6()
892{
893	test_maxgroups_too_many_entries cfg6 port "dev $swp1"
894}
895
896test_8021d_maxgroups_too_many_entries_ctl6()
897{
898	test_maxgroups_too_many_entries ctl6 port "dev $swp1"
899}
900
901test_8021q_maxgroups_too_many_entries_cfg4()
902{
903	test_maxgroups_too_many_entries cfg4 port "dev $swp1 vid 10"
904}
905
906test_8021q_maxgroups_too_many_entries_ctl4()
907{
908	test_maxgroups_too_many_entries ctl4 port "dev $swp1 vid 10"
909}
910
911test_8021q_maxgroups_too_many_entries_cfg6()
912{
913	test_maxgroups_too_many_entries cfg6 port "dev $swp1 vid 10"
914}
915
916test_8021q_maxgroups_too_many_entries_ctl6()
917{
918	test_maxgroups_too_many_entries ctl6 port "dev $swp1 vid 10"
919}
920
921test_8021qvs_maxgroups_too_many_entries_cfg4()
922{
923	test_maxgroups_too_many_entries cfg4 port_vlan "dev $swp1 vid 10"
924}
925
926test_8021qvs_maxgroups_too_many_entries_ctl4()
927{
928	test_maxgroups_too_many_entries ctl4 port_vlan "dev $swp1 vid 10"
929}
930
931test_8021qvs_maxgroups_too_many_entries_cfg6()
932{
933	test_maxgroups_too_many_entries cfg6 port_vlan "dev $swp1 vid 10"
934}
935
936test_8021qvs_maxgroups_too_many_entries_ctl6()
937{
938	test_maxgroups_too_many_entries ctl6 port_vlan "dev $swp1 vid 10"
939}
940
941test_maxgroups_too_many_cross_vlan()
942{
943	local CFG=$1; shift
944
945	RET=0
946
947	local locus0="dev $swp1"
948	local locus1="dev $swp1 vid 10"
949	local locus2="dev $swp1 vid 20"
950	local n1=$(bridge_port_vlan_ngroups_get "$locus1")
951	local n2=$(bridge_port_vlan_ngroups_get "$locus2")
952	local msg
953
954	if ((n1 > n2)); then
955		local tmp=$n1
956		n1=$n2
957		n2=$tmp
958
959		tmp="$locus1"
960		locus1="$locus2"
961		locus2="$tmp"
962	fi
963
964	# Now 0 <= n1 <= n2.
965	${CFG}_entries_add "$locus2" temp 5 112
966	check_err $? "Couldn't add 5 entries"
967
968	n2=$(bridge_port_vlan_ngroups_get "$locus2")
969	# Now 0 <= n1 < n2-1.
970
971	# Setting locus1'maxgroups to n2-1 should pass. The number is
972	# smaller than both the absolute number of MDB entries, and in
973	# particular than number of locus2's number of entries, but it is
974	# large enough to cover locus1's entries. Thus we check that
975	# individual VLAN's ngroups are independent.
976	bridge_port_vlan_maxgroups_set "$locus1" $((n2-1))
977	check_err $? "Setting ${locus1}'s maxgroups to $((n2-1)) failed"
978
979	msg=$(${CFG}_entries_add "$locus1" temp $n2 111 2>&1)
980	check_fail $? "$locus1: Adding $n2 MDB entries passed, but should have failed"
981	bridge_maxgroups_errmsg_check_${CFG} "$msg"
982
983	bridge_port_maxgroups_set "$locus0" $((n1 + n2 + 2))
984	check_err $? "$locus0: Couldn't set maximum"
985
986	msg=$(${CFG}_entries_add "$locus1" temp 5 111 2>&1)
987	check_fail $? "$locus1: Adding 5 MDB entries passed, but should have failed"
988	bridge_maxgroups_errmsg_check_${CFG} "$msg"
989
990	# IGMP/MLD packets can cause several entries to be added, before
991	# the maximum is hit and the rest is then bounced. Remove what was
992	# committed, if anything.
993	${CFG}_entries_del "$locus1" temp 5 111 2>/dev/null
994
995	${CFG}_entries_add "$locus1" temp 2 111
996	check_err $? "$locus1: Adding 2 MDB entries failed, but should have passed"
997
998	${CFG}_entries_del "$locus1" temp 2 111
999	check_err $? "Couldn't delete MDB entries"
1000
1001	${CFG}_entries_del "$locus2" temp 5 112
1002	check_err $? "Couldn't delete MDB entries"
1003
1004	bridge_port_vlan_maxgroups_set "$locus1" 0
1005	check_err $? "$locus1: Couldn't set maximum to 0"
1006
1007	bridge_port_maxgroups_set "$locus0" 0
1008	check_err $? "$locus0: Couldn't set maximum to 0"
1009
1010	log_test "$CFG: port_vlan maxgroups: isolation of port and per-VLAN ngroups"
1011}
1012
1013test_8021qvs_maxgroups_too_many_cross_vlan_cfg4()
1014{
1015	test_maxgroups_too_many_cross_vlan cfg4
1016}
1017
1018test_8021qvs_maxgroups_too_many_cross_vlan_ctl4()
1019{
1020	test_maxgroups_too_many_cross_vlan ctl4
1021}
1022
1023test_8021qvs_maxgroups_too_many_cross_vlan_cfg6()
1024{
1025	test_maxgroups_too_many_cross_vlan cfg6
1026}
1027
1028test_8021qvs_maxgroups_too_many_cross_vlan_ctl6()
1029{
1030	test_maxgroups_too_many_cross_vlan ctl6
1031}
1032
1033test_vlan_attributes()
1034{
1035	local locus=$1; shift
1036	local expect=$1; shift
1037
1038	RET=0
1039
1040	local max=$(bridge_port_vlan_maxgroups_get "$locus")
1041	local n=$(bridge_port_vlan_ngroups_get "$locus")
1042
1043	eval "[[ $max $expect ]]"
1044	check_err $? "$locus: maxgroups attribute expected to be $expect, but was $max"
1045
1046	eval "[[ $n $expect ]]"
1047	check_err $? "$locus: ngroups attribute expected to be $expect, but was $n"
1048
1049	log_test "port_vlan: presence of ngroups and maxgroups attributes"
1050}
1051
1052test_8021q_vlan_attributes()
1053{
1054	test_vlan_attributes "dev $swp1 vid 10" "== null"
1055}
1056
1057test_8021qvs_vlan_attributes()
1058{
1059	test_vlan_attributes "dev $swp1 vid 10" "-ge 0"
1060}
1061
1062test_toggle_vlan_snooping()
1063{
1064	local mode=$1; shift
1065
1066	RET=0
1067
1068	local CFG=cfg4
1069	local context=port_vlan
1070	local locus="dev $swp1 vid 10"
1071
1072	${CFG}_entries_add "$locus" $mode 5
1073	check_err $? "Couldn't add MDB entries"
1074
1075	bridge_${context}_maxgroups_set "$locus" 100
1076	check_err $? "Failed to set max to 100"
1077
1078	ip link set dev br0 type bridge mcast_vlan_snooping 0
1079	sleep 1
1080	ip link set dev br0 type bridge mcast_vlan_snooping 1
1081
1082	local n=$(bridge_${context}_ngroups_get "$locus")
1083	local nn=$(bridge mdb show dev br0 | grep $swp1 | wc -l)
1084	((nn == n))
1085	check_err $? "mcast_n_groups expected to be $nn, but $n reported"
1086
1087	local max=$(bridge_${context}_maxgroups_get "$locus")
1088	((max == 100))
1089	check_err $? "Max groups expected to be 100 but $max reported"
1090
1091	bridge_${context}_maxgroups_set "$locus" 0
1092	check_err $? "Failed to set max to 0"
1093
1094	log_test "$CFG: $context: $mode: mcast_vlan_snooping toggle"
1095}
1096
1097test_toggle_vlan_snooping_temp()
1098{
1099	test_toggle_vlan_snooping temp
1100}
1101
1102test_toggle_vlan_snooping_permanent()
1103{
1104	test_toggle_vlan_snooping permanent
1105}
1106
1107# ngroup test suites
1108
1109test_8021d_ngroups_cfg4()
1110{
1111	test_8021d_ngroups_reporting_cfg4
1112}
1113
1114test_8021d_ngroups_ctl4()
1115{
1116	test_8021d_ngroups_reporting_ctl4
1117}
1118
1119test_8021d_ngroups_cfg6()
1120{
1121	test_8021d_ngroups_reporting_cfg6
1122}
1123
1124test_8021d_ngroups_ctl6()
1125{
1126	test_8021d_ngroups_reporting_ctl6
1127}
1128
1129test_8021q_ngroups_cfg4()
1130{
1131	test_8021q_ngroups_reporting_cfg4
1132}
1133
1134test_8021q_ngroups_ctl4()
1135{
1136	test_8021q_ngroups_reporting_ctl4
1137}
1138
1139test_8021q_ngroups_cfg6()
1140{
1141	test_8021q_ngroups_reporting_cfg6
1142}
1143
1144test_8021q_ngroups_ctl6()
1145{
1146	test_8021q_ngroups_reporting_ctl6
1147}
1148
1149test_8021qvs_ngroups_cfg4()
1150{
1151	test_8021qvs_ngroups_reporting_cfg4
1152	test_8021qvs_ngroups_cross_vlan_cfg4
1153}
1154
1155test_8021qvs_ngroups_ctl4()
1156{
1157	test_8021qvs_ngroups_reporting_ctl4
1158	test_8021qvs_ngroups_cross_vlan_ctl4
1159}
1160
1161test_8021qvs_ngroups_cfg6()
1162{
1163	test_8021qvs_ngroups_reporting_cfg6
1164	test_8021qvs_ngroups_cross_vlan_cfg6
1165}
1166
1167test_8021qvs_ngroups_ctl6()
1168{
1169	test_8021qvs_ngroups_reporting_ctl6
1170	test_8021qvs_ngroups_cross_vlan_ctl6
1171}
1172
1173# maxgroups test suites
1174
1175test_8021d_maxgroups_cfg4()
1176{
1177	test_8021d_maxgroups_zero_cfg4
1178	test_8021d_maxgroups_too_low_cfg4
1179	test_8021d_maxgroups_too_many_entries_cfg4
1180}
1181
1182test_8021d_maxgroups_ctl4()
1183{
1184	test_8021d_maxgroups_zero_ctl4
1185	test_8021d_maxgroups_too_low_ctl4
1186	test_8021d_maxgroups_too_many_entries_ctl4
1187}
1188
1189test_8021d_maxgroups_cfg6()
1190{
1191	test_8021d_maxgroups_zero_cfg6
1192	test_8021d_maxgroups_too_low_cfg6
1193	test_8021d_maxgroups_too_many_entries_cfg6
1194}
1195
1196test_8021d_maxgroups_ctl6()
1197{
1198	test_8021d_maxgroups_zero_ctl6
1199	test_8021d_maxgroups_too_low_ctl6
1200	test_8021d_maxgroups_too_many_entries_ctl6
1201}
1202
1203test_8021q_maxgroups_cfg4()
1204{
1205	test_8021q_maxgroups_zero_cfg4
1206	test_8021q_maxgroups_too_low_cfg4
1207	test_8021q_maxgroups_too_many_entries_cfg4
1208}
1209
1210test_8021q_maxgroups_ctl4()
1211{
1212	test_8021q_maxgroups_zero_ctl4
1213	test_8021q_maxgroups_too_low_ctl4
1214	test_8021q_maxgroups_too_many_entries_ctl4
1215}
1216
1217test_8021q_maxgroups_cfg6()
1218{
1219	test_8021q_maxgroups_zero_cfg6
1220	test_8021q_maxgroups_too_low_cfg6
1221	test_8021q_maxgroups_too_many_entries_cfg6
1222}
1223
1224test_8021q_maxgroups_ctl6()
1225{
1226	test_8021q_maxgroups_zero_ctl6
1227	test_8021q_maxgroups_too_low_ctl6
1228	test_8021q_maxgroups_too_many_entries_ctl6
1229}
1230
1231test_8021qvs_maxgroups_cfg4()
1232{
1233	test_8021qvs_maxgroups_zero_cfg4
1234	test_8021qvs_maxgroups_zero_cross_vlan_cfg4
1235	test_8021qvs_maxgroups_too_low_cfg4
1236	test_8021qvs_maxgroups_too_many_entries_cfg4
1237	test_8021qvs_maxgroups_too_many_cross_vlan_cfg4
1238}
1239
1240test_8021qvs_maxgroups_ctl4()
1241{
1242	test_8021qvs_maxgroups_zero_ctl4
1243	test_8021qvs_maxgroups_zero_cross_vlan_ctl4
1244	test_8021qvs_maxgroups_too_low_ctl4
1245	test_8021qvs_maxgroups_too_many_entries_ctl4
1246	test_8021qvs_maxgroups_too_many_cross_vlan_ctl4
1247}
1248
1249test_8021qvs_maxgroups_cfg6()
1250{
1251	test_8021qvs_maxgroups_zero_cfg6
1252	test_8021qvs_maxgroups_zero_cross_vlan_cfg6
1253	test_8021qvs_maxgroups_too_low_cfg6
1254	test_8021qvs_maxgroups_too_many_entries_cfg6
1255	test_8021qvs_maxgroups_too_many_cross_vlan_cfg6
1256}
1257
1258test_8021qvs_maxgroups_ctl6()
1259{
1260	test_8021qvs_maxgroups_zero_ctl6
1261	test_8021qvs_maxgroups_zero_cross_vlan_ctl6
1262	test_8021qvs_maxgroups_too_low_ctl6
1263	test_8021qvs_maxgroups_too_many_entries_ctl6
1264	test_8021qvs_maxgroups_too_many_cross_vlan_ctl6
1265}
1266
1267# other test suites
1268
1269test_8021qvs_toggle_vlan_snooping()
1270{
1271	test_toggle_vlan_snooping_temp
1272	test_toggle_vlan_snooping_permanent
1273}
1274
1275# test groups
1276
1277test_8021d()
1278{
1279	# Tests for vlan_filtering 0 mcast_vlan_snooping 0.
1280
1281	switch_create_8021d
1282	setup_wait
1283
1284	test_8021d_ngroups_cfg4
1285	test_8021d_ngroups_ctl4
1286	test_8021d_ngroups_cfg6
1287	test_8021d_ngroups_ctl6
1288	test_8021d_maxgroups_cfg4
1289	test_8021d_maxgroups_ctl4
1290	test_8021d_maxgroups_cfg6
1291	test_8021d_maxgroups_ctl6
1292
1293	switch_destroy
1294}
1295
1296test_8021q()
1297{
1298	# Tests for vlan_filtering 1 mcast_vlan_snooping 0.
1299
1300	switch_create_8021q
1301	setup_wait
1302
1303	test_8021q_vlan_attributes
1304	test_8021q_ngroups_cfg4
1305	test_8021q_ngroups_ctl4
1306	test_8021q_ngroups_cfg6
1307	test_8021q_ngroups_ctl6
1308	test_8021q_maxgroups_cfg4
1309	test_8021q_maxgroups_ctl4
1310	test_8021q_maxgroups_cfg6
1311	test_8021q_maxgroups_ctl6
1312
1313	switch_destroy
1314}
1315
1316test_8021qvs()
1317{
1318	# Tests for vlan_filtering 1 mcast_vlan_snooping 1.
1319
1320	switch_create_8021qvs
1321	setup_wait
1322
1323	test_8021qvs_vlan_attributes
1324	test_8021qvs_ngroups_cfg4
1325	test_8021qvs_ngroups_ctl4
1326	test_8021qvs_ngroups_cfg6
1327	test_8021qvs_ngroups_ctl6
1328	test_8021qvs_maxgroups_cfg4
1329	test_8021qvs_maxgroups_ctl4
1330	test_8021qvs_maxgroups_cfg6
1331	test_8021qvs_maxgroups_ctl6
1332	test_8021qvs_toggle_vlan_snooping
1333
1334	switch_destroy
1335}
1336
1337if ! bridge link help 2>&1 | grep -q "mcast_max_groups"; then
1338	echo "SKIP: iproute2 too old, missing bridge \"mcast_max_groups\" support"
1339	exit $ksft_skip
1340fi
1341
1342trap cleanup EXIT
1343
1344setup_prepare
1345tests_run
1346
1347exit $EXIT_STATUS
1348