aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding
diff options
context:
space:
mode:
authorWilson Kok <wkok@cumulusnetworks.com>2015-01-26 01:16:59 -0500
committerDavid S. Miller <davem@davemloft.net>2015-01-27 20:09:04 -0500
commit63b46242f707849a1df10b70e026281bfa40e849 (patch)
treeb90aa0bb391d860341c88254969577565e76ffcc /drivers/net/bonding
parent8bbe71a5956f833ec0d940419d1d368de5f1b58b (diff)
bonding: fix incorrect lacp mux state when agg not active
This patch attempts to fix the following problems when an actor or partner's aggregator is not active: 1. a slave's lacp port state is marked as AD_STATE_SYNCHRONIZATION even if it is attached to an inactive aggregator. LACP advertises this state to the partner, making the partner think he can move into COLLECTING_DISTRIBUTING state even though this link will not pass traffic on the local side 2. a slave goes into COLLECTING_DISTRIBUTING state without checking if the aggregator is actually active 3. when in COLLECTING_DISTRIBUTING state, the partner parameters may change, e.g. the partner_oper_port_state.SYNCHRONIZATION. The local mux machine is not reacting to the change and continue to keep the slave and bond up 4. When bond slave leaves an inactive aggregator and joins an active aggregator, the actor oper port state need to update to SYNC state. v2: * fix style issues in bond_3ad.c Cc: Andy Gospodarek <gospo@cumulusnetworks.com> Reviewed-by: Nikolay Aleksandrov <nikolay@redhat.com> Signed-off-by: Wilson Kok <wkok@cumulusnetworks.com> Signed-off-by: Jonathan Toppins <jtoppins@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r--drivers/net/bonding/bond_3ad.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 8baa87df1738..e3c96b216eb8 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -467,11 +467,14 @@ static void __record_pdu(struct lacpdu *lacpdu, struct port *port)
467 /* set the partner sync. to on if the partner is sync, 467 /* set the partner sync. to on if the partner is sync,
468 * and the port is matched 468 * and the port is matched
469 */ 469 */
470 if ((port->sm_vars & AD_PORT_MATCHED) 470 if ((port->sm_vars & AD_PORT_MATCHED) &&
471 && (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION)) 471 (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION)) {
472 partner->port_state |= AD_STATE_SYNCHRONIZATION; 472 partner->port_state |= AD_STATE_SYNCHRONIZATION;
473 else 473 pr_debug("%s partner sync=1\n", port->slave->dev->name);
474 } else {
474 partner->port_state &= ~AD_STATE_SYNCHRONIZATION; 475 partner->port_state &= ~AD_STATE_SYNCHRONIZATION;
476 pr_debug("%s partner sync=0\n", port->slave->dev->name);
477 }
475 } 478 }
476} 479}
477 480
@@ -726,6 +729,8 @@ static inline void __update_lacpdu_from_port(struct port *port)
726 lacpdu->actor_port_priority = htons(port->actor_port_priority); 729 lacpdu->actor_port_priority = htons(port->actor_port_priority);
727 lacpdu->actor_port = htons(port->actor_port_number); 730 lacpdu->actor_port = htons(port->actor_port_number);
728 lacpdu->actor_state = port->actor_oper_port_state; 731 lacpdu->actor_state = port->actor_oper_port_state;
732 pr_debug("update lacpdu: %s, actor port state %x\n",
733 port->slave->dev->name, port->actor_oper_port_state);
729 734
730 /* lacpdu->reserved_3_1 initialized 735 /* lacpdu->reserved_3_1 initialized
731 * lacpdu->tlv_type_partner_info initialized 736 * lacpdu->tlv_type_partner_info initialized
@@ -898,7 +903,9 @@ static void ad_mux_machine(struct port *port, bool *update_slave_arr)
898 if ((port->sm_vars & AD_PORT_SELECTED) && 903 if ((port->sm_vars & AD_PORT_SELECTED) &&
899 (port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION) && 904 (port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION) &&
900 !__check_agg_selection_timer(port)) { 905 !__check_agg_selection_timer(port)) {
901 port->sm_mux_state = AD_MUX_COLLECTING_DISTRIBUTING; 906 if (port->aggregator->is_active)
907 port->sm_mux_state =
908 AD_MUX_COLLECTING_DISTRIBUTING;
902 } else if (!(port->sm_vars & AD_PORT_SELECTED) || 909 } else if (!(port->sm_vars & AD_PORT_SELECTED) ||
903 (port->sm_vars & AD_PORT_STANDBY)) { 910 (port->sm_vars & AD_PORT_STANDBY)) {
904 /* if UNSELECTED or STANDBY */ 911 /* if UNSELECTED or STANDBY */
@@ -910,12 +917,16 @@ static void ad_mux_machine(struct port *port, bool *update_slave_arr)
910 */ 917 */
911 __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator)); 918 __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
912 port->sm_mux_state = AD_MUX_DETACHED; 919 port->sm_mux_state = AD_MUX_DETACHED;
920 } else if (port->aggregator->is_active) {
921 port->actor_oper_port_state |=
922 AD_STATE_SYNCHRONIZATION;
913 } 923 }
914 break; 924 break;
915 case AD_MUX_COLLECTING_DISTRIBUTING: 925 case AD_MUX_COLLECTING_DISTRIBUTING:
916 if (!(port->sm_vars & AD_PORT_SELECTED) || 926 if (!(port->sm_vars & AD_PORT_SELECTED) ||
917 (port->sm_vars & AD_PORT_STANDBY) || 927 (port->sm_vars & AD_PORT_STANDBY) ||
918 !(port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION)) { 928 !(port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION) ||
929 !(port->actor_oper_port_state & AD_STATE_SYNCHRONIZATION)) {
919 port->sm_mux_state = AD_MUX_ATTACHED; 930 port->sm_mux_state = AD_MUX_ATTACHED;
920 } else { 931 } else {
921 /* if port state hasn't changed make 932 /* if port state hasn't changed make
@@ -937,8 +948,10 @@ static void ad_mux_machine(struct port *port, bool *update_slave_arr)
937 948
938 /* check if the state machine was changed */ 949 /* check if the state machine was changed */
939 if (port->sm_mux_state != last_state) { 950 if (port->sm_mux_state != last_state) {
940 pr_debug("Mux Machine: Port=%d, Last State=%d, Curr State=%d\n", 951 pr_debug("Mux Machine: Port=%d (%s), Last State=%d, Curr State=%d\n",
941 port->actor_port_number, last_state, 952 port->actor_port_number,
953 port->slave->dev->name,
954 last_state,
942 port->sm_mux_state); 955 port->sm_mux_state);
943 switch (port->sm_mux_state) { 956 switch (port->sm_mux_state) {
944 case AD_MUX_DETACHED: 957 case AD_MUX_DETACHED:
@@ -953,7 +966,12 @@ static void ad_mux_machine(struct port *port, bool *update_slave_arr)
953 port->sm_mux_timer_counter = __ad_timer_to_ticks(AD_WAIT_WHILE_TIMER, 0); 966 port->sm_mux_timer_counter = __ad_timer_to_ticks(AD_WAIT_WHILE_TIMER, 0);
954 break; 967 break;
955 case AD_MUX_ATTACHED: 968 case AD_MUX_ATTACHED:
956 port->actor_oper_port_state |= AD_STATE_SYNCHRONIZATION; 969 if (port->aggregator->is_active)
970 port->actor_oper_port_state |=
971 AD_STATE_SYNCHRONIZATION;
972 else
973 port->actor_oper_port_state &=
974 ~AD_STATE_SYNCHRONIZATION;
957 port->actor_oper_port_state &= ~AD_STATE_COLLECTING; 975 port->actor_oper_port_state &= ~AD_STATE_COLLECTING;
958 port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING; 976 port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING;
959 ad_disable_collecting_distributing(port, 977 ad_disable_collecting_distributing(port,
@@ -963,6 +981,7 @@ static void ad_mux_machine(struct port *port, bool *update_slave_arr)
963 case AD_MUX_COLLECTING_DISTRIBUTING: 981 case AD_MUX_COLLECTING_DISTRIBUTING:
964 port->actor_oper_port_state |= AD_STATE_COLLECTING; 982 port->actor_oper_port_state |= AD_STATE_COLLECTING;
965 port->actor_oper_port_state |= AD_STATE_DISTRIBUTING; 983 port->actor_oper_port_state |= AD_STATE_DISTRIBUTING;
984 port->actor_oper_port_state |= AD_STATE_SYNCHRONIZATION;
966 ad_enable_collecting_distributing(port, 985 ad_enable_collecting_distributing(port,
967 update_slave_arr); 986 update_slave_arr);
968 port->ntt = true; 987 port->ntt = true;
@@ -1044,8 +1063,10 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
1044 1063
1045 /* check if the State machine was changed or new lacpdu arrived */ 1064 /* check if the State machine was changed or new lacpdu arrived */
1046 if ((port->sm_rx_state != last_state) || (lacpdu)) { 1065 if ((port->sm_rx_state != last_state) || (lacpdu)) {
1047 pr_debug("Rx Machine: Port=%d, Last State=%d, Curr State=%d\n", 1066 pr_debug("Rx Machine: Port=%d (%s), Last State=%d, Curr State=%d\n",
1048 port->actor_port_number, last_state, 1067 port->actor_port_number,
1068 port->slave->dev->name,
1069 last_state,
1049 port->sm_rx_state); 1070 port->sm_rx_state);
1050 switch (port->sm_rx_state) { 1071 switch (port->sm_rx_state) {
1051 case AD_RX_INITIALIZE: 1072 case AD_RX_INITIALIZE:
@@ -1394,6 +1415,9 @@ static void ad_port_selection_logic(struct port *port, bool *update_slave_arr)
1394 1415
1395 aggregator = __get_first_agg(port); 1416 aggregator = __get_first_agg(port);
1396 ad_agg_selection_logic(aggregator, update_slave_arr); 1417 ad_agg_selection_logic(aggregator, update_slave_arr);
1418
1419 if (!port->aggregator->is_active)
1420 port->actor_oper_port_state &= ~AD_STATE_SYNCHRONIZATION;
1397} 1421}
1398 1422
1399/* Decide if "agg" is a better choice for the new active aggregator that 1423/* Decide if "agg" is a better choice for the new active aggregator that