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 <[EMAIL PROTECTED]>
---
 Documentation/networking/bonding.txt |   33 +++++++++++++++++++
 drivers/net/bonding/bond_main.c      |   57 +++++++++++++++++++++------------
 drivers/net/bonding/bond_sysfs.c     |   49 +++++++++++++++++++++++++++++
 drivers/net/bonding/bonding.h        |    6 ++--
 4 files changed, 121 insertions(+), 24 deletions(-)

diff --git a/Documentation/networking/bonding.txt 
b/Documentation/networking/bonding.txt
index 1da5666..1134062 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -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
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 77caca3..c01ff9d 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -97,6 +97,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);
@@ -130,6 +131,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 ----------------------------*/
 
@@ -1099,7 +1102,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 &&
@@ -1371,16 +1374,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;
@@ -1405,7 +1408,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
@@ -1641,7 +1644,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);
@@ -1823,7 +1826,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;
@@ -1944,7 +1947,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;
@@ -3066,9 +3069,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",
@@ -4008,8 +4017,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;
@@ -4402,10 +4415,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;
@@ -4739,6 +4748,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;
@@ -4750,6 +4764,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);
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 71db5d9..a907b68 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -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
  * MII monitoring.  Second, if the ARP timer isn't running, we must
@@ -1390,6 +1438,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,
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index ed0f587..9d6153e 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -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;
-- 1.5.2-rc2.GIT 

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to