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

net/bonding: Optionally allow ethernet slaves to keep own MAC

	Update the "don't change MAC of slaves" functionality added in
previous changes to be a generic option, rather than something tied to
IB devices, as it's occasionally useful for regular ethernet devices as
well.

	Adds "fail_over_mac" option (which is automatically enabled for IB
slaves), applicable only to active-backup mode.

	Includes documentation update.

	Updates bonding driver version to 3.2.0.
Signed-off-by: default avatarJay Vosburgh <fubar@us.ibm.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent d90a162a
...@@ -281,6 +281,39 @@ downdelay ...@@ -281,6 +281,39 @@ downdelay
will be rounded down to the nearest multiple. The default will be rounded down to the nearest multiple. The default
value is 0. 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 lacp_rate
Option specifying the rate in which we'll ask our link partner Option specifying the rate in which we'll ask our link partner
......
...@@ -98,6 +98,7 @@ static char *xmit_hash_policy = NULL; ...@@ -98,6 +98,7 @@ static char *xmit_hash_policy = NULL;
static int arp_interval = BOND_LINK_ARP_INTERV; static int arp_interval = BOND_LINK_ARP_INTERV;
static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, }; static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
static char *arp_validate = NULL; static char *arp_validate = NULL;
static int fail_over_mac = 0;
struct bond_params bonding_defaults; struct bond_params bonding_defaults;
module_param(max_bonds, int, 0); module_param(max_bonds, int, 0);
...@@ -131,6 +132,8 @@ module_param_array(arp_ip_target, charp, NULL, 0); ...@@ -131,6 +132,8 @@ module_param_array(arp_ip_target, charp, NULL, 0);
MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form"); MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
module_param(arp_validate, charp, 0); module_param(arp_validate, charp, 0);
MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes: none (default), active, backup or all"); 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 ----------------------------*/ /*----------------------------- Global variables ----------------------------*/
...@@ -1100,7 +1103,7 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) ...@@ -1100,7 +1103,7 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
/* when bonding does not set the slave MAC address, the bond MAC /* when bonding does not set the slave MAC address, the bond MAC
* address is the one of the active slave. * 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, memcpy(bond->dev->dev_addr, new_active->dev->dev_addr,
new_active->dev->addr_len); new_active->dev->addr_len);
if (bond->curr_active_slave && if (bond->curr_active_slave &&
...@@ -1367,16 +1370,16 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) ...@@ -1367,16 +1370,16 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
if (slave_dev->set_mac_address == NULL) { if (slave_dev->set_mac_address == NULL) {
if (bond->slave_cnt == 0) { if (bond->slave_cnt == 0) {
printk(KERN_WARNING DRV_NAME printk(KERN_WARNING DRV_NAME
": %s: Warning: The first slave device you " ": %s: Warning: The first slave device "
"specified does not support setting the MAC " "specified does not support setting the MAC "
"address. This bond MAC address would be that " "address. Enabling the fail_over_mac option.",
"of the active slave.\n", bond_dev->name); bond_dev->name);
bond->do_set_mac_addr = 0; bond->params.fail_over_mac = 1;
} else if (bond->do_set_mac_addr) { } else if (!bond->params.fail_over_mac) {
printk(KERN_ERR DRV_NAME printk(KERN_ERR DRV_NAME
": %s: Error: The slave device you specified " ": %s: Error: The slave device specified "
"does not support setting the MAC addres,." "does not support setting the MAC address, "
"but this bond uses this practice. \n" "but fail_over_mac is not enabled.\n"
, bond_dev->name); , bond_dev->name);
res = -EOPNOTSUPP; res = -EOPNOTSUPP;
goto err_undo_flags; goto err_undo_flags;
...@@ -1401,7 +1404,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) ...@@ -1401,7 +1404,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
*/ */
memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN); 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 slave to master's mac address. The application already
* set the master's mac address to that of the first slave * set the master's mac address to that of the first slave
...@@ -1637,7 +1640,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) ...@@ -1637,7 +1640,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
dev_close(slave_dev); dev_close(slave_dev);
err_restore_mac: 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); memcpy(addr.sa_data, new_slave->perm_hwaddr, ETH_ALEN);
addr.sa_family = slave_dev->type; addr.sa_family = slave_dev->type;
dev_set_mac_address(slave_dev, &addr); dev_set_mac_address(slave_dev, &addr);
...@@ -1814,7 +1817,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) ...@@ -1814,7 +1817,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
/* close slave before restoring its mac address */ /* close slave before restoring its mac address */
dev_close(slave_dev); dev_close(slave_dev);
if (bond->do_set_mac_addr) { if (!bond->params.fail_over_mac) {
/* restore original ("permanent") mac address */ /* restore original ("permanent") mac address */
memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
addr.sa_family = slave_dev->type; addr.sa_family = slave_dev->type;
...@@ -1935,7 +1938,7 @@ static int bond_release_all(struct net_device *bond_dev) ...@@ -1935,7 +1938,7 @@ static int bond_release_all(struct net_device *bond_dev)
/* close slave before restoring its mac address */ /* close slave before restoring its mac address */
dev_close(slave_dev); dev_close(slave_dev);
if (bond->do_set_mac_addr) { if (!bond->params.fail_over_mac) {
/* restore original ("permanent") mac address*/ /* restore original ("permanent") mac address*/
memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
addr.sa_family = slave_dev->type; addr.sa_family = slave_dev->type;
...@@ -3060,9 +3063,15 @@ static void bond_info_show_master(struct seq_file *seq) ...@@ -3060,9 +3063,15 @@ static void bond_info_show_master(struct seq_file *seq)
curr = bond->curr_active_slave; curr = bond->curr_active_slave;
read_unlock(&bond->curr_slave_lock); 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)); 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 || if (bond->params.mode == BOND_MODE_XOR ||
bond->params.mode == BOND_MODE_8023AD) { bond->params.mode == BOND_MODE_8023AD) {
seq_printf(seq, "Transmit Hash Policy: %s (%d)\n", seq_printf(seq, "Transmit Hash Policy: %s (%d)\n",
...@@ -3994,8 +4003,12 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr) ...@@ -3994,8 +4003,12 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
dprintk("bond=%p, name=%s\n", bond, (bond_dev ? bond_dev->name : "None")); 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)) { if (!is_valid_ether_addr(sa->sa_data)) {
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
...@@ -4384,10 +4397,6 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) ...@@ -4384,10 +4397,6 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
bond_create_proc_entry(bond); bond_create_proc_entry(bond);
#endif #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); list_add_tail(&bond->bond_list, &bond_dev_list);
return 0; return 0;
...@@ -4721,6 +4730,11 @@ static int bond_check_params(struct bond_params *params) ...@@ -4721,6 +4730,11 @@ static int bond_check_params(struct bond_params *params)
primary = NULL; 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 */ /* fill params struct with the proper values */
params->mode = bond_mode; params->mode = bond_mode;
params->xmit_policy = xmit_hashtype; params->xmit_policy = xmit_hashtype;
...@@ -4732,6 +4746,7 @@ static int bond_check_params(struct bond_params *params) ...@@ -4732,6 +4746,7 @@ static int bond_check_params(struct bond_params *params)
params->use_carrier = use_carrier; params->use_carrier = use_carrier;
params->lacp_fast = lacp_fast; params->lacp_fast = lacp_fast;
params->primary[0] = 0; params->primary[0] = 0;
params->fail_over_mac = fail_over_mac;
if (primary) { if (primary) {
strncpy(params->primary, primary, IFNAMSIZ); strncpy(params->primary, primary, IFNAMSIZ);
......
...@@ -567,6 +567,54 @@ static ssize_t bonding_store_arp_validate(struct device *d, ...@@ -567,6 +567,54 @@ static ssize_t bonding_store_arp_validate(struct device *d,
static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate); 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 * Show and set the arp timer interval. There are two tricky bits
* here. First, if ARP monitoring is activated, then we must disable * here. First, if ARP monitoring is activated, then we must disable
...@@ -1388,6 +1436,7 @@ static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL); ...@@ -1388,6 +1436,7 @@ static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);
static struct attribute *per_bond_attrs[] = { static struct attribute *per_bond_attrs[] = {
&dev_attr_slaves.attr, &dev_attr_slaves.attr,
&dev_attr_mode.attr, &dev_attr_mode.attr,
&dev_attr_fail_over_mac.attr,
&dev_attr_arp_validate.attr, &dev_attr_arp_validate.attr,
&dev_attr_arp_interval.attr, &dev_attr_arp_interval.attr,
&dev_attr_arp_ip_target.attr, &dev_attr_arp_ip_target.attr,
......
...@@ -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.1.3" #define DRV_VERSION "3.2.0"
#define DRV_RELDATE "June 13, 2007" #define DRV_RELDATE "September 13, 2007"
#define DRV_NAME "bonding" #define DRV_NAME "bonding"
#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
...@@ -128,6 +128,7 @@ struct bond_params { ...@@ -128,6 +128,7 @@ struct bond_params {
int arp_interval; int arp_interval;
int arp_validate; int arp_validate;
int use_carrier; int use_carrier;
int fail_over_mac;
int updelay; int updelay;
int downdelay; int downdelay;
int lacp_fast; int lacp_fast;
...@@ -186,7 +187,6 @@ struct bonding { ...@@ -186,7 +187,6 @@ struct bonding {
struct timer_list mii_timer; struct timer_list mii_timer;
struct timer_list arp_timer; struct timer_list arp_timer;
s8 kill_timers; s8 kill_timers;
s8 do_set_mac_addr;
s8 send_grat_arp; s8 send_grat_arp;
s8 setup_by_slave; s8 setup_by_slave;
struct net_device_stats stats; struct net_device_stats stats;
......
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