Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 69ae6ad2 authored by Nogah Frankel's avatar Nogah Frankel Committed by David S. Miller
Browse files

net: core: Add offload stats to if_stats_msg



Add a nested attribute of offload stats to if_stats_msg
named IFLA_STATS_LINK_OFFLOAD_XSTATS.
Under it, add SW stats, meaning stats only per packets that went via
slowpath to the cpu, named IFLA_OFFLOAD_XSTATS_CPU_HIT.

Signed-off-by: default avatarNogah Frankel <nogahf@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Acked-by: default avatarNikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2c9d85d4
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -826,6 +826,7 @@ enum {
	IFLA_STATS_LINK_64,
	IFLA_STATS_LINK_64,
	IFLA_STATS_LINK_XSTATS,
	IFLA_STATS_LINK_XSTATS,
	IFLA_STATS_LINK_XSTATS_SLAVE,
	IFLA_STATS_LINK_XSTATS_SLAVE,
	IFLA_STATS_LINK_OFFLOAD_XSTATS,
	__IFLA_STATS_MAX,
	__IFLA_STATS_MAX,
};
};


@@ -845,6 +846,14 @@ enum {
};
};
#define LINK_XSTATS_TYPE_MAX (__LINK_XSTATS_TYPE_MAX - 1)
#define LINK_XSTATS_TYPE_MAX (__LINK_XSTATS_TYPE_MAX - 1)


/* These are stats embedded into IFLA_STATS_LINK_OFFLOAD_XSTATS */
enum {
	IFLA_OFFLOAD_XSTATS_UNSPEC,
	IFLA_OFFLOAD_XSTATS_CPU_HIT, /* struct rtnl_link_stats64 */
	__IFLA_OFFLOAD_XSTATS_MAX
};
#define IFLA_OFFLOAD_XSTATS_MAX (__IFLA_OFFLOAD_XSTATS_MAX - 1)

/* XDP section */
/* XDP section */


enum {
enum {
+107 −4
Original line number Original line Diff line number Diff line
@@ -3577,6 +3577,91 @@ static bool stats_attr_valid(unsigned int mask, int attrid, int idxattr)
	       (!idxattr || idxattr == attrid);
	       (!idxattr || idxattr == attrid);
}
}


#define IFLA_OFFLOAD_XSTATS_FIRST (IFLA_OFFLOAD_XSTATS_UNSPEC + 1)
static int rtnl_get_offload_stats_attr_size(int attr_id)
{
	switch (attr_id) {
	case IFLA_OFFLOAD_XSTATS_CPU_HIT:
		return sizeof(struct rtnl_link_stats64);
	}

	return 0;
}

static int rtnl_get_offload_stats(struct sk_buff *skb, struct net_device *dev,
				  int *prividx)
{
	struct nlattr *attr = NULL;
	int attr_id, size;
	void *attr_data;
	int err;

	if (!(dev->netdev_ops && dev->netdev_ops->ndo_has_offload_stats &&
	      dev->netdev_ops->ndo_get_offload_stats))
		return -ENODATA;

	for (attr_id = IFLA_OFFLOAD_XSTATS_FIRST;
	     attr_id <= IFLA_OFFLOAD_XSTATS_MAX; attr_id++) {
		if (attr_id < *prividx)
			continue;

		size = rtnl_get_offload_stats_attr_size(attr_id);
		if (!size)
			continue;

		if (!dev->netdev_ops->ndo_has_offload_stats(attr_id))
			continue;

		attr = nla_reserve_64bit(skb, attr_id, size,
					 IFLA_OFFLOAD_XSTATS_UNSPEC);
		if (!attr)
			goto nla_put_failure;

		attr_data = nla_data(attr);
		memset(attr_data, 0, size);
		err = dev->netdev_ops->ndo_get_offload_stats(attr_id, dev,
							     attr_data);
		if (err)
			goto get_offload_stats_failure;
	}

	if (!attr)
		return -ENODATA;

	*prividx = 0;
	return 0;

nla_put_failure:
	err = -EMSGSIZE;
get_offload_stats_failure:
	*prividx = attr_id;
	return err;
}

