forked from mirrors/linux
		
	bonding, ipv4, ipv6, vlan: Handle NETDEV_BONDING_FAILOVER like NETDEV_NOTIFY_PEERS
It is undesirable for the bonding driver to be poking into higher level protocols, and notifiers provide a way to avoid that. This does mean removing the ability to configure reptitition of gratuitous ARPs and unsolicited NAs. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									99606477a5
								
							
						
					
					
						commit
						7c89943236
					
				
					 7 changed files with 4 additions and 207 deletions
				
			
		|  | @ -9,6 +9,3 @@ bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o bond_debugfs.o | |||
| proc-$(CONFIG_PROC_FS) += bond_procfs.o | ||||
| bonding-objs += $(proc-y) | ||||
| 
 | ||||
| ipv6-$(subst m,y,$(CONFIG_IPV6)) += bond_ipv6.o | ||||
| bonding-objs += $(ipv6-y) | ||||
| 
 | ||||
|  |  | |||
|  | @ -89,8 +89,6 @@ | |||
| 
 | ||||
| static int max_bonds	= BOND_DEFAULT_MAX_BONDS; | ||||
| static int tx_queues	= BOND_DEFAULT_TX_QUEUES; | ||||
| static int num_grat_arp = 1; | ||||
| static int num_unsol_na = 1; | ||||
| static int miimon	= BOND_LINK_MON_INTERV; | ||||
| static int updelay; | ||||
| static int downdelay; | ||||
|  | @ -113,10 +111,6 @@ module_param(max_bonds, int, 0); | |||
| MODULE_PARM_DESC(max_bonds, "Max number of bonded devices"); | ||||
| module_param(tx_queues, int, 0); | ||||
| MODULE_PARM_DESC(tx_queues, "Max number of transmit queues (default = 16)"); | ||||
| module_param(num_grat_arp, int, 0644); | ||||
| MODULE_PARM_DESC(num_grat_arp, "Number of gratuitous ARP packets to send on failover event"); | ||||
| module_param(num_unsol_na, int, 0644); | ||||
| MODULE_PARM_DESC(num_unsol_na, "Number of unsolicited IPv6 Neighbor Advertisements packets to send on failover event"); | ||||
| module_param(miimon, int, 0); | ||||
| MODULE_PARM_DESC(miimon, "Link check interval in milliseconds"); | ||||
| module_param(updelay, int, 0); | ||||
|  | @ -234,7 +228,6 @@ struct bond_parm_tbl ad_select_tbl[] = { | |||
| 
 | ||||
| /*-------------------------- Forward declarations ---------------------------*/ | ||||
| 
 | ||||
| static void bond_send_gratuitous_arp(struct bonding *bond); | ||||
| static int bond_init(struct net_device *bond_dev); | ||||
| static void bond_uninit(struct net_device *bond_dev); | ||||
| 
 | ||||
|  | @ -1162,14 +1155,6 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) | |||
| 				bond_do_fail_over_mac(bond, new_active, | ||||
| 						      old_active); | ||||
| 
 | ||||
| 			if (netif_running(bond->dev)) { | ||||
| 				bond->send_grat_arp = bond->params.num_grat_arp; | ||||
| 				bond_send_gratuitous_arp(bond); | ||||
| 
 | ||||
| 				bond->send_unsol_na = bond->params.num_unsol_na; | ||||
| 				bond_send_unsolicited_na(bond); | ||||
| 			} | ||||
| 
 | ||||
| 			write_unlock_bh(&bond->curr_slave_lock); | ||||
| 			read_unlock(&bond->lock); | ||||
| 
 | ||||
|  | @ -2580,18 +2565,6 @@ void bond_mii_monitor(struct work_struct *work) | |||
| 	if (bond->slave_cnt == 0) | ||||
| 		goto re_arm; | ||||
| 
 | ||||
| 	if (bond->send_grat_arp) { | ||||
| 		read_lock(&bond->curr_slave_lock); | ||||
| 		bond_send_gratuitous_arp(bond); | ||||
| 		read_unlock(&bond->curr_slave_lock); | ||||
| 	} | ||||
| 
 | ||||
| 	if (bond->send_unsol_na) { | ||||
| 		read_lock(&bond->curr_slave_lock); | ||||
| 		bond_send_unsolicited_na(bond); | ||||
| 		read_unlock(&bond->curr_slave_lock); | ||||
| 	} | ||||
| 
 | ||||
