Skip to content

Commit a176ded

Browse files
committed
Merge branch 'bonding-actor-updates'
Mahesh Bandewar says: ==================== re-org actor admin/oper key updates I was observing machines entering into weird LACP state when the partner is in passive mode. This issue is not because of the partners in passive state but probably because of some operational key update which is pushing the state-machine is that weird state. This was happening randomly on about 1% of the machine (when the sample size is a large set of machines with a variety of NICs/ports bonded). In this patch-series I'm attempting to unify the logic of actor-key / operational-key changes to one place to avoid possible errors in update. Also this eliminates the need for the event-handler to decide if the key needs update. After this patch-set none of the machines (from same sample set) were exhibiting LACP-weirdness that was observed earlier. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 12d4309 + 52bc671 commit a176ded

File tree

3 files changed

+54
-76
lines changed

3 files changed

+54
-76
lines changed

drivers/net/bonding/bond_3ad.c

Lines changed: 51 additions & 62 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 ================== */
@@ -327,14 +328,12 @@ static u16 __get_link_speed(struct port *port)
327328
static u8 __get_duplex(struct port *port)
328329
{
329330
struct slave *slave = port->slave;
330-
u8 retval;
331+
u8 retval = 0x0;
331332

332333
/* handling a special case: when the configuration starts with
333334
* link down, it sets the duplex to 0.
334335
*/
335-
if (slave->link != BOND_LINK_UP) {
336-
retval = 0x0;
337-
} else {
336+
if (slave->link == BOND_LINK_UP) {
338337
switch (slave->duplex) {
339338
case DUPLEX_FULL:
340339
retval = 0x1;
@@ -1953,14 +1952,7 @@ void bond_3ad_bind_slave(struct slave *slave)
19531952
* user key
19541953
*/
19551954
port->actor_admin_port_key = bond->params.ad_user_port_key << 6;
1956-
port->actor_admin_port_key |= __get_duplex(port);
1957-
port->actor_admin_port_key |= (__get_link_speed(port) << 1);
1958-
port->actor_oper_port_key = port->actor_admin_port_key;
1959-
/* if the port is not full duplex, then the port should be not
1960-
* lacp Enabled
1961-
*/
1962-
if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_MASKS))
1963-
port->sm_vars &= ~AD_PORT_LACP_ENABLED;
1955+
ad_update_actor_keys(port, false);
19641956
/* actor system is the bond's system */
19651957
port->actor_system = BOND_AD_INFO(bond).system.sys_mac_addr;
19661958
port->actor_system_priority =
@@ -2310,71 +2302,77 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave,
23102302
}
23112303

23122304
/**
2313-
* bond_3ad_adapter_speed_changed - handle a slave's speed change indication
2314-
* @slave: slave struct to work on
2305+
* ad_update_actor_keys - Update the oper / admin keys for a port based on
2306+
* its current speed and duplex settings.
23152307
*
2316-
* Handle reselection of aggregator (if needed) for this port.
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.
23172314
*/
2318-
void bond_3ad_adapter_speed_changed(struct slave *slave)
2315+
static void ad_update_actor_keys(struct port *port, bool reset)
23192316
{
2320-
struct port *port;
2321-
2322-
port = &(SLAVE_AD_INFO(slave)->port);
2323-
2324-
/* if slave is null, the whole port is not initialized */
2325-
if (!port->slave) {
2326-
netdev_warn(slave->bond->dev, "speed changed for uninitialized port on %s\n",
2327-
slave->dev->name);
2328-
return;
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;
23292327
}
2330-
2331-
spin_lock_bh(&slave->bond->mode_lock);
2332-
2333-
port->actor_admin_port_key &= ~AD_SPEED_KEY_MASKS;
2334-
port->actor_admin_port_key |= __get_link_speed(port) << 1;
23352328
port->actor_oper_port_key = port->actor_admin_port_key;
2336-
netdev_dbg(slave->bond->dev, "Port %d changed speed\n", port->actor_port_number);
2337-
/* there is no need to reselect a new aggregator, just signal the
2338-
* state machines to reinitialize
2339-
*/
2340-
port->sm_vars |= AD_PORT_BEGIN;
23412329

2342-
spin_unlock_bh(&slave->bond->mode_lock);
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+
}
23432348
}
23442349

