linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv2 net 0/3] bonding: fix negotiation flapping in 802.3ad passive mode
@ 2025-08-05  9:46 Hangbin Liu
  2025-08-05  9:46 ` [PATCHv2 net 1/3] bonding: update LACP activity flag after setting lacp_active Hangbin Liu
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Hangbin Liu @ 2025-08-05  9:46 UTC (permalink / raw)
  To: netdev
  Cc: Jay Vosburgh, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Nikolay Aleksandrov, Simon Horman,
	Shuah Khan, linux-kselftest, linux-kernel, Hangbin Liu

This patch fixes unstable LACP negotiation when bonding is configured in
passive mode (`lacp_active=off`).

Previously, the actor would stop sending LACPDUs after initial negotiation
succeeded, leading to the partner timing out and restarting the negotiation
cycle. This resulted in continuous LACP state flapping.

The fix ensures the passive actor starts sending periodic LACPDUs after
receiving the first LACPDU from the partner, in accordance with IEEE
802.1AX-2020 section 6.4.1.

v2:
a) Split the patch in to 2 parts. One for lacp_active setting.
   One for passive mode negotiation flapping issue. (Nikolay Aleksandrov)
b) Update fixes tags and some comments (Nikolay Aleksandrov)
c) Update selftest to pass on normal kernel (Jakub Kicinski)


Hangbin Liu (3):
  bonding: update LACP activity flag after setting lacp_active
  bonding: send LACPDUs periodically in passive mode after receiving
    partner's LACPDU
  selftests: bonding: add test for passive LACP mode

 drivers/net/bonding/bond_3ad.c                | 67 +++++++++----
 drivers/net/bonding/bond_options.c            |  1 +
 include/net/bond_3ad.h                        |  1 +
 .../selftests/drivers/net/bonding/Makefile    |  3 +-
 .../drivers/net/bonding/bond_passive_lacp.sh  | 95 +++++++++++++++++++
 5 files changed, 148 insertions(+), 19 deletions(-)
 create mode 100755 tools/testing/selftests/drivers/net/bonding/bond_passive_lacp.sh

-- 
2.46.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCHv2 net 1/3] bonding: update LACP activity flag after setting lacp_active
  2025-08-05  9:46 [PATCHv2 net 0/3] bonding: fix negotiation flapping in 802.3ad passive mode Hangbin Liu
@ 2025-08-05  9:46 ` Hangbin Liu
  2025-08-05  9:46 ` [PATCHv2 net 2/3] bonding: send LACPDUs periodically in passive mode after receiving partner's LACPDU Hangbin Liu
  2025-08-05  9:46 ` [PATCHv2 net 3/3] selftests: bonding: add test for passive LACP mode Hangbin Liu
  2 siblings, 0 replies; 7+ messages in thread
From: Hangbin Liu @ 2025-08-05  9:46 UTC (permalink / raw)
  To: netdev
  Cc: Jay Vosburgh, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Nikolay Aleksandrov, Simon Horman,
	Shuah Khan, linux-kselftest, linux-kernel, Hangbin Liu

The port's actor_oper_port_state activity flag should be updated immediately
after changing the lacp_active option to reflect the current mode correctly.

Fixes: 3a755cd8b7c6 ("bonding: add new option lacp_active")
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
 drivers/net/bonding/bond_3ad.c     | 25 +++++++++++++++++++++++++
 drivers/net/bonding/bond_options.c |  1 +
 include/net/bond_3ad.h             |  1 +
 3 files changed, 27 insertions(+)

diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 2fca8e84ab10..414fecfd2a0e 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2883,6 +2883,31 @@ void bond_3ad_update_lacp_rate(struct bonding *bond)
 	spin_unlock_bh(&bond->mode_lock);
 }
 
