aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Vosburgh <fubar@us.ibm.com>2008-11-04 20:51:16 -0500
committerJeff Garzik <jgarzik@redhat.com>2008-11-06 00:49:47 -0500
commitfd989c83325cb34795bc4d4aa6b13c06f90eac99 (patch)
treeba6a0589847a45cd558cf2273dae423a4ab78dcc
parent6146b1a4da98377e4abddc91ba5856bef8f23f1e (diff)
bonding: alternate agg selection policies for 802.3ad
This patch implements alternative aggregator selection policies for 802.3ad. The existing policy, now termed "stable," selects the active aggregator by greatest bandwidth, and only reselects a new aggregator if the active aggregator is entirely disabled (no more ports or all ports down). This patch adds two new policies: bandwidth and count, selecting the active aggregator by total bandwidth (like the stable policy) or by the number of ports in the aggregator, respectively. These two policies also differ from the stable policy in that they will reselect the active aggregator when availability-related changes occur in the bond (e.g., link state change). This permits "gang failover" within 802.3ad, allowing redundant aggregators along parallel paths to always maintain the "best" aggregator as the active aggregator (rather than having to wait for the active to entirely fail). This patch also updates the driver version to 3.5.0. Signed-off-by: Jay Vosburgh <fubar@us.ibm.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--Documentation/networking/bonding.txt42
-rw-r--r--drivers/net/bonding/bond_3ad.c326
-rw-r--r--drivers/net/bonding/bond_3ad.h10
-rw-r--r--drivers/net/bonding/bond_main.c30
-rw-r--r--drivers/net/bonding/bond_sysfs.c49
-rw-r--r--drivers/net/bonding/bonding.h5
6 files changed, 333 insertions, 129 deletions
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index 3f4d0fae7081..5ede7473b425 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -194,6 +194,48 @@ or, for backwards compatibility, the option value. E.g.,
194 194
195 The parameters are as follows: 195 The parameters are as follows:
196 196
197ad_select
198
199 Specifies the 802.3ad aggregation selection logic to use. The
200 possible values and their effects are:
201
202 stable or 0
203
204 The active aggregator is chosen by largest aggregate
205 bandwidth.
206
207 Reselection of the active aggregator occurs only when all
208 slaves of the active aggregator are down or the active
209 aggregator has no slaves.
210
211 This is the default value.
212
213 bandwidth or 1
214
215 The active aggregator is chosen by largest aggregate
216 bandwidth. Reselection occurs if:
217
218 - A slave is added to or removed from the bond
219
220 - Any slave's link state changes
221
222 - Any slave's 802.3ad association state changes
223
224 - The bond's adminstrative state changes to up
225
226 count or 2
227
228 The active aggregator is chosen by the largest number of
229 ports (slaves). Reselection occurs as described under the
230 "bandwidth" setting, above.
231
232 The bandwidth and count selection policies permit failover of
233 802.3ad aggregations when partial failure of the active aggregator
234 occurs. This keeps the aggregator with the highest availability
235 (either in bandwidth or in number of ports) active at all times.
236
237 This option was added in bonding version 3.4.0.
238
197arp_interval 239arp_interval
198 240
199 Specifies the ARP link monitoring frequency in milliseconds. 241 Specifies the ARP link monitoring frequency in milliseconds.
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 6106660a4a44..ba1372f2f144 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -27,6 +27,7 @@
27#include <linux/netdevice.h> 27#include <linux/netdevice.h>
28#include <linux/spinlock.h> 28#include <linux/spinlock.h>
29#include <linux/ethtool.h> 29#include <linux/ethtool.h>
30#include <linux/etherdevice.h>
30#include <linux/if_bonding.h> 31#include <linux/if_bonding.h>
31#include <linux/pkt_sched.h> 32#include <linux/pkt_sched.h>
32#include <net/net_namespace.h> 33#include <net/net_namespace.h>
@@ -236,6 +237,17 @@ static inline struct aggregator *__get_next_agg(struct aggregator *aggregator)
236 return &(SLAVE_AD_INFO(slave->next).aggregator); 237 return &(SLAVE_AD_INFO(slave->next).aggregator);
237} 238}
238 239
240/*
241 * __agg_has_partner
242 *
243 * Return nonzero if aggregator has a partner (denoted by a non-zero ether
244 * address for the partner). Return 0 if not.
245 */
246static inline int __agg_has_partner(struct aggregator *agg)
247{
248 return !is_zero_ether_addr(agg->partner_system.mac_addr_value);
249}
250
239/** 251/**
240 * __disable_port - disable the port's slave 252 * __disable_port - disable the port's slave
241 * @port: the port we're looking at 253 * @port: the port we're looking at
@@ -274,14 +286,14 @@ static inline int __port_is_enabled(struct port *port)
274 * __get_agg_selection_mode - get the aggregator selection mode 286 * __get_agg_selection_mode - get the aggregator selection mode
275 * @port: the port we're looking at 287 * @port: the port we're looking at
276 * 288 *
277 * Get the aggregator selection mode. Can be %BANDWIDTH or %COUNT. 289 * Get the aggregator selection mode. Can be %STABLE, %BANDWIDTH or %COUNT.
278 */ 290 */
279static inline u32 __get_agg_selection_mode(struct port *port) 291static inline u32 __get_agg_selection_mode(struct port *port)
280{ 292{
281 struct bonding *bond = __get_bond_by_port(port); 293 struct bonding *bond = __get_bond_by_port(port);
282 294
283 if (bond == NULL) { 295 if (bond == NULL) {
284 return AD_BANDWIDTH; 296 return BOND_AD_STABLE;
285 } 297 }
286 298
287 return BOND_AD_INFO(bond).agg_select_mode; 299 return BOND_AD_INFO(bond).agg_select_mode;
@@ -1414,9 +1426,82 @@ static void ad_port_selection_logic(struct port *port)
1414 // else set ready=FALSE in all aggregator's ports 1426 // else set ready=FALSE in all aggregator's ports
1415 __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator)); 1427 __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
1416 1428
1417 if (!__check_agg_selection_timer(port) && (aggregator = __get_first_agg(port))) { 1429 aggregator = __get_first_agg(port);
1418 ad_agg_selection_logic(aggregator); 1430 ad_agg_selection_logic(aggregator);
1431}
1432
1433/*
1434 * Decide if "agg" is a better choice for the new active aggregator that
1435 * the current best, according to the ad_select policy.
1436 */
1437static struct aggregator *ad_agg_selection_test(struct aggregator *best,
1438 struct aggregator *curr)
1439{
1440 /*
1441 * 0. If no best, select current.
1442 *
1443 * 1. If the current agg is not individual, and the best is
1444 * individual, select current.
1445 *
1446 * 2. If current agg is individual and the best is not, keep best.
1447 *
1448 * 3. Therefore, current and best are both individual or both not
1449 * individual, so:
1450 *
1451 * 3a. If current agg partner replied, and best agg partner did not,
1452 * select current.
1453 *
1454 * 3b. If current agg partner did not reply and best agg partner
1455 * did reply, keep best.
1456 *
1457 * 4. Therefore, current and best both have partner replies or
1458 * both do not, so perform selection policy:
1459 *
1460 * BOND_AD_COUNT: Select by count of ports. If count is equal,
1461 * select by bandwidth.
1462 *
1463 * BOND_AD_STABLE, BOND_AD_BANDWIDTH: Select by bandwidth.
1464 */
1465 if (!best)
1466 return curr;
1467
1468 if (!curr->is_individual && best->is_individual)
1469 return curr;
1470
1471 if (curr->is_individual && !best->is_individual)
1472 return best;
1473
1474 if (__agg_has_partner(curr) && !__agg_has_partner(best))
1475 return curr;
1476
1477 if (!__agg_has_partner(curr) && __agg_has_partner(best))
1478 return best;
1479
1480 switch (__get_agg_selection_mode(curr->lag_ports)) {
1481 case BOND_AD_COUNT:
1482 if (curr->num_of_ports > best->num_of_ports)
1483 return curr;
1484
1485 if (curr->num_of_ports < best->num_of_ports)
1486 return best;
1487
1488 /*FALLTHROUGH*/
1489 case BOND_AD_STABLE:
1490 case BOND_AD_BANDWIDTH:
1491 if (__get_agg_bandwidth(curr) > __get_agg_bandwidth(best))
1492 return curr;
1493
1494 break;
1495
1496 default:
1497 printk(KERN_WARNING DRV_NAME
1498 ": %s: Impossible agg select mode %d\n",
1499 curr->slave->dev->master->name,
1500 __get_agg_selection_mode(curr->lag_ports));
1501 break;
1419 } 1502 }
1503
1504 return best;
1420} 1505}
1421 1506
1422/** 1507/**
@@ -1424,156 +1509,138 @@ static void ad_port_selection_logic(struct port *port)
1424 * @aggregator: the aggregator we're looking at 1509 * @aggregator: the aggregator we're looking at
1425 * 1510 *
1426 * It is assumed that only one aggregator may be selected for a team. 1511 * It is assumed that only one aggregator may be selected for a team.
1427 * The logic of this function is to select (at first time) the aggregator with 1512 *
1428 * the most ports attached to it, and to reselect the active aggregator only if 1513 * The logic of this function is to select the aggregator according to
1429 * the previous aggregator has no more ports related to it. 1514 * the ad_select policy:
1515 *
1516 * BOND_AD_STABLE: select the aggregator with the most ports attached to
1517 * it, and to reselect the active aggregator only if the previous
1518 * aggregator has no more ports related to it.
1519 *
1520 * BOND_AD_BANDWIDTH: select the aggregator with the highest total
1521 * bandwidth, and reselect whenever a link state change takes place or the
1522 * set of slaves in the bond changes.
1523 *
1524 * BOND_AD_COUNT: select the aggregator with largest number of ports
1525 * (slaves), and reselect whenever a link state change takes place or the
1526 * set of slaves in the bond changes.
1430 * 1527 *
1431 * FIXME: this function MUST be called with the first agg in the bond, or 1528 * FIXME: this function MUST be called with the first agg in the bond, or
1432 * __get_active_agg() won't work correctly. This function should be better 1529 * __get_active_agg() won't work correctly. This function should be better
1433 * called with the bond itself, and retrieve the first agg from it. 1530 * called with the bond itself, and retrieve the first agg from it.
1434 */ 1531 */
1435static void ad_agg_selection_logic(struct aggregator *aggregator) 1532static void ad_agg_selection_logic(struct aggregator *agg)
1436{ 1533{
1437 struct aggregator *best_aggregator = NULL, *active_aggregator = NULL; 1534 struct aggregator *best, *active, *origin;
1438 struct aggregator *last_active_aggregator = NULL, *origin_aggregator;
1439 struct port *port; 1535 struct port *port;
1440 u16 num_of_aggs=0;
1441 1536
1442 origin_aggregator = aggregator; 1537 origin = agg;
1443 1538
1444 //get current active aggregator 1539 active = __get_active_agg(agg);
1445 last_active_aggregator = __get_active_agg(aggregator); 1540 best = active;
1446 1541
1447 // search for the aggregator with the most ports attached to it.
1448 do { 1542 do {
1449 // count how many candidate lag's we have 1543 agg->is_active = 0;
1450 if (aggregator->lag_ports) { 1544
1451 num_of_aggs++; 1545 if (agg->num_of_ports)
1452 } 1546 best = ad_agg_selection_test(best, agg);
1453 if (aggregator->is_active && !aggregator->is_individual && // if current aggregator is the active aggregator 1547
1454 MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(null_mac_addr))) { // and partner answers to 802.3ad PDUs 1548 } while ((agg = __get_next_agg(agg)));
1455 if (aggregator->num_of_ports) { // if any ports attached to the current aggregator 1549
1456 best_aggregator=NULL; // disregard the best aggregator that was chosen by now 1550 if (best &&
1457 break; // stop the selection of other aggregator if there are any ports attached to this active aggregator 1551 __get_agg_selection_mode(best->lag_ports) == BOND_AD_STABLE) {
1458 } else { // no ports attached to this active aggregator 1552 /*
1459 aggregator->is_active = 0; // mark this aggregator as not active anymore 1553 * For the STABLE policy, don't replace the old active
1554 * aggregator if it's still active (it has an answering
1555 * partner) or if both the best and active don't have an
1556 * answering partner.
1557 */
1558 if (active && active->lag_ports &&
1559 active->lag_ports->is_enabled &&
1560 (__agg_has_partner(active) ||
1561 (!__agg_has_partner(active) && !__agg_has_partner(best)))) {
1562 if (!(!active->actor_oper_aggregator_key &&
1563 best->actor_oper_aggregator_key)) {
1564 best = NULL;
1565 active->is_active = 1;
1460 } 1566 }
1461 } 1567 }
1462 if (aggregator->num_of_ports) { // if any ports attached 1568 }
1463 if (best_aggregator) { // if there is a candidte aggregator
1464 //The reasons for choosing new best aggregator:
1465 // 1. if current agg is NOT individual and the best agg chosen so far is individual OR
1466 // current and best aggs are both individual or both not individual, AND
1467 // 2a. current agg partner reply but best agg partner do not reply OR
1468 // 2b. current agg partner reply OR current agg partner do not reply AND best agg partner also do not reply AND
1469 // current has more ports/bandwidth, or same amount of ports but current has faster ports, THEN
1470 // current agg become best agg so far
1471
1472 //if current agg is NOT individual and the best agg chosen so far is individual change best_aggregator
1473 if (!aggregator->is_individual && best_aggregator->is_individual) {
1474 best_aggregator=aggregator;
1475 }
1476 // current and best aggs are both individual or both not individual
1477 else if ((aggregator->is_individual && best_aggregator->is_individual) ||
1478 (!aggregator->is_individual && !best_aggregator->is_individual)) {
1479 // current and best aggs are both individual or both not individual AND
1480 // current agg partner reply but best agg partner do not reply
1481 if ((MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(null_mac_addr)) &&
1482 !MAC_ADDRESS_COMPARE(&(best_aggregator->partner_system), &(null_mac_addr)))) {
1483 best_aggregator=aggregator;
1484 }
1485 // current agg partner reply OR current agg partner do not reply AND best agg partner also do not reply
1486 else if (! (!MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(null_mac_addr)) &&
1487 MAC_ADDRESS_COMPARE(&(best_aggregator->partner_system), &(null_mac_addr)))) {
1488 if ((__get_agg_selection_mode(aggregator->lag_ports) == AD_BANDWIDTH)&&
1489 (__get_agg_bandwidth(aggregator) > __get_agg_bandwidth(best_aggregator))) {
1490 best_aggregator=aggregator;
1491 } else if (__get_agg_selection_mode(aggregator->lag_ports) == AD_COUNT) {
1492 if (((aggregator->num_of_ports > best_aggregator->num_of_ports) &&
1493 (aggregator->actor_oper_aggregator_key & AD_SPEED_KEY_BITS))||
1494 ((aggregator->num_of_ports == best_aggregator->num_of_ports) &&
1495 ((u16)(aggregator->actor_oper_aggregator_key & AD_SPEED_KEY_BITS) >
1496 (u16)(best_aggregator->actor_oper_aggregator_key & AD_SPEED_KEY_BITS)))) {
1497 best_aggregator=aggregator;
1498 }
1499 }
1500 }
1501 }
1502 } else {
1503 best_aggregator=aggregator;
1504 }
1505 }
1506 aggregator->is_active = 0; // mark all aggregators as not active anymore
1507 } while ((aggregator = __get_next_agg(aggregator)));
1508
1509 // if we have new aggregator selected, don't replace the old aggregator if it has an answering partner,
1510 // or if both old aggregator and new aggregator don't have answering partner
1511 if (best_aggregator) {
1512 if (last_active_aggregator && last_active_aggregator->lag_ports && last_active_aggregator->lag_ports->is_enabled &&
1513 (MAC_ADDRESS_COMPARE(&(last_active_aggregator->partner_system), &(null_mac_addr)) || // partner answers OR
1514 (!MAC_ADDRESS_COMPARE(&(last_active_aggregator->partner_system), &(null_mac_addr)) && // both old and new
1515 !MAC_ADDRESS_COMPARE(&(best_aggregator->partner_system), &(null_mac_addr)))) // partner do not answer
1516 ) {
1517 // if new aggregator has link, and old aggregator does not, replace old aggregator.(do nothing)
1518 // -> don't replace otherwise.
1519 if (!(!last_active_aggregator->actor_oper_aggregator_key && best_aggregator->actor_oper_aggregator_key)) {
1520 best_aggregator=NULL;
1521 last_active_aggregator->is_active = 1; // don't replace good old aggregator
1522 1569
1523 } 1570 if (best && (best == active)) {
1524 } 1571 best = NULL;
1572 active->is_active = 1;
1525 } 1573 }
1526 1574
1527 // if there is new best aggregator, activate it 1575 // if there is new best aggregator, activate it
1528 if (best_aggregator) { 1576 if (best) {
1529 for (aggregator = __get_first_agg(best_aggregator->lag_ports); 1577 dprintk("best Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
1530 aggregator; 1578 best->aggregator_identifier, best->num_of_ports,
1531 aggregator = __get_next_agg(aggregator)) { 1579 best->actor_oper_aggregator_key,
1532 1580 best->partner_oper_aggregator_key,
1533 dprintk("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d\n", 1581 best->is_individual, best->is_active);
1534 aggregator->aggregator_identifier, aggregator->num_of_ports, 1582 dprintk("best ports %p slave %p %s\n",
1535 aggregator->actor_oper_aggregator_key, aggregator->partner_oper_aggregator_key, 1583 best->lag_ports, best->slave,
1536 aggregator->is_individual, aggregator->is_active); 1584 best->slave ? best->slave->dev->name : "NULL");
1585
1586 for (agg = __get_first_agg(best->lag_ports); agg;
1587 agg = __get_next_agg(agg)) {
1588
1589 dprintk("Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
1590 agg->aggregator_identifier, agg->num_of_ports,
1591 agg->actor_oper_aggregator_key,
1592 agg->partner_oper_aggregator_key,
1593 agg->is_individual, agg->is_active);
1537 } 1594 }
1538 1595
1539 // check if any partner replys 1596 // check if any partner replys
1540 if (best_aggregator->is_individual) { 1597 if (best->is_individual) {
1541 printk(KERN_WARNING DRV_NAME ": %s: Warning: No 802.3ad response from " 1598 printk(KERN_WARNING DRV_NAME ": %s: Warning: No 802.3ad"
1542 "the link partner for any adapters in the bond\n", 1599 " response from the link partner for any"
1543 best_aggregator->slave->dev->master->name); 1600 " adapters in the bond\n",
1544 } 1601 best->slave->dev->master->name);
1545
1546 // check if there are more than one aggregator
1547 if (num_of_aggs > 1) {
1548 dprintk("Warning: More than one Link Aggregation Group was "
1549 "found in the bond. Only one group will function in the bond\n");
1550 } 1602 }
1551 1603
1552 best_aggregator->is_active = 1; 1604 best->is_active = 1;
1553 dprintk("LAG %d choosed as the active LAG\n", best_aggregator->aggregator_identifier); 1605 dprintk("LAG %d chosen as the active LAG\n",
1554 dprintk("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d\n", 1606 best->aggregator_identifier);
1555 best_aggregator->aggregator_identifier, best_aggregator->num_of_ports, 1607 dprintk("Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
1556 best_aggregator->actor_oper_aggregator_key, best_aggregator->partner_oper_aggregator_key, 1608 best->aggregator_identifier, best->num_of_ports,
1557 best_aggregator->is_individual, best_aggregator->is_active); 1609 best->actor_oper_aggregator_key,
1610 best->partner_oper_aggregator_key,
1611 best->is_individual, best->is_active);
1558 1612
1559 // disable the ports that were related to the former active_aggregator 1613 // disable the ports that were related to the former active_aggregator
1560 if (last_active_aggregator) { 1614 if (active) {
1561 for (port=last_active_aggregator->lag_ports; port; port=port->next_port_in_aggregator) { 1615 for (port = active->lag_ports; port;
1616 port = port->next_port_in_aggregator) {
1562 __disable_port(port); 1617 __disable_port(port);
1563 } 1618 }
1564 } 1619 }
1565 } 1620 }
1566 1621
1567 // if the selected aggregator is of join individuals(partner_system is NULL), enable their ports 1622 /*
1568 active_aggregator = __get_active_agg(origin_aggregator); 1623 * if the selected aggregator is of join individuals
1624 * (partner_system is NULL), enable their ports
1625 */
1626 active = __get_active_agg(origin);
1569 1627
1570 if (active_aggregator) { 1628 if (active) {
1571 if (!MAC_ADDRESS_COMPARE(&(active_aggregator->partner_system), &(null_mac_addr))) { 1629 if (!__agg_has_partner(active)) {
1572 for (port=active_aggregator->lag_ports; port; port=port->next_port_in_aggregator) { 1630 for (port = active->lag_ports; port;
1631 port = port->next_port_in_aggregator) {
1573 __enable_port(port); 1632 __enable_port(port);
1574 } 1633 }
1575 } 1634 }
1576 } 1635 }
1636
1637 if (origin->slave) {
1638 struct bonding *bond;
1639
1640 bond = bond_get_bond_by_slave(origin->slave);
1641 if (bond)
1642 bond_3ad_set_carrier(bond);
1643 }
1577} 1644}
1578 1645
1579/** 1646/**
@@ -1830,6 +1897,19 @@ static void ad_initialize_lacpdu(struct lacpdu *lacpdu)
1830// Check aggregators status in team every T seconds 1897// Check aggregators status in team every T seconds
1831#define AD_AGGREGATOR_SELECTION_TIMER 8 1898#define AD_AGGREGATOR_SELECTION_TIMER 8
1832 1899
1900/*
1901 * bond_3ad_initiate_agg_selection(struct bonding *bond)
1902 *
1903 * Set the aggregation selection timer, to initiate an agg selection in
1904 * the very near future. Called during first initialization, and during
1905 * any down to up transitions of the bond.
1906 */
1907void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout)
1908{
1909 BOND_AD_INFO(bond).agg_select_timer = timeout;
1910 BOND_AD_INFO(bond).agg_select_mode = bond->params.ad_select;
1911}
1912
1833static u16 aggregator_identifier; 1913static u16 aggregator_identifier;
1834 1914
1835/** 1915/**
@@ -1854,9 +1934,9 @@ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fas
1854 // initialize how many times this module is called in one second(should be about every 100ms) 1934 // initialize how many times this module is called in one second(should be about every 100ms)
1855 ad_ticks_per_sec = tick_resolution; 1935 ad_ticks_per_sec = tick_resolution;
1856 1936
1857 // initialize the aggregator selection timer(to activate an aggregation selection after initialize) 1937 bond_3ad_initiate_agg_selection(bond,
1858 BOND_AD_INFO(bond).agg_select_timer = (AD_AGGREGATOR_SELECTION_TIMER * ad_ticks_per_sec); 1938 AD_AGGREGATOR_SELECTION_TIMER *
1859 BOND_AD_INFO(bond).agg_select_mode = AD_BANDWIDTH; 1939 ad_ticks_per_sec);
1860 } 1940 }
1861} 1941}
1862 1942
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index b5ee45f6d55a..a803fe05f63e 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -42,10 +42,11 @@ typedef struct mac_addr {
42 u8 mac_addr_value[ETH_ALEN]; 42 u8 mac_addr_value[ETH_ALEN];
43} mac_addr_t; 43} mac_addr_t;
44 44
45typedef enum { 45enum {
46 AD_BANDWIDTH = 0, 46 BOND_AD_STABLE = 0,
47 AD_COUNT 47 BOND_AD_BANDWIDTH = 1,
48} agg_selection_t; 48 BOND_AD_COUNT = 2,
49};
49 50
50// rx machine states(43.4.11 in the 802.3ad standard) 51// rx machine states(43.4.11 in the 802.3ad standard)
51typedef enum { 52typedef enum {
@@ -277,6 +278,7 @@ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fas
277int bond_3ad_bind_slave(struct slave *slave); 278int bond_3ad_bind_slave(struct slave *slave);
278void bond_3ad_unbind_slave(struct slave *slave); 279void bond_3ad_unbind_slave(struct slave *slave);
279void bond_3ad_state_machine_handler(struct work_struct *); 280void bond_3ad_state_machine_handler(struct work_struct *);
281void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout);
280void bond_3ad_adapter_speed_changed(struct slave *slave); 282void bond_3ad_adapter_speed_changed(struct slave *slave);
281void bond_3ad_adapter_duplex_changed(struct slave *slave); 283void bond_3ad_adapter_duplex_changed(struct slave *slave);
282void bond_3ad_handle_link_change(struct slave *slave, char link); 284void bond_3ad_handle_link_change(struct slave *slave, char link);
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 798d98ce2d97..02de3e031237 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -97,6 +97,7 @@ static int use_carrier = 1;
97static char *mode = NULL; 97static char *mode = NULL;
98static char *primary = NULL; 98static char *primary = NULL;
99static char *lacp_rate = NULL; 99static char *lacp_rate = NULL;
100static char *ad_select = NULL;
100static char *xmit_hash_policy = NULL; 101static char *xmit_hash_policy = NULL;
101static int arp_interval = BOND_LINK_ARP_INTERV; 102static int arp_interval = BOND_LINK_ARP_INTERV;
102static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, }; 103static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
@@ -130,6 +131,8 @@ MODULE_PARM_DESC(primary, "Primary network device to use");
130module_param(lacp_rate, charp, 0); 131module_param(lacp_rate, charp, 0);
131MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner " 132MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner "
132 "(slow/fast)"); 133 "(slow/fast)");
134module_param(ad_select, charp, 0);
135MODULE_PARM_DESC(ad_select, "803.ad aggregation selection logic: stable (0, default), bandwidth (1), count (2)");
133module_param(xmit_hash_policy, charp, 0); 136module_param(xmit_hash_policy, charp, 0);
134MODULE_PARM_DESC(xmit_hash_policy, "XOR hashing method: 0 for layer 2 (default)" 137MODULE_PARM_DESC(xmit_hash_policy, "XOR hashing method: 0 for layer 2 (default)"
135 ", 1 for layer 3+4"); 138 ", 1 for layer 3+4");
@@ -200,6 +203,13 @@ struct bond_parm_tbl fail_over_mac_tbl[] = {
200{ NULL, -1}, 203{ NULL, -1},
201}; 204};
202 205
206struct bond_parm_tbl ad_select_tbl[] = {
207{ "stable", BOND_AD_STABLE},
208{ "bandwidth", BOND_AD_BANDWIDTH},
209{ "count", BOND_AD_COUNT},
210{ NULL, -1},
211};
212
203/*-------------------------- Forward declarations ---------------------------*/ 213/*-------------------------- Forward declarations ---------------------------*/
204 214
205static void bond_send_gratuitous_arp(struct bonding *bond); 215static void bond_send_gratuitous_arp(struct bonding *bond);
@@ -3318,6 +3328,8 @@ static void bond_info_show_master(struct seq_file *seq)
3318 seq_puts(seq, "\n802.3ad info\n"); 3328 seq_puts(seq, "\n802.3ad info\n");
3319 seq_printf(seq, "LACP rate: %s\n", 3329 seq_printf(seq, "LACP rate: %s\n",
3320 (bond->params.lacp_fast) ? "fast" : "slow"); 3330 (bond->params.lacp_fast) ? "fast" : "slow");
3331 seq_printf(seq, "Aggregator selection policy (ad_select): %s\n",
3332 ad_select_tbl[bond->params.ad_select].modename);
3321 3333
3322 if (bond_3ad_get_active_agg_info(bond, &ad_info)) { 3334 if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
3323 seq_printf(seq, "bond %s has no active aggregator\n", 3335 seq_printf(seq, "bond %s has no active aggregator\n",
@@ -3824,6 +3836,7 @@ static int bond_open(struct net_device *bond_dev)
3824 queue_delayed_work(bond->wq, &bond->ad_work, 0); 3836 queue_delayed_work(bond->wq, &bond->ad_work, 0);
3825 /* register to receive LACPDUs */ 3837 /* register to receive LACPDUs */
3826 bond_register_lacpdu(bond); 3838 bond_register_lacpdu(bond);
3839 bond_3ad_initiate_agg_selection(bond, 1);
3827 } 3840 }
3828 3841
3829 return 0; 3842 return 0;
@@ -4763,6 +4776,23 @@ static int bond_check_params(struct bond_params *params)
4763 } 4776 }
4764 } 4777 }
4765 4778
4779 if (ad_select) {
4780 params->ad_select = bond_parse_parm(ad_select, ad_select_tbl);
4781 if (params->ad_select == -1) {
4782 printk(KERN_ERR DRV_NAME
4783 ": Error: Invalid ad_select \"%s\"\n",
4784 ad_select == NULL ? "NULL" : ad_select);
4785 return -EINVAL;
4786 }
4787
4788 if (bond_mode != BOND_MODE_8023AD) {
4789 printk(KERN_WARNING DRV_NAME
4790 ": ad_select param only affects 802.3ad mode\n");
4791 }
4792 } else {
4793 params->ad_select = BOND_AD_STABLE;
4794 }
4795
4766 if (max_bonds < 0 || max_bonds > INT_MAX) { 4796 if (max_bonds < 0 || max_bonds > INT_MAX) {
4767 printk(KERN_WARNING DRV_NAME 4797 printk(KERN_WARNING DRV_NAME
4768 ": Warning: max_bonds (%d) not in range %d-%d, so it " 4798 ": Warning: max_bonds (%d) not in range %d-%d, so it "
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 8788e3e33852..aaf2927b5c38 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -48,6 +48,7 @@ extern struct list_head bond_dev_list;
48extern struct bond_params bonding_defaults; 48extern struct bond_params bonding_defaults;
49extern struct bond_parm_tbl bond_mode_tbl[]; 49extern struct bond_parm_tbl bond_mode_tbl[];
50extern struct bond_parm_tbl bond_lacp_tbl[]; 50extern struct bond_parm_tbl bond_lacp_tbl[];
51extern struct bond_parm_tbl ad_select_tbl[];
51extern struct bond_parm_tbl xmit_hashtype_tbl[]; 52extern struct bond_parm_tbl xmit_hashtype_tbl[];
52extern struct bond_parm_tbl arp_validate_tbl[]; 53extern struct bond_parm_tbl arp_validate_tbl[];
53extern struct bond_parm_tbl fail_over_mac_tbl[]; 54extern struct bond_parm_tbl fail_over_mac_tbl[];
@@ -944,6 +945,53 @@ out:
944} 945}
945static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_store_lacp); 946static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_store_lacp);
946 947
948static ssize_t bonding_show_ad_select(struct device *d,
949 struct device_attribute *attr,
950 char *buf)
951{
952 struct bonding *bond = to_bond(d);
953
954 return sprintf(buf, "%s %d\n",
955 ad_select_tbl[bond->params.ad_select].modename,
956 bond->params.ad_select);
957}
958
959
960static ssize_t bonding_store_ad_select(struct device *d,
961 struct device_attribute *attr,
962 const char *buf, size_t count)
963{
964 int new_value, ret = count;
965 struct bonding *bond = to_bond(d);
966
967 if (bond->dev->flags & IFF_UP) {
968 printk(KERN_ERR DRV_NAME
969 ": %s: Unable to update ad_select because interface "
970 "is up.\n", bond->dev->name);
971 ret = -EPERM;
972 goto out;
973 }
974
975 new_value = bond_parse_parm(buf, ad_select_tbl);
976
977 if (new_value != -1) {
978 bond->params.ad_select = new_value;
979 printk(KERN_INFO DRV_NAME
980 ": %s: Setting ad_select to %s (%d).\n",
981 bond->dev->name, ad_select_tbl[new_value].modename,
982 new_value);
983 } else {
984 printk(KERN_ERR DRV_NAME
985 ": %s: Ignoring invalid ad_select value %.*s.\n",
986 bond->dev->name, (int)strlen(buf) - 1, buf);
987 ret = -EINVAL;
988 }
989out:
990 return ret;
991}
992
993static DEVICE_ATTR(ad_select, S_IRUGO | S_IWUSR, bonding_show_ad_select, bonding_store_ad_select);
994
947/* 995/*
948 * Show and set the number of grat ARP to send after a failover event. 996 * Show and set the number of grat ARP to send after a failover event.
949 */ 997 */
@@ -1459,6 +1507,7 @@ static struct attribute *per_bond_attrs[] = {
1459 &dev_attr_downdelay.attr, 1507 &dev_attr_downdelay.attr,
1460 &dev_attr_updelay.attr, 1508 &dev_attr_updelay.attr,
1461 &dev_attr_lacp_rate.attr, 1509 &dev_attr_lacp_rate.attr,
1510 &dev_attr_ad_select.attr,
1462 &dev_attr_xmit_hash_policy.attr, 1511 &dev_attr_xmit_hash_policy.attr,
1463 &dev_attr_num_grat_arp.attr, 1512 &dev_attr_num_grat_arp.attr,
1464 &dev_attr_num_unsol_na.attr, 1513 &dev_attr_num_unsol_na.attr,
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 0491c7c2645b..b5eb8e65b309 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -23,8 +23,8 @@
23#include "bond_3ad.h" 23#include "bond_3ad.h"
24#include "bond_alb.h" 24#include "bond_alb.h"
25 25
26#define DRV_VERSION "3.4.0" 26#define DRV_VERSION "3.5.0"
27#define DRV_RELDATE "October 7, 2008" 27#define DRV_RELDATE "November 4, 2008"
28#define DRV_NAME "bonding" 28#define DRV_NAME "bonding"
29#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" 29#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
30 30
@@ -137,6 +137,7 @@ struct bond_params {
137 int updelay; 137 int updelay;
138 int downdelay; 138 int downdelay;
139 int lacp_fast; 139 int lacp_fast;
140 int ad_select;
140 char primary[IFNAMSIZ]; 141 char primary[IFNAMSIZ];
141 __be32 arp_targets[BOND_MAX_ARP_TARGETS]; 142 __be32 arp_targets[BOND_MAX_ARP_TARGETS];
142}; 143};