Skip to content

Commit 7bb11dc

Browse files
Mahesh Bandewardavem330
authored andcommitted
bonding: unify all places where actor-oper key needs to be updated.
actor_admin, and actor_oper key is changed at multiple locations in the code. This patch brings all those updates into one location in an attempt to avoid possible inconsistent updates causing LACP state machine to go in weird state. The unified place is ad_update_actor_key() with simple state-machine logic - (a) If port is "duplex" then only it can participate in LACP (b) Speed change reinitializes the LACP state-machine. Signed-off-by: Mahesh Bandewar <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b25c2e7 commit 7bb11dc

File tree

1 file changed

+52
-35
lines changed

1 file changed

+52
-35
lines changed

drivers/net/bonding/bond_3ad.c

Lines changed: 52 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ static void ad_marker_info_received(struct bond_marker *marker_info,
127127
struct port *port);
128128
static void ad_marker_response_received(struct bond_marker *marker,
129129
struct port *port);
130+
static void ad_update_actor_keys(struct port *port, bool reset);
130131

131132

132133
/* ================= api to bonding and kernel code ================== */
@@ -1951,14 +1952,7 @@ void bond_3ad_bind_slave(struct slave *slave)
19511952
* user key
19521953
*/
19531954
port->actor_admin_port_key = bond->params.ad_user_port_key << 6;
1954-
port->actor_admin_port_key |= __get_duplex(port);
1955-
port->actor_admin_port_key |= (__get_link_speed(port) << 1);
1956-
port->actor_oper_port_key = port->actor_admin_port_key;
1957-
/* if the port is not full duplex, then the port should be not
1958-
* lacp Enabled
1959-
*/
1960-
if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_MASKS))
1961-
port->sm_vars &= ~AD_PORT_LACP_ENABLED;
1955+
ad_update_actor_keys(port, false);
19621956
/* actor system is the bond's system */
19631957
port->actor_system = BOND_AD_INFO(bond).system.sys_mac_addr;
19641958
port->actor_system_priority =
@@ -2307,6 +2301,52 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave,
23072301
return ret;
23082302
}
23092303

2304+
/**
2305+
* ad_update_actor_keys - Update the oper / admin keys for a port based on
2306+
* its current speed and duplex settings.
2307+
*
2308+
* @port: the port we'are looking at
2309+
* @reset: Boolean to just reset the speed and the duplex part of the key
2310+
*
2311+
* The logic to change the oper / admin keys is:
2312+
* (a) A full duplex port can participate in LACP with partner.
2313+
* (b) When the speed is changed, LACP need to be reinitiated.
2314+
*/
2315+
static void ad_update_actor_keys(struct port *port, bool reset)
2316+
{
2317+
u8 duplex = 0;
2318+
u16 ospeed = 0, speed = 0;
2319+
u16 old_oper_key = port->actor_oper_port_key;
2320+
2321+
port->actor_admin_port_key &= ~(AD_SPEED_KEY_MASKS|AD_DUPLEX_KEY_MASKS);
2322+
if (!reset) {
2323+
speed = __get_link_speed(port);
2324+
ospeed = (old_oper_key & AD_SPEED_KEY_MASKS) >> 1;
2325+
duplex = __get_duplex(port);
2326+
port->actor_admin_port_key |= (speed << 1) | duplex;
2327+
}
2328+
port->actor_oper_port_key = port->actor_admin_port_key;
2329+
2330+
if (old_oper_key != port->actor_oper_port_key) {
2331+
/* Only 'duplex' port participates in LACP */
2332+
if (duplex)
2333+
port->sm_vars |= AD_PORT_LACP_ENABLED;
2334+
else
2335+
port->sm_vars &= ~AD_PORT_LACP_ENABLED;
2336+
2337+
if (!reset) {
2338+
if (!speed) {
2339+
netdev_err(port->slave->dev,
2340+
"speed changed to 0 for port %s",
2341+
port->slave->dev->name);
2342+
} else if (duplex && ospeed != speed) {
2343+
/* Speed change restarts LACP state-machine */
2344+
port->sm_vars |= AD_PORT_BEGIN;
2345+
}
2346+
}
2347+
}
2348+
}
2349+
23102350
/**
23112351
* bond_3ad_adapter_speed_changed - handle a slave's speed change indication
23122352
* @slave: slave struct to work on
@@ -2328,14 +2368,8 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
23282368

23292369
spin_lock_bh(&slave->bond->mode_lock);
23302370

2331-
port->actor_admin_port_key &= ~AD_SPEED_KEY_MASKS;
2332-
port->actor_admin_port_key |= __get_link_speed(port) << 1;
2333-
port->actor_oper_port_key = port->actor_admin_port_key;
2371+
ad_update_actor_keys(port, false);
23342372
netdev_dbg(slave->bond->dev, "Port %d changed speed\n", port->actor_port_number);
2335-
/* there is no need to reselect a new aggregator, just signal the
2336-
* state machines to reinitialize
2337-
*/
2338-
port->sm_vars |= AD_PORT_BEGIN;
23392373

