LISP: make statistics thread safe 89/6089/7
authorFilip Tehlar <ftehlar@cisco.com>
Fri, 7 Apr 2017 08:41:42 +0000 (10:41 +0200)
committerFlorin Coras <florin.coras@gmail.com>
Thu, 13 Apr 2017 08:43:06 +0000 (08:43 +0000)
Change-Id: I056dc6246f79d887d69ad459a6b8b3092a099baa
Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
src/vat/api_format.c
src/vnet/lisp-cp/control.c
src/vnet/lisp-cp/one.api
src/vnet/lisp-cp/one_api.c
src/vnet/lisp-cp/one_cli.c
src/vnet/lisp-gpe/lisp_gpe.c
src/vnet/lisp-gpe/lisp_gpe.h
src/vnet/lisp-gpe/lisp_gpe_adjacency.c
src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c
src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h

index 107aa01..bf4a73a 100644 (file)
@@ -4238,6 +4238,7 @@ _(one_add_del_map_request_itr_rlocs_reply)              \
 _(one_eid_table_add_del_map_reply)                      \
 _(one_use_petr_reply)                                   \
 _(one_stats_enable_disable_reply)                       \
+_(one_stats_flush_reply)                                \
 _(gpe_add_del_fwd_entry_reply)                          \
 _(gpe_enable_disable_reply)                             \
 _(gpe_set_encap_mode_reply)                             \
@@ -4465,6 +4466,7 @@ _(ONE_MAP_RESOLVER_DETAILS, one_map_resolver_details)                   \
 _(ONE_MAP_SERVER_DETAILS, one_map_server_details)                       \
 _(ONE_ADJACENCIES_GET_REPLY, one_adjacencies_get_reply)                 \
 _(ONE_STATS_DETAILS, one_stats_details)                                 \
+_(ONE_STATS_FLUSH_REPLY, one_stats_flush_reply)                         \
 _(ONE_STATS_ENABLE_DISABLE_REPLY, one_stats_enable_disable_reply)       \
 _(SHOW_ONE_STATS_ENABLE_DISABLE_REPLY,                                  \
   show_one_stats_enable_disable_reply)                                  \
@@ -15855,6 +15857,18 @@ api_one_map_resolver_dump (vat_main_t * vam)
 
 #define api_lisp_map_resolver_dump api_one_map_resolver_dump
 
+static int
+api_one_stats_flush (vat_main_t * vam)
+{
+  vl_api_one_stats_flush_t *mp;
+  int ret = 0;
+
+  M (ONE_STATS_FLUSH, mp);
+  S (mp);
+  W (ret);
+  return ret;
+}
+
 static int
 api_one_stats_dump (vat_main_t * vam)
 {
@@ -18880,6 +18894,7 @@ _(show_one_rloc_probe_state, "")                                        \
 _(show_one_map_register_state, "")                                      \
 _(show_one_status, "")                                                  \
 _(one_stats_dump, "")                                                   \
+_(one_stats_flush, "")                                                  \
 _(one_get_map_request_itr_rlocs, "")                                    \
 _(show_one_pitr, "")                                                    \
 _(show_one_use_petr, "")                                                \
index 5c901f3..ebbd1be 100644 (file)
@@ -285,7 +285,7 @@ dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
   if (fe->is_src_dst)
     gid_address_copy (&a->lcl_eid, &fe->leid);
 
-  vnet_lisp_del_fwd_stats (a, feip[0]);
+  vnet_lisp_gpe_del_fwd_counters (a, feip[0]);
   vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
 
   /* delete entry in fwd table */
@@ -532,10 +532,18 @@ dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
       a->action = rmt_map->action;
     }
 
-  vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
+  rv = vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
+  if (rv)
+    {
+      if (a->locator_pairs)
+       vec_free (a->locator_pairs);
+      return;
+    }
 
-  /* add tunnel to fwd entry table XXX check return value from DP insertion */
+  /* add tunnel to fwd entry table */
   pool_get (lcm->fwd_entry_pool, fe);
+  vnet_lisp_gpe_add_fwd_counters (a, fe - lcm->fwd_entry_pool);
+
   fe->locator_pairs = a->locator_pairs;
   gid_address_copy (&fe->reid, &a->rmt_eid);
 