+/**
+ * bond_3ad_update_lacp_active - change the lacp active
+ * @bond: bonding struct
+ *
+ * Update actor_oper_port_state when lacp_active is modified.
+ */
+void bond_3ad_update_lacp_active(struct bonding *bond)
+{
+	struct port *port = NULL;
+	struct list_head *iter;
+	struct slave *slave;
+	int lacp_active;
+
+	lacp_active = bond->params.lacp_active;
+	spin_lock_bh(&bond->mode_lock);
+	bond_for_each_slave(bond, slave, iter) {
+		port = &(SLAVE_AD_INFO(slave)->port);
+		if (lacp_active)
+			port->actor_oper_port_state |= LACP_STATE_LACP_ACTIVITY;
+		else
+			port->actor_oper_port_state &= ~LACP_STATE_LACP_ACTIVITY;
+	}
+	spin_unlock_bh(&bond->mode_lock);
+}
+
 size_t bond_3ad_stats_size(void)
 {
 	return nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_RX */
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 1d639a3be6ba..3b6f815c55ff 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -1660,6 +1660,7 @@ static int bond_option_lacp_active_set(struct bonding *bond,
 	netdev_dbg(bond->dev, "Setting LACP active to %s (%llu)\n",
 		   newval->string, newval->value);
 	bond->params.lacp_active = newval->value;
+	bond_3ad_update_lacp_active(bond);
 
 	return 0;
 }
diff --git a/include/net/bond_3ad.h b/include/net/bond_3ad.h
index 2053cd8e788a..dba369a2cf27 100644
--- a/include/net/bond_3ad.h
+++ b/include/net/bond_3ad.h
@@ -307,6 +307,7 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
 			 struct slave *slave);
 int bond_3ad_set_carrier(struct bonding *bond);
 void bond_3ad_update_lacp_rate(struct bonding *bond);
+void bond_3ad_update_lacp_active(struct bonding *bond);
 void bond_3ad_update_ad_actor_settings(struct bonding *bond);
 int bond_3ad_stats_fill(struct sk_buff *skb, struct bond_3ad_stats *stats);
 size_t bond_3ad_stats_size(void);
-- 
2.46.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCHv2 net 2/3] bonding: send LACPDUs periodically in passive mode after receiving partner's LACPDU
  2025-08-05  9:46 [PATCHv2 net 0/3] bonding: fix negotiation flapping in 802.3ad passive mode Hangbin Liu
  2025-08-05  9:46 ` [PATCHv2 net 1/3] bonding: update LACP activity flag after setting lacp_active Hangbin Liu
@ 2025-08-05  9:46 ` Hangbin Liu
  2025-08-12  9:14   ` Paolo Abeni
  2025-08-05  9:46 ` [PATCHv2 net 3/3] selftests: bonding: add test for passive LACP mode Hangbin Liu
  2 siblings, 1 reply; 7+ messages in thread
From: Hangbin Liu @ 2025-08-05  9:46 UTC (permalink / raw)
  To: netdev
  Cc: Jay Vosburgh, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Nikolay Aleksandrov, Simon Horman,
	Shuah Khan, linux-kselftest, linux-kernel, Hangbin Liu

When `lacp_active` is set to `off`, the bond operates in passive mode, meaning
it only "speaks when spoken to." However, the current kernel implementation
only sends an LACPDU in response when the partner's state changes.

As a result, once LACP negotiation succeeds, the actor stops sending LACPDUs
until the partner times out and sends an "expired" LACPDU. This causes
continuous LACP state flapping.

According to IEEE 802.1AX-2014, 6.4.13 Periodic Transmission machine. The
values of Partner_Oper_Port_State.LACP_Activity and
Actor_Oper_Port_State.LACP_Activity determine whether periodic transmissions
take place. If either or both parameters are set to Active LACP, then periodic
transmissions occur; if both are set to Passive LACP, then periodic
transmissions do not occur.

To comply with this, we remove the `!bond->params.lacp_active` check in
`ad_periodic_machine()`. Instead, we initialize the actor's port's
`LACP_STATE_LACP_ACTIVITY` state based on `lacp_active` setting.

Additionally, we avoid setting the partner's state to
`LACP_STATE_LACP_ACTIVITY` in the EXPIRED state, since we should not assume
the partner is active by default.

This ensures that in passive mode, the bond starts sending periodic LACPDUs
after receiving one from the partner, and avoids flapping due to inactivity.

Fixes: 3a755cd8b7c6 ("bonding: add new option lacp_active")
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
 drivers/net/bonding/bond_3ad.c | 42 +++++++++++++++++++---------------
 1 file changed, 24 insertions(+), 18 deletions(-)

diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 414fecfd2a0e..da8cedba286d 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -95,13 +95,13 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker);
 static void ad_mux_machine(struct port *port, bool *update_slave_arr);
 static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port);
 static void ad_tx_machine(struct port *port);
-static void ad_periodic_machine(struct port *port, struct bond_params *bond_params);
+static void ad_periodic_machine(struct port *port);
 static void ad_port_selection_logic(struct port *port, bool *update_slave_arr);
 static void ad_agg_selection_logic(struct aggregator *aggregator,
 				   bool *update_slave_arr);
 static void ad_clear_agg(struct aggregator *aggregator);
 static void ad_initialize_agg(struct aggregator *aggregator);
-static void ad_initialize_port(struct port *port, int lacp_fast);
+static void ad_initialize_port(struct port *port, struct bond_params *bond_params);
 static void ad_enable_collecting(struct port *port);
 static void ad_disable_distributing(struct port *port,
 				    bool *update_slave_arr);
@@ -1307,10 +1307,16 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
 			 * case of EXPIRED even if LINK_DOWN didn't arrive for
 			 * the port.
 			 */
-			port->partner_oper.port_state &= ~LACP_STATE_SYNCHRONIZATION;
 			port->sm_vars &= ~AD_PORT_MATCHED;
+			/* Based on IEEE 8021AX-2014, Figure 6-18 - Receive
+			 * machine state diagram, the statue should be
+			 * Partner_Oper_Port_State.Synchronization = FALSE;
+			 * Partner_Oper_Port_State.LACP_Timeout = Short Timeout;
+			 * start current_while_timer(Short Timeout);
+			 * Actor_Oper_Port_State.Expired = TRUE;
+			 */
+			port->partner_oper.port_state &= ~LACP_STATE_SYNCHRONIZATION;
 			port->partner_oper.port_state |= LACP_STATE_LACP_TIMEOUT;
-			port->partner_oper.port_state |= LACP_STATE_LACP_ACTIVITY;
 			port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(AD_SHORT_TIMEOUT));
 			port->actor_oper_port_state |= LACP_STATE_EXPIRED;
 			port->sm_vars |= AD_PORT_CHURNED;
@@ -1417,11 +1423,10 @@ static void ad_tx_machine(struct port *port)
 /**
  * ad_periodic_machine - handle a port's periodic state machine
  * @port: the port we're looking at
- * @bond_params: bond parameters we will use
  *
  * Turn ntt flag on priodically to perform periodic transmission of lacpdu's.
  */
