@@ -127,6 +127,7 @@ static void ad_marker_info_received(struct bond_marker *marker_info,
127
127
struct port * port );
128
128
static void ad_marker_response_received (struct bond_marker * marker ,
129
129
struct port * port );
130
+ static void ad_update_actor_keys (struct port * port , bool reset );
130
131
131
132
132
133
/* ================= api to bonding and kernel code ================== */
@@ -327,14 +328,12 @@ static u16 __get_link_speed(struct port *port)
327
328
static u8 __get_duplex (struct port * port )
328
329
{
329
330
struct slave * slave = port -> slave ;
330
- u8 retval ;
331
+ u8 retval = 0x0 ;
331
332
332
333
/* handling a special case: when the configuration starts with
333
334
* link down, it sets the duplex to 0.
334
335
*/
335
- if (slave -> link != BOND_LINK_UP ) {
336
- retval = 0x0 ;
337
- } else {
336
+ if (slave -> link == BOND_LINK_UP ) {
338
337
switch (slave -> duplex ) {
339
338
case DUPLEX_FULL :
340
339
retval = 0x1 ;
@@ -1953,14 +1952,7 @@ void bond_3ad_bind_slave(struct slave *slave)
1953
1952
* user key
1954
1953
*/
1955
1954
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);
1964
1956
/* actor system is the bond's system */
1965
1957
port -> actor_system = BOND_AD_INFO (bond ).system .sys_mac_addr ;
1966
1958
port -> actor_system_priority =
@@ -2310,71 +2302,77 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave,
2310
2302
}
2311
2303
2312
2304
/**
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.
2315
2307
*
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.
2317
2314
*/
2318
- void bond_3ad_adapter_speed_changed (struct slave * slave )
2315
+ static void ad_update_actor_keys (struct port * port , bool reset )
2319
2316
{
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 ;
2329
2327
}
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 ;
2335
2328
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 ;
2341
2329
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
+ }
2343
2348
}
2344
2349
2345
2350
/**
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
+ *
2347
2354
* @slave: slave struct to work on
2348
2355
*
2349
2356
* Handle reselection of aggregator (if needed) for this port.
2350
2357
*/
2351
- void bond_3ad_adapter_duplex_changed (struct slave * slave )
2358
+ void bond_3ad_adapter_speed_duplex_changed (struct slave * slave )
2352
2359
{
2353
2360
struct port * port ;
2354
2361
2355
2362
port = & (SLAVE_AD_INFO (slave )-> port );
2356
2363
2357
2364
/* if slave is null, the whole port is not initialized */
2358
2365
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" ,
2360
2368
slave -> dev -> name );
2361
2369
return ;
2362
2370
}
2363
2371
2364
2372
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" ,
2370
2375
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
-
2378
2376
spin_unlock_bh (& slave -> bond -> mode_lock );
2379
2377
}
2380
2378
@@ -2406,26 +2404,17 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
2406
2404
* on link up we are forcing recheck on the duplex and speed since
2407
2405
* some of he adaptors(ce1000.lan) report.
2408
2406
*/
2409
- port -> actor_admin_port_key &= ~(AD_DUPLEX_KEY_MASKS |AD_SPEED_KEY_MASKS );
2410
2407
if (link == BOND_LINK_UP ) {
2411
2408
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);
2416
2410
} else {
2417
2411
/* link has failed */
2418
2412
port -> is_enabled = false;
2419
- port -> sm_vars &= ~ AD_PORT_LACP_ENABLED ;
2413
+ ad_update_actor_keys ( port , true) ;
2420
2414
}
2421
- port -> actor_oper_port_key = port -> actor_admin_port_key ;
2422
2415
netdev_dbg (slave -> bond -> dev , "Port %d changed link status to %s\n" ,
2423
2416
port -> actor_port_number ,
2424
2417
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 ;
2429
2418
2430
2419
spin_unlock_bh (& slave -> bond -> mode_lock );
2431
2420
0 commit comments