@@ -3608,7 +3616,8 @@ lisp_stats_api_fill (lisp_cp_main_t * lcm, lisp_gpe_main_t * lgm,
                     lisp_api_stats_t * stat, lisp_stats_key_t * key,
                     u32 stats_index)
 {
-  lisp_stats_t *s;
+  vlib_counter_t v;
+  vlib_combined_counter_main_t *cm = &lgm->counters;
   lisp_gpe_fwd_entry_key_t fwd_key;
   const lisp_gpe_tunnel_t *lgt;
   fwd_entry_t *fe;
@@ -3627,8 +3636,8 @@ lisp_stats_api_fill (lisp_cp_main_t * lcm, lisp_gpe_main_t * lgm,
   stat->loc_rloc = lgt->key->lcl;
   stat->rmt_rloc = lgt->key->rmt;
 
-  s = pool_elt_at_index (lgm->lisp_stats_pool, stats_index);
-  stat->stats = *s;
+  vlib_get_combined_counter (cm, stats_index, &v);
+  stat->counters = v;
   return 1;
 }
 
index 7cc9068..ca82f69 100644 (file)
@@ -901,6 +901,18 @@ define one_stats_details
   u32 bytes;
 };
 
+define one_stats_flush
+{
+  u32 client_index;
+  u32 context;
+};
+
+define one_stats_flush_reply
+{
+  u32 context;
+  i32 retval;
+};
+
 define one_stats_enable_disable
 {
   u32 client_index;
index 2892409..23549af 100644 (file)
@@ -108,6 +108,7 @@ _(SHOW_ONE_USE_PETR, show_one_use_petr)                                 \
 _(SHOW_ONE_STATS_ENABLE_DISABLE, show_one_stats_enable_disable)         \
 _(ONE_STATS_ENABLE_DISABLE, one_stats_enable_disable)                   \
 _(ONE_STATS_DUMP, one_stats_dump)                                       \
+_(ONE_STATS_FLUSH, one_stats_flush)                                     \
 
 
 static locator_t *
@@ -1346,6 +1347,16 @@ lisp_fid_addr_to_api (fid_address_t * fid, u8 * dst, u8 * api_eid_type,
     }
 }
 
+static void
+vl_api_one_stats_flush_t_handler (vl_api_one_stats_flush_t * mp)
+{
+  vl_api_one_stats_flush_reply_t *rmp;
+  u8 rv;
+
+  rv = vnet_lisp_flush_stats ();
+  REPLY_MACRO (VL_API_ONE_STATS_FLUSH_REPLY);
+}
+
 static void
 vl_api_one_stats_dump_t_handler (vl_api_one_stats_dump_t * mp)
 {
@@ -1369,8 +1380,8 @@ vl_api_one_stats_dump_t_handler (vl_api_one_stats_dump_t * mp)
         ip_address_copy_addr (rmp->rloc, &stat->rmt_rloc);
         ip_address_copy_addr (rmp->lloc, &stat->loc_rloc);
 
-        rmp->pkt_count = clib_host_to_net_u32 (stat->stats.pkt_count);
-        rmp->bytes = clib_host_to_net_u32 (stat->stats.bytes);
+        rmp->pkt_count = clib_host_to_net_u32 (stat->counters.packets);
+        rmp->bytes = clib_host_to_net_u32 (stat->counters.bytes);
       }));
       /* *INDENT-ON* */
   }
index 4b1a1cc..109aca2 100644 (file)
@@ -1682,7 +1682,7 @@ lisp_show_stats_details_command_fn (vlib_main_t * vm,
                     format_fid_address, &stat->deid,
                     format_ip_address, &stat->loc_rloc,
                     format_ip_address, &stat->rmt_rloc,
-                    stat->stats.pkt_count, stat->stats.bytes);
+                    stat->counters.packets, stat->counters.bytes);
   }
   vec_free (stats);
   return 0;
index 1241ab9..052410e 100644 (file)
@@ -426,6 +426,9 @@ lisp_gpe_init (vlib_main_t * vm)
 
   lgm->lisp_stats_index_by_key =
     hash_create_mem (0, sizeof (lisp_stats_key_t), sizeof (uword));
+  memset (&lgm->counters, 0, sizeof (lgm->counters));
+  lgm->counters.name = "LISP counters";
+
   return 0;
 }
 
index b3821ac..38d7699 100644 (file)
@@ -96,12 +96,6 @@ typedef struct
   u32 tunnel_index;
 } lisp_stats_key_t;
 
