xref: /linux/tools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh (revision d603517771d8e08a2d8fc9e1f7682ce393d3973a)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4ALL_TESTS="vlmc_control_test vlmc_querier_test vlmc_igmp_mld_version_test \
5	   vlmc_last_member_test vlmc_startup_query_test vlmc_membership_test \
6	   vlmc_querier_intvl_test vlmc_query_intvl_test vlmc_query_response_intvl_test \
7	   vlmc_router_port_test vlmc_filtering_test vlmc_mcast_toggle_test"
8NUM_NETIFS=4
9CHECK_TC="yes"
10TEST_GROUP="239.10.10.10"
11
12source lib.sh
13
14h1_create()
15{
16	simple_if_init $h1 192.0.2.1/24 2001:db8:1::1/64
17	ip link add l $h1 $h1.10 up type vlan id 10
18}
19
20h1_destroy()
21{
22	ip link del $h1.10
23	simple_if_fini $h1 192.0.2.1/24 2001:db8:1::1/64
24}
25
26h2_create()
27{
28	simple_if_init $h2 192.0.2.2/24 2001:db8:1::2/64
29	ip link add l $h2 $h2.10 up type vlan id 10
30}
31
32h2_destroy()
33{
34	ip link del $h2.10
35	simple_if_fini $h2 192.0.2.2/24 2001:db8:1::2/64
36}
37
38switch_create()
39{
40	ip link add dev br0 type bridge mcast_snooping 1 mcast_querier 1 vlan_filtering 1
41
42	ip link set dev $swp1 master br0
43	ip link set dev $swp2 master br0
44
45	ip link set dev br0 up
46	ip link set dev $swp1 up
47	ip link set dev $swp2 up
48
49	tc qdisc add dev $swp1 clsact
50	tc qdisc add dev $swp2 clsact
51
52	bridge vlan add vid 10-11 dev $swp1 master
53	bridge vlan add vid 10-11 dev $swp2 master
54
55	ip link set dev br0 type bridge mcast_vlan_snooping 1
56	check_err $? "Could not enable global vlan multicast snooping"
57	log_test "Vlan multicast snooping enable"
58}
59
60switch_destroy()
61{
62	tc qdisc del dev $swp2 clsact
63	tc qdisc del dev $swp1 clsact
64
65	ip link set dev $swp2 down
66	ip link set dev $swp1 down
67
68	ip link del dev br0
69}
70
71setup_prepare()
72{
73	h1=${NETIFS[p1]}
74	swp1=${NETIFS[p2]}
75
76	swp2=${NETIFS[p3]}
77	h2=${NETIFS[p4]}
78
79	vrf_prepare
80
81	h1_create
82	h2_create
83
84	switch_create
85}
86
87cleanup()
88{
89	pre_cleanup
90
91	switch_destroy
92
93	h2_destroy
94	h1_destroy
95
96	vrf_cleanup
97}
98
99vlmc_v2join_test()
100{
101	local expect=$1
102
103	RET=0
104	ip address add dev $h2.10 $TEST_GROUP/32 autojoin
105	check_err $? "Could not join $TEST_GROUP"
106
107	sleep 5
108	bridge -j mdb show dev br0 |
109		jq -e ".[].mdb[] | select(.grp == \"$TEST_GROUP\" and .vid == 10)" &>/dev/null
110	if [ $expect -eq 0 ]; then
111		check_err $? "IGMPv2 report didn't create mdb entry for $TEST_GROUP"
112	else
113		check_fail $? "IGMPv2 report shouldn't have created mdb entry for $TEST_GROUP"
114	fi
115
116	# check if we need to cleanup
117	if [ $RET -eq 0 ]; then
118		ip address del dev $h2.10 $TEST_GROUP/32 2>&1 1>/dev/null
119		sleep 5
120		bridge -j mdb show dev br0 |
121			jq -e ".[].mdb[] | select(.grp == \"$TEST_GROUP\" and \
122						  .vid == 10)" &>/dev/null
123		check_fail $? "IGMPv2 leave didn't remove mdb entry for $TEST_GROUP"
124	fi
125}
126
127vlmc_control_test()
128{
129	RET=0
130	local goutput=`bridge -j vlan global show`
131	echo -n $goutput |
132		jq -e ".[].vlans[] | select(.vlan == 10)" &>/dev/null
133	check_err $? "Could not find vlan 10's global options"
134	log_test "Vlan global options existence"
135
136	RET=0
137	echo -n $goutput |
138		jq -e ".[].vlans[] | select(.vlan == 10 and .mcast_snooping == 1) " &>/dev/null
139	check_err $? "Wrong default mcast_snooping global option value"
140	log_test "Vlan mcast_snooping global option default value"
141
142	RET=0
143	vlmc_v2join_test 0
144	bridge vlan global set vid 10 dev br0 mcast_snooping 0
145	check_err $? "Could not disable multicast snooping in vlan 10"
146	vlmc_v2join_test 1
147	log_test "Vlan 10 multicast snooping control"
148}
149
150# setup for general query counting
151vlmc_query_cnt_xstats()
152{
153	local type=$1
154	local version=$2
155	local dev=$3
156
157	ip -j link xstats type bridge_slave dev $dev | \
158	jq -e ".[].multicast.${type}_queries.tx_v${version}"
159}
160
161vlmc_query_cnt_setup()
162{
163	local type=$1
164	local dev=$2
165	local match=($3)
166
167	if [[ $type == "igmp" ]]; then
168		# This matches: IP Protocol 2 (IGMP)
169		tc filter add dev "$dev" egress pref 10 prot 802.1Q \
170			flower vlan_id 10 vlan_ethtype ipv4 dst_ip 224.0.0.1 ip_proto 2 \
171			action goto chain 1
172		# AND Type 0x11 (Query) at offset 0 of IGMP header
173		# 20 bytes IPv4 header + 4 bytes Router Alert option + IGMP[offset 0]
174		tc filter add dev "$dev" egress pref 20 chain 1 prot 802.1Q u32 \
175			match u8 0x11 0xff at 24 "${match[@]}" \
176			action pass
177	else
178		# This matches: ICMPv6
179		tc filter add dev "$dev" egress pref 10 prot 802.1Q \
180			flower vlan_id 10 vlan_ethtype ipv6 dst_ip ff02::1 ip_proto icmpv6 \
181			action goto chain 1
182		# AND Type 0x82 (Query) at offset 0 of MLD header
183		# 40 bytes IPv6 header + 8 bytes Hop-by-hop option + MLD[offset 0]
184		tc filter add dev "$dev" egress pref 20 chain 1 prot 802.1Q u32 \
185			match u8 0x82 0xff at 48 "${match[@]}" \
186			action pass
187	fi
188
189	ip link set dev br0 type bridge mcast_stats_enabled 1
190}
191
192vlmc_query_cnt_cleanup()
193{
194	local dev=$1
195
196	ip link set dev br0 type bridge mcast_stats_enabled 0
197	tc filter del dev "$dev" egress pref 20 chain 1
198	tc filter del dev "$dev" egress pref 10
199}
200
201vlmc_query_get_intvl_match()
202{
203	local type=$1
204	local version=$2
205	local test=$3
206	local enc_val=$4
207
208	if [ "$test" = "qqic" ]; then
209		# QQIC is 8-bit floating point encoding for IGMPv3 and MLDv2
210		if [ "${type}v${version}" = "igmpv3" ]; then
211			# QQIC is at offset 9 of IGMP header
212			# 20 bytes IPv4 header + 4 bytes Router Alert option + IGMP[offset 9]
213			echo "match u8 $enc_val 0xff at 33"
214		elif [ "${type}v${version}" = "mldv2" ]; then
215			# QQIC is at offset 25 of MLD header
216			# 40 bytes IPv6 header + 8 bytes Hop-by-hop option + MLD[offset 25]
217			echo "match u8 $enc_val 0xff at 73"
218		fi
219	elif [ "$test" = "mrc" ]; then
220		if [ "${type}v${version}" = "igmpv3" ]; then
221			# MRC is 8-bit floating point encoding at offset 1 of IGMP header
222			# 20 bytes IPv4 header + 4 bytes Router Alert option + IGMP[offset 1]
223			echo "match u8 $enc_val 0xff at 25"
224		elif [ "${type}v${version}" = "mldv2" ]; then
225			# MRC is 16-bit floating point encoding at offset 4 of MLD header
226			# 40 bytes IPv6 header + 8 bytes Hop-by-hop option + MLD[offset 4]
227			echo "match u16 $enc_val 0xffff at 52"
228		fi
229	fi
230}
231
232vlmc_check_query()
233{
234	local type=$1
235	local version=$2
236	local dev=$3
237	local expect=$4
238	local time=$5
239	local test=$6
240	local enc_val=$7
241	local intvl_match=""
242	local ret=0
243
244	intvl_match="$(vlmc_query_get_intvl_match "$type" "$version" "$test" "$enc_val")"
245	vlmc_query_cnt_setup "$type" "$dev" "$intvl_match"
246
247	local pre_tx_xstats=$(vlmc_query_cnt_xstats $type $version $dev)
248	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_querier 1
249	ret=$?
250	if [[ $ret -eq 0 ]]; then
251		sleep $time
252
253		local tcstats=$(tc_rule_stats_get "$dev" 20 egress)
254		local post_tx_xstats=$(vlmc_query_cnt_xstats $type $version $dev)
255
256		if [[ $tcstats != $expect || \
257		      $(($post_tx_xstats-$pre_tx_xstats)) != $expect || \
258		      $tcstats != $(($post_tx_xstats-$pre_tx_xstats)) ]]; then
259			ret=1
260		fi
261	fi
262
263	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_querier 0
264	vlmc_query_cnt_cleanup $dev
265
266	return $ret
267}
268
269vlmc_querier_test()
270{
271	RET=0
272	local goutput=`bridge -j vlan global show`
273	echo -n $goutput |
274		jq -e ".[].vlans[] | select(.vlan == 10)" &>/dev/null
275	check_err $? "Could not find vlan 10's global options"
276
277	echo -n $goutput |
278		jq -e ".[].vlans[] | select(.vlan == 10 and .mcast_querier == 0) " &>/dev/null
279	check_err $? "Wrong default mcast_querier global vlan option value"
280	log_test "Vlan mcast_querier global option default value"
281
282	RET=0
283	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_querier 1
284	check_err $? "Could not enable querier in vlan 10"
285	log_test "Vlan 10 multicast querier enable"
286	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_querier 0
287
288	RET=0
289	vlmc_check_query igmp 2 $swp1 1 1
290	check_err $? "No vlan tagged IGMPv2 general query packets sent"
291	log_test "Vlan 10 tagged IGMPv2 general query sent"
292
293	RET=0
294	vlmc_check_query mld 1 $swp1 1 1
295	check_err $? "No vlan tagged MLD general query packets sent"
296	log_test "Vlan 10 tagged MLD general query sent"
297}
298
299vlmc_igmp_mld_version_test()
300{
301	RET=0
302	local goutput=`bridge -j vlan global show`
303	echo -n $goutput |
304		jq -e ".[].vlans[] | select(.vlan == 10)" &>/dev/null
305	check_err $? "Could not find vlan 10's global options"
306
307	echo -n $goutput |
308		jq -e ".[].vlans[] | select(.vlan == 10 and .mcast_igmp_version == 2) " &>/dev/null
309	check_err $? "Wrong default mcast_igmp_version global vlan option value"
310	log_test "Vlan mcast_igmp_version global option default value"
311
312	RET=0
313	echo -n $goutput |
314		jq -e ".[].vlans[] | select(.vlan == 10 and .mcast_mld_version == 1) " &>/dev/null
315	check_err $? "Wrong default mcast_mld_version global vlan option value"
316	log_test "Vlan mcast_mld_version global option default value"
317
318	RET=0
319	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_igmp_version 3
320	check_err $? "Could not set mcast_igmp_version in vlan 10"
321	log_test "Vlan 10 mcast_igmp_version option changed to 3"
322
323	RET=0
324	vlmc_check_query igmp 3 $swp1 1 1
325	check_err $? "No vlan tagged IGMPv3 general query packets sent"
326	log_test "Vlan 10 tagged IGMPv3 general query sent"
327
328	RET=0
329	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_mld_version 2
330	check_err $? "Could not set mcast_mld_version in vlan 10"
331	log_test "Vlan 10 mcast_mld_version option changed to 2"
332
333	RET=0
334	vlmc_check_query mld 2 $swp1 1 1
335	check_err $? "No vlan tagged MLDv2 general query packets sent"
336	log_test "Vlan 10 tagged MLDv2 general query sent"
337
338	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_igmp_version 2
339	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_mld_version 1
340}
341
342vlmc_last_member_test()
343{
344	RET=0
345	local goutput=`bridge -j vlan global show`
346	echo -n $goutput |
347		jq -e ".[].vlans[] | select(.vlan == 10)" &>/dev/null
348	check_err $? "Could not find vlan 10's global options"
349
350	echo -n $goutput |
351		jq -e ".[].vlans[] | select(.vlan == 10 and \
352					    .mcast_last_member_count == 2) " &>/dev/null
353	check_err $? "Wrong default mcast_last_member_count global vlan option value"
354	log_test "Vlan mcast_last_member_count global option default value"
355
356	RET=0
357	echo -n $goutput |
358		jq -e ".[].vlans[] | select(.vlan == 10 and \
359					    .mcast_last_member_interval == 100) " &>/dev/null
360	check_err $? "Wrong default mcast_last_member_interval global vlan option value"
361	log_test "Vlan mcast_last_member_interval global option default value"
362
363	RET=0
364	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_last_member_count 3
365	check_err $? "Could not set mcast_last_member_count in vlan 10"
366	log_test "Vlan 10 mcast_last_member_count option changed to 3"
367	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_last_member_count 2
368
369	RET=0
370	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_last_member_interval 200
371	check_err $? "Could not set mcast_last_member_interval in vlan 10"
372	log_test "Vlan 10 mcast_last_member_interval option changed to 200"
373	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_last_member_interval 100
374}
375
376vlmc_startup_query_test()
377{
378	RET=0
379	local goutput=`bridge -j vlan global show`
380	echo -n $goutput |
381		jq -e ".[].vlans[] | select(.vlan == 10)" &>/dev/null
382	check_err $? "Could not find vlan 10's global options"
383
384	echo -n $goutput |
385		jq -e ".[].vlans[] | select(.vlan == 10 and \
386					    .mcast_startup_query_interval == 3125) " &>/dev/null
387	check_err $? "Wrong default mcast_startup_query_interval global vlan option value"
388	log_test "Vlan mcast_startup_query_interval global option default value"
389
390	RET=0
391	echo -n $goutput |
392		jq -e ".[].vlans[] | select(.vlan == 10 and \
393					    .mcast_startup_query_count == 2) " &>/dev/null
394	check_err $? "Wrong default mcast_startup_query_count global vlan option value"
395	log_test "Vlan mcast_startup_query_count global option default value"
396
397	RET=0
398	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_query_interval 100
399	check_err $? "Could not set mcast_startup_query_interval in vlan 10"
400	vlmc_check_query igmp 2 $swp1 2 3
401	check_err $? "Wrong number of tagged IGMPv2 general queries sent"
402	log_test "Vlan 10 mcast_startup_query_interval option changed to 100"
403
404	RET=0
405	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_query_count 3
406	check_err $? "Could not set mcast_startup_query_count in vlan 10"
407	vlmc_check_query igmp 2 $swp1 3 4
408	check_err $? "Wrong number of tagged IGMPv2 general queries sent"
409	log_test "Vlan 10 mcast_startup_query_count option changed to 3"
410
411	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_query_interval 3125
412	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_query_count 2
413}
414
415vlmc_membership_test()
416{
417	RET=0
418	local goutput=`bridge -j vlan global show`
419	echo -n $goutput |
420		jq -e ".[].vlans[] | select(.vlan == 10)" &>/dev/null
421	check_err $? "Could not find vlan 10's global options"
422
423	echo -n $goutput |
424		jq -e ".[].vlans[] | select(.vlan == 10 and \
425					    .mcast_membership_interval == 26000) " &>/dev/null
426	check_err $? "Wrong default mcast_membership_interval global vlan option value"
427	log_test "Vlan mcast_membership_interval global option default value"
428
429	RET=0
430	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_membership_interval 200
431	check_err $? "Could not set mcast_membership_interval in vlan 10"
432	log_test "Vlan 10 mcast_membership_interval option changed to 200"
433
434	RET=0
435	vlmc_v2join_test 1
436	log_test "Vlan 10 mcast_membership_interval mdb entry expire"
437
438	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_membership_interval 26000
439}
440
441vlmc_querier_intvl_test()
442{
443	RET=0
444	local goutput=`bridge -j vlan global show`
445	echo -n $goutput |
446		jq -e ".[].vlans[] | select(.vlan == 10)" &>/dev/null
447	check_err $? "Could not find vlan 10's global options"
448
449	echo -n $goutput |
450		jq -e ".[].vlans[] | select(.vlan == 10 and \
451					    .mcast_querier_interval == 25500) " &>/dev/null
452	check_err $? "Wrong default mcast_querier_interval global vlan option value"
453	log_test "Vlan mcast_querier_interval global option default value"
454
455	RET=0
456	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_querier_interval 100
457	check_err $? "Could not set mcast_querier_interval in vlan 10"
458	log_test "Vlan 10 mcast_querier_interval option changed to 100"
459
460	RET=0
461	ip link add dev br1 type bridge mcast_snooping 1 mcast_querier 1 vlan_filtering 1 \
462					mcast_vlan_snooping 1
463	bridge vlan add vid 10 dev br1 self pvid untagged
464	ip link set dev $h1 master br1
465	ip link set dev br1 up
466	setup_wait_dev $h1 0
467	bridge vlan add vid 10 dev $h1 master
468	bridge vlan global set vid 10 dev br1 mcast_snooping 1 mcast_querier 1
469	sleep 2
470	ip link del dev br1
471	ip addr replace 2001:db8:1::1/64 dev $h1
472	vlmc_check_query igmp 2 $swp1 1 1
473	check_err $? "Wrong number of IGMPv2 general queries after querier interval"
474	log_test "Vlan 10 mcast_querier_interval expire after outside query"
475
476	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_querier_interval 25500
477}
478
479vlmc_query_intvl_test()
480{
481	RET=0
482	local goutput=`bridge -j vlan global show`
483	echo -n $goutput |
484		jq -e ".[].vlans[] | select(.vlan == 10)" &>/dev/null
485	check_err $? "Could not find vlan 10's global options"
486
487	echo -n $goutput |
488		jq -e ".[].vlans[] | select(.vlan == 10 and \
489					    .mcast_query_interval == 12500) " &>/dev/null
490	check_err $? "Wrong default mcast_query_interval global vlan option value"
491	log_test "Vlan mcast_query_interval global option default value"
492
493	RET=0
494	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_query_count 0
495	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_interval 200
496	check_err $? "Could not set mcast_query_interval in vlan 10"
497	# 1 is sent immediately, then 2 more in the next 5 seconds
498	vlmc_check_query igmp 2 $swp1 3 5
499	check_err $? "Wrong number of tagged IGMPv2 general queries sent"
500	log_test "Number of tagged IGMPv2 general query"
501
502	RET=0
503	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_igmp_version 3
504	check_err $? "Could not set mcast_igmp_version in vlan 10"
505	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_mld_version 2
506	check_err $? "Could not set mcast_mld_version in vlan 10"
507	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_interval 6000
508	check_err $? "Could not set mcast_query_interval in vlan 10"
509	# 1 is sent immediately, IGMPv3 QQIC should match with linear value 60 (0x3c)
510	# which is 8-bit encoded value of 60 [units of seconds]
511	vlmc_check_query igmp 3 $swp1 1 1 qqic 0x3c
512	check_err $? "Wrong QQIC in generated IGMPv3 general queries"
513	log_test "IGMPv3 QQIC linear value 60(s)"
514
515	RET=0
516	# 1 is sent immediately, MLDv2 QQIC should match with linear value 60 (0x3c)
517	# which is 8-bit encoded value of 60 [units of seconds]
518	vlmc_check_query mld 2 $swp1 1 1 qqic 0x3c
519	check_err $? "Wrong QQIC in generated MLDv2 general queries"
520	log_test "MLDv2 QQIC linear value 60(s)"
521
522	RET=0
523	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_interval 16000
524	check_err $? "Could not set mcast_query_interval in vlan 10"
525	# 1 is sent immediately, IGMPv3 QQIC should match with non linear value 132 (0x84)
526	# which is 8-bit encoded value of 160 [units of seconds]
527	vlmc_check_query igmp 3 $swp1 1 1 qqic 0x84
528	check_err $? "Wrong QQIC in generated IGMPv3 general queries"
529	log_test "IGMPv3 QQIC non linear value 160(s)"
530
531	RET=0
532	# 1 is sent immediately, MLDv2 QQIC should match with non linear value 132 (0x84)
533	# which is 8-bit encoded value of 160 [units of seconds]
534	vlmc_check_query mld 2 $swp1 1 1 qqic 0x84
535	check_err $? "Wrong QQIC in generated MLDv2 general queries"
536	log_test "MLDv2 QQIC non linear value 160(s)"
537
538	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_igmp_version 2
539	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_mld_version 1
540	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_query_count 2
541	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_interval 12500
542}
543
544vlmc_query_response_intvl_test()
545{
546	RET=0
547	local goutput=`bridge -j vlan global show`
548	echo -n $goutput |
549		jq -e ".[].vlans[] | select(.vlan == 10)" &>/dev/null
550	check_err $? "Could not find vlan 10's global options"
551
552	echo -n $goutput |
553		jq -e ".[].vlans[] | select(.vlan == 10 and \
554					    .mcast_query_response_interval == 1000) " &>/dev/null
555	check_err $? "Wrong default mcast_query_response_interval global vlan option value"
556	log_test "Vlan mcast_query_response_interval global option default value"
557
558	RET=0
559	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_query_count 0
560	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_igmp_version 3
561	check_err $? "Could not set mcast_igmp_version in vlan 10"
562	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_mld_version 2
563	check_err $? "Could not set mcast_mld_version in vlan 10"
564	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_response_interval 600
565	check_err $? "Could not set mcast_query_response_interval in vlan 10"
566	# 1 is sent immediately, IGMPv3 MRC should match with linear value 60 (0x3c)
567	# which is 8-bit encoded value of 60 [units of 0.1s = 6 seconds]
568	vlmc_check_query igmp 3 $swp1 1 1 mrc 0x3c
569	check_err $? "Wrong MRC in generated IGMPv3 general queries"
570	log_test "IGMPv3 MRC linear value of 60(x0.1s)"
571
572	RET=0
573	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_response_interval 2400
574	check_err $? "Could not set mcast_query_response_interval in vlan 10"
575	# 1 is sent immediately, MLDv2 MRC should match with linear value 0x5dc0 (24000)
576	# which is 16-bit encoded value of 24000 [units of ms / 24 seconds]
577	vlmc_check_query mld 2 $swp1 1 1 mrc 0x5dc0
578	check_err $? "Wrong MRC in generated MLDv2 general queries"
579	log_test "MLDv2 MRC linear value of 24000(ms)"
580
581	RET=0
582	# 1 is sent immediately, IGMPv3 MRC should match with non linear value 142 (0x8e)
583	# which is 8-bit encoded value of 240 [units of 0.1s = 24 seconds]
584	vlmc_check_query igmp 3 $swp1 1 1 mrc 0x8e
585	check_err $? "Wrong MRC in generated IGMPv3 general queries"
586	log_test "IGMPv3 MRC non linear value of 240(x0.1s)"
587
588	RET=0
589	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_response_interval 4800
590	check_err $? "Could not set mcast_query_response_interval in vlan 10"
591	# 1 is sent immediately, MLDv2 MRC should match with non linear value 0x8770 (34672)
592	# which is 16-bit encoded value of 48000 [units of ms / 48 seconds]
593	vlmc_check_query mld 2 $swp1 1 1 mrc 0x8770
594	check_err $? "Wrong MRC in generated MLDv2 general queries"
595	log_test "MLDv2 MRC non linear value of 48000(ms)"
596
597	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_igmp_version 2
598	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_mld_version 1
599	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_query_count 2
600	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_response_interval 1000
601}
602
603vlmc_router_port_test()
604{
605	RET=0
606	local goutput=`bridge -j -d vlan show`
607	echo -n $goutput |
608		jq -e ".[] | select(.ifname == \"$swp1\" and \
609				    .vlans[].vlan == 10)" &>/dev/null
610	check_err $? "Could not find port vlan 10's options"
611
612	echo -n $goutput |
613		jq -e ".[] | select(.ifname == \"$swp1\" and \
614				    .vlans[].vlan == 10 and \
615				    .vlans[].mcast_router == 1)" &>/dev/null
616	check_err $? "Wrong default port mcast_router option value"
617	log_test "Port vlan 10 option mcast_router default value"
618
619	RET=0
620	bridge vlan set vid 10 dev $swp1 mcast_router 2
621	check_err $? "Could not set port vlan 10's mcast_router option"
622	log_test "Port vlan 10 mcast_router option changed to 2"
623
624	RET=0
625	tc filter add dev $swp1 egress pref 10 prot 802.1Q \
626		flower vlan_id 10 vlan_ethtype ipv4 dst_ip 239.1.1.1 ip_proto udp action pass
627	tc filter add dev $swp2 egress pref 10 prot 802.1Q \
628		flower vlan_id 10 vlan_ethtype ipv4 dst_ip 239.1.1.1 ip_proto udp action pass
629	bridge vlan set vid 10 dev $swp2 mcast_router 0
630	# we need to enable querier and disable query response interval to
631	# make sure packets are flooded only to router ports
632	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_querier 1 \
633					      mcast_query_response_interval 0
634	bridge vlan add vid 10 dev br0 self
635	sleep 1
636	mausezahn br0 -Q 10 -c 10 -p 128 -b 01:00:5e:01:01:01 -B 239.1.1.1 \
637			-t udp "dp=1024" &>/dev/null
638	local swp1_tcstats=$(tc_rule_stats_get $swp1 10 egress)
639	if [[ $swp1_tcstats != 10 ]]; then
640		check_err 1 "Wrong number of vlan 10 multicast packets flooded"
641	fi
642	local swp2_tcstats=$(tc_rule_stats_get $swp2 10 egress)
643	check_err $swp2_tcstats "Vlan 10 multicast packets flooded to non-router port"
644	log_test "Flood unknown vlan multicast packets to router port only"
645
646	tc filter del dev $swp2 egress pref 10
647	tc filter del dev $swp1 egress pref 10
648	bridge vlan del vid 10 dev br0 self
649	bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_response_interval 1000
650	bridge vlan set vid 10 dev $swp2 mcast_router 1
651	bridge vlan set vid 10 dev $swp1 mcast_router 1
652}
653
654vlmc_filtering_test()
655{
656	RET=0
657	ip link set dev br0 type bridge vlan_filtering 0
658	ip -j -d link show dev br0 | \
659	jq -e "select(.[0].linkinfo.info_data.mcast_vlan_snooping == 1)" &>/dev/null
660	check_fail $? "Vlan filtering is disabled but multicast vlan snooping is still enabled"
661	log_test "Disable multicast vlan snooping when vlan filtering is disabled"
662}
663
664vlmc_mcast_toggle_test()
665{
666	RET=0
667
668	ip link add name br1-mcast up type bridge mcast_snooping 1 mcast_querier 1 vlan_filtering 1
669	ip link add name dummy1-mcast up master br1-mcast type dummy
670
671	# Enabling per-VLAN multicast snooping should disable the per-port
672	# multicast context on "dummy1-mcast".
673	ip link set dev br1-mcast type bridge mcast_vlan_snooping 1
674
675	# Toggling multicast snooping on the bridge should not affect the
676	# per-port multicast context on "dummy1-mcast" given that per-VLAN
677	# multicast snooping is enabled.
678	ip link set dev br1-mcast type bridge mcast_snooping 0
679	ip link set dev br1-mcast type bridge mcast_snooping 1
680
681	# If both the per-port and per-{port, VLAN} multicast contexts are
682	# enabled on "dummy1-mcast", removing it from the bridge will result
683	# in a splat.
684	ip link set dev dummy1-mcast nomaster
685
686	log_test "Toggling mcast snooping with per-VLAN mcast snooping enabled"
687
688	ip link del dev dummy1-mcast
689	ip link del dev br1-mcast
690}
691
692trap cleanup EXIT
693
694setup_prepare
695setup_wait
696
697tests_run
698
699exit $EXIT_STATUS
700