summaryrefslogtreecommitdiffstats
path: root/vnet
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 /vnet
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>
Diffstat (limited to 'vnet')
-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);
}
}