|
@@ -558,6 +558,42 @@ out:
|
|
|
|
|
|
/*------------------------------- 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
|
|
|
* 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)
|
|
|
void bond_select_active_slave(struct bonding *bond)
|
|
|
{
|
|
|
struct slave *best_slave;
|
|
|
+ int rv;
|
|
|
|
|
|
best_slave = bond_find_best_slave(bond);
|
|
|
if (best_slave != bond->curr_active_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)
|
|
|
if (((!bond->curr_active_slave) ||
|
|
|
(bond->curr_active_slave->dev->priv_flags & IFF_SLAVE_INACTIVE)) &&
|
|
|
(new_slave->link != BOND_LINK_DOWN)) {
|
|
|
- dprintk("This is the first active slave\n");
|
|
|
/* first slave or no active slave yet, and this link
|
|
|
is OK, so make this interface the active one */
|
|
|
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 {
|
|
|
dprintk("This is just a backup slave\n");
|
|
|
bond_set_slave_inactive_flags(new_slave);
|
|
@@ -1517,6 +1571,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
|
|
break;
|
|
|
} /* switch(bond_mode) */
|
|
|
|
|
|
+ bond_set_carrier(bond);
|
|
|
+
|
|
|
write_unlock_bh(&bond->lock);
|
|
|
|
|
|
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)
|
|
|
bond_alb_deinit_slave(bond, slave);
|
|
|
}
|
|
|
|
|
|
- if (oldcurrent == slave) {
|
|
|
+ if (oldcurrent == slave)
|
|
|
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) {
|
|
|
+ bond_set_carrier(bond);
|
|
|
+
|
|
|
/* if the last slave was removed, zero the mac address
|
|
|
* of the master so it will be set by the application
|
|
|
* to the mac address of the first slave
|
|
@@ -1751,6 +1801,8 @@ static int bond_release_all(struct net_device *bond_dev)
|
|
|
|
|
|
write_lock_bh(&bond->lock);
|
|
|
|
|
|
+ netif_carrier_off(bond_dev);
|
|
|
+
|
|
|
if (bond->slave_cnt == 0) {
|
|
|
goto out;
|
|
|
}
|
|
@@ -2187,15 +2239,9 @@ void bond_mii_monitor(struct net_device *bond_dev)
|
|
|
|
|
|
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);
|
|
|
- }
|
|
|
+ } else
|
|
|
+ bond_set_carrier(bond);
|
|
|
|
|
|
re_arm:
|
|
|
if (bond->params.miimon) {
|
|
@@ -2499,13 +2545,6 @@ void bond_loadbalance_arp_mon(struct net_device *bond_dev)
|
|
|
|
|
|
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);
|
|
|
}
|
|
|
|
|
@@ -2579,12 +2618,15 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
|
|
|
bond->current_arp_slave = NULL;
|
|
|
}
|
|
|
|
|
|
+ bond_set_carrier(bond);
|
|
|
+
|
|
|
if (slave == bond->curr_active_slave) {
|
|
|
printk(KERN_INFO DRV_NAME
|
|
|
": %s: %s is up and now the "
|
|
|
"active interface\n",
|
|
|
bond_dev->name,
|
|
|
slave->dev->name);
|
|
|
+ netif_carrier_on(bond->dev);
|
|
|
} else {
|
|
|
printk(KERN_INFO DRV_NAME
|
|
|
": %s: backup interface %s is "
|
|
@@ -2844,7 +2886,8 @@ static void bond_info_show_master(struct seq_file *seq)
|
|
|
(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, "Up Delay (ms): %d\n",
|
|
|
bond->params.updelay * bond->params.miimon);
|
|
@@ -4531,6 +4574,8 @@ int bond_create(char *name, struct bond_params *params, struct bonding **newbond
|
|
|
if (newbond)
|
|
|
*newbond = bond_dev->priv;
|
|
|
|
|
|
+ netif_carrier_off(bond_dev);
|
|
|
+
|
|
|
rtnl_unlock(); /* allows sysfs registration of net device */
|
|
|
res = bond_create_sysfs_entry(bond_dev->priv);
|
|
|
goto done;
|