This patchset fixes an issue where bonding fails to establish a stable LACP negotiation when operating in passive mode (lacp_active=off).
In passive mode, the current implementation only replies when the partner's state changes, which results in LACP timeout and unstable aggregator formation.
With this change, the bond responds to each received LACPDU in passive mode by setting ntt = true, ensuring timely replies and stable LACP negotiation.
Hangbin Liu (2): bonding: update ntt to true in passive mode selftests: bonding: add test for passive LACP mode
drivers/net/bonding/bond_3ad.c | 6 ++ .../drivers/net/bonding/bond_passive_lacp.sh | 21 +++++ .../drivers/net/bonding/bond_topo_lacp.sh | 77 +++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100755 tools/testing/selftests/drivers/net/bonding/bond_passive_lacp.sh create mode 100644 tools/testing/selftests/drivers/net/bonding/bond_topo_lacp.sh
When lacp_active is set to off, the bond operates in passive mode, meaning it will only "speak when spoken to." However, the current kernel implementation only sends an LACPDU in response when the partner's state changes.
In this situation, once LACP negotiation succeeds, the actor stops sending LACPDUs until the partner times out and sends an "expired" LACPDU. This leads to endless LACP state flapping.
To avoid this, we need update ntt to true once received an LACPDU from the partner, ensuring an immediate reply. With this fix, the link becomes stable in most cases, except for one specific scenario:
Actor: lacp_active=off, lacp_rate=slow Partner: lacp_active=on, lacp_rate=fast
In this case, the partner expects frequent LACPDUs (every 1 second), but the actor only responds after receiving an LACPDU, which, in this setup, the partner sends every 30 seconds due to the actor's lacp_rate=slow. By the time the actor replies, the partner has already timed out and sent an "expired" LACPDU.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Hangbin Liu liuhangbin@gmail.com --- drivers/net/bonding/bond_3ad.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index c6807e473ab7..e001d1c8a49b 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -666,6 +666,8 @@ static void __update_default_selected(struct port *port) */ static void __update_ntt(struct lacpdu *lacpdu, struct port *port) { + struct bonding *bond; + /* validate lacpdu and port */ if (lacpdu && port) { /* check if any parameter is different then @@ -683,6 +685,10 @@ static void __update_ntt(struct lacpdu *lacpdu, struct port *port) ) { port->ntt = true; } + + bond = __get_bond_by_port(port); + if (bond && !bond->params.lacp_active) + port->ntt = true; } }
Add a selftest to verify bonding behavior when lacp_active is set to off.
Signed-off-by: Hangbin Liu liuhangbin@gmail.com --- .../drivers/net/bonding/bond_passive_lacp.sh | 21 +++++ .../drivers/net/bonding/bond_topo_lacp.sh | 77 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100755 tools/testing/selftests/drivers/net/bonding/bond_passive_lacp.sh create mode 100644 tools/testing/selftests/drivers/net/bonding/bond_topo_lacp.sh
diff --git a/tools/testing/selftests/drivers/net/bonding/bond_passive_lacp.sh b/tools/testing/selftests/drivers/net/bonding/bond_passive_lacp.sh new file mode 100755 index 000000000000..4cf8a5999aaa --- /dev/null +++ b/tools/testing/selftests/drivers/net/bonding/bond_passive_lacp.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# Testing if bond works with lacp_active = off + +lib_dir=$(dirname "$0") +source ${lib_dir}/bond_topo_lacp.sh + +trap cleanup EXIT +setup_topo_lacp + +lacp_bond_reset "${c_ns}" "lacp_active off" +# make sure the switch state is not expired [A,T,G,S,Ex] +if slowwait 15 ip netns exec ${s_ns} grep -q 'port state: 143' /proc/net/bonding/bond0; then + RET=1 +else + RET=0 +fi +log_test "bond 802.3ad" "lacp_active off" + +exit $EXIT_STATUS diff --git a/tools/testing/selftests/drivers/net/bonding/bond_topo_lacp.sh b/tools/testing/selftests/drivers/net/bonding/bond_topo_lacp.sh new file mode 100644 index 000000000000..33dca6ebdc4b --- /dev/null +++ b/tools/testing/selftests/drivers/net/bonding/bond_topo_lacp.sh @@ -0,0 +1,77 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Topology for Bond mode 802.3ad testing +# +# +-------------------------+ +# | bond0 | Switch +# | + | 192.0.2.254/24 +# | eth0 | eth1 | 2001:db8::254/24 +# | +---+---+ | +# | | | | +# +-------------------------+ +# | | +# +-------------------------+ +# | | | | +# | +---+---+ | Client +# | eth0 | eth1 | 192.0.2.1/24 +# | + | 2001:db8::1/24 +# | bond0 | +# +-------------------------+ + +REQUIRE_MZ=no +NUM_NETIFS=0 +lib_dir=$(dirname "$0") +source "$lib_dir"/../../../net/forwarding/lib.sh + +s_ip4="192.0.2.254" +c_ip4="192.0.2.1" +s_ip6="2001:db8::254" +c_ip6="2001:db8::1" + +switch_create() +{ + ip netns exec ${s_ns} sysctl -q net.ipv6.conf.default.keep_addr_on_down=1 + ip -n ${s_ns} link add eth0 type veth peer name eth0 netns ${c_ns} + ip -n ${s_ns} link add eth1 type veth peer name eth1 netns ${c_ns} + ip -n ${s_ns} link add bond0 type bond mode 802.3ad miimon 100 lacp_active on lacp_rate fast + ip -n ${s_ns} link set eth0 master bond0 + ip -n ${s_ns} link set eth1 master bond0 + ip -n ${s_ns} addr add ${s_ip4}/24 dev bond0 + ip -n ${s_ns} addr add ${s_ip6}/24 dev bond0 + ip -n ${s_ns} link set bond0 up +} + +client_create() +{ + ip netns exec ${c_ns} sysctl -q net.ipv6.conf.default.keep_addr_on_down=1 + ip -n ${c_ns} link add bond0 type bond mode 802.3ad miimon 100 lacp_active on lacp_rate fast + ip -n ${c_ns} link set eth0 master bond0 + ip -n ${c_ns} link set eth1 master bond0 + ip -n ${c_ns} addr add ${c_ip4}/24 dev bond0 + ip -n ${c_ns} addr add ${c_ip6}/24 dev bond0 + ip -n ${c_ns} link set bond0 up +} + +setup_topo_lacp() +{ + setup_ns s_ns c_ns + defer cleanup_all_ns + + switch_create + client_create +} + +# Reset bond with and options +lacp_bond_reset() +{ + local netns="$1" + local param="$2" + + ip -n ${netns} link set bond0 down + ip -n ${netns} link set bond0 type bond $param + ip -n ${netns} link set bond0 up + + # Wait for IPv6 address ready as it needs DAD + slowwait 10 ip netns exec ${c_ns} ping6 ${s_ip6} -c 1 -W 0.1 &> /dev/null +}
linux-kselftest-mirror@lists.linaro.org