|
@@ -657,6 +657,20 @@ static void __set_agg_ports_ready(struct aggregator *aggregator, int val)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static int __agg_active_ports(struct aggregator *agg)
|
|
|
+{
|
|
|
+ struct port *port;
|
|
|
+ int active = 0;
|
|
|
+
|
|
|
+ for (port = agg->lag_ports; port;
|
|
|
+ port = port->next_port_in_aggregator) {
|
|
|
+ if (port->is_enabled)
|
|
|
+ active++;
|
|
|
+ }
|
|
|
+
|
|
|
+ return active;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* __get_agg_bandwidth - get the total bandwidth of an aggregator
|
|
|
* @aggregator: the aggregator we're looking at
|
|
@@ -664,39 +678,40 @@ static void __set_agg_ports_ready(struct aggregator *aggregator, int val)
|
|
|
*/
|
|
|
static u32 __get_agg_bandwidth(struct aggregator *aggregator)
|
|
|
{
|
|
|
+ int nports = __agg_active_ports(aggregator);
|
|
|
u32 bandwidth = 0;
|
|
|
|
|
|
- if (aggregator->num_of_ports) {
|
|
|
+ if (nports) {
|
|
|
switch (__get_link_speed(aggregator->lag_ports)) {
|
|
|
case AD_LINK_SPEED_1MBPS:
|
|
|
- bandwidth = aggregator->num_of_ports;
|
|
|
+ bandwidth = nports;
|
|
|
break;
|
|
|
case AD_LINK_SPEED_10MBPS:
|
|
|
- bandwidth = aggregator->num_of_ports * 10;
|
|
|
+ bandwidth = nports * 10;
|
|
|
break;
|
|
|
case AD_LINK_SPEED_100MBPS:
|
|
|
- bandwidth = aggregator->num_of_ports * 100;
|
|
|
+ bandwidth = nports * 100;
|
|
|
break;
|
|
|
case AD_LINK_SPEED_1000MBPS:
|
|
|
- bandwidth = aggregator->num_of_ports * 1000;
|
|
|
+ bandwidth = nports * 1000;
|
|
|
break;
|
|
|
case AD_LINK_SPEED_2500MBPS:
|
|
|
- bandwidth = aggregator->num_of_ports * 2500;
|
|
|
+ bandwidth = nports * 2500;
|
|
|
break;
|
|
|
case AD_LINK_SPEED_10000MBPS:
|
|
|
- bandwidth = aggregator->num_of_ports * 10000;
|
|
|
+ bandwidth = nports * 10000;
|
|
|
break;
|
|
|
case AD_LINK_SPEED_20000MBPS:
|
|
|
- bandwidth = aggregator->num_of_ports * 20000;
|
|
|
+ bandwidth = nports * 20000;
|
|
|
break;
|
|
|
case AD_LINK_SPEED_40000MBPS:
|
|
|
- bandwidth = aggregator->num_of_ports * 40000;
|
|
|
+ bandwidth = nports * 40000;
|
|
|
break;
|
|
|
case AD_LINK_SPEED_56000MBPS:
|
|
|
- bandwidth = aggregator->num_of_ports * 56000;
|
|
|
+ bandwidth = nports * 56000;
|
|
|
break;
|
|
|
case AD_LINK_SPEED_100000MBPS:
|
|
|
- bandwidth = aggregator->num_of_ports * 100000;
|
|
|
+ bandwidth = nports * 100000;
|
|
|
break;
|
|
|
default:
|
|
|
bandwidth = 0; /* to silence the compiler */
|
|
@@ -1530,10 +1545,10 @@ static struct aggregator *ad_agg_selection_test(struct aggregator *best,
|
|
|
|
|
|
switch (__get_agg_selection_mode(curr->lag_ports)) {
|
|
|
case BOND_AD_COUNT:
|
|
|
- if (curr->num_of_ports > best->num_of_ports)
|
|
|
+ if (__agg_active_ports(curr) > __agg_active_ports(best))
|
|
|
return curr;
|
|
|
|
|
|
- if (curr->num_of_ports < best->num_of_ports)
|
|
|
+ if (__agg_active_ports(curr) < __agg_active_ports(best))
|
|
|
return best;
|
|
|
|
|
|
/*FALLTHROUGH*/
|
|
@@ -1561,8 +1576,14 @@ static int agg_device_up(const struct aggregator *agg)
|
|
|
if (!port)
|
|
|
return 0;
|
|
|
|
|
|
- return netif_running(port->slave->dev) &&
|
|
|
- netif_carrier_ok(port->slave->dev);
|
|
|
+ for (port = agg->lag_ports; port;
|
|
|
+ port = port->next_port_in_aggregator) {
|
|
|
+ if (netif_running(port->slave->dev) &&
|
|
|
+ netif_carrier_ok(port->slave->dev))
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1610,7 +1631,7 @@ static void ad_agg_selection_logic(struct aggregator *agg,
|
|
|
|
|
|
agg->is_active = 0;
|
|
|
|
|
|
- if (agg->num_of_ports && agg_device_up(agg))
|
|
|
+ if (__agg_active_ports(agg) && agg_device_up(agg))
|
|
|
best = ad_agg_selection_test(best, agg);
|
|
|
}
|
|
|
|
|
@@ -1622,7 +1643,7 @@ static void ad_agg_selection_logic(struct aggregator *agg,
|
|
|
* answering partner.
|
|
|
*/
|
|
|
if (active && active->lag_ports &&
|
|
|
- active->lag_ports->is_enabled &&
|
|
|
+ __agg_active_ports(active) &&
|
|
|
(__agg_has_partner(active) ||
|
|
|
(!__agg_has_partner(active) &&
|
|
|
!__agg_has_partner(best)))) {
|
|
@@ -2133,7 +2154,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
|
|
|
else
|
|
|
temp_aggregator->lag_ports = temp_port->next_port_in_aggregator;
|
|
|
temp_aggregator->num_of_ports--;
|
|
|
- if (temp_aggregator->num_of_ports == 0) {
|
|
|
+ if (__agg_active_ports(temp_aggregator) == 0) {
|
|
|
select_new_active_agg = temp_aggregator->is_active;
|
|
|
ad_clear_agg(temp_aggregator);
|
|
|
if (select_new_active_agg) {
|
|
@@ -2432,7 +2453,9 @@ void bond_3ad_adapter_speed_duplex_changed(struct slave *slave)
|
|
|
*/
|
|
|
void bond_3ad_handle_link_change(struct slave *slave, char link)
|
|
|
{
|
|
|
+ struct aggregator *agg;
|
|
|
struct port *port;
|
|
|
+ bool dummy;
|
|
|
|
|
|
port = &(SLAVE_AD_INFO(slave)->port);
|
|
|
|
|
@@ -2459,6 +2482,9 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
|
|
|
port->is_enabled = false;
|
|
|
ad_update_actor_keys(port, true);
|
|
|
}
|
|
|
+ agg = __get_first_agg(port);
|
|
|
+ ad_agg_selection_logic(agg, &dummy);
|
|
|
+
|
|
|
netdev_dbg(slave->bond->dev, "Port %d changed link status to %s\n",
|
|
|
port->actor_port_number,
|
|
|
link == BOND_LINK_UP ? "UP" : "DOWN");
|
|
@@ -2499,7 +2525,7 @@ int bond_3ad_set_carrier(struct bonding *bond)
|
|
|
active = __get_active_agg(&(SLAVE_AD_INFO(first_slave)->aggregator));
|
|
|
if (active) {
|
|
|
/* are enough slaves available to consider link up? */
|
|
|
- if (active->num_of_ports < bond->params.min_links) {
|
|
|
+ if (__agg_active_ports(active) < bond->params.min_links) {
|
|
|
if (netif_carrier_ok(bond->dev)) {
|
|
|
netif_carrier_off(bond->dev);
|
|
|
goto out;
|