static int rtnl_get_offload_stats_size(const struct net_device *dev)
{
	int nla_size = 0;
	int attr_id;
	int size;

	if (!(dev->netdev_ops && dev->netdev_ops->ndo_has_offload_stats &&
	      dev->netdev_ops->ndo_get_offload_stats))
		return 0;

	for (attr_id = IFLA_OFFLOAD_XSTATS_FIRST;
	     attr_id <= IFLA_OFFLOAD_XSTATS_MAX; attr_id++) {
		if (!dev->netdev_ops->ndo_has_offload_stats(attr_id))
			continue;
		size = rtnl_get_offload_stats_attr_size(attr_id);
		nla_size += nla_total_size_64bit(size);
	}

	if (nla_size != 0)
		nla_size += nla_total_size(0);

	return nla_size;
}

static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
			       int type, u32 pid, u32 seq, u32 change,
			       int type, u32 pid, u32 seq, u32 change,
			       unsigned int flags, unsigned int filter_mask,
			       unsigned int flags, unsigned int filter_mask,
@@ -3586,6 +3671,7 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
	struct nlmsghdr *nlh;
	struct nlmsghdr *nlh;
	struct nlattr *attr;
	struct nlattr *attr;
	int s_prividx = *prividx;
	int s_prividx = *prividx;
	int err;


	ASSERT_RTNL();
	ASSERT_RTNL();


@@ -3614,8 +3700,6 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
		const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
		const struct rtnl_link_ops *ops = dev->rtnl_link_ops;


		if (ops && ops->fill_linkxstats) {
		if (ops && ops->fill_linkxstats) {
			int err;

			*idxattr = IFLA_STATS_LINK_XSTATS;
			*idxattr = IFLA_STATS_LINK_XSTATS;
			attr = nla_nest_start(skb,
			attr = nla_nest_start(skb,
					      IFLA_STATS_LINK_XSTATS);
					      IFLA_STATS_LINK_XSTATS);
@@ -3639,8 +3723,6 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
		if (master)
		if (master)
			ops = master->rtnl_link_ops;
			ops = master->rtnl_link_ops;
		if (ops && ops->fill_linkxstats) {
		if (ops && ops->fill_linkxstats) {
			int err;

			*idxattr = IFLA_STATS_LINK_XSTATS_SLAVE;
			*idxattr = IFLA_STATS_LINK_XSTATS_SLAVE;
			attr = nla_nest_start(skb,
			attr = nla_nest_start(skb,
					      IFLA_STATS_LINK_XSTATS_SLAVE);
					      IFLA_STATS_LINK_XSTATS_SLAVE);
@@ -3655,6 +3737,24 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
		}
		}
	}
	}


	if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_OFFLOAD_XSTATS,
			     *idxattr)) {
		*idxattr = IFLA_STATS_LINK_OFFLOAD_XSTATS;
		attr = nla_nest_start(skb, IFLA_STATS_LINK_OFFLOAD_XSTATS);
		if (!attr)
			goto nla_put_failure;

		err = rtnl_get_offload_stats(skb, dev, prividx);
		if (err == -ENODATA)
			nla_nest_cancel(skb, attr);
		else
			nla_nest_end(skb, attr);

		if (err && err != -ENODATA)
			goto nla_put_failure;
		*idxattr = 0;
	}

	nlmsg_end(skb, nlh);
	nlmsg_end(skb, nlh);


	return 0;
	return 0;
@@ -3708,6 +3808,9 @@ static size_t if_nlmsg_stats_size(const struct net_device *dev,
		}
		}
	}
	}


	if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_OFFLOAD_XSTATS, 0))
		size += rtnl_get_offload_stats_size(dev);

	return size;
	return size;
}
}