Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] bonding: support carrier state for master

Add support for the bonding master to specify its carrier state
based upon the state of the slaves. For 802.3ad, the bond is up if
there is an active, parterned aggregator. For other modes, the bond is
up if any slaves are up. Updates driver version to 3.0.3.

Based on a patch by jamal <hadi@cyberus.ca>.

Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>

authored by

Jay Vosburgh and committed by
Jeff Garzik
ff59c456 e21a2b0c

+102 -28
+28
drivers/net/bonding/bond_3ad.c
··· 2294 2294 port->sm_vars |= AD_PORT_BEGIN; 2295 2295 } 2296 2296 2297 + /* 2298 + * set link state for bonding master: if we have an active partnered 2299 + * aggregator, we're up, if not, we're down. Presumes that we cannot 2300 + * have an active aggregator if there are no slaves with link up. 2301 + * 2302 + * Called by bond_set_carrier(). Return zero if carrier state does not 2303 + * change, nonzero if it does. 2304 + */ 2305 + int bond_3ad_set_carrier(struct bonding *bond) 2306 + { 2307 + struct aggregator *agg; 2308 + 2309 + agg = __get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator)); 2310 + if (agg && MAC_ADDRESS_COMPARE(&agg->partner_system, &null_mac_addr)) { 2311 + if (!netif_carrier_ok(bond->dev)) { 2312 + netif_carrier_on(bond->dev); 2313 + return 1; 2314 + } 2315 + return 0; 2316 + } 2317 + 2318 + if (netif_carrier_ok(bond->dev)) { 2319 + netif_carrier_off(bond->dev); 2320 + return 1; 2321 + } 2322 + return 0; 2323 + } 2324 + 2297 2325 /** 2298 2326 * bond_3ad_get_active_agg_info - get information of the active aggregator 2299 2327 * @bond: bonding struct to work on
+1
drivers/net/bonding/bond_3ad.h
··· 283 283 int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info); 284 284 int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev); 285 285 int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype, struct net_device *orig_dev); 286 + int bond_3ad_set_carrier(struct bonding *bond); 286 287 #endif //__BOND_3AD_H__ 287 288
+71 -26
drivers/net/bonding/bond_main.c
··· 559 559 /*------------------------------- Link status -------------------------------*/ 560 560 561 561 /* 562 + * Set the carrier state for the master according to the state of its 563 + * slaves. If any slaves are up, the master is up. In 802.3ad mode, 564 + * do special 802.3ad magic. 565 + * 566 + * Returns zero if carrier state does not change, nonzero if it does. 567 + */ 568 + static int bond_set_carrier(struct bonding *bond) 569 + { 570 + struct slave *slave; 571 + int i; 572 + 573 + if (bond->slave_cnt == 0) 574 + goto down; 575 + 576 + if (bond->params.mode == BOND_MODE_8023AD) 577 + return bond_3ad_set_carrier(bond); 578 + 579 + bond_for_each_slave(bond, slave, i) { 580 + if (slave->link == BOND_LINK_UP) { 581 + if (!netif_carrier_ok(bond->dev)) { 582 + netif_carrier_on(bond->dev); 583 + return 1; 584 + } 585 + return 0; 586 + } 587 + } 588 + 589 + down: 590 + if (netif_carrier_ok(bond->dev)) { 591 + netif_carrier_off(bond->dev); 592 + return 1; 593 + } 594 + return 0; 595 + } 596 + 597 + /* 562 598 * Get link speed and duplex from the slave's base driver 563 599 * using ethtool. If for some reason the call fails or the 564 600 * values are invalid, fake speed and duplex to 100/Full ··· 1110 1074 void bond_select_active_slave(struct bonding *bond) 1111 1075 { 1112 1076 struct slave *best_slave; 1077 + int rv; 1113 1078 1114 1079 best_slave = bond_find_best_slave(bond); 1115 1080 if (best_slave != bond->curr_active_slave) { 1116 1081 bond_change_active_slave(bond, best_slave); 1082 + rv = bond_set_carrier(bond); 1083 + if (!rv) 1084 + return; 1085 + 1086 + if (netif_carrier_ok(bond->dev)) { 1087 + printk(KERN_INFO DRV_NAME 1088 + ": %s: first active interface up!\n", 1089 + bond->dev->name); 1090 + } else { 1091 + printk(KERN_INFO DRV_NAME ": %s: " 1092 + "now running without any active interface !\n", 1093 + bond->dev->name); 1094 + } 1117 1095 } 1118 1096 } 1119 1097 ··· 1508 1458 if (((!bond->curr_active_slave) || 1509 1459 (bond->curr_active_slave->dev->priv_flags & IFF_SLAVE_INACTIVE)) && 1510 1460 (new_slave->link != BOND_LINK_DOWN)) { 1511 - dprintk("This is the first active slave\n"); 1512 1461 /* first slave or no active slave yet, and this link 1513 1462 is OK, so make this interface the active one */ 1514 1463 bond_change_active_slave(bond, new_slave); 1464 + printk(KERN_INFO DRV_NAME 1465 + ": %s: first active interface up!\n", 1466 + bond->dev->name); 1467 + netif_carrier_on(bond->dev); 1468 + 1515 1469 } else { 1516 1470 dprintk("This is just a backup slave\n"); 1517 1471 bond_set_slave_inactive_flags(new_slave); ··· 1570 1516 } 1571 1517 break; 1572 1518 } /* switch(bond_mode) */ 1519 + 1520 + bond_set_carrier(bond); 1573 1521 1574 1522 write_unlock_bh(&bond->lock); 1575 1523 ··· 1712 1656 bond_alb_deinit_slave(bond, slave); 1713 1657 } 1714 1658 1715 - if (oldcurrent == slave) { 1659 + if (oldcurrent == slave) 1716 1660 bond_select_active_slave(bond); 1717 1661 1718 - if (!bond->curr_active_slave) { 1719 - printk(KERN_INFO DRV_NAME 1720 - ": %s: now running without any active " 1721 - "interface !\n", 1722 - bond_dev->name); 1723 - } 1724 - } 1725 - 1726 1662 if (bond->slave_cnt == 0) { 1663 + bond_set_carrier(bond); 1664 + 1727 1665 /* if the last slave was removed, zero the mac address 1728 1666 * of the master so it will be set by the application 1729 1667 * to the mac address of the first slave ··· 1800 1750 struct sockaddr addr; 1801 1751 1802 1752 write_lock_bh(&bond->lock); 1753 + 1754 + netif_carrier_off(bond_dev); 1803 1755 1804 1756 if (bond->slave_cnt == 0) { 1805 1757 goto out; ··· 2239 2187 2240 2188 bond_select_active_slave(bond); 2241 2189 2242 - if (oldcurrent && !bond->curr_active_slave) { 2243 - printk(KERN_INFO DRV_NAME 2244 - ": %s: now running without any active " 2245 - "interface !\n", 2246 - bond_dev->name); 2247 - } 2248 - 2249 2190 write_unlock(&bond->curr_slave_lock); 2250 - } 2191 + } else 2192 + bond_set_carrier(bond); 2251 2193 2252 2194 re_arm: 2253 2195 if (bond->params.miimon) { ··· 2545 2499 2546 2500 bond_select_active_slave(bond); 2547 2501 2548 - if (oldcurrent && !bond->curr_active_slave) { 2549 - printk(KERN_INFO DRV_NAME 2550 - ": %s: now running without any active " 2551 - "interface !\n", 2552 - bond_dev->name); 2553 - } 2554 - 2555 2502 write_unlock(&bond->curr_slave_lock); 2556 2503 } 2557 2504 ··· 2618 2579 bond->current_arp_slave = NULL; 2619 2580 } 2620 2581 2582 + bond_set_carrier(bond); 2583 + 2621 2584 if (slave == bond->curr_active_slave) { 2622 2585 printk(KERN_INFO DRV_NAME 2623 2586 ": %s: %s is up and now the " 2624 2587 "active interface\n", 2625 2588 bond_dev->name, 2626 2589 slave->dev->name); 2590 + netif_carrier_on(bond->dev); 2627 2591 } else { 2628 2592 printk(KERN_INFO DRV_NAME 2629 2593 ": %s: backup interface %s is " ··· 2886 2844 (curr) ? curr->dev->name : "None"); 2887 2845 } 2888 2846 2889 - seq_printf(seq, "MII Status: %s\n", (curr) ? "up" : "down"); 2847 + seq_printf(seq, "MII Status: %s\n", netif_carrier_ok(bond->dev) ? 2848 + "up" : "down"); 2890 2849 seq_printf(seq, "MII Polling Interval (ms): %d\n", bond->params.miimon); 2891 2850 seq_printf(seq, "Up Delay (ms): %d\n", 2892 2851 bond->params.updelay * bond->params.miimon); ··· 4573 4530 } 4574 4531 if (newbond) 4575 4532 *newbond = bond_dev->priv; 4533 + 4534 + netif_carrier_off(bond_dev); 4576 4535 4577 4536 rtnl_unlock(); /* allows sysfs registration of net device */ 4578 4537 res = bond_create_sysfs_entry(bond_dev->priv);
+2 -2
drivers/net/bonding/bonding.h
··· 22 22 #include "bond_3ad.h" 23 23 #include "bond_alb.h" 24 24 25 - #define DRV_VERSION "3.0.2" 26 - #define DRV_RELDATE "February 21, 2006" 25 + #define DRV_VERSION "3.0.3" 26 + #define DRV_RELDATE "March 23, 2006" 27 27 #define DRV_NAME "bonding" 28 28 #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" 29 29