will be rounded down to the nearest multiple. The default
value is 0.
+fail_over_mac
+
+ Specifies whether active-backup mode should set all slaves to
+ the same MAC address (the traditional behavior), or, when
+ enabled, change the bond's MAC address when changing the
+ active interface (i.e., fail over the MAC address itself).
+
+ Fail over MAC is useful for devices that cannot ever alter
+ their MAC address, or for devices that refuse incoming
+ broadcasts with their own source MAC (which interferes with
+ the ARP monitor).
+
+ The down side of fail over MAC is that every device on the
+ network must be updated via gratuitous ARP, vs. just updating
+ a switch or set of switches (which often takes place for any
+ traffic, not just ARP traffic, if the switch snoops incoming
+ traffic to update its tables) for the traditional method. If
+ the gratuitous ARP is lost, communication may be disrupted.
+
+ When fail over MAC is used in conjuction with the mii monitor,
+ devices which assert link up prior to being able to actually
+ transmit and receive are particularly susecptible to loss of
+ the gratuitous ARP, and an appropriate updelay setting may be
+ required.
+
+ A value of 0 disables fail over MAC, and is the default. A
+ value of 1 enables fail over MAC. This option is enabled
+ automatically if the first slave added cannot change its MAC
+ address. This option may be modified via sysfs only when no
+ slaves are present in the bond.
+
+ This option was added in bonding version 3.2.0.
+
lacp_rate
Option specifying the rate in which we'll ask our link partner
static int arp_interval = BOND_LINK_ARP_INTERV;
static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
static char *arp_validate = NULL;
+static int fail_over_mac = 0;
struct bond_params bonding_defaults;
module_param(max_bonds, int, 0);
MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
module_param(arp_validate, charp, 0);
MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes: none (default), active, backup or all");
+module_param(fail_over_mac, int, 0);
+MODULE_PARM_DESC(fail_over_mac, "For active-backup, do not set all slaves to the same MAC. 0 of off (default), 1 for on.");
/*----------------------------- Global variables ----------------------------*/
/* when bonding does not set the slave MAC address, the bond MAC
* address is the one of the active slave.
*/
- if (new_active && !bond->do_set_mac_addr)
+ if (new_active && bond->params.fail_over_mac)
memcpy(bond->dev->dev_addr, new_active->dev->dev_addr,
new_active->dev->addr_len);
if (bond->curr_active_slave &&
if (slave_dev->set_mac_address == NULL) {
if (bond->slave_cnt == 0) {
printk(KERN_WARNING DRV_NAME
- ": %s: Warning: The first slave device you "
- "specified does not support setting the MAC "
- "address. This bond MAC address would be that "
- "of the active slave.\n", bond_dev->name);
- bond->do_set_mac_addr = 0;
- } else if (bond->do_set_mac_addr) {
+ ": %s: Warning: The first slave device "
+ "specified does not support setting the MAC "
+ "address. Enabling the fail_over_mac option.",
+ bond_dev->name);
+ bond->params.fail_over_mac = 1;
+ } else if (!bond->params.fail_over_mac) {
printk(KERN_ERR DRV_NAME
- ": %s: Error: The slave device you specified "
- "does not support setting the MAC addres,."
- "but this bond uses this practice. \n"
+ ": %s: Error: The slave device specified "
+ "does not support setting the MAC address, "
+ "but fail_over_mac is not enabled.\n"
, bond_dev->name);
res = -EOPNOTSUPP;
goto err_undo_flags;
*/
memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN);
- if (bond->do_set_mac_addr) {
+ if (!bond->params.fail_over_mac) {
/*
* Set slave to master's mac address. The application already
* set the master's mac address to that of the first slave
dev_close(slave_dev);
err_restore_mac:
- if (bond->do_set_mac_addr) {
+ if (!bond->params.fail_over_mac) {
memcpy(addr.sa_data, new_slave->perm_hwaddr, ETH_ALEN);
addr.sa_family = slave_dev->type;
dev_set_mac_address(slave_dev, &addr);
/* close slave before restoring its mac address */
dev_close(slave_dev);
- if (bond->do_set_mac_addr) {
+ if (!bond->params.fail_over_mac) {
/* restore original ("permanent") mac address */
memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
addr.sa_family = slave_dev->type;
/* close slave before restoring its mac address */
dev_close(slave_dev);
- if (bond->do_set_mac_addr) {
+ if (!bond->params.fail_over_mac) {
/* restore original ("permanent") mac address*/
memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
addr.sa_family = slave_dev->type;
curr = bond->curr_active_slave;
read_unlock(&bond->curr_slave_lock);
- seq_printf(seq, "Bonding Mode: %s\n",
+ seq_printf(seq, "Bonding Mode: %s",
bond_mode_name(bond->params.mode));
+ if (bond->params.mode == BOND_MODE_ACTIVEBACKUP &&
+ bond->params.fail_over_mac)
+ seq_printf(seq, " (fail_over_mac)");
+
+ seq_printf(seq, "\n");
+
if (bond->params.mode == BOND_MODE_XOR ||
bond->params.mode == BOND_MODE_8023AD) {
seq_printf(seq, "Transmit Hash Policy: %s (%d)\n",
dprintk("bond=%p, name=%s\n", bond, (bond_dev ? bond_dev->name : "None"));
- if (!bond->do_set_mac_addr)
- return -EOPNOTSUPP;
+ /*
+ * If fail_over_mac is enabled, do nothing and return success.
+ * Returning an error causes ifenslave to fail.
+ */
+ if (bond->params.fail_over_mac)
+ return 0;
if (!is_valid_ether_addr(sa->sa_data)) {
return -EADDRNOTAVAIL;
#ifdef CONFIG_PROC_FS
bond_create_proc_entry(bond);
#endif
-
- /* set do_set_mac_addr to true on startup */
- bond->do_set_mac_addr = 1;
-
list_add_tail(&bond->bond_list, &bond_dev_list);
return 0;
primary = NULL;
}
+ if (fail_over_mac && (bond_mode != BOND_MODE_ACTIVEBACKUP))
+ printk(KERN_WARNING DRV_NAME
+ ": Warning: fail_over_mac only affects "
+ "active-backup mode.\n");
+
/* fill params struct with the proper values */
params->mode = bond_mode;
params->xmit_policy = xmit_hashtype;
params->use_carrier = use_carrier;
params->lacp_fast = lacp_fast;
params->primary[0] = 0;
+ params->fail_over_mac = fail_over_mac;
if (primary) {
strncpy(params->primary, primary, IFNAMSIZ);
static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate);
+/*
+ * Show and store fail_over_mac. User only allowed to change the
+ * value when there are no slaves.
+ */
+static ssize_t bonding_show_fail_over_mac(struct device *d, struct device_attribute *attr, char *buf)
+{
+ struct bonding *bond = to_bond(d);
+
+ return sprintf(buf, "%d\n", bond->params.fail_over_mac) + 1;
+}
+
+static ssize_t bonding_store_fail_over_mac(struct device *d, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int new_value;
+ int ret = count;
+ struct bonding *bond = to_bond(d);
+
+ if (bond->slave_cnt != 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Can't alter fail_over_mac with slaves in bond.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ if (sscanf(buf, "%d", &new_value) != 1) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: no fail_over_mac value specified.\n",
+ bond->dev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if ((new_value == 0) || (new_value == 1)) {
+ bond->params.fail_over_mac = new_value;
+ printk(KERN_INFO DRV_NAME ": %s: Setting fail_over_mac to %d.\n",
+ bond->dev->name, new_value);
+ } else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Ignoring invalid fail_over_mac value %d.\n",
+ bond->dev->name, new_value);
+ }
+out:
+ return ret;
+}
+
+static DEVICE_ATTR(fail_over_mac, S_IRUGO | S_IWUSR, bonding_show_fail_over_mac, bonding_store_fail_over_mac);
+
/*
* Show and set the arp timer interval. There are two tricky bits
* here. First, if ARP monitoring is activated, then we must disable
static struct attribute *per_bond_attrs[] = {
&dev_attr_slaves.attr,
&dev_attr_mode.attr,
+ &dev_attr_fail_over_mac.attr,
&dev_attr_arp_validate.attr,
&dev_attr_arp_interval.attr,
&dev_attr_arp_ip_target.attr,