stats: add buffer gauges 81/17781/4
authorFilip Tehlar <ftehlar@cisco.com>
Fri, 22 Feb 2019 13:05:53 +0000 (05:05 -0800)
committerDamjan Marion <dmarion@me.com>
Fri, 22 Feb 2019 20:44:21 +0000 (20:44 +0000)
Change-Id: I7f7a459f25d64ea5fa36e30d7dccc667bc19c5a9
Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
src/vlib/buffer.c
src/vlib/main.c
src/vpp/stats/stat_segment.c
src/vpp/stats/stat_segment.h

index c44d8e4..091799b 100644 (file)
@@ -46,6 +46,7 @@
 #include <vppinfra/linux/sysfs.h>
 #include <vlib/vlib.h>
 #include <vlib/unix/unix.h>
+#include <vpp/stats/stat_segment.h>
 
 #define VLIB_BUFFER_DEFAULT_BUFFERS_PER_NUMA 16384
 #define VLIB_BUFFER_DEFAULT_BUFFERS_PER_NUMA_UNPRIV 8192
@@ -709,13 +710,84 @@ vlib_buffer_main_alloc (vlib_main_t * vm)
   bm->default_data_size = VLIB_BUFFER_DEFAULT_DATA_SIZE;
 }
 
+static u32
+buffer_get_cached (vlib_buffer_pool_t * bp)
+{
+  u32 cached = 0;
+  vlib_buffer_pool_thread_t *bpt;
+
+  /* *INDENT-OFF* */
+  vec_foreach (bpt, bp->threads)
+    cached += vec_len (bpt->cached_buffers);
+  /* *INDENT-ON* */
+
+  return cached;
+}
+
+static vlib_buffer_pool_t *
+buffer_get_by_name (vlib_buffer_main_t * bm, char *name)
+{
+  vlib_buffer_pool_t *bp;
+  vec_foreach (bp, bm->buffer_pools)
+  {
+    if (!strcmp ((char *) bp->name, name))
+      return bp;
+  }
+
+  return 0;
+}
+
+static void
+buffer_gauges_update_used_fn (stat_segment_directory_entry_t * e)
+{
+  vlib_main_t *vm = vlib_get_main ();
+  vlib_buffer_pool_t *bp;
+
+  bp = buffer_get_by_name (vm->buffer_main,
+                          &e->name[sizeof ("/buffer/used/") - 1]);
+  if (!bp)
+    return;
+
+  e->value = bp->n_buffers - vec_len (bp->buffers) - buffer_get_cached (bp);
+}
+
+static void
+buffer_gauges_update_available_fn (stat_segment_directory_entry_t * e)
+{
+  vlib_main_t *vm = vlib_get_main ();
+  vlib_buffer_pool_t *bp;
+
+  bp = buffer_get_by_name (vm->buffer_main,
+                          &e->name[sizeof ("/buffer/available/") - 1]);
+  if (!bp)
+    return;
+
+  e->value = vec_len (bp->buffers);
+}
+
+static void
+buffer_gauges_update_cached_fn (stat_segment_directory_entry_t * e)
+{
+  vlib_main_t *vm = vlib_get_main ();
+  vlib_buffer_pool_t *bp;
+
+  bp = buffer_get_by_name (vm->buffer_main,
+                          &e->name[sizeof ("/buffer/cached/") - 1]);
+  if (!bp)
+    return;
+
+  e->value = buffer_get_cached (bp);
+}
+
 clib_error_t *
-vlib_buffer_main_init (struct vlib_main_t *vm)
+vlib_buffer_main_init (struct vlib_main_t * vm)
 {
   vlib_buffer_main_t *bm;
   clib_error_t *err;
   clib_bitmap_t *bmp = 0;
   u32 numa_node;
+  vlib_buffer_pool_t *bp;
+  u8 *name;
 
   vlib_buffer_main_alloc (vm);
 
@@ -743,6 +815,20 @@ vlib_buffer_main_init (struct vlib_main_t *vm)
 
   bm->n_numa_nodes = clib_bitmap_last_set (bmp) + 1;
 
+  vec_foreach (bp, bm->buffer_pools)
+  {
+    name = format (0, "/buffer/cached/%s%c", bp->name, 0);
+    stat_segment_register_gauge (name, buffer_gauges_update_cached_fn);
+    vec_free (name);
+    name = format (0, "/buffer/used/%s%c", bp->name, 0);
+    stat_segment_register_gauge (name, buffer_gauges_update_used_fn);
+    vec_free (name);
+    name = format (0, "/buffer/available/%s%c", bp->name, 0);
+    stat_segment_register_gauge (name, buffer_gauges_update_available_fn);
+    vec_free (name);
+  }
+
+
 done:
   vec_free (bmp);
   return err;
index 89202be..552e693 100644 (file)
@@ -1979,19 +1979,19 @@ vlib_main (vlib_main_t * volatile vm, unformat_input_t * input)
       goto done;
     }
 
