diff options
Diffstat (limited to 'net/core/dev.c')
| -rw-r--r-- | net/core/dev.c | 105 | 
1 files changed, 95 insertions, 10 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 82f20022259d..2b67f2aa59dd 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3421,7 +3421,7 @@ static void qdisc_pkt_len_init(struct sk_buff *skb)  	/* To get more precise estimation of bytes sent on wire,  	 * we add to pkt_len the headers size of all segments  	 */ -	if (shinfo->gso_size)  { +	if (shinfo->gso_size && skb_transport_header_was_set(skb)) {  		unsigned int hdr_len;  		u16 gso_segs = shinfo->gso_segs; @@ -7878,6 +7878,63 @@ int dev_get_phys_port_name(struct net_device *dev,  EXPORT_SYMBOL(dev_get_phys_port_name);  /** + *	dev_get_port_parent_id - Get the device's port parent identifier + *	@dev: network device + *	@ppid: pointer to a storage for the port's parent identifier + *	@recurse: allow/disallow recursion to lower devices + * + *	Get the devices's port parent identifier + */ +int dev_get_port_parent_id(struct net_device *dev, +			   struct netdev_phys_item_id *ppid, +			   bool recurse) +{ +	const struct net_device_ops *ops = dev->netdev_ops; +	struct netdev_phys_item_id first = { }; +	struct net_device *lower_dev; +	struct list_head *iter; +	int err = -EOPNOTSUPP; + +	if (ops->ndo_get_port_parent_id) +		return ops->ndo_get_port_parent_id(dev, ppid); + +	if (!recurse) +		return err; + +	netdev_for_each_lower_dev(dev, lower_dev, iter) { +		err = dev_get_port_parent_id(lower_dev, ppid, recurse); +		if (err) +			break; +		if (!first.id_len) +			first = *ppid; +		else if (memcmp(&first, ppid, sizeof(*ppid))) +			return -ENODATA; +	} + +	return err; +} +EXPORT_SYMBOL(dev_get_port_parent_id); + +/** + *	netdev_port_same_parent_id - Indicate if two network devices have + *	the same port parent identifier + *	@a: first network device + *	@b: second network device + */ +bool netdev_port_same_parent_id(struct net_device *a, struct net_device *b) +{ +	struct netdev_phys_item_id a_id = { }; +	struct netdev_phys_item_id b_id = { }; + +	if (dev_get_port_parent_id(a, &a_id, true) || +	    dev_get_port_parent_id(b, &b_id, true)) +		return false; + +	return netdev_phys_item_id_same(&a_id, &b_id); +} +EXPORT_SYMBOL(netdev_port_same_parent_id); + +/**   *	dev_change_proto_down - update protocol port state information   *	@dev: device   *	@proto_down: new value @@ -7897,6 +7954,25 @@ int dev_change_proto_down(struct net_device *dev, bool proto_down)  }  EXPORT_SYMBOL(dev_change_proto_down); +/** + *	dev_change_proto_down_generic - generic implementation for + * 	ndo_change_proto_down that sets carrier according to + * 	proto_down. + * + *	@dev: device + *	@proto_down: new value + */ +int dev_change_proto_down_generic(struct net_device *dev, bool proto_down) +{ +	if (proto_down) +		netif_carrier_off(dev); +	else +		netif_carrier_on(dev); +	dev->proto_down = proto_down; +	return 0; +} +EXPORT_SYMBOL(dev_change_proto_down_generic); +  u32 __dev_xdp_query(struct net_device *dev, bpf_op_t bpf_op,  		    enum bpf_netdev_command cmd)  { @@ -7976,35 +8052,41 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,  	enum bpf_netdev_command query;  	struct bpf_prog *prog = NULL;  	bpf_op_t bpf_op, bpf_chk; +	bool offload;  	int err;  	ASSERT_RTNL(); -	query = flags & XDP_FLAGS_HW_MODE ? XDP_QUERY_PROG_HW : XDP_QUERY_PROG; +	offload = flags & XDP_FLAGS_HW_MODE; +	query = offload ? XDP_QUERY_PROG_HW : XDP_QUERY_PROG;  	bpf_op = bpf_chk = ops->ndo_bpf; -	if (!bpf_op && (flags & (XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE))) +	if (!bpf_op && (flags & (XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE))) { +		NL_SET_ERR_MSG(extack, "underlying driver does not support XDP in native mode");  		return -EOPNOTSUPP; +	}  	if (!bpf_op || (flags & XDP_FLAGS_SKB_MODE))  		bpf_op = generic_xdp_install;  	if (bpf_op == bpf_chk)  		bpf_chk = generic_xdp_install;  	if (fd >= 0) { -		if (__dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG) || -		    __dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG_HW)) +		if (!offload && __dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG)) { +			NL_SET_ERR_MSG(extack, "native and generic XDP can't be active at the same time");  			return -EEXIST; +		}  		if ((flags & XDP_FLAGS_UPDATE_IF_NOEXIST) && -		    __dev_xdp_query(dev, bpf_op, query)) +		    __dev_xdp_query(dev, bpf_op, query)) { +			NL_SET_ERR_MSG(extack, "XDP program already attached");  			return -EBUSY; +		}  		prog = bpf_prog_get_type_dev(fd, BPF_PROG_TYPE_XDP,  					     bpf_op == ops->ndo_bpf);  		if (IS_ERR(prog))  			return PTR_ERR(prog); -		if (!(flags & XDP_FLAGS_HW_MODE) && -		    bpf_prog_is_dev_bound(prog->aux)) { +		if (!offload && bpf_prog_is_dev_bound(prog->aux)) {  			NL_SET_ERR_MSG(extack, "using device-bound program without HW_MODE flag is not supported");  			bpf_prog_put(prog);  			return -EINVAL; @@ -8152,7 +8234,7 @@ static netdev_features_t netdev_sync_upper_features(struct net_device *lower,  	netdev_features_t feature;  	int feature_bit; -	for_each_netdev_feature(&upper_disables, feature_bit) { +	for_each_netdev_feature(upper_disables, feature_bit) {  		feature = __NETIF_F_BIT(feature_bit);  		if (!(upper->wanted_features & feature)  		    && (features & feature)) { @@ -8172,7 +8254,7 @@ static void netdev_sync_lower_features(struct net_device *upper,  	netdev_features_t feature;  	int feature_bit; -	for_each_netdev_feature(&upper_disables, feature_bit) { +	for_each_netdev_feature(upper_disables, feature_bit) {  		feature = __NETIF_F_BIT(feature_bit);  		if (!(features & feature) && (lower->features & feature)) {  			netdev_dbg(upper, "Disabling feature %pNF on lower dev %s.\n", @@ -8712,6 +8794,9 @@ int init_dummy_netdev(struct net_device *dev)  	set_bit(__LINK_STATE_PRESENT, &dev->state);  	set_bit(__LINK_STATE_START, &dev->state); +	/* napi_busy_loop stats accounting wants this */ +	dev_net_set(dev, &init_net); +  	/* Note : We dont allocate pcpu_refcnt for dummy devices,  	 * because users of this 'device' dont need to change  	 * its refcount.  |