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: Jay Vosburgh <fubar@us.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
parent
d90a162a4e
commit
dd957c57c5
4 changed files with 121 additions and 24 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
@ -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 ----------------------------*/
|
||||
|
||||
|
@ -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 &&
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -1637,7 +1640,7 @@ err_close:
|
|||
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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
@ -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,
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue