Commit ff59c456 authored by Jay Vosburgh's avatar Jay Vosburgh Committed by Jeff Garzik

[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: default avatarJay Vosburgh <fubar@us.ibm.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent e21a2b0c
...@@ -2294,6 +2294,34 @@ void bond_3ad_handle_link_change(struct slave *slave, char link) ...@@ -2294,6 +2294,34 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
port->sm_vars |= AD_PORT_BEGIN; port->sm_vars |= AD_PORT_BEGIN;
} }
/*
* set link state for bonding master: if we have an active partnered
* aggregator, we're up, if not, we're down. Presumes that we cannot
* have an active aggregator if there are no slaves with link up.
*
* Called by bond_set_carrier(). Return zero if carrier state does not
* change, nonzero if it does.
*/
int bond_3ad_set_carrier(struct bonding *bond)
{
struct aggregator *agg;
agg = __get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator));
if (agg && MAC_ADDRESS_COMPARE(&agg->partner_system, &null_mac_addr)) {
if (!netif_carrier_ok(bond->dev)) {
netif_carrier_on(bond->dev);
return 1;
}
return 0;
}
if (netif_carrier_ok(bond->dev)) {
netif_carrier_off(bond->dev);
return 1;
}
return 0;
}
/** /**
* bond_3ad_get_active_agg_info - get information of the active aggregator * bond_3ad_get_active_agg_info - get information of the active aggregator
* @bond: bonding struct to work on * @bond: bonding struct to work on
......
...@@ -283,5 +283,6 @@ void bond_3ad_handle_link_change(struct slave *slave, char link); ...@@ -283,5 +283,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_xmit_xor(struct sk_buff *skb, struct net_device *dev);
int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype, struct net_device *orig_dev); int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype, struct net_device *orig_dev);
int bond_3ad_set_carrier(struct bonding *bond);
#endif //__BOND_3AD_H__ #endif //__BOND_3AD_H__
...@@ -558,6 +558,42 @@ static void bond_del_vlans_from_slave(struct bonding *bond, struct net_device *s ...@@ -558,6 +558,42 @@ static void bond_del_vlans_from_slave(struct bonding *bond, struct net_device *s
/*------------------------------- Link status -------------------------------*/ /*------------------------------- Link status -------------------------------*/
/*
* Set the carrier state for the master according to the state of its
* slaves. If any slaves are up, the master is up. In 802.3ad mode,
* do special 802.3ad magic.
*
* Returns zero if carrier state does not change, nonzero if it does.
*/
static int bond_set_carrier(struct bonding *bond)
{
struct slave *slave;
int i;
if (bond->slave_cnt == 0)
goto down;
if (bond->params.mode == BOND_MODE_8023AD)
return bond_3ad_set_carrier(bond);
bond_for_each_slave(bond, slave, i) {
if (slave->link == BOND_LINK_UP) {
if (!netif_carrier_ok(bond->dev)) {
netif_carrier_on(bond->dev);
return 1;
}
return 0;
}
}
down:
if (netif_carrier_ok(bond->dev)) {
netif_carrier_off(bond->dev);
return 1;
}
return 0;
}
/* /*
* Get link speed and duplex from the slave's base driver * Get link speed and duplex from the slave's base driver
* using ethtool. If for some reason the call fails or the * using ethtool. If for some reason the call fails or the
...@@ -1074,10 +1110,24 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) ...@@ -1074,10 +1110,24 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
void bond_select_active_slave(struct bonding *bond) void bond_select_active_slave(struct bonding *bond)
{ {
struct slave *best_slave; struct slave *best_slave;
int rv;
best_slave = bond_find_best_slave(bond); best_slave = bond_find_best_slave(bond);
if (best_slave != bond->curr_active_slave) { if (best_slave != bond->curr_active_slave) {
bond_change_active_slave(bond, best_slave); bond_change_active_slave(bond, best_slave);
rv = bond_set_carrier(bond);
if (!rv)
return;
if (netif_carrier_ok(bond->dev)) {
printk(KERN_INFO DRV_NAME
": %s: first active interface up!\n",
bond->dev->name);
} else {
printk(KERN_INFO DRV_NAME ": %s: "
"now running without any active interface !\n",
bond->dev->name);
}
} }
} }
...@@ -1458,10 +1508,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) ...@@ -1458,10 +1508,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
if (((!bond->curr_active_slave) || if (((!bond->curr_active_slave) ||
(bond->curr_active_slave->dev->priv_flags & IFF_SLAVE_INACTIVE)) && (bond->curr_active_slave->dev->priv_flags & IFF_SLAVE_INACTIVE)) &&
(new_slave->link != BOND_LINK_DOWN)) { (new_slave->link != BOND_LINK_DOWN)) {
dprintk("This is the first active slave\n");
/* first slave or no active slave yet, and this link /* first slave or no active slave yet, and this link
is OK, so make this interface the active one */ is OK, so make this interface the active one */
bond_change_active_slave(bond, new_slave); bond_change_active_slave(bond, new_slave);
printk(KERN_INFO DRV_NAME
": %s: first active interface up!\n",
bond->dev->name);
netif_carrier_on(bond->dev);
} else { } else {
dprintk("This is just a backup slave\n"); dprintk("This is just a backup slave\n");
bond_set_slave_inactive_flags(new_slave); bond_set_slave_inactive_flags(new_slave);
...@@ -1517,6 +1571,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) ...@@ -1517,6 +1571,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
break; break;
} /* switch(bond_mode) */ } /* switch(bond_mode) */
bond_set_carrier(bond);
write_unlock_bh(&bond->lock); write_unlock_bh(&bond->lock);
res = bond_create_slave_symlinks(bond_dev, slave_dev); res = bond_create_slave_symlinks(bond_dev, slave_dev);
...@@ -1656,18 +1712,12 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) ...@@ -1656,18 +1712,12 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
bond_alb_deinit_slave(bond, slave); bond_alb_deinit_slave(bond, slave);
} }
if (oldcurrent == slave) { if (oldcurrent == slave)
bond_select_active_slave(bond); bond_select_active_slave(bond);
if (!bond->curr_active_slave) {
printk(KERN_INFO DRV_NAME
": %s: now running without any active "
"interface !\n",
bond_dev->name);
}
}
if (bond->slave_cnt == 0) { if (bond->slave_cnt == 0) {
bond_set_carrier(bond);
/* if the last slave was removed, zero the mac address /* if the last slave was removed, zero the mac address
* of the master so it will be set by the application * of the master so it will be set by the application
* to the mac address of the first slave * to the mac address of the first slave
...@@ -1751,6 +1801,8 @@ static int bond_release_all(struct net_device *bond_dev) ...@@ -1751,6 +1801,8 @@ static int bond_release_all(struct net_device *bond_dev)
write_lock_bh(&bond->lock); write_lock_bh(&bond->lock);
netif_carrier_off(bond_dev);
if (bond->slave_cnt == 0) { if (bond->slave_cnt == 0) {
goto out; goto out;
} }
...@@ -2187,15 +2239,9 @@ void bond_mii_monitor(struct net_device *bond_dev) ...@@ -2187,15 +2239,9 @@ void bond_mii_monitor(struct net_device *bond_dev)
bond_select_active_slave(bond); bond_select_active_slave(bond);
if (oldcurrent && !bond->curr_active_slave) {
printk(KERN_INFO DRV_NAME
": %s: now running without any active "
"interface !\n",
bond_dev->name);
}
write_unlock(&bond->curr_slave_lock); write_unlock(&bond->curr_slave_lock);
} } else
bond_set_carrier(bond);
re_arm: re_arm:
if (bond->params.miimon) { if (bond->params.miimon) {
...@@ -2499,13 +2545,6 @@ void bond_loadbalance_arp_mon(struct net_device *bond_dev) ...@@ -2499,13 +2545,6 @@ void bond_loadbalance_arp_mon(struct net_device *bond_dev)
bond_select_active_slave(bond); bond_select_active_slave(bond);
if (oldcurrent && !bond->curr_active_slave) {
printk(KERN_INFO DRV_NAME
": %s: now running without any active "
"interface !\n",
bond_dev->name);
}
write_unlock(&bond->curr_slave_lock); write_unlock(&bond->curr_slave_lock);
} }
...@@ -2579,12 +2618,15 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev) ...@@ -2579,12 +2618,15 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
bond->current_arp_slave = NULL; bond->current_arp_slave = NULL;
} }
bond_set_carrier(bond);
if (slave == bond->curr_active_slave) { if (slave == bond->curr_active_slave) {
printk(KERN_INFO DRV_NAME printk(KERN_INFO DRV_NAME
": %s: %s is up and now the " ": %s: %s is up and now the "
"active interface\n", "active interface\n",
bond_dev->name, bond_dev->name,
slave->dev->name); slave->dev->name);
netif_carrier_on(bond->dev);
} else { } else {
printk(KERN_INFO DRV_NAME printk(KERN_INFO DRV_NAME
": %s: backup interface %s is " ": %s: backup interface %s is "
...@@ -2844,7 +2886,8 @@ static void bond_info_show_master(struct seq_file *seq) ...@@ -2844,7 +2886,8 @@ static void bond_info_show_master(struct seq_file *seq)
(curr) ? curr->dev->name : "None"); (curr) ? curr->dev->name : "None");
} }
seq_printf(seq, "MII Status: %s\n", (curr) ? "up" : "down"); seq_printf(seq, "MII Status: %s\n", netif_carrier_ok(bond->dev) ?
"up" : "down");
seq_printf(seq, "MII Polling Interval (ms): %d\n", bond->params.miimon); seq_printf(seq, "MII Polling Interval (ms): %d\n", bond->params.miimon);
seq_printf(seq, "Up Delay (ms): %d\n", seq_printf(seq, "Up Delay (ms): %d\n",
bond->params.updelay * bond->params.miimon); bond->params.updelay * bond->params.miimon);
...@@ -4531,6 +4574,8 @@ int bond_create(char *name, struct bond_params *params, struct bonding **newbond ...@@ -4531,6 +4574,8 @@ int bond_create(char *name, struct bond_params *params, struct bonding **newbond
if (newbond) if (newbond)
*newbond = bond_dev->priv; *newbond = bond_dev->priv;
netif_carrier_off(bond_dev);
rtnl_unlock(); /* allows sysfs registration of net device */ rtnl_unlock(); /* allows sysfs registration of net device */
res = bond_create_sysfs_entry(bond_dev->priv); res = bond_create_sysfs_entry(bond_dev->priv);
goto done; goto done;
......
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
#include "bond_3ad.h" #include "bond_3ad.h"
#include "bond_alb.h" #include "bond_alb.h"
#define DRV_VERSION "3.0.2" #define DRV_VERSION "3.0.3"
#define DRV_RELDATE "February 21, 2006" #define DRV_RELDATE "March 23, 2006"
#define DRV_NAME "bonding" #define DRV_NAME "bonding"
#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment