summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-01-27 17:09:09 -0800
committerDavid S. Miller <davem@davemloft.net>2015-01-27 17:09:09 -0800
commit5094c6f8755407e2d97bfbb4c76fefca3274d3c7 (patch)
tree585a12ea9325e14b1b27fd73497873ddbc18d288
parent999028cc1ccd1cd3a1c0104c6423553d3f573197 (diff)
parent303691042d2fc996125f479cf01bd5ead8b90a16 (diff)
Merge branch 'bonding-next'
Jonathan Toppins says: ==================== bonding: various 802.3ad fixes This patch series is a forward porting of patches we (Cumulus) are shipping in our 3.2 series kernels. These fixes attempt to make 802.3ad bonding mode more predictable in certian state machine transtions in addition to fixing 802.3ad bond carrier determination when bonding min_links option is changed. Specific notes are contained within each patch. For this patch series there are no userspace facing changes, a diff between the modinfo output showed no difference. However, there are behavioral facing changes, primarily in the bond carrier state. Please make sure to review carefully. v2: * fixed some style issues * dropped a portion of patch 1 in favor of more testing on my side ==================== Signed-off-by: Andy Gospodarek <gospo@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/bonding/bond_3ad.c55
-rw-r--r--drivers/net/bonding/bond_main.c6
-rw-r--r--drivers/net/bonding/bond_options.c1
-rw-r--r--include/net/bond_3ad.h1
-rw-r--r--include/net/bonding.h1
5 files changed, 47 insertions, 17 deletions
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 8baa87df1738..cfc4a9c1000a 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)
/* set the partner sync. to on if the partner is sync,
* and the port is matched
*/
- if ((port->sm_vars & AD_PORT_MATCHED)
- && (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION))
+ if ((port->sm_vars & AD_PORT_MATCHED) &&
+ (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION)) {
partner->port_state |= AD_STATE_SYNCHRONIZATION;
- else
+ pr_debug("%s partner sync=1\n", port->slave->dev->name);
+ } else {
partner->port_state &= ~AD_STATE_SYNCHRONIZATION;
+ pr_debug("%s partner sync=0\n", port->slave->dev->name);
+ }
}
}
@@ -726,6 +729,8 @@ static inline void __update_lacpdu_from_port(struct port *port)
lacpdu->actor_port_priority = htons(port->actor_port_priority);
lacpdu->actor_port = htons(port->actor_port_number);
lacpdu->actor_state = port->actor_oper_port_state;
+ pr_debug("update lacpdu: %s, actor port state %x\n",
+ port->slave->dev->name, port->actor_oper_port_state);
/* lacpdu->reserved_3_1 initialized
* lacpdu->tlv_type_partner_info initialized
@@ -898,7 +903,9 @@ static void ad_mux_machine(struct port *port, bool *update_slave_arr)
if ((port->sm_vars & AD_PORT_SELECTED) &&
(port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION) &&
!__check_agg_selection_timer(port)) {
- port->sm_mux_state = AD_MUX_COLLECTING_DISTRIBUTING;
+ if (port->aggregator->is_active)
+ port->sm_mux_state =
+ AD_MUX_COLLECTING_DISTRIBUTING;
} else if (!(port->sm_vars & AD_PORT_SELECTED) ||
(port->sm_vars & AD_PORT_STANDBY)) {
/* if UNSELECTED or STANDBY */
@@ -910,12 +917,16 @@ static void ad_mux_machine(struct port *port, bool *update_slave_arr)
*/
__set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
port->sm_mux_state = AD_MUX_DETACHED;
+ } else if (port->aggregator->is_active) {
+ port->actor_oper_port_state |=
+ AD_STATE_SYNCHRONIZATION;
}
break;
case AD_MUX_COLLECTING_DISTRIBUTING:
if (!(port->sm_vars & AD_PORT_SELECTED) ||
(port->sm_vars & AD_PORT_STANDBY) ||
- !(port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION)) {
+ !(port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION) ||
+ !(port->actor_oper_port_state & AD_STATE_SYNCHRONIZATION)) {
port->sm_mux_state = AD_MUX_ATTACHED;
} else {
/* if port state hasn't changed make
@@ -937,8 +948,10 @@ static void ad_mux_machine(struct port *port, bool *update_slave_arr)
/* check if the state machine was changed */
if (port->sm_mux_state != last_state) {
- pr_debug("Mux Machine: Port=%d, Last State=%d, Curr State=%d\n",
- port->actor_port_number, last_state,
+ pr_debug("Mux Machine: Port=%d (%s), Last State=%d, Curr State=%d\n",
+ port->actor_port_number,
+ port->slave->dev->name,
+ last_state,
port->sm_mux_state);
switch (port->sm_mux_state) {
case AD_MUX_DETACHED:
@@ -953,7 +966,12 @@ static void ad_mux_machine(struct port *port, bool *update_slave_arr)
port->sm_mux_timer_counter = __ad_timer_to_ticks(AD_WAIT_WHILE_TIMER, 0);
break;
case AD_MUX_ATTACHED:
- port->actor_oper_port_state |= AD_STATE_SYNCHRONIZATION;
+ if (port->aggregator->is_active)
+ port->actor_oper_port_state |=
+ AD_STATE_SYNCHRONIZATION;
+ else
+ port->actor_oper_port_state &=
+ ~AD_STATE_SYNCHRONIZATION;
port->actor_oper_port_state &= ~AD_STATE_COLLECTING;
port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING;
ad_disable_collecting_distributing(port,
@@ -963,6 +981,7 @@ static void ad_mux_machine(struct port *port, bool *update_slave_arr)
case AD_MUX_COLLECTING_DISTRIBUTING:
port->actor_oper_port_state |= AD_STATE_COLLECTING;
port->actor_oper_port_state |= AD_STATE_DISTRIBUTING;
+ port->actor_oper_port_state |= AD_STATE_SYNCHRONIZATION;
ad_enable_collecting_distributing(port,
update_slave_arr);
port->ntt = true;
@@ -1044,8 +1063,10 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
/* check if the State machine was changed or new lacpdu arrived */
if ((port->sm_rx_state != last_state) || (lacpdu)) {
- pr_debug("Rx Machine: Port=%d, Last State=%d, Curr State=%d\n",
- port->actor_port_number, last_state,
+ pr_debug("Rx Machine: Port=%d (%s), Last State=%d, Curr State=%d\n",
+ port->actor_port_number,
+ port->slave->dev->name,
+ last_state,
port->sm_rx_state);
switch (port->sm_rx_state) {
case AD_RX_INITIALIZE:
@@ -1394,6 +1415,9 @@ static void ad_port_selection_logic(struct port *port, bool *update_slave_arr)
aggregator = __get_first_agg(port);
ad_agg_selection_logic(aggregator, update_slave_arr);
+
+ if (!port->aggregator->is_active)
+ port->actor_oper_port_state &= ~AD_STATE_SYNCHRONIZATION;
}
/* Decide if "agg" is a better choice for the new active aggregator that
@@ -2195,8 +2219,10 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave,
switch (lacpdu->subtype) {
case AD_TYPE_LACPDU:
ret = RX_HANDLER_CONSUMED;
- netdev_dbg(slave->bond->dev, "Received LACPDU on port %d\n",
- port->actor_port_number);
+ netdev_dbg(slave->bond->dev,
+ "Received LACPDU on port %d slave %s\n",
+ port->actor_port_number,
+ slave->dev->name);
/* Protect against concurrent state machines */
spin_lock(&slave->bond->mode_lock);
ad_rx_machine(lacpdu, port);
@@ -2288,7 +2314,10 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
port->actor_admin_port_key &= ~AD_DUPLEX_KEY_MASKS;
port->actor_oper_port_key = port->actor_admin_port_key |=
__get_duplex(port);
- netdev_dbg(slave->bond->dev, "Port %d changed duplex\n", port->actor_port_number);
+ netdev_dbg(slave->bond->dev, "Port %d slave %s changed duplex\n",
+ port->actor_port_number, slave->dev->name);
+ if (port->actor_oper_port_key & AD_DUPLEX_KEY_MASKS)
+ port->sm_vars |= AD_PORT_LACP_ENABLED;
/* there is no need to reselect a new aggregator, just signal the
* state machines to reinitialize
*/
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index f47bc433407a..e229a8657de8 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -334,7 +334,7 @@ static int bond_vlan_rx_kill_vid(struct net_device *bond_dev,
*
* Returns zero if carrier state does not change, nonzero if it does.
*/
-static int bond_set_carrier(struct bonding *bond)
+int bond_set_carrier(struct bonding *bond)
{
struct list_head *iter;
struct slave *slave;
@@ -3066,7 +3066,7 @@ static int bond_open(struct net_device *bond_dev)
slave != rcu_access_pointer(bond->curr_active_slave)) {
bond_set_slave_inactive_flags(slave,
BOND_SLAVE_NOTIFY_NOW);
- } else {
+ } else if (BOND_MODE(bond) != BOND_MODE_8023AD) {
bond_set_slave_active_flags(slave,
BOND_SLAVE_NOTIFY_NOW);
}
@@ -3734,7 +3734,7 @@ out:
* usable slave array is formed in the control path. The xmit function
* just calculates hash and sends the packet out.
*/
-int bond_3ad_xor_xmit(struct sk_buff *skb, struct net_device *dev)
+static int bond_3ad_xor_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct bonding *bond = netdev_priv(dev);
struct slave *slave;
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 9bd538d4474b..4df28943d222 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -1181,6 +1181,7 @@ static int bond_option_min_links_set(struct bonding *bond,
netdev_info(bond->dev, "Setting min links value to %llu\n",
newval->value);
bond->params.min_links = newval->value;
+ bond_set_carrier(bond);
return 0;
}
diff --git a/include/net/bond_3ad.h b/include/net/bond_3ad.h
index e01d903633ef..f04cdbb7848e 100644
--- a/include/net/bond_3ad.h
+++ b/include/net/bond_3ad.h
@@ -274,7 +274,6 @@ void bond_3ad_handle_link_change(struct slave *slave, char link);
int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info);
int __bond_3ad_get_active_agg_info(struct bonding *bond,
struct ad_info *ad_info);
-int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev);
int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
struct slave *slave);
int bond_3ad_set_carrier(struct bonding *bond);
diff --git a/include/net/bonding.h b/include/net/bonding.h
index 983a94b86b95..29f53eacac0a 100644
--- a/include/net/bonding.h
+++ b/include/net/bonding.h
@@ -525,6 +525,7 @@ void bond_sysfs_slave_del(struct slave *slave);
int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev);
int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb);
+int bond_set_carrier(struct bonding *bond);
void bond_select_active_slave(struct bonding *bond);
void bond_change_active_slave(struct bonding *bond, struct slave *new_active);
void bond_create_debugfs(void);