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	# Forwarding according to MDB entries only takes place when the bridge
213	# detects that there is a valid querier in the network. Set the bridge
214	# as the querier and assign it a valid IPv6 link-local address to be
215	# used as the source address for MLD queries.
216	ip link set dev br1 type bridge mcast_querier 1
217	ip -6 address add fe80::1/64 nodad dev br1
218	# Wait the default Query Response Interval (10 seconds) for the bridge
219	# to determine that there are no other queriers in the network.
220	sleep 10
221
222	test_l2_miss_multicast_ipv4
223	test_l2_miss_multicast_ipv6
224
225	ip -6 address del fe80::1/64 dev br1
226	ip link set dev br1 type bridge mcast_querier 0
227	bridge link set dev $swp2 mcast_router 1
228}
229
230test_l2_miss_multicast_common2()
231{
232	local name=$1; shift
233	local dmac=$1; shift
234	local dip=224.0.0.1
235	local sip=192.0.2.1
236
237}
238
239test_l2_miss_ll_multicast_common()
240{
241	local proto=$1; shift
242	local dmac=$1; shift
243	local sip=$1; shift
244	local dip=$1; shift
245	local mode=$1; shift
246	local name=$1; shift
247
248	RET=0
249
250	tc filter add dev $swp2 egress protocol $proto handle 101 pref 1 \
251	   flower indev $swp1 l2_miss 1 dst_mac $dmac src_ip $sip \
252	   dst_ip $dip action pass
253
254	$MZ $mode $h1 -a own -b $dmac -t ip -A $sip -B $dip -c 1 -p 100 -q
255
256	tc_check_packets "dev $swp2 egress" 101 1
257	check_err $? "Filter was not hit"
258
259	tc filter del dev $swp2 egress protocol $proto pref 1 handle 101 flower
260
261	log_test "L2 miss - Link-local multicast ($name)"
262}
263
264test_l2_miss_ll_multicast_ipv4()
265{
266	local proto=ipv4
267	local dmac=01:00:5e:00:00:01
268	local sip=192.0.2.1
269	local dip=224.0.0.1
270	local mode="-4"
271	local name="IPv4"
272
273	test_l2_miss_ll_multicast_common $proto $dmac $sip $dip $mode $name
274}
275
276test_l2_miss_ll_multicast_ipv6()
277{
278	local proto=ipv6
279	local dmac=33:33:00:00:00:01
280	local sip=2001:db8:1::1
281	local dip=ff02::1
282	local mode="-6"
283	local name="IPv6"
284
285	test_l2_miss_ll_multicast_common $proto $dmac $sip $dip $mode $name
286}
287
288test_l2_miss_ll_multicast()
289{
290	test_l2_miss_ll_multicast_ipv4
291	test_l2_miss_ll_multicast_ipv6
292}
293
294test_l2_miss_broadcast()
295{
296	local dmac=ff:ff:ff:ff:ff:ff
297	local smac=00:01:02:03:04:05
298
299	RET=0
300
301	tc filter add dev $swp2 egress protocol all handle 101 pref 1 \
302	   flower l2_miss 1 dst_mac $dmac src_mac $smac \
303	   action pass
304	tc filter add dev $swp2 egress protocol all handle 102 pref 1 \
305	   flower l2_miss 0 dst_mac $dmac src_mac $smac \
306	   action pass
307
308	$MZ $h1 -a $smac -b $dmac -c 1 -p 100 -q
309
310	tc_check_packets "dev $swp2 egress" 101 0
311	check_err $? "L2 miss filter was hit when should not"
312
313	tc_check_packets "dev $swp2 egress" 102 1
314	check_err $? "L2 no miss filter was not hit when should"
315
316	tc filter del dev $swp2 egress protocol all pref 1 handle 102 flower
317	tc filter del dev $swp2 egress protocol all pref 1 handle 101 flower
318
319	log_test "L2 miss - Broadcast"
320}
321
322setup_prepare()
323{
324	h1=${NETIFS[p1]}
325	swp1=${NETIFS[p2]}
326
327	swp2=${NETIFS[p3]}
328	h2=${NETIFS[p4]}
329
330	vrf_prepare
331	h1_create
332	h2_create
333	switch_create
334}
335
336cleanup()
337{
338	pre_cleanup
339
340	switch_destroy
341	h2_destroy
342	h1_destroy
343	vrf_cleanup
344}
345
346trap cleanup EXIT
347
348setup_prepare
349setup_wait
350
351tests_run
352
353exit $EXIT_STATUS
354