Add API to get the dpdk interface stats delta. 23/623/3
authorSean Hope <shope@cisco.com>
Mon, 28 Mar 2016 17:11:31 +0000 (13:11 -0400)
committerDamjan Marion <damarion@cisco.com>
Mon, 18 Apr 2016 14:26:48 +0000 (14:26 +0000)
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>
vnet/vnet/devices/dpdk/device.c
vnet/vnet/devices/dpdk/dpdk.h
vnet/vnet/devices/dpdk/dpdk_priv.h
vnet/vnet/devices/dpdk/format.c

index 748fb82..7821ebe 100644 (file)
@@ -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);
+}
index e2bb1e2..bfe2279 100644 (file)
@@ -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;
index a0fa38a..54d3803 100644 (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
 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();
   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);
 }
index 447dfff..9c015d0 100644 (file)
@@ -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);
         }
     }