@@ -127,6 +127,7 @@ static void ad_marker_info_received(struct bond_marker *marker_info,
127127 struct port * port );
128128static 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