Skip to content

Commit 9aa3749

Browse files
vladimirolteandavem330
authored andcommitted
selftests: net: local_termination: don't use xfail_on_veth()
xfail_on_veth() for this test is an incorrect approximation which gives false positives and false negatives. When local_termination fails with "reception succeeded, but should have failed", it is because the DUT ($h2) accepts packets even when not configured as promiscuous. This is not something specific to veth; even the bridge behaves that way, but this is not captured by the xfail_on_veth test. The IFF_UNICAST_FLT flag is not explicitly exported to user space, but it can somewhat be determined from the interface's behavior. We have to create a macvlan upper with a different MAC address. This forces a dev_uc_add() call in the kernel. When the unicast filtering list is not empty, but the device doesn't support IFF_UNICAST_FLT, __dev_set_rx_mode() force-enables promiscuity on the interface, to ensure correct behavior (that the requested address is received). We can monitor the change in the promiscuity flag and infer from it whether the device supports unicast filtering. There is no equivalent thing for allmulti, unfortunately. We never know what's hiding behind a device which has allmulti=off. Whether it will actually perform RX multicast filtering of unknown traffic is a strong "maybe". The bridge driver, for example, completely ignores the flag. We'll have to keep the xfail behavior, but instead of XFAIL on just veth, always XFAIL. Signed-off-by: Vladimir Oltean <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 5fea8bb commit 9aa3749

File tree

2 files changed

+99
-16
lines changed

2 files changed

+99
-16
lines changed

tools/testing/selftests/net/forwarding/lib.sh

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,11 @@ check_err_fail()
500500
fi
501501
}
502502

503+
xfail()
504+
{
505+
FAIL_TO_XFAIL=yes "$@"
506+
}
507+
503508
xfail_on_slow()
504509
{
505510
if [[ $KSFT_MACHINE_SLOW = yes ]]; then
@@ -1113,6 +1118,39 @@ mac_get()
11131118
ip -j link show dev $if_name | jq -r '.[]["address"]'
11141119
}
11151120

1121+
ether_addr_to_u64()
1122+
{
1123+
local addr="$1"
1124+
local order="$((1 << 40))"
1125+
local val=0
1126+
local byte
1127+
1128+
addr="${addr//:/ }"
1129+
1130+
for byte in $addr; do
1131+
byte="0x$byte"
1132+
val=$((val + order * byte))
1133+
order=$((order >> 8))
1134+
done
1135+
1136+
printf "0x%x" $val
1137+
}
1138+
1139+
u64_to_ether_addr()
1140+
{
1141+
local val=$1
1142+
local byte
1143+
local i
1144+
1145+
for ((i = 40; i >= 0; i -= 8)); do
1146+
byte=$(((val & (0xff << i)) >> i))
1147+
printf "%02x" $byte
1148+
if [ $i -ne 0 ]; then
1149+
printf ":"
1150+
fi
1151+
done
1152+
}
1153+
11161154
ipv6_lladdr_get()
11171155
{
11181156
local if_name=$1
@@ -2229,3 +2267,22 @@ absval()
22292267

22302268
echo $((v > 0 ? v : -v))
22312269
}
2270+
2271+
has_unicast_flt()
2272+
{
2273+
local dev=$1; shift
2274+
local mac_addr=$(mac_get $dev)
2275+
local tmp=$(ether_addr_to_u64 $mac_addr)
2276+
local promisc
2277+
2278+
ip link set $dev up
2279+
ip link add link $dev name macvlan-tmp type macvlan mode private
2280+
ip link set macvlan-tmp address $(u64_to_ether_addr $((tmp + 1)))
2281+
ip link set macvlan-tmp up
2282+
2283+
promisc=$(ip -j -d link show dev $dev | jq -r '.[].promiscuity')
2284+
2285+
ip link del macvlan-tmp
2286+
2287+
[[ $promisc == 1 ]] && echo "no" || echo "yes"
2288+
}

