Add a debug-CLI leak-checker 90/19690/4
authorDave Barach <dave@barachs.net>
Fri, 17 May 2019 14:46:40 +0000 (10:46 -0400)
committerDave Wallace <dwallacelf@gmail.com>
Fri, 17 May 2019 21:06:13 +0000 (21:06 +0000)
leak-check { <any-debug-cli-command-and-args> }

Hint: "set term history off" or you'll have to sort through a bunch of
bogus leaks related to the debug cli history mechanism.

Cleaned up a set of reported leaks in the "show interface" command. At
some point, we thought about making a per-thread vlib_mains vector,
but we never did that. Several interface-related CLI's maintained
local static cache vectors. Not a bad idea, but not useful as things
shook out. Removed the static vectors.

Change-Id: I756bf2721a0d91993ecfded34c79da406f30a548
Signed-off-by: Dave Barach <dave@barachs.net>
src/vlib/cli.c
src/vnet/interface_api.c
src/vnet/interface_cli.c
src/vnet/interface_format.c
src/vnet/misc.c
src/vnet/vnet.h
src/vppinfra/mem.h

index 835cb87..6d83e2a 100644 (file)
@@ -552,6 +552,31 @@ vlib_cli_dispatch_sub_commands (vlib_main_t * vm,
                                        parent_command_index);
       unformat_free (&sub_input);
     }
+  else if (unformat (input, "leak-check %U",
+                    unformat_vlib_cli_sub_input, &sub_input))
+    {
+      u8 *leak_report;
+      clib_mem_trace (1);
+      error =
+       vlib_cli_dispatch_sub_commands (vm, cm, &sub_input,
+                                       parent_command_index);
+      unformat_free (&sub_input);
+
+      /* Otherwise, the clib_error_t shows up as a leak... */
+      if (error)
+       {
+         vlib_cli_output (vm, "%v", error->what);
+         clib_error_free (error);
+         error = 0;
+       }
+
+      (void) clib_mem_trace_enable_disable (0);
+      leak_report = format (0, "%U", format_mheap, clib_mem_get_heap (),
+                           1 /* verbose, i.e. print leaks */ );
+      clib_mem_trace (0);
+      vlib_cli_output (vm, "%v", leak_report);
+      vec_free (leak_report);
+    }
 
   else
     if (unformat_user (input, unformat_vlib_cli_sub_command, vm, parent, &c))
