summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Hope <shope@cisco.com>2016-03-28 13:11:31 -0400
committerDamjan Marion <damarion@cisco.com>2016-04-18 14:26:48 +0000
commita4f16a0e570e663bdf6285b0ac5c4258fcd9ffd3 (patch)
tree4b9386c4c483ffbec77579a559c44f90cd61d925
parentfef15b4bb88c61248393b93d13b1f79bb628def0 (diff)
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>
-rw-r--r--vnet/vnet/devices/dpdk/device.c44
-rw-r--r--vnet/vnet/devices/dpdk/dpdk.h5
-rw-r--r--vnet/vnet/devices/dpdk/dpdk_priv.h30
-rw-r--r--vnet/vnet/devices/dpdk/format.c28
4 files changed, 85 insertions, 22 deletions
diff --git a/vnet/vnet/devices/dpdk/device.c b/vnet/vnet/devices/dpdk/device.c
index 748fb829115..7821ebeb7c2 100644
--- a/vnet/vnet/devices/dpdk/device.c
+++ b/vnet/vnet/devices/dpdk/device.c
@@ -835,17 +835,27 @@ static void dpdk_clear_hw_interface_counters (u32 instance)
*/
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));
+
+ 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
{
- 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));
}
- rte_eth_xstats_reset(xd->device_index);
if (PREDICT_FALSE(xd->dev_type == VNET_DPDK_DEV_VHOST_USER)) {
int i;
@@ -1225,3 +1235,27 @@ int rte_delay_us_override (unsigned us) {
}
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);
+}
diff --git a/vnet/vnet/devices/dpdk/dpdk.h b/vnet/vnet/devices/dpdk/dpdk.h
index e2bb1e2a107..bfe22795e0f 100644
--- a/vnet/vnet/devices/dpdk/dpdk.h
+++ b/vnet/vnet/devices/dpdk/dpdk.h
@@ -245,7 +245,9 @@ typedef struct {
struct rte_eth_stats stats;
struct rte_eth_stats last_stats;
+ struct rte_eth_stats last_cleared_stats;
struct rte_eth_xstats * xstats;
+ struct rte_eth_xstats * last_cleared_xstats;
f64 time_last_stats_update;
dpdk_port_type_t port_type;
@@ -567,6 +569,9 @@ u32 dpdk_get_admin_up_down_in_progress (void);
uword
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;
format_function_t format_dpdk_tx_dma_trace;
diff --git a/vnet/vnet/devices/dpdk/dpdk_priv.h b/vnet/vnet/devices/dpdk/dpdk_priv.h
index a0fa38a4712..54d3803058d 100644
--- a/vnet/vnet/devices/dpdk/dpdk_priv.h
+++ b/vnet/vnet/devices/dpdk/dpdk_priv.h
@@ -142,13 +142,33 @@ 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
dpdk_update_counters (dpdk_device_t * xd, f64 now)
{
vlib_simple_counter_main_t * cm;
vnet_main_t * vnm = vnet_get_main();
u32 my_cpu = os_get_cpu_number();
u64 rxerrors, last_rxerrors;
- int len;
/* only update counters for PMD interfaces */
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)
- {
- 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;
- }
+ dpdk_get_xstats(xd);
}
diff --git a/vnet/vnet/devices/dpdk/format.c b/vnet/vnet/devices/dpdk/format.c
index 447dfffb1b6..9c015d06272 100644
--- a/vnet/vnet/devices/dpdk/format.c
+++ b/vnet/vnet/devices/dpdk/format.c
@@ -529,27 +529,37 @@ u8 * format_dpdk_device (u8 * s, va_list * args)
{
#define _(N, V) \
- if (xd->stats.V != 0) \
- s = format (s, "\n%U%-40U%16Ld", \
- format_white_space, indent + 2, \
- format_c_identifier, #N, xd->stats.V);
+ if ((xd->stats.V - xd->last_cleared_stats.V) != 0) { \
+ s = format (s, "\n%U%-40U%16Ld", \
+ format_white_space, indent + 2, \
+ format_c_identifier, #N, \
+ xd->stats.V - xd->last_cleared_stats.V); \
+ } \
foreach_dpdk_counter
#undef _
}
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);
xs = format(xs, "\n%U%-38U%16Ld",
format_white_space, indent + 4,
- format_c_identifier, name, xstat->value);
+ format_c_identifier, name, delta);
vec_free(name);
}
}