-typedef struct
-{
-  u32 pkt_count;
-  u32 bytes;
-} lisp_stats_t;
-
 typedef struct
 {
   u32 vni;
@@ -110,7 +104,7 @@ typedef struct
   ip_address_t loc_rloc;
   ip_address_t rmt_rloc;
 
-  lisp_stats_t stats;
+  vlib_counter_t counters;
 } lisp_api_stats_t;
 
 typedef enum gpe_encap_mode_e
@@ -165,8 +159,9 @@ typedef struct lisp_gpe_main
 
   gpe_encap_mode_t encap_mode;
 
-  lisp_stats_t *lisp_stats_pool;
+  u8 *dummy_stats_pool;
   uword *lisp_stats_index_by_key;
+  vlib_combined_counter_main_t counters;
 
   /** convenience */
   vlib_main_t *vlib_main;
@@ -313,7 +308,7 @@ int vnet_gpe_set_encap_mode (gpe_encap_mode_t mode);
 u8 vnet_lisp_stats_enable_disable_state (void);
 vnet_api_error_t vnet_lisp_stats_enable_disable (u8 enable);
 lisp_api_stats_t *vnet_lisp_get_stats (void);
-void vnet_lisp_flush_stats (void);
+int vnet_lisp_flush_stats (void);
 
 #endif /* included_vnet_lisp_gpe_h */
 
index 79b2a07..d5f3a28 100644 (file)
@@ -250,7 +250,6 @@ lisp_gpe_increment_stats_counters (lisp_cp_main_t * lcm, ip_adjacency_t * adj,
   index_t lai;
   u32 si, di;
   gid_address_t src, dst;
-  lisp_stats_t *stats;
   uword *feip;
 
   ip46_address_to_ip_address (&adj->sub_type.nbr.next_hop, &rloc);
@@ -299,23 +298,12 @@ lisp_gpe_increment_stats_counters (lisp_cp_main_t * lcm, ip_adjacency_t * adj,
   key.tunnel_index = ladj->tunnel_index;
 
   uword *p = hash_get_mem (lgm->lisp_stats_index_by_key, &key);
-  if (p)
-    {
-      stats = pool_elt_at_index (lgm->lisp_stats_pool, p[0]);
-    }
-  else
-    {
-      pool_get (lgm->lisp_stats_pool, stats);
-      memset (stats, 0, sizeof (*stats));
+  ASSERT (p);
 
-      lisp_stats_key_t *key_copy = clib_mem_alloc (sizeof (*key_copy));
-      memcpy (key_copy, &key, sizeof (*key_copy));
-      hash_set_mem (lgm->lisp_stats_index_by_key, key_copy,
-                   stats - lgm->lisp_stats_pool);
-    }
-  stats->pkt_count++;
   /* compute payload length starting after GPE */
-  stats->bytes += b->current_length - (lisp_data - b->data - b->current_data);
+  u32 bytes = b->current_length - (lisp_data - b->data - b->current_data);
+  vlib_increment_combined_counter (&lgm->counters, os_get_cpu_number (),
+                                  p[0], 1, bytes);
 }
 
 static void
index d2954e9..6d400f7 100644 (file)
@@ -410,6 +410,43 @@ lisp_gpe_fwd_entry_mk_paths (lisp_gpe_fwd_entry_t * lfe,
   vec_sort_with_function (lfe->paths, lisp_gpe_fwd_entry_path_sort);
 }
 
+void
+vnet_lisp_gpe_add_fwd_counters (vnet_lisp_gpe_add_del_fwd_entry_args_t * a,
+                               u32 fwd_entry_index)
+{
+  const lisp_gpe_adjacency_t *ladj;
+  lisp_fwd_path_t *path;
+  lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
+  u8 *dummy_elt;
+  lisp_gpe_fwd_entry_t *lfe;
+  lisp_gpe_fwd_entry_key_t fe_key;
+  lisp_stats_key_t key;
+
+  lfe = find_fwd_entry (lgm, a, &fe_key);
+
+  if (LISP_GPE_FWD_ENTRY_TYPE_NORMAL != lfe->type)
+    return;
+
+  memset (&key, 0, sizeof (key));
+  key.fwd_entry_index = fwd_entry_index;
+
+  vec_foreach (path, lfe->paths)
+  {
+    ladj = lisp_gpe_adjacency_get (path->lisp_adj);
+    key.tunnel_index = ladj->tunnel_index;
+    lisp_stats_key_t *key_copy = clib_mem_alloc (sizeof (*key_copy));
+    memcpy (key_copy, &key, sizeof (*key_copy));
+    pool_get (lgm->dummy_stats_pool, dummy_elt);
+    hash_set_mem (lgm->lisp_stats_index_by_key, key_copy,
+                 dummy_elt - lgm->dummy_stats_pool);
+
+    vlib_validate_combined_counter (&lgm->counters,
+                                   dummy_elt - lgm->dummy_stats_pool);
+    vlib_zero_combined_counter (&lgm->counters,
+                               dummy_elt - lgm->dummy_stats_pool);
+  }
+}
+
 /**
  * @brief Add/Delete LISP IP forwarding entry.
  *
@@ -1172,19 +1209,17 @@ vnet_lisp_gpe_add_del_fwd_entry (vnet_lisp_gpe_add_del_fwd_entry_args_t * a,
     }
 }
 
-void
+int
 vnet_lisp_flush_stats (void)
 {
   lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
-  lisp_stats_t *stat;
+  vlib_combined_counter_main_t *cm = &lgm->counters;
+  u32 i;
 
-  /* *INDENT-OFF* */
-  pool_foreach (stat, lgm->lisp_stats_pool,
-  {
-    stat->pkt_count = 0;
-    stat->bytes = 0;
-  });
-  /* *INDENT-ON* */
+  for (i = 0; i < vlib_combined_counter_n_counters (cm); i++)
+    vlib_zero_combined_counter (cm, i);
+
+  return 0;
 }
 
 static void
