📄 bond_main.c
字号:
* 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 <fubar at us dot ibm dot com>, * Amir Noam <amir.noam at intel dot com> and * Shmulik Hen <shmulik.hen at intel dot com> * - 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 <shemminger at osdl dot org>, * Amir Noam <amir.noam at intel dot com> * - 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 <amir.noam at intel dot com> * - Fix /proc creation/destruction. * * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com> * - 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 <amir.noam at intel dot com> * - 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 <amir.noam at intel dot com> * - Save bonding parameters per bond instead of using the global values. * Set version to 2.5.4. * * 2004/01/14 - Shmulik Hen <shmulik.hen at intel dot com> * - 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 <mitch.a.williams at intel dot com> * - 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. * *///#define BONDING_DEBUG 1#include <linux/config.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/fcntl.h>#include <linux/interrupt.h>#include <linux/ptrace.h>#include <linux/ioport.h>#include <linux/in.h>#include <linux/ip.h>#include <linux/slab.h>#include <linux/string.h>#include <linux/init.h>#include <linux/timer.h>#include <linux/socket.h>#include <linux/ctype.h>#include <linux/inet.h>#include <linux/bitops.h>#include <asm/system.h>#include <asm/io.h>#include <asm/dma.h>#include <asm/uaccess.h>#include <linux/errno.h>#include <linux/netdevice.h>#include <linux/inetdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <net/sock.h>#include <linux/rtnetlink.h>#include <linux/proc_fs.h>#include <linux/seq_file.h>#include <linux/smp.h>#include <linux/if_ether.h>#include <net/arp.h>#include <linux/mii.h>#include <linux/ethtool.h>#include <linux/if_vlan.h>#include <linux/if_bonding.h>#include "bonding.h"#include "bond_3ad.h"#include "bond_alb.h"/*---------------------------- Module parameters ----------------------------*//* monitor all links that often (in milliseconds). <=0 disables monitoring */#define BOND_LINK_MON_INTERV 0#define BOND_LINK_ARP_INTERV 0static int max_bonds = BOND_DEFAULT_MAX_BONDS;static int miimon = BOND_LINK_MON_INTERV;static int updelay = 0;static int downdelay = 0;static int use_carrier = 1;static char *mode = NULL;static char *primary = NULL;static char *lacp_rate = NULL;static int arp_interval = BOND_LINK_ARP_INTERV;static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };module_param(max_bonds, int, 0);MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");module_param(miimon, int, 0);MODULE_PARM_DESC(miimon, "Link check interval in milliseconds");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_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_param(mode, charp, 0);MODULE_PARM_DESC(mode, "Mode of operation : 0 for round robin, 1 for active-backup, 2 for xor");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_param(arp_interval, int, 0);MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");module_param_array(arp_ip_target, charp, NULL, 0);MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");/*----------------------------- Global variables ----------------------------*/static const char *version = DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n";static LIST_HEAD(bond_dev_list);#ifdef CONFIG_PROC_FSstatic struct proc_dir_entry *bond_proc_dir = NULL;#endifstatic u32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ;static int arp_ip_count = 0;static u32 my_ip = 0;static int bond_mode = BOND_MODE_ROUNDROBIN;static int lacp_fast = 0;static int app_abi_ver = 0;static int orig_app_abi_ver = -1; /* This is used to save the first ABI version * we receive from the application. Once set, * it won't be changed, and the module will * refuse to enslave/release interfaces if the * command comes from an application using * another ABI version. */struct bond_parm_tbl { char *modename; int mode;};static struct bond_parm_tbl bond_lacp_tbl[] = {{ "slow", AD_LACP_SLOW},{ "fast", AD_LACP_FAST},{ NULL, -1},};static struct bond_parm_tbl bond_mode_tbl[] = {{ "balance-rr", BOND_MODE_ROUNDROBIN},{ "active-backup", BOND_MODE_ACTIVEBACKUP},{ "balance-xor", BOND_MODE_XOR},{ "broadcast", BOND_MODE_BROADCAST},{ "802.3ad", BOND_MODE_8023AD},{ "balance-tlb", BOND_MODE_TLB},{ "balance-alb", BOND_MODE_ALB},{ NULL, -1},};/*-------------------------- Forward declarations ---------------------------*/static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode);/*---------------------------- General routines -----------------------------*/static const char *bond_mode_name(int mode){ switch (mode) { case BOND_MODE_ROUNDROBIN : return "load balancing (round-robin)"; case BOND_MODE_ACTIVEBACKUP : return "fault-tolerance (active-backup)"; case BOND_MODE_XOR : return "load balancing (xor)"; case BOND_MODE_BROADCAST : return "fault-tolerance (broadcast)"; case BOND_MODE_8023AD: return "IEEE 802.3ad Dynamic link aggregation"; case BOND_MODE_TLB: return "transmit load balancing"; case BOND_MODE_ALB: return "adaptive load balancing"; default: return "unknown"; }}/*---------------------------------- VLAN -----------------------------------*//** * bond_add_vlan - add a new vlan id on bond * @bond: bond that got the notification * @vlan_id: the vlan id to add * * Returns -ENOMEM if allocation failed. */static int bond_add_vlan(struct bonding *bond, unsigned short vlan_id){ struct vlan_entry *vlan; dprintk("bond: %s, vlan id %d\n", (bond ? bond->dev->name: "None"), vlan_id); vlan = kmalloc(sizeof(struct vlan_entry), GFP_KERNEL); if (!vlan) { return -ENOMEM; } INIT_LIST_HEAD(&vlan->vlan_list); vlan->vlan_id = vlan_id; write_lock_bh(&bond->lock); list_add_tail(&vlan->vlan_list, &bond->vlan_list); write_unlock_bh(&bond->lock); dprintk("added VLAN ID %d on bond %s\n", vlan_id, bond->dev->name); return 0;}/** * bond_del_vlan - delete a vlan id from bond * @bond: bond that got the notification * @vlan_id: the vlan id to delete * * returns -ENODEV if @vlan_id was not found in @bond. */static int bond_del_vlan(struct bonding *bond, unsigned short vlan_id){ struct vlan_entry *vlan, *next; int res = -ENODEV; dprintk("bond: %s, vlan id %d\n", bond->dev->name, vlan_id); write_lock_bh(&bond->lock); list_for_each_entry_safe(vlan, next, &bond->vlan_list, vlan_list) { if (vlan->vlan_id == vlan_id) { list_del(&vlan->vlan_list); if ((bond->params.mode == BOND_MODE_TLB) || (bond->params.mode == BOND_MODE_ALB)) { bond_alb_clear_vlan(bond, vlan_id); } dprintk("removed VLAN ID %d from bond %s\n", vlan_id, bond->dev->name); kfree(vlan); if (list_empty(&bond->vlan_list) && (bond->slave_cnt == 0)) { /* Last VLAN removed and no slaves, so * restore block on adding VLANs. This will * be removed once new slaves that are not * VLAN challenged will be added. */ bond->dev->features |= NETIF_F_VLAN_CHALLENGED; } res = 0; goto out; } } dprintk("couldn't find VLAN ID %d in bond %s\n", vlan_id, bond->dev->name);out: write_unlock_bh(&bond->lock); return res;}/** * bond_has_challenged_slaves * @bond: the bond we're working on * * Searches the slave list. Returns 1 if a vlan challenged slave * was found, 0 otherwise. * * Assumes bond->lock is held. */static int bond_has_challenged_slaves(struct bonding *bond){ struct slave *slave; int i; bond_for_each_slave(bond, slave, i) { if (slave->dev->features & NETIF_F_VLAN_CHALLENGED) { dprintk("found VLAN challenged slave - %s\n", slave->dev->name); return 1; } } dprintk("no VLAN challenged slaves found\n"); return 0;}/** * bond_next_vlan - safely skip to the next item in the vlans list. * @bond: the bond we're working on * @curr: item we're advancing from * * Returns %NULL if list is empty, bond->next_vlan if @curr is %NULL, * or @curr->next otherwise (even if it is @curr itself again). * * Caller must hold bond->lock */struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr){ struct vlan_entry *next, *last; if (list_empty(&bond->vlan_list)) { return NULL; } if (!curr) { next = list_entry(bond->vlan_list.next, struct vlan_entry, vlan_list); } else { last = list_entry(bond->vlan_list.prev, struct vlan_entry, vlan_list); if (last == curr) { next = list_entry(bond->vlan_list.next, struct vlan_entry, vlan_list); } else { next = list_entry(curr->vlan_list.next, struct vlan_entry, vlan_list); } } return next;}/** * bond_dev_queue_xmit - Prepare skb for xmit. * * @bond: bond device that got this skb for tx. * @skb: hw accel VLAN tagged skb to transmit * @slave_dev: slave that is supposed to xmit this skbuff * * When the bond gets an skb to tarnsmit that is * already hardware accelerated VLAN tagged, and it * needs to relay this skb to a slave that is not * hw accel capable, the skb needs to be "unaccelerated", * i.e. strip the hwaccel tag and re-insert it as part * of the payload. * * Assumption - once a VLAN device is created over the bond device, all * packets are going to be hardware accelerated VLAN tagged since the IP * binding is done over the VLAN device */int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev){ unsigned short vlan_id; int res; if (!list_empty(&bond->vlan_list) &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -