diff options
Diffstat (limited to 'net/core/dev.c')
| -rw-r--r-- | net/core/dev.c | 101 | 
1 files changed, 66 insertions, 35 deletions
| diff --git a/net/core/dev.c b/net/core/dev.c index 7ee9fecd3aff..edeb811c454e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -140,7 +140,7 @@  #include <linux/if_macvlan.h>  #include <linux/errqueue.h>  #include <linux/hrtimer.h> -#include <linux/netfilter_ingress.h> +#include <linux/netfilter_netdev.h>  #include <linux/crash_dump.h>  #include <linux/sctp.h>  #include <net/udp_tunnel.h> @@ -303,6 +303,12 @@ static struct netdev_name_node *netdev_name_node_lookup_rcu(struct net *net,  	return NULL;  } +bool netdev_name_in_use(struct net *net, const char *name) +{ +	return netdev_name_node_lookup(net, name); +} +EXPORT_SYMBOL(netdev_name_in_use); +  int netdev_name_node_alt_create(struct net_device *dev, const char *name)  {  	struct netdev_name_node *name_node; @@ -1133,7 +1139,7 @@ static int __dev_alloc_name(struct net *net, const char *name, char *buf)  	}  	snprintf(buf, IFNAMSIZ, name, i); -	if (!__dev_get_by_name(net, buf)) +	if (!netdev_name_in_use(net, buf))  		return i;  	/* It is possible to run out of possible slots @@ -1187,7 +1193,7 @@ static int dev_get_valid_name(struct net *net, struct net_device *dev,  	if (strchr(name, '%'))  		return dev_alloc_name_ns(net, dev, name); -	else if (__dev_get_by_name(net, name)) +	else if (netdev_name_in_use(net, name))  		return -EEXIST;  	else if (dev->name != name)  		strlcpy(dev->name, name, IFNAMSIZ); @@ -1290,8 +1296,8 @@ rollback:  			old_assign_type = NET_NAME_RENAMED;  			goto rollback;  		} else { -			pr_err("%s: name change rollback failed: %d\n", -			       dev->name, ret); +			netdev_err(dev, "name change rollback failed: %d\n", +				   ret);  		}  	} @@ -2345,7 +2351,7 @@ static void netif_setup_tc(struct net_device *dev, unsigned int txq)  	/* If TC0 is invalidated disable TC mapping */  	if (tc->offset + tc->count > txq) { -		pr_warn("Number of in use tx queues changed invalidating tc mappings. Priority traffic classification disabled!\n"); +		netdev_warn(dev, "Number of in use tx queues changed invalidating tc mappings. Priority traffic classification disabled!\n");  		dev->num_tc = 0;  		return;  	} @@ -2356,8 +2362,8 @@ static void netif_setup_tc(struct net_device *dev, unsigned int txq)  		tc = &dev->tc_to_txq[q];  		if (tc->offset + tc->count > txq) { -			pr_warn("Number of in use tx queues changed. Priority %i to tc mapping %i is no longer valid. Setting map to 0\n", -				i, q); +			netdev_warn(dev, "Number of in use tx queues changed. Priority %i to tc mapping %i is no longer valid. Setting map to 0\n", +				    i, q);  			netdev_set_prio_tc_map(dev, i, 0);  		}  	} @@ -2921,6 +2927,8 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)  		if (dev->num_tc)  			netif_setup_tc(dev, txq); +		dev_qdisc_change_real_num_tx(dev, txq); +  		dev->real_num_tx_queues = txq;  		if (disabling) { @@ -3163,6 +3171,12 @@ static u16 skb_tx_hash(const struct net_device *dev,  		qoffset = sb_dev->tc_to_txq[tc].offset;  		qcount = sb_dev->tc_to_txq[tc].count; +		if (unlikely(!qcount)) { +			net_warn_ratelimited("%s: invalid qcount, qoffset %u for tc %u\n", +					     sb_dev->name, qoffset, tc); +			qoffset = 0; +			qcount = dev->real_num_tx_queues; +		}  	}  	if (skb_rx_queue_recorded(skb)) { @@ -3408,7 +3422,7 @@ EXPORT_SYMBOL(__skb_gso_segment);  #ifdef CONFIG_BUG  static void do_netdev_rx_csum_fault(struct net_device *dev, struct sk_buff *skb)  { -	pr_err("%s: hw csum failure\n", dev ? dev->name : "<unknown>"); +	netdev_err(dev, "hw csum failure\n");  	skb_dump(KERN_ERR, skb, true);  	dump_stack();  } @@ -3906,7 +3920,8 @@ int dev_loopback_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)  	skb_reset_mac_header(skb);  	__skb_pull(skb, skb_network_offset(skb));  	skb->pkt_type = PACKET_LOOPBACK; -	skb->ip_summed = CHECKSUM_UNNECESSARY; +	if (skb->ip_summed == CHECKSUM_NONE) +		skb->ip_summed = CHECKSUM_UNNECESSARY;  	WARN_ON(!skb_dst(skb));  	skb_dst_force(skb);  	netif_rx_ni(skb); @@ -3918,6 +3933,7 @@ EXPORT_SYMBOL(dev_loopback_xmit);  static struct sk_buff *  sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)  { +#ifdef CONFIG_NET_CLS_ACT  	struct mini_Qdisc *miniq = rcu_dereference_bh(dev->miniq_egress);  	struct tcf_result cl_res; @@ -3953,6 +3969,7 @@ sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)  	default:  		break;  	} +#endif /* CONFIG_NET_CLS_ACT */  	return skb;  } @@ -4146,13 +4163,20 @@ static int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev)  	qdisc_pkt_len_init(skb);  #ifdef CONFIG_NET_CLS_ACT  	skb->tc_at_ingress = 0; -# ifdef CONFIG_NET_EGRESS +#endif +#ifdef CONFIG_NET_EGRESS  	if (static_branch_unlikely(&egress_needed_key)) { +		if (nf_hook_egress_active()) { +			skb = nf_hook_egress(skb, &rc, dev); +			if (!skb) +				goto out; +		} +		nf_skip_egress(skb, true);  		skb = sch_handle_egress(skb, &rc, dev);  		if (!skb)  			goto out; +		nf_skip_egress(skb, false);  	} -# endif  #endif  	/* If device/qdisc don't need skb->dst, release it right now while  	 * its hot in this cpu cache. @@ -5294,6 +5318,7 @@ skip_taps:  	if (static_branch_unlikely(&ingress_needed_key)) {  		bool another = false; +		nf_skip_egress(skb, true);  		skb = sch_handle_ingress(skb, &pt_prev, &ret, orig_dev,  					 &another);  		if (another) @@ -5301,6 +5326,7 @@ skip_taps:  		if (!skb)  			goto out; +		nf_skip_egress(skb, false);  		if (nf_ingress(skb, &pt_prev, &ret, orig_dev) < 0)  			goto out;  	} @@ -5837,7 +5863,7 @@ static void gro_normal_one(struct napi_struct *napi, struct sk_buff *skb, int se  		gro_normal_list(napi);  } -static int napi_gro_complete(struct napi_struct *napi, struct sk_buff *skb) +static void napi_gro_complete(struct napi_struct *napi, struct sk_buff *skb)  {  	struct packet_offload *ptype;  	__be16 type = skb->protocol; @@ -5866,12 +5892,11 @@ static int napi_gro_complete(struct napi_struct *napi, struct sk_buff *skb)  	if (err) {  		WARN_ON(&ptype->list == head);  		kfree_skb(skb); -		return NET_RX_SUCCESS; +		return;  	}  out:  	gro_normal_one(napi, skb, NAPI_GRO_CB(skb)->count); -	return NET_RX_SUCCESS;  }  static void __napi_gro_flush_chain(struct napi_struct *napi, u32 index, @@ -6898,19 +6923,25 @@ EXPORT_SYMBOL(netif_napi_add);  void napi_disable(struct napi_struct *n)  { +	unsigned long val, new; +  	might_sleep();  	set_bit(NAPI_STATE_DISABLE, &n->state); -	while (test_and_set_bit(NAPI_STATE_SCHED, &n->state)) -		msleep(1); -	while (test_and_set_bit(NAPI_STATE_NPSVC, &n->state)) -		msleep(1); +	do { +		val = READ_ONCE(n->state); +		if (val & (NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC)) { +			usleep_range(20, 200); +			continue; +		} + +		new = val | NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC; +		new &= ~(NAPIF_STATE_THREADED | NAPIF_STATE_PREFER_BUSY_POLL); +	} while (cmpxchg(&n->state, val, new) != val);  	hrtimer_cancel(&n->timer); -	clear_bit(NAPI_STATE_PREFER_BUSY_POLL, &n->state);  	clear_bit(NAPI_STATE_DISABLE, &n->state); -	clear_bit(NAPI_STATE_THREADED, &n->state);  }  EXPORT_SYMBOL(napi_disable); @@ -6988,8 +7019,8 @@ static int __napi_poll(struct napi_struct *n, bool *repoll)  	}  	if (unlikely(work > weight)) -		pr_err_once("NAPI poll function %pS returned %d, exceeding its budget of %d.\n", -			    n->poll, work, weight); +		netdev_err_once(n->dev, "NAPI poll function %pS returned %d, exceeding its budget of %d.\n", +				n->poll, work, weight);  	if (likely(work < weight))  		return work; @@ -8543,8 +8574,7 @@ static int __dev_set_promiscuity(struct net_device *dev, int inc, bool notify)  			dev->flags &= ~IFF_PROMISC;  		else {  			dev->promiscuity -= inc; -			pr_warn("%s: promiscuity touches roof, set promiscuity failed. promiscuity feature of device might be broken.\n", -				dev->name); +			netdev_warn(dev, "promiscuity touches roof, set promiscuity failed. promiscuity feature of device might be broken.\n");  			return -EOVERFLOW;  		}  	} @@ -8614,8 +8644,7 @@ static int __dev_set_allmulti(struct net_device *dev, int inc, bool notify)  			dev->flags &= ~IFF_ALLMULTI;  		else {  			dev->allmulti -= inc; -			pr_warn("%s: allmulti touches roof, set allmulti failed. allmulti feature of device might be broken.\n", -				dev->name); +			netdev_warn(dev, "allmulti touches roof, set allmulti failed. allmulti feature of device might be broken.\n");  			return -EOVERFLOW;  		}  	} @@ -9152,14 +9181,11 @@ int dev_get_port_parent_id(struct net_device *dev,  	}  	err = devlink_compat_switch_id_get(dev, ppid); -	if (!err || err != -EOPNOTSUPP) +	if (!recurse || err != -EOPNOTSUPP)  		return err; -	if (!recurse) -		return -EOPNOTSUPP; -  	netdev_for_each_lower_dev(dev, lower_dev, iter) { -		err = dev_get_port_parent_id(lower_dev, ppid, recurse); +		err = dev_get_port_parent_id(lower_dev, ppid, true);  		if (err)  			break;  		if (!first.id_len) @@ -9903,6 +9929,11 @@ static netdev_features_t netdev_fix_features(struct net_device *dev,  		}  	} +	if ((features & NETIF_F_GRO_HW) && (features & NETIF_F_LRO)) { +		netdev_dbg(dev, "Dropping LRO feature since HW-GRO is requested.\n"); +		features &= ~NETIF_F_LRO; +	} +  	if (features & NETIF_F_HW_TLS_TX) {  		bool ip_csum = (features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) ==  			(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); @@ -10860,7 +10891,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,  	if (!dev->ethtool_ops)  		dev->ethtool_ops = &default_ethtool_ops; -	nf_hook_ingress_init(dev); +	nf_hook_netdev_init(dev);  	return dev; @@ -11146,7 +11177,7 @@ int __dev_change_net_namespace(struct net_device *dev, struct net *net,  	 * we can use it in the destination network namespace.  	 */  	err = -EEXIST; -	if (__dev_get_by_name(net, dev->name)) { +	if (netdev_name_in_use(net, dev->name)) {  		/* We get here if we can't use the current device name */  		if (!pat)  			goto out; @@ -11499,7 +11530,7 @@ static void __net_exit default_device_exit(struct net *net)  		/* Push remaining network devices to init_net */  		snprintf(fb_name, IFNAMSIZ, "dev%d", dev->ifindex); -		if (__dev_get_by_name(&init_net, fb_name)) +		if (netdev_name_in_use(&init_net, fb_name))  			snprintf(fb_name, IFNAMSIZ, "dev%%d");  		err = dev_change_net_namespace(dev, &init_net, fb_name);  		if (err) { |