23402374
spin_unlock_bh(&slave->bond->mode_lock);
23412375
}
@@ -2361,17 +2395,9 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
23612395

23622396
spin_lock_bh(&slave->bond->mode_lock);
23632397

2364-
port->actor_admin_port_key &= ~AD_DUPLEX_KEY_MASKS;
2365-
port->actor_admin_port_key |= __get_duplex(port);
2366-
port->actor_oper_port_key = port->actor_admin_port_key;
2398+
ad_update_actor_keys(port, false);
23672399
netdev_dbg(slave->bond->dev, "Port %d slave %s changed duplex\n",
23682400
port->actor_port_number, slave->dev->name);
2369-
if (port->actor_oper_port_key & AD_DUPLEX_KEY_MASKS)
2370-
port->sm_vars |= AD_PORT_LACP_ENABLED;
2371-
/* there is no need to reselect a new aggregator, just signal the
2372-
* state machines to reinitialize
2373-
*/
2374-
port->sm_vars |= AD_PORT_BEGIN;
23752401

23762402
spin_unlock_bh(&slave->bond->mode_lock);
23772403
}
@@ -2404,26 +2430,17 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
24042430
* on link up we are forcing recheck on the duplex and speed since
24052431
* some of he adaptors(ce1000.lan) report.
24062432
*/
2407-
port->actor_admin_port_key &= ~(AD_DUPLEX_KEY_MASKS|AD_SPEED_KEY_MASKS);
24082433
if (link == BOND_LINK_UP) {
24092434
port->is_enabled = true;
2410-
port->actor_admin_port_key |=
2411-
(__get_link_speed(port) << 1) | __get_duplex(port);
2412-
if (port->actor_admin_port_key & AD_DUPLEX_KEY_MASKS)
2413-
port->sm_vars |= AD_PORT_LACP_ENABLED;
2435+
ad_update_actor_keys(port, false);
24142436
} else {
24152437
/* link has failed */
24162438
port->is_enabled = false;
2417-
port->sm_vars &= ~AD_PORT_LACP_ENABLED;
2439+
ad_update_actor_keys(port, true);
24182440
}
2419-
port->actor_oper_port_key = port->actor_admin_port_key;
24202441
netdev_dbg(slave->bond->dev, "Port %d changed link status to %s\n",
24212442
port->actor_port_number,
24222443
link == BOND_LINK_UP ? "UP" : "DOWN");
2423-
/* there is no need to reselect a new aggregator, just signal the
2424-
* state machines to reinitialize
2425-
*/
2426-
port->sm_vars |= AD_PORT_BEGIN;
24272444

24282445
spin_unlock_bh(&slave->bond->mode_lock);
24292446

0 commit comments

Comments
 (0)