1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# +-----------------------+                             +----------------------+
5# | H1 (vrf)              |                             | H2 (vrf)             |
6# |    + $h1              |                             |              $h2 +   |
7# |    | 192.0.2.1/28     |                             |     192.0.2.2/28 |   |
8# |    | 2001:db8:1::1/64 |                             | 2001:db8:1::2/64 |   |
9# +----|------------------+                             +------------------|---+
10#      |                                                                   |
11# +----|-------------------------------------------------------------------|---+
12# | SW |                                                                   |   |
13# |  +-|-------------------------------------------------------------------|-+ |
14# |  | + $swp1                       BR                              $swp2 + | |
15# |  +-----------------------------------------------------------------------+ |
16# +----------------------------------------------------------------------------+
17
18ALL_TESTS="
19	test_l2_miss_unicast
20	test_l2_miss_multicast
21	test_l2_miss_ll_multicast
22	test_l2_miss_broadcast
23"
24
25NUM_NETIFS=4
26source lib.sh
27source tc_common.sh
28
29h1_create()
30{
31	simple_if_init $h1 192.0.2.1/28 2001:db8:1::1/64
32}
33
34h1_destroy()
35{
36	simple_if_fini $h1 192.0.2.1/28 2001:db8:1::1/64
37}
38
39h2_create()
40{
41	simple_if_init $h2 192.0.2.2/28 2001:db8:1::2/64
42}
43
44h2_destroy()
45{
46	simple_if_fini $h2 192.0.2.2/28 2001:db8:1::2/64
47}
48
49switch_create()
50{
51	ip link add name br1 up type bridge
52	ip link set dev $swp1 master br1
53	ip link set dev $swp1 up
54	ip link set dev $swp2 master br1
55	ip link set dev $swp2 up
56
57	tc qdisc add dev $swp2 clsact
58}
59
60switch_destroy()
61{
62	tc qdisc del dev $swp2 clsact
63
64	ip link set dev $swp2 down
65	ip link set dev $swp2 nomaster
66	ip link set dev $swp1 down
67	ip link set dev $swp1 nomaster
68	ip link del dev br1
69}
70
71test_l2_miss_unicast()
72{
73	local dmac=00:01:02:03:04:05
74	local dip=192.0.2.2
75	local sip=192.0.2.1
76
77	RET=0
78
79	# Unknown unicast.
80	tc filter add dev $swp2 egress protocol ipv4 handle 101 pref 1 \
81	   flower indev $swp1 l2_miss 1 dst_mac $dmac src_ip $sip \
82	   dst_ip $dip action pass
83	# Known unicast.
84	tc filter add dev $swp2 egress protocol ipv4 handle 102 pref 1 \
85	   flower indev $swp1 l2_miss 0 dst_mac $dmac src_ip $sip \
86	   dst_ip $dip action pass
87
88	# Before adding FDB entry.
89	$MZ $h1 -a own -b $dmac -t ip -A $sip -B $dip -c 1 -p 100 -q
90
91	tc_check_packets "dev $swp2 egress" 101 1
92	check_err $? "Unknown unicast filter was not hit before adding FDB entry"
93
94	tc_check_packets "dev $swp2 egress" 102 0
95	check_err $? "Known unicast filter was hit before adding FDB entry"
96
97	# Adding FDB entry.
98	bridge fdb replace $dmac dev $swp2 master static
99
100	$MZ $h1 -a own -b $dmac -t ip -A $sip -B $dip -c 1 -p 100 -q
101
102	tc_check_packets "dev $swp2 egress" 101 1
103	check_err $? "Unknown unicast filter was hit after adding FDB entry"
104
105	tc_check_packets "dev $swp2 egress" 102 1
106	check_err $? "Known unicast filter was not hit after adding FDB entry"
107
108	# Deleting FDB entry.
109	bridge fdb del $dmac dev $swp2 master static
110
111	$MZ $h1 -a own -b $dmac -t ip -A $sip -B $dip -c 1 -p 100 -q
112
113	tc_check_packets "dev $swp2 egress" 101 2
114	check_err $? "Unknown unicast filter was not hit after deleting FDB entry"
115
116	tc_check_packets "dev $swp2 egress" 102 1
117	check_err $? "Known unicast filter was hit after deleting FDB entry"
118
119	tc filter del dev $swp2 egress protocol ipv4 pref 1 handle 102 flower
120	tc filter del dev $swp2 egress protocol ipv4 pref 1 handle 101 flower
121
122	log_test "L2 miss - Unicast"
123}
124
125test_l2_miss_multicast_common()
126{
127	local proto=$1; shift
128	local sip=$1; shift
129	local dip=$1; shift
130	local dmac=$1; shift
131	local mode=$1; shift
132	local name=$1; shift
133
134	RET=0
135
136	# Unregistered multicast.
137	tc filter add dev $swp2 egress protocol $proto handle 101 pref 1 \
138	   flower indev $swp1 l2_miss 1 src_ip $sip dst_ip $dip \
139	   action pass
140	# Registered multicast.
141	tc filter add dev $swp2 egress protocol $proto handle 102 pref 1 \
142	   flower indev $swp1 l2_miss 0 src_ip $sip dst_ip $dip \
143	   action pass
144
145	# Before adding MDB entry.
146	$MZ $mode $h1 -a own -b $dmac -t ip -A $sip -B $dip -c 1 -p 100 -q
147
148	tc_check_packets "dev $swp2 egress" 101 1
149	check_err $? "Unregistered multicast filter was not hit before adding MDB entry"
150
151	tc_check_packets "dev $swp2 egress" 102 0
152	check_err $? "Registered multicast filter was hit before adding MDB entry"
153
154	# Adding MDB entry.
155	bridge mdb replace dev br1 port $swp2 grp $dip permanent
156
157	$MZ $mode $h1 -a own -b $dmac -t ip -A $sip -B $dip -c 1 -p 100 -q
158
159	tc_check_packets "dev $swp2 egress" 101 1
160	check_err $? "Unregistered multicast filter was hit after adding MDB entry"
161
162	tc_check_packets "dev $swp2 egress" 102 1
163	check_err $? "Registered multicast filter was not hit after adding MDB entry"
164
165	# Deleting MDB entry.
166	bridge mdb del dev br1 port $swp2 grp $dip
167
168	$MZ $mode $h1 -a own -b $dmac -t ip -A $sip -B $dip -c 1 -p 100 -q
169
170	tc_check_packets "dev $swp2 egress" 101 2
171	check_err $? "Unregistered multicast filter was not hit after deleting MDB entry"
172
173	tc_check_packets "dev $swp2 egress" 102 1
174	check_err $? "Registered multicast filter was hit after deleting MDB entry"
175
176	tc filter del dev $swp2 egress protocol $proto pref 1 handle 102 flower
177	tc filter del dev $swp2 egress protocol $proto pref 1 handle 101 flower
178
179	log_test "L2 miss - Multicast ($name)"
180}
181
182test_l2_miss_multicast_ipv4()
183{
184	local proto="ipv4"
185	local sip=192.0.2.1
186	local dip=239.1.1.1
187	local dmac=01:00:5e:01:01:01
188	local mode="-4"
189	local name="IPv4"
190
191	test_l2_miss_multicast_common $proto $sip $dip $dmac $mode $name
192}
193
194test_l2_miss_multicast_ipv6()
195{
196	local proto="ipv6"
197	local sip=2001:db8:1::1
198	local dip=ff0e::1
199	local dmac=33:33:00:00:00:01
200	local mode="-6"
201	local name="IPv6"
202
203	test_l2_miss_multicast_common $proto $sip $dip $dmac $mode $name
204}
205
206test_l2_miss_multicast()
207{
208	# Configure $swp2 as a multicast router port so that it will forward
209	# both registered and unregistered multicast traffic.
210	bridge link set dev $swp2 mcast_router 2
211
212	# Set the Max Response Delay to 100 centiseconds (1 second) so that the
213	# bridge will start forwarding according to its MDB soon after a
214	# multicast querier is enabled.
215	ip link set dev br1 type bridge mcast_query_response_interval 100
216
217	# Forwarding according to MDB entries only takes place when the bridge
218	# detects that there is a valid querier in the network. Set the bridge
219	# as the querier and assign it a valid IPv6 link-local address to be
220	# used as the source address for MLD queries.
221	ip link set dev br1 type bridge mcast_querier 1
222	ip -6 address add fe80::1/64 nodad dev br1
223	sleep 10
224
225	test_l2_miss_multicast_ipv4
226	test_l2_miss_multicast_ipv6
227
228	ip -6 address del fe80::1/64 dev br1
229	ip link set dev br1 type bridge mcast_querier 0
230	ip link set dev br1 type bridge mcast_query_response_interval 1000
231	bridge link set dev $swp2 mcast_router 1
232}
233
234test_l2_miss_multicast_common2()
235{
236	local name=$1; shift
237	local dmac=$1; shift
238	local dip=224.0.0.1
239	local sip=192.0.2.1
240
241}
242
243test_l2_miss_ll_multicast_common()
244{
245	local proto=$1; shift
246	local dmac=$1; shift
247	local sip=$1; shift
248	local dip=$1; shift
249	local mode=$1; shift
250	local name=$1; shift
251
252	RET=0
253
254	tc filter add dev $swp2 egress protocol $proto handle 101 pref 1 \
255	   flower indev $swp1 l2_miss 1 dst_mac $dmac src_ip $sip \
256	   dst_ip $dip action pass
257
258	$MZ $mode $h1 -a own -b $dmac -t ip -A $sip -B $dip -c 1 -p 100 -q
259
260	tc_check_packets "dev $swp2 egress" 101 1
261	check_err $? "Filter was not hit"
262
263	tc filter del dev $swp2 egress protocol $proto pref 1 handle 101 flower
264
265	log_test "L2 miss - Link-local multicast ($name)"
266}
267
268test_l2_miss_ll_multicast_ipv4()
269{
270	local proto=ipv4
271	local dmac=01:00:5e:00:00:01
272	local sip=192.0.2.1
273	local dip=224.0.0.1
274	local mode="-4"
275	local name="IPv4"
276
277	test_l2_miss_ll_multicast_common $proto $dmac $sip $dip $mode $name
278}
279
280test_l2_miss_ll_multicast_ipv6()
281{
282	local proto=ipv6
283	local dmac=33:33:00:00:00:01
284	local sip=2001:db8:1::1
285	local dip=ff02::1
286	local mode="-6"
287	local name="IPv6"
288
289	test_l2_miss_ll_multicast_common $proto $dmac $sip $dip $mode $name
290}
291
292test_l2_miss_ll_multicast()
293{
294	test_l2_miss_ll_multicast_ipv4
295	test_l2_miss_ll_multicast_ipv6
296}
297
298test_l2_miss_broadcast()
299{
300	local dmac=ff:ff:ff:ff:ff:ff
301	local smac=00:01:02:03:04:05
302
303	RET=0
304
305	tc filter add dev $swp2 egress protocol all handle 101 pref 1 \
306	   flower l2_miss 1 dst_mac $dmac src_mac $smac \
307	   action pass
308	tc filter add dev $swp2 egress protocol all handle 102 pref 1 \
309	   flower l2_miss 0 dst_mac $dmac src_mac $smac \
310	   action pass
311
312	$MZ $h1 -a $smac -b $dmac -c 1 -p 100 -q
313
314	tc_check_packets "dev $swp2 egress" 101 0
315	check_err $? "L2 miss filter was hit when should not"
316
317	tc_check_packets "dev $swp2 egress" 102 1
318	check_err $? "L2 no miss filter was not hit when should"
319
320	tc filter del dev $swp2 egress protocol all pref 1 handle 102 flower
321	tc filter del dev $swp2 egress protocol all pref 1 handle 101 flower
322
323	log_test "L2 miss - Broadcast"
324}
325
326setup_prepare()
327{
328	h1=${NETIFS[p1]}
329	swp1=${NETIFS[p2]}
330
331	swp2=${NETIFS[p3]}
332	h2=${NETIFS[p4]}
333
334	vrf_prepare
335	h1_create
336	h2_create
337	switch_create
338}
339
340cleanup()
341{
342	pre_cleanup
343
344	switch_destroy
345	h2_destroy
346	h1_destroy
347	vrf_cleanup
348}
349
350trap cleanup EXIT
351
352setup_prepare
353setup_wait
354
355tests_run
356
357exit $EXIT_STATUS
358