1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4ALL_TESTS="mldv2include_test mldv2inc_allow_test mldv2inc_is_include_test mldv2inc_is_exclude_test \
5	   mldv2inc_to_exclude_test mldv2exc_allow_test"
6NUM_NETIFS=4
7CHECK_TC="yes"
8TEST_GROUP="ff02::cc"
9TEST_GROUP_MAC="33:33:00:00:00:cc"
10
11# MLDv2 is_in report: grp ff02::cc is_include 2001:db8:1::1,2001:db8:1::2,2001:db8:1::3
12MZPKT_IS_INC="33:33:00:00:00:01:fe:54:00:04:5e:ba:86:dd:60:0a:2d:ae:00:54:00:01:fe:80:00:\
1300:00:00:00:00:fc:54:00:ff:fe:04:5e:ba:ff:02:00:00:00:00:00:00:00:00:00:00:00:00:00:01:3a:\
1400:05:02:00:00:00:00:8f:00:8e:d9:00:00:00:01:01:00:00:03:ff:02:00:00:00:00:00:00:00:00:00:\
1500:00:00:00:cc:20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:01:20:01:0d:b8:00:01:00:00:00:\
1600:00:00:00:00:00:02:20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:03"
17# MLDv2 is_in report: grp ff02::cc is_include 2001:db8:1::10,2001:db8:1::11,2001:db8:1::12
18MZPKT_IS_INC2="33:33:00:00:00:01:fe:54:00:04:5e:ba:86:dd:60:0a:2d:ae:00:54:00:01:fe:80:00:\
1900:00:00:00:00:fc:54:00:ff:fe:04:5e:ba:ff:02:00:00:00:00:00:00:00:00:00:00:00:00:00:01:3a:00:\
2005:02:00:00:00:00:8f:00:8e:ac:00:00:00:01:01:00:00:03:ff:02:00:00:00:00:00:00:00:00:00:00:00:\
2100:00:cc:20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:10:20:01:0d:b8:00:01:00:00:00:00:00:00:\
2200:00:00:11:20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:12"
23# MLDv2 allow report: grp ff02::cc allow 2001:db8:1::10,2001:db8:1::11,2001:db8:1::12
24MZPKT_ALLOW="33:33:00:00:00:01:fe:54:00:04:5e:ba:86:dd:60:0a:2d:ae:00:54:00:01:fe:80:00:00:\
2500:00:00:00:fc:54:00:ff:fe:04:5e:ba:ff:02:00:00:00:00:00:00:00:00:00:00:00:00:00:01:3a:00:05:\
2602:00:00:00:00:8f:00:8a:ac:00:00:00:01:05:00:00:03:ff:02:00:00:00:00:00:00:00:00:00:00:00:00:\
2700:cc:20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:10:20:01:0d:b8:00:01:00:00:00:00:00:00:00:\
2800:00:11:20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:12"
29# MLDv2 allow report: grp ff02::cc allow 2001:db8:1::20,2001:db8:1::30
30MZPKT_ALLOW2="33:33:00:00:00:01:fe:54:00:04:5e:ba:86:dd:60:0a:2d:ae:00:44:00:01:fe:80:00:00:00:\
3100:00:00:fc:54:00:ff:fe:04:5e:ba:ff:02:00:00:00:00:00:00:00:00:00:00:00:00:00:01:3a:00:05:02:00:\
3200:00:00:8f:00:b8:5a:00:00:00:01:05:00:00:02:ff:02:00:00:00:00:00:00:00:00:00:00:00:00:00:cc:20:\
3301:0d:b8:00:01:00:00:00:00:00:00:00:00:00:20:20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:30"
34# MLDv2 is_ex report: grp ff02::cc is_exclude 2001:db8:1::1,2001:db8:1::2,2001:db8:1::20,2001:db8:1::21
35MZPKT_IS_EXC="33:33:00:00:00:01:fe:54:00:04:5e:ba:86:dd:60:0a:2d:ae:00:64:00:01:fe:80:00:00:00:\
3600:00:00:fc:54:00:ff:fe:04:5e:ba:ff:02:00:00:00:00:00:00:00:00:00:00:00:00:00:01:3a:00:05:02:00:\
3700:00:00:8f:00:5f:d0:00:00:00:01:02:00:00:04:ff:02:00:00:00:00:00:00:00:00:00:00:00:00:00:cc:20:\
3801:0d:b8:00:01:00:00:00:00:00:00:00:00:00:01:20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:02:20:\
3901:0d:b8:00:01:00:00:00:00:00:00:00:00:00:20:20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:21"
40# MLDv2 to_ex report: grp ff02::cc to_exclude 2001:db8:1::1,2001:db8:1::20,2001:db8:1::30
41MZPKT_TO_EXC="33:33:00:00:00:01:fe:54:00:04:5e:ba:86:dd:60:0a:2d:ae:00:54:00:01:fe:80:00:00:00:\
4200:00:00:fc:54:00:ff:fe:04:5e:ba:ff:02:00:00:00:00:00:00:00:00:00:00:00:00:00:01:3a:00:05:02:00:\
4300:00:00:8f:00:8b:8e:00:00:00:01:04:00:00:03:ff:02:00:00:00:00:00:00:00:00:00:00:00:00:00:cc:20:\
4401:0d:b8:00:01:00:00:00:00:00:00:00:00:00:01:20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:20:20:\
4501:0d:b8:00:01:00:00:00:00:00:00:00:00:00:30"
46
47source lib.sh
48
49h1_create()
50{
51	simple_if_init $h1 2001:db8:1::1/64
52}
53
54h1_destroy()
55{
56	simple_if_fini $h1 2001:db8:1::1/64
57}
58
59h2_create()
60{
61	simple_if_init $h2 2001:db8:1::2/64
62}
63
64h2_destroy()
65{
66	simple_if_fini $h2 2001:db8:1::2/64
67}
68
69switch_create()
70{
71	ip link add dev br0 type bridge mcast_snooping 1 mcast_query_response_interval 100 \
72					mcast_mld_version 2 mcast_startup_query_interval 300 \
73					mcast_querier 1
74
75	ip link set dev $swp1 master br0
76	ip link set dev $swp2 master br0
77
78	ip link set dev br0 up
79	ip link set dev $swp1 up
80	ip link set dev $swp2 up
81
82	# make sure a query has been generated
83	sleep 5
84}
85
86switch_destroy()
87{
88	ip link set dev $swp2 down
89	ip link set dev $swp1 down
90
91	ip link del dev br0
92}
93
94setup_prepare()
95{
96	h1=${NETIFS[p1]}
97	swp1=${NETIFS[p2]}
98
99	swp2=${NETIFS[p3]}
100	h2=${NETIFS[p4]}
101
102	vrf_prepare
103
104	h1_create
105	h2_create
106
107	switch_create
108}
109
110cleanup()
111{
112	pre_cleanup
113
114	switch_destroy
115
116	h2_destroy
117	h1_destroy
118
119	vrf_cleanup
120}
121
122mldv2include_prepare()
123{
124	local host1_if=$1
125	local X=("2001:db8:1::1" "2001:db8:1::2" "2001:db8:1::3")
126
127	ip link set dev br0 type bridge mcast_mld_version 2
128	check_err $? "Could not change bridge MLD version to 2"
129
130	$MZ $host1_if $MZPKT_IS_INC -q
131	sleep 1
132	bridge -j -d -s mdb show dev br0 \
133		| jq -e ".[].mdb[] | \
134			 select(.grp == \"$TEST_GROUP\" and .source_list != null)" &>/dev/null
135	check_err $? "Missing *,G entry with source list"
136	bridge -j -d -s mdb show dev br0 \
137		| jq -e ".[].mdb[] | \
138			 select(.grp == \"$TEST_GROUP\" and \
139				.source_list != null and .filter_mode == \"include\")" &>/dev/null
140	check_err $? "Wrong *,G entry filter mode"
141	brmcast_check_sg_entries "is_include" "${X[@]}"
142}
143
144mldv2exclude_prepare()
145{
146	local host1_if=$1
147	local mac=$2
148	local group=$3
149	local pkt=$4
150	local X=("2001:db8:1::1" "2001:db8:1::2")
151	local Y=("2001:db8:1::20" "2001:db8:1::21")
152
153	mldv2include_prepare $h1
154
155	$MZ $host1_if -c 1 $MZPKT_IS_EXC -q
156	sleep 1
157	bridge -j -d -s mdb show dev br0 \
158		| jq -e ".[].mdb[] | \
159			 select(.grp == \"$TEST_GROUP\" and \
160			 .source_list != null and .filter_mode == \"exclude\")" &>/dev/null
161	check_err $? "Wrong *,G entry filter mode"
162
163	brmcast_check_sg_entries "is_exclude" "${X[@]}" "${Y[@]}"
164
165	brmcast_check_sg_state 0 "${X[@]}"
166	brmcast_check_sg_state 1 "${Y[@]}"
167
168	bridge -j -d -s mdb show dev br0 \
169		| jq -e ".[].mdb[] | \
170			 select(.grp == \"$TEST_GROUP\" and \
171				.source_list != null and
172				.source_list[].address == \"2001:db8:1::3\")" &>/dev/null
173	check_fail $? "Wrong *,G entry source list, 2001:db8:1::3 entry still exists"
174}
175
176mldv2cleanup()
177{
178	local port=$1
179
180	bridge mdb del dev br0 port $port grp $TEST_GROUP
181	ip link set dev br0 type bridge mcast_mld_version 1
182}
183
184mldv2include_test()
185{
186	RET=0
187	local X=("2001:db8:1::1" "2001:db8:1::2" "2001:db8:1::3")
188
189	mldv2include_prepare $h1
190
191	brmcast_check_sg_state 0 "${X[@]}"
192
193	brmcast_check_sg_fwding 1 "${X[@]}"
194	brmcast_check_sg_fwding 0 "2001:db8:1::100"
195
196	log_test "MLDv2 report $TEST_GROUP is_include"
197
198	mldv2cleanup $swp1
199}
200
201mldv2inc_allow_test()
202{
203	RET=0
204	local X=("2001:db8:1::10" "2001:db8:1::11" "2001:db8:1::12")
205
206	mldv2include_prepare $h1
207
208	$MZ $h1 -c 1 $MZPKT_ALLOW -q
209	sleep 1
210	brmcast_check_sg_entries "allow" "${X[@]}"
211
212	brmcast_check_sg_state 0 "${X[@]}"
213
214	brmcast_check_sg_fwding 1 "${X[@]}"
215	brmcast_check_sg_fwding 0 "2001:db8:1::100"
216
217	log_test "MLDv2 report $TEST_GROUP include -> allow"
218
219	mldv2cleanup $swp1
220}
221
222mldv2inc_is_include_test()
223{
224	RET=0
225	local X=("2001:db8:1::10" "2001:db8:1::11" "2001:db8:1::12")
226
227	mldv2include_prepare $h1
228
229	$MZ $h1 -c 1 $MZPKT_IS_INC2 -q
230	sleep 1
231	brmcast_check_sg_entries "is_include" "${X[@]}"
232
233	brmcast_check_sg_state 0 "${X[@]}"
234
235	brmcast_check_sg_fwding 1 "${X[@]}"
236	brmcast_check_sg_fwding 0 "2001:db8:1::100"
237
238	log_test "MLDv2 report $TEST_GROUP include -> is_include"
239
240	mldv2cleanup $swp1
241}
242
243mldv2inc_is_exclude_test()
244{
245	RET=0
246
247	mldv2exclude_prepare $h1
248
249	brmcast_check_sg_fwding 1 "${X[@]}" 2001:db8:1::100
250	brmcast_check_sg_fwding 0 "${Y[@]}"
251
252	log_test "MLDv2 report $TEST_GROUP include -> is_exclude"
253
254	mldv2cleanup $swp1
255}
256
257mldv2inc_to_exclude_test()
258{
259	RET=0
260	local X=("2001:db8:1::1")
261	local Y=("2001:db8:1::20" "2001:db8:1::30")
262
263	mldv2include_prepare $h1
264
265	ip link set dev br0 type bridge mcast_last_member_interval 500
266	check_err $? "Could not change mcast_last_member_interval to 5s"
267
268	$MZ $h1 -c 1 $MZPKT_TO_EXC -q
269	sleep 1
270	bridge -j -d -s mdb show dev br0 \
271		| jq -e ".[].mdb[] | \
272			 select(.grp == \"$TEST_GROUP\" and \
273				.source_list != null and .filter_mode == \"exclude\")" &>/dev/null
274	check_err $? "Wrong *,G entry filter mode"
275
276	brmcast_check_sg_entries "to_exclude" "${X[@]}" "${Y[@]}"
277
278	brmcast_check_sg_state 0 "${X[@]}"
279	brmcast_check_sg_state 1 "${Y[@]}"
280
281	bridge -j -d -s mdb show dev br0 \
282		| jq -e ".[].mdb[] | \
283			 select(.grp == \"$TEST_GROUP\" and \
284				.source_list != null and
285				.source_list[].address == \"2001:db8:1::2\")" &>/dev/null
286	check_fail $? "Wrong *,G entry source list, 2001:db8:1::2 entry still exists"
287	bridge -j -d -s mdb show dev br0 \
288		| jq -e ".[].mdb[] | \
289			 select(.grp == \"$TEST_GROUP\" and \
290				.source_list != null and
291				.source_list[].address == \"2001:db8:1::21\")" &>/dev/null
292	check_fail $? "Wrong *,G entry source list, 2001:db8:1::21 entry still exists"
293
294	brmcast_check_sg_fwding 1 "${X[@]}" 2001:db8:1::100
295	brmcast_check_sg_fwding 0 "${Y[@]}"
296
297	log_test "MLDv2 report $TEST_GROUP include -> to_exclude"
298
299	ip link set dev br0 type bridge mcast_last_member_interval 100
300
301	mldv2cleanup $swp1
302}
303
304mldv2exc_allow_test()
305{
306	RET=0
307	local X=("2001:db8:1::1" "2001:db8:1::2" "2001:db8:1::20" "2001:db8:1::30")
308	local Y=("2001:db8:1::21")
309
310	mldv2exclude_prepare $h1
311
312	$MZ $h1 -c 1 $MZPKT_ALLOW2 -q
313	sleep 1
314	brmcast_check_sg_entries "allow" "${X[@]}" "${Y[@]}"
315
316	brmcast_check_sg_state 0 "${X[@]}"
317	brmcast_check_sg_state 1 "${Y[@]}"
318
319	brmcast_check_sg_fwding 1 "${X[@]}" 2001:db8:1::100
320	brmcast_check_sg_fwding 0 "${Y[@]}"
321
322	log_test "MLDv2 report $TEST_GROUP exclude -> allow"
323
324	mldv2cleanup $swp1
325}
326
327trap cleanup EXIT
328
329setup_prepare
330setup_wait
331
332tests_run
333
334exit $EXIT_STATUS
335