diff options
Diffstat (limited to 'drivers/net/bonding/bonding.h')
| -rw-r--r-- | drivers/net/bonding/bonding.h | 352 | 
1 files changed, 222 insertions, 130 deletions
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 03cf3fd1449..0b4d9cde0b0 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -23,8 +23,11 @@  #include <linux/netpoll.h>  #include <linux/inetdevice.h>  #include <linux/etherdevice.h> +#include <linux/reciprocal_div.h> +  #include "bond_3ad.h"  #include "bond_alb.h" +#include "bond_options.h"  #define DRV_VERSION	"3.7.1"  #define DRV_RELDATE	"April 27, 2011" @@ -33,32 +36,12 @@  #define bond_version DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n" +#define BOND_MAX_VLAN_ENCAP	2  #define BOND_MAX_ARP_TARGETS	16 -#define IS_UP(dev)					   \ -	      ((((dev)->flags & IFF_UP) == IFF_UP)	&& \ -	       netif_running(dev)			&& \ -	       netif_carrier_ok(dev)) +#define BOND_DEFAULT_MIIMON	100  /* - * Checks whether slave is ready for transmit. - */ -#define SLAVE_IS_OK(slave)			        \ -		    (((slave)->dev->flags & IFF_UP)  && \ -		     netif_running((slave)->dev)     && \ -		     ((slave)->link == BOND_LINK_UP) && \ -		     bond_is_active_slave(slave)) - - -#define USES_PRIMARY(mode)				\ -		(((mode) == BOND_MODE_ACTIVEBACKUP) ||	\ -		 ((mode) == BOND_MODE_TLB)          ||	\ -		 ((mode) == BOND_MODE_ALB)) - -#define TX_QUEUE_OVERRIDE(mode)				\ -			(((mode) == BOND_MODE_ACTIVEBACKUP) ||	\ -			 ((mode) == BOND_MODE_ROUNDROBIN)) -/*   * Less bad way to call ioctl from within the kernel; this needs to be   * done some other way to get the call out of interrupt context.   * Needs "ioctl" variable to be supplied by calling context. @@ -71,64 +54,44 @@  	set_fs(fs);			\  	res; }) +#define BOND_MODE(bond) ((bond)->params.mode) +  /* slave list primitives */ -#define bond_to_slave(ptr) list_entry(ptr, struct slave, list) +#define bond_slave_list(bond) (&(bond)->dev->adj_list.lower) + +#define bond_has_slaves(bond) !list_empty(bond_slave_list(bond))  /* IMPORTANT: bond_first/last_slave can return NULL in case of an empty list */  #define bond_first_slave(bond) \ -	list_first_entry_or_null(&(bond)->slave_list, struct slave, list) +	(bond_has_slaves(bond) ? \ +		netdev_adjacent_get_private(bond_slave_list(bond)->next) : \ +		NULL)  #define bond_last_slave(bond) \ -	(list_empty(&(bond)->slave_list) ? NULL : \ -					   bond_to_slave((bond)->slave_list.prev)) - -#define bond_is_first_slave(bond, pos) ((pos)->list.prev == &(bond)->slave_list) -#define bond_is_last_slave(bond, pos) ((pos)->list.next == &(bond)->slave_list) +	(bond_has_slaves(bond) ? \ +		netdev_adjacent_get_private(bond_slave_list(bond)->prev) : \ +		NULL) -/* Since bond_first/last_slave can return NULL, these can return NULL too */ -#define bond_next_slave(bond, pos) \ -	(bond_is_last_slave(bond, pos) ? bond_first_slave(bond) : \ -					 bond_to_slave((pos)->list.next)) - -#define bond_prev_slave(bond, pos) \ -	(bond_is_first_slave(bond, pos) ? bond_last_slave(bond) : \ -					  bond_to_slave((pos)->list.prev)) +/* Caller must have rcu_read_lock */ +#define bond_first_slave_rcu(bond) \ +	netdev_lower_get_first_private_rcu(bond->dev) -/** - * bond_for_each_slave_from - iterate the slaves list from a starting point - * @bond:	the bond holding this list. - * @pos:	current slave. - * @cnt:	counter for max number of moves - * @start:	starting point. - * - * Caller must hold bond->lock - */ -#define bond_for_each_slave_from(bond, pos, cnt, start) \ -	for (cnt = 0, pos = start; pos && cnt < (bond)->slave_cnt; \ -	     cnt++, pos = bond_next_slave(bond, pos)) +#define bond_is_first_slave(bond, pos) (pos == bond_first_slave(bond)) +#define bond_is_last_slave(bond, pos) (pos == bond_last_slave(bond))  /**   * bond_for_each_slave - iterate over all slaves   * @bond:	the bond holding this list   * @pos:	current slave + * @iter:	list_head * iterator   *   * Caller must hold bond->lock   */ -#define bond_for_each_slave(bond, pos) \ -	list_for_each_entry(pos, &(bond)->slave_list, list) +#define bond_for_each_slave(bond, pos, iter) \ +	netdev_for_each_lower_private((bond)->dev, pos, iter)  /* Caller must have rcu_read_lock */ -#define bond_for_each_slave_rcu(bond, pos) \ -	list_for_each_entry_rcu(pos, &(bond)->slave_list, list) - -/** - * bond_for_each_slave_reverse - iterate in reverse from a given position - * @bond:	the bond holding this list - * @pos:	slave to continue from - * - * Caller must hold bond->lock - */ -#define bond_for_each_slave_continue_reverse(bond, pos) \ -	list_for_each_entry_continue_reverse(pos, &(bond)->slave_list, list) +#define bond_for_each_slave_rcu(bond, pos, iter) \ +	netdev_for_each_lower_private_rcu((bond)->dev, pos, iter)  #ifdef CONFIG_NET_POLL_CONTROLLER  extern atomic_t netpoll_block_tx; @@ -177,6 +140,9 @@ struct bond_params {  	int all_slaves_active;  	int resend_igmp;  	int lp_interval; +	int packets_per_slave; +	int tlb_dynamic_lb; +	struct reciprocal_value reciprocal_packets_per_slave;  };  struct bond_parm_tbl { @@ -184,32 +150,32 @@ struct bond_parm_tbl {  	int mode;  }; -#define BOND_MAX_MODENAME_LEN 20 -  struct slave {  	struct net_device *dev; /* first - useful for panic debug */ -	struct list_head list;  	struct bonding *bond; /* our master */  	int    delay; -	unsigned long jiffies; -	unsigned long last_arp_rx; +	/* all three in jiffies */ +	unsigned long last_link_up; +	unsigned long last_rx;  	unsigned long target_last_arp_rx[BOND_MAX_ARP_TARGETS];  	s8     link;    /* one of BOND_LINK_XXXX */  	s8     new_link;  	u8     backup:1,   /* indicates backup slave. Value corresponds with  			      BOND_STATE_ACTIVE and BOND_STATE_BACKUP */ -	       inactive:1; /* indicates inactive slave */ +	       inactive:1, /* indicates inactive slave */ +	       should_notify:1; /* indicateds whether the state changed */  	u8     duplex;  	u32    original_mtu;  	u32    link_failure_count;  	u32    speed;  	u16    queue_id;  	u8     perm_hwaddr[ETH_ALEN]; -	struct ad_slave_info ad_info; /* HUGE - better to dynamically alloc */ +	struct ad_slave_info *ad_info;  	struct tlb_slave_info tlb_info;  #ifdef CONFIG_NET_POLL_CONTROLLER  	struct netpoll *np;  #endif +	struct kobject kobj;  };  /* @@ -228,7 +194,6 @@ struct slave {   */  struct bonding {  	struct   net_device *dev; /* first - useful for panic debug */ -	struct   list_head slave_list;  	struct   slave *curr_active_slave;  	struct   slave *current_arp_slave;  	struct   slave *primary_slave; @@ -245,8 +210,7 @@ struct bonding {  	char     proc_file_name[IFNAMSIZ];  #endif /* CONFIG_PROC_FS */  	struct   list_head bond_list; -	int      (*xmit_hash_policy)(struct sk_buff *, int); -	u16      rr_tx_counter; +	u32      rr_tx_counter;  	struct   ad_bond_info ad_info;  	struct   alb_bond_info alb_info;  	struct   bond_params params; @@ -268,6 +232,11 @@ struct bonding {  #define bond_slave_get_rtnl(dev) \  	((struct slave *) rtnl_dereference(dev->rx_handler_data)) +struct bond_vlan_tag { +	__be16		vlan_proto; +	unsigned short	vlan_id; +}; +  /**   * Returns NULL if the net_device does not belong to any of the bond's slaves   * @@ -276,36 +245,106 @@ struct bonding {  static inline struct slave *bond_get_slave_by_dev(struct bonding *bond,  						  struct net_device *slave_dev)  { -	struct slave *slave = NULL; - -	bond_for_each_slave(bond, slave) -		if (slave->dev == slave_dev) -			return slave; - -	return NULL; +	return netdev_lower_dev_get_private(bond->dev, slave_dev);  }  static inline struct bonding *bond_get_bond_by_slave(struct slave *slave)  { -	if (!slave || !slave->bond) -		return NULL;  	return slave->bond;  } +static inline bool bond_should_override_tx_queue(struct bonding *bond) +{ +	return BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP || +	       BOND_MODE(bond) == BOND_MODE_ROUNDROBIN; +} +  static inline bool bond_is_lb(const struct bonding *bond)  { -	return (bond->params.mode == BOND_MODE_TLB || -		bond->params.mode == BOND_MODE_ALB); +	return BOND_MODE(bond) == BOND_MODE_TLB || +	       BOND_MODE(bond) == BOND_MODE_ALB; +} + +static inline bool bond_mode_uses_arp(int mode) +{ +	return mode != BOND_MODE_8023AD && mode != BOND_MODE_TLB && +	       mode != BOND_MODE_ALB; +} + +static inline bool bond_mode_uses_primary(int mode) +{ +	return mode == BOND_MODE_ACTIVEBACKUP || mode == BOND_MODE_TLB || +	       mode == BOND_MODE_ALB; +} + +static inline bool bond_uses_primary(struct bonding *bond) +{ +	return bond_mode_uses_primary(BOND_MODE(bond)); +} + +static inline bool bond_slave_is_up(struct slave *slave) +{ +	return netif_running(slave->dev) && netif_carrier_ok(slave->dev);  }  static inline void bond_set_active_slave(struct slave *slave)  { -	slave->backup = 0; +	if (slave->backup) { +		slave->backup = 0; +		rtmsg_ifinfo(RTM_NEWLINK, slave->dev, 0, GFP_ATOMIC); +	}  }  static inline void bond_set_backup_slave(struct slave *slave)  { -	slave->backup = 1; +	if (!slave->backup) { +		slave->backup = 1; +		rtmsg_ifinfo(RTM_NEWLINK, slave->dev, 0, GFP_ATOMIC); +	} +} + +static inline void bond_set_slave_state(struct slave *slave, +					int slave_state, bool notify) +{ +	if (slave->backup == slave_state) +		return; + +	slave->backup = slave_state; +	if (notify) { +		rtmsg_ifinfo(RTM_NEWLINK, slave->dev, 0, GFP_ATOMIC); +		slave->should_notify = 0; +	} else { +		if (slave->should_notify) +			slave->should_notify = 0; +		else +			slave->should_notify = 1; +	} +} + +static inline void bond_slave_state_change(struct bonding *bond) +{ +	struct list_head *iter; +	struct slave *tmp; + +	bond_for_each_slave(bond, tmp, iter) { +		if (tmp->link == BOND_LINK_UP) +			bond_set_active_slave(tmp); +		else if (tmp->link == BOND_LINK_DOWN) +			bond_set_backup_slave(tmp); +	} +} + +static inline void bond_slave_state_notify(struct bonding *bond) +{ +	struct list_head *iter; +	struct slave *tmp; + +	bond_for_each_slave(bond, tmp, iter) { +		if (tmp->should_notify) { +			rtmsg_ifinfo(RTM_NEWLINK, tmp->dev, 0, GFP_ATOMIC); +			tmp->should_notify = 0; +		} +	}  }  static inline int bond_slave_state(struct slave *slave) @@ -318,6 +357,12 @@ static inline bool bond_is_active_slave(struct slave *slave)  	return !bond_slave_state(slave);  } +static inline bool bond_slave_can_tx(struct slave *slave) +{ +	return bond_slave_is_up(slave) && slave->link == BOND_LINK_UP && +	       bond_is_active_slave(slave); +} +  #define BOND_PRI_RESELECT_ALWAYS	0  #define BOND_PRI_RESELECT_BETTER	1  #define BOND_PRI_RESELECT_FAILURE	2 @@ -334,6 +379,14 @@ static inline bool bond_is_active_slave(struct slave *slave)  #define BOND_ARP_VALIDATE_BACKUP	(1 << BOND_STATE_BACKUP)  #define BOND_ARP_VALIDATE_ALL		(BOND_ARP_VALIDATE_ACTIVE | \  					 BOND_ARP_VALIDATE_BACKUP) +#define BOND_ARP_FILTER			(BOND_ARP_VALIDATE_ALL + 1) +#define BOND_ARP_FILTER_ACTIVE		(BOND_ARP_VALIDATE_ACTIVE | \ +					 BOND_ARP_FILTER) +#define BOND_ARP_FILTER_BACKUP		(BOND_ARP_VALIDATE_BACKUP | \ +					 BOND_ARP_FILTER) + +#define BOND_SLAVE_NOTIFY_NOW		true +#define BOND_SLAVE_NOTIFY_LATER		false  static inline int slave_do_arp_validate(struct bonding *bond,  					struct slave *slave) @@ -341,6 +394,16 @@ static inline int slave_do_arp_validate(struct bonding *bond,  	return bond->params.arp_validate & (1 << bond_slave_state(slave));  } +static inline int slave_do_arp_validate_only(struct bonding *bond) +{ +	return bond->params.arp_validate & BOND_ARP_FILTER; +} + +static inline int bond_is_ip_target_ok(__be32 addr) +{ +	return !ipv4_is_lbcast(addr) && !ipv4_is_zeronet(addr); +} +  /* Get the oldest arp which we've received on this slave for bond's   * arp_targets.   */ @@ -360,14 +423,10 @@ static inline unsigned long slave_oldest_target_arp_rx(struct bonding *bond,  static inline unsigned long slave_last_rx(struct bonding *bond,  					struct slave *slave)  { -	if (slave_do_arp_validate(bond, slave)) { -		if (bond->params.arp_all_targets == BOND_ARP_TARGETS_ALL) -			return slave_oldest_target_arp_rx(bond, slave); -		else -			return slave->last_arp_rx; -	} +	if (bond->params.arp_all_targets == BOND_ARP_TARGETS_ALL) +		return slave_oldest_target_arp_rx(bond, slave); -	return slave->dev->last_rx; +	return slave->last_rx;  }  #ifdef CONFIG_NET_POLL_CONTROLLER @@ -386,17 +445,19 @@ static inline void bond_netpoll_send_skb(const struct slave *slave,  }  #endif -static inline void bond_set_slave_inactive_flags(struct slave *slave) +static inline void bond_set_slave_inactive_flags(struct slave *slave, +						 bool notify)  {  	if (!bond_is_lb(slave->bond)) -		bond_set_backup_slave(slave); +		bond_set_slave_state(slave, BOND_STATE_BACKUP, notify);  	if (!slave->bond->params.all_slaves_active)  		slave->inactive = 1;  } -static inline void bond_set_slave_active_flags(struct slave *slave) +static inline void bond_set_slave_active_flags(struct slave *slave, +					       bool notify)  { -	bond_set_active_slave(slave); +	bond_set_slave_state(slave, BOND_STATE_ACTIVE, notify);  	slave->inactive = 0;  } @@ -414,40 +475,32 @@ static inline __be32 bond_confirm_addr(struct net_device *dev, __be32 dst, __be3  	in_dev = __in_dev_get_rcu(dev);  	if (in_dev) -		addr = inet_confirm_addr(in_dev, dst, local, RT_SCOPE_HOST); - +		addr = inet_confirm_addr(dev_net(dev), in_dev, dst, local, +					 RT_SCOPE_HOST);  	rcu_read_unlock();  	return addr;  } -static inline bool slave_can_tx(struct slave *slave) -{ -	if (IS_UP(slave->dev) && slave->link == BOND_LINK_UP && -	    bond_is_active_slave(slave)) -		return true; -	else -		return false; -} - -struct bond_net; +struct bond_net { +	struct net		*net;	/* Associated network namespace */ +	struct list_head	dev_list; +#ifdef CONFIG_PROC_FS +	struct proc_dir_entry	*proc_dir; +#endif +	struct class_attribute	class_attr_bonding_masters; +};  int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, 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_xmit_slave_id(struct bonding *bond, struct sk_buff *skb, int slave_id); +void bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);  int bond_create(struct net *net, const char *name);  int bond_create_sysfs(struct bond_net *net);  void bond_destroy_sysfs(struct bond_net *net);  void bond_prepare_sysfs_group(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_sysfs_slave_add(struct slave *slave); +void bond_sysfs_slave_del(struct slave *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); -void bond_mii_monitor(struct work_struct *); -void bond_loadbalance_arp_mon(struct work_struct *); -void bond_activebackup_arp_mon(struct work_struct *); -void bond_set_mode_ops(struct bonding *bond, int mode); -int bond_parse_parm(const char *mode_arg, const struct bond_parm_tbl *tbl); +u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb);  void bond_select_active_slave(struct bonding *bond);  void bond_change_active_slave(struct bonding *bond, struct slave *new_active);  void bond_create_debugfs(void); @@ -456,15 +509,16 @@ void bond_debug_register(struct bonding *bond);  void bond_debug_unregister(struct bonding *bond);  void bond_debug_reregister(struct bonding *bond);  const char *bond_mode_name(int mode); - -struct bond_net { -	struct net *		net;	/* Associated network namespace */ -	struct list_head	dev_list; -#ifdef CONFIG_PROC_FS -	struct proc_dir_entry *	proc_dir; -#endif -	struct class_attribute	class_attr_bonding_masters; -}; +void bond_setup(struct net_device *bond_dev); +unsigned int bond_get_num_tx_queues(void); +int bond_netlink_init(void); +void bond_netlink_fini(void); +struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond); +struct net_device *bond_option_active_slave_get(struct bonding *bond); +const char *bond_slave_link_status(s8 link); +bool bond_verify_device_path(struct net_device *start_dev, +			     struct net_device *end_dev, +			     struct bond_vlan_tag *tags);  #ifdef CONFIG_PROC_FS  void bond_create_proc_entry(struct bonding *bond); @@ -492,15 +546,51 @@ static inline void bond_destroy_proc_dir(struct bond_net *bn)  static inline struct slave *bond_slave_has_mac(struct bonding *bond,  					       const u8 *mac)  { +	struct list_head *iter; +	struct slave *tmp; + +	bond_for_each_slave(bond, tmp, iter) +		if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr)) +			return tmp; + +	return NULL; +} + +/* Caller must hold rcu_read_lock() for read */ +static inline struct slave *bond_slave_has_mac_rcu(struct bonding *bond, +					       const u8 *mac) +{ +	struct list_head *iter;  	struct slave *tmp; -	bond_for_each_slave(bond, tmp) +	bond_for_each_slave_rcu(bond, tmp, iter)  		if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr))  			return tmp;  	return NULL;  } +/* Caller must hold rcu_read_lock() for read */ +static inline bool bond_slave_has_mac_rx(struct bonding *bond, const u8 *mac) +{ +	struct list_head *iter; +	struct slave *tmp; +	struct netdev_hw_addr *ha; + +	bond_for_each_slave_rcu(bond, tmp, iter) +		if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr)) +			return true; + +	if (netdev_uc_empty(bond->dev)) +		return false; + +	netdev_for_each_uc_addr(ha, bond->dev) +		if (ether_addr_equal_64bits(mac, ha->addr)) +			return true; + +	return false; +} +  /* Check if the ip is present in arp ip list, or first free slot if ip == 0   * Returns -1 if not found, index if found   */ @@ -520,7 +610,6 @@ static inline int bond_get_targets_ip(__be32 *targets, __be32 ip)  /* exported from bond_main.c */  extern int bond_net_id;  extern const struct bond_parm_tbl bond_lacp_tbl[]; -extern const struct bond_parm_tbl bond_mode_tbl[];  extern const struct bond_parm_tbl xmit_hashtype_tbl[];  extern const struct bond_parm_tbl arp_validate_tbl[];  extern const struct bond_parm_tbl arp_all_targets_tbl[]; @@ -528,4 +617,7 @@ extern const struct bond_parm_tbl fail_over_mac_tbl[];  extern const struct bond_parm_tbl pri_reselect_tbl[];  extern struct bond_parm_tbl ad_select_tbl[]; +/* exported from bond_netlink.c */ +extern struct rtnl_link_ops bond_link_ops; +  #endif /* _LINUX_BONDING_H */  | 