-static void ad_periodic_machine(struct port *port, struct bond_params *bond_params)
+static void ad_periodic_machine(struct port *port)
 {
 	periodic_states_t last_state;
 
@@ -1430,8 +1435,7 @@ static void ad_periodic_machine(struct port *port, struct bond_params *bond_para
 
 	/* check if port was reinitialized */
 	if (((port->sm_vars & AD_PORT_BEGIN) || !(port->sm_vars & AD_PORT_LACP_ENABLED) || !port->is_enabled) ||
-	    (!(port->actor_oper_port_state & LACP_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & LACP_STATE_LACP_ACTIVITY)) ||
-	    !bond_params->lacp_active) {
+	    (!(port->actor_oper_port_state & LACP_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & LACP_STATE_LACP_ACTIVITY))) {
 		port->sm_periodic_state = AD_NO_PERIODIC;
 	}
 	/* check if state machine should change state */
@@ -1955,16 +1959,16 @@ static void ad_initialize_agg(struct aggregator *aggregator)
 /**
  * ad_initialize_port - initialize a given port's parameters
  * @port: the port we're looking at
- * @lacp_fast: boolean. whether fast periodic should be used
+ * @bond_params: bond parameters we will use
  */
-static void ad_initialize_port(struct port *port, int lacp_fast)
+static void ad_initialize_port(struct port *port, struct bond_params *bond_params)
 {
 	static const struct port_params tmpl = {
 		.system_priority = 0xffff,
 		.key             = 1,
 		.port_number     = 1,
 		.port_priority   = 0xff,
-		.port_state      = 1,
+		.port_state      = 0,
 	};
 	static const struct lacpdu lacpdu = {
 		.subtype		= 0x01,
@@ -1982,12 +1986,14 @@ static void ad_initialize_port(struct port *port, int lacp_fast)
 		port->actor_port_priority = 0xff;
 		port->actor_port_aggregator_identifier = 0;
 		port->ntt = false;
-		port->actor_admin_port_state = LACP_STATE_AGGREGATION |
-					       LACP_STATE_LACP_ACTIVITY;
-		port->actor_oper_port_state  = LACP_STATE_AGGREGATION |
-					       LACP_STATE_LACP_ACTIVITY;
+		port->actor_admin_port_state = LACP_STATE_AGGREGATION;
+		port->actor_oper_port_state  = LACP_STATE_AGGREGATION;
+		if (bond_params->lacp_active) {
+			port->actor_admin_port_state |= LACP_STATE_LACP_ACTIVITY;
+			port->actor_oper_port_state  |= LACP_STATE_LACP_ACTIVITY;
+		}
 
-		if (lacp_fast)
+		if (bond_params->lacp_fast)
 			port->actor_oper_port_state |= LACP_STATE_LACP_TIMEOUT;
 
 		memcpy(&port->partner_admin, &tmpl, sizeof(tmpl));
@@ -2201,7 +2207,7 @@ void bond_3ad_bind_slave(struct slave *slave)
 		/* port initialization */
 		port = &(SLAVE_AD_INFO(slave)->port);
 
-		ad_initialize_port(port, bond->params.lacp_fast);
+		ad_initialize_port(port, &bond->params);
 
 		port->slave = slave;
 		port->actor_port_number = SLAVE_AD_INFO(slave)->id;
@@ -2513,7 +2519,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
 		}
 
 		ad_rx_machine(NULL, port);
-		ad_periodic_machine(port, &bond->params);
+		ad_periodic_machine(port);
 		ad_port_selection_logic(port, &update_slave_arr);
 		ad_mux_machine(port, &update_slave_arr);
 		ad_tx_machine(port);
-- 
2.46.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCHv2 net 3/3] selftests: bonding: add test for passive LACP mode
  2025-08-05  9:46 [PATCHv2 net 0/3] bonding: fix negotiation flapping in 802.3ad passive mode Hangbin Liu
  2025-08-05  9:46 ` [PATCHv2 net 1/3] bonding: update LACP activity flag after setting lacp_active Hangbin Liu
  2025-08-05  9:46 ` [PATCHv2 net 2/3] bonding: send LACPDUs periodically in passive mode after receiving partner's LACPDU Hangbin Liu
@ 2025-08-05  9:46 ` Hangbin Liu
  2025-08-12  9:23   ` Paolo Abeni
  2 siblings, 1 reply; 7+ messages in thread
From: Hangbin Liu @ 2025-08-05  9:46 UTC (permalink / raw)
  To: netdev
  Cc: Jay Vosburgh, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Nikolay Aleksandrov, Simon Horman,
	Shuah Khan, linux-kselftest, linux-kernel, Hangbin Liu

Add a selftest to verify bonding behavior when `lacp_active` is set to `off`.

The test checks the following:
- The passive LACP bond should not send LACPDUs before receiving a partner's
  LACPDU.
- The transmitted LACPDUs must not include the active flag.
- After transitioning to EXPIRED and DEFAULTED states, the passive side should
  still not initiate LACPDUs.

Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
 .../selftests/drivers/net/bonding/Makefile    |  3 +-
 .../drivers/net/bonding/bond_passive_lacp.sh  | 95 +++++++++++++++++++
 2 files changed, 97 insertions(+), 1 deletion(-)
 create mode 100755 tools/testing/selftests/drivers/net/bonding/bond_passive_lacp.sh

diff --git a/tools/testing/selftests/drivers/net/bonding/Makefile b/tools/testing/selftests/drivers/net/bonding/Makefile
index 2b10854e4b1e..44b98f17f8ff 100644
--- a/tools/testing/selftests/drivers/net/bonding/Makefile
+++ b/tools/testing/selftests/drivers/net/bonding/Makefile
@@ -10,7 +10,8 @@ TEST_PROGS := \
 	mode-2-recovery-updelay.sh \
 	bond_options.sh \
 	bond-eth-type-change.sh \
-	bond_macvlan_ipvlan.sh
+	bond_macvlan_ipvlan.sh \
+	bond_passive_lacp.sh
 
 TEST_FILES := \
 	lag_lib.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..4c714c166566
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/bonding/bond_passive_lacp.sh
@@ -0,0 +1,95 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Test if a bond interface works with lacp_active=off.
+
+# shellcheck disable=SC2034
+REQUIRE_MZ=no
+NUM_NETIFS=0
+lib_dir=$(dirname "$0")
+# shellcheck disable=SC1091
+source "$lib_dir"/../../../net/forwarding/lib.sh
+
+check_port_state()
+{
+	local netns=$1
+	local port=$2
+	local state=$3
+
+	ip -n "${netns}" -d -j link show "$port" | \
+		jq -e ".[].linkinfo.info_slave_data.ad_actor_oper_port_state_str | index(\"${state}\") != null" > /dev/null
+}
+
+trap cleanup EXIT
+setup_ns c_ns s_ns
+defer cleanup_all_ns
+
+# shellcheck disable=SC2154
+ip -n "${c_ns}" link add eth0 type veth peer name eth0 netns "${s_ns}"
+ip -n "${c_ns}" link add eth1 type veth peer name eth1 netns "${s_ns}"
+ip -n "${s_ns}" link set eth0 up
+ip -n "${s_ns}" link set eth1 up
+ip -n "${c_ns}" link add bond0 type bond mode 802.3ad lacp_active off 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}" link set bond0 up
+
+# 1. The passive side shouldn't send LACPDU.
+RET=0
+client_mac=$(cmd_jq "ip -j -n ${c_ns} link show bond0" ".[].address")
+# Wait for the first LACPDU due to state change.
+sleep 5
+timeout 62 ip netns exec "${c_ns}" tcpdump --immediate-mode -c 1 -i eth0 \
+	-nn -l -vvv ether proto 0x8809 2> /dev/null > /tmp/client_init.out
+grep -q "System $client_mac" /tmp/client_init.out && RET=1
+log_test "802.3ad" "init port pkt lacp_active off"
+
+# 2. The passive side should not have the 'active' flag.
+RET=0
+check_port_state "${c_ns}" "eth0" "active" && RET=1
+log_test "802.3ad" "port state lacp_active off"
+
+# Set up the switch side with active mode.
+ip -n "${s_ns}" link set eth0 down
+ip -n "${s_ns}" link set eth1 down
+ip -n "${s_ns}" link add bond0 type bond mode 802.3ad 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}" link set bond0 up
+# Make sure the negotiation finished
+sleep 5
+
+# 3. The active side should have the 'active' flag.
+RET=0
+check_port_state "${s_ns}" "eth0" "active" || RET=1
+log_test "802.3ad" "port state lacp_active on"
+
+# 4. Make sure the connection has not expired.
+RET=0
+slowwait 15 check_port_state "${s_ns}" "eth0" "expired" && RET=1
+slowwait 15 check_port_state "${s_ns}" "eth1" "expired" && RET=1
+log_test "bond 802.3ad" "port connect lacp_active off"
+
+# After testing, disconnect one port on each side to check the state.
+ip -n "${s_ns}" link set eth0 nomaster
+ip -n "${s_ns}" link set eth0 up
+ip -n "${c_ns}" link set eth1 nomaster
+ip -n "${c_ns}" link set eth1 up
+# 5. The passive side shouldn't send LACPDU anymore.
+RET=0
+# Wait for LACPDU due to state change.
+sleep 5
+timeout 62 ip netns exec "${c_ns}" tcpdump --immediate-mode -c 1 -i eth0 \
+	-nn -l -vvv ether proto 0x8809 2> /dev/null > /tmp/client_dis.out
+grep -q "System $client_mac" /tmp/client_dis.out && RET=1
+log_test "bond 802.3ad" "disconnect port pkt lacp_active off"
+
+# 6. The active side keeps sending LACPDU.
+RET=0
+switch_mac=$(cmd_jq "ip -j -n ${s_ns} link show bond0" ".[].address")
+timeout 62 ip netns exec "${s_ns}" tcpdump --immediate-mode -c 1 -i eth1 \
+	-nn -l -vvv ether proto 0x8809 2> /dev/null > /tmp/switch.out
+grep -q "System $switch_mac" /tmp/switch.out || RET=1
+log_test "bond 802.3ad" "disconnect port pkt lacp_active on"
+
+exit "$EXIT_STATUS"
-- 
2.46.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCHv2 net 2/3] bonding: send LACPDUs periodically in passive mode after receiving partner's LACPDU
  2025-08-05  9:46 ` [PATCHv2 net 2/3] bonding: send LACPDUs periodically in passive mode after receiving partner's LACPDU Hangbin Liu
@ 2025-08-12  9:14   ` Paolo Abeni
  0 siblings, 0 replies; 7+ messages in thread
