From 12479f9a823dc7d791f198af2d3e4efae418a65e Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Wed, 9 Nov 2005 10:35:44 -0800 Subject: [PATCH] bonding: expose some structs The sysfs code needs to know what these structs look like, so make them not static, and move the definition to the header. Signed-off-by: Mitch Williams Acked-by: Jay Vosburgh Signed-off-by: John W. Linville --- drivers/net/bonding/bonding.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net/bonding/bonding.h') diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 1433e91db0f..c8a873fe76c 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -152,6 +152,11 @@ struct bond_params { u32 arp_targets[BOND_MAX_ARP_TARGETS]; }; +struct bond_parm_tbl { + char *modename; + int mode; +}; + struct vlan_entry { struct list_head vlan_list; u32 vlan_ip; -- cgit v1.2.3-70-g09d2 From a77b53258d76513c37e766dc0db1fc9db7c4ac1e Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Wed, 9 Nov 2005 10:35:51 -0800 Subject: [PATCH] bonding: make functions not static The sysfs code needs access these functions, so make them not static, and move the protos to the header file. Signed-off-by: Mitch Williams Acked-by: Jay Vosburgh Signed-off-by: John W. Linville --- drivers/net/bonding/bond_main.c | 25 ++++++++++++------------- drivers/net/bonding/bonding.h | 12 ++++++++++++ 2 files changed, 24 insertions(+), 13 deletions(-) (limited to 'drivers/net/bonding/bonding.h') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 7139d6e6bdb..b8d617626c9 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -632,12 +632,11 @@ struct bond_parm_tbl xmit_hashtype_tbl[] = { /*-------------------------- Forward declarations ---------------------------*/ -static inline void bond_set_mode_ops(struct bonding *bond, int mode); static void bond_send_gratuitous_arp(struct bonding *bond); /*---------------------------- General routines -----------------------------*/ -static const char *bond_mode_name(int mode) +const char *bond_mode_name(int mode) { switch (mode) { case BOND_MODE_ROUNDROBIN : @@ -1453,7 +1452,7 @@ static struct slave *bond_find_best_slave(struct bonding *bond) * * Warning: Caller must hold curr_slave_lock for writing. */ -static void bond_change_active_slave(struct bonding *bond, struct slave *new_active) +void bond_change_active_slave(struct bonding *bond, struct slave *new_active) { struct slave *old_active = bond->curr_active_slave; @@ -1527,7 +1526,7 @@ static void bond_change_active_slave(struct bonding *bond, struct slave *new_act * * Warning: Caller must hold curr_slave_lock for writing. */ -static void bond_select_active_slave(struct bonding *bond) +void bond_select_active_slave(struct bonding *bond) { struct slave *best_slave; @@ -1595,7 +1594,7 @@ static void bond_detach_slave(struct bonding *bond, struct slave *slave) /*---------------------------------- IOCTL ----------------------------------*/ -static int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev) +int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev) { dprintk("bond_dev=%p\n", bond_dev); dprintk("slave_dev=%p\n", slave_dev); @@ -1635,7 +1634,7 @@ static int bond_compute_features(struct bonding *bond) } /* enslave device to bond device */ -static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) +int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) { struct bonding *bond = bond_dev->priv; struct slave *new_slave = NULL; @@ -2002,7 +2001,7 @@ err_undo_flags: * for Bonded connections: * The first up interface should be left on and all others downed. */ -static int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) +int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) { struct bonding *bond = bond_dev->priv; struct slave *slave, *oldcurrent; @@ -2403,7 +2402,7 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in /*-------------------------------- Monitoring -------------------------------*/ /* this function is called regularly to monitor each slave's link. */ -static void bond_mii_monitor(struct net_device *bond_dev) +void bond_mii_monitor(struct net_device *bond_dev) { struct bonding *bond = bond_dev->priv; struct slave *slave, *oldcurrent; @@ -2834,7 +2833,7 @@ static void bond_send_gratuitous_arp(struct bonding *bond) * arp is transmitted to generate traffic. see activebackup_arp_monitor for * arp monitoring in active backup mode. */ -static void bond_loadbalance_arp_mon(struct net_device *bond_dev) +void bond_loadbalance_arp_mon(struct net_device *bond_dev) { struct bonding *bond = bond_dev->priv; struct slave *slave, *oldcurrent; @@ -2972,7 +2971,7 @@ out: * may have received. * see loadbalance_arp_monitor for arp monitoring in load balancing mode */ -static void bond_activebackup_arp_mon(struct net_device *bond_dev) +void bond_activebackup_arp_mon(struct net_device *bond_dev) { struct bonding *bond = bond_dev->priv; struct slave *slave; @@ -4448,7 +4447,7 @@ out: /* * set bond mode specific net device operations */ -static inline void bond_set_mode_ops(struct bonding *bond, int mode) +void bond_set_mode_ops(struct bonding *bond, int mode) { struct net_device *bond_dev = bond->dev; @@ -4583,7 +4582,7 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par /* De-initialize device specific data. * Caller must hold rtnl_lock. */ -static inline void bond_deinit(struct net_device *bond_dev) +void bond_deinit(struct net_device *bond_dev) { struct bonding *bond = bond_dev->priv; @@ -4619,7 +4618,7 @@ static void bond_free_all(void) * Convert string input module parms. Accept either the * number of the mode or its string name. */ -static inline int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl) +int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl) { int i; diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index c8a873fe76c..96a733f2337 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -260,6 +260,18 @@ extern inline void bond_set_slave_active_flags(struct slave *slave) struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev); +void bond_deinit(struct net_device *bond_dev); +int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev); +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); +void bond_mii_monitor(struct net_device *bond_dev); +void bond_loadbalance_arp_mon(struct net_device *bond_dev); +void bond_activebackup_arp_mon(struct net_device *bond_dev); +void bond_set_mode_ops(struct bonding *bond, int mode); +int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl); +const char *bond_mode_name(int mode); +void bond_select_active_slave(struct bonding *bond); +void bond_change_active_slave(struct bonding *bond, struct slave *new_active); #endif /* _LINUX_BONDING_H */ -- cgit v1.2.3-70-g09d2 From dfe60397a62b1a5ebc7f05fd65463d3e29397677 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Wed, 9 Nov 2005 10:36:04 -0800 Subject: [PATCH] bonding: move bond creation into separate function The sysfs interface can create bonds at runtime, so we need a separate function to do this, instead of just doing it in the module init code. Signed-off-by: Mitch Williams Acked-by: Jay Vosburgh Signed-off-by: John W. Linville --- drivers/net/bonding/bond_main.c | 113 ++++++++++++++++++++++------------------ drivers/net/bonding/bonding.h | 1 + 2 files changed, 62 insertions(+), 52 deletions(-) (limited to 'drivers/net/bonding/bonding.h') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index b8d617626c9..2475b76e10e 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4898,81 +4898,90 @@ static int bond_check_params(struct bond_params *params) return 0; } +/* Create a new bond based on the specified name and bonding parameters. + * Caller must NOT hold rtnl_lock; we need to release it here before we + * set up our sysfs entries. + */ +int bond_create(char *name, struct bond_params *params, struct bonding **newbond) +{ + struct net_device *bond_dev; + int res; + + rtnl_lock(); + bond_dev = alloc_netdev(sizeof(struct bonding), name, ether_setup); + if (!bond_dev) { + printk(KERN_ERR DRV_NAME + ": %s: eek! can't alloc netdev!\n", + name); + res = -ENOMEM; + goto out_rtnl; + } + + /* bond_init() must be called after dev_alloc_name() (for the + * /proc files), but before register_netdevice(), because we + * need to set function pointers. + */ + + res = bond_init(bond_dev, params); + if (res < 0) { + goto out_netdev; + } + + SET_MODULE_OWNER(bond_dev); + + res = register_netdevice(bond_dev); + if (res < 0) { + goto out_bond; + } + if (newbond) + *newbond = bond_dev->priv; + + rtnl_unlock(); /* allows sysfs registration of net device */ + goto done; +out_bond: + bond_deinit(bond_dev); +out_netdev: + free_netdev(bond_dev); +out_rtnl: + rtnl_unlock(); +done: + return res; +} + static int __init bonding_init(void) { - struct bond_params params; int i; int res; + char new_bond_name[8]; /* Enough room for 999 bonds at init. */ printk(KERN_INFO "%s", version); - res = bond_check_params(¶ms); + res = bond_check_params(&bonding_defaults); if (res) { - return res; + goto out; } - rtnl_lock(); - #ifdef CONFIG_PROC_FS bond_create_proc_dir(); #endif - for (i = 0; i < max_bonds; i++) { - struct net_device *bond_dev; - - bond_dev = alloc_netdev(sizeof(struct bonding), "", ether_setup); - if (!bond_dev) { - res = -ENOMEM; - goto out_err; - } - - res = dev_alloc_name(bond_dev, "bond%d"); - if (res < 0) { - free_netdev(bond_dev); - goto out_err; - } - - /* bond_init() must be called after dev_alloc_name() (for the - * /proc files), but before register_netdevice(), because we - * need to set function pointers. - */ - res = bond_init(bond_dev, ¶ms); - if (res < 0) { - free_netdev(bond_dev); - goto out_err; - } - - SET_MODULE_OWNER(bond_dev); - - res = register_netdevice(bond_dev); - if (res < 0) { - bond_deinit(bond_dev); - free_netdev(bond_dev); - goto out_err; - } + sprintf(new_bond_name, "bond%d",i); + res = bond_create(new_bond_name,&bonding_defaults, NULL); + if (res) + goto err; } - rtnl_unlock(); register_netdevice_notifier(&bond_netdev_notifier); register_inetaddr_notifier(&bond_inetaddr_notifier); - return 0; - -out_err: - /* - * rtnl_unlock() will run netdev_run_todo(), putting the - * thus-far-registered bonding devices into a state which - * unregigister_netdevice() will accept - */ - rtnl_unlock(); + goto out; +err: rtnl_lock(); - - /* free and unregister all bonds that were successfully added */ bond_free_all(); - rtnl_unlock(); - +out: return res; + } static void __exit bonding_exit(void) diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 96a733f2337..863605aab20 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -260,6 +260,7 @@ extern inline void bond_set_slave_active_flags(struct slave *slave) struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); 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_enslave(struct net_device *bond_dev, struct net_device *slave_dev); int bond_release(struct net_device *bond_dev, struct net_device *slave_dev); -- cgit v1.2.3-70-g09d2 From b76cdba9cdb29b091cacb4c11534ffb2eac02f64 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Wed, 9 Nov 2005 10:36:41 -0800 Subject: [PATCH] bonding: add sysfs functionality to bonding (large) This large patch adds sysfs functionality to the channel bonding module. Bonds can be added, removed, and reconfigured at runtime without having to reload the module. Multiple bonds with different configurations are easily configured, and ifenslave is no longer required to configure bonds. Signed-off-by: Mitch Williams Acked-by: Jay Vosburgh Signed-off-by: John W. Linville --- drivers/net/bonding/Makefile | 2 +- drivers/net/bonding/bond_main.c | 23 +- drivers/net/bonding/bond_sysfs.c | 1399 ++++++++++++++++++++++++++++++++++++++ drivers/net/bonding/bonding.h | 7 + 4 files changed, 1429 insertions(+), 2 deletions(-) create mode 100644 drivers/net/bonding/bond_sysfs.c (limited to 'drivers/net/bonding/bonding.h') diff --git a/drivers/net/bonding/Makefile b/drivers/net/bonding/Makefile index cf50384b469..5cdae2bc055 100644 --- a/drivers/net/bonding/Makefile +++ b/drivers/net/bonding/Makefile @@ -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 diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index d5415ba9bdb..5ac9718c598 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -600,6 +600,7 @@ LIST_HEAD(bond_dev_list); 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; @@ -1960,6 +1961,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) write_unlock_bh(&bond->lock); + 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, @@ -2133,6 +2138,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) 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 @@ -2224,6 +2232,7 @@ static int bond_release_all(struct net_device *bond_dev) */ 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 @@ -3518,7 +3527,10 @@ static int bond_event_changename(struct bonding *bond) 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; } @@ -3995,6 +4007,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd return -EPERM; } + down_write(&(bonding_rwsem)); slave_dev = dev_get_by_name(ifr->ifr_slave); dprintk("slave_dev=%p: \n", slave_dev); @@ -4027,6 +4040,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd dev_put(slave_dev); } + up_write(&(bonding_rwsem)); return res; } @@ -4962,6 +4976,7 @@ int bond_create(char *name, struct bond_params *params, struct bonding **newbond *newbond = bond_dev->priv; rtnl_unlock(); /* allows sysfs registration of net device */ + res = bond_create_sysfs_entry(bond_dev->priv); goto done; out_bond: bond_deinit(bond_dev); @@ -4996,6 +5011,10 @@ static int __init bonding_init(void) goto err; } + res = bond_create_sysfs(); + if (res) + goto err; + register_netdevice_notifier(&bond_netdev_notifier); register_inetaddr_notifier(&bond_inetaddr_notifier); @@ -5003,6 +5022,7 @@ static int __init bonding_init(void) err: rtnl_lock(); bond_free_all(); + bond_destroy_sysfs(); rtnl_unlock(); out: return res; @@ -5016,6 +5036,7 @@ static void __exit bonding_exit(void) rtnl_lock(); bond_free_all(); + bond_destroy_sysfs(); rtnl_unlock(); } diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c new file mode 100644 index 00000000000..c5f1c52863c --- /dev/null +++ b/drivers/net/bonding/bond_sysfs.c @@ -0,0 +1,1399 @@ + +/* + * 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 + * - Initial creation of sysfs interface. + * + * 2005/06/22 - Radheka Godse + * - 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 + * + * 2005/09/19 - Mitch Williams + * - Changed semantics of multi-item files to be command-based + * instead of list-based. + * - Changed ARP target handler to use in_aton instead of sscanf + * - Style changes. + * 2005/09/27 - Mitch Williams + * - Made line endings consistent. + * - Removed "none" from primary output - just put blank instead + * - Fixed bug with long interface names + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* #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 -------------------------------*/ + + +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 int expected_refcount = -1; +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. + * This lock is only needed when deleting a bond - we need to make sure + * that we don't collide with an ongoing ioctl. + */ + +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) { + if (res > (PAGE_SIZE - IFNAMSIZ)) { + /* not enough space for another interface name */ + if ((PAGE_SIZE - res) > 10) + res = PAGE_SIZE - 10; + res += sprintf(buffer + res, "++more++"); + break; + } + res += sprintf(buffer + res, "%s ", + bond->dev->name); + } + 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. + * + */ + +static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t count) +{ + char command[IFNAMSIZ + 1] = {0, }; + char *ifname; + int res = count; + struct bonding *bond; + struct bonding *nxt; + + down_write(&(bonding_rwsem)); + sscanf(buffer, "%16s", command); /* IFNAMSIZ*/ + ifname = command + 1; + if ((strlen(command) <= 1) || + !dev_valid_name(ifname)) + goto err_no_cmd; + + if (command[0] == '+') { + + /* Check to see if the bond already exists. */ + list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) + if (strnicmp(bond->dev->name, ifname, IFNAMSIZ) == 0) { + printk(KERN_ERR DRV_NAME + ": cannot add bond %s; it already exists\n", + ifname); + res = -EPERM; + goto out; + } + + printk(KERN_INFO DRV_NAME + ": %s is being created...\n", ifname); + if (bond_create(ifname, &bonding_defaults, &bond)) { + printk(KERN_INFO DRV_NAME + ": %s interface already exists. Bond creation failed.\n", + ifname); + res = -EPERM; + } + goto out; + } + + if (command[0] == '-') { + list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) + if (strnicmp(bond->dev->name, ifname, IFNAMSIZ) == 0) { + rtnl_lock(); + /* check the ref count on the bond's kobject. + * If it's > expected, then there's a file open, + * and we have to fail. + */ + if (atomic_read(&bond->dev->class_dev.kobj.kref.refcount) + > expected_refcount){ + rtnl_unlock(); + printk(KERN_INFO DRV_NAME + ": Unable remove bond %s due to open references.\n", + ifname); + res = -EPERM; + goto out; + } + printk(KERN_INFO DRV_NAME + ": %s is being deleted...\n", + bond->dev->name); + unregister_netdevice(bond->dev); + bond_deinit(bond->dev); + bond_destroy_sysfs_entry(bond); + rtnl_unlock(); + goto out; + } + + printk(KERN_ERR DRV_NAME + ": unable to delete non-existent bond %s\n", ifname); + res = -ENODEV; + goto out; + } + +err_no_cmd: + printk(KERN_ERR DRV_NAME + ": no command found in bonding_masters. Use +ifname or -ifname.\n"); + res = -EPERM; + + /* Always return either count or an error. If you return 0, you'll + * get called forever, which is bad. + */ +out: + up_write(&(bonding_rwsem)); + return res; +} +/* 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); + + read_lock_bh(&bond->lock); + bond_for_each_slave(bond, slave, i) { + if (res > (PAGE_SIZE - IFNAMSIZ)) { + /* not enough space for another interface name */ + if ((PAGE_SIZE - res) > 10) + res = PAGE_SIZE - 10; + res += sprintf(buf + res, "++more++"); + break; + } + res += sprintf(buf + res, "%s ", slave->dev->name); + } + read_unlock_bh(&bond->lock); + res += sprintf(buf + res, "\n"); + res++; + 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 command[IFNAMSIZ + 1] = { 0, }; + char *ifname; + int i, res, found, ret = count; + struct slave *slave; + struct net_device *dev = 0; + struct bonding *bond = to_bond(cd); + + /* 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. */ + + sscanf(buffer, "%16s", command); /* IFNAMSIZ*/ + ifname = command + 1; + if ((strlen(command) <= 1) || + !dev_valid_name(ifname)) + goto err_no_cmd; + + if (command[0] == '+') { + + /* Got a slave name in ifname. Is it already in the list? */ + found = 0; + read_lock_bh(&bond->lock); + bond_for_each_slave(bond, slave, i) + if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) { + printk(KERN_ERR DRV_NAME + ": %s: Interface %s is already enslaved!\n", + bond->dev->name, ifname); + ret = -EPERM; + read_unlock_bh(&bond->lock); + goto out; + } + + read_unlock_bh(&bond->lock); + printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n", + bond->dev->name, ifname); + dev = dev_get_by_name(ifname); + if (!dev) { + printk(KERN_INFO DRV_NAME + ": %s: Interface %s does not exist!\n", + bond->dev->name, ifname); + ret = -EPERM; + goto out; + } + else + dev_put(dev); + + if (dev->flags & IFF_UP) { + printk(KERN_ERR DRV_NAME + ": %s: Error: Unable to enslave %s " + "because it is already up.\n", + bond->dev->name, dev->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); + rtnl_unlock(); + if (res) { + ret = res; + } + goto out; + } + + if (command[0] == '-') { + dev = NULL; + bond_for_each_slave(bond, slave, i) + if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) { + dev = slave->dev; + break; + } + if (dev) { + printk(KERN_INFO DRV_NAME ": %s: Removing slave %s\n", + bond->dev->name, dev->name); + 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; + } + } + else { + printk(KERN_ERR DRV_NAME ": unable to remove non-existent slave %s for bond %s.\n", + ifname, bond->dev->name); + ret = -ENODEV; + } + goto out; + } + +err_no_cmd: + printk(KERN_ERR DRV_NAME ": no command found in slaves file for bond %s. Use +ifname or -ifname.\n", bond->dev->name); + ret = -EPERM; + +out: + 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) +{ + struct bonding *bond = to_bond(cd); + + return sprintf(buf, "%s %d\n", + bond_mode_tbl[bond->params.mode].modename, + bond->params.mode) + 1; +} + +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); + + 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: + 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); + + 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; + } + + 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); + + 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: + 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) +{ + struct bonding *bond = to_bond(cd); + + return sprintf(buf, "%d\n", bond->params.arp_interval) + 1; +} + +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); + + if (sscanf(buf, "%d", &new_value) != 1) { + printk(KERN_ERR DRV_NAME + ": %s: no arp_interval value specified.\n", + bond->dev->name); + ret = -EINVAL; + goto out; + } + if (new_value < 0) { + printk(KERN_ERR DRV_NAME + ": %s: Invalid arp_interval value %d not in range 1-%d; rejected.\n", + bond->dev->name, new_value, INT_MAX); + ret = -EINVAL; + goto out; + } + + 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: + 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); + + for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) { + if (bond->params.arp_targets[i]) + res += sprintf(buf + res, "%u.%u.%u.%u ", + NIPQUAD(bond->params.arp_targets[i])); + } + if (res) + res--; /* eat the leftover space */ + res += sprintf(buf + res, "\n"); + res++; + return res; +} + +static ssize_t bonding_store_arp_targets(struct class_device *cd, const char *buf, size_t count) +{ + u32 newtarget; + int i = 0, done = 0, ret = count; + struct bonding *bond = to_bond(cd); + u32 *targets; + + targets = bond->params.arp_targets; + newtarget = in_aton(buf + 1); + /* look for adds */ + if (buf[0] == '+') { + if ((newtarget == 0) || (newtarget == INADDR_BROADCAST)) { + printk(KERN_ERR DRV_NAME + ": %s: invalid ARP target %u.%u.%u.%u specified for addition\n", + bond->dev->name, NIPQUAD(newtarget)); + ret = -EINVAL; + goto out; + } + /* look for an empty slot to put the target in, and check for dupes */ + for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) { + if (targets[i] == newtarget) { /* duplicate */ + printk(KERN_ERR DRV_NAME + ": %s: ARP target %u.%u.%u.%u is already present\n", + bond->dev->name, NIPQUAD(newtarget)); + if (done) + targets[i] = 0; + ret = -EINVAL; + goto out; + } + if (targets[i] == 0 && !done) { + printk(KERN_INFO DRV_NAME + ": %s: adding ARP target %d.%d.%d.%d.\n", + bond->dev->name, NIPQUAD(newtarget)); + done = 1; + targets[i] = newtarget; + } + } + if (!done) { + printk(KERN_ERR DRV_NAME + ": %s: ARP target table is full!\n", + bond->dev->name); + ret = -EINVAL; + goto out; + } + + } + else if (buf[0] == '-') { + if ((newtarget == 0) || (newtarget == INADDR_BROADCAST)) { + printk(KERN_ERR DRV_NAME + ": %s: invalid ARP target %d.%d.%d.%d specified for removal\n", + bond->dev->name, NIPQUAD(newtarget)); + ret = -EINVAL; + goto out; + } + + for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) { + if (targets[i] == newtarget) { + printk(KERN_INFO DRV_NAME + ": %s: removing ARP target %d.%d.%d.%d.\n", + bond->dev->name, NIPQUAD(newtarget)); + targets[i] = 0; + done = 1; + } + } + if (!done) { + printk(KERN_INFO DRV_NAME + ": %s: unable to remove nonexistent ARP target %d.%d.%d.%d.\n", + bond->dev->name, NIPQUAD(newtarget)); + ret = -EINVAL; + goto out; + } + } + else { + printk(KERN_ERR DRV_NAME ": no command found in arp_ip_targets file for bond %s. Use + or -.\n", + bond->dev->name); + ret = -EPERM; + goto out; + } + +out: + 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) +{ + struct bonding *bond = to_bond(cd); + + return sprintf(buf, "%d\n", bond->params.downdelay * bond->params.miimon) + 1; +} + +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); + + 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; + } + + if (sscanf(buf, "%d", &new_value) != 1) { + printk(KERN_ERR DRV_NAME + ": %s: no down delay value specified.\n", + bond->dev->name); + ret = -EINVAL; + goto out; + } + 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: + return ret; +} +static CLASS_DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR , bonding_show_downdelay, bonding_store_downdelay); + +static ssize_t bonding_show_updelay(struct class_device *cd, char *buf) +{ + struct bonding *bond = to_bond(cd); + + return sprintf(buf, "%d\n", bond->params.updelay * bond->params.miimon) + 1; + +} + +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); + + 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; + } + + if (sscanf(buf, "%d", &new_value) != 1) { + printk(KERN_ERR DRV_NAME + ": %s: no up delay value specified.\n", + bond->dev->name); + ret = -EINVAL; + goto out; + } + 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: + return ret; +} +static CLASS_DEVICE_ATTR(updelay, 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) +{ + struct bonding *bond = to_bond(cd); + + return sprintf(buf, "%s %d\n", + bond_lacp_tbl[bond->params.lacp_fast].modename, + bond->params.lacp_fast) + 1; +} + +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); + + 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: + 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) +{ + struct bonding *bond = to_bond(cd); + + return sprintf(buf, "%d\n", bond->params.miimon) + 1; +} + +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); + + if (sscanf(buf, "%d", &new_value) != 1) { + printk(KERN_ERR DRV_NAME + ": %s: no miimon value specified.\n", + bond->dev->name); + ret = -EINVAL; + goto out; + } + 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: + 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); + + if (bond->primary_slave) + count = sprintf(buf, "%s\n", bond->primary_slave->dev->name) + 1; + else + count = sprintf(buf, "\n") + 1; + + 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); + + 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); + 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) +{ + struct bonding *bond = to_bond(cd); + + return sprintf(buf, "%d\n", bond->params.use_carrier) + 1; +} + +static ssize_t bonding_store_carrier(struct class_device *cd, const char *buf, size_t count) +{ + int new_value, ret = count; + struct bonding *bond = to_bond(cd); + + + if (sscanf(buf, "%d", &new_value) != 1) { + printk(KERN_ERR DRV_NAME + ": %s: no use_carrier value specified.\n", + bond->dev->name); + ret = -EINVAL; + goto out; + } + 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); + } +out: + 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; + + + read_lock(&bond->curr_slave_lock); + curr = bond->curr_active_slave; + read_unlock(&bond->curr_slave_lock); + + if (USES_PRIMARY(bond->params.mode) && curr) + count = sprintf(buf, "%s\n", curr->dev->name) + 1; + else + count = sprintf(buf, "\n") + 1; + 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); + + 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); + 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) +{ + struct slave *curr; + struct bonding *bond = to_bond(cd); + + read_lock(&bond->curr_slave_lock); + curr = bond->curr_active_slave; + read_unlock(&bond->curr_slave_lock); + + return sprintf(buf, "%s\n", (curr) ? "up" : "down") + 1; +} +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); + + 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; + } + else + count = sprintf(buf, "\n") + 1; + + 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); + + 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; + } + else + count = sprintf(buf, "\n") + 1; + + 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); + + 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; + } + else + count = sprintf(buf, "\n") + 1; + + 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); + + 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; + } + else + count = sprintf(buf, "\n") + 1; + + 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); + + 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; + } + } + else + count = sprintf(buf, "\n") + 1; + + 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_downdelay.attr, + &class_device_attr_updelay.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"); + } + + if (expected_refcount < 1) + expected_refcount = atomic_read(&bond->dev->class_dev.kobj.kref.refcount); + + 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 --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 863605aab20..903e60aa611 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -37,6 +37,7 @@ #include #include #include +#include #include "bond_3ad.h" #include "bond_alb.h" @@ -262,6 +263,12 @@ struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr) 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_enslave(struct net_device *bond_dev, struct net_device *slave_dev); 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); -- cgit v1.2.3-70-g09d2 From 39755cad88f7b26dcb1edf9dcf14bd85f8fc2a3a Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Wed, 9 Nov 2005 10:36:46 -0800 Subject: [PATCH] bonding: version update Update the version number for the bonding module. Since we've just added a significant new feature (sysfs support), bump the major number. Signed-off-by: Mitch Williams Acked-by: Jay Vosburgh Signed-off-by: John W. Linville --- drivers/net/bonding/bonding.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/bonding/bonding.h') diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 903e60aa611..88b8981d24b 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -41,8 +41,8 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "2.6.5" -#define DRV_RELDATE "November 4, 2005" +#define DRV_VERSION "3.0.0" +#define DRV_RELDATE "November 8, 2005" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" -- cgit v1.2.3-70-g09d2 From e944ef79184ff7f283e7bf79496d2873a0b0410b Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Wed, 9 Nov 2005 10:36:50 -0800 Subject: [PATCH] bonding: spelling and whitespace corrections Minor spelling and whitespace corrections. Signed-off-by: Mitch Williams Acked-by: Jay Vosburgh Signed-off-by: John W. Linville --- drivers/net/bonding/bond_alb.c | 2 +- drivers/net/bonding/bond_main.c | 1 + drivers/net/bonding/bonding.h | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/net/bonding/bonding.h') diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 24f4a3d1499..9bd1e104554 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -1417,7 +1417,7 @@ void bond_alb_monitor(struct bonding *bond) 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 --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 5ac9718c598..c7cd6b96d2c 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4125,6 +4125,7 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu) 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) { diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 88b8981d24b..ef4b11c4006 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -165,7 +165,7 @@ struct vlan_entry { }; 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 @@ struct slave { * 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; -- cgit v1.2.3-70-g09d2 From 691b73b13220886aefacb7c7f7ace7f528bbf800 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Wed, 9 Nov 2005 10:36:57 -0800 Subject: [PATCH] bonding: comments and changelog Bonding source files still have changelogs in the comments. This, then, is an update to that changelog. Signed-off-by: Mitch Williams Acked-by: Jay Vosburgh Signed-off-by: John W. Linville --- drivers/net/bonding/bond_main.c | 22 ++++++++++++++++++++++ drivers/net/bonding/bonding.h | 4 ++++ 2 files changed, 26 insertions(+) (limited to 'drivers/net/bonding/bonding.h') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index c7cd6b96d2c..40ff79175c4 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -489,6 +489,28 @@ * Set version to 2.6.3. * 2005/09/26 - Jay Vosburgh * - Removed backwards compatibility for old ifenslaves. Version 2.6.4. + * 2005/09/27 - Mitch Williams + * - Radheka Godse + * - Split out bond creation code to allow for sysfs interface. + * - 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: : prefix to sysfs log messages + * - Added arp_ip_targets to /proc entry + * - Allow ARP target table to have empty entries + * - 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: : 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 diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index ef4b11c4006..d6d085480f2 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -29,6 +29,10 @@ * 2005/05/05 - Jason Gabler * - added "xmit_policy" kernel parameter for alternate hashing policy * support for mode 2 + * + * 2005/09/27 - Mitch Williams + * Radheka Godse + * - Added bonding sysfs interface */ #ifndef _LINUX_BONDING_H -- cgit v1.2.3-70-g09d2 From 2e06cb5859fdaeba0529806eb1bf161ffd0db201 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Mon, 28 Nov 2005 13:54:22 -0500 Subject: [bonding] Remove superfluous changelog. No need to record this information in source code, its all in the git repository, and kernel archives. --- drivers/net/bonding/bond_3ad.c | 32 --- drivers/net/bonding/bond_3ad.h | 13 -- drivers/net/bonding/bond_alb.c | 19 -- drivers/net/bonding/bond_alb.h | 9 - drivers/net/bonding/bond_main.c | 482 --------------------------------------- drivers/net/bonding/bond_sysfs.c | 41 ---- drivers/net/bonding/bonding.h | 23 -- 7 files changed, 619 deletions(-) (limited to 'drivers/net/bonding/bonding.h') diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 04705233ca0..f3f5825469d 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -18,38 +18,6 @@ * The full GNU General Public License is included in this distribution in the * file called LICENSE. * - * - * Changes: - * - * 2003/05/01 - Tsippy Mendelson and - * Amir Noam - * - Added support for lacp_rate module param. - * - * 2003/05/01 - Shmulik Hen - * - Based on discussion on mailing list, changed locking scheme - * to use lock/unlock or lock_bh/unlock_bh appropriately instead - * of lock_irqsave/unlock_irqrestore. The new scheme helps exposing - * hidden bugs and solves system hangs that occurred due to the fact - * that holding lock_irqsave doesn't prevent softirqs from running. - * This also increases total throughput since interrupts are not - * blocked on each transmitted packets or monitor timeout. - * - * 2003/05/01 - Shmulik Hen - * - Renamed bond_3ad_link_status_changed() to - * bond_3ad_handle_link_change() for compatibility with TLB. - * - * 2003/05/20 - Amir Noam - * - Fix long fail over time when releasing last slave of an active - * aggregator - send LACPDU on unbind of slave to tell partner this - * port is no longer aggregatable. - * - * 2003/06/25 - Tsippy Mendelson - * - Send LACPDU as highest priority packet to further fix the above - * problem on very high Tx traffic load where packets may get dropped - * by the slave. - * - * 2003/12/01 - Shmulik Hen - * - Code cleanup and style changes */ //#define BONDING_DEBUG 1 diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h index 673a30af566..5ee2cef5b03 100644 --- a/drivers/net/bonding/bond_3ad.h +++ b/drivers/net/bonding/bond_3ad.h @@ -18,19 +18,6 @@ * The full GNU General Public License is included in this distribution in the * file called LICENSE. * - * - * Changes: - * - * 2003/05/01 - Tsippy Mendelson and - * Amir Noam - * - Added support for lacp_rate module param. - * - * 2003/05/01 - Shmulik Hen - * - Renamed bond_3ad_link_status_changed() to - * bond_3ad_handle_link_change() for compatibility with TLB. - * - * 2003/12/01 - Shmulik Hen - * - Code cleanup and style changes */ #ifndef __BOND_3AD_H__ diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 9bd1e104554..854ddfb90da 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -18,25 +18,6 @@ * The full GNU General Public License is included in this distribution in the * file called LICENSE. * - * - * Changes: - * - * 2003/06/25 - Shmulik Hen - * - Fixed signed/unsigned calculation errors that caused load sharing - * to collapse to one slave under very heavy UDP Tx stress. - * - * 2003/08/06 - Amir Noam - * - Add support for setting bond's MAC address with special - * handling required for ALB/TLB. - * - * 2003/12/01 - Shmulik Hen - * - Code cleanup and style changes - * - * 2003/12/30 - Amir Noam - * - Fixed: Cannot remove and re-enslave the original active slave. - * - * 2004/01/14 - Shmulik Hen - * - Add capability to tag self generated packets in ALB/TLB modes. */ //#define BONDING_DEBUG 1 diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h index e4091cd8d65..28f2a2fd1b5 100644 --- a/drivers/net/bonding/bond_alb.h +++ b/drivers/net/bonding/bond_alb.h @@ -18,15 +18,6 @@ * The full GNU General Public License is included in this distribution in the * file called LICENSE. * - * - * Changes: - * - * 2003/08/06 - Amir Noam - * - Add support for setting bond's MAC address with special - * handling required for ALB/TLB. - * - * 2003/12/01 - Shmulik Hen - * - Code cleanup and style changes */ #ifndef __BOND_ALB_H__ diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 40ff79175c4..2582d98ef5c 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -29,488 +29,6 @@ * b: if a hw mac address already is there, eth0's hw mac address * will then be set from bond0. * - * v0.1 - first working version. - * v0.2 - changed stats to be calculated by summing slaves stats. - * - * Changes: - * Arnaldo Carvalho de Melo - * - fix leaks on failure at bond_init - * - * 2000/09/30 - Willy Tarreau - * - added trivial code to release a slave device. - * - fixed security bug (CAP_NET_ADMIN not checked) - * - implemented MII link monitoring to disable dead links : - * All MII capable slaves are checked every milliseconds - * (100 ms seems good). This value can be changed by passing it to - * insmod. A value of zero disables the monitoring (default). - * - fixed an infinite loop in bond_xmit_roundrobin() when there's no - * good slave. - * - made the code hopefully SMP safe - * - * 2000/10/03 - Willy Tarreau - * - optimized slave lists based on relevant suggestions from Thomas Davis - * - implemented active-backup method to obtain HA with two switches: - * stay as long as possible on the same active interface, while we - * also monitor the backup one (MII link status) because we want to know - * if we are able to switch at any time. ( pass "mode=1" to insmod ) - * - lots of stress testings because we need it to be more robust than the - * wires ! :-> - * - * 2000/10/09 - Willy Tarreau - * - added up and down delays after link state change. - * - optimized the slaves chaining so that when we run forward, we never - * repass through the bond itself, but we can find it by searching - * backwards. Renders the deletion more difficult, but accelerates the - * scan. - * - smarter enslaving and releasing. - * - finer and more robust SMP locking - * - * 2000/10/17 - Willy Tarreau - * - fixed two potential SMP race conditions - * - * 2000/10/18 - Willy Tarreau - * - small fixes to the monitoring FSM in case of zero delays - * 2000/11/01 - Willy Tarreau - * - fixed first slave not automatically used in trunk mode. - * 2000/11/10 : spelling of "EtherChannel" corrected. - * 2000/11/13 : fixed a race condition in case of concurrent accesses to ioctl(). - * 2000/12/16 : fixed improper usage of rtnl_exlock_nowait(). - * - * 2001/1/3 - Chad N. Tindel - * - The bonding driver now simulates MII status monitoring, just like - * a normal network device. It will show that the link is down iff - * every slave in the bond shows that their links are down. If at least - * one slave is up, the bond's MII status will appear as up. - * - * 2001/2/7 - Chad N. Tindel - * - Applications can now query the bond from user space to get - * information which may be useful. They do this by calling - * the BOND_INFO_QUERY ioctl. Once the app knows how many slaves - * are in the bond, it can call the BOND_SLAVE_INFO_QUERY ioctl to - * get slave specific information (# link failures, etc). See - * for more details. The structs of interest - * are ifbond and ifslave. - * - * 2001/4/5 - Chad N. Tindel - * - Ported to 2.4 Kernel - * - * 2001/5/2 - Jeffrey E. Mast - * - When a device is detached from a bond, the slave device is no longer - * left thinking that is has a master. - * - * 2001/5/16 - Jeffrey E. Mast - * - memset did not appropriately initialized the bond rw_locks. Used - * rwlock_init to initialize to unlocked state to prevent deadlock when - * first attempting a lock - * - Called SET_MODULE_OWNER for bond device - * - * 2001/5/17 - Tim Anderson - * - 2 paths for releasing for slave release; 1 through ioctl - * and 2) through close. Both paths need to release the same way. - * - the free slave in bond release is changing slave status before - * the free. The netdev_set_master() is intended to change slave state - * so it should not be done as part of the release process. - * - Simple rule for slave state at release: only the active in A/B and - * only one in the trunked case. - * - * 2001/6/01 - Tim Anderson - * - Now call dev_close when releasing a slave so it doesn't screw up - * out routing table. - * - * 2001/6/01 - Chad N. Tindel - * - Added /proc support for getting bond and slave information. - * Information is in /proc/net//info. - * - Changed the locking when calling bond_close to prevent deadlock. - * - * 2001/8/05 - Janice Girouard - * - correct problem where refcnt of slave is not incremented in bond_ioctl - * so the system hangs when halting. - * - correct locking problem when unable to malloc in bond_enslave. - * - adding bond_xmit_xor logic. - * - adding multiple bond device support. - * - * 2001/8/13 - Erik Habbinga - * - correct locking problem with rtnl_exlock_nowait - * - * 2001/8/23 - Janice Girouard - * - bzero initial dev_bonds, to correct oops - * - convert SIOCDEVPRIVATE to new MII ioctl calls - * - * 2001/9/13 - Takao Indoh - * - Add the BOND_CHANGE_ACTIVE ioctl implementation - * - * 2001/9/14 - Mark Huth - * - Change MII_LINK_READY to not check for end of auto-negotiation, - * but only for an up link. - * - * 2001/9/20 - Chad N. Tindel - * - Add the device field to bonding_t. Previously the net_device - * corresponding to a bond wasn't available from the bonding_t - * structure. - * - * 2001/9/25 - Janice Girouard - * - add arp_monitor for active backup mode - * - * 2001/10/23 - Takao Indoh - * - Various memory leak fixes - * - * 2001/11/5 - Mark Huth - * - Don't take rtnl lock in bond_mii_monitor as it deadlocks under - * certain hotswap conditions. - * Note: this same change may be required in bond_arp_monitor ??? - * - Remove possibility of calling bond_sethwaddr with NULL slave_dev ptr - * - Handle hot swap ethernet interface deregistration events to remove - * kernel oops following hot swap of enslaved interface - * - * 2002/1/2 - Chad N. Tindel - * - Restore original slave flags at release time. - * - * 2002/02/18 - Erik Habbinga - * - bond_release(): calling kfree on our_slave after call to - * bond_restore_slave_flags, not before - * - bond_enslave(): saving slave flags into original_flags before - * call to netdev_set_master, so the IFF_SLAVE flag doesn't end - * up in original_flags - * - * 2002/04/05 - Mark Smith and - * Steve Mead - * - Port Gleb Natapov's multicast support patchs from 2.4.12 - * to 2.4.18 adding support for multicast. - * - * 2002/06/10 - Tony Cureington - * - corrected uninitialized pointer (ifr.ifr_data) in bond_check_dev_link; - * actually changed function to use MIIPHY, then MIIREG, and finally - * ETHTOOL to determine the link status - * - fixed bad ifr_data pointer assignments in bond_ioctl - * - corrected mode 1 being reported as active-backup in bond_get_info; - * also added text to distinguish type of load balancing (rr or xor) - * - change arp_ip_target module param from "1-12s" (array of 12 ptrs) - * to "s" (a single ptr) - * - * 2002/08/30 - Jay Vosburgh - * - Removed acquisition of xmit_lock in set_multicast_list; caused - * deadlock on SMP (lock is held by caller). - * - Revamped SIOCGMIIPHY, SIOCGMIIREG portion of bond_check_dev_link(). - * - * 2002/09/18 - Jay Vosburgh - * - Fixed up bond_check_dev_link() (and callers): removed some magic - * numbers, banished local MII_ defines, wrapped ioctl calls to - * prevent EFAULT errors - * - * 2002/9/30 - Jay Vosburgh - * - make sure the ip target matches the arp_target before saving the - * hw address. - * - * 2002/9/30 - Dan Eisner - * - make sure my_ip is set before taking down the link, since - * not all switches respond if the source ip is not set. - * - * 2002/10/8 - Janice Girouard - * - read in the local ip address when enslaving a device - * - add primary support - * - make sure 2*arp_interval has passed when a new device - * is brought on-line before taking it down. - * - * 2002/09/11 - Philippe De Muyter - * - Added bond_xmit_broadcast logic. - * - Added bond_mode() support function. - * - * 2002/10/26 - Laurent Deniel - * - allow to register multicast addresses only on active slave - * (useful in active-backup mode) - * - add multicast module parameter - * - fix deletion of multicast groups after unloading module - * - * 2002/11/06 - Kameshwara Rayaprolu - * - Changes to prevent panic from closing the device twice; if we close - * the device in bond_release, we must set the original_flags to down - * so it won't be closed again by the network layer. - * - * 2002/11/07 - Tony Cureington - * - Fix arp_target_hw_addr memory leak - * - Created activebackup_arp_monitor function to handle arp monitoring - * in active backup mode - the bond_arp_monitor had several problems... - * such as allowing slaves to tx arps sequentially without any delay - * for a response - * - Renamed bond_arp_monitor to loadbalance_arp_monitor and re-wrote - * this function to just handle arp monitoring in load-balancing mode; - * it is a lot more compact now - * - Changes to ensure one and only one slave transmits in active-backup - * mode - * - Robustesize parameters; warn users about bad combinations of - * parameters; also if miimon is specified and a network driver does - * not support MII or ETHTOOL, inform the user of this - * - Changes to support link_failure_count when in arp monitoring mode - * - Fix up/down delay reported in /proc - * - Added version; log version; make version available from "modinfo -d" - * - Fixed problem in bond_check_dev_link - if the first IOCTL (SIOCGMIIPH) - * failed, the ETHTOOL ioctl never got a chance - * - * 2002/11/16 - Laurent Deniel - * - fix multicast handling in activebackup_arp_monitor - * - remove one unnecessary and confusing curr_active_slave == slave test - * in activebackup_arp_monitor - * - * 2002/11/17 - Laurent Deniel - * - fix bond_slave_info_query when slave_id = num_slaves - * - * 2002/11/19 - Janice Girouard - * - correct ifr_data reference. Update ifr_data reference - * to mii_ioctl_data struct values to avoid confusion. - * - * 2002/11/22 - Bert Barbe - * - Add support for multiple arp_ip_target - * - * 2002/12/13 - Jay Vosburgh - * - Changed to allow text strings for mode and multicast, e.g., - * insmod bonding mode=active-backup. The numbers still work. - * One change: an invalid choice will cause module load failure, - * rather than the previous behavior of just picking one. - * - Minor cleanups; got rid of dup ctype stuff, atoi function - * - * 2003/02/07 - Jay Vosburgh - * - Added use_carrier module parameter that causes miimon to - * use netif_carrier_ok() test instead of MII/ETHTOOL ioctls. - * - Minor cleanups; consolidated ioctl calls to one function. - * - * 2003/02/07 - Tony Cureington - * - Fix bond_mii_monitor() logic error that could result in - * bonding round-robin mode ignoring links after failover/recovery - * - * 2003/03/17 - Jay Vosburgh - * - kmalloc fix (GFP_KERNEL to GFP_ATOMIC) reported by - * Shmulik dot Hen at intel.com. - * - Based on discussion on mailing list, changed use of - * update_slave_cnt(), created wrapper functions for adding/removing - * slaves, changed bond_xmit_xor() to check slave_cnt instead of - * checking slave and slave->dev (which only worked by accident). - * - Misc code cleanup: get arp_send() prototype from header file, - * add max_bonds to bonding.txt. - * - * 2003/03/18 - Tsippy Mendelson and - * Shmulik Hen - * - Make sure only bond_attach_slave() and bond_detach_slave() can - * manipulate the slave list, including slave_cnt, even when in - * bond_release_all(). - * - Fixed hang in bond_release() with traffic running: - * netdev_set_master() must not be called from within the bond lock. - * - * 2003/03/18 - Tsippy Mendelson and - * Shmulik Hen - * - Fixed hang in bond_enslave() with traffic running: - * netdev_set_master() must not be called from within the bond lock. - * - * 2003/03/18 - Amir Noam - * - Added support for getting slave's speed and duplex via ethtool. - * Needed for 802.3ad and other future modes. - * - * 2003/03/18 - Tsippy Mendelson and - * Shmulik Hen - * - Enable support of modes that need to use the unique mac address of - * each slave. - * * bond_enslave(): Moved setting the slave's mac address, and - * openning it, from the application to the driver. This breaks - * backward comaptibility with old versions of ifenslave that open - * the slave before enalsving it !!!. - * * bond_release(): The driver also takes care of closing the slave - * and restoring its original mac address. - * - Removed the code that restores all base driver's flags. - * Flags are automatically restored once all undo stages are done - * properly. - * - Block possibility of enslaving before the master is up. This - * prevents putting the system in an unstable state. - * - * 2003/03/18 - Amir Noam , - * Tsippy Mendelson and - * Shmulik Hen - * - Added support for IEEE 802.3ad Dynamic link aggregation mode. - * - * 2003/05/01 - Amir Noam - * - Added ABI version control to restore compatibility between - * new/old ifenslave and new/old bonding. - * - * 2003/05/01 - Shmulik Hen - * - Fixed bug in bond_release_all(): save old value of curr_active_slave - * before setting it to NULL. - * - Changed driver versioning scheme to include version number instead - * of release date (that is already in another field). There are 3 - * fields X.Y.Z where: - * X - Major version - big behavior changes - * Y - Minor version - addition of features - * Z - Extra version - minor changes and bug fixes - * The current version is 1.0.0 as a base line. - * - * 2003/05/01 - Tsippy Mendelson and - * Amir Noam - * - Added support for lacp_rate module param. - * - Code beautification and style changes (mainly in comments). - * new version - 1.0.1 - * - * 2003/05/01 - Shmulik Hen - * - Based on discussion on mailing list, changed locking scheme - * to use lock/unlock or lock_bh/unlock_bh appropriately instead - * of lock_irqsave/unlock_irqrestore. The new scheme helps exposing - * hidden bugs and solves system hangs that occurred due to the fact - * that holding lock_irqsave doesn't prevent softirqs from running. - * This also increases total throughput since interrupts are not - * blocked on each transmitted packets or monitor timeout. - * new version - 2.0.0 - * - * 2003/05/01 - Shmulik Hen - * - Added support for Transmit load balancing mode. - * - Concentrate all assignments of curr_active_slave to a single point - * so specific modes can take actions when the primary adapter is - * changed. - * - Take the updelay parameter into consideration during bond_enslave - * since some adapters loose their link during setting the device. - * - Renamed bond_3ad_link_status_changed() to - * bond_3ad_handle_link_change() for compatibility with TLB. - * new version - 2.1.0 - * - * 2003/05/01 - Tsippy Mendelson - * - Added support for Adaptive load balancing mode which is - * equivalent to Transmit load balancing + Receive load balancing. - * new version - 2.2.0 - * - * 2003/05/15 - Jay Vosburgh - * - Applied fix to activebackup_arp_monitor posted to bonding-devel - * by Tony Cureington . Fixes ARP - * monitor endless failover bug. Version to 2.2.10 - * - * 2003/05/20 - Amir Noam - * - Fixed bug in ABI version control - Don't commit to a specific - * ABI version if receiving unsupported ioctl commands. - * - * 2003/05/22 - Jay Vosburgh - * - Fix ifenslave -c causing bond to loose existing routes; - * added bond_set_mac_address() that doesn't require the - * bond to be down. - * - In conjunction with fix for ifenslave -c, in - * bond_change_active(), changing to the already active slave - * is no longer an error (it successfully does nothing). - * - * 2003/06/30 - Amir Noam - * - Fixed bond_change_active() for ALB/TLB modes. - * Version to 2.2.14. - * - * 2003/07/29 - Amir Noam - * - Fixed ARP monitoring bug. - * Version to 2.2.15. - * - * 2003/07/31 - Willy Tarreau - * - Fixed kernel panic when using ARP monitoring without - * setting bond's IP address. - * Version to 2.2.16. - * - * 2003/08/06 - Amir Noam - * - Back port from 2.6: use alloc_netdev(); fix /proc handling; - * made stats a part of bond struct so no need to allocate - * and free it separately; use standard list operations instead - * of pre-allocated array of bonds. - * Version to 2.3.0. - * - * 2003/08/07 - Jay Vosburgh , - * Amir Noam and - * Shmulik Hen - * - Propagating master's settings: Distinguish between modes that - * use a primary slave from those that don't, and propagate settings - * accordingly; Consolidate change_active opeartions and add - * reselect_active and find_best opeartions; Decouple promiscuous - * handling from the multicast mode setting; Add support for changing - * HW address and MTU with proper unwind; Consolidate procfs code, - * add CHANGENAME handler; Enhance netdev notification handling. - * Version to 2.4.0. - * - * 2003/09/15 - Stephen Hemminger , - * Amir Noam - * - Convert /proc to seq_file interface. - * Change /proc/net/bondX/info to /proc/net/bonding/bondX. - * Set version to 2.4.1. - * - * 2003/11/20 - Amir Noam - * - Fix /proc creation/destruction. - * - * 2003/12/01 - Shmulik Hen - * - Massive cleanup - Set version to 2.5.0 - * Code changes: - * o Consolidate format of prints and debug prints. - * o Remove bonding_t/slave_t typedefs and consolidate all casts. - * o Remove dead code and unnecessary checks. - * o Consolidate starting/stopping timers. - * o Consolidate handling of primary module param throughout the code. - * o Removed multicast module param support - all settings are done - * according to mode. - * o Slave list iteration - bond is no longer part of the list, - * added cyclic list iteration macros. - * o Consolidate error handling in all xmit functions. - * Style changes: - * o Consolidate function naming and declarations. - * o Consolidate function params and local variables names. - * o Consolidate return values. - * o Consolidate curly braces. - * o Consolidate conditionals format. - * o Change struct member names and types. - * o Chomp trailing spaces, remove empty lines, fix indentations. - * o Re-organize code according to context. - * - * 2003/12/30 - Amir Noam - * - Fixed: Cannot remove and re-enslave the original active slave. - * - Fixed: Releasing the original active slave causes mac address - * duplication. - * - Add support for slaves that use ethtool_ops. - * Set version to 2.5.3. - * - * 2004/01/05 - Amir Noam - * - Save bonding parameters per bond instead of using the global values. - * Set version to 2.5.4. - * - * 2004/01/14 - Shmulik Hen - * - Enhance VLAN support: - * * Add support for VLAN hardware acceleration capable slaves. - * * Add capability to tag self generated packets in ALB/TLB modes. - * Set version to 2.6.0. - * 2004/10/29 - Mitch Williams - * - Fixed bug when unloading module while using 802.3ad. If - * spinlock debugging is turned on, this causes a stack dump. - * Solution is to move call to dev_remove_pack outside of the - * spinlock. - * Set version to 2.6.1. - * 2005/06/05 - Jay Vosburgh - * - Support for generating gratuitous ARPs in active-backup mode. - * Includes support for VLAN tagging all bonding-generated ARPs - * as needed. Set version to 2.6.2. - * 2005/06/08 - Jason Gabler - * - alternate hashing policy support for mode 2 - * * Added kernel parameter "xmit_hash_policy" to allow the selection - * of different hashing policies for mode 2. The original mode 2 - * policy is the default, now found in xmit_hash_policy_layer2(). - * * Added xmit_hash_policy_layer34() - * - Modified by Jay Vosburgh to also support mode 4. - * Set version to 2.6.3. - * 2005/09/26 - Jay Vosburgh - * - Removed backwards compatibility for old ifenslaves. Version 2.6.4. - * 2005/09/27 - Mitch Williams - * - Radheka Godse - * - Split out bond creation code to allow for sysfs interface. - * - 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: : prefix to sysfs log messages - * - Added arp_ip_targets to /proc entry - * - Allow ARP target table to have empty entries - * - 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: : 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 diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index c5f1c52863c..32d13da43a0 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -19,47 +19,6 @@ * The full GNU General Public License is included in this distribution in the * file called LICENSE. * - * - * Changes: - * - * 2004/12/12 - Mitch Williams - * - Initial creation of sysfs interface. - * - * 2005/06/22 - Radheka Godse - * - 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 - * - * 2005/09/19 - Mitch Williams - * - Changed semantics of multi-item files to be command-based - * instead of list-based. - * - Changed ARP target handler to use in_aton instead of sscanf - * - Style changes. - * 2005/09/27 - Mitch Williams - * - Made line endings consistent. - * - Removed "none" from primary output - just put blank instead - * - Fixed bug with long interface names */ #include #include diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index d6d085480f2..015c7f1d1bc 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -10,29 +10,6 @@ * This software may be used and distributed according to the terms * of the GNU Public License, incorporated herein by reference. * - * - * 2003/03/18 - Amir Noam , - * Tsippy Mendelson and - * Shmulik Hen - * - Added support for IEEE 802.3ad Dynamic link aggregation mode. - * - * 2003/05/01 - Tsippy Mendelson and - * Amir Noam - * - Code beautification and style changes (mainly in comments). - * - * 2003/05/01 - Shmulik Hen - * - Added support for Transmit load balancing mode. - * - * 2003/12/01 - Shmulik Hen - * - Code cleanup and style changes - * - * 2005/05/05 - Jason Gabler - * - added "xmit_policy" kernel parameter for alternate hashing policy - * support for mode 2 - * - * 2005/09/27 - Mitch Williams - * Radheka Godse - * - Added bonding sysfs interface */ #ifndef _LINUX_BONDING_H -- cgit v1.2.3-70-g09d2