@@ -1194,7 +1229,7 @@ lisp_del_adj_stats (lisp_gpe_main_t * lgm, u32 fwd_entry_index, u32 ti)
   lisp_stats_key_t key;
   void *key_copy;
   uword *p;
-  lisp_stats_t *s;
+  u8 *s;
 
   memset (&key, 0, sizeof (key));
   key.fwd_entry_index = fwd_entry_index;
@@ -1203,18 +1238,18 @@ lisp_del_adj_stats (lisp_gpe_main_t * lgm, u32 fwd_entry_index, u32 ti)
   p = hash_get_mem (lgm->lisp_stats_index_by_key, &key);
   if (p)
     {
-      s = pool_elt_at_index (lgm->lisp_stats_pool, p[0]);
+      s = pool_elt_at_index (lgm->dummy_stats_pool, p[0]);
       hp = hash_get_pair (lgm->lisp_stats_index_by_key, &key);
       key_copy = (void *) (hp->key);
       hash_unset_mem (lgm->lisp_stats_index_by_key, &key);
       clib_mem_free (key_copy);
-      pool_put (lgm->lisp_stats_pool, s);
+      pool_put (lgm->dummy_stats_pool, s);
     }
 }
 
 void
-vnet_lisp_del_fwd_stats (vnet_lisp_gpe_add_del_fwd_entry_args_t * a,
-                        u32 fwd_entry_index)
+vnet_lisp_gpe_del_fwd_counters (vnet_lisp_gpe_add_del_fwd_entry_args_t * a,
+                               u32 fwd_entry_index)
 {
   lisp_gpe_main_t *lgm = &lisp_gpe_main;
   lisp_gpe_fwd_entry_key_t fe_key;
index 92e1852..b9d9c98 100644 (file)
@@ -212,8 +212,11 @@ extern u32 lisp_l2_fib_lookup (lisp_gpe_main_t * lgm,
 extern const dpo_id_t *lisp_nsh_fib_lookup (lisp_gpe_main_t * lgm,
                                            u32 spi_si);
 extern void
-vnet_lisp_del_fwd_stats (vnet_lisp_gpe_add_del_fwd_entry_args_t * a,
-                        u32 fwd_entry_index);
+vnet_lisp_gpe_del_fwd_counters (vnet_lisp_gpe_add_del_fwd_entry_args_t * a,
+                               u32 fwd_entry_index);
+extern void
+vnet_lisp_gpe_add_fwd_counters (vnet_lisp_gpe_add_del_fwd_entry_args_t * a,
+                               u32 fwd_entry_index);
 #endif
 
 /*