Skip to content

Commit 0599640

Browse files
liuhangbinPaolo Abeni
authored andcommitted
bonding: send LACPDUs periodically in passive mode after receiving partner's LACPDU
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: 3a755cd ("bonding: add new option lacp_active") Signed-off-by: Hangbin Liu <liuhangbin@gmail.com> Link: https://patch.msgid.link/20250815062000.22220-3-liuhangbin@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
1 parent b64d035 commit 0599640

File tree

1 file changed

+24
-18
lines changed

1 file changed

+24
-18
lines changed

drivers/net/bonding/bond_3ad.c

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,13 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker);
9595
static void ad_mux_machine(struct port *port, bool *update_slave_arr);
9696
static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port);
9797
static void ad_tx_machine(struct port *port);
98-
static void ad_periodic_machine(struct port *port, struct bond_params *bond_params);
98+
static void ad_periodic_machine(struct port *port);
9999
static void ad_port_selection_logic(struct port *port, bool *update_slave_arr);
100100
static void ad_agg_selection_logic(struct aggregator *aggregator,
101101
bool *update_slave_arr);
102102
static void ad_clear_agg(struct aggregator *aggregator);
103103
static void ad_initialize_agg(struct aggregator *aggregator);
104-
static void ad_initialize_port(struct port *port, int lacp_fast);
104+
static void ad_initialize_port(struct port *port, const struct bond_params *bond_params);
105105
static void ad_enable_collecting(struct port *port);
106106
static void ad_disable_distributing(struct port *port,
107107
bool *update_slave_arr);
@@ -1307,10 +1307,16 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
13071307
* case of EXPIRED even if LINK_DOWN didn't arrive for
13081308
* the port.
13091309
*/
1310-
port->partner_oper.port_state &= ~LACP_STATE_SYNCHRONIZATION;
13111310
port->sm_vars &= ~AD_PORT_MATCHED;
1311+
/* Based on IEEE 8021AX-2014, Figure 6-18 - Receive
1312+
* machine state diagram, the statue should be
1313+
* Partner_Oper_Port_State.Synchronization = FALSE;
1314+
* Partner_Oper_Port_State.LACP_Timeout = Short Timeout;
1315+
* start current_while_timer(Short Timeout);
1316+
* Actor_Oper_Port_State.Expired = TRUE;
1317+
*/
1318+
port->partner_oper.port_state &= ~LACP_STATE_SYNCHRONIZATION;
13121319
port->partner_oper.port_state |= LACP_STATE_LACP_TIMEOUT;
1313-
port->partner_oper.port_state |= LACP_STATE_LACP_ACTIVITY;
13141320
port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(AD_SHORT_TIMEOUT));
13151321
port->actor_oper_port_state |= LACP_STATE_EXPIRED;
13161322
port->sm_vars |= AD_PORT_CHURNED;
@@ -1417,11 +1423,10 @@ static void ad_tx_machine(struct port *port)
14171423
/**
14181424
* ad_periodic_machine - handle a port's periodic state machine
14191425
* @port: the port we're looking at
1420-
* @bond_params: bond parameters we will use
14211426
*
14221427
* Turn ntt flag on priodically to perform periodic transmission of lacpdu's.
14231428
*/
1424-
static void ad_periodic_machine(struct port *port, struct bond_params *bond_params)
1429+
static void ad_periodic_machine(struct port *port)
14251430
{
14261431
periodic_states_t last_state;
14271432

@@ -1430,8 +1435,7 @@ static void ad_periodic_machine(struct port *port, struct bond_params *bond_para
14301435

14311436
/* check if port was reinitialized */
14321437
if (((port->sm_vars & AD_PORT_BEGIN) || !(port->sm_vars & AD_PORT_LACP_ENABLED) || !port->is_enabled) ||
1433-
(!(port->actor_oper_port_state & LACP_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & LACP_STATE_LACP_ACTIVITY)) ||
1434-
!bond_params->lacp_active) {
1438+
(!(port->actor_oper_port_state & LACP_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & LACP_STATE_LACP_ACTIVITY))) {
14351439
port->sm_periodic_state = AD_NO_PERIODIC;
14361440
}
14371441
/* check if state machine should change state */
@@ -1955,16 +1959,16 @@ static void ad_initialize_agg(struct aggregator *aggregator)
19551959
/**
19561960
* ad_initialize_port - initialize a given port's parameters
19571961
* @port: the port we're looking at
1958-
* @lacp_fast: boolean. whether fast periodic should be used
1962+
* @bond_params: bond parameters we will use
19591963
*/
1960-
static void ad_initialize_port(struct port *port, int lacp_fast)
1964+
static void ad_initialize_port(struct port *port, const struct bond_params *bond_params)
19611965
{
19621966
static const struct port_params tmpl = {
19631967
.system_priority = 0xffff,
19641968
.key = 1,
19651969
.port_number = 1,
19661970
.port_priority = 0xff,
1967-
.port_state = 1,
1971+
.port_state = 0,
19681972
};
19691973
static const struct lacpdu lacpdu = {
19701974
.subtype = 0x01,
@@ -1982,12 +1986,14 @@ static void ad_initialize_port(struct port *port, int lacp_fast)
19821986
port->actor_port_priority = 0xff;
19831987
port->actor_port_aggregator_identifier = 0;
19841988
port->ntt = false;
1985-
port->actor_admin_port_state = LACP_STATE_AGGREGATION |
1986-
LACP_STATE_LACP_ACTIVITY;
1987-
port->actor_oper_port_state = LACP_STATE_AGGREGATION |
1988-
LACP_STATE_LACP_ACTIVITY;
1989+
port->actor_admin_port_state = LACP_STATE_AGGREGATION;
1990+
port->actor_oper_port_state = LACP_STATE_AGGREGATION;
1991+
if (bond_params->lacp_active) {
1992+
port->actor_admin_port_state |= LACP_STATE_LACP_ACTIVITY;
1993+
port->actor_oper_port_state |= LACP_STATE_LACP_ACTIVITY;
1994+
}
19891995

1990-
if (lacp_fast)
1996+
if (bond_params->lacp_fast)
19911997
port->actor_oper_port_state |= LACP_STATE_LACP_TIMEOUT;
19921998

19931999
memcpy(&port->partner_admin, &tmpl, sizeof(tmpl));
@@ -2201,7 +2207,7 @@ void bond_3ad_bind_slave(struct slave *slave)
22012207
/* port initialization */
22022208
port = &(SLAVE_AD_INFO(slave)->port);
22032209

2204-
ad_initialize_port(port, bond->params.lacp_fast);
2210+
ad_initialize_port(port, &bond->params);
22052211

22062212
port->slave = slave;
22072213
port->actor_port_number = SLAVE_AD_INFO(slave)->id;
@@ -2513,7 +2519,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
25132519
}
25142520

25152521
ad_rx_machine(NULL, port);
2516-
ad_periodic_machine(port, &bond->params);
2522+
ad_periodic_machine(port);
25172523
ad_port_selection_logic(port, &update_slave_arr);
25182524
ad_mux_machine(port, &update_slave_arr);
25192525
ad_tx_machine(port);

0 commit comments

Comments
 (0)