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