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

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
...@@ -826,6 +826,7 @@ enum { ...@@ -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 { ...@@ -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 {
......
...@@ -3577,6 +3577,91 @@ static bool stats_attr_valid(unsigned int mask, int attrid, int idxattr) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment