From e74216b8def3803e98ae536de78733e9d7f3b109 Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Wed, 23 Aug 2023 15:19:04 +0800 Subject: [PATCH 1/3] bonding: fix macvlan over alb bond support The commit 14af9963ba1e ("bonding: Support macvlans on top of tlb/rlb mode bonds") aims to enable the use of macvlans on top of rlb bond mode. However, the current rlb bond mode only handles ARP packets to update remote neighbor entries. This causes an issue when a macvlan is on top of the bond, and remote devices send packets to the macvlan using the bond's MAC address as the destination. After delivering the packets to the macvlan, the macvlan will rejects them as the MAC address is incorrect. Consequently, this commit makes macvlan over bond non-functional. To address this problem, one potential solution is to check for the presence of a macvlan port on the bond device using netif_is_macvlan_port(bond->dev) and return NULL in the rlb_arp_xmit() function. However, this approach doesn't fully resolve the situation when a VLAN exists between the bond and macvlan. So let's just do a partial revert for commit 14af9963ba1e in rlb_arp_xmit(). As the comment said, Don't modify or load balance ARPs that do not originate locally. Fixes: 14af9963ba1e ("bonding: Support macvlans on top of tlb/rlb mode bonds") Reported-by: susan.zheng@veritas.com Closes: https://bugzilla.redhat.com/show_bug.cgi?id=2117816 Signed-off-by: Hangbin Liu Acked-by: Jay Vosburgh Signed-off-by: Paolo Abeni --- drivers/net/bonding/bond_alb.c | 6 +++--- include/net/bonding.h | 11 +---------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index b9dbad3a8af8..fc5da5d7744d 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -660,10 +660,10 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond) return NULL; arp = (struct arp_pkt *)skb_network_header(skb); - /* Don't modify or load balance ARPs that do not originate locally - * (e.g.,arrive via a bridge). + /* Don't modify or load balance ARPs that do not originate + * from the bond itself or a VLAN directly above the bond. */ - if (!bond_slave_has_mac_rx(bond, arp->mac_src)) + if (!bond_slave_has_mac_rcu(bond, arp->mac_src)) return NULL; dev = ip_dev_find(dev_net(bond->dev), arp->ip_src); diff --git a/include/net/bonding.h b/include/net/bonding.h index 30ac427cf0c6..5b8b1b644a2d 100644 --- a/include/net/bonding.h +++ b/include/net/bonding.h @@ -722,23 +722,14 @@ static inline struct slave *bond_slave_has_mac(struct bonding *bond, } /* Caller must hold rcu_read_lock() for read */ -static inline bool bond_slave_has_mac_rx(struct bonding *bond, const u8 *mac) +static inline bool bond_slave_has_mac_rcu(struct bonding *bond, const u8 *mac) { struct list_head *iter; struct slave *tmp; - struct netdev_hw_addr *ha; bond_for_each_slave_rcu(bond, tmp, iter) if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr)) return true; - - if (netdev_uc_empty(bond->dev)) - return false; - - netdev_for_each_uc_addr(ha, bond->dev) - if (ether_addr_equal_64bits(mac, ha->addr)) - return true; - return false; } From 27aa43f83c83e9243c6959426f6e36cb32aeb2d5 Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Wed, 23 Aug 2023 15:19:05 +0800 Subject: [PATCH 2/3] selftest: bond: add new topo bond_topo_2d1c.sh Add a new testing topo bond_topo_2d1c.sh which is used more commonly. Make bond_topo_3d1c.sh just source bond_topo_2d1c.sh and add the extra link. Signed-off-by: Hangbin Liu Acked-by: Jay Vosburgh Signed-off-by: Paolo Abeni --- .../selftests/drivers/net/bonding/Makefile | 1 + .../drivers/net/bonding/bond_options.sh | 3 - .../drivers/net/bonding/bond_topo_2d1c.sh | 158 ++++++++++++++++++ .../drivers/net/bonding/bond_topo_3d1c.sh | 120 +------------ 4 files changed, 168 insertions(+), 114 deletions(-) create mode 100644 tools/testing/selftests/drivers/net/bonding/bond_topo_2d1c.sh diff --git a/tools/testing/selftests/drivers/net/bonding/Makefile b/tools/testing/selftests/drivers/net/bonding/Makefile index 03f92d7aeb19..0a3eb0a10772 100644 --- a/tools/testing/selftests/drivers/net/bonding/Makefile +++ b/tools/testing/selftests/drivers/net/bonding/Makefile @@ -13,6 +13,7 @@ TEST_PROGS := \ TEST_FILES := \ lag_lib.sh \ + bond_topo_2d1c.sh \ bond_topo_3d1c.sh \ net_forwarding_lib.sh diff --git a/tools/testing/selftests/drivers/net/bonding/bond_options.sh b/tools/testing/selftests/drivers/net/bonding/bond_options.sh index 607ba5c38977..c54d1697f439 100755 --- a/tools/testing/selftests/drivers/net/bonding/bond_options.sh +++ b/tools/testing/selftests/drivers/net/bonding/bond_options.sh @@ -9,10 +9,7 @@ ALL_TESTS=" num_grat_arp " -REQUIRE_MZ=no -NUM_NETIFS=0 lib_dir=$(dirname "$0") -source ${lib_dir}/net_forwarding_lib.sh source ${lib_dir}/bond_topo_3d1c.sh skip_prio() diff --git a/tools/testing/selftests/drivers/net/bonding/bond_topo_2d1c.sh b/tools/testing/selftests/drivers/net/bonding/bond_topo_2d1c.sh new file mode 100644 index 000000000000..a509ef949dcf --- /dev/null +++ b/tools/testing/selftests/drivers/net/bonding/bond_topo_2d1c.sh @@ -0,0 +1,158 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Topology for Bond mode 1,5,6 testing +# +# +-------------------------+ +# | bond0 | Server +# | + | 192.0.2.1/24 +# | eth0 | eth1 | 2001:db8::1/24 +# | +---+---+ | +# | | | | +# +-------------------------+ +# | | +# +-------------------------+ +# | | | | +# | +---+-------+---+ | Gateway +# | | br0 | | 192.0.2.254/24 +# | +-------+-------+ | 2001:db8::254/24 +# | | | +# +-------------------------+ +# | +# +-------------------------+ +# | | | Client +# | + | 192.0.2.10/24 +# | eth0 | 2001:db8::10/24 +# +-------------------------+ + +REQUIRE_MZ=no +NUM_NETIFS=0 +lib_dir=$(dirname "$0") +source ${lib_dir}/net_forwarding_lib.sh + +s_ns="s-$(mktemp -u XXXXXX)" +c_ns="c-$(mktemp -u XXXXXX)" +g_ns="g-$(mktemp -u XXXXXX)" +s_ip4="192.0.2.1" +c_ip4="192.0.2.10" +g_ip4="192.0.2.254" +s_ip6="2001:db8::1" +c_ip6="2001:db8::10" +g_ip6="2001:db8::254" + +gateway_create() +{ + ip netns add ${g_ns} + ip -n ${g_ns} link add br0 type bridge + ip -n ${g_ns} link set br0 up + ip -n ${g_ns} addr add ${g_ip4}/24 dev br0 + ip -n ${g_ns} addr add ${g_ip6}/24 dev br0 +} + +gateway_destroy() +{ + ip -n ${g_ns} link del br0 + ip netns del ${g_ns} +} + +server_create() +{ + ip netns add ${s_ns} + ip -n ${s_ns} link add bond0 type bond mode active-backup miimon 100 + + for i in $(seq 0 1); do + ip -n ${s_ns} link add eth${i} type veth peer name s${i} netns ${g_ns} + + ip -n ${g_ns} link set s${i} up + ip -n ${g_ns} link set s${i} master br0 + ip -n ${s_ns} link set eth${i} master bond0 + + tc -n ${g_ns} qdisc add dev s${i} clsact + done + + ip -n ${s_ns} link set bond0 up + ip -n ${s_ns} addr add ${s_ip4}/24 dev bond0 + ip -n ${s_ns} addr add ${s_ip6}/24 dev bond0 + sleep 2 +} + +# Reset bond with new mode and options +bond_reset() +{ + # Count the eth link number in real-time as this function + # maybe called from other topologies. + local link_num=$(ip -n ${s_ns} -br link show | grep -c "^eth") + local param="$1" + link_num=$((link_num -1)) + + ip -n ${s_ns} link set bond0 down + ip -n ${s_ns} link del bond0 + + ip -n ${s_ns} link add bond0 type bond $param + for i in $(seq 0 ${link_num}); do + ip -n ${s_ns} link set eth$i master bond0 + done + + ip -n ${s_ns} link set bond0 up + ip -n ${s_ns} addr add ${s_ip4}/24 dev bond0 + ip -n ${s_ns} addr add ${s_ip6}/24 dev bond0 + sleep 2 +} + +server_destroy() +{ + # Count the eth link number in real-time as this function + # maybe called from other topologies. + local link_num=$(ip -n ${s_ns} -br link show | grep -c "^eth") + link_num=$((link_num -1)) + for i in $(seq 0 ${link_num}); do + ip -n ${s_ns} link del eth${i} + done + ip netns del ${s_ns} +} + +client_create() +{ + ip netns add ${c_ns} + ip -n ${c_ns} link add eth0 type veth peer name c0 netns ${g_ns} + + ip -n ${g_ns} link set c0 up + ip -n ${g_ns} link set c0 master br0 + + ip -n ${c_ns} link set eth0 up + ip -n ${c_ns} addr add ${c_ip4}/24 dev eth0 + ip -n ${c_ns} addr add ${c_ip6}/24 dev eth0 +} + +client_destroy() +{ + ip -n ${c_ns} link del eth0 + ip netns del ${c_ns} +} + +setup_prepare() +{ + gateway_create + server_create + client_create +} + +cleanup() +{ + pre_cleanup + + client_destroy + server_destroy + gateway_destroy +} + +bond_check_connection() +{ + local msg=${1:-"check connection"} + + sleep 2 + ip netns exec ${s_ns} ping ${c_ip4} -c5 -i 0.1 &>/dev/null + check_err $? "${msg}: ping failed" + ip netns exec ${s_ns} ping6 ${c_ip6} -c5 -i 0.1 &>/dev/null + check_err $? "${msg}: ping6 failed" +} diff --git a/tools/testing/selftests/drivers/net/bonding/bond_topo_3d1c.sh b/tools/testing/selftests/drivers/net/bonding/bond_topo_3d1c.sh index 69ab99a56043..3a1333d9a85b 100644 --- a/tools/testing/selftests/drivers/net/bonding/bond_topo_3d1c.sh +++ b/tools/testing/selftests/drivers/net/bonding/bond_topo_3d1c.sh @@ -25,121 +25,19 @@ # | eth0 | 2001:db8::10/24 # +-------------------------------------+ -s_ns="s-$(mktemp -u XXXXXX)" -c_ns="c-$(mktemp -u XXXXXX)" -g_ns="g-$(mktemp -u XXXXXX)" -s_ip4="192.0.2.1" -c_ip4="192.0.2.10" -g_ip4="192.0.2.254" -s_ip6="2001:db8::1" -c_ip6="2001:db8::10" -g_ip6="2001:db8::254" - -gateway_create() -{ - ip netns add ${g_ns} - ip -n ${g_ns} link add br0 type bridge - ip -n ${g_ns} link set br0 up - ip -n ${g_ns} addr add ${g_ip4}/24 dev br0 - ip -n ${g_ns} addr add ${g_ip6}/24 dev br0 -} - -gateway_destroy() -{ - ip -n ${g_ns} link del br0 - ip netns del ${g_ns} -} - -server_create() -{ - ip netns add ${s_ns} - ip -n ${s_ns} link add bond0 type bond mode active-backup miimon 100 - - for i in $(seq 0 2); do - ip -n ${s_ns} link add eth${i} type veth peer name s${i} netns ${g_ns} - - ip -n ${g_ns} link set s${i} up - ip -n ${g_ns} link set s${i} master br0 - ip -n ${s_ns} link set eth${i} master bond0 - - tc -n ${g_ns} qdisc add dev s${i} clsact - done - - ip -n ${s_ns} link set bond0 up - ip -n ${s_ns} addr add ${s_ip4}/24 dev bond0 - ip -n ${s_ns} addr add ${s_ip6}/24 dev bond0 - sleep 2 -} - -# Reset bond with new mode and options -bond_reset() -{ - local param="$1" - - ip -n ${s_ns} link set bond0 down - ip -n ${s_ns} link del bond0 - - ip -n ${s_ns} link add bond0 type bond $param - for i in $(seq 0 2); do - ip -n ${s_ns} link set eth$i master bond0 - done - - ip -n ${s_ns} link set bond0 up - ip -n ${s_ns} addr add ${s_ip4}/24 dev bond0 - ip -n ${s_ns} addr add ${s_ip6}/24 dev bond0 - sleep 2 -} - -server_destroy() -{ - for i in $(seq 0 2); do - ip -n ${s_ns} link del eth${i} - done - ip netns del ${s_ns} -} - -client_create() -{ - ip netns add ${c_ns} - ip -n ${c_ns} link add eth0 type veth peer name c0 netns ${g_ns} - - ip -n ${g_ns} link set c0 up - ip -n ${g_ns} link set c0 master br0 - - ip -n ${c_ns} link set eth0 up - ip -n ${c_ns} addr add ${c_ip4}/24 dev eth0 - ip -n ${c_ns} addr add ${c_ip6}/24 dev eth0 -} - -client_destroy() -{ - ip -n ${c_ns} link del eth0 - ip netns del ${c_ns} -} +source bond_topo_2d1c.sh setup_prepare() { gateway_create server_create client_create -} - -cleanup() -{ - pre_cleanup - - client_destroy - server_destroy - gateway_destroy -} - -bond_check_connection() -{ - local msg=${1:-"check connection"} - - sleep 2 - ip netns exec ${s_ns} ping ${c_ip4} -c5 -i 0.1 &>/dev/null - check_err $? "${msg}: ping failed" - ip netns exec ${s_ns} ping6 ${c_ip6} -c5 -i 0.1 &>/dev/null - check_err $? "${msg}: ping6 failed" + + # Add the extra device as we use 3 down links for bond0 + local i=2 + ip -n ${s_ns} link add eth${i} type veth peer name s${i} netns ${g_ns} + ip -n ${g_ns} link set s${i} up + ip -n ${g_ns} link set s${i} master br0 + ip -n ${s_ns} link set eth${i} master bond0 + tc -n ${g_ns} qdisc add dev s${i} clsact } From 246af950b9404da3cb1fed0dc85c7a637be0aff6 Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Wed, 23 Aug 2023 15:19:06 +0800 Subject: [PATCH 3/3] selftests: bonding: add macvlan over bond testing Add a macvlan over bonding test with mode active-backup, balance-tlb and balance-alb. ]# ./bond_macvlan.sh TEST: active-backup: IPv4: client->server [ OK ] TEST: active-backup: IPv6: client->server [ OK ] TEST: active-backup: IPv4: client->macvlan_1 [ OK ] TEST: active-backup: IPv6: client->macvlan_1 [ OK ] TEST: active-backup: IPv4: client->macvlan_2 [ OK ] TEST: active-backup: IPv6: client->macvlan_2 [ OK ] TEST: active-backup: IPv4: macvlan_1->macvlan_2 [ OK ] TEST: active-backup: IPv6: macvlan_1->macvlan_2 [ OK ] TEST: active-backup: IPv4: server->client [ OK ] TEST: active-backup: IPv6: server->client [ OK ] TEST: active-backup: IPv4: macvlan_1->client [ OK ] TEST: active-backup: IPv6: macvlan_1->client [ OK ] TEST: active-backup: IPv4: macvlan_2->client [ OK ] TEST: active-backup: IPv6: macvlan_2->client [ OK ] TEST: active-backup: IPv4: macvlan_2->macvlan_2 [ OK ] TEST: active-backup: IPv6: macvlan_2->macvlan_2 [ OK ] [...] TEST: balance-alb: IPv4: client->server [ OK ] TEST: balance-alb: IPv6: client->server [ OK ] TEST: balance-alb: IPv4: client->macvlan_1 [ OK ] TEST: balance-alb: IPv6: client->macvlan_1 [ OK ] TEST: balance-alb: IPv4: client->macvlan_2 [ OK ] TEST: balance-alb: IPv6: client->macvlan_2 [ OK ] TEST: balance-alb: IPv4: macvlan_1->macvlan_2 [ OK ] TEST: balance-alb: IPv6: macvlan_1->macvlan_2 [ OK ] TEST: balance-alb: IPv4: server->client [ OK ] TEST: balance-alb: IPv6: server->client [ OK ] TEST: balance-alb: IPv4: macvlan_1->client [ OK ] TEST: balance-alb: IPv6: macvlan_1->client [ OK ] TEST: balance-alb: IPv4: macvlan_2->client [ OK ] TEST: balance-alb: IPv6: macvlan_2->client [ OK ] TEST: balance-alb: IPv4: macvlan_2->macvlan_2 [ OK ] TEST: balance-alb: IPv6: macvlan_2->macvlan_2 [ OK ] Signed-off-by: Hangbin Liu Acked-by: Jay Vosburgh Signed-off-by: Paolo Abeni --- .../selftests/drivers/net/bonding/Makefile | 3 +- .../drivers/net/bonding/bond_macvlan.sh | 99 +++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100755 tools/testing/selftests/drivers/net/bonding/bond_macvlan.sh diff --git a/tools/testing/selftests/drivers/net/bonding/Makefile b/tools/testing/selftests/drivers/net/bonding/Makefile index 0a3eb0a10772..8a72bb7de70f 100644 --- a/tools/testing/selftests/drivers/net/bonding/Makefile +++ b/tools/testing/selftests/drivers/net/bonding/Makefile @@ -9,7 +9,8 @@ TEST_PROGS := \ mode-1-recovery-updelay.sh \ mode-2-recovery-updelay.sh \ bond_options.sh \ - bond-eth-type-change.sh + bond-eth-type-change.sh \ + bond_macvlan.sh TEST_FILES := \ lag_lib.sh \ diff --git a/tools/testing/selftests/drivers/net/bonding/bond_macvlan.sh b/tools/testing/selftests/drivers/net/bonding/bond_macvlan.sh new file mode 100755 index 000000000000..b609fb6231f4 --- /dev/null +++ b/tools/testing/selftests/drivers/net/bonding/bond_macvlan.sh @@ -0,0 +1,99 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Test macvlan over balance-alb + +lib_dir=$(dirname "$0") +source ${lib_dir}/bond_topo_2d1c.sh + +m1_ns="m1-$(mktemp -u XXXXXX)" +m2_ns="m1-$(mktemp -u XXXXXX)" +m1_ip4="192.0.2.11" +m1_ip6="2001:db8::11" +m2_ip4="192.0.2.12" +m2_ip6="2001:db8::12" + +cleanup() +{ + ip -n ${m1_ns} link del macv0 + ip netns del ${m1_ns} + ip -n ${m2_ns} link del macv0 + ip netns del ${m2_ns} + + client_destroy + server_destroy + gateway_destroy +} + +check_connection() +{ + local ns=${1} + local target=${2} + local message=${3:-"macvlan_over_bond"} + RET=0 + + + ip netns exec ${ns} ping ${target} -c 4 -i 0.1 &>/dev/null + check_err $? "ping failed" + log_test "$mode: $message" +} + +macvlan_over_bond() +{ + local param="$1" + RET=0 + + # setup new bond mode + bond_reset "${param}" + + ip -n ${s_ns} link add link bond0 name macv0 type macvlan mode bridge + ip -n ${s_ns} link set macv0 netns ${m1_ns} + ip -n ${m1_ns} link set dev macv0 up + ip -n ${m1_ns} addr add ${m1_ip4}/24 dev macv0 + ip -n ${m1_ns} addr add ${m1_ip6}/24 dev macv0 + + ip -n ${s_ns} link add link bond0 name macv0 type macvlan mode bridge + ip -n ${s_ns} link set macv0 netns ${m2_ns} + ip -n ${m2_ns} link set dev macv0 up + ip -n ${m2_ns} addr add ${m2_ip4}/24 dev macv0 + ip -n ${m2_ns} addr add ${m2_ip6}/24 dev macv0 + + sleep 2 + + check_connection "${c_ns}" "${s_ip4}" "IPv4: client->server" + check_connection "${c_ns}" "${s_ip6}" "IPv6: client->server" + check_connection "${c_ns}" "${m1_ip4}" "IPv4: client->macvlan_1" + check_connection "${c_ns}" "${m1_ip6}" "IPv6: client->macvlan_1" + check_connection "${c_ns}" "${m2_ip4}" "IPv4: client->macvlan_2" + check_connection "${c_ns}" "${m2_ip6}" "IPv6: client->macvlan_2" + check_connection "${m1_ns}" "${m2_ip4}" "IPv4: macvlan_1->macvlan_2" + check_connection "${m1_ns}" "${m2_ip6}" "IPv6: macvlan_1->macvlan_2" + + + sleep 5 + + check_connection "${s_ns}" "${c_ip4}" "IPv4: server->client" + check_connection "${s_ns}" "${c_ip6}" "IPv6: server->client" + check_connection "${m1_ns}" "${c_ip4}" "IPv4: macvlan_1->client" + check_connection "${m1_ns}" "${c_ip6}" "IPv6: macvlan_1->client" + check_connection "${m2_ns}" "${c_ip4}" "IPv4: macvlan_2->client" + check_connection "${m2_ns}" "${c_ip6}" "IPv6: macvlan_2->client" + check_connection "${m2_ns}" "${m1_ip4}" "IPv4: macvlan_2->macvlan_2" + check_connection "${m2_ns}" "${m1_ip6}" "IPv6: macvlan_2->macvlan_2" + + ip -n ${c_ns} neigh flush dev eth0 +} + +trap cleanup EXIT + +setup_prepare +ip netns add ${m1_ns} +ip netns add ${m2_ns} + +modes="active-backup balance-tlb balance-alb" + +for mode in $modes; do + macvlan_over_bond "mode $mode" +done + +exit $EXIT_STATUS