@@ -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 ================== */
@@ -1951,14 +1952,7 @@ void bond_3ad_bind_slave(struct slave *slave)
1951
1952
* user key
1952
1953
*/
1953
1954
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);
1962
1956
/* actor system is the bond's system */
1963
1957
port -> actor_system = BOND_AD_INFO (bond ).system .sys_mac_addr ;
1964
1958
port -> actor_system_priority =
@@ -2307,6 +2301,52 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave,
2307
2301
return ret ;
2308
2302
}
2309
2303
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
+
2310
2350
/**
2311
2351
* bond_3ad_adapter_speed_changed - handle a slave's speed change indication
2312
2352
* @slave: slave struct to work on
@@ -2328,14 +2368,8 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
2328
2368
2329
2369
spin_lock_bh (& slave -> bond -> mode_lock );
2330
2370
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);
2334
2372
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 ;
2339
2373
2340
2374
spin_unlock_bh (& slave -> bond -> mode_lock );
2341
2375
}
@@ -2361,17 +2395,9 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
2361
2395
2362
2396
spin_lock_bh (& slave -> bond -> mode_lock );
2363
2397
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);
2367
2399
netdev_dbg (slave -> bond -> dev , "Port %d slave %s changed duplex\n" ,
2368
2400
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 ;
2375
2401
2376
2402
spin_unlock_bh (& slave -> bond -> mode_lock );
2377
2403
}
@@ -2404,26 +2430,17 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
2404
2430
* on link up we are forcing recheck on the duplex and speed since
2405
2431
* some of he adaptors(ce1000.lan) report.
2406
2432
*/
2407
- port -> actor_admin_port_key &= ~(AD_DUPLEX_KEY_MASKS |AD_SPEED_KEY_MASKS );
2408
2433
if (link == BOND_LINK_UP ) {
2409
2434
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);
2414
2436
} else {
2415
2437
/* link has failed */
2416
2438
port -> is_enabled = false;
2417
- port -> sm_vars &= ~ AD_PORT_LACP_ENABLED ;
2439
+ ad_update_actor_keys ( port , true) ;
2418
2440
}
2419
- port -> actor_oper_port_key = port -> actor_admin_port_key ;
2420
2441
netdev_dbg (slave -> bond -> dev , "Port %d changed link status to %s\n" ,
2421
2442
port -> actor_port_number ,
2422
2443
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 ;
2427
2444
2428
2445
spin_unlock_bh (& slave -> bond -> mode_lock );
2429
2446
0 commit comments