* [PATCH 2.6.13-rc1 8/17] bonding: SYSFS INTERFACE (large)
From: Radheka Godse @ 2005-07-01 20:48 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
This large patch adds the sysfs interface to channel bonding. It will
allow users to add and remove bonds, add and remove slaves, and change
all bonding parameters without using ifenslave.
The ifenslave interface still works.
Signed-off-by: Radheka Godse <radheka.godse@intel.com>
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bonding.h linux-2.6.12post-sysfs/drivers/net/bonding/bonding.h
--- linux-2.6.12post/drivers/net/bonding/bonding.h 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bonding.h 2005-06-30 13:58:27.000000000 -0700
@@ -37,6 +37,7 @@
#include <linux/timer.h>
#include <linux/proc_fs.h>
#include <linux/if_bonding.h>
+#include <linux/kobject.h>
#include "bond_3ad.h"
#include "bond_alb.h"
@@ -262,6 +259,13 @@
int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
int bond_create(char *name, struct bond_params *params, struct bonding **newbond);
void bond_deinit(struct net_device *bond_dev);
+int bond_create_sysfs(void);
+void bond_destroy_sysfs(void);
+void bond_destroy_sysfs_entry(struct bonding *bond);
+int bond_create_sysfs_entry(struct bonding *bond);
+int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave);
+void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave);
+int bond_check_abi_ver(void);
int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev, struct slave **vassal);
int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev);
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_main.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c
--- linux-2.6.12post/drivers/net/bonding/bond_main.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c 2005-06-30 13:53:55.000000000 -0700
@@ -591,6 +591,7 @@
static struct proc_dir_entry *bond_proc_dir = NULL;
#endif
+extern struct rw_semaphore bonding_rwsem;
static u32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ;
static int arp_ip_count = 0;
static int bond_mode = BOND_MODE_ROUNDROBIN;
@@ -1994,6 +1994,9 @@
}
}
+ res = bond_create_slave_symlinks(bond_dev, slave_dev);
+ if (res)
+ goto err_unset_master;
printk(KERN_INFO DRV_NAME
": %s: enslaving %s as a%s interface with a%s link.\n",
bond_dev->name, slave_dev->name,
@@ -2165,6 +2176,9 @@
write_unlock_bh(&bond->lock);
+ /* must do this from outside any spinlocks */
+ bond_destroy_slave_symlinks(bond_dev, slave_dev);
+
bond_del_vlans_from_slave(bond, slave_dev);
/* If the mode USES_PRIMARY, then we should only remove its
@@ -2256,6 +2263,7 @@
*/
write_unlock_bh(&bond->lock);
+ bond_destroy_slave_symlinks(bond_dev, slave_dev);
bond_del_vlans_from_slave(bond, slave_dev);
/* If the mode USES_PRIMARY, then we should only remove its
@@ -2436,6 +2444,22 @@
}
}
+int bond_check_abi_ver(void)
+{
+ int retval = 1;
+
+ if (orig_app_abi_ver == -1) {
+ orig_app_abi_ver = BOND_ABI_VERSION;
+ app_abi_ver = BOND_ABI_VERSION;
+ }
+ else {
+ if (app_abi_ver == 0)
+ retval = 0;
+ }
+
+ return retval;
+}
+
static int bond_info_query(struct net_device *bond_dev, struct ifbond *info)
{
struct bonding *bond = bond_dev->priv;
@@ -3569,7 +3593,10 @@
bond_remove_proc_entry(bond);
bond_create_proc_entry(bond);
#endif
-
+ down_write(&(bonding_rwsem));
+ bond_destroy_sysfs_entry(bond);
+ bond_create_sysfs_entry(bond);
+ up_write(&(bonding_rwsem));
return NOTIFY_DONE;
}
@@ -4101,6 +4128,7 @@
orig_app_abi_ver = prev_abi_ver;
}
+ up_write(&(bonding_rwsem));
return res;
}
@@ -5000,18 +4990,22 @@
goto err;
}
+ res = bond_create_sysfs();
+ if (res)
+ goto err;
+
register_netdevice_notifier(&bond_netdev_notifier);
register_inetaddr_notifier(&bond_inetaddr_notifier);
- return 0;
-
-out_err:
- /* free and unregister all bonds that were successfully added */
+ goto out;
+err:
+ rtnl_lock();
bond_free_all();
-
+ bond_destroy_sysfs();
rtnl_unlock();
-
+out:
return res;
+
}
static void __exit bonding_exit(void)
@@ -5021,6 +5053,7 @@
rtnl_lock();
bond_free_all();
+ bond_destroy_sysfs();
rtnl_unlock();
}
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_sysfs.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_sysfs.c
--- linux-2.6.12post/drivers/net/bonding/bond_sysfs.c 1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_sysfs.c 2005-06-30 13:54:22.000000000 -0700
@@ -0,0 +1,1493 @@
+
+/*
+ * Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ *
+ * Changes:
+ *
+ * 2004/12/12 - Mitch Williams <mitch.a.williams at intel dot com>
+ * - Initial creation of sysfs interface.
+ *
+ * 2005/06/22 - Radheka Godse <radheka.godse at intel dot com>
+ * - Added ifenslave -c type functionality to sysfs
+ * - Added sysfs files for attributes such as MII Status and
+ * 802.3ad aggregator that are displayed in /proc
+ * - Added "name value" format to sysfs "mode" and
+ * "lacp_rate", for e.g., "active-backup 1" or "slow 0" for
+ * consistency and ease of script parsing
+ * - Fixed reversal of octets in arp_ip_targets via sysfs
+ * - sysfs support to handle bond interface re-naming
+ * - Moved all sysfs entries into /sys/class/net instead of
+ * of using a standalone subsystem.
+ * - Added sysfs symlinks between masters and slaves
+ * - Corrected bugs in sysfs unload path when creating bonds
+ * with existing interface names.
+ * - Removed redundant sysfs stat file since it duplicates slave info
+ * from the proc file
+ * - Fixed errors in sysfs show/store arp targets.
+ * - For consistency with ifenslave, instead of exiting
+ * with an error, updated bonding sysfs to
+ * close and attempt to enslave an up adapter.
+ * - Fixed NULL dereference when adding a slave interface
+ * that does not exist.
+ * - Added checks in sysfs bonding to reject invalid ip addresses
+ * - Synch up with post linux-2.6.12 bonding changes
+ * - Created sysfs bond attrib for xmit_hash_policy
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/in.h>
+#include <linux/sysfs.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/inet.h>
+#include <linux/rtnetlink.h>
+
+/* #define BONDING_DEBUG 1 */
+#include "bonding.h"
+#define to_class_dev(obj) container_of(obj,struct class_device,kobj)
+#define to_net_dev(class) container_of(class, struct net_device, class_dev)
+#define to_bond(cd) ((struct bonding *)(to_net_dev(cd)->priv))
+
+/*---------------------------- Declarations -------------------------------*/
+
+/* Macros for real simple parsing of text. */
+#define eat_nonalnum(str,whence,max) \
+ while (whence < max) {if (!isalnum(str[whence])) whence++; else break;};
+#define find_next_nonalpha(str,whence,max) \
+ while (whence < max) {if (isalnum(str[whence])) whence++; else break;};
+
+extern struct list_head bond_dev_list;
+extern struct bond_params bonding_defaults;
+extern struct bond_parm_tbl bond_mode_tbl[];
+extern struct bond_parm_tbl bond_lacp_tbl[];
+extern struct bond_parm_tbl xmit_hashtype_tbl[];
+
+static struct class *netdev_class;
+/*--------------------------- Data Structures -----------------------------*/
+
+/* Bonding sysfs lock. Why can't we just use the subsytem lock?
+ * Because kobject_register tries to acquire the subsystem lock. If
+ * we already hold the lock (which we would if the user was creating
+ * a new bond through the sysfs interface), we deadlock.
+ */
+
+struct rw_semaphore bonding_rwsem;
+
+
+
+
+/*------------------------------ Functions --------------------------------*/
+
+/*
+ * "show" function for the bond_masters attribute.
+ * The class parameter is ignored.
+ */
+static ssize_t bonding_show_bonds(struct class *cls, char *buffer)
+{
+ int res = 0;
+ struct bonding *bond;
+
+ down_read(&(bonding_rwsem));
+
+ list_for_each_entry(bond, &bond_dev_list, bond_list) {
+ res += sprintf(buffer + res, "%s ",
+ bond->dev->name);
+ if (res > (PAGE_SIZE - IFNAMSIZ)) {
+ dprintk("eek! too many bonds!\n");
+ break;
+ }
+ }
+ res += sprintf(buffer + res, "\n");
+ res++;
+ up_read(&(bonding_rwsem));
+ return res;
+}
+
+/*
+ * "store" function for the bond_masters attribute. This is what
+ * creates and deletes entire bonds.
+ *
+ * The class parameter is ignored.
+ *
+ * This function uses the eat_nonalnum and eat_alnum macros, define
+ * above. Why not use sscanf()? Scanf can get strings, but can't filter
+ * out inappropriate characters. For example, we can't have bonds named
+ * "foo/bar" or "foo*bar" or "Does this work?" as these aren't valid
+ * filenames. While we could use scanf to get strings and then validate
+ * them, this is quicker.
+ * The above examples give us these results:
+ * "foo/bar" gives two bonds, "foo" and "bar".
+ * "foo*bar" gives two bonds, "foo" and "bar".
+ * "Does this work?" gives three bonds, "Does", "this", and "work".
+ */
+
+static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t count)
+{
+ char name[IFNAMSIZ];
+ int i, res, found, pos = 0;
+ struct bonding *bond;
+ struct bonding *nxt;
+
+ down_write(&(bonding_rwsem));
+ /* First process adds */
+ eat_nonalnum(buffer, pos, count);
+ /* Pos now points to the first alpha character. */
+ i = pos;
+ find_next_nonalpha(buffer, i, count);
+ /* i now points to the next character past the end of the bond name. */
+ if (i - pos >= IFNAMSIZ) {
+ printk(KERN_ERR DRV_NAME "Interface name %.*s too large! Ignoring.\n",
+ i - pos, buffer + pos);
+ up_write(&(bonding_rwsem));
+ return -EPERM;
+ }
+ /* Copy the bond name so we can deal with it separately. */
+ strncpy(name, buffer + pos, i - pos);
+ /* Don't forget the null terminator! */
+ name[i - pos] = 0;
+ while (strlen(name)) {
+ /* Got a bond name in name. Is it already in the list? */
+ found = 0;
+ list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) {
+ if (strnicmp(bond->dev->name, name, IFNAMSIZ) == 0) {
+ /* Temporarily set a meaningless flag. When
+ * we get done with the loop, we'll check all of these.
+ * If the bond doesn't have this flag set, then we need
+ * to remove the bond. If the flag has it set, then
+ * we can just clear the flag.
+ */
+ bond->flags |= IFF_DYNAMIC;
+ found = 1;
+ break; /* Found it, so go to next name */
+ }
+ }
+ if (found == 0) {
+ printk(KERN_INFO DRV_NAME ": %s is being created...\n", name);
+ res = bond_create(name, &bonding_defaults, &bond);
+ if (res) {
+ up_write(&(bonding_rwsem));
+ printk(KERN_INFO DRV_NAME ": %s interface already exists. Bond creation failed.\n", name);
+ return res;
+ }
+ printk(KERN_INFO DRV_NAME ": %s created.\n", name);
+ /* Set the flag so we don't delete
+ * this interface in the loop below.
+ */
+ bond->flags |= IFF_DYNAMIC;
+ }
+ /* Scan for the next name. i still has the location of
+ * the char just past the end of the last name we handled.
+ */
+ pos = i;
+ eat_nonalnum(buffer, pos, count);
+ i = pos;
+ find_next_nonalpha(buffer, i, count);
+ if (i - pos >= IFNAMSIZ) {
+ printk(KERN_ERR DRV_NAME
+ ": %.*s interface name too large! Ignoring.\n",
+ i - pos, buffer + pos);
+ up_write(&(bonding_rwsem));
+ return -EPERM;
+ }
+ strncpy(name, buffer + pos, i - pos);
+ name[i - pos] = 0;
+ } /* end of while loop and end of input */
+
+ /* Now we do deletes. Walk through the list, and check to see
+ * if the flag didn't get set. If it's set, clear it. If it's
+ * not set, delete the bond.
+ */
+ list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) {
+ if (bond->flags & IFF_DYNAMIC) {
+ bond->flags &= ~IFF_DYNAMIC;
+ } else {
+ printk(KERN_INFO DRV_NAME ": %s is being deleted...\n", bond->dev->name);
+ rtnl_lock();
+ unregister_netdevice(bond->dev);
+ bond_deinit(bond->dev);
+ bond_destroy_sysfs_entry(bond);
+ rtnl_unlock();
+ printk(KERN_INFO DRV_NAME ": %s deleted.\n", bond->dev->name);
+ }
+ }
+ /* Always return either count or an error. If you return 0, you'll
+ * get called forever, which is bad.
+ */
+ up_write(&(bonding_rwsem));
+ return count;
+}
+/* class attribute for bond_masters file. This ends up in /sys/class/net */
+static CLASS_ATTR(bonding_masters, S_IWUSR | S_IRUGO,
+ bonding_show_bonds, bonding_store_bonds);
+
+int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave)
+{
+ char linkname[IFNAMSIZ+7];
+ int ret = 0;
+
+ /* first, create a link from the slave back to the master */
+ ret = sysfs_create_link(&(slave->class_dev.kobj), &(master->class_dev.kobj),
+ "master");
+ if (ret)
+ return ret;
+ /* next, create a link from the master to the slave */
+ sprintf(linkname,"slave_%s",slave->name);
+ ret = sysfs_create_link(&(master->class_dev.kobj), &(slave->class_dev.kobj),
+ linkname);
+ return ret;
+
+}
+
+void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave)
+{
+ char linkname[IFNAMSIZ+7];
+
+ sysfs_remove_link(&(slave->class_dev.kobj), "master");
+ sprintf(linkname,"slave_%s",slave->name);
+ sysfs_remove_link(&(master->class_dev.kobj), linkname);
+}
+
+
+/*
+ * Show the slaves in the current bond.
+ */
+static ssize_t bonding_show_slaves(struct class_device *cd, char *buf)
+{
+ struct slave *slave;
+ int i, res = 0;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+
+ read_lock_bh(&bond->lock);
+ bond_for_each_slave(bond, slave, i) {
+ res += sprintf(buf + res, "%s ", slave->dev->name);
+ if (res > (PAGE_SIZE - IFNAMSIZ)) {
+ dprintk("eek! too many slaves!\n");
+ break;
+ }
+ }
+ read_unlock_bh(&bond->lock);
+ res += sprintf(buf + res, "\n");
+ res++;
+ up_read(&(bonding_rwsem));
+ return res;
+}
+
+/*
+ * Set the slaves in the current bond. The bond interface must be
+ * up for this to succeed.
+ * This function is largely the same flow as bonding_update_bonds().
+ */
+static ssize_t bonding_store_slaves(struct class_device *cd, const char *buffer, size_t count)
+{
+ char name[IFNAMSIZ];
+ int i, j, res, found, pos = 0, ret = count;
+ struct slave *slave;
+ struct net_device *dev = 0;
+ struct bonding *bond = to_bond(cd);
+
+ if (!bond_check_abi_ver())
+ {
+ printk(KERN_ERR DRV_NAME
+ ": Error: your version of ifenslave is incompatible "
+ "with the sysfs interface in this version of bonding. "
+ "Upgrade ifenslave to version 1 or greater and reload "
+ "bonding.\n");
+ return -EINVAL;
+ }
+
+ down_write(&(bonding_rwsem));
+
+ /* Quick sanity check -- is the bond interface up? */
+ if (!(bond->dev->flags & IFF_UP)) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Unable to update slaves because interface is down.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ /* Note: We can't hold bond->lock here, as bond_create grabs it. */
+
+ /* First process adds */
+
+ /* Copy the first name we find. */
+ eat_nonalnum(buffer, pos, count);
+ i = pos;
+ find_next_nonalpha(buffer, i, count);
+ if (i - pos >= IFNAMSIZ) {
+ printk(KERN_ERR DRV_NAME ": %s: Slave name %.*s too large! Ignoring.\n",
+ bond->dev->name,
+ i - pos, buffer + pos);
+ ret = -EPERM;
+ goto out;
+ }
+ strncpy(name, buffer + pos, i - pos);
+ name[i - pos] = 0;
+
+ while (strlen(name)) {
+ /* Got a slave name in name. Is it already there? */
+ found = 0;
+ read_lock_bh(&bond->lock);
+ bond_for_each_slave(bond, slave, j) {
+ if (strnicmp(slave->dev->name, name, IFNAMSIZ) == 0) {
+ /* Temporarily set a meaningless flag. When
+ * we get done with the loop, we'll check all of these.
+ * If the slave doesn't have this flag set, then we need
+ * to remove the slave. If the flag has it set, then
+ * we can just clear the flag.
+ */
+ slave->original_flags |= IFF_DYNAMIC;
+ found = 1;
+ break; /* Found it, so go to next name */
+ }
+ }
+ read_unlock_bh(&bond->lock);
+ if (found == 0) {
+ printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n",
+ bond->dev->name, name);
+ dev = dev_get_by_name(name);
+ if (!dev) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Interface %s does not exist!\n",
+ bond->dev->name, name);
+ ret = -EPERM;
+ goto out;
+ }
+ else {
+ dev_put(dev);
+ }
+
+
+ if (dev->flags & IFF_SLAVE) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Interface %s is already enslaved!\n",
+ bond->dev->name, name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ /* If this is the first slave, then we need to set
+ the master's hardware address to be the same as the
+ slave's. */
+ if (!(*((u32 *) & (bond->dev->dev_addr[0])))) {
+ memcpy(bond->dev->dev_addr, dev->dev_addr,
+ dev->addr_len);
+ }
+
+ /* Set the slave's MTU to match the bond */
+ if (dev->mtu != bond->dev->mtu) {
+ if (dev->change_mtu) {
+ res = dev->change_mtu(dev,
+ bond->dev->mtu);
+ if (res) {
+ ret = res;
+ goto out;
+ }
+ } else {
+ dev->mtu = bond->dev->mtu;
+ }
+ }
+ rtnl_lock();
+ res = bond_enslave(bond->dev, dev, &slave);
+ rtnl_unlock();
+ if (res) {
+ ret = res;
+ goto out;
+ }
+ slave->original_flags |= IFF_DYNAMIC;
+ }
+ /* Get the next name in the buffer. */
+ pos = i;
+ eat_nonalnum(buffer, pos, count);
+ i = pos;
+ find_next_nonalpha(buffer, i, count);
+ if (i - pos >= IFNAMSIZ) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Slave name %.*s too large! Ignoring.\n",
+ bond->dev->name, i - pos, buffer + pos);
+ ret = -EPERM;
+ goto out;
+ }
+ strncpy(name, buffer + pos, i - pos);
+ name[i - pos] = 0;
+ } /* End of while loop, and end of input. */
+
+ /* Now handle deletes.
+ * We can't use bond_for_each_slave here because we might modify
+ * the list when we're inside the loop. We can't hold the lock
+ * either because bond_release grabs it.
+ */
+ slave = bond->first_slave;
+ i = bond->slave_cnt;
+ while (i > 0) {
+ BUG_ON(slave == 0);
+ if (slave->original_flags & IFF_DYNAMIC) {
+ slave->original_flags &= ~IFF_DYNAMIC;
+ slave = slave->next;
+ } else {
+ /* Didn't find the name of this slave in the list, so
+ * remove the slave.
+ */
+ printk(KERN_INFO DRV_NAME
+ ": %s: Removing slave %s\n",
+ bond->dev->name,
+ slave->dev->name);
+ dev = slave->dev;
+ slave = slave->next;
+ rtnl_lock();
+ res = bond_release(bond->dev, dev);
+ rtnl_unlock();
+ if (res) {
+ ret = res;
+ goto out;
+ }
+ /* set the slave MTU to the default */
+ if (dev->change_mtu) {
+ dev->change_mtu(dev, 1500);
+ } else {
+ dev->mtu = 1500;
+ }
+ }
+ i--;
+ }
+
+out:
+ up_write(&(bonding_rwsem));
+ return ret;
+}
+static CLASS_DEVICE_ATTR(slaves, S_IRUGO | S_IWUSR, bonding_show_slaves, bonding_store_slaves);
+
+/*
+ * Show and set the bonding mode. The bond interface must be down to
+ * change the mode.
+ */
+static ssize_t bonding_show_mode(struct class_device *cd, char *buf)
+{
+ int count;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ count = sprintf(buf, "%s %d\n",
+ bond_mode_tbl[bond->params.mode].modename,
+ bond->params.mode) + 1;
+ up_read(&(bonding_rwsem));
+ return count;
+}
+
+static ssize_t bonding_store_mode(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ down_write(&(bonding_rwsem));
+
+ if (bond->dev->flags & IFF_UP) {
+ printk(KERN_ERR DRV_NAME
+ "Unable to update mode of %s because interface is up.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ new_value = bond_parse_parm((char *)buf, bond_mode_tbl);
+ if (new_value < 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Ignoring invalid mode value %.*s.\n",
+ bond->dev->name,
+ (int)strlen(buf) - 1, buf);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ bond->params.mode = new_value;
+ bond_set_mode_ops(bond, bond->params.mode);
+ printk(KERN_INFO DRV_NAME ": %s: setting mode to %s (%d).\n",
+ bond->dev->name, bond_mode_tbl[new_value].modename, new_value);
+ }
+out:
+ up_write(&(bonding_rwsem));
+ return ret;
+}
+static CLASS_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, bonding_show_mode, bonding_store_mode);
+
+/*
+ * Show and set the bonding transmit hash method. The bond interface must be down to
+ * change the xmit hash policy.
+ */
+static ssize_t bonding_show_xmit_hash(struct class_device *cd, char *buf)
+{
+ int count;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ if ((bond->params.mode != BOND_MODE_XOR) &&
+ (bond->params.mode != BOND_MODE_8023AD)) {
+ // Not Applicable
+ count = sprintf(buf, "NA\n") + 1;
+ } else {
+ count = sprintf(buf, "%s %d\n",
+ xmit_hashtype_tbl[bond->params.xmit_policy].modename,
+ bond->params.xmit_policy) + 1;
+ }
+ up_read(&(bonding_rwsem));
+
+ return count;
+}
+
+static ssize_t bonding_store_xmit_hash(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ down_write(&(bonding_rwsem));
+
+ if (bond->dev->flags & IFF_UP) {
+ printk(KERN_ERR DRV_NAME
+ "%s: Interface is up. Unable to update xmit policy.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ if ((bond->params.mode != BOND_MODE_XOR) &&
+ (bond->params.mode != BOND_MODE_8023AD)) {
+ printk(KERN_ERR DRV_NAME
+ "%s: Transmit hash policy is irrelevant in this mode.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ new_value = bond_parse_parm((char *)buf, xmit_hashtype_tbl);
+ if (new_value < 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Ignoring invalid xmit hash policy value %.*s.\n",
+ bond->dev->name,
+ (int)strlen(buf) - 1, buf);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ bond->params.xmit_policy = new_value;
+ bond_set_mode_ops(bond, bond->params.mode);
+ printk(KERN_INFO DRV_NAME ": %s: setting xmit hash policy to %s (%d).\n",
+ bond->dev->name, xmit_hashtype_tbl[new_value].modename, new_value);
+ }
+out:
+ up_write(&(bonding_rwsem));
+ return ret;
+}
+static CLASS_DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, bonding_show_xmit_hash, bonding_store_xmit_hash);
+
+/*
+ * 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
+ * start it.
+ */
+static ssize_t bonding_show_arp_interval(struct class_device *cd, char *buf)
+{
+ int count;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ count = sprintf(buf, "%d\n", bond->params.arp_interval) + 1;
+ up_read(&(bonding_rwsem));
+ return count;
+}
+
+static ssize_t bonding_store_arp_interval(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ down_write(&(bonding_rwsem));
+
+ sscanf(buf, "%d", &new_value);
+ if (new_value < 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid arp_interval value %d not in range %d-%d; rejected.\n",
+ bond->dev->name, new_value, 1, INT_MAX);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting ARP monitoring interval to %d.\n",
+ bond->dev->name, new_value);
+ bond->params.arp_interval = new_value;
+ if (bond->params.miimon) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: ARP monitoring cannot be used with MII monitoring. "
+ "%s Disabling MII monitoring.\n",
+ bond->dev->name, bond->dev->name);
+ bond->params.miimon = 0;
+ /* Kill MII timer, else it brings bond's link down */
+ if (bond->arp_timer.function) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Kill MII timer, else it brings bond's link down...\n",
+ bond->dev->name);
+ del_timer_sync(&bond->mii_timer);
+ }
+ }
+ if (!bond->params.arp_targets[0]) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: ARP monitoring has been set up, "
+ "but no ARP targets have been specified.\n",
+ bond->dev->name);
+ }
+ if (bond->dev->flags & IFF_UP) {
+ /* If the interface is up, we may need to fire off
+ * the ARP timer. If the interface is down, the
+ * timer will get fired off when the open function
+ * is called.
+ */
+ if (bond->arp_timer.function) {
+ /* The timer's already set up, so fire it off */
+ mod_timer(&bond->arp_timer, jiffies + 1);
+ } else {
+ /* Set up the timer. */
+ init_timer(&bond->arp_timer);
+ bond->arp_timer.expires = jiffies + 1;
+ bond->arp_timer.data =
+ (unsigned long) bond->dev;
+ if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
+ bond->arp_timer.function =
+ (void *)
+ &bond_activebackup_arp_mon;
+ } else {
+ bond->arp_timer.function =
+ (void *)
+ &bond_loadbalance_arp_mon;
+ }
+ add_timer(&bond->arp_timer);
+ }
+ }
+ }
+
+out:
+ up_write(&(bonding_rwsem));
+ return ret;
+}
+static CLASS_DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR , bonding_show_arp_interval, bonding_store_arp_interval);
+
+/*
+ * Show and set the arp targets.
+ */
+static ssize_t bonding_show_arp_targets(struct class_device *cd, char *buf)
+{
+ int i, res = 0;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+
+ for (i = 0; (i < BOND_MAX_ARP_TARGETS) && bond->params.arp_targets[i];
+ i++) {
+ res += sprintf(buf + res, "%u.%u.%u.%u",
+ NIPQUAD(bond->params.arp_targets[i]));
+ if ((i+1 < BOND_MAX_ARP_TARGETS) && bond->params.arp_targets[i+1])
+ res += sprintf(buf + res, " ");
+ else
+ res += sprintf(buf + res, "\n");
+ res++;
+ }
+
+ up_read(&(bonding_rwsem));
+ return res;
+}
+
+static ssize_t bonding_store_arp_targets(struct class_device *cd, const char *buf, size_t count)
+{
+ int octet1, octet2, octet3, octet4, ret = count;
+ int newpos = 0, pos = 0, i = 0;
+ struct bonding *bond = to_bond(cd);
+ const char *delimiter;
+
+ down_write(&(bonding_rwsem));
+
+ memset(bond->params.arp_targets, 0, sizeof(bond->params.arp_targets));
+ if (sscanf(buf, "%d.%d.%d.%d%n", &octet1, &octet2, &octet3, &octet4, &pos) != 4) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid arp targets.\n", bond->dev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* check for delimiting white space */
+ delimiter = buf + pos;
+ if(*delimiter != ' ' && *delimiter != '\n' ) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid arp targets with missing whitespace.\n", bond->dev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ while ((pos < count) && (i < BOND_MAX_ARP_TARGETS)) {
+ if ( (octet1 < 0) || (octet1 > 255)
+ || (octet2 < 0) || (octet2 > 255)
+ || (octet3 < 0) || (octet3 > 255)
+ || (octet4 < 0) || (octet4 > 255)
+ || ((octet1 == 0) && (octet2 == 0) &&
+ (octet3 == 0) && (octet4 == 0))
+ || ((octet1 == 255) && (octet2 == 255) &&
+ (octet3 == 255) && (octet4 == 255))
+ ) {
+ memset(bond->params.arp_targets, 0, sizeof(bond->params.arp_targets));
+ printk(KERN_ERR DRV_NAME
+ ": %s: Unable to add arp target %d.%d.%d.%d\n",
+ bond->dev->name, octet1, octet2, octet3, octet4);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Adding arp target %d.%d.%d.%d\n",
+ bond->dev->name, octet1, octet2, octet3, octet4);
+ bond->params.arp_targets[i] = htonl
+ ((((u32) octet1 & 0xff) << 24) |
+ (((u32) octet2 & 0xff) << 16) |
+ (((u32) octet3 & 0xff) << 8) | ((u32) octet4 &
+ 0xff));
+
+ i++;
+ }
+
+ newpos = 0;
+ if (sscanf(buf + pos, "%d.%d.%d.%d%n", &octet1, &octet2, &octet3,
+ &octet4, &newpos) != 4 && newpos != 0) {
+ memset(bond->params.arp_targets, 0, sizeof(bond->params.arp_targets));
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid arp targets specified.\n", bond->dev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+ if (newpos == 0) {
+ break;
+ }
+
+ pos += newpos;
+ /* check for delimiting white space */
+ delimiter = buf + pos;
+ if(*delimiter != ' ' && *delimiter != '\n' ) {
+ memset(bond->params.arp_targets, 0, sizeof(bond->params.arp_targets));
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid arp targets with missing whitespace.\n", bond->dev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+out:
+ up_write(&(bonding_rwsem));
+ return ret;
+}
+static CLASS_DEVICE_ATTR(arp_ip_target, S_IRUGO | S_IWUSR , bonding_show_arp_targets, bonding_store_arp_targets);
+
+/*
+ * Show and set the up and down delays. These must be multiples of the
+ * MII monitoring value, and are stored internally as the multiplier.
+ * Thus, we must translate to MS for the real world.
+ */
+static ssize_t bonding_show_downdelay(struct class_device *cd, char *buf)
+{
+ int count;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ count = sprintf(buf, "%d\n", bond->params.downdelay * bond->params.miimon) + 1;
+ up_read(&(bonding_rwsem));
+ return count;
+}
+
+static ssize_t bonding_store_downdelay(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ down_write(&(bonding_rwsem));
+
+ if (!(bond->params.miimon)) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Unable to set down delay as MII monitoring is disabled\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ sscanf(buf, "%d", &new_value);
+ if (new_value < 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n",
+ bond->dev->name, new_value, 1, INT_MAX);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ if ((new_value % bond->params.miimon) != 0) {
+ printk(KERN_WARNING DRV_NAME
+ ": %s: Warning: down delay (%d) is not a multiple "
+ "of miimon (%d), delay rounded to %d ms\n",
+ bond->dev->name, new_value, bond->params.miimon,
+ (new_value / bond->params.miimon) *
+ bond->params.miimon);
+ }
+ bond->params.downdelay = new_value / bond->params.miimon;
+ printk(KERN_INFO DRV_NAME ": %s: Setting down delay to %d.\n",
+ bond->dev->name, bond->params.downdelay * bond->params.miimon);
+
+ }
+
+out:
+ up_write(&(bonding_rwsem));
+ return ret;
+}
+static CLASS_DEVICE_ATTR(down_delay, S_IRUGO | S_IWUSR , bonding_show_downdelay, bonding_store_downdelay);
+
+static ssize_t bonding_show_updelay(struct class_device *cd, char *buf)
+{
+ int count;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ count = sprintf(buf, "%d\n", bond->params.updelay * bond->params.miimon) + 1;
+ up_read(&(bonding_rwsem));
+ return count;
+
+}
+
+static ssize_t bonding_store_updelay(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ down_write(&(bonding_rwsem));
+
+ if (!(bond->params.miimon)) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Unable to set up delay as MII monitoring is disabled\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ sscanf(buf, "%d", &new_value);
+ if (new_value < 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n",
+ bond->dev->name, new_value, 1, INT_MAX);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ if ((new_value % bond->params.miimon) != 0) {
+ printk(KERN_WARNING DRV_NAME
+ ": %s: Warning: up delay (%d) is not a multiple "
+ "of miimon (%d), updelay rounded to %d ms\n",
+ bond->dev->name, new_value, bond->params.miimon,
+ (new_value / bond->params.miimon) *
+ bond->params.miimon);
+ }
+ bond->params.updelay = new_value / bond->params.miimon;
+ printk(KERN_INFO DRV_NAME ": %s: Setting up delay to %d.\n",
+ bond->dev->name, bond->params.updelay * bond->params.miimon);
+
+ }
+
+out:
+ up_write(&(bonding_rwsem));
+ return ret;
+}
+static CLASS_DEVICE_ATTR(up_delay, S_IRUGO | S_IWUSR , bonding_show_updelay, bonding_store_updelay);
+
+/*
+ * Show and set the LACP interval. Interface must be down, and the mode
+ * must be set to 802.3ad mode.
+ */
+static ssize_t bonding_show_lacp(struct class_device *cd, char *buf)
+{
+ int count;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ count = sprintf(buf, "%s %d\n",
+ bond_lacp_tbl[bond->params.lacp_fast].modename,
+ bond->params.lacp_fast) + 1;
+ up_read(&(bonding_rwsem));
+ return count;
+}
+
+static ssize_t bonding_store_lacp(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ down_write(&(bonding_rwsem));
+
+ if (bond->dev->flags & IFF_UP) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Unable to update LACP rate because interface is up.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ if (bond->params.mode != BOND_MODE_8023AD) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Unable to update LACP rate because bond is not in 802.3ad mode.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ new_value = bond_parse_parm((char *)buf, bond_lacp_tbl);
+
+ if ((new_value == 1) || (new_value == 0)) {
+ bond->params.lacp_fast = new_value;
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting LACP rate to %s (%d).\n",
+ bond->dev->name, bond_lacp_tbl[new_value].modename, new_value);
+ } else {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Ignoring invalid LACP rate value %.*s.\n",
+ bond->dev->name, (int)strlen(buf) - 1, buf);
+ ret = -EINVAL;
+ }
+out:
+ up_write(&(bonding_rwsem));
+ return ret;
+}
+static CLASS_DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_store_lacp);
+
+/*
+ * Show and set the MII monitor interval. There are two tricky bits
+ * here. First, if MII monitoring is activated, then we must disable
+ * ARP monitoring. Second, if the timer isn't running, we must
+ * start it.
+ */
+static ssize_t bonding_show_miimon(struct class_device *cd, char *buf)
+{
+ int count;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ count = sprintf(buf, "%d\n", bond->params.miimon) + 1;
+ up_read(&(bonding_rwsem));
+ return count;
+}
+
+static ssize_t bonding_store_miimon(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+
+ sscanf(buf, "%d", &new_value);
+ if (new_value < 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid miimon value %d not in range %d-%d; rejected.\n",
+ bond->dev->name, new_value, 1, INT_MAX);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting MII monitoring interval to %d.\n",
+ bond->dev->name, new_value);
+ bond->params.miimon = new_value;
+ if(bond->params.updelay)
+ printk(KERN_INFO DRV_NAME
+ ": %s: Note: Updating updelay (to %d) "
+ "since it is a multiple of the miimon value.\n",
+ bond->dev->name,
+ bond->params.updelay * bond->params.miimon);
+ if(bond->params.downdelay)
+ printk(KERN_INFO DRV_NAME
+ ": %s: Note: Updating downdelay (to %d) "
+ "since it is a multiple of the miimon value.\n",
+ bond->dev->name,
+ bond->params.downdelay * bond->params.miimon);
+ if (bond->params.arp_interval) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: MII monitoring cannot be used with "
+ "ARP monitoring. Disabling ARP monitoring...\n",
+ bond->dev->name);
+ bond->params.arp_interval = 0;
+ /* Kill ARP timer, else it brings bond's link down */
+ if (bond->mii_timer.function) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Kill ARP timer, else it brings bond's link down...\n",
+ bond->dev->name);
+ del_timer_sync(&bond->arp_timer);
+ }
+ }
+
+ if (bond->dev->flags & IFF_UP) {
+ /* If the interface is up, we may need to fire off
+ * the MII timer. If the interface is down, the
+ * timer will get fired off when the open function
+ * is called.
+ */
+ if (bond->mii_timer.function) {
+ /* The timer's already set up, so fire it off */
+ mod_timer(&bond->mii_timer, jiffies + 1);
+ } else {
+ /* Set up the timer. */
+ init_timer(&bond->mii_timer);
+ bond->mii_timer.expires = jiffies + 1;
+ bond->mii_timer.data =
+ (unsigned long) bond->dev;
+ bond->mii_timer.function =
+ (void *) &bond_mii_monitor;
+ add_timer(&bond->mii_timer);
+ }
+ }
+ }
+out:
+ up_read(&(bonding_rwsem));
+ return ret;
+}
+static CLASS_DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR, bonding_show_miimon, bonding_store_miimon);
+
+/*
+ * Show and set the primary slave. The store function is much
+ * simpler than bonding_store_slaves function because it only needs to
+ * handle one interface name.
+ * The bond must be a mode that supports a primary for this be
+ * set.
+ */
+static ssize_t bonding_show_primary(struct class_device *cd, char *buf)
+{
+ int count = 0;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ if (bond->primary_slave)
+ count = sprintf(buf, "%s\n", bond->primary_slave->dev->name) + 1;
+
+ up_read(&(bonding_rwsem));
+ return count;
+}
+
+static ssize_t bonding_store_primary(struct class_device *cd, const char *buf, size_t count)
+{
+ int i;
+ struct slave *slave;
+ struct bonding *bond = to_bond(cd);
+
+ down_write(&(bonding_rwsem));
+
+ write_lock_bh(&bond->lock);
+ if (!USES_PRIMARY(bond->params.mode)) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Unable to set primary slave; %s is in mode %d\n",
+ bond->dev->name, bond->dev->name, bond->params.mode);
+ } else {
+ bond_for_each_slave(bond, slave, i) {
+ if (strnicmp
+ (slave->dev->name, buf,
+ strlen(slave->dev->name)) == 0) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting %s as primary slave.\n",
+ bond->dev->name, slave->dev->name);
+ bond->primary_slave = slave;
+ bond_select_active_slave(bond);
+ goto out;
+ }
+ }
+
+ /* if we got here, then we didn't match the name of any slave */
+
+ if (strlen(buf) == 0 || buf[0] == '\n') {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting primary slave to None.\n",
+ bond->dev->name);
+ bond->primary_slave = 0;
+ bond_select_active_slave(bond);
+ } else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Unable to set %.*s as primary slave as it is not a slave.\n",
+ bond->dev->name, (int)strlen(buf) - 1, buf);
+ }
+ }
+out:
+ write_unlock_bh(&bond->lock);
+ up_write(&(bonding_rwsem));
+ return count;
+}
+static CLASS_DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary);
+
+/*
+ * Show and set the use_carrier flag.
+ */
+static ssize_t bonding_show_carrier(struct class_device *cd, char *buf)
+{
+ int count;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ count = sprintf(buf, "%d\n", bond->params.use_carrier) + 1;
+ up_read(&(bonding_rwsem));
+ return count;
+}
+
+static ssize_t bonding_store_carrier(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value;
+ struct bonding *bond = to_bond(cd);
+
+ down_write(&(bonding_rwsem));
+
+ sscanf(buf, "%d", &new_value);
+ if ((new_value == 0) || (new_value == 1)) {
+ bond->params.use_carrier = new_value;
+ printk(KERN_INFO DRV_NAME ": %s: Setting use_carrier to %d.\n",
+ bond->dev->name, new_value);
+ } else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Ignoring invalid use_carrier value %d.\n",
+ bond->dev->name, new_value);
+ }
+ up_write(&(bonding_rwsem));
+ return count;
+}
+static CLASS_DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR, bonding_show_carrier, bonding_store_carrier);
+
+
+/*
+ * Show and set currently active_slave.
+ */
+static ssize_t bonding_show_active_slave(struct class_device *cd, char *buf)
+{
+ struct slave *curr;
+ struct bonding *bond = to_bond(cd);
+ int count;
+
+ down_read(&(bonding_rwsem));
+
+ read_lock(&bond->curr_slave_lock);
+ curr = bond->curr_active_slave;
+ read_unlock(&bond->curr_slave_lock);
+
+ if (USES_PRIMARY(bond->params.mode)) {
+ count = sprintf(buf, "%s\n", (curr) ? curr->dev->name : "None") + 1;
+ }
+ else {
+ count = sprintf(buf, "%s\n", "None") + 1;
+ }
+ up_read(&(bonding_rwsem));
+ return count;
+}
+
+static ssize_t bonding_store_active_slave(struct class_device *cd, const char *buf, size_t count)
+{
+ int i;
+ struct slave *slave;
+ struct slave *old_active = NULL;
+ struct slave *new_active = NULL;
+ struct bonding *bond = to_bond(cd);
+
+ down_write(&(bonding_rwsem));
+
+ write_lock_bh(&bond->lock);
+ if (!USES_PRIMARY(bond->params.mode)) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Unable to change active slave; %s is in mode %d\n",
+ bond->dev->name, bond->dev->name, bond->params.mode);
+ } else {
+ bond_for_each_slave(bond, slave, i) {
+ if (strnicmp
+ (slave->dev->name, buf,
+ strlen(slave->dev->name)) == 0) {
+ old_active = bond->curr_active_slave;
+ new_active = slave;
+ if (new_active && (new_active == old_active)) {
+ /* do nothing */
+ printk(KERN_INFO DRV_NAME
+ ": %s: %s is already the current active slave.\n",
+ bond->dev->name, slave->dev->name);
+ goto out;
+ }
+ else {
+ if ((new_active) &&
+ (old_active) &&
+ (new_active->link == BOND_LINK_UP) &&
+ IS_UP(new_active->dev)) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting %s as active slave.\n",
+ bond->dev->name, slave->dev->name);
+ bond_change_active_slave(bond, new_active);
+ }
+ else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Could not set %s as active slave; "
+ "either %s is down or the link is down.\n",
+ bond->dev->name, slave->dev->name,
+ slave->dev->name);
+ }
+ goto out;
+ }
+ }
+ }
+
+ /* if we got here, then we didn't match the name of any slave */
+
+ if (strlen(buf) == 0 || buf[0] == '\n') {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting active slave to None.\n",
+ bond->dev->name);
+ bond->primary_slave = 0;
+ bond_select_active_slave(bond);
+ } else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Unable to set %.*s as active slave as it is not a slave.\n",
+ bond->dev->name, (int)strlen(buf) - 1, buf);
+ }
+ }
+out:
+ write_unlock_bh(&bond->lock);
+ up_write(&(bonding_rwsem));
+ return count;
+
+}
+static CLASS_DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR, bonding_show_active_slave, bonding_store_active_slave);
+
+
+/*
+ * Show link status of the bond interface.
+ */
+static ssize_t bonding_show_mii_status(struct class_device *cd, char *buf)
+{
+ int count;
+ struct slave *curr;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+
+ read_lock(&bond->curr_slave_lock);
+ curr = bond->curr_active_slave;
+ read_unlock(&bond->curr_slave_lock);
+
+ count = sprintf(buf, "%s\n", (curr) ? "up" : "down") + 1;
+ up_read(&(bonding_rwsem));
+ return count;
+}
+static CLASS_DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL);
+
+
+/*
+ * Show current 802.3ad aggregator ID.
+ */
+static ssize_t bonding_show_ad_aggregator(struct class_device *cd, char *buf)
+{
+ int count = 0;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ if (bond->params.mode == BOND_MODE_8023AD) {
+ struct ad_info ad_info;
+ count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.aggregator_id) + 1;
+ }
+ up_read(&(bonding_rwsem));
+ return count;
+}
+static CLASS_DEVICE_ATTR(ad_aggregator, S_IRUGO, bonding_show_ad_aggregator, NULL);
+
+
+/*
+ * Show number of active 802.3ad ports.
+ */
+static ssize_t bonding_show_ad_num_ports(struct class_device *cd, char *buf)
+{
+ int count = 0;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ if (bond->params.mode == BOND_MODE_8023AD) {
+ struct ad_info ad_info;
+ count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0: ad_info.ports) + 1;
+ }
+ up_read(&(bonding_rwsem));
+ return count;
+}
+static CLASS_DEVICE_ATTR(ad_num_ports, S_IRUGO, bonding_show_ad_num_ports, NULL);
+
+
+/*
+ * Show current 802.3ad actor key.
+ */
+static ssize_t bonding_show_ad_actor_key(struct class_device *cd, char *buf)
+{
+ int count = 0;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ if (bond->params.mode == BOND_MODE_8023AD) {
+ struct ad_info ad_info;
+ count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.actor_key) + 1;
+ }
+ up_read(&(bonding_rwsem));
+ return count;
+}
+static CLASS_DEVICE_ATTR(ad_actor_key, S_IRUGO, bonding_show_ad_actor_key, NULL);
+
+
+/*
+ * Show current 802.3ad partner key.
+ */
+static ssize_t bonding_show_ad_partner_key(struct class_device *cd, char *buf)
+{
+ int count = 0;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ if (bond->params.mode == BOND_MODE_8023AD) {
+ struct ad_info ad_info;
+ count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.partner_key) + 1;
+ }
+ up_read(&(bonding_rwsem));
+ return count;
+}
+static CLASS_DEVICE_ATTR(ad_partner_key, S_IRUGO, bonding_show_ad_partner_key, NULL);
+
+
+/*
+ * Show current 802.3ad partner mac.
+ */
+static ssize_t bonding_show_ad_partner_mac(struct class_device *cd, char *buf)
+{
+ int count = 0;
+ struct bonding *bond = to_bond(cd);
+
+ down_read(&(bonding_rwsem));
+ if (bond->params.mode == BOND_MODE_8023AD) {
+ struct ad_info ad_info;
+ if (!bond_3ad_get_active_agg_info(bond, &ad_info)) {
+ count = sprintf(buf,"%02x:%02x:%02x:%02x:%02x:%02x\n",
+ ad_info.partner_system[0],
+ ad_info.partner_system[1],
+ ad_info.partner_system[2],
+ ad_info.partner_system[3],
+ ad_info.partner_system[4],
+ ad_info.partner_system[5]) + 1;
+ }
+ }
+ up_read(&(bonding_rwsem));
+ return count;
+}
+static CLASS_DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);
+
+
+
+static struct attribute *per_bond_attrs[] = {
+ &class_device_attr_slaves.attr,
+ &class_device_attr_mode.attr,
+ &class_device_attr_arp_interval.attr,
+ &class_device_attr_arp_ip_target.attr,
+ &class_device_attr_down_delay.attr,
+ &class_device_attr_up_delay.attr,
+ &class_device_attr_lacp_rate.attr,
+ &class_device_attr_xmit_hash_policy.attr,
+ &class_device_attr_miimon.attr,
+ &class_device_attr_primary.attr,
+ &class_device_attr_use_carrier.attr,
+ &class_device_attr_active_slave.attr,
+ &class_device_attr_mii_status.attr,
+ &class_device_attr_ad_aggregator.attr,
+ &class_device_attr_ad_num_ports.attr,
+ &class_device_attr_ad_actor_key.attr,
+ &class_device_attr_ad_partner_key.attr,
+ &class_device_attr_ad_partner_mac.attr,
+ NULL,
+};
+
+static struct attribute_group bonding_group = {
+ .name = "bonding",
+ .attrs = per_bond_attrs,
+};
+
+/*
+ * Initialize sysfs. This sets up the bonding_masters file in
+ * /sys/class/net.
+ */
+int bond_create_sysfs(void)
+{
+ int ret = 0;
+ struct bonding *firstbond;
+
+ init_rwsem(&bonding_rwsem);
+
+ /* get the netdev class pointer */
+ firstbond = container_of(bond_dev_list.next, struct bonding, bond_list);
+ if (!firstbond)
+ {
+ return -ENODEV;
+
+ }
+ netdev_class = firstbond->dev->class_dev.class;
+ if (!netdev_class)
+ {
+ return -ENODEV;
+ }
+ ret = class_create_file(netdev_class, &class_attr_bonding_masters);
+
+ return ret;
+
+}
+
+/*
+ * Remove /sys/class/net/bonding_masters.
+ */
+void bond_destroy_sysfs(void)
+{
+ if (netdev_class)
+ class_remove_file(netdev_class, &class_attr_bonding_masters);
+}
+
+/*
+ * Initialize sysfs for each bond. This sets up and registers
+ * the 'bondctl' directory for each individual bond under /sys/class/net.
+ */
+int bond_create_sysfs_entry(struct bonding *bond)
+{
+ struct net_device *dev = bond->dev;
+ int err;
+
+ err = sysfs_create_group(&(dev->class_dev.kobj), &bonding_group);
+ if (err) {
+ printk(KERN_EMERG "eek! didn't create group!\n");
+ }
+
+ return err;
+}
+/*
+ * Remove sysfs entries for each bond.
+ */
+void bond_destroy_sysfs_entry(struct bonding *bond)
+{
+ struct net_device *dev = bond->dev;
+
+ sysfs_remove_group(&(dev->class_dev.kobj), &bonding_group);
+}
+
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/Makefile linux-2.6.12post-sysfs/drivers/net/bonding/Makefile
--- linux-2.6.12post/drivers/net/bonding/Makefile 2005-06-17 12:48:29.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/Makefile 2005-06-28 18:22:23.000000000 -0700
@@ -4,5 +4,5 @@
obj-$(CONFIG_BONDING) += bonding.o
-bonding-objs := bond_main.o bond_3ad.o bond_alb.o
+bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o
^ permalink raw reply
* [PATCH 2.6.13-rc1 9/17] bonding: get primary name from slave dev
From: Radheka Godse @ 2005-07-01 20:49 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
This patch fixes a bug in the proc file handler in bonding. The name of
the primary slave was taken from the command-line options, instead of from
the dev structure of the primary slave itself. This caused an incorrect
dispaly if t he primary is set or changed via sysfs.
Signed-off-by: Radheka Godse <radheka.godse@intel.com>
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_main.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c
--- linux-2.6.12post/drivers/net/bonding/bond_main.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c 2005-06-30 13:53:55.000000000 -0700
@@ -3369,8 +3369,8 @@
if (USES_PRIMARY(bond->params.mode)) {
seq_printf(seq, "Primary Slave: %s\n",
- (bond->params.primary[0]) ?
- bond->params.primary : "None");
+ (bond->primary_slave) ?
+ bond->primary_slave->dev->name : "None");
seq_printf(seq, "Currently Active Slave: %s\n",
(curr) ? curr->dev->name : "None");
^ permalink raw reply
* [PATCH 2.6.13-rc1 10/17] bonding: added missing mode descriptions to modinfo
From: Radheka Godse @ 2005-07-01 20:50 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
This patch updates the modinfo description for mode module param to
include all available modes as described in bonding.txt.
Signed-off-by: Radheka Godse <radheka.godse@intel.com>
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_main.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c
--- linux-2.6.12post/drivers/net/bonding/bond_main.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c 2005-06-30 13:53:55.000000000 -0700
@@ -564,17 +564,24 @@
module_param(updelay, int, 0);
MODULE_PARM_DESC(updelay, "Delay before considering link up, in milliseconds");
module_param(downdelay, int, 0);
-MODULE_PARM_DESC(downdelay, "Delay before considering link down, in milliseconds");
+MODULE_PARM_DESC(downdelay, "Delay before considering link down, "
+ "in milliseconds");
module_param(use_carrier, int, 0);
-MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; 0 for off, 1 for on (default)");
+MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; "
+ "0 for off, 1 for on (default)");
module_param(mode, charp, 0);
-MODULE_PARM_DESC(mode, "Mode of operation : 0 for round robin, 1 for active-backup, 2 for xor");
+MODULE_PARM_DESC(mode, "Mode of operation : 0 for balance-rr, "
+ "1 for active-backup, 2 for balance-xor, "
+ "3 for broadcast, 4 for 802.3ad, 5 for balance-tlb, "
+ "6 for balance-alb");
module_param(primary, charp, 0);
MODULE_PARM_DESC(primary, "Primary network device to use");
module_param(lacp_rate, charp, 0);
-MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner (slow/fast)");
+MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner "
+ "(slow/fast)");
module_param(xmit_hash_policy, charp, 0);
-MODULE_PARM_DESC(xmit_hash_policy, "XOR hashing method : 0 for layer 2 (default), 1 for layer 3+4");
+MODULE_PARM_DESC(xmit_hash_policy, "XOR hashing method: 0 for layer 2 (default)"
+ ", 1 for layer 3+4");
module_param(arp_interval, int, 0);
MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");
module_param_array(arp_ip_target, charp, NULL, 0);
^ permalink raw reply
* [PATCH 2.6.13-rc1 11/17] bonding: add driver name to log messages
From: Radheka Godse @ 2005-07-01 20:51 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
Trivial fix to include DRVNAME in logs printed to /var/log/messages
Signed-off-by: Radheka Godse <radheka.godse@intel.com>
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_3ad.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_3ad.c
--- linux-2.6.12post/drivers/net/bonding/bond_3ad.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_3ad.c 2005-06-28 18:21:34.000000000 -0700
@@ -1915,7 +1915,8 @@
struct aggregator *aggregator;
if (bond == NULL) {
- printk(KERN_ERR "The slave %s is not attached to its bond\n", slave->dev->name);
+ printk(KERN_ERR DRV_NAME ": %s: The slave %s is not attached to its bond\n",
+ slave->dev->master->name, slave->dev->name);
return -1;
}
@@ -2085,7 +2086,8 @@
// clear the aggregator
ad_clear_agg(temp_aggregator);
if (select_new_active_agg) {
- printk(KERN_INFO "Removing an active aggregator\n");
+ printk(KERN_INFO DRV_NAME ": %s: Removing an active aggregator\n",
+ slave->dev->master->name);
// select new active aggregator
ad_agg_selection_logic(__get_first_agg(port));
}
@@ -2230,8 +2232,9 @@
// if slave is null, the whole port is not initialized
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": Warning: speed changed for uninitialized port on %s\n",
- slave->dev->name);
+ printk(KERN_WARNING DRV_NAME ": Warning: %s: speed "
+ "changed for uninitialized port on %s\n",
+ slave->dev->master->name, slave->dev->name);
return;
}
@@ -2257,8 +2260,9 @@
// if slave is null, the whole port is not initialized
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": Warning: duplex changed for uninitialized port on %s\n",
- slave->dev->name);
+ printk(KERN_WARNING DRV_NAME ": %s: Warning: duplex changed "
+ "for uninitialized port on %s\n",
+ slave->dev->master->name, slave->dev->name);
return;
}
@@ -2363,7 +2367,8 @@
}
if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
- printk(KERN_DEBUG "ERROR: bond_3ad_get_active_agg_info failed\n");
+ printk(KERN_DEBUG DRV_NAME ": %s: Error: "
+ "bond_3ad_get_active_agg_info failed\n", dev->name);
goto out;
}
@@ -2372,7 +2377,9 @@
if (slaves_in_agg == 0) {
/*the aggregator is empty*/
- printk(KERN_DEBUG "ERROR: active aggregator is empty\n");
+ printk(KERN_DEBUG DRV_NAME ": %s: Error: active "
+ "aggregator is empty\n",
+ dev->name);
goto out;
}
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_main.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c
--- linux-2.6.12post/drivers/net/bonding/bond_main.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c 2005-06-30 13:53:55.000000000 -0700
@@ -1884,10 +1884,10 @@
new_slave->dev->name);
if (bond->params.mode == BOND_MODE_8023AD) {
- printk(KERN_WARNING
- "Operation of 802.3ad mode requires ETHTOOL "
+ printk(KERN_WARNING DRV_NAME
+ ": %s: Warning: Operation of 802.3ad mode requires ETHTOOL "
"support in base driver for proper aggregator "
- "selection.\n");
+ "selection.\n", bond_dev->name);
}
}
@@ -2716,8 +2706,11 @@
break;
default:
/* Should not happen */
- printk(KERN_ERR "bonding: Error: %s Illegal value (link=%d)\n",
- slave->dev->name, slave->link);
+ printk(KERN_ERR DRV_NAME
+ ": %s: Error: %s Illegal value (link=%d)\n",
+ bond_dev->name,
+ slave->dev->name,
+ slave->link);
goto out;
} /* end of switch (slave->link) */
^ permalink raw reply
* [PATCH 2.6.13-rc1 12/17] bonding: prefix bondname to log messages
From: Radheka Godse @ 2005-07-01 20:53 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
This patch adds <bondname>: prefix to logs printed to /var/log/messages to
identify messages on a per bond basis.
Signed-off-by: Radheka Godse <radheka.godse@intel.com>
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_3ad.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_3ad.c
--- linux-2.6.12post/drivers/net/bonding/bond_3ad.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_3ad.c 2005-06-28 18:21:34.000000000 -0700
@@ -1378,8 +1378,9 @@
}
}
if (!curr_port) { // meaning: the port was related to an aggregator but was not on the aggregator port list
- printk(KERN_WARNING DRV_NAME ": Warning: Port %d (on %s) was "
+ printk(KERN_WARNING DRV_NAME ": %s: Warning: Port %d (on %s) was "
"related to aggregator %d but was not on its port list\n",
+ port->slave->dev->master->name,
port->actor_port_number, port->slave->dev->name,
port->aggregator->aggregator_identifier);
}
@@ -1450,7 +1451,8 @@
dprintk("Port %d joined LAG %d(new LAG)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
} else {
- printk(KERN_ERR DRV_NAME ": Port %d (on %s) did not find a suitable aggregator\n",
+ printk(KERN_ERR DRV_NAME ": %s: Port %d (on %s) did not find a suitable aggregator\n",
+ port->slave->dev->master->name,
port->actor_port_number, port->slave->dev->name);
}
}
@@ -1582,8 +1584,9 @@
// check if any partner replys
if (best_aggregator->is_individual) {
- printk(KERN_WARNING DRV_NAME ": Warning: No 802.3ad response from the link partner "
- "for any adapters in the bond\n");
+ printk(KERN_WARNING DRV_NAME ": %s: Warning: No 802.3ad response from "
+ "the link partner for any adapters in the bond\n",
+ best_aggregator->slave->dev->master->name);
}
// check if there are more than one aggregator
@@ -1991,7 +1994,9 @@
// if slave is null, the whole port is not initialized
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": Trying to unbind an uninitialized port on %s\n", slave->dev->name);
+ printk(KERN_WARNING DRV_NAME ": Warning: %s: Trying to "
+ "unbind an uninitialized port on %s\n",
+ slave->dev->master->name, slave->dev->name);
return;
}
@@ -2022,7 +2027,8 @@
dprintk("Some port(s) related to LAG %d - replaceing with LAG %d\n", aggregator->aggregator_identifier, new_aggregator->aggregator_identifier);
if ((new_aggregator->lag_ports == port) && new_aggregator->is_active) {
- printk(KERN_INFO DRV_NAME ": Removing an active aggregator\n");
+ printk(KERN_INFO DRV_NAME ": %s: Removing an active aggregator\n",
+ aggregator->slave->dev->master->name);
// select new active aggregator
select_new_active_agg = 1;
}
@@ -2052,15 +2058,17 @@
ad_agg_selection_logic(__get_first_agg(port));
}
} else {
- printk(KERN_WARNING DRV_NAME ": Warning: unbinding aggregator, "
- "and could not find a new aggregator for its ports\n");
+ printk(KERN_WARNING DRV_NAME ": %s: Warning: unbinding aggregator, "
+ "and could not find a new aggregator for its ports\n",
+ slave->dev->master->name);
}
} else { // in case that the only port related to this aggregator is the one we want to remove
select_new_active_agg = aggregator->is_active;
// clear the aggregator
ad_clear_agg(aggregator);
if (select_new_active_agg) {
- printk(KERN_INFO "Removing an active aggregator\n");
+ printk(KERN_INFO DRV_NAME ": %s: Removing an active aggregator\n",
+ slave->dev->master->name);
// select new active aggregator
ad_agg_selection_logic(__get_first_agg(port));
}
@@ -2133,7 +2141,8 @@
// select the active aggregator for the bond
if ((port = __get_first_port(bond))) {
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": Warning: bond's first port is uninitialized\n");
+ printk(KERN_WARNING DRV_NAME ": %s: Warning: bond's first port is "
+ "uninitialized\n", bond->dev->name);
goto re_arm;
}
@@ -2145,7 +2154,8 @@
// for each port run the state machines
for (port = __get_first_port(bond); port; port = __get_next_port(port)) {
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": Warning: Found an uninitialized port\n");
+ printk(KERN_WARNING DRV_NAME ": %s: Warning: Found an uninitialized "
+ "port\n", bond->dev->name);
goto re_arm;
}
@@ -2186,7 +2196,8 @@
port = &(SLAVE_AD_INFO(slave).port);
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": Warning: port of slave %s is uninitialized\n", slave->dev->name);
+ printk(KERN_WARNING DRV_NAME ": %s: Warning: port of slave %s is "
+ "uninitialized\n", slave->dev->name, slave->dev->master->name);
return;
}
@@ -2289,8 +2300,9 @@
// if slave is null, the whole port is not initialized
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": Warning: link status changed for uninitialized port on %s\n",
- slave->dev->name);
+ printk(KERN_WARNING DRV_NAME ": Warning: %s: link status changed for "
+ "uninitialized port on %s\n",
+ slave->dev->master->name, slave->dev->name);
return;
}
@@ -2397,7 +2409,8 @@
}
if (slave_agg_no >= 0) {
- printk(KERN_ERR DRV_NAME ": Error: Couldn't find a slave to tx on for aggregator ID %d\n", agg_id);
+ printk(KERN_ERR DRV_NAME ": %s: Error: Couldn't find a slave to tx on "
+ "for aggregator ID %d\n", dev->name, agg_id);
goto out;
}
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_alb.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_alb.c
--- linux-2.6.12post/drivers/net/bonding/bond_alb.c 2005-06-17 12:48:29.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_alb.c 2005-06-28 18:21:35.000000000 -0700
@@ -515,7 +515,8 @@
client_info->mac_dst);
if (!skb) {
printk(KERN_ERR DRV_NAME
- ": Error: failed to create an ARP packet\n");
+ ": %s: Error: failed to create an ARP packet\n",
+ client_info->slave->dev->master->name);
continue;
}
@@ -525,7 +526,8 @@
skb = vlan_put_tag(skb, client_info->vlan_id);
if (!skb) {
printk(KERN_ERR DRV_NAME
- ": Error: failed to insert VLAN tag\n");
+ ": %s: Error: failed to insert VLAN tag\n",
+ client_info->slave->dev->master->name);
continue;
}
}
@@ -608,8 +610,9 @@
if (!client_info->slave) {
printk(KERN_ERR DRV_NAME
- ": Error: found a client with no channel in "
- "the client's hash table\n");
+ ": %s: Error: found a client with no channel in "
+ "the client's hash table\n",
+ bond->dev->name);
continue;
}
/*update all clients using this src_ip, that are not assigned
@@ -930,7 +933,8 @@
skb = vlan_put_tag(skb, vlan->vlan_id);
if (!skb) {
printk(KERN_ERR DRV_NAME
- ": Error: failed to insert VLAN tag\n");
+ ": %s: Error: failed to insert VLAN tag\n",
+ bond->dev->name);
continue;
}
}
@@ -959,11 +963,11 @@
s_addr.sa_family = dev->type;
if (dev_set_mac_address(dev, &s_addr)) {
printk(KERN_ERR DRV_NAME
- ": Error: dev_set_mac_address of dev %s failed! ALB "
+ ": %s: Error: dev_set_mac_address of dev %s failed! ALB "
"mode requires that the base driver support setting "
"the hw address also when the network device's "
"interface is open\n",
- dev->name);
+ dev->master->name, dev->name);
return -EOPNOTSUPP;
}
return 0;
@@ -1113,9 +1117,9 @@
* of the new slave
*/
printk(KERN_ERR DRV_NAME
- ": Error: the hw address of slave %s is not "
+ ": %s: Error: the hw address of slave %s is not "
"unique - cannot enslave it!",
- slave->dev->name);
+ bond->dev->name, slave->dev->name);
return -EINVAL;
}
@@ -1161,16 +1165,16 @@
bond->alb_info.rlb_enabled);
printk(KERN_WARNING DRV_NAME
- ": Warning: the hw address of slave %s is in use by "
+ ": %s: Warning: the hw address of slave %s is in use by "
"the bond; giving it the hw address of %s\n",
- slave->dev->name, free_mac_slave->dev->name);
+ bond->dev->name, slave->dev->name, free_mac_slave->dev->name);
} else if (has_bond_addr) {
printk(KERN_ERR DRV_NAME
- ": Error: the hw address of slave %s is in use by the "
+ ": %s: Error: the hw address of slave %s is in use by the "
"bond; couldn't find a slave with a free hw address to "
"give it (this should not have happened)\n",
- slave->dev->name);
+ bond->dev->name, slave->dev->name);
return -EFAULT;
}
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_main.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c
--- linux-2.6.12post/drivers/net/bonding/bond_main.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c 2005-06-30 13:53:55.000000000 -0700
@@ -1621,8 +1621,8 @@
if (slave_dev->do_ioctl == NULL) {
printk(KERN_WARNING DRV_NAME
- ": Warning : no link monitoring support for %s\n",
- slave_dev->name);
+ ": %s: Warning: no link monitoring support for %s\n",
+ bond_dev->name, slave_dev->name);
}
/* bond must be initialized by bond_open() before enslaving */
@@ -1643,17 +1643,17 @@
dprintk("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
if (!list_empty(&bond->vlan_list)) {
printk(KERN_ERR DRV_NAME
- ": Error: cannot enslave VLAN "
+ ": %s: Error: cannot enslave VLAN "
"challenged slave %s on VLAN enabled "
- "bond %s\n", slave_dev->name,
+ "bond %s\n", bond_dev->name, slave_dev->name,
bond_dev->name);
return -EPERM;
} else {
printk(KERN_WARNING DRV_NAME
- ": Warning: enslaved VLAN challenged "
+ ": %s: Warning: enslaved VLAN challenged "
"slave %s. Adding VLANs will be blocked as "
"long as %s is part of bond %s\n",
- slave_dev->name, slave_dev->name,
+ bond_dev->name, slave_dev->name, slave_dev->name,
bond_dev->name);
bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
}
@@ -1705,8 +1705,8 @@
*/
if (!(slave_dev->flags & IFF_UP)) {
printk(KERN_ERR DRV_NAME
- ": Error: %s is not running\n",
- slave_dev->name);
+ ": %s: Error: %s is not running\n",
+ bond_dev->name, slave_dev->name);
res = -EINVAL;
goto err_undo_flags;
}
@@ -1715,9 +1715,9 @@
(bond->params.mode == BOND_MODE_TLB) ||
(bond->params.mode == BOND_MODE_ALB)) {
printk(KERN_ERR DRV_NAME
- ": Error: to use %s mode, you must upgrade "
+ ": %s: Error: to use %s mode, you must upgrade "
"ifenslave.\n",
- bond_mode_name(bond->params.mode));
+ bond_dev->name, bond_mode_name(bond->params.mode));
res = -EOPNOTSUPP;
goto err_undo_flags;
}
@@ -1838,21 +1838,21 @@
* the messages for netif_carrier.
*/
printk(KERN_WARNING DRV_NAME
- ": Warning: MII and ETHTOOL support not "
+ ": %s: Warning: MII and ETHTOOL support not "
"available for interface %s, and "
"arp_interval/arp_ip_target module parameters "
"not specified, thus bonding will not detect "
"link failures! see bonding.txt for details.\n",
- slave_dev->name);
+ bond_dev->name, slave_dev->name);
} else if (link_reporting == -1) {
/* unable get link status using mii/ethtool */
printk(KERN_WARNING DRV_NAME
- ": Warning: can't get link status from "
+ ": %s: Warning: can't get link status from "
"interface %s; the network driver associated "
"with this interface does not support MII or "
"ETHTOOL link status reporting, thus miimon "
"has no effect on this interface.\n",
- slave_dev->name);
+ bond_dev->name, slave_dev->name);
}
}
@@ -1879,9 +1894,9 @@
if (bond_update_speed_duplex(new_slave) &&
(new_slave->link != BOND_LINK_DOWN)) {
printk(KERN_WARNING DRV_NAME
- ": Warning: failed to get speed and duplex from %s, "
+ ": %s: Warning: failed to get speed and duplex from %s, "
"assumed to be 100Mb/sec and Full.\n",
- new_slave->dev->name);
+ bond_dev->name, new_slave->dev->name);
if (bond->params.mode == BOND_MODE_8023AD) {
printk(KERN_WARNING DRV_NAME
@@ -2080,11 +2080,12 @@
ETH_ALEN);
if (!mac_addr_differ && (bond->slave_cnt > 1)) {
printk(KERN_WARNING DRV_NAME
- ": Warning: the permanent HWaddr of %s "
+ ": %s: Warning: the permanent HWaddr of %s "
"- %02X:%02X:%02X:%02X:%02X:%02X - is "
"still in use by %s. Set the HWaddr of "
"%s to a different address to avoid "
"conflicts.\n",
+ bond_dev->name,
slave_dev->name,
slave->perm_hwaddr[0],
slave->perm_hwaddr[1],
@@ -2158,19 +2168,20 @@
bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
} else {
printk(KERN_WARNING DRV_NAME
- ": Warning: clearing HW address of %s while it "
+ ": %s: Warning: clearing HW address of %s while it "
"still has VLANs.\n",
- bond_dev->name);
+ bond_dev->name, bond_dev->name);
printk(KERN_WARNING DRV_NAME
- ": When re-adding slaves, make sure the bond's "
- "HW address matches its VLANs'.\n");
+ ": %s: When re-adding slaves, make sure the bond's "
+ "HW address matches its VLANs'.\n",
+ bond_dev->name);
}
} else if ((bond_dev->features & NETIF_F_VLAN_CHALLENGED) &&
!bond_has_challenged_slaves(bond)) {
printk(KERN_INFO DRV_NAME
- ": last VLAN challenged slave %s "
+ ": %s: last VLAN challenged slave %s "
"left bond %s. VLAN blocking is removed\n",
- slave_dev->name, bond_dev->name);
+ bond_dev->name, slave_dev->name, bond_dev->name);
bond_dev->features &= ~NETIF_F_VLAN_CHALLENGED;
}
@@ -2327,12 +2329,13 @@
bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
} else {
printk(KERN_WARNING DRV_NAME
- ": Warning: clearing HW address of %s while it "
+ ": %s: Warning: clearing HW address of %s while it "
"still has VLANs.\n",
- bond_dev->name);
+ bond_dev->name, bond_dev->name);
printk(KERN_WARNING DRV_NAME
- ": When re-adding slaves, make sure the bond's "
- "HW address matches its VLANs'.\n");
+ ": %s: When re-adding slaves, make sure the bond's "
+ "HW address matches its VLANs'.\n",
+ bond_dev->name);
}
printk(KERN_INFO DRV_NAME
@@ -2424,8 +2427,9 @@
&endptr, 0);
if (*endptr) {
printk(KERN_ERR DRV_NAME
- ": Error: got invalid ABI "
- "version from application\n");
+ ": %s: Error: got invalid ABI "
+ "version from application\n",
+ bond_dev->name);
return -EINVAL;
}
@@ -4496,8 +4500,9 @@
struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
if (!skb2) {
printk(KERN_ERR DRV_NAME
- ": Error: bond_xmit_broadcast(): "
- "skb_clone() failed\n");
+ ": %s: Error: bond_xmit_broadcast(): "
+ "skb_clone() failed\n",
+ bond_dev->name);
continue;
}
@@ -4566,7 +4571,8 @@
default:
/* Should never happen, mode already checked */
printk(KERN_ERR DRV_NAME
- ": Error: Unknown bonding mode %d\n",
+ ": %s: Error: Unknown bonding mode %d\n",
+ bond_dev->name,
mode);
break;
}
^ permalink raw reply
* [PATCH 2.6.13-rc1 13/17] bonding: make error messages more consistent
From: Radheka Godse @ 2005-07-01 20:53 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
This patch attempts to make error reporting more consistent, removes/adds
newlines as appropriate, adds bonding: <bondname>: prefix if missing
(especially in alb, ad) messages.
Signed-off-by: Radheka Godse <radheka.godse@intel.com>
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_3ad.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_3ad.c
--- linux-2.6.12post/drivers/net/bonding/bond_3ad.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_3ad.c 2005-06-28 18:21:34.000000000 -0700
@@ -1198,10 +1198,10 @@
// detect loopback situation
if (!MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->actor_system))) {
// INFO_RECEIVED_LOOPBACK_FRAMES
- printk(KERN_ERR DRV_NAME ": An illegal loopback occurred on adapter (%s)\n",
- port->slave->dev->name);
- printk(KERN_ERR "Check the configuration to verify that all Adapters "
- "are connected to 802.3ad compliant switch ports\n");
+ printk(KERN_ERR DRV_NAME ": %s: An illegal loopback occurred on "
+ "adapter (%s). Check the configuration to verify that all "
+ "Adapters are connected to 802.3ad compliant switch ports\n",
+ port->slave->dev->master->name, port->slave->dev->name);
__release_rx_machine_lock(port);
return;
}
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_alb.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_alb.c
--- linux-2.6.12post/drivers/net/bonding/bond_alb.c 2005-06-17 12:48:29.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_alb.c 2005-06-28 18:21:35.000000000 -0700
@@ -206,7 +206,7 @@
new_hashtbl = kmalloc(size, GFP_KERNEL);
if (!new_hashtbl) {
printk(KERN_ERR DRV_NAME
- ": Error: %s: Failed to allocate TLB hash table\n",
+ ": %s: Error: Failed to allocate TLB hash table\n",
bond->dev->name);
return -1;
}
@@ -811,7 +798,7 @@
new_hashtbl = kmalloc(size, GFP_KERNEL);
if (!new_hashtbl) {
printk(KERN_ERR DRV_NAME
- ": Error: %s: Failed to allocate RLB hash table\n",
+ ": %s: Error: Failed to allocate RLB hash table\n",
bond->dev->name);
return -1;
}
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_main.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c
--- linux-2.6.12post/drivers/net/bonding/bond_main.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c 2005-06-30 13:53:55.000000000 -0700
@@ -919,7 +919,7 @@
res = bond_add_vlan(bond, vid);
if (res) {
printk(KERN_ERR DRV_NAME
- ": %s: Failed to add vlan id %d\n",
+ ": %s: Error: Failed to add vlan id %d\n",
bond_dev->name, vid);
}
}
@@ -953,7 +953,7 @@
res = bond_del_vlan(bond, vid);
if (res) {
printk(KERN_ERR DRV_NAME
- ": %s: Failed to remove vlan id %d\n",
+ ": %s: Error: Failed to remove vlan id %d\n",
bond_dev->name, vid);
}
}
@@ -1690,11 +1698,10 @@
if (slave_dev->set_mac_address == NULL) {
printk(KERN_ERR DRV_NAME
- ": Error: The slave device you specified does "
- "not support setting the MAC address.\n");
- printk(KERN_ERR
+ ": %s: Error: The slave device you specified does "
+ "not support setting the MAC address. "
"Your kernel likely does not support slave "
- "devices.\n");
+ "devices.\n", bond_dev->name);
res = -EOPNOTSUPP;
goto err_undo_flags;
@@ -2059,7 +2058,7 @@
if (!(slave_dev->flags & IFF_SLAVE) ||
(slave_dev->master != bond_dev)) {
printk(KERN_ERR DRV_NAME
- ": Error: %s: cannot release %s.\n",
+ ": %s: Error: cannot release %s.\n",
bond_dev->name, slave_dev->name);
return -EINVAL;
}
@@ -4758,7 +4757,7 @@
if (max_bonds < 1 || max_bonds > INT_MAX) {
printk(KERN_WARNING DRV_NAME
": Warning: max_bonds (%d) not in range %d-%d, so it "
- "was reset to BOND_DEFAULT_MAX_BONDS (%d)",
+ "was reset to BOND_DEFAULT_MAX_BONDS (%d)\n",
max_bonds, 1, INT_MAX, BOND_DEFAULT_MAX_BONDS);
max_bonds = BOND_DEFAULT_MAX_BONDS;
}
^ permalink raw reply
* [PATCH 2.6.13-rc1 14/17] bonding: spelling and whitespace correction
From: Radheka Godse @ 2005-07-01 20:55 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
Trivial patch to fix spelling errors and some white spaces changes for
readabilitiy.
Signed-off-by: Radheka Godse <radheka.godse@intel.com>
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_alb.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_alb.c
--- linux-2.6.12post/drivers/net/bonding/bond_alb.c 2005-06-17 12:48:29.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_alb.c 2005-06-28 18:21:35.000000000 -0700
@@ -1423,7 +1423,7 @@
read_lock(&bond->curr_slave_lock);
bond_for_each_slave(bond, slave, i) {
- alb_send_learning_packets(slave,slave->dev->dev_addr);
+ alb_send_learning_packets(slave, slave->dev->dev_addr);
}
read_unlock(&bond->curr_slave_lock);
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bonding.h linux-2.6.12post-sysfs/drivers/net/bonding/bonding.h
--- linux-2.6.12post/drivers/net/bonding/bonding.h 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bonding.h 2005-06-30 13:58:27.000000000 -0700
@@ -165,7 +165,7 @@
};
struct slave {
- struct net_device *dev; /* first - usefull for panic debug */
+ struct net_device *dev; /* first - useful for panic debug */
struct slave *next;
struct slave *prev;
s16 delay;
@@ -191,7 +191,7 @@
* beforehand.
*/
struct bonding {
- struct net_device *dev; /* first - usefull for panic debug */
+ struct net_device *dev; /* first - useful for panic debug */
struct slave *first_slave;
struct slave *curr_active_slave;
struct slave *current_arp_slave;
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_main.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c
--- linux-2.6.12post/drivers/net/bonding/bond_main.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c 2005-06-30 13:53:55.000000000 -0700
@@ -2117,7 +2117,6 @@
/* release the slave from its bond */
bond_detach_slave(bond, slave);
-
if (bond->primary_slave == slave) {
bond->primary_slave = NULL;
}
@@ -2436,7 +2435,6 @@
if (orig_app_abi_ver == -1) {
orig_app_abi_ver = new_abi_ver;
}
-
app_abi_ver = new_abi_ver;
}
@@ -4226,6 +4224,7 @@
bond_for_each_slave(bond, slave, i) {
dprintk("s %p s->p %p c_m %p\n", slave,
slave->prev, slave->dev->change_mtu);
+
res = dev_set_mtu(slave->dev, new_mtu);
if (res) {
@@ -4623,7 +4622,7 @@
*/
bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
- /* don't acquire bond device's xmit_lock when
+ /* don't acquire bond device's xmit_lock when
* transmitting */
bond_dev->features |= NETIF_F_LLTX;
@@ -5035,7 +4976,6 @@
#ifdef CONFIG_PROC_FS
bond_create_proc_dir();
#endif
-
for (i = 0; i < max_bonds; i++) {
sprintf(new_bond_name, "bond%d",i);
res = bond_create(new_bond_name,&bonding_defaults, NULL);
^ permalink raw reply
* [PATCH 2.6.13-rc1 15/17] bonding: include ARP and Xmit Hash Policy information in /proc file
From: Radheka Godse @ 2005-07-01 21:08 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
For bonds configured to do ARP monitoring, this patch displays polling
interval and ip targets info in their respective proc files.
For balance-XOR and 802.3ad modes, this patch displays Xmit Hash Policy.
Signed-off-by: Radheka Godse <radheka.godse@intel.com>
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_main.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c
--- linux-2.6.12post/drivers/net/bonding/bond_main.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c 2005-06-30 13:53:55.000000000 -0700
@@ -3370,6 +3370,8 @@
{
struct bonding *bond = seq->private;
struct slave *curr;
+ int i;
+ u32 target;
read_lock(&bond->curr_slave_lock);
curr = bond->curr_active_slave;
@@ -3378,6 +3366,13 @@
seq_printf(seq, "Bonding Mode: %s\n",
bond_mode_name(bond->params.mode));
+ if (bond->params.mode == BOND_MODE_XOR ||
+ bond->params.mode == BOND_MODE_8023AD) {
+ seq_printf(seq, "Transmit Hash Policy: %s (%d)\n",
+ xmit_hashtype_tbl[bond->params.xmit_policy].modename,
+ bond->params.xmit_policy);
+ }
+
if (USES_PRIMARY(bond->params.mode)) {
seq_printf(seq, "Primary Slave: %s\n",
(bond->primary_slave) ?
@@ -3394,6 +3403,24 @@
seq_printf(seq, "Down Delay (ms): %d\n",
bond->params.downdelay * bond->params.miimon);
+
+ // ARP information
+ if(bond->params.arp_interval > 0) {
+ seq_printf(seq, "ARP Polling Interval (ms): %d\n",
+ bond->params.arp_interval);
+
+ seq_printf(seq, "ARP IP target/s (n.n.n.n form):");
+
+ for(i = 0; (i < BOND_MAX_ARP_TARGETS) && bond->params.arp_targets[i] ;i++) {
+ target = ntohl(bond->params.arp_targets[i]);
+ seq_printf(seq, " %d.%d.%d.%d", HIPQUAD(target));
+ if((i+1 < BOND_MAX_ARP_TARGETS) && bond->params.arp_targets[i+1])
+ seq_printf(seq, ",");
+ else
+ seq_printf(seq, "\n");
+ }
+ }
+
if (bond->params.mode == BOND_MODE_8023AD) {
struct ad_info ad_info;
^ permalink raw reply
* [PATCH 2.6.13-rc1 16/17] bonding: version, date and log update
From: Radheka Godse @ 2005-07-01 21:10 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
This patch updates the bonding version number and adds a few entries to
the change log in bond_main. The major version number is changed to 3
because of the sysfs interface.
Signed-off-by: Radheka Godse <radheka.godse@intel.com>
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bonding.h linux-2.6.12post-sysfs/drivers/net/bonding/bonding.h
--- linux-2.6.12post/drivers/net/bonding/bonding.h 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bonding.h 2005-06-30 13:58:27.000000000 -0700
@@ -29,6 +29,10 @@
* 2005/05/05 - Jason Gabler <jygabler at lbl dot gov>
* - added "xmit_policy" kernel parameter for alternate hashing policy
* support for mode 2
+ *
+ * 2005/06/21 - Mitch Williams <mitch.a.williams at intel dot com>
+ * Radheka Godse <radheka.godse at intel dot com>
+ * - Added bonding sysfs interface
*/
#ifndef _LINUX_BONDING_H
@@ -41,8 +37,8 @@
#include "bond_3ad.h"
#include "bond_alb.h"
-#define DRV_VERSION "2.6.3"
-#define DRV_RELDATE "June 8, 2005"
+#define DRV_VERSION "3.0.0"
+#define DRV_RELDATE "June 28, 2005"
#define DRV_NAME "bonding"
#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_main.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c
--- linux-2.6.12post/drivers/net/bonding/bond_main.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c 2005-06-30 13:53:55.000000000 -0700
@@ -487,7 +487,36 @@
* * Added xmit_hash_policy_layer34()
* - Modified by Jay Vosburgh <fubar@us.ibm.com> to also support mode 4.
* Set version to 2.6.3.
- */
+ * 2005/06/24 - Mitch Williams <mitch.a.williams at intel dot com>
+ * - Radheka Godse <radheka.godse at intel dot com>
+ * - Added bonding sysfs interface
+ *
+ * - pre-work:
+ * - Split out bond creation code to allow for future addition of
+ * sysfs interface.
+ * - Added extra optional parameter to bond_enslave to return a
+ * a pointer to the new slave. This will be used by future
+ * sysfs functionality.
+ * - Removed static declaration on some functions and data items.
+ *
+ * - Added sysfs support, including capability to add/remove/change
+ * any bond at runtime.
+ *
+ * - Miscellaneous:
+ * - Added bonding: <bondname>: prefix to sysfs log messages
+ * - added arp_ip_targets to /proc entry
+ * - trivial fix: added missing modes description to modinfo
+ * - Corrected bug in ALB init where kmalloc is called inside
+ * a held lock
+ * - Corrected behavior to maintain bond link when changing
+ * from arp monitor to miimon and vice versa
+ * - Added missing bonding: <bondname>: prefix to alb, ad log messages
+ * - Fixed stack dump warnings seen if changing between miimon
+ * and arp monitoring when the bond interface is down.
+ * - Fixed stack dump warnings seen when enslaving an e100
+ * driver
+ * Set version to 3.0.0
+*/
//#define BONDING_DEBUG 1
^ permalink raw reply
* [PATCH 2.6.13-rc1 17/17] bonding: Optimization to read MII only when link status has changed.
From: Radheka Godse @ 2005-07-01 21:14 UTC (permalink / raw)
To: fubar, bonding-devel; +Cc: netdev
Enhanced bond_mii_monitor fn: to read MII only when link status has
changed for an enslaved adapter.
Signed-off-by: Radheka Godse <radheka.godse@intel.com>
diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bond_main.c linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c
--- linux-2.6.12post/drivers/net/bonding/bond_main.c 2005-06-28 18:18:03.000000000 -0700
+++ linux-2.6.12post-sysfs/drivers/net/bonding/bond_main.c 2005-06-30 13:53:55.000000000 -0700
@@ -2652,6 +2652,7 @@
if (slave == oldcurrent) {
do_failover = 1;
}
+ bond_update_speed_duplex(slave);
} else {
slave->delay--;
}
@@ -2742,6 +2675,7 @@
} else {
slave->delay--;
}
+ bond_update_speed_duplex(slave);
}
break;
default:
@@ -2754,8 +2675,6 @@
goto out;
} /* end of switch (slave->link) */
- bond_update_speed_duplex(slave);
-
if (bond->params.mode == BOND_MODE_8023AD) {
if (old_speed != slave->speed) {
bond_3ad_adapter_speed_changed(slave);
~
^ permalink raw reply
* [rfc | patch 0/6] netpoll: add support for the bonding driver
From: Jeff Moyer @ 2005-07-01 23:05 UTC (permalink / raw)
To: mpm; +Cc: netdev, linux-kernel
Hi,
The following patch series provides netpoll support for the bonding driver.
The best way to describe the approach taken is to walk through how it
works. We'll use netconsole as our example.
Netconsole registers a console, and so release_console_sem will trigger the
write_msg implementation in netconsole.ko. This, in turn, calls
netpoll_send_udp. netpoll_send_udp will then call netpoll_send_skb, which
then calls into the network drivers hard_start_xmit routine. It is
important to note that netpoll_send_skb takes care to not call the
hard_start_xmit routine if netif_queue_stopped(dev) returns true. In this
case, it instead calls netpoll_poll, to hopefully free up some tx
descriptors. After this is done, and the queue is woken up, the
hard_start_xmit routine can and will be called.
For all network drivers up to this point, this was the end of the line.
Netpoll would no longer have to be concerned with the skb. It will be
sent off to the network by the driver. However, this is not the case with
the bonding driver.
In the case of the bonding driver, we have now called its hard_start_xmit
routine, which can be one of many, depending on the configured bonging_mode
(specified at module load time). For all of my testing, I have used
dynamic link aggregation (802.3ad). So, in this case, we will call
bond_3ad_xmit_xor. In all cases, the hard_start_xmit routine selects the
proper slave device over which to send the packet, and fills in the
skb->dev pointer to point at that device. Then, they all send the skb off
to bond_dev_queue_xmit.
bond_dev_queue_xmit will then send the skb off to the networking layer via
dev_queue_xmit. dev_queue_xmit is then responsible for calling the
underlying network device's hard_start_xmit routine. Note that
dev_queue_xmit cannot be called with interrupts disabled.
And so, we bring our discussion back to netpoll. In the case of netpoll,
we cannot have the bonding driver call into dev_queue_xmit. For
netconsole, we have disabled irqs before calling netpoll_send_skb (and we
may even be called from interrupt context, in the case of sysrq-X). This
is not the only problem with allowing the bonding driver to call
dev_queue_xmit. We also have to deal with the fact that the underlying
network device may not be ready to send. As in the case described above,
we may be short on tx descriptors. In such a case, we need to be able to
call the driver's poll_controller routine to clear them out. And so, we
have to modify bond_dev_queue_xmit to call *back* into the netpoll code.
The call chain will look something like this:
printk
release_console_sem
call_console_drivers
write_msg
netpoll_send_udp <----- skb->dev points to bond0
netpoll_send_skb
bond_3ad_xmit_xor
bond_dev_queue_xmit
netpoll_send_skb <------ skb->dev now points to real_dev
(may have to call dev->poll_controller, and perform a
napi poll here)
dev->hard_start_xmit
I wrote a test module to exercise the receive code path, as well. The
module registers a struct netpoll with an rx_hook. It then responds to
each packet it receives with a "PONG". For this case, our call path now
looks as follows:
net_rx
dev->poll
netif_receive_skb
netpoll_rx
__netpoll_rx
module_rx_routine
netpoll_send_udp
netpoll_send_skb <-- skb->dev points at bond0
bond_3ad_xmit_xor
bond_dev_queue_xmit
netpoll_send_skb <-- skb->dev points at real_dev
And here it gets tricky. If we are sending out over the same interface
on which the packet arrived, then we will have to either queue the packet,
or drop it. This functionality is already implemented in netpoll, so if we
filled in our queue routine to point at netpoll_queue, then at this point
we will call that via the ->drop pointer in our netpoll structure. So,
continuing along, we have:
netpoll_queue
schedule_work
and we are done. If the packet was schedule to head out a different
device, then we would continue with the send path:
dev->hard_start_xmit
New netpoll function implemented by the network drivers:
net_device->netpoll_setup
This is required, since the bonding device has to walk through each slave
and point its slave_dev->npinfo at the npinfo for the master device. The
reason for this is so that when we're doing the napi polling, we can set
the rx_flags appropriately.
net_device->netpoll_start_xmit
This routine is required since, otherwise, there is no way to intercept
packets bound for interfaces that are not ready for them. Of course, it
requires further logic in the bonding driver to then call into the
netpoll_send_skb routine (which is a new export).
Note that neither of these pointers has to be filled in by the driver.
These functions should only be implemented where needed, and to date, that
is only in the bonding driver.
Newly exported are:
netpoll_send_skb
This is exported so that the bonding driver can queue a packet to be sent
via the real ethernet device it has chosen.
netpoll_poll_dev
This is a new routine that was created and exported so that the
poll_controller implementation in the bonding driver could poll each of
the underlying real devices without duplicating all of the logic that
exists internally to netpoll already.
To test this, as I mentioned above, I wrote a simple module which, upon
receipt of any packet, sends out a packet with the message "PONG". I fired
up netcat to send test packets, and receive the responses. I also loaded
the netconsole module for the very same interface, bond0, and issue a
series of sysrq-X's, both via sysrq-trigger and via the keyboard. I did
this while simultaneously testing the PING server on an SMP machine. As
things stand, it is very stable in my environment.
And so, the patch set follows. Any and all comments are appreciated.
Thanks,
Jeff
^ permalink raw reply
* Re: [rfc | patch 0/6] netpoll: add support for the bonding driver
From: Jeff Moyer @ 2005-07-01 23:06 UTC (permalink / raw)
To: mpm, netdev, linux-kernel
In-Reply-To: <17093.52306.136742.190912@segfault.boston.redhat.com>
Initialize npinfo->rx_flags. The way it stands now, this will have random
garbage, and so will incur a locking penalty even when an rx_hook isn't
registered and we are not active in the netpoll polling code.
Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
---
--- linux-2.6.12/net/core/netpoll.c.orig 2005-07-01 14:02:56.039174635 -0400
+++ linux-2.6.12/net/core/netpoll.c 2005-07-01 14:03:16.688739508 -0400
@@ -639,6 +639,7 @@ int netpoll_setup(struct netpoll *np)
if (!npinfo)
goto release;
+ npinfo->rx_flags = 0;
npinfo->rx_np = NULL;
npinfo->poll_lock = SPIN_LOCK_UNLOCKED;
npinfo->poll_owner = -1;
^ permalink raw reply
* Re: [rfc | patch 0/6] netpoll: add support for the bonding driver
From: Jeff Moyer @ 2005-07-01 23:06 UTC (permalink / raw)
To: mpm, netdev, linux-kernel
In-Reply-To: <17093.52306.136742.190912@segfault.boston.redhat.com>
Move the poll_lock and poll_owner to the struct net_device. This change is
important for the bonding driver support, as multiple real devices will
point at the same netpoll_info. In such cases, we would be artificially
limiting ourselves to calling the polling routine of only one member of a
bond at a time.
To understand how this benefits the bonding driver, let's consider a
netpoll client that sends packets in response to receiving packets. Let's
assume a packet comes in on eth0, and the response is to be delivered over
eth1. If the poll_lock lived in the npinfo (and hence, there was only one
per bond), then we would have to queue the packet. With this patch in
place, we can send the outbound packet immediately.
Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
---
--- linux-2.6.12/net/core/netpoll.c.orig 2005-07-01 14:52:11.932101811 -0400
+++ linux-2.6.12/net/core/netpoll.c 2005-07-01 14:53:59.322183590 -0400
@@ -131,19 +131,20 @@ static int checksum_udp(struct sk_buff *
static void poll_napi(struct netpoll *np)
{
struct netpoll_info *npinfo = np->dev->npinfo;
+ struct net_device *dev = np->dev;
int budget = 16;
- if (test_bit(__LINK_STATE_RX_SCHED, &np->dev->state) &&
- npinfo->poll_owner != smp_processor_id() &&
- spin_trylock(&npinfo->poll_lock)) {
+ if (test_bit(__LINK_STATE_RX_SCHED, &dev->state) &&
+ dev->poll_owner != smp_processor_id() &&
+ spin_trylock(&dev->poll_lock)) {
npinfo->rx_flags |= NETPOLL_RX_DROP;
atomic_inc(&trapped);
- np->dev->poll(np->dev, &budget);
+ dev->poll(dev, &budget);
atomic_dec(&trapped);
npinfo->rx_flags &= ~NETPOLL_RX_DROP;
- spin_unlock(&npinfo->poll_lock);
+ spin_unlock(&dev->poll_lock);
}
}
@@ -246,7 +247,6 @@ repeat:
static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
{
int status;
- struct netpoll_info *npinfo;
repeat:
if(!np || !np->dev || !netif_running(np->dev)) {
@@ -255,8 +255,7 @@ repeat:
}
/* avoid recursion */
- npinfo = np->dev->npinfo;
- if (npinfo->poll_owner == smp_processor_id() ||
+ if (dev->poll_owner == smp_processor_id() ||
np->dev->xmit_lock_owner == smp_processor_id()) {
if (np->drop)
np->drop(skb);
@@ -641,8 +640,6 @@ int netpoll_setup(struct netpoll *np)
npinfo->rx_flags = 0;
npinfo->rx_np = NULL;
- npinfo->poll_lock = SPIN_LOCK_UNLOCKED;
- npinfo->poll_owner = -1;
npinfo->rx_lock = SPIN_LOCK_UNLOCKED;
} else
npinfo = ndev->npinfo;
--- linux-2.6.12/net/core/dev.c.orig 2005-07-01 14:52:08.613655521 -0400
+++ linux-2.6.12/net/core/dev.c 2005-07-01 14:52:38.495669512 -0400
@@ -3069,6 +3069,10 @@ struct net_device *alloc_netdev(int size
setup(dev);
strcpy(dev->name, name);
+#ifdef CONFIG_NETPOLL
+ dev->poll_owner = -1;
+ dev->poll_lock = SPIN_LOCK_UNLOCKED;
+#endif
return dev;
}
EXPORT_SYMBOL(alloc_netdev);
--- linux-2.6.12/include/linux/netpoll.h.orig 2005-07-01 14:52:16.016420312 -0400
+++ linux-2.6.12/include/linux/netpoll.h 2005-07-01 14:52:38.495669512 -0400
@@ -24,8 +24,6 @@ struct netpoll {
};
struct netpoll_info {
- spinlock_t poll_lock;
- int poll_owner;
int rx_flags;
spinlock_t rx_lock;
struct netpoll *rx_np; /* netpoll that registered an rx_hook */
@@ -63,16 +61,16 @@ static inline int netpoll_rx(struct sk_b
static inline void netpoll_poll_lock(struct net_device *dev)
{
if (dev->npinfo) {
- spin_lock(&dev->npinfo->poll_lock);
- dev->npinfo->poll_owner = smp_processor_id();
+ spin_lock(&dev->poll_lock);
+ dev->poll_owner = smp_processor_id();
}
}
static inline void netpoll_poll_unlock(struct net_device *dev)
{
if (dev->npinfo) {
- dev->npinfo->poll_owner = -1;
- spin_unlock(&dev->npinfo->poll_lock);
+ dev->poll_owner = -1;
+ spin_unlock(&dev->poll_lock);
}
}
--- linux-2.6.12/include/linux/netdevice.h.orig 2005-07-01 14:52:22.666310731 -0400
+++ linux-2.6.12/include/linux/netdevice.h 2005-07-01 14:52:38.496669345 -0400
@@ -469,6 +469,8 @@ struct net_device
int (*neigh_setup)(struct net_device *dev, struct neigh_parms *);
#ifdef CONFIG_NETPOLL
struct netpoll_info *npinfo;
+ spinlock_t poll_lock;
+ int poll_owner;
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
void (*poll_controller)(struct net_device *dev);
^ permalink raw reply
* [rfc | patch 3/6] netpoll: change poll_napi to take a net_device
From: Jeff Moyer @ 2005-07-01 23:08 UTC (permalink / raw)
To: mpm, netdev, linux-kernel
In-Reply-To: <17093.52306.136742.190912@segfault.boston.redhat.com>
(sorry for munging the subject of the prior two patches)
The poll_napi routine is not specific to a netpoll. It really should be
able to be called with a struct net_device. Changing the routine to take a
struct net_device makes it easier to support the bonding driver, since we
will be implementing a netpoll_poll_dev routine, that will not have a
struct netpoll associated with it.
Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
---
--- linux-2.6.12/net/core/netpoll.c.orig 2005-07-01 14:12:33.986337259 -0400
+++ linux-2.6.12/net/core/netpoll.c 2005-07-01 14:20:45.848186887 -0400
@@ -128,10 +128,9 @@ static int checksum_udp(struct sk_buff *
* network adapter, forcing superfluous retries and possibly timeouts.
* Thus, we set our budget to greater than 1.
*/
-static void poll_napi(struct netpoll *np)
+static void poll_napi(struct net_device *dev)
{
- struct netpoll_info *npinfo = np->dev->npinfo;
- struct net_device *dev = np->dev;
+ struct netpoll_info *npinfo = dev->npinfo;
int budget = 16;
if (test_bit(__LINK_STATE_RX_SCHED, &dev->state) &&
@@ -156,7 +155,7 @@ void netpoll_poll(struct netpoll *np)
/* Process pending work on NIC */
np->dev->poll_controller(np->dev);
if (np->dev->poll)
- poll_napi(np);
+ poll_napi(np->dev);
zap_completion_queue();
}
^ permalink raw reply
* [rfc | patch 4/6] netpoll: add netpoll hooks to support the bonding driver
From: Jeff Moyer @ 2005-07-01 23:08 UTC (permalink / raw)
To: mpm, netdev, linux-kernel
In-Reply-To: <17093.52306.136742.190912@segfault.boston.redhat.com>
Implement hooks in the netpoll code to support the bonding driver (and
hopefully other virtual device drivers, as well). The key additions here
are netpoll_poll_dev(new) and netpoll_send_skb(newly exported).
netpoll_send_skb
This is exported so that the bonding driver can queue a packet to be sent
via the real ethernet device it has chosen.
netpoll_poll_dev
This is a new routine that was created and exported so that the
poll_controller implementation in the bonding driver could poll each of
the underlying real devices without duplicating all of the logic that
exists internally to netpoll already.
Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
---
--- linux-2.6.12/net/core/netpoll.c.orig 2005-07-01 15:02:05.503951082 -0400
+++ linux-2.6.12/net/core/netpoll.c 2005-07-01 15:02:36.718705979 -0400
@@ -147,19 +147,27 @@ static void poll_napi(struct net_device
}
}
-void netpoll_poll(struct netpoll *np)
+void netpoll_poll_dev(struct net_device *dev)
{
- if(!np->dev || !netif_running(np->dev) || !np->dev->poll_controller)
+ if(!netif_running(dev) || !dev->poll_controller)
return;
/* Process pending work on NIC */
- np->dev->poll_controller(np->dev);
- if (np->dev->poll)
- poll_napi(np->dev);
+ dev->poll_controller(dev);
+ if (dev->poll)
+ poll_napi(dev);
zap_completion_queue();
}
+void netpoll_poll(struct netpoll *np)
+{
+ if(!np->dev)
+ return;
+
+ netpoll_poll_dev(np->dev);
+}
+
static void refill_skbs(void)
{
struct sk_buff *skb;
@@ -243,48 +251,59 @@ repeat:
return skb;
}
-static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
+/*
+ * This function can be called from virtual device drivers, such as the
+ * bonding driver. In this case, skb->dev is filled in with the real
+ * device over which the packet needs to be sent. For this reason, we use
+ * the skb->dev instead of np->dev. Essentially, np->dev can be, for
+ * example, bond0, while we actually need to send the packet out over eth0.
+ */
+void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
{
int status;
+ struct net_device *dev = skb->dev;
repeat:
- if(!np || !np->dev || !netif_running(np->dev)) {
+ if(!np || !dev || !netif_running(dev)) {
__kfree_skb(skb);
return;
}
/* avoid recursion */
if (dev->poll_owner == smp_processor_id() ||
- np->dev->xmit_lock_owner == smp_processor_id()) {
- if (np->drop)
+ dev->xmit_lock_owner == smp_processor_id()) {
+ if (np && np->drop)
np->drop(skb);
else
__kfree_skb(skb);
return;
}
- spin_lock(&np->dev->xmit_lock);
- np->dev->xmit_lock_owner = smp_processor_id();
+ spin_lock(&dev->xmit_lock);
+ dev->xmit_lock_owner = smp_processor_id();
/*
* network drivers do not expect to be called if the queue is
* stopped.
*/
- if (netif_queue_stopped(np->dev)) {
- np->dev->xmit_lock_owner = -1;
- spin_unlock(&np->dev->xmit_lock);
+ if (netif_queue_stopped(dev)) {
+ dev->xmit_lock_owner = -1;
+ spin_unlock(&dev->xmit_lock);
- netpoll_poll(np);
+ netpoll_poll_dev(dev);
goto repeat;
}
- status = np->dev->hard_start_xmit(skb, np->dev);
- np->dev->xmit_lock_owner = -1;
- spin_unlock(&np->dev->xmit_lock);
+ if (dev->netpoll_start_xmit)
+ status = dev->netpoll_start_xmit(np, skb, dev);
+ else
+ status = dev->hard_start_xmit(skb, dev);
+ dev->xmit_lock_owner = -1;
+ spin_unlock(&dev->xmit_lock);
/* transmit busy */
if(status) {
- netpoll_poll(np);
+ netpoll_poll_dev(dev);
goto repeat;
}
}
@@ -715,6 +734,11 @@ int netpoll_setup(struct netpoll *np)
npinfo->rx_np = np;
spin_unlock_irqrestore(&npinfo->rx_lock, flags);
}
+
+ /* Call the device specific netpoll initialization routine. */
+ if (ndev->netpoll_setup)
+ ndev->netpoll_setup(ndev, npinfo);
+
/* last thing to do is link it to the net device structure */
ndev->npinfo = npinfo;
@@ -766,5 +790,7 @@ EXPORT_SYMBOL(netpoll_parse_options);
EXPORT_SYMBOL(netpoll_setup);
EXPORT_SYMBOL(netpoll_cleanup);
EXPORT_SYMBOL(netpoll_send_udp);
+EXPORT_SYMBOL(netpoll_send_skb);
EXPORT_SYMBOL(netpoll_poll);
+EXPORT_SYMBOL(netpoll_poll_dev);
EXPORT_SYMBOL(netpoll_queue);
--- linux-2.6.12/net/core/dev.c.orig 2005-07-01 14:59:50.161654219 -0400
+++ linux-2.6.12/net/core/dev.c 2005-07-01 15:00:23.437103656 -0400
@@ -1655,15 +1655,15 @@ int netif_receive_skb(struct sk_buff *sk
int ret = NET_RX_DROP;
unsigned short type;
- /* if we've gotten here through NAPI, check netpoll */
- if (skb->dev->poll && netpoll_rx(skb))
+ skb_bond(skb);
+
+ /* if there is a netpoll client registered, check netpoll */
+ if (skb->dev->npinfo && netpoll_rx(skb))
return NET_RX_DROP;
if (!skb->stamp.tv_sec)
net_timestamp(&skb->stamp);
- skb_bond(skb);
-
__get_cpu_var(netdev_rx_stat).total++;
skb->h.raw = skb->nh.raw = skb->data;
--- linux-2.6.12/include/linux/netpoll.h.orig 2005-07-01 14:59:56.135657708 -0400
+++ linux-2.6.12/include/linux/netpoll.h 2005-07-01 15:00:23.437103656 -0400
@@ -30,7 +30,9 @@ struct netpoll_info {
};
void netpoll_poll(struct netpoll *np);
+void netpoll_poll_dev(struct net_device *dev);
void netpoll_send_udp(struct netpoll *np, const char *msg, int len);
+void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb);
int netpoll_parse_options(struct netpoll *np, char *opt);
int netpoll_setup(struct netpoll *np);
int netpoll_trap(void);
--- linux-2.6.12/include/linux/netdevice.h.orig 2005-07-01 14:59:59.835040624 -0400
+++ linux-2.6.12/include/linux/netdevice.h 2005-07-01 15:00:23.438103489 -0400
@@ -41,6 +41,7 @@
struct divert_blk;
struct vlan_group;
struct ethtool_ops;
+struct netpoll;
struct netpoll_info;
/* source back-compat hooks */
#define SET_ETHTOOL_OPS(netdev,ops) \
@@ -473,7 +474,12 @@ struct net_device
int poll_owner;
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
+ void (*netpoll_setup)(struct net_device *dev,
+ struct netpoll_info *npinfo);
void (*poll_controller)(struct net_device *dev);
+ int (*netpoll_start_xmit)(struct netpoll *np,
+ struct sk_buff *skb,
+ struct net_device *dev);
#endif
/* bridge stuff */
^ permalink raw reply
* [rfc | patch 5/6] netpoll: modify bonding driver to support netpoll
From: Jeff Moyer @ 2005-07-01 23:09 UTC (permalink / raw)
To: mpm, netdev, linux-kernel
In-Reply-To: <17093.52306.136742.190912@segfault.boston.redhat.com>
Implement netpoll hooks in the bonding driver. We register the following
netpoll specific routines:
bond_netpoll_setup
This routine associates the struct netpoll_info of the master device with
each of the slave devices.
bond_xmit_netpoll
This routine sets bonding->netpoll to the struct netpoll provided by
netpoll_send_skb. This pointer is then passed along to netpoll_send_skb
in bond_dev_queue_xmit, when we are ready to send the skb out over the
real network device.
bond_poll_controller
This routine calls netpoll_poll_dev for each of the slaves in the bond.
When a new slave is added to the bond, if it does not support netpoll, then
netpoll is disabled for the bond. When a slave is released, that slave's
npinfo pointer is cleared.
I have tested this code extensively, and it works well in my environment.
Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
---
--- linux-2.6.12/drivers/net/bonding/bond_main.c.orig 2005-06-29 14:28:08.000000000 -0400
+++ linux-2.6.12/drivers/net/bonding/bond_main.c 2005-06-30 19:33:50.641009622 -0400
@@ -821,8 +821,12 @@ int bond_dev_queue_xmit(struct bonding *
}
skb->priority = 1;
- dev_queue_xmit(skb);
-
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ if (bond->netpoll)
+ netpoll_send_skb(bond->netpoll, skb);
+ else
+#endif
+ dev_queue_xmit(skb);
return 0;
}
@@ -1567,6 +1571,45 @@ static void bond_detach_slave(struct bon
bond->slave_cnt--;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static int slaves_support_netpoll(struct net_device *bond_dev)
+{
+ struct bonding *bond = bond_dev->priv;
+ struct slave *slave;
+ int i;
+
+ bond_for_each_slave(bond, slave, i) {
+ if (!slave->dev->poll_controller)
+ return 0;
+ }
+
+ return 1;
+}
+
+static void bond_poll_controller(struct net_device *bond_dev)
+{
+ struct bonding *bond = bond_dev->priv;
+ struct slave *slave;
+ int i;
+
+ bond_for_each_slave(bond, slave, i) {
+ if (slave->dev->poll_controller)
+ netpoll_poll_dev(slave->dev);
+ }
+}
+
+static void bond_netpoll_setup(struct net_device *bond_dev,
+ struct netpoll_info *npinfo)
+{
+ struct bonding *bond = bond_dev->priv;
+ struct slave *slave;
+ int i;
+
+ bond_for_each_slave(bond, slave, i)
+ slave->dev->npinfo = npinfo;
+}
+#endif
+
/*---------------------------------- IOCTL ----------------------------------*/
static int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
@@ -1969,6 +2012,17 @@ static int bond_enslave(struct net_devic
new_slave->state == BOND_STATE_ACTIVE ? "n active" : " backup",
new_slave->link != BOND_LINK_DOWN ? "n up" : " down");
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ if (slaves_support_netpoll(bond_dev)) {
+ bond_dev->poll_controller = bond_poll_controller;
+ slave_dev->npinfo = bond_dev->npinfo;
+ } else if (bond_dev->poll_controller) {
+ bond_dev->poll_controller = NULL;
+ printk("New slave device %s does not support netpoll.\n",
+ slave_dev->name);
+ printk("netpoll disabled for %s.\n", bond_dev->name);
+ }
+#endif
/* enslave is successful */
return 0;
@@ -2173,6 +2227,9 @@ static int bond_release(struct net_devic
slave_dev->flags &= ~IFF_NOARP;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ slave_dev->npinfo = NULL;
+#endif
kfree(slave);
return 0; /* deletion OK */
@@ -4203,6 +4260,21 @@ out:
return 0;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+int bond_xmit_netpoll(struct netpoll *np, struct sk_buff *skb,
+ struct net_device *bond_dev)
+{
+ struct bonding *bond = bond_dev->priv;
+ int ret;
+
+ bond->netpoll = np;
+ ret = bond_dev->hard_start_xmit(skb, bond_dev);
+ bond->netpoll = NULL;
+
+ return ret;
+}
+#endif
+
/*------------------------- Device initialization ---------------------------*/
/*
@@ -4277,6 +4349,10 @@ static int __init bond_init(struct net_d
bond_dev->destructor = free_netdev;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ bond_dev->netpoll_setup = bond_netpoll_setup;
+ bond_dev->netpoll_start_xmit = bond_xmit_netpoll;
+#endif
/* Initialize the device options */
bond_dev->tx_queue_len = 0;
bond_dev->flags |= IFF_MASTER|IFF_MULTICAST;
--- linux-2.6.12/drivers/net/bonding/bonding.h.orig 2005-06-29 14:29:40.000000000 -0400
+++ linux-2.6.12/drivers/net/bonding/bonding.h 2005-06-30 19:02:54.000000000 -0400
@@ -33,6 +33,7 @@
#include <linux/timer.h>
#include <linux/proc_fs.h>
#include <linux/if_bonding.h>
+#include <linux/netpoll.h>
#include "bond_3ad.h"
#include "bond_alb.h"
@@ -203,6 +204,9 @@ struct bonding {
struct bond_params params;
struct list_head vlan_list;
struct vlan_group *vlgrp;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ struct netpoll *netpoll;
+#endif
};
/**
^ permalink raw reply
* [rfc | patch 6/6] netpoll: fix deadlock in arp_reply
From: Jeff Moyer @ 2005-07-01 23:10 UTC (permalink / raw)
To: mpm, netdev, linux-kernel
In-Reply-To: <17093.52306.136742.190912@segfault.boston.redhat.com>
This fixes an obvious deadlock in the netpoll code. netpoll_rx takes the
npinfo->rx_lock. netpoll_rx is also the only caller of arp_reply (through
__netpoll_rx). As such, it is not necessary to take this lock.
Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
--- linux-2.6.12/net/core/netpoll.c.orig 2005-07-01 17:55:24.313339068 -0400
+++ linux-2.6.12/net/core/netpoll.c 2005-07-01 17:55:57.354863472 -0400
@@ -370,11 +370,8 @@ static void arp_reply(struct sk_buff *sk
struct sk_buff *send_skb;
struct netpoll *np = NULL;
- spin_lock_irqsave(&npinfo->rx_lock, flags);
if (npinfo->rx_np && npinfo->rx_np->dev == skb->dev)
np = npinfo->rx_np;
- spin_unlock_irqrestore(&npinfo->rx_lock, flags);
-
if (!np)
return;
^ permalink raw reply
* Re: [rfc | patch 0/6] netpoll: add support for the bonding driver
From: Matt Mackall @ 2005-07-01 23:38 UTC (permalink / raw)
To: Jeff Moyer; +Cc: netdev, linux-kernel
In-Reply-To: <17093.52306.136742.190912@segfault.boston.redhat.com>
On Fri, Jul 01, 2005 at 07:05:54PM -0400, Jeff Moyer wrote:
> New netpoll function implemented by the network drivers:
>
> net_device->netpoll_setup
> This is required, since the bonding device has to walk through each slave
> and point its slave_dev->npinfo at the npinfo for the master device. The
> reason for this is so that when we're doing the napi polling, we can set
> the rx_flags appropriately.
>
> net_device->netpoll_start_xmit
> This routine is required since, otherwise, there is no way to intercept
> packets bound for interfaces that are not ready for them. Of course, it
> requires further logic in the bonding driver to then call into the
> netpoll_send_skb routine (which is a new export).
>
> Note that neither of these pointers has to be filled in by the driver.
> These functions should only be implemented where needed, and to date, that
> is only in the bonding driver.
>
> Newly exported are:
>
> netpoll_send_skb
> This is exported so that the bonding driver can queue a packet to be sent
> via the real ethernet device it has chosen.
>
> netpoll_poll_dev
> This is a new routine that was created and exported so that the
> poll_controller implementation in the bonding driver could poll each of
> the underlying real devices without duplicating all of the logic that
> exists internally to netpoll already.
>
>
> To test this, as I mentioned above, I wrote a simple module which, upon
> receipt of any packet, sends out a packet with the message "PONG". I fired
> up netcat to send test packets, and receive the responses. I also loaded
> the netconsole module for the very same interface, bond0, and issue a
> series of sysrq-X's, both via sysrq-trigger and via the keyboard. I did
> this while simultaneously testing the PING server on an SMP machine. As
> things stand, it is very stable in my environment.
>
> And so, the patch set follows. Any and all comments are appreciated.
Patches 1, 3, and 6 are unrelated bugfixes and should just go in.
I don't like that we rely on queueing to process round trips for PONG.
Is this really unavoidable?
And I think the most controversial thing here is moving locks from npinfo
into the device.
Not really happy about how incestuous this makes the bonding driver
with netpoll. I'll try to think more about it over the weekend.
--
Mathematics is the supreme nostalgia of our time.
^ permalink raw reply
* Re: [rfc | patch 0/6] netpoll: add support for the bonding driver
From: Jeff Moyer @ 2005-07-01 23:43 UTC (permalink / raw)
To: Matt Mackall; +Cc: netdev, linux-kernel
In-Reply-To: <20050701233811.GQ12006@waste.org>
==> Regarding Re: [rfc | patch 0/6] netpoll: add support for the bonding driver; Matt Mackall <mpm@selenic.com> adds:
mpm> On Fri, Jul 01, 2005 at 07:05:54PM -0400, Jeff Moyer wrote:
>> New netpoll function implemented by the network drivers:
>>
net_device-> netpoll_setup
>> This is required, since the bonding device has to walk through each
>> slave and point its slave_dev->npinfo at the npinfo for the master
>> device. The reason for this is so that when we're doing the napi
>> polling, we can set the rx_flags appropriately.
>>
net_device-> netpoll_start_xmit
>> This routine is required since, otherwise, there is no way to intercept
>> packets bound for interfaces that are not ready for them. Of course, it
>> requires further logic in the bonding driver to then call into the
>> netpoll_send_skb routine (which is a new export).
>>
>> Note that neither of these pointers has to be filled in by the driver.
>> These functions should only be implemented where needed, and to date,
>> that is only in the bonding driver.
>>
>> Newly exported are:
>>
>> netpoll_send_skb This is exported so that the bonding driver can queue a
>> packet to be sent via the real ethernet device it has chosen.
>>
>> netpoll_poll_dev This is a new routine that was created and exported so
>> that the poll_controller implementation in the bonding driver could poll
>> each of the underlying real devices without duplicating all of the logic
>> that exists internally to netpoll already.
>>
>>
>> To test this, as I mentioned above, I wrote a simple module which, upon
>> receipt of any packet, sends out a packet with the message "PONG". I
>> fired up netcat to send test packets, and receive the responses. I also
>> loaded the netconsole module for the very same interface, bond0, and
>> issue a series of sysrq-X's, both via sysrq-trigger and via the
>> keyboard. I did this while simultaneously testing the PING server on an
>> SMP machine. As things stand, it is very stable in my environment.
>>
>> And so, the patch set follows. Any and all comments are appreciated.
mpm> Patches 1, 3, and 6 are unrelated bugfixes and should just go in.
Right. Sorry I lumped them together.
mpm> I don't like that we rely on queueing to process round trips for PONG.
mpm> Is this really unavoidable?
That's how it works without these patches, too.
mpm> And I think the most controversial thing here is moving locks from
mpm> npinfo into the device.
Well, as I mentioned, that's a bit of an optimization, if you will.
mpm> Not really happy about how incestuous this makes the bonding driver
mpm> with netpoll. I'll try to think more about it over the weekend.
I'd be delighted if you came up with a better way to do things. However, I
think you'll find that this is about as clean as it gets.
-Jeff
^ permalink raw reply
* controlling ARP Proxy scope?
From: Zdenek Radouch @ 2005-07-02 2:16 UTC (permalink / raw)
To: netdev, linux-net
I haven't been able to locate anything discussing how to control the scope
of Linux proxy ARP.
So, left with only a binary flag in /proc, and network definition on the
interface,
I assumed (perhaps naively) that the arp would proxy only for the addresses
within the subnet defined for the interface (on which the proxy arp is
turned on).
However, that does not seem to be the case.
I have an interface with address 10.1.2.219 and mask 255.255.255.248 with
proxy arp turned on on this interface, and the machine is responding
(I see that with tcpdump) to arp requests for address 10.1.2.1, i.e.,
an address outside of the proxy interface's subnet.
Can anyone explain the behavior?
What is the scope of the proxying?
If the scope is not limited to the proxy interface's subnet, then how do I
avoid proxying
for addresses of machines facing the proxy server? This seems to be quite
broken.
I am running 2.4.25 kernel.
I'll appreciate any pointers. Thanks!
-Zdenek
^ permalink raw reply
* Re: [PATCH 2.6.13-rc1 8/17] bonding: SYSFS INTERFACE (large)
From: Dmitry Torokhov @ 2005-07-02 5:30 UTC (permalink / raw)
To: netdev; +Cc: Radheka Godse, fubar, bonding-devel
In-Reply-To: <Pine.LNX.4.61.0507011347060.17459@localhost.localdomain>
Hi,
On Friday 01 July 2005 15:48, Radheka Godse wrote:
> This large patch adds the sysfs interface to channel bonding. It will
> allow users to add and remove bonds, add and remove slaves, and change
> all bonding parameters without using ifenslave.
> The ifenslave interface still works.
...
Couple of comments:
> @@ -3569,7 +3593,10 @@
> bond_remove_proc_entry(bond);
> bond_create_proc_entry(bond);
> #endif
> -
> + down_write(&(bonding_rwsem));
> + bond_destroy_sysfs_entry(bond);
> + bond_create_sysfs_entry(bond);
> + up_write(&(bonding_rwsem));
Space vs. tab identation.
> return NOTIFY_DONE;
> }
>
> @@ -4101,6 +4128,7 @@
> orig_app_abi_ver = prev_abi_ver;
> }
>
> + up_write(&(bonding_rwsem));
Whu extra parens?
> + * Changes:
> + *
> + * 2004/12/12 - Mitch Williams <mitch.a.williams at intel dot com>
> + * - Initial creation of sysfs interface.
> + *
> + * 2005/06/22 - Radheka Godse <radheka.godse at intel dot com>
> + * - Added ifenslave -c type functionality to sysfs
> + * - Added sysfs files for attributes such as MII Status and
> + * 802.3ad aggregator that are displayed in /proc
> + * - Added "name value" format to sysfs "mode" and
> + * "lacp_rate", for e.g., "active-backup 1" or "slow 0" for
> + * consistency and ease of script parsing
> + * - Fixed reversal of octets in arp_ip_targets via sysfs
> + * - sysfs support to handle bond interface re-naming
> + * - Moved all sysfs entries into /sys/class/net instead of
> + * of using a standalone subsystem.
> + * - Added sysfs symlinks between masters and slaves
> + * - Corrected bugs in sysfs unload path when creating bonds
> + * with existing interface names.
> + * - Removed redundant sysfs stat file since it duplicates slave info
> + * from the proc file
> + * - Fixed errors in sysfs show/store arp targets.
> + * - For consistency with ifenslave, instead of exiting
> + * with an error, updated bonding sysfs to
> + * close and attempt to enslave an up adapter.
> + * - Fixed NULL dereference when adding a slave interface
> + * that does not exist.
> + * - Added checks in sysfs bonding to reject invalid ip addresses
> + * - Synch up with post linux-2.6.12 bonding changes
> + * - Created sysfs bond attrib for xmit_hash_policy
I think we prefer to rely in SCMs to keep changelogs for new modules.
> +
> +static struct class *netdev_class;
> +/*--------------------------- Data Structures -----------------------------*/
> +
> +/* Bonding sysfs lock. Why can't we just use the subsytem lock?
> + * Because kobject_register tries to acquire the subsystem lock. If
> + * we already hold the lock (which we would if the user was creating
> + * a new bond through the sysfs interface), we deadlock.
> + */
> +
> +struct rw_semaphore bonding_rwsem;
klists were just added to the kernel proper. Does this sentiment still
holds true?
> +
> +/*
> + * "show" function for the bond_masters attribute.
> + * The class parameter is ignored.
> + */
> +static ssize_t bonding_show_bonds(struct class *cls, char *buffer)
> +{
> + int res = 0;
> + struct bonding *bond;
> +
> + down_read(&(bonding_rwsem));
Why extra parens?
> + list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) {
> + if (strnicmp(bond->dev->name, name, IFNAMSIZ) == 0) {
> + /* Temporarily set a meaningless flag. When
> + * we get done with the loop, we'll check all of these.
> + * If the bond doesn't have this flag set, then we need
> + * to remove the bond. If the flag has it set, then
> + * we can just clear the flag.
> + */
> + bond->flags |= IFF_DYNAMIC;
> + found = 1;
> + break; /* Found it, so go to next name */
> + }
> + }
Why list_for_each_entry_safe is used? NO elements is being deleted in
the loop...
> +
> + /* first, create a link from the slave back to the master */
> + ret = sysfs_create_link(&(slave->class_dev.kobj), &(master->class_dev.kobj),
> + "master");
Extra parens again.
> +static ssize_t bonding_show_arp_interval(struct class_device *cd, char *buf)
> +{
> + int count;
> + struct bonding *bond = to_bond(cd);
> +
> + down_read(&(bonding_rwsem));
> + count = sprintf(buf, "%d\n", bond->params.arp_interval) + 1;
> + up_read(&(bonding_rwsem));
> + return count;
> +}
What does this lock really protects here? As far as I can see params will
not go away...
> +
> + /* get the netdev class pointer */
> + firstbond = container_of(bond_dev_list.next, struct bonding, bond_list);
> + if (!firstbond)
> + {
Open brace should go on the same line as if. Besides, here it is not needed
at all...
Thanks!
--
Dmitry
^ permalink raw reply
* Re: [PATCH 2.6.13-rc1 8/17] bonding: SYSFS INTERFACE (large)
From: Greg KH @ 2005-07-02 8:13 UTC (permalink / raw)
To: Radheka Godse; +Cc: netdev
In-Reply-To: <Pine.LNX.4.61.0507011347060.17459@localhost.localdomain>
On Fri, Jul 01, 2005 at 01:48:44PM -0700, Radheka Godse wrote:
> This large patch adds the sysfs interface to channel bonding. It will
> allow users to add and remove bonds, add and remove slaves, and change
> all bonding parameters without using ifenslave.
> The ifenslave interface still works.
Have a short example of what the sysfs tree looks like, and what the new
files contain and expect to be written to?
> diff -urN -X dontdiff linux-2.6.12post/drivers/net/bonding/bonding.h
> linux-2.6.12post-sysfs/drivers/net/bonding/bonding.h
> --- linux-2.6.12post/drivers/net/bonding/bonding.h 2005-06-28
> 18:18:03.000000000 -0700
patch looks linewrapped :(
> +/* Bonding sysfs lock. Why can't we just use the subsytem lock?
The subsystem lock is no more. Well, it's still around, but almost no
one uses it, due to the klist changes. You shouldn't need a lock
either now.
> + * Because kobject_register tries to acquire the subsystem lock. If
> + * we already hold the lock (which we would if the user was creating
> + * a new bond through the sysfs interface), we deadlock.
> + */
> +
> +struct rw_semaphore bonding_rwsem;
> +
> +
> +
> +
> +/*------------------------------ Functions
> --------------------------------*/
> +
> +/*
> + * "show" function for the bond_masters attribute.
> + * The class parameter is ignored.
> + */
> +static ssize_t bonding_show_bonds(struct class *cls, char *buffer)
> +{
> + int res = 0;
> + struct bonding *bond;
> +
> + down_read(&(bonding_rwsem));
> +
> + list_for_each_entry(bond, &bond_dev_list, bond_list) {
> + res += sprintf(buffer + res, "%s ",
> + bond->dev->name);
> + if (res > (PAGE_SIZE - IFNAMSIZ)) {
> + dprintk("eek! too many bonds!\n");
> + break;
> + }
> + }
> + res += sprintf(buffer + res, "\n");
> + res++;
> + up_read(&(bonding_rwsem));
> + return res;
This violates the 1-value-per-sysfs file rule. Please fix this up.
> +static ssize_t bonding_show_slaves(struct class_device *cd, char *buf)
> +{
> + struct slave *slave;
> + int i, res = 0;
> + struct bonding *bond = to_bond(cd);
> +
> + down_read(&(bonding_rwsem));
> +
> + read_lock_bh(&bond->lock);
> + bond_for_each_slave(bond, slave, i) {
> + res += sprintf(buf + res, "%s ", slave->dev->name);
> + if (res > (PAGE_SIZE - IFNAMSIZ)) {
> + dprintk("eek! too many slaves!\n");
> + break;
> + }
> + }
> + read_unlock_bh(&bond->lock);
> + res += sprintf(buf + res, "\n");
> + res++;
> + up_read(&(bonding_rwsem));
> + return res;
> +}
Same sysfs violation. I think other files also have problems :(
thanks,
greg k-h
^ permalink raw reply
* Re: controlling ARP Proxy scope?
From: Henrik Nordstrom @ 2005-07-02 21:21 UTC (permalink / raw)
To: Zdenek Radouch; +Cc: netdev, linux-net
In-Reply-To: <3u3gb7$1mhk2i@smtp05.mrf.mail.rcn.net>
On Fri, 1 Jul 2005, Zdenek Radouch wrote:
> So, left with only a binary flag in /proc, and network definition on the
> interface,
> I assumed (perhaps naively) that the arp would proxy only for the addresses
> within the subnet defined for the interface (on which the proxy arp is
> turned on).
> However, that does not seem to be the case.
You may be able to tune this with either arp_filter or arp_ignore.
> I have an interface with address 10.1.2.219 and mask 255.255.255.248 with
> proxy arp turned on on this interface, and the machine is responding
> (I see that with tcpdump) to arp requests for address 10.1.2.1, i.e.,
> an address outside of the proxy interface's subnet.
Correct.
> Can anyone explain the behavior?
proxy_arp simply ARPs if there is a route for the requested destination
going out on another interface than where the ARP was seen.
Regards
Henrik
^ permalink raw reply
* [2.6 patch] drivers/net/wireless/ipw2100.c: possible cleanups
From: Adrian Bunk @ 2005-07-02 21:46 UTC (permalink / raw)
To: jgarzik, ipw2100-admin; +Cc: linux-kernel, netdev
This patch contains the following possible cleanups:
- make needlessly global code static
- remove the unused IPW_DEBUG_ENABLED
Signed-off-by: Adrian Bunk <bunk@stusta.de>
---
drivers/net/wireless/ipw2100.c | 136 ++++++++++++++++++++-------------
drivers/net/wireless/ipw2100.h | 28 ------
2 files changed, 86 insertions(+), 78 deletions(-)
--- linux-2.6.13-rc1-mm1-full/drivers/net/wireless/ipw2100.h.old 2005-07-02 22:11:53.000000000 +0200
+++ linux-2.6.13-rc1-mm1-full/drivers/net/wireless/ipw2100.h 2005-07-02 22:25:46.000000000 +0200
@@ -48,22 +48,6 @@
struct ipw2100_tx_packet;
struct ipw2100_rx_packet;
-#ifdef CONFIG_IPW_DEBUG
-enum { IPW_DEBUG_ENABLED = 1 };
-extern u32 ipw2100_debug_level;
-#define IPW_DEBUG(level, message...) \
-do { \
- if (ipw2100_debug_level & (level)) { \
- printk(KERN_DEBUG "ipw2100: %c %s ", \
- in_interrupt() ? 'I' : 'U', __FUNCTION__); \
- printk(message); \
- } \
-} while (0)
-#else
-enum { IPW_DEBUG_ENABLED = 0 };
-#define IPW_DEBUG(level, message...) do {} while (0)
-#endif /* CONFIG_IPW_DEBUG */
-
#define IPW_DL_UNINIT 0x80000000
#define IPW_DL_NONE 0x00000000
#define IPW_DL_ALL 0x7FFFFFFF
@@ -1144,10 +1128,6 @@
#define WIRELESS_SPY // enable iwspy support
#endif
-extern struct iw_handler_def ipw2100_wx_handler_def;
-extern struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device * dev);
-extern void ipw2100_wx_event_work(struct ipw2100_priv *priv);
-
#define IPW_HOST_FW_SHARED_AREA0 0x0002f200
#define IPW_HOST_FW_SHARED_AREA0_END 0x0002f510 // 0x310 bytes
@@ -1182,14 +1162,6 @@
const struct firmware *fw_entry;
};
-int ipw2100_get_firmware(struct ipw2100_priv *priv, struct ipw2100_fw *fw);
-void ipw2100_release_firmware(struct ipw2100_priv *priv, struct ipw2100_fw *fw);
-int ipw2100_fw_download(struct ipw2100_priv *priv, struct ipw2100_fw *fw);
-int ipw2100_ucode_download(struct ipw2100_priv *priv, struct ipw2100_fw *fw);
-
#define MAX_FW_VERSION_LEN 14
-int ipw2100_get_fwversion(struct ipw2100_priv *priv, char *buf, size_t max);
-int ipw2100_get_ucodeversion(struct ipw2100_priv *priv, char *buf, size_t max);
-
#endif /* _IPW2100_H */
--- linux-2.6.13-rc1-mm1-full/drivers/net/wireless/ipw2100.c.old 2005-07-02 20:54:55.000000000 +0200
+++ linux-2.6.13-rc1-mm1-full/drivers/net/wireless/ipw2100.c 2005-07-02 22:31:21.000000000 +0200
@@ -207,7 +207,20 @@
MODULE_PARM_DESC(associate, "auto associate when scanning (default on)");
MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
-u32 ipw2100_debug_level = IPW_DL_NONE;
+static u32 ipw2100_debug_level = IPW_DL_NONE;
+
+#ifdef CONFIG_IPW_DEBUG
+#define IPW_DEBUG(level, message...) \
+do { \
+ if (ipw2100_debug_level & (level)) { \
+ printk(KERN_DEBUG "ipw2100: %c %s ", \
+ in_interrupt() ? 'I' : 'U', __FUNCTION__); \
+ printk(message); \
+ } \
+} while (0)
+#else
+#define IPW_DEBUG(level, message...) do {} while (0)
+#endif /* CONFIG_IPW_DEBUG */
#ifdef CONFIG_IPW_DEBUG
static const char *command_types[] = {
@@ -295,6 +308,22 @@
static void ipw2100_queues_free(struct ipw2100_priv *priv);
static int ipw2100_queues_allocate(struct ipw2100_priv *priv);
+static int ipw2100_fw_download(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw);
+static int ipw2100_get_firmware(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw);
+static int ipw2100_get_fwversion(struct ipw2100_priv *priv, char *buf,
+ size_t max);
+static int ipw2100_get_ucodeversion(struct ipw2100_priv *priv, char *buf,
+ size_t max);
+static void ipw2100_release_firmware(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw);
+static int ipw2100_ucode_download(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw);
+static void ipw2100_wx_event_work(struct ipw2100_priv *priv);
+static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device * dev);
+static struct iw_handler_def ipw2100_wx_handler_def;
+
static inline void read_register(struct net_device *dev, u32 reg, u32 *val)
{
@@ -473,8 +502,8 @@
== IPW_DATA_DOA_DEBUG_VALUE));
}
-int ipw2100_get_ordinal(struct ipw2100_priv *priv, u32 ord,
- void *val, u32 *len)
+static int ipw2100_get_ordinal(struct ipw2100_priv *priv, u32 ord,
+ void *val, u32 *len)
{
struct ipw2100_ordinals *ordinals = &priv->ordinals;
u32 addr;
@@ -1574,7 +1603,7 @@
return err;
}
-int ipw2100_set_scan_options(struct ipw2100_priv *priv)
+static int ipw2100_set_scan_options(struct ipw2100_priv *priv)
{
struct host_command cmd = {
.host_command = SET_SCAN_OPTIONS,
@@ -1604,7 +1633,7 @@
return err;
}
-int ipw2100_start_scan(struct ipw2100_priv *priv)
+static int ipw2100_start_scan(struct ipw2100_priv *priv)
{
struct host_command cmd = {
.host_command = BROADCAST_SCAN,
@@ -1815,7 +1844,7 @@
netif_stop_queue(priv->net_dev);
}
-void ipw2100_reset_adapter(struct ipw2100_priv *priv)
+static void ipw2100_reset_adapter(struct ipw2100_priv *priv)
{
unsigned long flags;
union iwreq_data wrqu = {
@@ -1945,8 +1974,8 @@
}
-int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid,
- int length, int batch_mode)
+static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid,
+ int length, int batch_mode)
{
int ssid_len = min(length, IW_ESSID_MAX_SIZE);
struct host_command cmd = {
@@ -2077,7 +2106,7 @@
priv->status |= STATUS_SCANNING;
}
-const struct ipw2100_status_indicator status_handlers[] = {
+static const struct ipw2100_status_indicator status_handlers[] = {
IPW2100_HANDLER(IPW_STATE_INITIALIZED, 0),
IPW2100_HANDLER(IPW_STATE_COUNTRY_FOUND, 0),
IPW2100_HANDLER(IPW_STATE_ASSOCIATED, isr_indicate_associated),
@@ -2145,7 +2174,7 @@
}
#ifdef CONFIG_IPW_DEBUG
-const char *frame_types[] = {
+static const char *frame_types[] = {
"COMMAND_STATUS_VAL",
"STATUS_CHANGE_VAL",
"P80211_DATA_VAL",
@@ -2265,7 +2294,7 @@
*
*/
#ifdef CONFIG_IPW2100_RX_DEBUG
-u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH];
+static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH];
#endif
static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv,
@@ -3407,7 +3436,7 @@
#define IPW2100_REG(x) { IPW_ ##x, #x }
-const struct {
+static const struct {
u32 addr;
const char *name;
} hw_data[] = {
@@ -3418,7 +3447,7 @@
IPW2100_REG(REG_RESET_REG),
};
#define IPW2100_NIC(x, s) { x, #x, s }
-const struct {
+static const struct {
u32 addr;
const char *name;
size_t size;
@@ -3428,7 +3457,7 @@
IPW2100_NIC(0x210000, 1),
};
#define IPW2100_ORD(x, d) { IPW_ORD_ ##x, #x, d }
-const struct {
+static const struct {
u8 index;
const char *name;
const char *desc;
@@ -3793,7 +3822,7 @@
static DEVICE_ATTR(stats, S_IRUGO, show_stats, NULL);
-int ipw2100_switch_mode(struct ipw2100_priv *priv, u32 mode)
+static int ipw2100_switch_mode(struct ipw2100_priv *priv, u32 mode)
{
int err;
@@ -4471,7 +4500,7 @@
*
********************************************************************/
-int ipw2100_set_mac_address(struct ipw2100_priv *priv, int batch_mode)
+static int ipw2100_set_mac_address(struct ipw2100_priv *priv, int batch_mode)
{
struct host_command cmd = {
.host_command = ADAPTER_ADDRESS,
@@ -4494,7 +4523,7 @@
return err;
}
-int ipw2100_set_port_type(struct ipw2100_priv *priv, u32 port_type,
+static int ipw2100_set_port_type(struct ipw2100_priv *priv, u32 port_type,
int batch_mode)
{
struct host_command cmd = {
@@ -4535,7 +4564,8 @@
}
-int ipw2100_set_channel(struct ipw2100_priv *priv, u32 channel, int batch_mode)
+static int ipw2100_set_channel(struct ipw2100_priv *priv, u32 channel,
+ int batch_mode)
{
struct host_command cmd = {
.host_command = CHANNEL,
@@ -4585,7 +4615,7 @@
return 0;
}
-int ipw2100_system_config(struct ipw2100_priv *priv, int batch_mode)
+static int ipw2100_system_config(struct ipw2100_priv *priv, int batch_mode)
{
struct host_command cmd = {
.host_command = SYSTEM_CONFIG,
@@ -4647,7 +4677,8 @@
return 0;
}
-int ipw2100_set_tx_rates(struct ipw2100_priv *priv, u32 rate, int batch_mode)
+static int ipw2100_set_tx_rates(struct ipw2100_priv *priv, u32 rate,
+ int batch_mode)
{
struct host_command cmd = {
.host_command = BASIC_TX_RATES,
@@ -4686,8 +4717,8 @@
return 0;
}
-int ipw2100_set_power_mode(struct ipw2100_priv *priv,
- int power_level)
+static int ipw2100_set_power_mode(struct ipw2100_priv *priv,
+ int power_level)
{
struct host_command cmd = {
.host_command = POWER_MODE,
@@ -4724,7 +4755,7 @@
}
-int ipw2100_set_rts_threshold(struct ipw2100_priv *priv, u32 threshold)
+static int ipw2100_set_rts_threshold(struct ipw2100_priv *priv, u32 threshold)
{
struct host_command cmd = {
.host_command = RTS_THRESHOLD,
@@ -4788,7 +4819,7 @@
}
#endif
-int ipw2100_set_short_retry(struct ipw2100_priv *priv, u32 retry)
+static int ipw2100_set_short_retry(struct ipw2100_priv *priv, u32 retry)
{
struct host_command cmd = {
.host_command = SHORT_RETRY_LIMIT,
@@ -4808,7 +4839,7 @@
return 0;
}
-int ipw2100_set_long_retry(struct ipw2100_priv *priv, u32 retry)
+static int ipw2100_set_long_retry(struct ipw2100_priv *priv, u32 retry)
{
struct host_command cmd = {
.host_command = LONG_RETRY_LIMIT,
@@ -4829,8 +4860,8 @@
}
-int ipw2100_set_mandatory_bssid(struct ipw2100_priv *priv, u8 *bssid,
- int batch_mode)
+static int ipw2100_set_mandatory_bssid(struct ipw2100_priv *priv, u8 *bssid,
+ int batch_mode)
{
struct host_command cmd = {
.host_command = MANDATORY_BSSID,
@@ -4963,11 +4994,11 @@
u8 unicast_using_group;
} __attribute__ ((packed));
-int ipw2100_set_security_information(struct ipw2100_priv *priv,
- int auth_mode,
- int security_level,
- int unicast_using_group,
- int batch_mode)
+static int ipw2100_set_security_information(struct ipw2100_priv *priv,
+ int auth_mode,
+ int security_level,
+ int unicast_using_group,
+ int batch_mode)
{
struct host_command cmd = {
.host_command = SET_SECURITY_INFORMATION,
@@ -5029,8 +5060,8 @@
return err;
}
-int ipw2100_set_tx_power(struct ipw2100_priv *priv,
- u32 tx_power)
+static int ipw2100_set_tx_power(struct ipw2100_priv *priv,
+ u32 tx_power)
{
struct host_command cmd = {
.host_command = TX_POWER_INDEX,
@@ -5049,8 +5080,8 @@
return 0;
}
-int ipw2100_set_ibss_beacon_interval(struct ipw2100_priv *priv,
- u32 interval, int batch_mode)
+static int ipw2100_set_ibss_beacon_interval(struct ipw2100_priv *priv,
+ u32 interval, int batch_mode)
{
struct host_command cmd = {
.host_command = BEACON_INTERVAL,
@@ -6781,7 +6812,7 @@
#define WEXT_USECHANNELS 1
-const long ipw2100_frequencies[] = {
+static const long ipw2100_frequencies[] = {
2412, 2417, 2422, 2427,
2432, 2437, 2442, 2447,
2452, 2457, 2462, 2467,
@@ -6791,7 +6822,7 @@
#define FREQ_COUNT (sizeof(ipw2100_frequencies) / \
sizeof(ipw2100_frequencies[0]))
-const long ipw2100_rates_11b[] = {
+static const long ipw2100_rates_11b[] = {
1000000,
2000000,
5500000,
@@ -6950,7 +6981,7 @@
#define POWER_MODES 5
/* Values are in microsecond */
-const s32 timeout_duration[POWER_MODES] = {
+static const s32 timeout_duration[POWER_MODES] = {
350000,
250000,
75000,
@@ -6958,7 +6989,7 @@
25000,
};
-const s32 period_duration[POWER_MODES] = {
+static const s32 period_duration[POWER_MODES] = {
400000,
700000,
1000000,
@@ -8023,7 +8054,7 @@
ipw2100_wx_get_preamble,
};
-struct iw_handler_def ipw2100_wx_handler_def =
+static struct iw_handler_def ipw2100_wx_handler_def =
{
.standard = ipw2100_wx_handlers,
.num_standard = sizeof(ipw2100_wx_handlers) / sizeof(iw_handler),
@@ -8039,7 +8070,7 @@
* Called by /proc/net/wireless
* Also called by SIOCGIWSTATS
*/
-struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device * dev)
+static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device * dev)
{
enum {
POOR = 30,
@@ -8175,7 +8206,7 @@
return (struct iw_statistics *) NULL;
}
-void ipw2100_wx_event_work(struct ipw2100_priv *priv)
+static void ipw2100_wx_event_work(struct ipw2100_priv *priv)
{
union iwreq_data wrqu;
int len = ETH_ALEN;
@@ -8288,7 +8319,8 @@
}
-int ipw2100_get_firmware(struct ipw2100_priv *priv, struct ipw2100_fw *fw)
+static int ipw2100_get_firmware(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw)
{
char *fw_name;
int rc;
@@ -8327,8 +8359,8 @@
return 0;
}
-void ipw2100_release_firmware(struct ipw2100_priv *priv,
- struct ipw2100_fw *fw)
+static void ipw2100_release_firmware(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw)
{
fw->version = 0;
if (fw->fw_entry)
@@ -8337,7 +8369,8 @@
}
-int ipw2100_get_fwversion(struct ipw2100_priv *priv, char *buf, size_t max)
+static int ipw2100_get_fwversion(struct ipw2100_priv *priv, char *buf,
+ size_t max)
{
char ver[MAX_FW_VERSION_LEN];
u32 len = MAX_FW_VERSION_LEN;
@@ -8356,7 +8389,8 @@
return tmp;
}
-int ipw2100_get_ucodeversion(struct ipw2100_priv *priv, char *buf, size_t max)
+static int ipw2100_get_ucodeversion(struct ipw2100_priv *priv, char *buf,
+ size_t max)
{
u32 ver;
u32 len = sizeof(ver);
@@ -8370,7 +8404,8 @@
/*
* On exit, the firmware will have been freed from the fw list
*/
-int ipw2100_fw_download(struct ipw2100_priv *priv, struct ipw2100_fw *fw)
+static int ipw2100_fw_download(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw)
{
/* firmware is constructed of N contiguous entries, each entry is
* structured as:
@@ -8427,7 +8462,8 @@
u8 ucode_valid;
};
-int ipw2100_ucode_download(struct ipw2100_priv *priv, struct ipw2100_fw *fw)
+static int ipw2100_ucode_download(struct ipw2100_priv *priv,
+ struct ipw2100_fw *fw)
{
struct net_device *dev = priv->net_dev;
const unsigned char *microcode_data = fw->uc.data;
^ permalink raw reply
* [2.6 patch]
From: Adrian Bunk @ 2005-07-02 21:48 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel, zippel
This patch fixes the following kconfig warning:
net/ipv4/Kconfig:92:warning: defaults for choice values not supported
Signed-off-by: Adrian Bunk <bunk@stusta.de>
---
I've Cc'ed Roman because I might have missed a more elegant solution.
--- linux-2.6.13-rc1-mm1-full/net/ipv4/Kconfig.old 2005-07-02 20:07:25.000000000 +0200
+++ linux-2.6.13-rc1-mm1-full/net/ipv4/Kconfig 2005-07-02 20:13:05.000000000 +0200
@@ -58,8 +58,9 @@
depends on IP_ADVANCED_ROUTER
default IP_FIB_HASH
-config IP_FIB_HASH
+config ASK_IP_FIB_HASH
bool "FIB_HASH"
+ select IP_FIB_HASH
---help---
Current FIB is very proven and good enough for most users.
@@ -84,12 +85,9 @@
endchoice
-# If the user does not enable advanced routing, he gets the safe
-# default of the fib-hash algorithm.
config IP_FIB_HASH
bool
- depends on !IP_ADVANCED_ROUTER
- default y
+ default y if !IP_ADVANCED_ROUTER
config IP_MULTIPLE_TABLES
bool "IP: policy routing"
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox