net/failsafe: support xstats

Add support for extended statistics in failsafe driver.
Reports detailed statistics for each sub device.

Example:

testpmd> show port xstats 1
rx_good_packets: 0
tx_good_packets: 0
rx_good_bytes: 0
tx_good_bytes: 0
rx_missed_errors: 0
rx_errors: 0
tx_errors: 0
rx_mbuf_allocation_errors: 0
rx_q0packets: 0
rx_q0bytes: 0
rx_q0errors: 0
tx_q0packets: 0
tx_q0bytes: 0
rx_sub0_good_packets: 0
tx_sub0_good_packets: 0
...
rx_sub1_good_packets: 0
tx_sub1_good_packets: 0
rx_sub1_good_bytes: 0

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
This commit is contained in:
Stephen Hemminger 2019-11-01 13:12:56 -07:00 committed by Ferruh Yigit
parent bd67b67724
commit 938420ebd1

View File

@ -14,6 +14,7 @@
#include <rte_flow.h>
#include <rte_cycles.h>
#include <rte_ethdev.h>
#include <rte_string_fns.h>
#include "failsafe_private.h"
@ -881,6 +882,154 @@ fs_stats_reset(struct rte_eth_dev *dev)
return 0;
}
static int
__fs_xstats_count(struct rte_eth_dev *dev)
{
struct sub_device *sdev;
int count = 0;
uint8_t i;
int ret;
FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
ret = rte_eth_xstats_get_names(PORT_ID(sdev), NULL, 0);
if (ret < 0)
return ret;
count += ret;
}
return count;
}
static int
__fs_xstats_get_names(struct rte_eth_dev *dev,
struct rte_eth_xstat_name *xstats_names,
unsigned int limit)
{
struct sub_device *sdev;
unsigned int count = 0;
uint8_t i;
/* Caller only cares about count */
if (!xstats_names)
return __fs_xstats_count(dev);
FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
struct rte_eth_xstat_name *sub_names = xstats_names + count;
int j, r;
if (count >= limit)
break;
r = rte_eth_xstats_get_names(PORT_ID(sdev),
sub_names, limit - count);
if (r < 0)
return r;
/* add subN_ prefix to names */
for (j = 0; j < r; j++) {
char *xname = sub_names[j].name;
char tmp[RTE_ETH_XSTATS_NAME_SIZE];
if ((xname[0] == 't' || xname[0] == 'r') &&
xname[1] == 'x' && xname[2] == '_')
snprintf(tmp, sizeof(tmp), "%.3ssub%u_%s",
xname, i, xname + 3);
else
snprintf(tmp, sizeof(tmp), "sub%u_%s",
i, xname);
strlcpy(xname, tmp, RTE_ETH_XSTATS_NAME_SIZE);
}
count += r;
}
return count;
}
static int
fs_xstats_get_names(struct rte_eth_dev *dev,
struct rte_eth_xstat_name *xstats_names,
unsigned int limit)
{
int ret;
fs_lock(dev, 0);
ret = __fs_xstats_get_names(dev, xstats_names, limit);
fs_unlock(dev, 0);
return ret;
}
static int
__fs_xstats_get(struct rte_eth_dev *dev,
struct rte_eth_xstat *xstats,
unsigned int n)
{
unsigned int count = 0;
struct sub_device *sdev;
uint8_t i;
int j, ret;
ret = __fs_xstats_count(dev);
/*
* if error
* or caller did not give enough space
* or just querying
*/
if (ret < 0 || ret > (int)n || xstats == NULL)
return ret;
FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
ret = rte_eth_xstats_get(PORT_ID(sdev), xstats, n);
if (ret < 0)
return ret;
if (ret > (int)n)
return n + count;
/* add offset to id's from sub-device */
for (j = 0; j < ret; j++)
xstats[j].id += count;
xstats += ret;
n -= ret;
count += ret;
}
return count;
}
static int
fs_xstats_get(struct rte_eth_dev *dev,
struct rte_eth_xstat *xstats,
unsigned int n)
{
int ret;
fs_lock(dev, 0);
ret = __fs_xstats_get(dev, xstats, n);
fs_unlock(dev, 0);
return ret;
}
static int
fs_xstats_reset(struct rte_eth_dev *dev)
{
struct sub_device *sdev;
uint8_t i;
int r = 0;
fs_lock(dev, 0);
FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
r = rte_eth_xstats_reset(PORT_ID(sdev));
if (r < 0)
break;
}
fs_unlock(dev, 0);
return r;
}
static void
fs_dev_merge_desc_lim(struct rte_eth_desc_lim *to,
const struct rte_eth_desc_lim *from)
@ -1331,6 +1480,9 @@ const struct eth_dev_ops failsafe_ops = {
.link_update = fs_link_update,
.stats_get = fs_stats_get,
.stats_reset = fs_stats_reset,
.xstats_get = fs_xstats_get,
.xstats_get_names = fs_xstats_get_names,
.xstats_reset = fs_xstats_reset,
.dev_infos_get = fs_dev_infos_get,
.dev_supported_ptypes_get = fs_dev_supported_ptypes_get,
.mtu_set = fs_mtu_set,