Add API to get the dpdk interface stats delta.

Internally change the clearing and displaying of the dpdk stats to be
based on deltas.

Change-Id: I76605ac67492a374ff5522ff44d4a0190cf94e18
Signed-off-by: Todd Foggoa (tfoggoa) <tfoggoa@cisco.com>
This commit is contained in:
Sean Hope
2016-03-28 13:11:31 -04:00
committed by Damjan Marion
parent fef15b4bb8
commit a4f16a0e57
4 changed files with 85 additions and 22 deletions

View File

@ -835,17 +835,27 @@ static void dpdk_clear_hw_interface_counters (u32 instance)
*/ */
if (xd->admin_up != 0xff) if (xd->admin_up != 0xff)
{ {
rte_eth_stats_reset (xd->device_index); /*
memset (&xd->last_stats, 0, sizeof (xd->last_stats)); * Set the "last_cleared_stats" to the current stats, so that
* things appear to clear from a display perspective.
*/
dpdk_update_counters (xd, vlib_time_now (dm->vlib_main)); dpdk_update_counters (xd, vlib_time_now (dm->vlib_main));
memcpy (&xd->last_cleared_stats, &xd->stats, sizeof(xd->stats));
memcpy (xd->last_cleared_xstats, xd->xstats,
vec_len(xd->last_cleared_xstats) *
sizeof(xd->last_cleared_xstats[0]));
} }
else else
{ {
rte_eth_stats_reset (xd->device_index); /*
memset(&xd->stats, 0, sizeof(xd->stats)); * Internally rte_eth_xstats_reset() is calling rte_eth_stats_reset(),
* so we're only calling xstats_reset() here.
*/
rte_eth_xstats_reset (xd->device_index);
memset (&xd->stats, 0, sizeof(xd->stats));
memset (&xd->last_stats, 0, sizeof (xd->last_stats)); memset (&xd->last_stats, 0, sizeof (xd->last_stats));
} }
rte_eth_xstats_reset(xd->device_index);
if (PREDICT_FALSE(xd->dev_type == VNET_DPDK_DEV_VHOST_USER)) { if (PREDICT_FALSE(xd->dev_type == VNET_DPDK_DEV_VHOST_USER)) {
int i; int i;
@ -1225,3 +1235,27 @@ int rte_delay_us_override (unsigned us) {
} }
return 0; // no override return 0; // no override
} }
/*
* Return a copy of the DPDK port stats in dest.
*/
clib_error_t*
dpdk_get_hw_interface_stats (u32 hw_if_index, struct rte_eth_stats* dest)
{
dpdk_main_t * dm = &dpdk_main;
vnet_main_t * vnm = vnet_get_main();
vnet_hw_interface_t * hi = vnet_get_hw_interface (vnm, hw_if_index);
dpdk_device_t * xd = vec_elt_at_index (dm->devices, hi->dev_instance);
if (!dest) {
return clib_error_return (0, "Missing or NULL argument");
}
if (!xd) {
return clib_error_return (0, "Unable to get DPDK device from HW interface");
}
dpdk_update_counters (xd, vlib_time_now (dm->vlib_main));
memcpy(dest, &xd->stats, sizeof(xd->stats));
return (0);
}

View File

@ -245,7 +245,9 @@ typedef struct {
struct rte_eth_stats stats; struct rte_eth_stats stats;
struct rte_eth_stats last_stats; struct rte_eth_stats last_stats;
struct rte_eth_stats last_cleared_stats;
struct rte_eth_xstats * xstats; struct rte_eth_xstats * xstats;
struct rte_eth_xstats * last_cleared_xstats;
f64 time_last_stats_update; f64 time_last_stats_update;
dpdk_port_type_t port_type; dpdk_port_type_t port_type;
@ -567,6 +569,9 @@ u32 dpdk_get_admin_up_down_in_progress (void);
uword uword
dpdk_input_rss (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * f); dpdk_input_rss (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * f);
clib_error_t*
dpdk_get_hw_interface_stats (u32 hw_if_index, struct rte_eth_stats* dest);
format_function_t format_dpdk_device_name; format_function_t format_dpdk_device_name;
format_function_t format_dpdk_device; format_function_t format_dpdk_device;
format_function_t format_dpdk_tx_dma_trace; format_function_t format_dpdk_tx_dma_trace;

View File

@ -141,6 +141,27 @@ dpdk_rx_burst ( dpdk_main_t * dm, dpdk_device_t * xd, u16 queue_id)
} }
static inline void
dpdk_get_xstats (dpdk_device_t * xd)
{
int len;
if ((len = rte_eth_xstats_get(xd->device_index, NULL, 0)) > 0)
{
vec_validate(xd->xstats, len - 1);
vec_validate(xd->last_cleared_xstats, len - 1);
len = rte_eth_xstats_get(xd->device_index, xd->xstats, vec_len(xd->xstats));
ASSERT(vec_len(xd->xstats) == len);
ASSERT(vec_len(xd->last_cleared_xstats) == len);
_vec_len(xd->xstats) = len;
_vec_len(xd->last_cleared_xstats) = len;
}
}
static inline void static inline void
dpdk_update_counters (dpdk_device_t * xd, f64 now) dpdk_update_counters (dpdk_device_t * xd, f64 now)
{ {
@ -148,7 +169,6 @@ dpdk_update_counters (dpdk_device_t * xd, f64 now)
vnet_main_t * vnm = vnet_get_main(); vnet_main_t * vnm = vnet_get_main();
u32 my_cpu = os_get_cpu_number(); u32 my_cpu = os_get_cpu_number();
u64 rxerrors, last_rxerrors; u64 rxerrors, last_rxerrors;
int len;
/* only update counters for PMD interfaces */ /* only update counters for PMD interfaces */
if (xd->dev_type != VNET_DPDK_DEV_ETH) if (xd->dev_type != VNET_DPDK_DEV_ETH)
@ -207,11 +227,5 @@ dpdk_update_counters (dpdk_device_t * xd, f64 now)
} }
} }
if ((len = rte_eth_xstats_get(xd->device_index, NULL, 0)) > 0) dpdk_get_xstats(xd);
{
vec_validate(xd->xstats, len - 1);
len = rte_eth_xstats_get(xd->device_index, xd->xstats, vec_len(xd->xstats));
ASSERT(vec_len(xd->xstats) == len);
_vec_len(xd->xstats) = len;
}
} }

View File

@ -529,27 +529,37 @@ u8 * format_dpdk_device (u8 * s, va_list * args)
{ {
#define _(N, V) \ #define _(N, V) \
if (xd->stats.V != 0) \ if ((xd->stats.V - xd->last_cleared_stats.V) != 0) { \
s = format (s, "\n%U%-40U%16Ld", \ s = format (s, "\n%U%-40U%16Ld", \
format_white_space, indent + 2, \ format_white_space, indent + 2, \
format_c_identifier, #N, xd->stats.V); format_c_identifier, #N, \
xd->stats.V - xd->last_cleared_stats.V); \
} \
foreach_dpdk_counter foreach_dpdk_counter
#undef _ #undef _
} }
u8 * xs = 0; u8 * xs = 0;
struct rte_eth_xstats * xstat; u32 i = 0;
vec_foreach(xstat, xd->xstats) ASSERT(vec_len(xd->xstats) == vec_len(xd->last_cleared_xstats));
vec_foreach_index(i, xd->xstats)
{ {
if (verbose == 2 || (verbose && xstat->value)) u64 delta = 0;
struct rte_eth_xstats* xstat = vec_elt_at_index(xd->xstats, i);
struct rte_eth_xstats* last_xstat =
vec_elt_at_index(xd->last_cleared_xstats, i);
delta = xstat->value - last_xstat->value;
if (verbose == 2 || (verbose && delta))
{ {
/* format_c_identifier don't like c strings inside vector */ /* format_c_identifier doesn't like c strings inside vector */
u8 * name = format(0,"%s", xstat->name); u8 * name = format(0,"%s", xstat->name);
xs = format(xs, "\n%U%-38U%16Ld", xs = format(xs, "\n%U%-38U%16Ld",
format_white_space, indent + 4, format_white_space, indent + 4,
format_c_identifier, name, xstat->value); format_c_identifier, name, delta);
vec_free(name); vec_free(name);
} }
} }