//#define BONDING_DEBUG 1
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
/*----------------------------- Global variables ----------------------------*/
-static const char * const version =
+static const char *version =
DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n";
LIST_HEAD(bond_dev_list);
/*------------------------------- 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
if ((bond->params.mode == BOND_MODE_TLB) ||
(bond->params.mode == BOND_MODE_ALB)) {
bond_alb_handle_active_change(bond, new_active);
- if (old_active)
- bond_set_slave_inactive_flags(old_active);
- if (new_active)
- bond_set_slave_active_flags(new_active);
} else {
bond->curr_active_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);
- }
}
}
}
#define BOND_INTERSECT_FEATURES \
- (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_TSO | NETIF_F_UFO)
+ (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM|\
+ NETIF_F_TSO|NETIF_F_UFO)
/*
* Compute the common dev->feature set available to all slaves. Some
features &= (slave->dev->features & BOND_INTERSECT_FEATURES);
if ((features & NETIF_F_SG) &&
- !(features & NETIF_F_ALL_CSUM))
+ !(features & (NETIF_F_IP_CSUM |
+ NETIF_F_NO_CSUM |
+ NETIF_F_HW_CSUM)))
features &= ~NETIF_F_SG;
/*
switch (bond->params.mode) {
case BOND_MODE_ACTIVEBACKUP:
- /* if we're in active-backup mode, we need one and
- * only one active interface. The backup interfaces
- * will have their SLAVE_INACTIVE flag set because we
- * need them to be drop all packets. Thus, since we
- * guarantee that curr_active_slave always point to
- * the last usable interface, we just have to verify
- * this interface's flag.
+ /* if we're in active-backup mode, we need one and only one active
+ * interface. The backup interfaces will have their NOARP flag set
+ * because we need them to be completely deaf and not to respond to
+ * any ARP request on the network to avoid fooling a switch. Thus,
+ * since we guarantee that curr_active_slave always point to the last
+ * usable interface, we just have to verify this interface's flag.
*/
if (((!bond->curr_active_slave) ||
- (bond->curr_active_slave->dev->priv_flags & IFF_SLAVE_INACTIVE)) &&
+ (bond->curr_active_slave->dev->flags & IFF_NOARP)) &&
(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);
* is OK, so make this interface the active one
*/
bond_change_active_slave(bond, new_slave);
- } else {
- bond_set_slave_inactive_flags(new_slave);
}
break;
default:
break;
} /* switch(bond_mode) */
- bond_set_carrier(bond);
-
write_unlock_bh(&bond->lock);
res = bond_create_slave_symlinks(bond_dev, slave_dev);
bond_alb_deinit_slave(bond, slave);
}
- if (oldcurrent == slave)
+ if (oldcurrent == slave) {
bond_select_active_slave(bond);
- if (bond->slave_cnt == 0) {
- bond_set_carrier(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 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
addr.sa_family = slave_dev->type;
dev_set_mac_address(slave_dev, &addr);
- slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
- IFF_SLAVE_INACTIVE);
+ /* restore the original state of the
+ * IFF_NOARP flag that might have been
+ * set by bond_set_slave_inactive_flags()
+ */
+ if ((slave->original_flags & IFF_NOARP) == 0) {
+ slave_dev->flags &= ~IFF_NOARP;
+ }
kfree(slave);
write_lock_bh(&bond->lock);
- netif_carrier_off(bond_dev);
-
if (bond->slave_cnt == 0) {
goto out;
}
addr.sa_family = slave_dev->type;
dev_set_mac_address(slave_dev, &addr);
- slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
- IFF_SLAVE_INACTIVE);
+ /* restore the original state of the IFF_NOARP flag that might have
+ * been set by bond_set_slave_inactive_flags()
+ */
+ if ((slave->original_flags & IFF_NOARP) == 0) {
+ slave_dev->flags &= ~IFF_NOARP;
+ }
kfree(slave);
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) {
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);
}
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 "
(curr) ? curr->dev->name : "None");
}
- seq_printf(seq, "MII Status: %s\n", netif_carrier_ok(bond->dev) ?
- "up" : "down");
+ seq_printf(seq, "MII Status: %s\n", (curr) ? "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);
* bond_netdev_event: handle netdev notifier chain events.
*
* This function receives events for the netdev chain. The caller (an
- * ioctl handler calling blocking_notifier_call_chain) holds the necessary
+ * ioctl handler calling notifier_call_chain) holds the necessary
* locks for us to safely manipulate the slave devices (RTNL lock,
* dev_probe_lock).
*/
mii->val_out = 0;
read_lock_bh(&bond->lock);
read_lock(&bond->curr_slave_lock);
- if (netif_carrier_ok(bond->dev)) {
+ if (bond->curr_active_slave) {
mii->val_out = BMSR_LSTATUS;
}
read_unlock(&bond->curr_slave_lock);
bond_dev->hard_start_xmit = bond_xmit_broadcast;
break;
case BOND_MODE_8023AD:
- bond_set_master_3ad_flags(bond);
bond_dev->hard_start_xmit = bond_3ad_xmit_xor;
if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34)
bond->xmit_hash_policy = bond_xmit_hash_policy_l34;
else
bond->xmit_hash_policy = bond_xmit_hash_policy_l2;
break;
- case BOND_MODE_ALB:
- bond_set_master_alb_flags(bond);
- /* FALLTHRU */
case BOND_MODE_TLB:
+ case BOND_MODE_ALB:
bond_dev->hard_start_xmit = bond_alb_xmit;
bond_dev->set_mac_address = bond_alb_set_mac_address;
break;
*/
bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
- /* don't acquire bond device's netif_tx_lock when
+ /* don't acquire bond device's xmit_lock when
* transmitting */
bond_dev->features |= NETIF_F_LLTX;
return 0;
}
-static struct lock_class_key bonding_netdev_xmit_lock_key;
-
/* Create a new bond based on the specified name and bonding parameters.
* Caller must NOT hold rtnl_lock; we need to release it here before we
* set up our sysfs entries.
if (res < 0) {
goto out_bond;
}
-
- lockdep_set_class(&bond_dev->_xmit_lock, &bonding_netdev_xmit_lock_key);
-
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;