From: Paolo Abeni @ 2025-08-12  9:14 UTC (permalink / raw)
  To: Hangbin Liu, netdev
  Cc: Jay Vosburgh, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Nikolay Aleksandrov, Simon Horman, Shuah Khan,
	linux-kselftest, linux-kernel

On 8/5/25 11:46 AM, Hangbin Liu wrote:
> @@ -95,13 +95,13 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker);
>  static void ad_mux_machine(struct port *port, bool *update_slave_arr);
>  static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port);
>  static void ad_tx_machine(struct port *port);
> -static void ad_periodic_machine(struct port *port, struct bond_params *bond_params);
> +static void ad_periodic_machine(struct port *port);
>  static void ad_port_selection_logic(struct port *port, bool *update_slave_arr);
>  static void ad_agg_selection_logic(struct aggregator *aggregator,
>  				   bool *update_slave_arr);
>  static void ad_clear_agg(struct aggregator *aggregator);
>  static void ad_initialize_agg(struct aggregator *aggregator);
> -static void ad_initialize_port(struct port *port, int lacp_fast);
> +static void ad_initialize_port(struct port *port, struct bond_params *bond_params);

The `bond_params` argument should be constified.

Thanks,

Paolo



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCHv2 net 3/3] selftests: bonding: add test for passive LACP mode
  2025-08-05  9:46 ` [PATCHv2 net 3/3] selftests: bonding: add test for passive LACP mode Hangbin Liu
@ 2025-08-12  9:23   ` Paolo Abeni
  2025-08-14  9:54     ` Hangbin Liu
  0 siblings, 1 reply; 7+ messages in thread
From: Paolo Abeni @ 2025-08-12  9:23 UTC (permalink / raw)
  To: Hangbin Liu, netdev
  Cc: Jay Vosburgh, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Nikolay Aleksandrov, Simon Horman, Shuah Khan,
	linux-kselftest, linux-kernel

On 8/5/25 11:46 AM, Hangbin Liu wrote:
@@ -0,0 +1,95 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# Test if a bond interface works with lacp_active=off.
> +
> +# shellcheck disable=SC2034
> +REQUIRE_MZ=no
> +NUM_NETIFS=0
> +lib_dir=$(dirname "$0")
> +# shellcheck disable=SC1091
> +source "$lib_dir"/../../../net/forwarding/lib.sh
> +
> +check_port_state()
> +{
> +	local netns=$1
> +	local port=$2
> +	local state=$3
> +
> +	ip -n "${netns}" -d -j link show "$port" | \
> +		jq -e ".[].linkinfo.info_slave_data.ad_actor_oper_port_state_str | index(\"${state}\") != null" > /dev/null
> +}
> +
> +trap cleanup EXIT
> +setup_ns c_ns s_ns
> +defer cleanup_all_ns
> +
> +# shellcheck disable=SC2154
> +ip -n "${c_ns}" link add eth0 type veth peer name eth0 netns "${s_ns}"
> +ip -n "${c_ns}" link add eth1 type veth peer name eth1 netns "${s_ns}"
> +ip -n "${s_ns}" link set eth0 up
> +ip -n "${s_ns}" link set eth1 up
> +ip -n "${c_ns}" link add bond0 type bond mode 802.3ad lacp_active off 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}" link set bond0 up
> +
> +# 1. The passive side shouldn't send LACPDU.
> +RET=0
> +client_mac=$(cmd_jq "ip -j -n ${c_ns} link show bond0" ".[].address")
> +# Wait for the first LACPDU due to state change.
> +sleep 5
> +timeout 62 ip netns exec "${c_ns}" tcpdump --immediate-mode -c 1 -i eth0 \
> +	-nn -l -vvv ether proto 0x8809 2> /dev/null > /tmp/client_init.out
> +grep -q "System $client_mac" /tmp/client_init.out && RET=1
> +log_test "802.3ad" "init port pkt lacp_active off"
> +
> +# 2. The passive side should not have the 'active' flag.
> +RET=0
> +check_port_state "${c_ns}" "eth0" "active" && RET=1
> +log_test "802.3ad" "port state lacp_active off"
> +
> +# Set up the switch side with active mode.
> +ip -n "${s_ns}" link set eth0 down
> +ip -n "${s_ns}" link set eth1 down
> +ip -n "${s_ns}" link add bond0 type bond mode 802.3ad 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}" link set bond0 up
> +# Make sure the negotiation finished
> +sleep 5

Minor nit: I guess the above sleep time depends on some kernel constant,
but it's not obvious to me if the minimum time is mandated by the RFC,
nor how long is such interval.

A comment explaining the rationale behind such sleep will help, and
possibly a loop with smaller minimal wait and periodic checks for the
expected condition up to a significantly higher timeout could make the
test both faster on average and more robust.

> +
> +# 3. The active side should have the 'active' flag.
> +RET=0
> +check_port_state "${s_ns}" "eth0" "active" || RET=1
> +log_test "802.3ad" "port state lacp_active on"
> +
> +# 4. Make sure the connection has not expired.
> +RET=0
> +slowwait 15 check_port_state "${s_ns}" "eth0" "expired" && RET=1
> +slowwait 15 check_port_state "${s_ns}" "eth1" "expired" && RET=1
> +log_test "bond 802.3ad" "port connect lacp_active off"
> +
> +# After testing, disconnect one port on each side to check the state.
> +ip -n "${s_ns}" link set eth0 nomaster
> +ip -n "${s_ns}" link set eth0 up
> +ip -n "${c_ns}" link set eth1 nomaster
> +ip -n "${c_ns}" link set eth1 up
> +# 5. The passive side shouldn't send LACPDU anymore.
> +RET=0
> +# Wait for LACPDU due to state change.
> +sleep 5

Same here.

Thanks,

Paolo


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCHv2 net 3/3] selftests: bonding: add test for passive LACP mode
  2025-08-12  9:23   ` Paolo Abeni