23452350
/**
2346-
* bond_3ad_adapter_duplex_changed - handle a slave's duplex change indication
2351+
* bond_3ad_adapter_speed_duplex_changed - handle a slave's speed / duplex
2352+
* change indication
2353+
*
23472354
* @slave: slave struct to work on
23482355
*
23492356
* Handle reselection of aggregator (if needed) for this port.
23502357
*/
2351-
void bond_3ad_adapter_duplex_changed(struct slave *slave)
2358+
void bond_3ad_adapter_speed_duplex_changed(struct slave *slave)
23522359
{
23532360
struct port *port;
23542361

23552362
port = &(SLAVE_AD_INFO(slave)->port);
23562363

23572364
/* if slave is null, the whole port is not initialized */
23582365
if (!port->slave) {
2359-
netdev_warn(slave->bond->dev, "duplex changed for uninitialized port on %s\n",
2366+
netdev_warn(slave->bond->dev,
2367+
"speed/duplex changed for uninitialized port %s\n",
23602368
slave->dev->name);
23612369
return;
23622370
}
23632371

23642372
spin_lock_bh(&slave->bond->mode_lock);
2365-
2366-
port->actor_admin_port_key &= ~AD_DUPLEX_KEY_MASKS;
2367-
port->actor_admin_port_key |= __get_duplex(port);
2368-
port->actor_oper_port_key = port->actor_admin_port_key;
2369-
netdev_dbg(slave->bond->dev, "Port %d slave %s changed duplex\n",
2373+
ad_update_actor_keys(port, false);
2374+
netdev_dbg(slave->bond->dev, "Port %d slave %s changed speed/duplex\n",
23702375
port->actor_port_number, slave->dev->name);
2371-
if (port->actor_oper_port_key & AD_DUPLEX_KEY_MASKS)
2372-
port->sm_vars |= AD_PORT_LACP_ENABLED;
2373-
/* there is no need to reselect a new aggregator, just signal the
2374-
* state machines to reinitialize
2375-
*/
2376-
port->sm_vars |= AD_PORT_BEGIN;
2377-
23782376
spin_unlock_bh(&slave->bond->mode_lock);
23792377
}
23802378

@@ -2406,26 +2404,17 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
24062404
* on link up we are forcing recheck on the duplex and speed since
24072405
* some of he adaptors(ce1000.lan) report.
24082406
*/
2409-
port->actor_admin_port_key &= ~(AD_DUPLEX_KEY_MASKS|AD_SPEED_KEY_MASKS);
24102407
if (link == BOND_LINK_UP) {
24112408
port->is_enabled = true;
2412-
port->actor_admin_port_key |=
2413-
(__get_link_speed(port) << 1) | __get_duplex(port);
2414-
if (port->actor_admin_port_key & AD_DUPLEX_KEY_MASKS)
2415-
port->sm_vars |= AD_PORT_LACP_ENABLED;
2409+
ad_update_actor_keys(port, false);
24162410
} else {
24172411
/* link has failed */
24182412
port->is_enabled = false;
2419-
port->sm_vars &= ~AD_PORT_LACP_ENABLED;
2413+
ad_update_actor_keys(port, true);
24202414
}
2421-
port->actor_oper_port_key = port->actor_admin_port_key;
24222415
netdev_dbg(slave->bond->dev, "Port %d changed link status to %s\n",
24232416
port->actor_port_number,
24242417
link == BOND_LINK_UP ? "UP" : "DOWN");
2425-
/* there is no need to reselect a new aggregator, just signal the
2426-
* state machines to reinitialize
2427-
*/
2428-
port->sm_vars |= AD_PORT_BEGIN;
24292418

24302419
spin_unlock_bh(&slave->bond->mode_lock);
24312420

drivers/net/bonding/bond_main.c

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2943,8 +2943,6 @@ static int bond_slave_netdev_event(unsigned long event,
29432943
struct slave *slave = bond_slave_get_rtnl(slave_dev), *primary;
29442944
struct bonding *bond;
29452945
struct net_device *bond_dev;
2946-
u32 old_speed;
2947-
u8 old_duplex;
29482946

29492947
/* A netdev event can be generated while enslaving a device
29502948
* before netdev_rx_handler_register is called in which case
@@ -2965,17 +2963,9 @@ static int bond_slave_netdev_event(unsigned long event,
29652963
break;
29662964
case NETDEV_UP:
29672965
case NETDEV_CHANGE:
2968-
old_speed = slave->speed;
2969-
old_duplex = slave->duplex;
2970-
29712966
bond_update_speed_duplex(slave);
2972-
2973-
if (BOND_MODE(bond) == BOND_MODE_8023AD) {
2974-
if (old_speed != slave->speed)
2975-
bond_3ad_adapter_speed_changed(slave);
2976-
if (old_duplex != slave->duplex)
2977-
bond_3ad_adapter_duplex_changed(slave);
2978-
}
2967+
if (BOND_MODE(bond) == BOND_MODE_8023AD)
2968+
bond_3ad_adapter_speed_duplex_changed(slave);
29792969
/* Fallthrough */
29802970
case NETDEV_DOWN:
29812971
/* Refresh slave-array if applicable!

include/net/bond_3ad.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,7 @@ void bond_3ad_bind_slave(struct slave *slave);
297297
void bond_3ad_unbind_slave(struct slave *slave);
298298
void bond_3ad_state_machine_handler(struct work_struct *);
299299
void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout);
300-
void bond_3ad_adapter_speed_changed(struct slave *slave);
301-
void bond_3ad_adapter_duplex_changed(struct slave *slave);
300+
void bond_3ad_adapter_speed_duplex_changed(struct slave *slave);
302301
void bond_3ad_handle_link_change(struct slave *slave, char link);
303302
int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info);
304303
int __bond_3ad_get_active_agg_info(struct bonding *bond,

0 commit comments

Comments
 (0)