diff options
Diffstat (limited to 'net/core/rtnetlink.c')
| -rw-r--r-- | net/core/rtnetlink.c | 91 | 
1 files changed, 70 insertions, 21 deletions
| diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 5ef61222fdef..24431e578310 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -964,7 +964,8 @@ static size_t rtnl_xdp_size(void)  {  	size_t xdp_size = nla_total_size(0) +	/* nest IFLA_XDP */  			  nla_total_size(1) +	/* XDP_ATTACHED */ -			  nla_total_size(4);	/* XDP_PROG_ID */ +			  nla_total_size(4) +	/* XDP_PROG_ID (or 1st mode) */ +			  nla_total_size(4);	/* XDP_<mode>_PROG_ID */  	return xdp_size;  } @@ -1014,6 +1015,8 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,  	       + nla_total_size(4)  /* IFLA_IF_NETNSID */  	       + nla_total_size(4)  /* IFLA_CARRIER_UP_COUNT */  	       + nla_total_size(4)  /* IFLA_CARRIER_DOWN_COUNT */ +	       + nla_total_size(4)  /* IFLA_MIN_MTU */ +	       + nla_total_size(4)  /* IFLA_MAX_MTU */  	       + 0;  } @@ -1353,27 +1356,51 @@ static int rtnl_fill_link_ifmap(struct sk_buff *skb, struct net_device *dev)  	return 0;  } -static u8 rtnl_xdp_attached_mode(struct net_device *dev, u32 *prog_id) +static u32 rtnl_xdp_prog_skb(struct net_device *dev)  { -	const struct net_device_ops *ops = dev->netdev_ops;  	const struct bpf_prog *generic_xdp_prog; -	struct netdev_bpf xdp;  	ASSERT_RTNL(); -	*prog_id = 0;  	generic_xdp_prog = rtnl_dereference(dev->xdp_prog); -	if (generic_xdp_prog) { -		*prog_id = generic_xdp_prog->aux->id; -		return XDP_ATTACHED_SKB; -	} -	if (!ops->ndo_bpf) -		return XDP_ATTACHED_NONE; +	if (!generic_xdp_prog) +		return 0; +	return generic_xdp_prog->aux->id; +} + +static u32 rtnl_xdp_prog_drv(struct net_device *dev) +{ +	return __dev_xdp_query(dev, dev->netdev_ops->ndo_bpf, XDP_QUERY_PROG); +} + +static u32 rtnl_xdp_prog_hw(struct net_device *dev) +{ +	return __dev_xdp_query(dev, dev->netdev_ops->ndo_bpf, +			       XDP_QUERY_PROG_HW); +} + +static int rtnl_xdp_report_one(struct sk_buff *skb, struct net_device *dev, +			       u32 *prog_id, u8 *mode, u8 tgt_mode, u32 attr, +			       u32 (*get_prog_id)(struct net_device *dev)) +{ +	u32 curr_id; +	int err; + +	curr_id = get_prog_id(dev); +	if (!curr_id) +		return 0; -	__dev_xdp_query(dev, ops->ndo_bpf, &xdp); -	*prog_id = xdp.prog_id; +	*prog_id = curr_id; +	err = nla_put_u32(skb, attr, curr_id); +	if (err) +		return err; + +	if (*mode != XDP_ATTACHED_NONE) +		*mode = XDP_ATTACHED_MULTI; +	else +		*mode = tgt_mode; -	return xdp.prog_attached; +	return 0;  }  static int rtnl_xdp_fill(struct sk_buff *skb, struct net_device *dev) @@ -1381,17 +1408,32 @@ static int rtnl_xdp_fill(struct sk_buff *skb, struct net_device *dev)  	struct nlattr *xdp;  	u32 prog_id;  	int err; +	u8 mode;  	xdp = nla_nest_start(skb, IFLA_XDP);  	if (!xdp)  		return -EMSGSIZE; -	err = nla_put_u8(skb, IFLA_XDP_ATTACHED, -			 rtnl_xdp_attached_mode(dev, &prog_id)); +	prog_id = 0; +	mode = XDP_ATTACHED_NONE; +	err = rtnl_xdp_report_one(skb, dev, &prog_id, &mode, XDP_ATTACHED_SKB, +				  IFLA_XDP_SKB_PROG_ID, rtnl_xdp_prog_skb); +	if (err) +		goto err_cancel; +	err = rtnl_xdp_report_one(skb, dev, &prog_id, &mode, XDP_ATTACHED_DRV, +				  IFLA_XDP_DRV_PROG_ID, rtnl_xdp_prog_drv); +	if (err) +		goto err_cancel; +	err = rtnl_xdp_report_one(skb, dev, &prog_id, &mode, XDP_ATTACHED_HW, +				  IFLA_XDP_HW_PROG_ID, rtnl_xdp_prog_hw); +	if (err) +		goto err_cancel; + +	err = nla_put_u8(skb, IFLA_XDP_ATTACHED, mode);  	if (err)  		goto err_cancel; -	if (prog_id) { +	if (prog_id && mode != XDP_ATTACHED_MULTI) {  		err = nla_put_u32(skb, IFLA_XDP_PROG_ID, prog_id);  		if (err)  			goto err_cancel; @@ -1561,6 +1603,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,  		       netif_running(dev) ? dev->operstate : IF_OPER_DOWN) ||  	    nla_put_u8(skb, IFLA_LINKMODE, dev->link_mode) ||  	    nla_put_u32(skb, IFLA_MTU, dev->mtu) || +	    nla_put_u32(skb, IFLA_MIN_MTU, dev->min_mtu) || +	    nla_put_u32(skb, IFLA_MAX_MTU, dev->max_mtu) ||  	    nla_put_u32(skb, IFLA_GROUP, dev->group) ||  	    nla_put_u32(skb, IFLA_PROMISCUITY, dev->promiscuity) ||  	    nla_put_u32(skb, IFLA_NUM_TX_QUEUES, dev->num_tx_queues) || @@ -1692,6 +1736,8 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {  	[IFLA_IF_NETNSID]	= { .type = NLA_S32 },  	[IFLA_CARRIER_UP_COUNT]	= { .type = NLA_U32 },  	[IFLA_CARRIER_DOWN_COUNT] = { .type = NLA_U32 }, +	[IFLA_MIN_MTU]		= { .type = NLA_U32 }, +	[IFLA_MAX_MTU]		= { .type = NLA_U32 },  };  static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { @@ -2336,7 +2382,7 @@ static int do_setlink(const struct sk_buff *skb,  	}  	if (tb[IFLA_MTU]) { -		err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU])); +		err = dev_set_mtu_ext(dev, nla_get_u32(tb[IFLA_MTU]), extack);  		if (err < 0)  			goto errout;  		status |= DO_SETLINK_MODIFIED; @@ -2759,9 +2805,12 @@ int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm)  			return err;  	} -	dev->rtnl_link_state = RTNL_LINK_INITIALIZED; - -	__dev_notify_flags(dev, old_flags, ~0U); +	if (dev->rtnl_link_state == RTNL_LINK_INITIALIZED) { +		__dev_notify_flags(dev, old_flags, 0U); +	} else { +		dev->rtnl_link_state = RTNL_LINK_INITIALIZED; +		__dev_notify_flags(dev, old_flags, ~0U); +	}  	return 0;  }  EXPORT_SYMBOL(rtnl_configure_link); |