stats: fix duplicate /if/names entry

stats entries /if/names are never deleted as it is a vector of the
sw_if_index value. When the interface is deleted and then created again
later, and if the new interface takes a different sw_if_index, we may
end up with duplicate entries for the same interface name. For example,
the following configuration sequence causes problem

create loopback interface
create loopback interface
delete loopback interface intfc loop0
delete loopback interface intfc loop1
create loopback interface

vpp_get_stats dump /if/names
[0]: local0 /if/names
[1]: loop0 /if/names
[2]: loop0 /if/names

The fix is to set the delete /if/names entry to deleted when the interface is deleted.

Type: fix

Change-Id: I7d811b12d56e3cf8c7deffe14736ea0f24814d02
Signed-off-by: Steven Luong <sluong@cisco.com>
diff --git a/src/vnet/interface/stats.c b/src/vnet/interface/stats.c
index f58ffa3..cb0eda0 100644
--- a/src/vnet/interface/stats.c
+++ b/src/vnet/interface/stats.c
@@ -25,6 +25,8 @@
 static clib_error_t *
 statseg_sw_interface_add_del (vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
 {
+  u8 *name;
+
   if (if_names == 0)
     {
       if_names = vlib_stats_add_string_vector ("/if/names");
@@ -42,7 +44,6 @@
     {
       vnet_sw_interface_t *si, *si_sup;
       vnet_hw_interface_t *hi_sup;
-      u8 *name;
 
       si = vnet_get_sw_interface (vnm, sw_if_index);
       si_sup = vnet_get_sup_sw_interface (vnm, si->sw_if_index);
@@ -57,22 +58,25 @@
 
       for (u32 index, i = 0; i < ARRAY_LEN (if_counters); i++)
 	{
+	  name = format (0, "%v", hi_sup->name);
 	  index = vlib_stats_add_symlink (
 	    if_counters[i].index, sw_if_index, "/interfaces/%U/%s",
 	    format_vlib_stats_symlink, name, if_counters[i].name);
 	  ASSERT (index != ~0);
 	  vec_add1 (dir_entry_indices[sw_if_index], index);
 	}
-
-      vec_free (name);
     }
   else
     {
+      name = format (0, "%s", "deleted");
+      vlib_stats_set_string_vector (&if_names, sw_if_index, "%v", name);
       for (u32 i = 0; i < vec_len (dir_entry_indices[sw_if_index]); i++)
 	vlib_stats_remove_entry (dir_entry_indices[sw_if_index][i]);
       vec_free (dir_entry_indices[sw_if_index]);
     }
 
+  vec_free (name);
+
   vlib_stats_segment_unlock ();
 
   return 0;