@ 2025-08-14  9:54     ` Hangbin Liu
  0 siblings, 0 replies; 7+ messages in thread
From: Hangbin Liu @ 2025-08-14  9:54 UTC (permalink / raw)
  To: Paolo Abeni
  Cc: netdev, Jay Vosburgh, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Nikolay Aleksandrov, Simon Horman, Shuah Khan,
	linux-kselftest, linux-kernel

On Tue, Aug 12, 2025 at 11:23:17AM +0200, Paolo Abeni wrote:
> On 8/5/25 11:46 AM, Hangbin Liu wrote:
> @@ -0,0 +1,95 @@
> > +#!/bin/bash
> > +# SPDX-License-Identifier: GPL-2.0
> > +#
> > +# Test if a bond interface works with lacp_active=off.
> > +
> > +# shellcheck disable=SC2034
> > +REQUIRE_MZ=no
> > +NUM_NETIFS=0
> > +lib_dir=$(dirname "$0")
> > +# shellcheck disable=SC1091
> > +source "$lib_dir"/../../../net/forwarding/lib.sh
> > +
> > +check_port_state()
> > +{
> > +	local netns=$1
> > +	local port=$2
> > +	local state=$3
> > +
> > +	ip -n "${netns}" -d -j link show "$port" | \
> > +		jq -e ".[].linkinfo.info_slave_data.ad_actor_oper_port_state_str | index(\"${state}\") != null" > /dev/null
> > +}
> > +
> > +trap cleanup EXIT
> > +setup_ns c_ns s_ns
> > +defer cleanup_all_ns
> > +
> > +# shellcheck disable=SC2154
> > +ip -n "${c_ns}" link add eth0 type veth peer name eth0 netns "${s_ns}"
> > +ip -n "${c_ns}" link add eth1 type veth peer name eth1 netns "${s_ns}"
> > +ip -n "${s_ns}" link set eth0 up
> > +ip -n "${s_ns}" link set eth1 up
> > +ip -n "${c_ns}" link add bond0 type bond mode 802.3ad lacp_active off 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}" link set bond0 up
> > +
> > +# 1. The passive side shouldn't send LACPDU.
> > +RET=0
> > +client_mac=$(cmd_jq "ip -j -n ${c_ns} link show bond0" ".[].address")
> > +# Wait for the first LACPDU due to state change.
> > +sleep 5
> > +timeout 62 ip netns exec "${c_ns}" tcpdump --immediate-mode -c 1 -i eth0 \
> > +	-nn -l -vvv ether proto 0x8809 2> /dev/null > /tmp/client_init.out
> > +grep -q "System $client_mac" /tmp/client_init.out && RET=1
> > +log_test "802.3ad" "init port pkt lacp_active off"
> > +
> > +# 2. The passive side should not have the 'active' flag.
> > +RET=0
> > +check_port_state "${c_ns}" "eth0" "active" && RET=1
> > +log_test "802.3ad" "port state lacp_active off"
> > +
> > +# Set up the switch side with active mode.
> > +ip -n "${s_ns}" link set eth0 down
> > +ip -n "${s_ns}" link set eth1 down
> > +ip -n "${s_ns}" link add bond0 type bond mode 802.3ad 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}" link set bond0 up
> > +# Make sure the negotiation finished
> > +sleep 5
> 
> Minor nit: I guess the above sleep time depends on some kernel constant,
> but it's not obvious to me if the minimum time is mandated by the RFC,
> nor how long is such interval.

We need to make sure the lacp negotiation finished. There is no definition
in IEEE standard. 

> 
> A comment explaining the rationale behind such sleep will help, and
> possibly a loop with smaller minimal wait and periodic checks for the
> expected condition up to a significantly higher timeout could make the
> test both faster on average and more robust.

I will use tc rules to catch pkts and see if we can reduce some time.

Thanks
Hangbin

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2025-08-14  9:55 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-05  9:46 [PATCHv2 net 0/3] bonding: fix negotiation flapping in 802.3ad passive mode Hangbin Liu
2025-08-05  9:46 ` [PATCHv2 net 1/3] bonding: update LACP activity flag after setting lacp_active Hangbin Liu
2025-08-05  9:46 ` [PATCHv2 net 2/3] bonding: send LACPDUs periodically in passive mode after receiving partner's LACPDU Hangbin Liu
2025-08-12  9:14   ` Paolo Abeni
2025-08-05  9:46 ` [PATCHv2 net 3/3] selftests: bonding: add test for passive LACP mode Hangbin Liu
2025-08-12  9:23   ` Paolo Abeni
2025-08-14  9:54     ` Hangbin Liu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).