tools/testing/selftests/net/forwarding/local_termination.sh

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,11 @@ run_test()
109109
{
110110
local send_if_name=$1; shift
111111
local rcv_if_name=$1; shift
112+
local no_unicast_flt=$1; shift
112113
local test_name="$1"; shift
113114
local smac=$(mac_get $send_if_name)
114115
local rcv_dmac=$(mac_get $rcv_if_name)
116+
local should_receive
115117

116118
tcpdump_start $rcv_if_name
117119

@@ -160,26 +162,26 @@ run_test()
160162
"$smac > $MACVLAN_ADDR, ethertype IPv4 (0x0800)" \
161163
true "$test_name"
162164

163-
xfail_on_veth $h1 \
164-
check_rcv $rcv_if_name "Unicast IPv4 to unknown MAC address" \
165-
"$smac > $UNKNOWN_UC_ADDR1, ethertype IPv4 (0x0800)" \
166-
false "$test_name"
165+
[ $no_unicast_flt = true ] && should_receive=true || should_receive=false
166+
check_rcv $rcv_if_name "Unicast IPv4 to unknown MAC address" \
167+
"$smac > $UNKNOWN_UC_ADDR1, ethertype IPv4 (0x0800)" \
168+
$should_receive "$test_name"
167169

168170
check_rcv $rcv_if_name "Unicast IPv4 to unknown MAC address, promisc" \
169171
"$smac > $UNKNOWN_UC_ADDR2, ethertype IPv4 (0x0800)" \
170172
true "$test_name"
171173

172-
xfail_on_veth $h1 \
173-
check_rcv $rcv_if_name \
174-
"Unicast IPv4 to unknown MAC address, allmulti" \
175-
"$smac > $UNKNOWN_UC_ADDR3, ethertype IPv4 (0x0800)" \
176-
false "$test_name"
174+
[ $no_unicast_flt = true ] && should_receive=true || should_receive=false
175+
check_rcv $rcv_if_name \
176+
"Unicast IPv4 to unknown MAC address, allmulti" \
177+
"$smac > $UNKNOWN_UC_ADDR3, ethertype IPv4 (0x0800)" \
178+
$should_receive "$test_name"
177179

178180
check_rcv $rcv_if_name "Multicast IPv4 to joined group" \
179181
"$smac > $JOINED_MACV4_MC_ADDR, ethertype IPv4 (0x0800)" \
180182
true "$test_name"
181183

182-
xfail_on_veth $h1 \
184+
xfail \
183185
check_rcv $rcv_if_name \
184186
"Multicast IPv4 to unknown group" \
185187
"$smac > $UNKNOWN_MACV4_MC_ADDR1, ethertype IPv4 (0x0800)" \
@@ -197,7 +199,7 @@ run_test()
197199
"$smac > $JOINED_MACV6_MC_ADDR, ethertype IPv6 (0x86dd)" \
198200
true "$test_name"
199201

200-
xfail_on_veth $h1 \
202+
xfail \
201203
check_rcv $rcv_if_name "Multicast IPv6 to unknown group" \
202204
"$smac > $UNKNOWN_MACV6_MC_ADDR1, ethertype IPv6 (0x86dd)" \
203205
false "$test_name"
@@ -290,11 +292,17 @@ macvlan_destroy()
290292

291293
standalone()
292294
{
295+
local no_unicast_flt=true
296+
297+
if [ $(has_unicast_flt $h2) = yes ]; then
298+
no_unicast_flt=false
299+
fi
300+
293301
h1_create
294302
h2_create
295303
macvlan_create $h2
296304

297-
run_test $h1 $h2 "$h2"
305+
run_test $h1 $h2 $no_unicast_flt "$h2"
298306

299307
macvlan_destroy
300308
h2_destroy
@@ -303,14 +311,15 @@ standalone()
303311

304312
test_bridge()
305313
{
314+
local no_unicast_flt=true
306315
local vlan_filtering=$1
307316

308317
h1_create
309318
bridge_create $vlan_filtering
310319
simple_if_init br0 $H2_IPV4/24 $H2_IPV6/64
311320
macvlan_create br0
312321

313-
run_test $h1 br0 "vlan_filtering=$vlan_filtering bridge"
322+
run_test $h1 br0 $no_unicast_flt "vlan_filtering=$vlan_filtering bridge"
314323

315324
macvlan_destroy
316325
simple_if_fini br0 $H2_IPV4/24 $H2_IPV6/64
@@ -330,11 +339,17 @@ vlan_aware_bridge()
330339

331340
test_vlan()
332341
{
342+
local no_unicast_flt=true
343+
344+
if [ $(has_unicast_flt $h2) = yes ]; then
345+
no_unicast_flt=false
346+
fi
347+
333348
h1_vlan_create
334349
h2_vlan_create
335350
macvlan_create $h2.100
336351

337-
run_test $h1.100 $h2.100 "VLAN upper"
352+
run_test $h1.100 $h2.100 $no_unicast_flt "VLAN upper"
338353

339354
macvlan_destroy
340355
h2_vlan_destroy
@@ -343,14 +358,23 @@ test_vlan()
343358

344359
vlan_over_bridged_port()
345360
{
361+
local no_unicast_flt=true
346362
local vlan_filtering=$1
347363

364+
# br_manage_promisc() will not force a single vlan_filtering port to
365+
# promiscuous mode, so we should still expect unicast filtering to take
366+
# place if the device can do it.
367+
if [ $(has_unicast_flt $h2) = yes ] && [ $vlan_filtering = 1 ]; then
368+
no_unicast_flt=false
369+
fi
370+
348371
h1_vlan_create
349372
h2_vlan_create
350373
bridge_create $vlan_filtering
351374
macvlan_create $h2.100
352375

353-
run_test $h1.100 $h2.100 "VLAN over vlan_filtering=$vlan_filtering bridged port"
376+
run_test $h1.100 $h2.100 $no_unicast_flt \
377+
"VLAN over vlan_filtering=$vlan_filtering bridged port"
354378

355379
macvlan_destroy
356380
bridge_destroy
@@ -370,6 +394,7 @@ vlan_over_vlan_aware_bridged_port()
370394

371395
vlan_over_bridge()
372396
{
397+
local no_unicast_flt=true
373398
local vlan_filtering=$1
374399

375400
h1_vlan_create
@@ -383,7 +408,8 @@ vlan_over_bridge()
383408
bridge vlan add dev br0 vid 100 self
384409
fi
385410

386-
run_test $h1.100 br0.100 "VLAN over vlan_filtering=$vlan_filtering bridge"
411+
run_test $h1.100 br0.100 $no_unicast_flt \
412+
"VLAN over vlan_filtering=$vlan_filtering bridge"
387413

388414
if [ $vlan_filtering = 1 ]; then
389415
bridge vlan del dev br0 vid 100 self

0 commit comments

Comments
 (0)