Skip to content

Commit dbd9134

Browse files
pmachatakuba-moo
authored andcommitted
selftests: forwarding: Add test for BR_BOOLOPT_FDB_LOCAL_VLAN_0
Add a selftest to check the operation of this newly-introduced bridge option. Signed-off-by: Petr Machata <[email protected]> Acked-by: Nikolay Aleksandrov <[email protected]> Link: https://patch.msgid.link/62294f96884ab5d341648eef21243fa099a2dee5.1757004393.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski <[email protected]>
1 parent fa57032 commit dbd9134

File tree

2 files changed

+375
-0
lines changed

2 files changed

+375
-0
lines changed

tools/testing/selftests/net/forwarding/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ TEST_PROGS = \
55
bridge_fdb_learning_limit.sh \
66
bridge_igmp.sh \
77
bridge_locked_port.sh \
8+
bridge_fdb_local_vlan_0.sh \
89
bridge_mdb.sh \
910
bridge_mdb_host.sh \
1011
bridge_mdb_max.sh \
Lines changed: 374 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,374 @@
1+
#!/bin/bash
2+
# SPDX-License-Identifier: GPL-2.0
3+
4+
# +-----------------------+ +-----------------------+ +-----------------------+
5+
# | H1 (vrf) | | H2 (vrf) | | H3 (vrf) |
6+
# | + $h1 | | + $h2 | | + $h3 |
7+
# | | 192.0.2.1/28 | | | 192.0.2.2/28 | | | 192.0.2.18/28 |
8+
# | | 2001:db8:1::1/64 | | | 2001:db8:1::2/64 | | | 2001:db8:2::2/64 |
9+
# | | | | | | | | |
10+
# +----|------------------+ +----|------------------+ +----|------------------+
11+
# | | |
12+
# +----|-------------------------|-------------------------|------------------+
13+
# | +--|-------------------------|------------------+ | |
14+
# | | + $swp1 + $swp2 | + $swp3 |
15+
# | | | 192.0.2.17/28 |
16+
# | | BR1 (802.1q) | 2001:db8:2::1/64 |
17+
# | | 192.0.2.3/28 | |
18+
# | | 2001:db8:1::3/64 | |
19+
# | +-----------------------------------------------+ SW |
20+
# +---------------------------------------------------------------------------+
21+
#
22+
#shellcheck disable=SC2317 # SC doesn't see our uses of functions.
23+
#shellcheck disable=SC2034 # ... and global variables
24+
25+
ALL_TESTS="
26+
test_d_no_sharing
27+
test_d_sharing
28+
test_q_no_sharing
29+
test_q_sharing
30+
"
31+
32+
NUM_NETIFS=6
33+
source lib.sh
34+
35+
pMAC=00:11:22:33:44:55
36+
bMAC=00:11:22:33:44:66
37+
mMAC=00:11:22:33:44:77
38+
xMAC=00:11:22:33:44:88
39+
40+
host_create()
41+
{
42+
local h=$1; shift
43+
local ipv4=$1; shift
44+
local ipv6=$1; shift
45+
46+
simple_if_init "$h" "$ipv4" "$ipv6"
47+
defer simple_if_fini "$h" "$ipv4" "$ipv6"
48+
49+
ip_route_add vrf "v$h" 192.0.2.16/28 nexthop via 192.0.2.3
50+
ip_route_add vrf "v$h" 2001:db8:2::/64 nexthop via 2001:db8:1::3
51+
}
52+
53+
h3_create()
54+
{
55+
simple_if_init "$h3" 192.0.2.18/28 2001:db8:2::2/64
56+
defer simple_if_fini "$h3" 192.0.2.18/28 2001:db8:2::2/64
57+
58+
ip_route_add vrf "v$h3" 192.0.2.0/28 nexthop via 192.0.2.17
59+
ip_route_add vrf "v$h3" 2001:db8:1::/64 nexthop via 2001:db8:2::1
60+
61+
tc qdisc add dev "$h3" clsact
62+
defer tc qdisc del dev "$h3" clsact
63+
64+
tc filter add dev "$h3" ingress proto ip pref 104 \
65+
flower skip_hw ip_proto udp dst_port 4096 \
66+
action pass
67+
defer tc filter del dev "$h3" ingress proto ip pref 104
68+
69+
tc qdisc add dev "$h2" clsact
70+
defer tc qdisc del dev "$h2" clsact
71+
72+
tc filter add dev "$h2" ingress proto ip pref 104 \
73+
flower skip_hw ip_proto udp dst_port 4096 \
74+
action pass
75+
defer tc filter del dev "$h2" ingress proto ip pref 104
76+
}
77+
78+
switch_create()
79+
{
80+
ip_link_set_up "$swp1"
81+
82+
ip_link_set_up "$swp2"
83+
84+
ip_addr_add "$swp3" 192.0.2.17/28
85+
ip_addr_add "$swp3" 2001:db8:2::1/64
86+
ip_link_set_up "$swp3"
87+
}
88+
89+
setup_prepare()
90+
{
91+
h1=${NETIFS[p1]}
92+
swp1=${NETIFS[p2]}
93+
94+
swp2=${NETIFS[p3]}
95+
h2=${NETIFS[p4]}
96+
97+
swp3=${NETIFS[p5]}
98+
h3=${NETIFS[p6]}
99+
100+
vrf_prepare
101+
defer vrf_cleanup
102+
103+
forwarding_enable
104+
defer forwarding_restore
105+
106+
host_create "$h1" 192.0.2.1/28 2001:db8:1::1/64
107+
host_create "$h2" 192.0.2.2/28 2001:db8:1::2/64
108+
h3_create
109+
110+
switch_create
111+
}
112+
113+
adf_bridge_create()
114+
{
115+
local dev
116+
local mac
117+
118+
ip_link_add br up type bridge vlan_default_pvid 0 "$@"
119+
mac=$(mac_get br)
120+
ip_addr_add br 192.0.2.3/28
121+
ip_addr_add br 2001:db8:1::3/64
122+
123+
bridge_vlan_add dev br vid 1 pvid untagged self
124+
bridge_vlan_add dev br vid 2 self
125+
bridge_vlan_add dev br vid 3 self
126+
127+
for dev in "$swp1" "$swp2"; do
128+
ip_link_set_master "$dev" br
129+
bridge_vlan_add dev "$dev" vid 1 pvid untagged
130+
bridge_vlan_add dev "$dev" vid 2
131+
bridge_vlan_add dev "$dev" vid 3
132+
done
133+
134+
ip_link_set_addr br "$mac"
135+
}
136+
137+
check_fdb_local_vlan_0_support()
138+
{
139+
if ip_link_add XXbr up type bridge vlan_filtering 1 fdb_local_vlan_0 1 \
140+
&>/dev/null; then
141+
return 0
142+
fi
143+
144+
log_test_skip "FDB sharing" \
145+
"iproute 2 or the kernel do not support fdb_local_vlan_0"
146+
}
147+
148+
check_mac_presence()
149+
{
150+
local should_fail=$1; shift
151+
local dev=$1; shift
152+
local vlan=$1; shift
153+
local mac
154+
155+
mac=$(mac_get "$dev")
156+
157+
if ((vlan == 0)); then
158+
vlan=null
159+
fi
160+
161+
bridge -j fdb show dev "$dev" |
162+
jq -e --arg mac "$mac" --argjson vlan "$vlan" \
163+
'.[] | select(.mac == $mac) | select(.vlan == $vlan)' > /dev/null
164+
check_err_fail "$should_fail" $? "FDB dev $dev vid $vlan addr $mac exists"
165+
}
166+
167+
do_sharing_test()
168+
{
169+
local should_fail=$1; shift
170+
local what=$1; shift
171+
local dev
172+
173+
RET=0
174+
175+
for dev in "$swp1" "$swp2" br; do
176+
check_mac_presence 0 "$dev" 0
177+
check_mac_presence "$should_fail" "$dev" 1
178+
check_mac_presence "$should_fail" "$dev" 2
179+
check_mac_presence "$should_fail" "$dev" 3
180+
done
181+
182+
log_test "$what"
183+
}
184+
185+
do_end_to_end_test()
186+
{
187+
local mac=$1; shift
188+
local what=$1; shift
189+
local probe_dev=${1-$h3}; shift
190+
local expect=${1-10}; shift
191+
192+
local t0
193+
local t1
194+
local dd
195+
196+
RET=0
197+
198+
# In mausezahn, use $dev MAC as the destination MAC. In the MAC sharing
199+
# context, that will cause an FDB miss on VLAN 1 and prompt a second
200+
# lookup in VLAN 0.
201+
202+
t0=$(tc_rule_stats_get "$probe_dev" 104 ingress)
203+
204+
$MZ "$h1" -c 10 -p 64 -a own -b "$mac" \
205+
-A 192.0.2.1 -B 192.0.2.18 -t udp "dp=4096,sp=2048" -q
206+
sleep 1
207+
208+
t1=$(tc_rule_stats_get "$probe_dev" 104 ingress)
209+
dd=$((t1 - t0))
210+
211+
((dd == expect))
212+
check_err $? "Expected $expect packets on $probe_dev got $dd"
213+
214+
log_test "$what"
215+
}
216+
217+
do_tests()
218+
{
219+
local should_fail=$1; shift
220+
local what=$1; shift
221+
local swp1_mac
222+
local br_mac
223+
224+
swp1_mac=$(mac_get "$swp1")
225+
br_mac=$(mac_get br)
226+
227+
do_sharing_test "$should_fail" "$what"
228+
do_end_to_end_test "$swp1_mac" "$what: end to end, $swp1 MAC"
229+
do_end_to_end_test "$br_mac" "$what: end to end, br MAC"
230+
}
231+
232+
bridge_standard()
233+
{
234+
local vlan_filtering=$1; shift
235+
236+
if ((vlan_filtering)); then
237+
echo 802.1q
238+
else
239+
echo 802.1d
240+
fi
241+
}
242+
243+
nonexistent_fdb_test()
244+
{
245+
local vlan_filtering=$1; shift
246+
local standard
247+
248+
standard=$(bridge_standard "$vlan_filtering")
249+
250+
# We expect flooding, so $h2 should get the traffic.
251+
do_end_to_end_test "$xMAC" "$standard: Nonexistent FDB" "$h2"
252+
}
253+
254+
misleading_fdb_test()
255+
{
256+
local vlan_filtering=$1; shift
257+
local standard
258+
259+
standard=$(bridge_standard "$vlan_filtering")
260+
261+
defer_scope_push
262+
# Add an FDB entry on VLAN 0. The lookup on VLAN-aware bridge
263+
# shouldn't pick this up even with fdb_local_vlan_0 enabled, so
264+
# the traffic should be flooded. This all holds on
265+
# vlan_filtering bridge, on non-vlan_filtering one the FDB entry
266+
# is expected to be found as usual, no flooding takes place.
267+
#
268+
# Adding only on VLAN 0 is a bit tricky, because bridge is
269+
# trying to be nice and interprets the request as if the FDB
270+
# should be added on each VLAN.
271+
272+
bridge fdb add "$mMAC" dev "$swp1" master
273+
bridge fdb del "$mMAC" dev "$swp1" vlan 1 master
274+
bridge fdb del "$mMAC" dev "$swp1" vlan 2 master
275+
bridge fdb del "$mMAC" dev "$swp1" vlan 3 master
276+
277+
local expect=$((vlan_filtering ? 10 : 0))
278+
do_end_to_end_test "$mMAC" \
279+
"$standard: Lookup of non-local MAC on VLAN 0" \
280+
"$h2" "$expect"
281+
defer_scope_pop
282+
}
283+
284+
change_mac()
285+
{
286+
local dev=$1; shift
287+
local mac=$1; shift
288+
local cur_mac
289+
290+
cur_mac=$(mac_get "$dev")
291+
292+
log_info "Change $dev MAC $cur_mac -> $mac"
293+
ip_link_set_addr "$dev" "$mac"
294+
defer log_info "Change $dev MAC back"
295+
}
296+
297+
do_test_no_sharing()
298+
{
299+
local vlan_filtering=$1; shift
300+
local standard
301+
302+
standard=$(bridge_standard "$vlan_filtering")
303+
304+
adf_bridge_create vlan_filtering "$vlan_filtering"
305+
setup_wait
306+
307+
do_tests 0 "$standard, no FDB sharing"
308+
309+
change_mac "$swp1" "$pMAC"
310+
change_mac br "$bMAC"
311+
312+
do_tests 0 "$standard, no FDB sharing after MAC change"
313+
314+
in_defer_scope check_fdb_local_vlan_0_support || return
315+
316+
log_info "Set fdb_local_vlan_0=1"
317+
ip link set dev br type bridge fdb_local_vlan_0 1
318+
319+
do_tests 1 "$standard, fdb sharing after toggle"
320+
}
321+
322+
do_test_sharing()
323+
{
324+
local vlan_filtering=$1; shift
325+
local standard
326+
327+
standard=$(bridge_standard "$vlan_filtering")
328+
329+
in_defer_scope check_fdb_local_vlan_0_support || return
330+
331+
adf_bridge_create vlan_filtering "$vlan_filtering" fdb_local_vlan_0 1
332+
setup_wait
333+
334+
do_tests 1 "$standard, FDB sharing"
335+
336+
nonexistent_fdb_test "$vlan_filtering"
337+
misleading_fdb_test "$vlan_filtering"
338+
339+
change_mac "$swp1" "$pMAC"
340+
change_mac br "$bMAC"
341+
342+
do_tests 1 "$standard, FDB sharing after MAC change"
343+
344+
log_info "Set fdb_local_vlan_0=0"
345+
ip link set dev br type bridge fdb_local_vlan_0 0
346+
347+
do_tests 0 "$standard, No FDB sharing after toggle"
348+
}
349+
350+
test_d_no_sharing()
351+
{
352+
do_test_no_sharing 0
353+
}
354+
355+
test_d_sharing()
356+
{
357+
do_test_sharing 0
358+
}
359+
360+
test_q_no_sharing()
361+
{
362+
do_test_no_sharing 1
363+
}
364+
365+
test_q_sharing()
366+
{
367+
do_test_sharing 1
368+
}
369+
370+
371+
trap cleanup EXIT
372+
373+
setup_prepare
374+
tests_run

0 commit comments

Comments
 (0)