diff options
Diffstat (limited to 'net/core/dev.c')
| -rw-r--r-- | net/core/dev.c | 138 | 
1 files changed, 92 insertions, 46 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 89e33a5d4d9..1e0a1847c3b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -959,18 +959,30 @@ int dev_alloc_name(struct net_device *dev, const char *name)  }  EXPORT_SYMBOL(dev_alloc_name); -static int dev_get_valid_name(struct net_device *dev, const char *name) +static int dev_alloc_name_ns(struct net *net, +			     struct net_device *dev, +			     const char *name)  { -	struct net *net; +	char buf[IFNAMSIZ]; +	int ret; -	BUG_ON(!dev_net(dev)); -	net = dev_net(dev); +	ret = __dev_alloc_name(net, name, buf); +	if (ret >= 0) +		strlcpy(dev->name, buf, IFNAMSIZ); +	return ret; +} + +static int dev_get_valid_name(struct net *net, +			      struct net_device *dev, +			      const char *name) +{ +	BUG_ON(!net);  	if (!dev_valid_name(name))  		return -EINVAL;  	if (strchr(name, '%')) -		return dev_alloc_name(dev, name); +		return dev_alloc_name_ns(net, dev, name);  	else if (__dev_get_by_name(net, name))  		return -EEXIST;  	else if (dev->name != name) @@ -1006,7 +1018,7 @@ int dev_change_name(struct net_device *dev, const char *newname)  	memcpy(oldname, dev->name, IFNAMSIZ); -	err = dev_get_valid_name(dev, newname); +	err = dev_get_valid_name(net, dev, newname);  	if (err < 0)  		return err; @@ -1109,11 +1121,23 @@ void netdev_state_change(struct net_device *dev)  }  EXPORT_SYMBOL(netdev_state_change); -int netdev_bonding_change(struct net_device *dev, unsigned long event) +/** + * 	netdev_notify_peers - notify network peers about existence of @dev + * 	@dev: network device + * + * Generate traffic such that interested network peers are aware of + * @dev, such as by generating a gratuitous ARP. This may be used when + * a device wants to inform the rest of the network about some sort of + * reconfiguration such as a failover event or virtual machine + * migration. + */ +void netdev_notify_peers(struct net_device *dev)  { -	return call_netdevice_notifiers(event, dev); +	rtnl_lock(); +	call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, dev); +	rtnl_unlock();  } -EXPORT_SYMBOL(netdev_bonding_change); +EXPORT_SYMBOL(netdev_notify_peers);  /**   *	dev_load 	- load a network module @@ -1394,7 +1418,6 @@ rollback:  				nb->notifier_call(nb, NETDEV_DOWN, dev);  			}  			nb->notifier_call(nb, NETDEV_UNREGISTER, dev); -			nb->notifier_call(nb, NETDEV_UNREGISTER_BATCH, dev);  		}  	} @@ -1436,7 +1459,6 @@ int unregister_netdevice_notifier(struct notifier_block *nb)  				nb->notifier_call(nb, NETDEV_DOWN, dev);  			}  			nb->notifier_call(nb, NETDEV_UNREGISTER, dev); -			nb->notifier_call(nb, NETDEV_UNREGISTER_BATCH, dev);  		}  	}  unlock: @@ -2175,9 +2197,7 @@ EXPORT_SYMBOL(netif_skb_features);  /*   * Returns true if either:   *	1. skb has frag_list and the device doesn't support FRAGLIST, or - *	2. skb is fragmented and the device does not support SG, or if - *	   at least one of fragments is in highmem and device does not - *	   support DMA from it. + *	2. skb is fragmented and the device does not support SG.   */  static inline int skb_needs_linearize(struct sk_buff *skb,  				      int features) @@ -2206,9 +2226,6 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,  		if (dev->priv_flags & IFF_XMIT_DST_RELEASE)  			skb_dst_drop(skb); -		if (!list_empty(&ptype_all)) -			dev_queue_xmit_nit(skb, dev); -  		features = netif_skb_features(skb);  		if (vlan_tx_tag_present(skb) && @@ -2243,6 +2260,9 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,  			}  		} +		if (!list_empty(&ptype_all)) +			dev_queue_xmit_nit(skb, dev); +  		skb_len = skb->len;  		rc = ops->ndo_start_xmit(skb, dev);  		trace_net_dev_xmit(skb, rc, dev, skb_len); @@ -2265,6 +2285,9 @@ gso:  		if (dev->priv_flags & IFF_XMIT_DST_RELEASE)  			skb_dst_drop(nskb); +		if (!list_empty(&ptype_all)) +			dev_queue_xmit_nit(nskb, dev); +  		skb_len = nskb->len;  		rc = ops->ndo_start_xmit(nskb, dev);  		trace_net_dev_xmit(nskb, rc, dev, skb_len); @@ -2374,8 +2397,8 @@ static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)  #endif  } -static struct netdev_queue *dev_pick_tx(struct net_device *dev, -					struct sk_buff *skb) +struct netdev_queue *netdev_pick_tx(struct net_device *dev, +				    struct sk_buff *skb)  {  	int queue_index;  	const struct net_device_ops *ops = dev->netdev_ops; @@ -2549,7 +2572,7 @@ int dev_queue_xmit(struct sk_buff *skb)  	skb_update_prio(skb); -	txq = dev_pick_tx(dev, skb); +	txq = netdev_pick_tx(dev, skb);  	q = rcu_dereference_bh(txq->qdisc);  #ifdef CONFIG_NET_CLS_ACT @@ -2622,6 +2645,8 @@ EXPORT_SYMBOL(dev_queue_xmit);    =======================================================================*/  int netdev_max_backlog __read_mostly = 1000; +EXPORT_SYMBOL(netdev_max_backlog); +  int netdev_tstamp_prequeue __read_mostly = 1;  int netdev_budget __read_mostly = 300;  int weight_p __read_mostly = 64;            /* old backlog weight */ @@ -4512,8 +4537,8 @@ static void dev_change_rx_flags(struct net_device *dev, int flags)  static int __dev_set_promiscuity(struct net_device *dev, int inc)  {  	unsigned int old_flags = dev->flags; -	uid_t uid; -	gid_t gid; +	kuid_t uid; +	kgid_t gid;  	ASSERT_RTNL(); @@ -4544,8 +4569,9 @@ static int __dev_set_promiscuity(struct net_device *dev, int inc)  				"dev=%s prom=%d old_prom=%d auid=%u uid=%u gid=%u ses=%u",  				dev->name, (dev->flags & IFF_PROMISC),  				(old_flags & IFF_PROMISC), -				audit_get_loginuid(current), -				uid, gid, +				from_kuid(&init_user_ns, audit_get_loginuid(current)), +				from_kuid(&init_user_ns, uid), +				from_kgid(&init_user_ns, gid),  				audit_get_sessionid(current));  		} @@ -5238,12 +5264,12 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)   */  static int dev_new_index(struct net *net)  { -	static int ifindex; +	int ifindex = net->ifindex;  	for (;;) {  		if (++ifindex <= 0)  			ifindex = 1;  		if (!__dev_get_by_index(net, ifindex)) -			return ifindex; +			return net->ifindex = ifindex;  	}  } @@ -5321,10 +5347,6 @@ static void rollback_registered_many(struct list_head *head)  		netdev_unregister_kobject(dev);  	} -	/* Process any work delayed until the end of the batch */ -	dev = list_first_entry(head, struct net_device, unreg_list); -	call_netdevice_notifiers(NETDEV_UNREGISTER_BATCH, dev); -  	synchronize_net();  	list_for_each_entry(dev, head, unreg_list) @@ -5582,7 +5604,7 @@ int register_netdevice(struct net_device *dev)  	dev->iflink = -1; -	ret = dev_get_valid_name(dev, dev->name); +	ret = dev_get_valid_name(net, dev, dev->name);  	if (ret < 0)  		goto out; @@ -5596,7 +5618,12 @@ int register_netdevice(struct net_device *dev)  		}  	} -	dev->ifindex = dev_new_index(net); +	ret = -EBUSY; +	if (!dev->ifindex) +		dev->ifindex = dev_new_index(net); +	else if (__dev_get_by_index(net, dev->ifindex)) +		goto err_uninit; +  	if (dev->iflink == -1)  		dev->iflink = dev->ifindex; @@ -5639,6 +5666,8 @@ int register_netdevice(struct net_device *dev)  	set_bit(__LINK_STATE_PRESENT, &dev->state); +	linkwatch_init_dev(dev); +  	dev_init_scheduler(dev);  	dev_hold(dev);  	list_netdevice(dev); @@ -5772,9 +5801,12 @@ static void netdev_wait_allrefs(struct net_device *dev)  			/* Rebroadcast unregister notification */  			call_netdevice_notifiers(NETDEV_UNREGISTER, dev); -			/* don't resend NETDEV_UNREGISTER_BATCH, _BATCH users -			 * should have already handle it the first time */ +			__rtnl_unlock(); +			rcu_barrier(); +			rtnl_lock(); + +			call_netdevice_notifiers(NETDEV_UNREGISTER_FINAL, dev);  			if (test_bit(__LINK_STATE_LINKWATCH_PENDING,  				     &dev->state)) {  				/* We must not have linkwatch events @@ -5836,9 +5868,8 @@ void netdev_run_todo(void)  	__rtnl_unlock(); -	/* Wait for rcu callbacks to finish before attempting to drain -	 * the device list.  This usually avoids a 250ms wait. -	 */ + +	/* Wait for rcu callbacks to finish before next phase */  	if (!list_empty(&list))  		rcu_barrier(); @@ -5847,6 +5878,10 @@ void netdev_run_todo(void)  			= list_first_entry(&list, struct net_device, todo_list);  		list_del(&dev->todo_list); +		rtnl_lock(); +		call_netdevice_notifiers(NETDEV_UNREGISTER_FINAL, dev); +		__rtnl_unlock(); +  		if (unlikely(dev->reg_state != NETREG_UNREGISTERING)) {  			pr_err("network todo '%s' but state %d\n",  			       dev->name, dev->reg_state); @@ -5942,6 +5977,8 @@ struct netdev_queue *dev_ingress_queue_create(struct net_device *dev)  	return queue;  } +static const struct ethtool_ops default_ethtool_ops; +  /**   *	alloc_netdev_mqs - allocate network device   *	@sizeof_priv:	size of private data to allocate space for @@ -6029,6 +6066,8 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,  	strcpy(dev->name, name);  	dev->group = INIT_NETDEV_GROUP; +	if (!dev->ethtool_ops) +		dev->ethtool_ops = &default_ethtool_ops;  	return dev;  free_all: @@ -6213,7 +6252,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char  		/* We get here if we can't use the current device name */  		if (!pat)  			goto out; -		if (dev_get_valid_name(dev, pat) < 0) +		if (dev_get_valid_name(net, dev, pat) < 0)  			goto out;  	} @@ -6241,7 +6280,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char  	   the device is just moving and can keep their slaves up.  	*/  	call_netdevice_notifiers(NETDEV_UNREGISTER, dev); -	call_netdevice_notifiers(NETDEV_UNREGISTER_BATCH, dev); +	rcu_barrier(); +	call_netdevice_notifiers(NETDEV_UNREGISTER_FINAL, dev);  	rtmsg_ifinfo(RTM_DELLINK, dev, ~0U);  	/* @@ -6424,22 +6464,26 @@ const char *netdev_drivername(const struct net_device *dev)  	return empty;  } -int __netdev_printk(const char *level, const struct net_device *dev, +static int __netdev_printk(const char *level, const struct net_device *dev,  			   struct va_format *vaf)  {  	int r; -	if (dev && dev->dev.parent) -		r = dev_printk(level, dev->dev.parent, "%s: %pV", -			       netdev_name(dev), vaf); -	else if (dev) +	if (dev && dev->dev.parent) { +		r = dev_printk_emit(level[1] - '0', +				    dev->dev.parent, +				    "%s %s %s: %pV", +				    dev_driver_string(dev->dev.parent), +				    dev_name(dev->dev.parent), +				    netdev_name(dev), vaf); +	} else if (dev) {  		r = printk("%s%s: %pV", level, netdev_name(dev), vaf); -	else +	} else {  		r = printk("%s(NULL net_device): %pV", level, vaf); +	}  	return r;  } -EXPORT_SYMBOL(__netdev_printk);  int netdev_printk(const char *level, const struct net_device *dev,  		  const char *format, ...) @@ -6454,6 +6498,7 @@ int netdev_printk(const char *level, const struct net_device *dev,  	vaf.va = &args;  	r = __netdev_printk(level, dev, &vaf); +  	va_end(args);  	return r; @@ -6473,6 +6518,7 @@ int func(const struct net_device *dev, const char *fmt, ...)	\  	vaf.va = &args;						\  								\  	r = __netdev_printk(level, dev, &vaf);			\ +								\  	va_end(args);						\  								\  	return r;						\  |