2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Copyright ( c )  1999  -  2004  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 . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-12-13 20:06:07 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# include  <linux/skbuff.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/netdevice.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/etherdevice.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/pkt_sched.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/spinlock.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/slab.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/timer.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/ip.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/ipv6.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/if_arp.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/if_ether.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/if_bonding.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/if_vlan.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/in.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <net/ipx.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <net/arp.h> 
  
						 
					
						
							
								
									
										
										
										
											2008-08-28 15:38:41 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <net/ipv6.h> 
  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# include  <asm/byteorder.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "bonding.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "bond_alb.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define ALB_TIMER_TICKS_PER_SEC	    10	 /* should be a divisor of HZ */ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BOND_TLB_REBALANCE_INTERVAL 10	 / * In seconds, periodic re-balancing. 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 *  Used  for  division  -  never  set 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 *  to  zero  ! ! ! 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BOND_ALB_LP_INTERVAL	    1	 / * In seconds, periodic send of 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 *  learning  packets  to  the  switch 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BOND_TLB_REBALANCE_TICKS (BOND_TLB_REBALANCE_INTERVAL \ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												  *  ALB_TIMER_TICKS_PER_SEC ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BOND_ALB_LP_TICKS (BOND_ALB_LP_INTERVAL \ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   *  ALB_TIMER_TICKS_PER_SEC ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define TLB_HASH_TABLE_SIZE 256	 / * The size of the clients hash table. 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 *  Note  that  this  value  MUST  NOT  be  smaller 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 *  because  the  key  hash  table  is  BYTE  wide  ! 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define TLB_NULL_INDEX		0xffffffff 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define MAX_LP_BURST		3 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* rlb defs */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define RLB_HASH_TABLE_SIZE	256 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define RLB_NULL_INDEX		0xffffffff 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define RLB_UPDATE_DELAY	2*ALB_TIMER_TICKS_PER_SEC  /* 2 seconds */ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define RLB_ARP_BURST_SIZE	2 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define RLB_UPDATE_RETRY	3	 / * 3-ticks - must be smaller than the rlb 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 *  rebalance  interval  ( 5  min ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* RLB_PROMISC_TIMEOUT = 10 sec equals the time that the current slave is
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  promiscuous  after  failover 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define RLB_PROMISC_TIMEOUT	10*ALB_TIMER_TICKS_PER_SEC 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-09-01 06:31:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# ifndef __long_aligned 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define __long_aligned __attribute__((aligned((sizeof(long))))) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  const  u8  mac_bcast [ ETH_ALEN ]  __long_aligned  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0xff ,  0xff ,  0xff ,  0xff ,  0xff ,  0xff 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  const  u8  mac_v6_allmcast [ ETH_ALEN ]  __long_aligned  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x33 ,  0x33 ,  0x00 ,  0x00 ,  0x00 ,  0x01 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								static  const  int  alb_delta_in_ticks  =  HZ  /  ALB_TIMER_TICKS_PER_SEC ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# pragma pack(1) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  learning_pkt  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									u8  mac_dst [ ETH_ALEN ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									u8  mac_src [ ETH_ALEN ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-08-22 20:06:58 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									__be16  type ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									u8  padding [ ETH_ZLEN  -  ETH_HLEN ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  arp_pkt  {  
						 
					
						
							
								
									
										
										
										
											2007-08-22 20:06:58 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									__be16   hw_addr_space ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									__be16   prot_addr_space ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									u8       hw_addr_len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									u8       prot_addr_len ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-08-22 20:06:58 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									__be16   op_code ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									u8       mac_src [ ETH_ALEN ] ; 	/* sender hardware address */ 
							 
						 
					
						
							
								
									
										
										
										
											2007-08-22 20:06:58 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									__be32   ip_src ; 			/* sender IP address */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									u8       mac_dst [ ETH_ALEN ] ; 	/* target hardware address */ 
							 
						 
					
						
							
								
									
										
										
										
											2007-08-22 20:06:58 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									__be32   ip_dst ; 			/* target IP address */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# pragma pack() 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-03-10 16:07:19 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  inline  struct  arp_pkt  * arp_pkt ( const  struct  sk_buff  * skb )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2007-04-10 20:50:43 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  ( struct  arp_pkt  * ) skb_network_header ( skb ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-03-10 16:07:19 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/* Forward declaration */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  alb_send_learning_packets ( struct  slave  * slave ,  u8  mac_addr [ ] ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-04-20 22:47:35 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  inline  u8  _simple_hash ( const  u8  * hash_start ,  int  hash_size )  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									u8  hash  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  hash_size ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hash  ^ =  hash_start [ i ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  hash ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*********************** tlb specific functions ***************************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  inline  void  _lock_tx_hashtbl ( struct  bonding  * bond )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:50 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									spin_lock_bh ( & ( BOND_ALB_INFO ( bond ) . tx_hashtbl_lock ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  inline  void  _unlock_tx_hashtbl ( struct  bonding  * bond )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:50 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									spin_unlock_bh ( & ( BOND_ALB_INFO ( bond ) . tx_hashtbl_lock ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Caller must hold tx_hashtbl lock */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  inline  void  tlb_init_table_entry ( struct  tlb_client_info  * entry ,  int  save_load )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( save_load )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										entry - > load_history  =  1  +  entry - > tx_bytes  / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												      BOND_TLB_REBALANCE_INTERVAL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										entry - > tx_bytes  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									entry - > tx_slave  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									entry - > next  =  TLB_NULL_INDEX ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									entry - > prev  =  TLB_NULL_INDEX ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  inline  void  tlb_init_slave ( struct  slave  * slave )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									SLAVE_TLB_INFO ( slave ) . load  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									SLAVE_TLB_INFO ( slave ) . head  =  TLB_NULL_INDEX ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Caller must hold bond lock for read */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  tlb_clear_slave ( struct  bonding  * bond ,  struct  slave  * slave ,  int  save_load )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  tlb_client_info  * tx_hash_table ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									u32  index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_lock_tx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* clear slave from tx_hashtbl */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tx_hash_table  =  BOND_ALB_INFO ( bond ) . tx_hashtbl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-10-30 17:41:16 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* skip this if we've already freed the tx hash table */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( tx_hash_table )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										index  =  SLAVE_TLB_INFO ( slave ) . head ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										while  ( index  ! =  TLB_NULL_INDEX )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											u32  next_index  =  tx_hash_table [ index ] . next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											tlb_init_table_entry ( & tx_hash_table [ index ] ,  save_load ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											index  =  next_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tlb_init_slave ( slave ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-01-09 12:14:00 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_unlock_tx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Must be called before starting the monitor timer */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  tlb_initialize ( struct  bonding  * bond )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  alb_bond_info  * bond_info  =  & ( BOND_ALB_INFO ( bond ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  size  =  TLB_HASH_TABLE_SIZE  *  sizeof ( struct  tlb_client_info ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-09 10:35:30 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  tlb_client_info  * new_hashtbl ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									spin_lock_init ( & ( bond_info - > tx_hashtbl_lock ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-02-06 14:16:40 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									new_hashtbl  =  kzalloc ( size ,  GFP_KERNEL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-09 10:35:30 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! new_hashtbl )  { 
							 
						 
					
						
							
								
									
										
										
										
											2009-12-13 20:06:07 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										pr_err ( " %s: Error: Failed to allocate TLB hash table \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										       bond - > dev - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-09 10:35:30 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									_lock_tx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bond_info - > tx_hashtbl  =  new_hashtbl ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  TLB_HASH_TABLE_SIZE ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tlb_init_table_entry ( & bond_info - > tx_hashtbl [ i ] ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_unlock_tx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Must be called only after all slaves have been released */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  tlb_deinitialize ( struct  bonding  * bond )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  alb_bond_info  * bond_info  =  & ( BOND_ALB_INFO ( bond ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_lock_tx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									kfree ( bond_info - > tx_hashtbl ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bond_info - > tx_hashtbl  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_unlock_tx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Caller must hold bond lock for read */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  slave  * tlb_get_least_loaded_slave ( struct  bonding  * bond )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  slave  * slave ,  * least_loaded ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									s64  max_gap ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ,  found  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Find the first enabled slave */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bond_for_each_slave ( bond ,  slave ,  i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( SLAVE_IS_OK ( slave ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											found  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! found )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									least_loaded  =  slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									max_gap  =  ( s64 ) ( slave - > speed  < <  20 )  -  /* Convert to Megabit per sec */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											( s64 ) ( SLAVE_TLB_INFO ( slave ) . load  < <  3 ) ;  /* Bytes to bits */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Find the slave with the largest gap */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bond_for_each_slave_from ( bond ,  slave ,  i ,  least_loaded )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( SLAVE_IS_OK ( slave ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											s64  gap  =  ( s64 ) ( slave - > speed  < <  20 )  - 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													( s64 ) ( SLAVE_TLB_INFO ( slave ) . load  < <  3 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( max_gap  <  gap )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												least_loaded  =  slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												max_gap  =  gap ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  least_loaded ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Caller must hold bond lock for read */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  slave  * tlb_choose_channel ( struct  bonding  * bond ,  u32  hash_index ,  u32  skb_len )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  alb_bond_info  * bond_info  =  & ( BOND_ALB_INFO ( bond ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  tlb_client_info  * hash_table ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  slave  * assigned_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_lock_tx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									hash_table  =  bond_info - > tx_hashtbl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									assigned_slave  =  hash_table [ hash_index ] . tx_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! assigned_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										assigned_slave  =  tlb_get_least_loaded_slave ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( assigned_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  tlb_slave_info  * slave_info  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												& ( SLAVE_TLB_INFO ( assigned_slave ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											u32  next_index  =  slave_info - > head ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											hash_table [ hash_index ] . tx_slave  =  assigned_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											hash_table [ hash_index ] . next  =  next_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											hash_table [ hash_index ] . prev  =  TLB_NULL_INDEX ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( next_index  ! =  TLB_NULL_INDEX )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												hash_table [ next_index ] . prev  =  hash_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											slave_info - > head  =  hash_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											slave_info - > load  + = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												hash_table [ hash_index ] . load_history ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( assigned_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hash_table [ hash_index ] . tx_bytes  + =  skb_len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_unlock_tx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  assigned_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*********************** rlb specific functions ***************************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  inline  void  _lock_rx_hashtbl ( struct  bonding  * bond )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:50 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									spin_lock_bh ( & ( BOND_ALB_INFO ( bond ) . rx_hashtbl_lock ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  inline  void  _unlock_rx_hashtbl ( struct  bonding  * bond )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:50 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									spin_unlock_bh ( & ( BOND_ALB_INFO ( bond ) . rx_hashtbl_lock ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* when an ARP REPLY is received from a client update its info
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  in  the  rx_hashtbl 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  rlb_update_entry_from_arp ( struct  bonding  * bond ,  struct  arp_pkt  * arp )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  alb_bond_info  * bond_info  =  & ( BOND_ALB_INFO ( bond ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  rlb_client_info  * client_info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									u32  hash_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_lock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									hash_index  =  _simple_hash ( ( u8 * ) & ( arp - > ip_src ) ,  sizeof ( arp - > ip_src ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									client_info  =  & ( bond_info - > rx_hashtbl [ hash_index ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ( client_info - > assigned )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    ( client_info - > ip_src  = =  arp - > ip_dst )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    ( client_info - > ip_dst  = =  arp - > ip_src ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* update the clients MAC address */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memcpy ( client_info - > mac_dst ,  arp - > mac_src ,  ETH_ALEN ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										client_info - > ntt  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond_info - > rx_ntt  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_unlock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-08-09 19:34:12 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  rlb_arp_recv ( struct  sk_buff  * skb ,  struct  net_device  * bond_dev ,  struct  packet_type  * ptype ,  struct  net_device  * orig_dev )  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2008-11-04 17:51:15 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  bonding  * bond ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									struct  arp_pkt  * arp  =  ( struct  arp_pkt  * ) skb - > data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  NET_RX_DROP ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-11-04 17:51:15 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									while  ( bond_dev - > priv_flags  &  IFF_802_1Q_VLAN ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond_dev  =  vlan_dev_real_dev ( bond_dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! ( bond_dev - > priv_flags  &  IFF_BONDING )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    ! ( bond_dev - > flags  &  IFF_MASTER ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										goto  out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! arp )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-12-09 23:09:22 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										pr_debug ( " Packet has no ARP data \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										goto  out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( skb - > len  <  sizeof ( struct  arp_pkt ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-12-09 23:09:22 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										pr_debug ( " Packet is too small to be an ARP \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										goto  out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( arp - > op_code  = =  htons ( ARPOP_REPLY ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* update rx hash table for this ARP */ 
							 
						 
					
						
							
								
									
										
										
										
											2008-11-12 23:37:49 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bond  =  netdev_priv ( bond_dev ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										rlb_update_entry_from_arp ( bond ,  arp ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-12-09 23:09:22 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										pr_debug ( " Server received an ARP Reply from client \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  NET_RX_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								out :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dev_kfree_skb ( skb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Caller must hold bond lock for read */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  slave  * rlb_next_rx_slave ( struct  bonding  * bond )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  alb_bond_info  * bond_info  =  & ( BOND_ALB_INFO ( bond ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  slave  * rx_slave ,  * slave ,  * start_at ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bond_info - > next_rx_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										start_at  =  bond_info - > next_rx_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										start_at  =  bond - > first_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									rx_slave  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bond_for_each_slave_from ( bond ,  slave ,  i ,  start_at )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( SLAVE_IS_OK ( slave ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! rx_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												rx_slave  =  slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  if  ( slave - > speed  >  rx_slave - > speed )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												rx_slave  =  slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( rx_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond_info - > next_rx_slave  =  rx_slave - > next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  rx_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* teach the switch the mac of a disabled slave
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  on  the  primary  for  fault  tolerance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Caller  must  hold  bond - > curr_slave_lock  for  write  or  bond  lock  for  write 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  rlb_teach_disabled_mac_on_primary ( struct  bonding  * bond ,  u8  addr [ ] )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! bond - > curr_active_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! bond - > alb_info . primary_is_promisc )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-14 20:51:36 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! dev_set_promiscuity ( bond - > curr_active_slave - > dev ,  1 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bond - > alb_info . primary_is_promisc  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bond - > alb_info . primary_is_promisc  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bond - > alb_info . rlb_promisc_timeout_counter  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									alb_send_learning_packets ( bond - > curr_active_slave ,  addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* slave being removed should not be active at this point
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Caller  must  hold  bond  lock  for  read 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  rlb_clear_slave ( struct  bonding  * bond ,  struct  slave  * slave )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  alb_bond_info  * bond_info  =  & ( BOND_ALB_INFO ( bond ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  rlb_client_info  * rx_hash_table ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									u32  index ,  next_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* clear slave from rx_hashtbl */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_lock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									rx_hash_table  =  bond_info - > rx_hashtbl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									index  =  bond_info - > rx_hashtbl_head ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( ;  index  ! =  RLB_NULL_INDEX ;  index  =  next_index )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										next_index  =  rx_hash_table [ index ] . next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( rx_hash_table [ index ] . slave  = =  slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  slave  * assigned_slave  =  rlb_next_rx_slave ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( assigned_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												rx_hash_table [ index ] . slave  =  assigned_slave ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-09-01 06:31:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  ( compare_ether_addr_64bits ( rx_hash_table [ index ] . mac_dst , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															      mac_bcast ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
													bond_info - > rx_hashtbl [ index ] . ntt  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													bond_info - > rx_ntt  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													/* A slave has been removed from the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 *  table  because  it  is  either  disabled 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 *  or  being  released .  We  must  retry  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 *  update  to  avoid  clients  from  not 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 *  being  updated  &  disconnecting  when 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 *  there  is  stress 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													bond_info - > rlb_update_retry_counter  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														RLB_UPDATE_RETRY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  {   /* there is no active slave */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												rx_hash_table [ index ] . slave  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_unlock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:50 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									write_lock_bh ( & bond - > curr_slave_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( slave  ! =  bond - > curr_active_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rlb_teach_disabled_mac_on_primary ( bond ,  slave - > dev - > dev_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:50 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									write_unlock_bh ( & bond - > curr_slave_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  rlb_update_client ( struct  rlb_client_info  * client_info )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! client_info - > slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  RLB_ARP_BURST_SIZE ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  sk_buff  * skb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										skb  =  arp_create ( ARPOP_REPLY ,  ETH_P_ARP , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 client_info - > ip_dst , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 client_info - > slave - > dev , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 client_info - > ip_src , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 client_info - > mac_dst , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 client_info - > slave - > dev - > dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 client_info - > mac_dst ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! skb )  { 
							 
						 
					
						
							
								
									
										
										
										
											2009-12-13 20:06:07 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											pr_err ( " %s: Error: failed to create an ARP packet \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-09 10:34:57 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											       client_info - > slave - > dev - > master - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										skb - > dev  =  client_info - > slave - > dev ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( client_info - > tag )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											skb  =  vlan_put_tag ( skb ,  client_info - > vlan_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! skb )  { 
							 
						 
					
						
							
								
									
										
										
										
											2009-12-13 20:06:07 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												pr_err ( " %s: Error: failed to insert VLAN tag \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-09 10:34:57 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												       client_info - > slave - > dev - > master - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										arp_xmit ( skb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* sends ARP REPLIES that update the clients that need updating */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  rlb_update_rx_clients ( struct  bonding  * bond )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  alb_bond_info  * bond_info  =  & ( BOND_ALB_INFO ( bond ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  rlb_client_info  * client_info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									u32  hash_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_lock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									hash_index  =  bond_info - > rx_hashtbl_head ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( ;  hash_index  ! =  RLB_NULL_INDEX ;  hash_index  =  client_info - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										client_info  =  & ( bond_info - > rx_hashtbl [ hash_index ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( client_info - > ntt )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											rlb_update_client ( client_info ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( bond_info - > rlb_update_retry_counter  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												client_info - > ntt  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-10-16 15:20:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* do not update the entries again until this counter is zero so that
 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									 *  not  to  confuse  the  clients . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bond_info - > rlb_update_delay_counter  =  RLB_UPDATE_DELAY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_unlock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* The slave was assigned a new mac address - update the clients */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  rlb_req_update_slave_clients ( struct  bonding  * bond ,  struct  slave  * slave )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  alb_bond_info  * bond_info  =  & ( BOND_ALB_INFO ( bond ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  rlb_client_info  * client_info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ntt  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									u32  hash_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_lock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									hash_index  =  bond_info - > rx_hashtbl_head ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( ;  hash_index  ! =  RLB_NULL_INDEX ;  hash_index  =  client_info - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										client_info  =  & ( bond_info - > rx_hashtbl [ hash_index ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ( client_info - > slave  = =  slave )  & & 
							 
						 
					
						
							
								
									
										
										
										
											2009-09-01 06:31:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										    compare_ether_addr_64bits ( client_info - > mac_dst ,  mac_bcast ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											client_info - > ntt  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ntt  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// update the team's flag only after the whole iteration
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ntt )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond_info - > rx_ntt  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										//fasten the change
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond_info - > rlb_update_retry_counter  =  RLB_UPDATE_RETRY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_unlock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* mark all clients using src_ip to be updated */  
						 
					
						
							
								
									
										
										
										
											2007-08-22 20:06:58 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  rlb_req_update_subnet_clients ( struct  bonding  * bond ,  __be32  src_ip )  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  alb_bond_info  * bond_info  =  & ( BOND_ALB_INFO ( bond ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  rlb_client_info  * client_info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									u32  hash_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_lock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									hash_index  =  bond_info - > rx_hashtbl_head ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( ;  hash_index  ! =  RLB_NULL_INDEX ;  hash_index  =  client_info - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										client_info  =  & ( bond_info - > rx_hashtbl [ hash_index ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! client_info - > slave )  { 
							 
						 
					
						
							
								
									
										
										
										
											2009-12-13 20:06:07 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											pr_err ( " %s: Error: found a client with no channel in the client's hash table \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-09 10:34:57 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											       bond - > dev - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*update all clients using this src_ip, that are not assigned
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  to  the  team ' s  address  ( curr_active_slave )  and  have  a  known 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  unicast  mac  address . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ( client_info - > ip_src  = =  src_ip )  & & 
							 
						 
					
						
							
								
									
										
										
										
											2009-09-01 06:31:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										    compare_ether_addr_64bits ( client_info - > slave - > dev - > dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   bond - > dev - > dev_addr )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    compare_ether_addr_64bits ( client_info - > mac_dst ,  mac_bcast ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											client_info - > ntt  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bond_info - > rx_ntt  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_unlock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Caller must hold both bond and ptr locks for read */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  slave  * rlb_choose_channel ( struct  sk_buff  * skb ,  struct  bonding  * bond )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  alb_bond_info  * bond_info  =  & ( BOND_ALB_INFO ( bond ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-03-10 16:07:19 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  arp_pkt  * arp  =  arp_pkt ( skb ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									struct  slave  * assigned_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  rlb_client_info  * client_info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									u32  hash_index  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_lock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									hash_index  =  _simple_hash ( ( u8  * ) & arp - > ip_dst ,  sizeof ( arp - > ip_src ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									client_info  =  & ( bond_info - > rx_hashtbl [ hash_index ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( client_info - > assigned )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ( client_info - > ip_src  = =  arp - > ip_src )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    ( client_info - > ip_dst  = =  arp - > ip_dst ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* the entry is already assigned to this client */ 
							 
						 
					
						
							
								
									
										
										
										
											2009-09-01 06:31:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( compare_ether_addr_64bits ( arp - > mac_dst ,  mac_bcast ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												/* update mac address from arp */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												memcpy ( client_info - > mac_dst ,  arp - > mac_dst ,  ETH_ALEN ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											assigned_slave  =  client_info - > slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( assigned_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												_unlock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  assigned_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* the entry is already assigned to some other client,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  move  the  old  client  to  primary  ( curr_active_slave )  so 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  that  the  new  client  can  be  assigned  to  this  entry . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( bond - > curr_active_slave  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											    client_info - > slave  ! =  bond - > curr_active_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												client_info - > slave  =  bond - > curr_active_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												rlb_update_client ( client_info ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* assign a new slave */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									assigned_slave  =  rlb_next_rx_slave ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( assigned_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										client_info - > ip_src  =  arp - > ip_src ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										client_info - > ip_dst  =  arp - > ip_dst ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* arp->mac_dst is broadcast for arp reqeusts.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  will  be  updated  with  clients  actual  unicast  mac  address 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  upon  receiving  an  arp  reply . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memcpy ( client_info - > mac_dst ,  arp - > mac_dst ,  ETH_ALEN ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										client_info - > slave  =  assigned_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-09-01 06:31:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( compare_ether_addr_64bits ( client_info - > mac_dst ,  mac_bcast ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											client_info - > ntt  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bond - > alb_info . rx_ntt  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											client_info - > ntt  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! list_empty ( & bond - > vlan_list ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-03-21 22:29:34 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ! vlan_get_tag ( skb ,  & client_info - > vlan_id ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												client_info - > tag  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! client_info - > assigned )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											u32  prev_tbl_head  =  bond_info - > rx_hashtbl_head ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bond_info - > rx_hashtbl_head  =  hash_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											client_info - > next  =  prev_tbl_head ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( prev_tbl_head  ! =  RLB_NULL_INDEX )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												bond_info - > rx_hashtbl [ prev_tbl_head ] . prev  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													hash_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											client_info - > assigned  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_unlock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  assigned_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* chooses (and returns) transmit channel for arp reply
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  does  not  choose  channel  for  other  arp  types  since  they  are 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  sent  on  the  curr_active_slave 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  slave  * rlb_arp_xmit ( struct  sk_buff  * skb ,  struct  bonding  * bond )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2007-03-10 16:07:19 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  arp_pkt  * arp  =  arp_pkt ( skb ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									struct  slave  * tx_slave  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-09-02 10:08:08 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( arp - > op_code  = =  htons ( ARPOP_REPLY ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										/* the arp must be sent on the selected
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										*  rx  channel 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										*/ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tx_slave  =  rlb_choose_channel ( skb ,  bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( tx_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											memcpy ( arp - > mac_src , tx_slave - > dev - > dev_addr ,  ETH_ALEN ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2008-12-09 23:09:22 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										pr_debug ( " Server sent ARP Reply packet \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-09-02 10:08:08 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( arp - > op_code  = =  htons ( ARPOP_REQUEST ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										/* Create an entry in the rx_hashtbl for this client as a
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  place  holder . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  When  the  arp  reply  is  received  the  entry  will  be  updated 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  with  the  correct  unicast  address  of  the  client . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rlb_choose_channel ( skb ,  bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* The ARP relpy packets must be delayed so that
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  they  can  cancel  out  the  influence  of  the  ARP  request . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond - > alb_info . rlb_update_delay_counter  =  RLB_UPDATE_DELAY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* arp requests are broadcast and are sent on the primary
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  the  arp  request  will  collapse  all  clients  on  the  subnet  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  the  primary  slave .  We  must  register  these  clients  to  be 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  updated  with  their  assigned  mac . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rlb_req_update_subnet_clients ( bond ,  arp - > ip_src ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-12-09 23:09:22 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										pr_debug ( " Server sent ARP Request packet \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  tx_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Caller must hold bond lock for read */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  rlb_rebalance ( struct  bonding  * bond )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  alb_bond_info  * bond_info  =  & ( BOND_ALB_INFO ( bond ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  slave  * assigned_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  rlb_client_info  * client_info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ntt ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									u32  hash_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_lock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ntt  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									hash_index  =  bond_info - > rx_hashtbl_head ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( ;  hash_index  ! =  RLB_NULL_INDEX ;  hash_index  =  client_info - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										client_info  =  & ( bond_info - > rx_hashtbl [ hash_index ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										assigned_slave  =  rlb_next_rx_slave ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( assigned_slave  & &  ( client_info - > slave  ! =  assigned_slave ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											client_info - > slave  =  assigned_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											client_info - > ntt  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ntt  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* update the team's flag only after the whole iteration */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ntt )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond_info - > rx_ntt  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_unlock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Caller must hold rx_hashtbl lock */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  rlb_init_table_entry ( struct  rlb_client_info  * entry )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									memset ( entry ,  0 ,  sizeof ( struct  rlb_client_info ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									entry - > next  =  RLB_NULL_INDEX ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									entry - > prev  =  RLB_NULL_INDEX ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  rlb_initialize ( struct  bonding  * bond )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  alb_bond_info  * bond_info  =  & ( BOND_ALB_INFO ( bond ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  packet_type  * pk_type  =  & ( BOND_ALB_INFO ( bond ) . rlb_pkt_type ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-09 10:35:30 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  rlb_client_info 	* new_hashtbl ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									int  size  =  RLB_HASH_TABLE_SIZE  *  sizeof ( struct  rlb_client_info ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									spin_lock_init ( & ( bond_info - > rx_hashtbl_lock ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-11-09 10:35:30 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									new_hashtbl  =  kmalloc ( size ,  GFP_KERNEL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! new_hashtbl )  { 
							 
						 
					
						
							
								
									
										
										
										
											2009-12-13 20:06:07 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										pr_err ( " %s: Error: Failed to allocate RLB hash table \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										       bond - > dev - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-09 10:35:30 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									_lock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bond_info - > rx_hashtbl  =  new_hashtbl ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bond_info - > rx_hashtbl_head  =  RLB_NULL_INDEX ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  RLB_HASH_TABLE_SIZE ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rlb_init_table_entry ( bond_info - > rx_hashtbl  +  i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_unlock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*initialize packet type*/ 
							 
						 
					
						
							
								
									
										
										
										
											2009-02-01 00:45:17 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									pk_type - > type  =  cpu_to_be16 ( ETH_P_ARP ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-11-04 17:51:15 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									pk_type - > dev  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									pk_type - > func  =  rlb_arp_recv ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* register to receive ARPs */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dev_add_pack ( pk_type ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  rlb_deinitialize ( struct  bonding  * bond )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  alb_bond_info  * bond_info  =  & ( BOND_ALB_INFO ( bond ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dev_remove_pack ( & ( bond_info - > rlb_pkt_type ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_lock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									kfree ( bond_info - > rx_hashtbl ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bond_info - > rx_hashtbl  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bond_info - > rx_hashtbl_head  =  RLB_NULL_INDEX ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_unlock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  rlb_clear_vlan ( struct  bonding  * bond ,  unsigned  short  vlan_id )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  alb_bond_info  * bond_info  =  & ( BOND_ALB_INFO ( bond ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									u32  curr_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_lock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									curr_index  =  bond_info - > rx_hashtbl_head ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( curr_index  ! =  RLB_NULL_INDEX )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  rlb_client_info  * curr  =  & ( bond_info - > rx_hashtbl [ curr_index ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										u32  next_index  =  bond_info - > rx_hashtbl [ curr_index ] . next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										u32  prev_index  =  bond_info - > rx_hashtbl [ curr_index ] . prev ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( curr - > tag  & &  ( curr - > vlan_id  = =  vlan_id ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( curr_index  = =  bond_info - > rx_hashtbl_head )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												bond_info - > rx_hashtbl_head  =  next_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( prev_index  ! =  RLB_NULL_INDEX )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												bond_info - > rx_hashtbl [ prev_index ] . next  =  next_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( next_index  ! =  RLB_NULL_INDEX )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												bond_info - > rx_hashtbl [ next_index ] . prev  =  prev_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											rlb_init_table_entry ( curr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										curr_index  =  next_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_unlock_rx_hashtbl ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*********************** tlb/rlb shared functions *********************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  alb_send_learning_packets ( struct  slave  * slave ,  u8  mac_addr [ ] )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  bonding  * bond  =  bond_get_bond_by_slave ( slave ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  learning_pkt  pkt ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  size  =  sizeof ( struct  learning_pkt ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									memset ( & pkt ,  0 ,  size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									memcpy ( pkt . mac_dst ,  mac_addr ,  ETH_ALEN ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									memcpy ( pkt . mac_src ,  mac_addr ,  ETH_ALEN ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-02-01 00:45:17 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									pkt . type  =  cpu_to_be16 ( ETH_P_LOOP ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  MAX_LP_BURST ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  sk_buff  * skb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										char  * data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										skb  =  dev_alloc_skb ( size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! skb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										data  =  skb_put ( skb ,  size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memcpy ( data ,  & pkt ,  size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-03-19 15:30:44 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										skb_reset_mac_header ( skb ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-04-10 21:21:55 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										skb - > network_header  =  skb - > mac_header  +  ETH_HLEN ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										skb - > protocol  =  pkt . type ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										skb - > priority  =  TC_PRIO_CONTROL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										skb - > dev  =  slave - > dev ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! list_empty ( & bond - > vlan_list ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  vlan_entry  * vlan ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											vlan  =  bond_next_vlan ( bond , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													      bond - > alb_info . current_alb_vlan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bond - > alb_info . current_alb_vlan  =  vlan ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! vlan )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												kfree_skb ( skb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											skb  =  vlan_put_tag ( skb ,  vlan - > vlan_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! skb )  { 
							 
						 
					
						
							
								
									
										
										
										
											2009-12-13 20:06:07 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												pr_err ( " %s: Error: failed to insert VLAN tag \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-09 10:34:57 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												       bond - > dev - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dev_queue_xmit ( skb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* hw is a boolean parameter that determines whether we should try and
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  set  the  hw  address  of  the  device  as  well  as  the  hw  address  of  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  net_device 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  alb_set_slave_mac_addr ( struct  slave  * slave ,  u8  addr [ ] ,  int  hw )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  net_device  * dev  =  slave - > dev ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sockaddr  s_addr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! hw )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memcpy ( dev - > dev_addr ,  addr ,  dev - > addr_len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* for rlb each slave must have a unique hw mac addresses so that */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* each slave will receive packets destined to a different mac */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									memcpy ( s_addr . sa_data ,  addr ,  dev - > addr_len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									s_addr . sa_family  =  dev - > type ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( dev_set_mac_address ( dev ,  & s_addr ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2009-12-13 20:06:07 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										pr_err ( " %s: Error: dev_set_mac_address of dev %s failed! \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       " ALB mode requires that the base driver support setting the hw address also when the network device's interface is open \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-09 10:34:57 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										       dev - > master - > name ,  dev - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  - EOPNOTSUPP ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:49 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Swap  MAC  addresses  between  two  slaves . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Called  with  RTNL  held ,  and  no  other  locks . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								static  void  alb_swap_mac_addr ( struct  bonding  * bond ,  struct  slave  * slave1 ,  struct  slave  * slave2 )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									u8  tmp_mac_addr [ ETH_ALEN ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									memcpy ( tmp_mac_addr ,  slave1 - > dev - > dev_addr ,  ETH_ALEN ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									alb_set_slave_mac_addr ( slave1 ,  slave2 - > dev - > dev_addr ,  bond - > alb_info . rlb_enabled ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									alb_set_slave_mac_addr ( slave2 ,  tmp_mac_addr ,  bond - > alb_info . rlb_enabled ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:49 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Send  learning  packets  after  MAC  address  swap . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2008-01-17 16:24:59 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Called  with  RTNL  and  no  other  locks 
							 
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:49 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  alb_fasten_mac_swap ( struct  bonding  * bond ,  struct  slave  * slave1 ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												struct  slave  * slave2 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  slaves_state_differ  =  ( SLAVE_IS_OK ( slave1 )  ! =  SLAVE_IS_OK ( slave2 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  slave  * disabled_slave  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-01-17 16:24:59 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ASSERT_RTNL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									/* fasten the change in the switch */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( SLAVE_IS_OK ( slave1 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										alb_send_learning_packets ( slave1 ,  slave1 - > dev - > dev_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( bond - > alb_info . rlb_enabled )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* inform the clients that the mac address
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  has  changed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											rlb_req_update_slave_clients ( bond ,  slave1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										disabled_slave  =  slave1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( SLAVE_IS_OK ( slave2 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										alb_send_learning_packets ( slave2 ,  slave2 - > dev - > dev_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( bond - > alb_info . rlb_enabled )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* inform the clients that the mac address
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  has  changed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											rlb_req_update_slave_clients ( bond ,  slave2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										disabled_slave  =  slave2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bond - > alb_info . rlb_enabled  & &  slaves_state_differ )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* A disabled slave was assigned an active mac addr */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rlb_teach_disabled_mac_on_primary ( bond , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														  disabled_slave - > dev - > dev_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/**
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  alb_change_hw_addr_on_detach 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @ bond :  bonding  we ' re  working  on 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @ slave :  the  slave  that  was  just  detached 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  We  assume  that  @ slave  was  already  detached  from  the  slave  list . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  If  @ slave ' s  permanent  hw  address  is  different  both  from  its  current 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  address  and  from  @ bond ' s  address ,  then  somewhere  in  the  bond  there ' s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  a  slave  that  has  @ slave ' s  permanet  address  as  its  current  address . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  We ' ll  make  sure  that  that  slave  no  longer  uses  @ slave ' s  permanent  address . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2008-01-17 16:24:59 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Caller  must  hold  RTNL  and  no  other  locks 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  alb_change_hw_addr_on_detach ( struct  bonding  * bond ,  struct  slave  * slave )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  perm_curr_diff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  perm_bond_diff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-09-01 06:31:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									perm_curr_diff  =  compare_ether_addr_64bits ( slave - > perm_hwaddr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														   slave - > dev - > dev_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									perm_bond_diff  =  compare_ether_addr_64bits ( slave - > perm_hwaddr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														   bond - > dev - > dev_addr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( perm_curr_diff  & &  perm_bond_diff )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  slave  * tmp_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  i ,  found  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond_for_each_slave ( bond ,  tmp_slave ,  i )  { 
							 
						 
					
						
							
								
									
										
										
										
											2009-09-01 06:31:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ! compare_ether_addr_64bits ( slave - > perm_hwaddr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														       tmp_slave - > dev - > dev_addr ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												found  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( found )  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:49 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											/* locking: needs RTNL and nothing else */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											alb_swap_mac_addr ( bond ,  slave ,  tmp_slave ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:49 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											alb_fasten_mac_swap ( bond ,  slave ,  tmp_slave ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/**
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  alb_handle_addr_collision_on_attach 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @ bond :  bonding  we ' re  working  on 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @ slave :  the  slave  that  was  just  attached 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  checks  uniqueness  of  slave ' s  mac  address  and  handles  the  case  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  new  slave  uses  the  bonds  mac  address . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  If  the  permanent  hw  address  of  @ slave  is  @ bond ' s  hw  address ,  we  need  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  find  a  different  hw  address  to  give  @ slave ,  that  isn ' t  in  use  by  any  other 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  slave  in  the  bond .  This  address  must  be ,  of  course ,  one  of  the  premanent 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  addresses  of  the  other  slaves . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  We  go  over  the  slave  list ,  and  for  each  slave  there  we  compare  its 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  permanent  hw  address  with  the  current  address  of  all  the  other  slaves . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  If  no  match  was  found ,  then  we ' ve  found  a  slave  with  a  permanent  address 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  that  isn ' t  used  by  any  other  slave  in  the  bond ,  so  we  can  assign  it  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @ slave . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  assumption :  this  function  is  called  before  @ slave  is  attached  to  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  	       bond  slave  list . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  caller  must  hold  the  bond  lock  for  write  since  the  mac  addresses  are  compared 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  and  may  be  swapped . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  alb_handle_addr_collision_on_attach ( struct  bonding  * bond ,  struct  slave  * slave )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  slave  * tmp_slave1 ,  * tmp_slave2 ,  * free_mac_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  slave  * has_bond_addr  =  bond - > curr_active_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ,  j ,  found  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bond - > slave_cnt  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* this is the first slave */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* if slave's mac address differs from bond's mac address
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  check  uniqueness  of  slave ' s  mac  address  against  the  other 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  slaves  in  the  bond . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
									
										
										
										
											2009-09-01 06:31:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( compare_ether_addr_64bits ( slave - > perm_hwaddr ,  bond - > dev - > dev_addr ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										bond_for_each_slave ( bond ,  tmp_slave1 ,  i )  { 
							 
						 
					
						
							
								
									
										
										
										
											2009-09-01 06:31:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ! compare_ether_addr_64bits ( tmp_slave1 - > dev - > dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														       slave - > dev - > dev_addr ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												found  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-28 15:00:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! found ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-28 15:00:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Try setting slave mac to bond address and fall-through
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   to  code  handling  that  situation  below . . .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										alb_set_slave_mac_addr ( slave ,  bond - > dev - > dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       bond - > alb_info . rlb_enabled ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* The slave's address is equal to the address of the bond.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Search  for  a  spare  address  in  the  bond  for  this  slave . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									free_mac_slave  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bond_for_each_slave ( bond ,  tmp_slave1 ,  i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										found  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond_for_each_slave ( bond ,  tmp_slave2 ,  j )  { 
							 
						 
					
						
							
								
									
										
										
										
											2009-09-01 06:31:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ! compare_ether_addr_64bits ( tmp_slave1 - > perm_hwaddr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														       tmp_slave2 - > dev - > dev_addr ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												found  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! found )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* no slave has tmp_slave1's perm addr
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  as  its  curr  addr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											free_mac_slave  =  tmp_slave1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! has_bond_addr )  { 
							 
						 
					
						
							
								
									
										
										
										
											2009-09-01 06:31:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ! compare_ether_addr_64bits ( tmp_slave1 - > dev - > dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														       bond - > dev - > dev_addr ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												has_bond_addr  =  tmp_slave1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( free_mac_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										alb_set_slave_mac_addr ( slave ,  free_mac_slave - > perm_hwaddr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       bond - > alb_info . rlb_enabled ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-12-13 20:06:07 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										pr_warning ( " %s: Warning: the hw address of slave %s is in use by the bond; giving it the hw address of %s \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2009-08-13 04:11:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											   bond - > dev - > name ,  slave - > dev - > name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   free_mac_slave - > dev - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( has_bond_addr )  { 
							 
						 
					
						
							
								
									
										
										
										
											2009-12-13 20:06:07 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										pr_err ( " %s: Error: the hw address of slave %s is in use by the bond; couldn't find a slave with a free hw address to give it (this should not have happened) \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-09 10:34:57 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										       bond - > dev - > name ,  slave - > dev - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  - EFAULT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/**
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  alb_set_mac_address 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @ bond : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @ addr : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  In  TLB  mode  all  slaves  are  configured  to  the  bond ' s  hw  address ,  but  set 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  their  dev_addr  field  to  different  addresses  ( based  on  their  permanent  hw 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  addresses ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  For  each  slave ,  this  function  sets  the  interface  to  the  new  address  and  then 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  changes  its  dev_addr  field  to  its  previous  value . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Unwinding  assumes  bond ' s  mac  address  has  not  yet  changed . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  alb_set_mac_address ( struct  bonding  * bond ,  void  * addr )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sockaddr  sa ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  slave  * slave ,  * stop_at ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  tmp_addr [ ETH_ALEN ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bond - > alb_info . rlb_enabled )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bond_for_each_slave ( bond ,  slave ,  i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* save net_device's current hw address */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memcpy ( tmp_addr ,  slave - > dev - > dev_addr ,  ETH_ALEN ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  dev_set_mac_address ( slave - > dev ,  addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* restore net_device's hw address */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memcpy ( slave - > dev - > dev_addr ,  tmp_addr ,  ETH_ALEN ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-11-19 21:56:05 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( res ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											goto  unwind ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								unwind :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									memcpy ( sa . sa_data ,  bond - > dev - > dev_addr ,  bond - > dev - > addr_len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sa . sa_family  =  bond - > dev - > type ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* unwind from head to the slave that failed */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									stop_at  =  slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bond_for_each_slave_from_to ( bond ,  slave ,  i ,  bond - > first_slave ,  stop_at )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memcpy ( tmp_addr ,  slave - > dev - > dev_addr ,  ETH_ALEN ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dev_set_mac_address ( slave - > dev ,  & sa ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memcpy ( slave - > dev - > dev_addr ,  tmp_addr ,  ETH_ALEN ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/************************ exported alb funcions ************************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  bond_alb_initialize ( struct  bonding  * bond ,  int  rlb_enabled )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  tlb_initialize ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( rlb_enabled )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond - > alb_info . rlb_enabled  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* initialize rlb */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  rlb_initialize ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											tlb_deinitialize ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-09 10:35:35 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond - > alb_info . rlb_enabled  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  bond_alb_deinitialize ( struct  bonding  * bond )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  alb_bond_info  * bond_info  =  & ( BOND_ALB_INFO ( bond ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tlb_deinitialize ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bond_info - > rlb_enabled )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rlb_deinitialize ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  bond_alb_xmit ( struct  sk_buff  * skb ,  struct  net_device  * bond_dev )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2008-11-12 23:37:49 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  bonding  * bond  =  netdev_priv ( bond_dev ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									struct  ethhdr  * eth_data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  alb_bond_info  * bond_info  =  & ( BOND_ALB_INFO ( bond ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  slave  * tx_slave  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-08-22 20:06:58 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									static  const  __be32  ip_bcast  =  htonl ( 0xffffffff ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									int  hash_size  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  do_tx_balance  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									u32  hash_index  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-04-20 22:47:35 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  u8  * hash_start  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									int  res  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-08-28 15:38:41 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ipv6hdr  * ip6hdr ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-03-19 15:30:44 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									skb_reset_mac_header ( skb ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									eth_data  =  eth_hdr ( skb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* make sure that the curr_active_slave and the slaves list do
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  not  change  during  tx 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									read_lock ( & bond - > lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									read_lock ( & bond - > curr_slave_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! BOND_IS_OK ( bond ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( ntohs ( skb - > protocol ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-04-20 22:47:35 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  ETH_P_IP :  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										const  struct  iphdr  * iph  =  ip_hdr ( skb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-09-01 06:31:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! compare_ether_addr_64bits ( eth_data - > h_dest ,  mac_bcast )  | | 
							 
						 
					
						
							
								
									
										
										
										
											2007-04-20 22:47:35 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										    ( iph - > daddr  = =  ip_bcast )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    ( iph - > protocol  = =  IPPROTO_IGMP ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											do_tx_balance  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2007-04-20 22:47:35 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										hash_start  =  ( char  * ) & ( iph - > daddr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hash_size  =  sizeof ( iph - > daddr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  ETH_P_IPV6 : 
							 
						 
					
						
							
								
									
										
										
										
											2008-08-28 15:38:41 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* IPv6 doesn't really use broadcast mac address, but leave
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  that  here  just  in  case . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
									
										
										
										
											2009-09-01 06:31:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! compare_ether_addr_64bits ( eth_data - > h_dest ,  mac_bcast ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											do_tx_balance  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-08-28 15:38:41 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* IPv6 uses all-nodes multicast as an equivalent to
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  broadcasts  in  IPv4 . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
									
										
										
										
											2009-09-01 06:31:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! compare_ether_addr_64bits ( eth_data - > h_dest ,  mac_v6_allmcast ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-08-28 15:38:41 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											do_tx_balance  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Additianally, DAD probes should not be tx-balanced as that
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  will  lead  to  false  positives  for  duplicate  addresses  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  prevent  address  configuration  from  working . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ip6hdr  =  ipv6_hdr ( skb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ipv6_addr_any ( & ip6hdr - > saddr ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											do_tx_balance  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-04-25 17:54:47 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										hash_start  =  ( char  * ) & ( ipv6_hdr ( skb ) - > daddr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hash_size  =  sizeof ( ipv6_hdr ( skb ) - > daddr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  ETH_P_IPX : 
							 
						 
					
						
							
								
									
										
										
										
											2007-08-22 20:06:58 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ipx_hdr ( skb ) - > ipx_checksum  ! =  IPX_NO_CHECKSUM )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											/* something is wrong with this packet */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											do_tx_balance  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ipx_hdr ( skb ) - > ipx_type  ! =  IPX_TYPE_NCP )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* The only protocol worth balancing in
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  this  family  since  it  has  an  " ARP "  like 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  mechanism 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											do_tx_balance  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hash_start  =  ( char * ) eth_data - > h_dest ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hash_size  =  ETH_ALEN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  ETH_P_ARP : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										do_tx_balance  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( bond_info - > rlb_enabled )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											tx_slave  =  rlb_arp_xmit ( skb ,  bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										do_tx_balance  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( do_tx_balance )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hash_index  =  _simple_hash ( hash_start ,  hash_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tx_slave  =  tlb_choose_channel ( bond ,  hash_index ,  skb - > len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! tx_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* unbalanced or unassigned, send through primary */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tx_slave  =  bond - > curr_active_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond_info - > unbalanced_load  + =  skb - > len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( tx_slave  & &  SLAVE_IS_OK ( tx_slave ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( tx_slave  ! =  bond - > curr_active_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											memcpy ( eth_data - > h_source , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											       tx_slave - > dev - > dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											       ETH_ALEN ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  bond_dev_queue_xmit ( bond ,  skb ,  tx_slave - > dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( tx_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											tlb_clear_slave ( bond ,  tx_slave ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								out :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* no suitable interface, frame not sent */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dev_kfree_skb ( skb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									read_unlock ( & bond - > curr_slave_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									read_unlock ( & bond - > lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-07-05 19:23:38 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  NETDEV_TX_OK ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:45 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  bond_alb_monitor ( struct  work_struct  * work )  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:45 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  bonding  * bond  =  container_of ( work ,  struct  bonding , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													    alb_work . work ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									struct  alb_bond_info  * bond_info  =  & ( BOND_ALB_INFO ( bond ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  slave  * slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									read_lock ( & bond - > lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bond - > kill_timers )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bond - > slave_cnt  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond_info - > tx_rebalance_counter  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond_info - > lp_counter  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  re_arm ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bond_info - > tx_rebalance_counter + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bond_info - > lp_counter + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* send learning packets */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bond_info - > lp_counter  > =  BOND_ALB_LP_TICKS )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* change of curr_active_slave involves swapping of mac addresses.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  in  order  to  avoid  this  swapping  from  happening  while 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  sending  the  learning  packets ,  the  curr_slave_lock  must  be  held  for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  read . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										read_lock ( & bond - > curr_slave_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond_for_each_slave ( bond ,  slave ,  i )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-09 10:36:50 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											alb_send_learning_packets ( slave ,  slave - > dev - > dev_addr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										read_unlock ( & bond - > curr_slave_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond_info - > lp_counter  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* rebalance tx traffic */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bond_info - > tx_rebalance_counter  > =  BOND_TLB_REBALANCE_TICKS )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										read_lock ( & bond - > curr_slave_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond_for_each_slave ( bond ,  slave ,  i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											tlb_clear_slave ( bond ,  slave ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( slave  = =  bond - > curr_active_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												SLAVE_TLB_INFO ( slave ) . load  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													bond_info - > unbalanced_load  / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														BOND_TLB_REBALANCE_INTERVAL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												bond_info - > unbalanced_load  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										read_unlock ( & bond - > curr_slave_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond_info - > tx_rebalance_counter  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* handle rlb stuff */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bond_info - > rlb_enabled )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( bond_info - > primary_is_promisc  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    ( + + bond_info - > rlb_promisc_timeout_counter  > =  RLB_PROMISC_TIMEOUT ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:51 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  dev_set_promiscuity  requires  rtnl  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  nothing  else . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											read_unlock ( & bond - > lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											rtnl_lock ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											bond_info - > rlb_promisc_timeout_counter  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* If the primary was set to promiscuous mode
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  because  a  slave  was  disabled  then 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  it  can  now  leave  promiscuous  mode . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											dev_set_promiscuity ( bond - > curr_active_slave - > dev ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bond_info - > primary_is_promisc  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:51 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											rtnl_unlock ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											read_lock ( & bond - > lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( bond_info - > rlb_rebalance )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bond_info - > rlb_rebalance  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											rlb_rebalance ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* check if clients need updating */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( bond_info - > rx_ntt )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( bond_info - > rlb_update_delay_counter )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												- - bond_info - > rlb_update_delay_counter ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												rlb_update_rx_clients ( bond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( bond_info - > rlb_update_retry_counter )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													- - bond_info - > rlb_update_retry_counter ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													bond_info - > rx_ntt  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								re_arm :  
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:45 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									queue_delayed_work ( bond - > wq ,  & bond - > alb_work ,  alb_delta_in_ticks ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								out :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									read_unlock ( & bond - > lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* assumption: called before the slave is attached to the bond
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  and  not  locked  by  the  bond  lock 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  bond_alb_init_slave ( struct  bonding  * bond ,  struct  slave  * slave )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  alb_set_slave_mac_addr ( slave ,  slave - > perm_hwaddr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												     bond - > alb_info . rlb_enabled ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* caller must hold the bond lock for write since the mac addresses
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  are  compared  and  may  be  swapped . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:50 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									read_lock ( & bond - > lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  alb_handle_addr_collision_on_attach ( bond ,  slave ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:50 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									read_unlock ( & bond - > lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tlb_init_slave ( slave ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* order a rebalance ASAP */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bond - > alb_info . tx_rebalance_counter  =  BOND_TLB_REBALANCE_TICKS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bond - > alb_info . rlb_enabled )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond - > alb_info . rlb_rebalance  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-01-17 16:24:59 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Remove  slave  from  tlb  and  rlb  hash  tables ,  and  fix  up  MAC  addresses 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  if  necessary . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Caller  must  hold  RTNL  and  no  other  locks 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								void  bond_alb_deinit_slave ( struct  bonding  * bond ,  struct  slave  * slave )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bond - > slave_cnt  >  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										alb_change_hw_addr_on_detach ( bond ,  slave ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tlb_clear_slave ( bond ,  slave ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bond - > alb_info . rlb_enabled )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond - > alb_info . next_rx_slave  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rlb_clear_slave ( bond ,  slave ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Caller must hold bond lock for read */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  bond_alb_handle_link_change ( struct  bonding  * bond ,  struct  slave  * slave ,  char  link )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  alb_bond_info  * bond_info  =  & ( BOND_ALB_INFO ( bond ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( link  = =  BOND_LINK_DOWN )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tlb_clear_slave ( bond ,  slave ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( bond - > alb_info . rlb_enabled )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											rlb_clear_slave ( bond ,  slave ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( link  = =  BOND_LINK_UP )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* order a rebalance ASAP */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond_info - > tx_rebalance_counter  =  BOND_TLB_REBALANCE_TICKS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( bond - > alb_info . rlb_enabled )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bond - > alb_info . rlb_rebalance  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* If the updelay module parameter is smaller than the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  forwarding  delay  of  the  switch  the  rebalance  will 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  not  work  because  the  rebalance  arp  replies  will 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  not  be  forwarded  to  the  clients . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/**
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  bond_alb_handle_active_change  -  assign  new  curr_active_slave 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @ bond :  our  bonding  struct 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @ new_slave :  new  slave  to  assign 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Set  the  bond - > curr_active_slave  to  @ new_slave  and  handle 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  mac  address  swapping  and  promiscuity  changes  as  needed . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:49 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  If  new_slave  is  NULL ,  caller  must  hold  curr_slave_lock  or 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  bond - > lock  for  write . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  If  new_slave  is  not  NULL ,  caller  must  hold  RTNL ,  bond - > lock  for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  read  and  curr_slave_lock  for  write .   Processing  here  may  sleep ,  so 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  no  other  locks  may  be  held . 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  bond_alb_handle_active_change ( struct  bonding  * bond ,  struct  slave  * new_slave )  
						 
					
						
							
								
									
										
										
										
											2009-02-14 11:15:33 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									__releases ( & bond - > curr_slave_lock ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									__releases ( & bond - > lock ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									__acquires ( & bond - > lock ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									__acquires ( & bond - > curr_slave_lock ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  slave  * swap_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bond - > curr_active_slave  = =  new_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bond - > curr_active_slave  & &  bond - > alb_info . primary_is_promisc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dev_set_promiscuity ( bond - > curr_active_slave - > dev ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond - > alb_info . primary_is_promisc  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond - > alb_info . rlb_promisc_timeout_counter  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									swap_slave  =  bond - > curr_active_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bond - > curr_active_slave  =  new_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! new_slave  | |  ( bond - > slave_cnt  = =  0 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* set the new curr_active_slave to the bonds mac address
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  i . e .  swap  mac  addresses  of  old  curr_active_slave  and  new  curr_active_slave 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! swap_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  slave  * tmp_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* find slave that is holding the bond's mac address */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond_for_each_slave ( bond ,  tmp_slave ,  i )  { 
							 
						 
					
						
							
								
									
										
										
										
											2009-09-01 06:31:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ! compare_ether_addr_64bits ( tmp_slave - > dev - > dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														       bond - > dev - > dev_addr ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												swap_slave  =  tmp_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:49 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Arrange  for  swap_slave  and  new_slave  to  temporarily  be 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  ignored  so  we  can  mess  with  their  MAC  addresses  without 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  fear  of  interference  from  transmit  activity . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( swap_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tlb_clear_slave ( bond ,  swap_slave ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tlb_clear_slave ( bond ,  new_slave ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									write_unlock_bh ( & bond - > curr_slave_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									read_unlock ( & bond - > lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-01-17 16:24:58 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ASSERT_RTNL ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									/* curr_active_slave must be set before calling alb_swap_mac_addr */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( swap_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* swap mac address */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										alb_swap_mac_addr ( bond ,  swap_slave ,  new_slave ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* set the new_slave to the bond mac address */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										alb_set_slave_mac_addr ( new_slave ,  bond - > dev - > dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       bond - > alb_info . rlb_enabled ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:49 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( swap_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										alb_fasten_mac_swap ( bond ,  swap_slave ,  new_slave ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-01-17 16:24:59 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										read_lock ( & bond - > lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:49 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-01-17 16:24:59 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										read_lock ( & bond - > lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										alb_send_learning_packets ( new_slave ,  bond - > dev - > dev_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:49 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									write_lock_bh ( & bond - > curr_slave_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:49 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Called  with  RTNL 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								int  bond_alb_set_mac_address ( struct  net_device  * bond_dev ,  void  * addr )  
						 
					
						
							
								
									
										
										
										
											2009-02-14 11:15:33 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									__acquires ( & bond - > lock ) 
							 
						 
					
						
							
								
									
										
										
										
											2009-05-04 09:03:37 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									__releases ( & bond - > lock ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2008-11-12 23:37:49 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  bonding  * bond  =  netdev_priv ( bond_dev ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									struct  sockaddr  * sa  =  addr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  slave  * slave ,  * swap_slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! is_valid_ether_addr ( sa - > sa_data ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - EADDRNOTAVAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  alb_set_mac_address ( bond ,  addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									memcpy ( bond_dev - > dev_addr ,  sa - > sa_data ,  bond_dev - > addr_len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* If there is no curr_active_slave there is nothing else to do.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Otherwise  we ' ll  need  to  pass  the  new  address  to  it  and  handle 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  duplications . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! bond - > curr_active_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									swap_slave  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bond_for_each_slave ( bond ,  slave ,  i )  { 
							 
						 
					
						
							
								
									
										
										
										
											2009-09-01 06:31:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! compare_ether_addr_64bits ( slave - > dev - > dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													       bond_dev - > dev_addr ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											swap_slave  =  slave ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( swap_slave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										alb_swap_mac_addr ( bond ,  swap_slave ,  bond - > curr_active_slave ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-10-17 17:37:49 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										alb_fasten_mac_swap ( bond ,  swap_slave ,  bond - > curr_active_slave ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										alb_set_slave_mac_addr ( bond - > curr_active_slave ,  bond_dev - > dev_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       bond - > alb_info . rlb_enabled ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-05-04 09:03:37 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										read_lock ( & bond - > lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										alb_send_learning_packets ( bond - > curr_active_slave ,  bond_dev - > dev_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( bond - > alb_info . rlb_enabled )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* inform clients mac address has changed */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											rlb_req_update_slave_clients ( bond ,  bond - > curr_active_slave ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2009-05-04 09:03:37 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										read_unlock ( & bond - > lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  bond_alb_clear_vlan ( struct  bonding  * bond ,  unsigned  short  vlan_id )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bond - > alb_info . current_alb_vlan  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    ( bond - > alb_info . current_alb_vlan - > vlan_id  = =  vlan_id ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bond - > alb_info . current_alb_vlan  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bond - > alb_info . rlb_enabled )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rlb_clear_vlan ( bond ,  vlan_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}