Skip to content

Commit 330689f

Browse files
committed
Merge branch 'bridge-prevent-unicast-arp-ns-packets-from-being-suppressed-by-bridge'
Amit Cohen says: ==================== bridge: Prevent unicast ARP/NS packets from being suppressed by bridge Currently, unicast ARP requests/NS packets are replied by bridge when suppression is enabled, then they are also forwarded, which results two replicas of ARP reply/NA - one from the bridge and second from the target. The purpose of ARP/ND suppression is to reduce flooding in the broadcast domain, which is not relevant for unicast packets. In addition, the use case of unicast ARP/NS is to poll a specific host, so it does not make sense to have the switch answer on behalf of the host. Forward ARP requests/NS packets and prevent the bridge from replying to them. Patch set overview: Patch #1 prevents unicast ARP/NS packets from being suppressed by bridge Patch #2 adds test cases for unicast ARP/NS with suppression enabled ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 229671a + 0ffb594 commit 330689f

File tree

2 files changed

+132
-0
lines changed

2 files changed

+132
-0
lines changed

net/bridge/br_arp_nd_proxy.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,9 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
160160
if (br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED)) {
161161
if (br_is_neigh_suppress_enabled(p, vid))
162162
return;
163+
if (is_unicast_ether_addr(eth_hdr(skb)->h_dest) &&
164+
parp->ar_op == htons(ARPOP_REQUEST))
165+
return;
163166
if (parp->ar_op != htons(ARPOP_RREQUEST) &&
164167
parp->ar_op != htons(ARPOP_RREPLY) &&
165168
(ipv4_is_zeronet(sip) || sip == tip)) {
@@ -410,6 +413,10 @@ void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br,
410413
if (br_is_neigh_suppress_enabled(p, vid))
411414
return;
412415

416+
if (is_unicast_ether_addr(eth_hdr(skb)->h_dest) &&
417+
msg->icmph.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION)
418+
return;
419+
413420
if (msg->icmph.icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT &&
414421
!msg->icmph.icmp6_solicited) {
415422
/* prevent flooding to neigh suppress ports */

tools/testing/selftests/net/test_bridge_neigh_suppress.sh

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ ret=0
5151
# All tests in this script. Can be overridden with -t option.
5252
TESTS="
5353
neigh_suppress_arp
54+
neigh_suppress_uc_arp
5455
neigh_suppress_ns
56+
neigh_suppress_uc_ns
5557
neigh_vlan_suppress_arp
5658
neigh_vlan_suppress_ns
5759
"
@@ -388,6 +390,52 @@ neigh_suppress_arp()
388390
neigh_suppress_arp_common $vid $sip $tip
389391
}
390392

393+
neigh_suppress_uc_arp_common()
394+
{
395+
local vid=$1; shift
396+
local sip=$1; shift
397+
local tip=$1; shift
398+
local tmac
399+
400+
echo
401+
echo "Unicast ARP, per-port ARP suppression - VLAN $vid"
402+
echo "-----------------------------------------------"
403+
404+
run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress on"
405+
run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress on\""
406+
log_test $? 0 "\"neigh_suppress\" is on"
407+
408+
tmac=$(ip -n $h2 -j -p link show eth0.$vid | jq -r '.[]["address"]')
409+
run_cmd "bridge -n $sw1 fdb replace $tmac dev vx0 master static vlan $vid"
410+
run_cmd "ip -n $sw1 neigh replace $tip lladdr $tmac nud permanent dev br0.$vid"
411+
412+
run_cmd "tc -n $h1 qdisc replace dev eth0.$vid clsact"
413+
run_cmd "tc -n $h1 filter replace dev eth0.$vid ingress pref 1 handle 101 proto arp flower arp_sip $tip arp_op reply action pass"
414+
415+
run_cmd "tc -n $h2 qdisc replace dev eth0.$vid clsact"
416+
run_cmd "tc -n $h2 filter replace dev eth0.$vid egress pref 1 handle 101 proto arp flower arp_tip $sip arp_op reply action pass"
417+
418+
run_cmd "ip netns exec $h1 mausezahn eth0.$vid -c 1 -a own -b $tmac -t arp 'request sip=$sip, tip=$tip, tmac=$tmac' -q"
419+
tc_check_packets $h1 "dev eth0.$vid ingress" 101 1
420+
log_test $? 0 "Unicast ARP, suppression on, h1 filter"
421+
tc_check_packets $h2 "dev eth0.$vid egress" 101 1
422+
log_test $? 0 "Unicast ARP, suppression on, h2 filter"
423+
}
424+
425+
neigh_suppress_uc_arp()
426+
{
427+
local vid=10
428+
local sip=192.0.2.1
429+
local tip=192.0.2.2
430+
431+
neigh_suppress_uc_arp_common $vid $sip $tip
432+
433+
vid=20
434+
sip=192.0.2.17
435+
tip=192.0.2.18
436+
neigh_suppress_uc_arp_common $vid $sip $tip
437+
}
438+
391439
neigh_suppress_ns_common()
392440
{
393441
local vid=$1; shift
@@ -494,6 +542,78 @@ neigh_suppress_ns()
494542
neigh_suppress_ns_common $vid $saddr $daddr $maddr
495543
}
496544

545+
icmpv6_header_get()
546+
{
547+
local csum=$1; shift
548+
local tip=$1; shift
549+
local type
550+
local p
551+
552+
# Type 135 (Neighbor Solicitation), hex format
553+
type="87"
554+
p=$(:
555+
)"$type:"$( : ICMPv6.type
556+
)"00:"$( : ICMPv6.code
557+
)"$csum:"$( : ICMPv6.checksum
558+
)"00:00:00:00:"$( : Reserved
559+
)"$tip:"$( : Target Address
560+
)
561+
echo $p
562+
}
563+
564+
neigh_suppress_uc_ns_common()
565+
{
566+
local vid=$1; shift
567+
local sip=$1; shift
568+
local dip=$1; shift
569+
local full_dip=$1; shift
570+
local csum=$1; shift
571+
local tmac
572+
573+
echo
574+
echo "Unicast NS, per-port NS suppression - VLAN $vid"
575+
echo "---------------------------------------------"
576+
577+
run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress on"
578+
run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress on\""
579+
log_test $? 0 "\"neigh_suppress\" is on"
580+
581+
tmac=$(ip -n $h2 -j -p link show eth0.$vid | jq -r '.[]["address"]')
582+
run_cmd "bridge -n $sw1 fdb replace $tmac dev vx0 master static vlan $vid"
583+
run_cmd "ip -n $sw1 -6 neigh replace $dip lladdr $tmac nud permanent dev br0.$vid"
584+
585+
run_cmd "tc -n $h1 qdisc replace dev eth0.$vid clsact"
586+
run_cmd "tc -n $h1 filter replace dev eth0.$vid ingress pref 1 handle 101 proto ipv6 flower ip_proto icmpv6 src_ip $dip type 136 code 0 action pass"
587+
588+
run_cmd "tc -n $h2 qdisc replace dev eth0.$vid clsact"
589+
run_cmd "tc -n $h2 filter replace dev eth0.$vid egress pref 1 handle 101 proto ipv6 flower ip_proto icmpv6 dst_ip $sip type 136 code 0 action pass"
590+
591+
run_cmd "ip netns exec $h1 mausezahn -6 eth0.$vid -c 1 -a own -b $tmac -A $sip -B $dip -t ip hop=255,next=58,payload=$(icmpv6_header_get $csum $full_dip) -q"
592+
tc_check_packets $h1 "dev eth0.$vid ingress" 101 1
593+
log_test $? 0 "Unicast NS, suppression on, h1 filter"
594+
tc_check_packets $h2 "dev eth0.$vid egress" 101 1
595+
log_test $? 0 "Unicast NS, suppression on, h2 filter"
596+
}
597+
598+
neigh_suppress_uc_ns()
599+
{
600+
local vid=10
601+
local saddr=2001:db8:1::1
602+
local daddr=2001:db8:1::2
603+
local full_daddr=20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:02
604+
local csum="ef:79"
605+
606+
neigh_suppress_uc_ns_common $vid $saddr $daddr $full_daddr $csum
607+
608+
vid=20
609+
saddr=2001:db8:2::1
610+
daddr=2001:db8:2::2
611+
full_daddr=20:01:0d:b8:00:02:00:00:00:00:00:00:00:00:00:02
612+
csum="ef:76"
613+
614+
neigh_suppress_uc_ns_common $vid $saddr $daddr $full_daddr $csum
615+
}
616+
497617
neigh_vlan_suppress_arp()
498618
{
499619
local vid1=10
@@ -825,6 +945,11 @@ if [ ! -x "$(command -v jq)" ]; then
825945
exit $ksft_skip
826946
fi
827947

948+
if [ ! -x "$(command -v mausezahn)" ]; then
949+
echo "SKIP: Could not run test without mausezahn tool"
950+
exit $ksft_skip
951+
fi
952+
828953
bridge link help 2>&1 | grep -q "neigh_vlan_suppress"
829954
if [ $? -ne 0 ]; then
830955
echo "SKIP: iproute2 bridge too old, missing per-VLAN neighbor suppression support"

0 commit comments

Comments
 (0)