index 58035fb..1b91382 100644 (file)
@@ -661,52 +661,34 @@ vl_api_sw_interface_clear_stats_t_handler (vl_api_sw_interface_clear_stats_t *
   vnet_interface_main_t *im = &vnm->interface_main;
   vlib_simple_counter_main_t *sm;
   vlib_combined_counter_main_t *cm;
-  static vnet_main_t **my_vnet_mains;
-  int i, j, n_counters;
+  int j, n_counters;
   int rv = 0;
 
   if (mp->sw_if_index != ~0)
     VALIDATE_SW_IF_INDEX (mp);
 
-  vec_reset_length (my_vnet_mains);
-
-  for (i = 0; i < vec_len (vnet_mains); i++)
-    {
-      if (vnet_mains[i])
-       vec_add1 (my_vnet_mains, vnet_mains[i]);
-    }
-
-  if (vec_len (vnet_mains) == 0)
-    vec_add1 (my_vnet_mains, vnm);
-
   n_counters = vec_len (im->combined_sw_if_counters);
 
   for (j = 0; j < n_counters; j++)
     {
-      for (i = 0; i < vec_len (my_vnet_mains); i++)
-       {
-         im = &my_vnet_mains[i]->interface_main;
-         cm = im->combined_sw_if_counters + j;
-         if (mp->sw_if_index == (u32) ~ 0)
-           vlib_clear_combined_counters (cm);
-         else
-           vlib_zero_combined_counter (cm, ntohl (mp->sw_if_index));
-       }
+      im = &vnm->interface_main;
+      cm = im->combined_sw_if_counters + j;
+      if (mp->sw_if_index == (u32) ~ 0)
+       vlib_clear_combined_counters (cm);
+      else
+       vlib_zero_combined_counter (cm, ntohl (mp->sw_if_index));
     }
 
   n_counters = vec_len (im->sw_if_counters);
 
   for (j = 0; j < n_counters; j++)
     {
-      for (i = 0; i < vec_len (my_vnet_mains); i++)
-       {
-         im = &my_vnet_mains[i]->interface_main;
-         sm = im->sw_if_counters + j;
-         if (mp->sw_if_index == (u32) ~ 0)
-           vlib_clear_simple_counters (sm);
-         else
-           vlib_zero_simple_counter (sm, ntohl (mp->sw_if_index));
-       }
+      im = &vnm->interface_main;
+      sm = im->sw_if_counters + j;
+      if (mp->sw_if_index == (u32) ~ 0)
+       vlib_clear_simple_counters (sm);
+      else
+       vlib_zero_simple_counter (sm, ntohl (mp->sw_if_index));
     }
 
   BAD_SW_IF_INDEX_LABEL;
index 624f8ef..f990cde 100644 (file)
@@ -304,6 +304,7 @@ show_sw_interfaces (vlib_main_t * vm,
            verbose = 1;
          else
            {
+             vec_free (sorted_sis);
              error = clib_error_return (0, "unknown input `%U'",
                                         format_unformat_error, linput);
              goto done;
@@ -314,7 +315,10 @@ show_sw_interfaces (vlib_main_t * vm,
   if (show_features || show_tag)
     {
       if (sw_if_index == ~(u32) 0)
-       return clib_error_return (0, "Interface not specified...");
+       {
+         vec_free (sorted_sis);
+         return clib_error_return (0, "Interface not specified...");
+       }
     }
 
   if (show_features)
@@ -335,6 +339,7 @@ show_sw_interfaces (vlib_main_t * vm,
        vlib_cli_output (vm, "%10s (%s)", "VTR", "--internal--");
       vlib_cli_output (vm, "%U", format_l2_output_features,
                       l2_output->feature_bitmap, 1);
+      vec_free (sorted_sis);
       return 0;
     }
   if (show_tag)
@@ -344,6 +349,7 @@ show_sw_interfaces (vlib_main_t * vm,
       vlib_cli_output (vm, "%U: %s",
                       format_vnet_sw_if_index_name, vnm, sw_if_index,
                       tag ? (char *) tag : "(none)");
+      vec_free (sorted_sis);
       return 0;
     }
 
@@ -497,42 +503,24 @@ clear_interface_counters (vlib_main_t * vm,
   vnet_interface_main_t *im = &vnm->interface_main;
   vlib_simple_counter_main_t *sm;
   vlib_combined_counter_main_t *cm;
-  static vnet_main_t **my_vnet_mains;
-  int i, j, n_counters;
-
-  vec_reset_length (my_vnet_mains);
-
-  for (i = 0; i < vec_len (vnet_mains); i++)
-    {
-      if (vnet_mains[i])
-       vec_add1 (my_vnet_mains, vnet_mains[i]);
-    }
-
-  if (vec_len (vnet_mains) == 0)
-    vec_add1 (my_vnet_mains, vnm);
+  int j, n_counters;
 
   n_counters = vec_len (im->combined_sw_if_counters);
 
   for (j = 0; j < n_counters; j++)
     {
-      for (i = 0; i < vec_len (my_vnet_mains); i++)
-       {
-         im = &my_vnet_mains[i]->interface_main;
-         cm = im->combined_sw_if_counters + j;
-         vlib_clear_combined_counters (cm);
-       }
+      im = &vnm->interface_main;
+      cm = im->combined_sw_if_counters + j;
+      vlib_clear_combined_counters (cm);
     }
 
   n_counters = vec_len (im->sw_if_counters);
 
   for (j = 0; j < n_counters; j++)
     {
-      for (i = 0; i < vec_len (my_vnet_mains); i++)
-       {
-         im = &my_vnet_mains[i]->interface_main;
-         sm = im->sw_if_counters + j;
-         vlib_clear_simple_counters (sm);
-       }
+      im = &vnm->interface_main;
+      sm = im->sw_if_counters + j;
+      vlib_clear_simple_counters (sm);
     }
 
   return 0;
index ee332f3..e25a05a 100644 (file)
@@ -219,66 +219,46 @@ format_vnet_sw_interface_cntrs (u8 * s, vnet_interface_main_t * im,
                                vnet_sw_interface_t * si)
 {
   u32 indent, n_printed;
-  int i, j, n_counters;
-  static vnet_main_t **my_vnet_mains;
-
-  vec_reset_length (my_vnet_mains);
+  int j, n_counters;
+  u8 *n = 0;
 
   indent = format_get_indent (s);
   n_printed = 0;
 
-  {
-    vlib_combined_counter_main_t *cm;
-    vlib_counter_t v, vtotal;
-    u8 *n = 0;
-
-    for (i = 0; i < vec_len (vnet_mains); i++)
-      {
-       if (vnet_mains[i])
-         vec_add1 (my_vnet_mains, vnet_mains[i]);
-      }
+  n_counters = vec_len (im->combined_sw_if_counters);
 
-    if (vec_len (my_vnet_mains) == 0)
-      vec_add1 (my_vnet_mains, &vnet_main);
-
-    /* Each vnet_main_t has its own copy of the interface counters */
-    n_counters = vec_len (im->combined_sw_if_counters);
-
-    /* rx, tx counters... */
-    for (j = 0; j < n_counters; j++)
-      {
-       vtotal.packets = 0;
-       vtotal.bytes = 0;
-
-       for (i = 0; i < vec_len (my_vnet_mains); i++)
-         {
-           im = &my_vnet_mains[i]->interface_main;
-           cm = im->combined_sw_if_counters + j;
-           vlib_get_combined_counter (cm, si->sw_if_index, &v);
-           vtotal.packets += v.packets;
-           vtotal.bytes += v.bytes;
-         }
+  /* rx, tx counters... */
+  for (j = 0; j < n_counters; j++)
+    {
+      vlib_combined_counter_main_t *cm;
+      vlib_counter_t v, vtotal;
+      vtotal.packets = 0;
+      vtotal.bytes = 0;
 
-       /* Only display non-zero counters. */
-       if (vtotal.packets == 0)
-         continue;
+      cm = im->combined_sw_if_counters + j;
+      vlib_get_combined_counter (cm, si->sw_if_index, &v);
+      vtotal.packets += v.packets;
+      vtotal.bytes += v.bytes;
 
-       if (n_printed > 0)
-         s = format (s, "\n%U", format_white_space, indent);
-       n_printed += 2;
+      /* Only display non-zero counters. */
+      if (vtotal.packets == 0)
+       continue;
 
-       if (n)
-         _vec_len (n) = 0;
-       n = format (n, "%s packets", cm->name);
-       s = format (s, "%-16v%16Ld", n, vtotal.packets);
+      if (n_printed > 0)
+       s = format (s, "\n%U", format_white_space, indent);
+      n_printed += 2;
 
+      if (n)
        _vec_len (n) = 0;
-       n = format (n, "%s bytes", cm->name);
-       s = format (s, "\n%U%-16v%16Ld",
-                   format_white_space, indent, n, vtotal.bytes);
-      }
-    vec_free (n);
-  }
+      n = format (n, "%s packets", cm->name);
+      s = format (s, "%-16v%16Ld", n, vtotal.packets);
+
+      _vec_len (n) = 0;
+      n = format (n, "%s bytes", cm->name);
+      s = format (s, "\n%U%-16v%16Ld",
+                 format_white_space, indent, n, vtotal.bytes);
+    }
+  vec_free (n);
 
   {
     vlib_simple_counter_main_t *cm;
@@ -290,14 +270,10 @@ format_vnet_sw_interface_cntrs (u8 * s, vnet_interface_main_t * im,
       {
        vtotal = 0;
 
-       for (i = 0; i < vec_len (my_vnet_mains); i++)
-         {
-           im = &my_vnet_mains[i]->interface_main;
-           cm = im->sw_if_counters + j;
+       cm = im->sw_if_counters + j;
 
-           v = vlib_get_simple_counter (cm, si->sw_if_index);
-           vtotal += v;
-         }
+       v = vlib_get_simple_counter (cm, si->sw_if_index);
+       vtotal += v;
 
        /* Only display non-zero counters. */
        if (vtotal == 0)
index ab0f823..cd8bd78 100644 (file)
@@ -41,7 +41,6 @@
 #include <vnet/ip/ip.h>
 
 vnet_main_t vnet_main;
-vnet_main_t **vnet_mains;
 
 vnet_main_t *
 vnet_get_main (void)
index 9b2a878..3b20f71 100644 (file)
@@ -81,7 +81,6 @@ typedef struct vnet_main_t
 } vnet_main_t;
 
 extern vnet_main_t vnet_main;
-extern vnet_main_t **vnet_mains;
 
 #include <vnet/interface_funcs.h>
 #include <vnet/global_funcs.h>
index 65b25f0..1e14698 100644 (file)
@@ -406,6 +406,8 @@ typedef struct
 clib_error_t *clib_mem_vm_ext_map (clib_mem_vm_map_t * a);
 void clib_mem_vm_randomize_va (uword * requested_va, u32 log2_page_size);
 void mheap_trace (void *v, int enable);
+uword clib_mem_trace_enable_disable (uword enable);
+void clib_mem_trace (int enable);
 
 #include <vppinfra/error.h>    /* clib_panic */