| 	if (bond_miimon_inspect(bond)) { | ||||
| 		read_unlock(&bond->lock); | ||||
| 		rtnl_lock(); | ||||
|  | @ -2753,42 +2726,6 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Kick out a gratuitous ARP for an IP on the bonding master plus one | ||||
|  * for each VLAN above us. | ||||
|  * | ||||
|  * Caller must hold curr_slave_lock for read or better | ||||
|  */ | ||||
| static void bond_send_gratuitous_arp(struct bonding *bond) | ||||
| { | ||||
| 	struct slave *slave = bond->curr_active_slave; | ||||
| 	struct vlan_entry *vlan; | ||||
| 
 | ||||
| 	pr_debug("bond_send_grat_arp: bond %s slave %s\n", | ||||
| 		 bond->dev->name, slave ? slave->dev->name : "NULL"); | ||||
| 
 | ||||
| 	if (!slave || !bond->send_grat_arp || | ||||
| 	    test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state)) | ||||
| 		return; | ||||
| 
 | ||||
| 	bond->send_grat_arp--; | ||||
| 
 | ||||
| 	if (bond->master_ip) { | ||||
| 		bond_arp_send(slave->dev, ARPOP_REPLY, bond->master_ip, | ||||
| 				bond->master_ip, 0); | ||||
| 	} | ||||
| 
 | ||||
| 	if (!bond->vlgrp) | ||||
| 		return; | ||||
| 
 | ||||
| 	list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { | ||||
| 		if (vlan->vlan_ip) { | ||||
| 			bond_arp_send(slave->dev, ARPOP_REPLY, vlan->vlan_ip, | ||||
| 				      vlan->vlan_ip, vlan->vlan_id); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32 sip, __be32 tip) | ||||
| { | ||||
| 	int i; | ||||
|  | @ -3255,18 +3192,6 @@ void bond_activebackup_arp_mon(struct work_struct *work) | |||
| 	if (bond->slave_cnt == 0) | ||||
| 		goto re_arm; | ||||
| 
 | ||||
| 	if (bond->send_grat_arp) { | ||||
| 		read_lock(&bond->curr_slave_lock); | ||||
| 		bond_send_gratuitous_arp(bond); | ||||
| 		read_unlock(&bond->curr_slave_lock); | ||||
| 	} | ||||
| 
 | ||||
| 	if (bond->send_unsol_na) { | ||||
| 		read_lock(&bond->curr_slave_lock); | ||||
| 		bond_send_unsolicited_na(bond); | ||||
| 		read_unlock(&bond->curr_slave_lock); | ||||
| 	} | ||||
| 
 | ||||
| 	if (bond_ab_arp_inspect(bond, delta_in_ticks)) { | ||||
| 		read_unlock(&bond->lock); | ||||
| 		rtnl_lock(); | ||||
|  | @ -3645,9 +3570,6 @@ static int bond_close(struct net_device *bond_dev) | |||
| 
 | ||||
| 	write_lock_bh(&bond->lock); | ||||
| 
 | ||||
| 	bond->send_grat_arp = 0; | ||||
| 	bond->send_unsol_na = 0; | ||||
| 
 | ||||
| 	/* signal timers not to re-arm */ | ||||
| 	bond->kill_timers = 1; | ||||
| 
 | ||||
|  | @ -4724,18 +4646,6 @@ static int bond_check_params(struct bond_params *params) | |||
| 		use_carrier = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (num_grat_arp < 0 || num_grat_arp > 255) { | ||||
| 		pr_warning("Warning: num_grat_arp (%d) not in range 0-255 so it was reset to 1\n", | ||||
| 			   num_grat_arp); | ||||
| 		num_grat_arp = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (num_unsol_na < 0 || num_unsol_na > 255) { | ||||
| 		pr_warning("Warning: num_unsol_na (%d) not in range 0-255 so it was reset to 1\n", | ||||
| 			   num_unsol_na); | ||||
| 		num_unsol_na = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	/* reset values for 802.3ad */ | ||||
| 	if (bond_mode == BOND_MODE_8023AD) { | ||||
| 		if (!miimon) { | ||||
|  | @ -4925,8 +4835,6 @@ static int bond_check_params(struct bond_params *params) | |||
| 	params->mode = bond_mode; | ||||
| 	params->xmit_policy = xmit_hashtype; | ||||
| 	params->miimon = miimon; | ||||
| 	params->num_grat_arp = num_grat_arp; | ||||
| 	params->num_unsol_na = num_unsol_na; | ||||
| 	params->arp_interval = arp_interval; | ||||
| 	params->arp_validate = arp_validate_value; | ||||
| 	params->updelay = updelay; | ||||
|  | @ -5121,7 +5029,6 @@ static int __init bonding_init(void) | |||
| 
 | ||||
| 	register_netdevice_notifier(&bond_netdev_notifier); | ||||
| 	register_inetaddr_notifier(&bond_inetaddr_notifier); | ||||
| 	bond_register_ipv6_notifier(); | ||||
| out: | ||||
| 	return res; | ||||
| err: | ||||
|  | @ -5136,7 +5043,6 @@ static void __exit bonding_exit(void) | |||
| { | ||||
| 	unregister_netdevice_notifier(&bond_netdev_notifier); | ||||
| 	unregister_inetaddr_notifier(&bond_inetaddr_notifier); | ||||
| 	bond_unregister_ipv6_notifier(); | ||||
| 
 | ||||
| 	bond_destroy_sysfs(); | ||||
| 	bond_destroy_debugfs(); | ||||
|  |  | |||
|  | @ -873,84 +873,6 @@ static ssize_t bonding_store_ad_select(struct device *d, | |||
| static DEVICE_ATTR(ad_select, S_IRUGO | S_IWUSR, | ||||
| 		   bonding_show_ad_select, bonding_store_ad_select); | ||||
| 
 | ||||
| /*
 | ||||
|  * Show and set the number of grat ARP to send after a failover event. | ||||
|  */ | ||||
| static ssize_t bonding_show_n_grat_arp(struct device *d, | ||||
| 				   struct device_attribute *attr, | ||||
| 				   char *buf) | ||||
| { | ||||
| 	struct bonding *bond = to_bond(d); | ||||
| 
 | ||||
| 	return sprintf(buf, "%d\n", bond->params.num_grat_arp); | ||||
| } | ||||
| 
 | ||||
| static ssize_t bonding_store_n_grat_arp(struct device *d, | ||||
| 				    struct device_attribute *attr, | ||||
| 				    const char *buf, size_t count) | ||||
| { | ||||
| 	int new_value, ret = count; | ||||
| 	struct bonding *bond = to_bond(d); | ||||
| 
 | ||||
| 	if (sscanf(buf, "%d", &new_value) != 1) { | ||||
| 		pr_err("%s: no num_grat_arp value specified.\n", | ||||
| 		       bond->dev->name); | ||||
| 		ret = -EINVAL; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	if (new_value < 0 || new_value > 255) { | ||||
| 		pr_err("%s: Invalid num_grat_arp value %d not in range 0-255; rejected.\n", | ||||
| 		       bond->dev->name, new_value); | ||||
| 		ret = -EINVAL; | ||||
| 		goto out; | ||||
| 	} else { | ||||
| 		bond->params.num_grat_arp = new_value; | ||||
| 	} | ||||
| out: | ||||
| 	return ret; | ||||
| } | ||||
| static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR, | ||||
| 		   bonding_show_n_grat_arp, bonding_store_n_grat_arp); | ||||
| 
 | ||||
| /*
 | ||||
|  * Show and set the number of unsolicited NA's to send after a failover event. | ||||
|  */ | ||||
| static ssize_t bonding_show_n_unsol_na(struct device *d, | ||||
| 				       struct device_attribute *attr, | ||||
| 				       char *buf) | ||||
| { | ||||
| 	struct bonding *bond = to_bond(d); | ||||
| 
 | ||||
| 	return sprintf(buf, "%d\n", bond->params.num_unsol_na); | ||||
| } | ||||
| 
 | ||||
| static ssize_t bonding_store_n_unsol_na(struct device *d, | ||||
| 					struct device_attribute *attr, | ||||
| 					const char *buf, size_t count) | ||||
| { | ||||
| 	int new_value, ret = count; | ||||
| 	struct bonding *bond = to_bond(d); | ||||
| 
 | ||||
| 	if (sscanf(buf, "%d", &new_value) != 1) { | ||||
| 		pr_err("%s: no num_unsol_na value specified.\n", | ||||
| 		       bond->dev->name); | ||||
| 		ret = -EINVAL; | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	if (new_value < 0 || new_value > 255) { | ||||
| 		pr_err("%s: Invalid num_unsol_na value %d not in range 0-255; rejected.\n", | ||||
| 		       bond->dev->name, new_value); | ||||
| 		ret = -EINVAL; | ||||
| 		goto out; | ||||
| 	} else | ||||
| 		bond->params.num_unsol_na = new_value; | ||||
| out: | ||||
| 	return ret; | ||||
| } | ||||
| static DEVICE_ATTR(num_unsol_na, S_IRUGO | S_IWUSR, | ||||
| 		   bonding_show_n_unsol_na, bonding_store_n_unsol_na); | ||||
| 
 | ||||
| /*
 | ||||
|  * Show and set the MII monitor interval.  There are two tricky bits | ||||
|  * here.  First, if MII monitoring is activated, then we must disable | ||||
|  | @ -1650,8 +1572,6 @@ static struct attribute *per_bond_attrs[] = { | |||
| 	&dev_attr_lacp_rate.attr, | ||||
| 	&dev_attr_ad_select.attr, | ||||
| 	&dev_attr_xmit_hash_policy.attr, | ||||
| 	&dev_attr_num_grat_arp.attr, | ||||
| 	&dev_attr_num_unsol_na.attr, | ||||
| 	&dev_attr_miimon.attr, | ||||
| 	&dev_attr_primary.attr, | ||||
| 	&dev_attr_primary_reselect.attr, | ||||
|  |  | |||
|  | @ -149,8 +149,6 @@ struct bond_params { | |||
| 	int mode; | ||||
| 	int xmit_policy; | ||||
| 	int miimon; | ||||
| 	int num_grat_arp; | ||||
| 	int num_unsol_na; | ||||
| 	int arp_interval; | ||||
| 	int arp_validate; | ||||
| 	int use_carrier; | ||||
|  | @ -178,9 +176,6 @@ struct vlan_entry { | |||
| 	struct list_head vlan_list; | ||||
| 	__be32 vlan_ip; | ||||
| 	unsigned short vlan_id; | ||||
| #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||||
| 	struct in6_addr vlan_ipv6; | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| struct slave { | ||||
|  | @ -234,8 +229,6 @@ struct bonding { | |||
| 	rwlock_t lock; | ||||
| 	rwlock_t curr_slave_lock; | ||||
| 	s8       kill_timers; | ||||
| 	s8	 send_grat_arp; | ||||
| 	s8	 send_unsol_na; | ||||
| 	s8	 setup_by_slave; | ||||
| 	s8       igmp_retrans; | ||||
| #ifdef CONFIG_PROC_FS | ||||
|  | @ -260,9 +253,6 @@ struct bonding { | |||
| 	struct   delayed_work alb_work; | ||||
| 	struct   delayed_work ad_work; | ||||
| 	struct   delayed_work mcast_work; | ||||
| #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||||
| 	struct   in6_addr master_ipv6; | ||||
| #endif | ||||
| #ifdef CONFIG_DEBUG_FS | ||||
| 	/* debugging suport via debugfs */ | ||||
| 	struct	 dentry *debug_dir; | ||||
|  | @ -460,23 +450,4 @@ extern const struct bond_parm_tbl fail_over_mac_tbl[]; | |||
| extern const struct bond_parm_tbl pri_reselect_tbl[]; | ||||
| extern struct bond_parm_tbl ad_select_tbl[]; | ||||
| 
 | ||||
| #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||||
| void bond_send_unsolicited_na(struct bonding *bond); | ||||
| void bond_register_ipv6_notifier(void); | ||||
| void bond_unregister_ipv6_notifier(void); | ||||
| #else | ||||
| static inline void bond_send_unsolicited_na(struct bonding *bond) | ||||
| { | ||||
| 	return; | ||||
| } | ||||
| static inline void bond_register_ipv6_notifier(void) | ||||
| { | ||||
| 	return; | ||||
| } | ||||
| static inline void bond_unregister_ipv6_notifier(void) | ||||
| { | ||||
| 	return; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* _LINUX_BONDING_H */ | ||||
|  |  | |||
|  | @ -501,13 +501,14 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
| 		return NOTIFY_BAD; | ||||
| 
 | ||||
| 	case NETDEV_NOTIFY_PEERS: | ||||
| 	case NETDEV_BONDING_FAILOVER: | ||||
| 		/* Propagate to vlan devices */ | ||||
| 		for (i = 0; i < VLAN_N_VID; i++) { | ||||
| 			vlandev = vlan_group_get_device(grp, i); | ||||
| 			if (!vlandev) | ||||
| 				continue; | ||||
| 
 | ||||
| 			call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, vlandev); | ||||
| 			call_netdevice_notifiers(event, vlandev); | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
|  |  | |||
|  | @ -1203,6 +1203,7 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, | |||
| 			break; | ||||
| 		/* fall through */ | ||||
| 	case NETDEV_NOTIFY_PEERS: | ||||
| 	case NETDEV_BONDING_FAILOVER: | ||||
| 		/* Send gratuitous ARP to notify of link change */ | ||||
| 		inetdev_send_gratuitous_arp(dev, in_dev); | ||||
| 		break; | ||||
|  |  | |||
|  | @ -1747,6 +1747,7 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, | |||
| 		fib6_run_gc(~0UL, net); | ||||
| 		break; | ||||
| 	case NETDEV_NOTIFY_PEERS: | ||||
| 	case NETDEV_BONDING_FAILOVER: | ||||
| 		ndisc_send_unsol_na(dev); | ||||
| 		break; | ||||
| 	default: | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Ben Hutchings
						Ben Hutchings