Skip to content

Commit

Permalink
net/bonding: Optionally allow ethernet slaves to keep own MAC
Browse files Browse the repository at this point in the history
	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: Jay Vosburgh <fubar@us.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
  • Loading branch information
Jay Vosburgh authored and Jeff Garzik committed Oct 15, 2007
1 parent d90a162 commit dd957c5
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 24 deletions.
33 changes: 33 additions & 0 deletions Documentation/networking/bonding.txt
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,39 @@ downdelay
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
Expand Down
57 changes: 36 additions & 21 deletions drivers/net/bonding/bond_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ static char *xmit_hash_policy = NULL;
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);
Expand Down Expand Up @@ -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_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 ----------------------------*/

Expand Down Expand Up @@ -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
* 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 &&
Expand Down Expand Up @@ -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 (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;
Expand All @@ -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);

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
Expand Down Expand Up @@ -1637,7 +1640,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
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);
Expand Down Expand Up @@ -1814,7 +1817,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
/* 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;
Expand Down Expand Up @@ -1935,7 +1938,7 @@ static int bond_release_all(struct net_device *bond_dev)
/* 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;
Expand Down Expand Up @@ -3060,9 +3063,15 @@ static void bond_info_show_master(struct seq_file *seq)
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",
Expand Down Expand Up @@ -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"));

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;
Expand Down Expand Up @@ -4384,10 +4397,6 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
#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;
Expand Down Expand Up @@ -4721,6 +4730,11 @@ static int bond_check_params(struct bond_params *params)
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;
Expand All @@ -4732,6 +4746,7 @@ static int bond_check_params(struct bond_params *params)
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);
Expand Down
49 changes: 49 additions & 0 deletions drivers/net/bonding/bond_sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/*
* 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
Expand Down Expand Up @@ -1388,6 +1436,7 @@ static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);
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,
Expand Down
6 changes: 3 additions & 3 deletions drivers/net/bonding/bonding.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
#include "bond_3ad.h"
#include "bond_alb.h"

#define DRV_VERSION "3.1.3"
#define DRV_RELDATE "June 13, 2007"
#define DRV_VERSION "3.2.0"
#define DRV_RELDATE "September 13, 2007"
#define DRV_NAME "bonding"
#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"

Expand Down Expand Up @@ -128,6 +128,7 @@ struct bond_params {
int arp_interval;
int arp_validate;
int use_carrier;
int fail_over_mac;
int updelay;
int downdelay;
int lacp_fast;
Expand Down Expand Up @@ -186,7 +187,6 @@ struct bonding {
struct timer_list mii_timer;
struct timer_list arp_timer;
s8 kill_timers;
s8 do_set_mac_addr;
s8 send_grat_arp;
s8 setup_by_slave;
struct net_device_stats stats;
Expand Down

0 comments on commit dd957c5

Please sign in to comment.