-  if ((error = vlib_buffer_main_init (vm)))
+  if ((error = vlib_map_stat_segment_init (vm)))
     {
       clib_error_report (error);
       goto done;
     }
 
-  if ((error = vlib_thread_init (vm)))
+  if ((error = vlib_buffer_main_init (vm)))
     {
       clib_error_report (error);
       goto done;
     }
 
-  if ((error = vlib_map_stat_segment_init (vm)))
+  if ((error = vlib_thread_init (vm)))
     {
       clib_error_report (error);
       goto done;
index 793936b..2d6c8c6 100644 (file)
@@ -214,15 +214,8 @@ vlib_map_stat_segment_init (void)
   stat_segment_main_t *sm = &stat_segment_main;
   stat_segment_shared_header_t *shared_header;
   stat_segment_directory_entry_t *ep;
-
-  f64 *scalar_data;
-  u8 *name;
   void *oldheap;
-  u32 *lock;
-  int rv;
   ssize_t memory_size;
-
-
   int mfd;
   char *mem_name = "stat_segment_test";
   void *memaddr;
@@ -282,6 +275,7 @@ vlib_map_stat_segment_init (void)
     /* Save the vector offset in the shared segment, for clients */
     shared_header->directory_offset =
     stat_segment_offset (shared_header, sm->directory_vector);
+  sm->gauges_fns = 0;
 
   clib_mem_set_heap (oldheap);
 
@@ -514,6 +508,12 @@ do_stat_segment_updates (stat_segment_main_t * sm)
   if (sm->node_counters_enabled)
     update_node_counters (sm);
 
+  for (i = 0; i < vec_len (sm->gauges_fns); i++)
+    {
+      if (sm->gauges_fns[i])
+       sm->gauges_fns[i] (&sm->directory_vector[i]);
+    }
+
   /* Heartbeat, so clients detect we're still here */
   sm->directory_vector[STAT_COUNTER_HEARTBEAT].value++;
 }
@@ -618,6 +618,39 @@ statseg_init (vlib_main_t * vm)
   return 0;
 }
 
+clib_error_t *
+stat_segment_register_gauge (u8 * name, stat_segment_update_fn update_fn)
+{
+  stat_segment_main_t *sm = &stat_segment_main;
+  stat_segment_shared_header_t *shared_header = sm->shared_header;
+  void *oldheap;
+  stat_segment_directory_entry_t e;
+  u32 index;
+
+  ASSERT (shared_header);
+
+  oldheap = vlib_stats_push_heap ();
+  vlib_stat_segment_lock ();
+
+  memset (&e, 0, sizeof (e));
+  e.type = STAT_DIR_TYPE_SCALAR_INDEX;
+
+  memcpy (e.name, name, vec_len (name));
+  index = vec_len (sm->directory_vector);
+  vec_add1 (sm->directory_vector, e);
+
+  shared_header->directory_offset =
+    stat_segment_offset (shared_header, sm->directory_vector);
+
+  vlib_stat_segment_unlock ();
+  clib_mem_set_heap (oldheap);
+
+  vec_validate (sm->gauges_fns, index);
+  sm->gauges_fns[index] = update_fn;
+
+  return NULL;
+}
+
 static clib_error_t *
 statseg_config (vlib_main_t * vm, unformat_input_t * input)
 {
index 3ce8280..f3ea50c 100644 (file)
@@ -85,8 +85,13 @@ stat_segment_pointer (void *start, uint64_t offset)
   return ((char *) start + offset);
 }
 
+typedef void (*stat_segment_update_fn)(stat_segment_directory_entry_t * e);
+
 typedef struct
 {
+  /* internal, does not point to shared memory */
+  stat_segment_update_fn *gauges_fns;
+
   /* statistics segment */
   uword *directory_vector_by_name;
   stat_segment_directory_entry_t *directory_vector;
@@ -104,4 +109,7 @@ typedef struct
 
 extern stat_segment_main_t stat_segment_main;
 
+clib_error_t *
+stat_segment_register_gauge (u8 *names, stat_segment_update_fn update_fn);
+
 #endif