LISP statistics 35/5735/6
authorFilip Tehlar <ftehlar@cisco.com>
Thu, 9 Mar 2017 15:48:39 +0000 (16:48 +0100)
committerFlorin Coras <florin.coras@gmail.com>
Tue, 21 Mar 2017 15:31:56 +0000 (15:31 +0000)
Change-Id: I399cac46d279e020ba33459ef759d9d29d3ac716
Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
13 files changed:
src/vat/api_format.c
src/vnet/adj/adj_l2.c
src/vnet/lisp-cp/control.c
src/vnet/lisp-cp/control.h
src/vnet/lisp-cp/lisp_types.c
src/vnet/lisp-cp/lisp_types.h
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 391fe9c..d34a97f 100644 (file)
@@ -2610,6 +2610,92 @@ vl_api_one_eid_table_details_t_handler_json (vl_api_one_eid_table_details_t
   vec_free (eid);
 }
 
+static void
+vl_api_one_stats_details_t_handler (vl_api_one_stats_details_t * mp)
+{
+  vat_main_t *vam = &vat_main;
+  u8 *seid = 0, *deid = 0;
+  u8 *(*format_ip_address_fcn) (u8 *, va_list *) = 0;
+
+  deid = format (0, "%U", format_lisp_eid_vat,
+                mp->eid_type, mp->deid, mp->deid_pref_len, 0, 0, 0);
+
+  seid = format (0, "%U", format_lisp_eid_vat,
+                mp->eid_type, mp->seid, mp->seid_pref_len, 0, 0, 0);
+
+  vec_add1 (deid, 0);
+  vec_add1 (seid, 0);
+
+  if (mp->is_ip4)
+    format_ip_address_fcn = format_ip4_address;
+  else
+    format_ip_address_fcn = format_ip6_address;
+
+
+  print (vam->ofp, "([%d] %s %s) (%U %U) %u %u",
+        clib_net_to_host_u32 (mp->vni),
+        seid, deid,
+        format_ip_address_fcn, mp->lloc,
+        format_ip_address_fcn, mp->rloc,
+        clib_net_to_host_u32 (mp->pkt_count),
+        clib_net_to_host_u32 (mp->bytes));
+
+  vec_free (deid);
+  vec_free (seid);
+}
+
+static void
+vl_api_one_stats_details_t_handler_json (vl_api_one_stats_details_t * mp)
+{
+  struct in6_addr ip6;
+  struct in_addr ip4;
+  vat_main_t *vam = &vat_main;
+  vat_json_node_t *node = 0;
+  u8 *deid = 0, *seid = 0;
+
+  if (VAT_JSON_ARRAY != vam->json_tree.type)
+    {
+      ASSERT (VAT_JSON_NONE == vam->json_tree.type);
+      vat_json_init_array (&vam->json_tree);
+    }
+  node = vat_json_array_add (&vam->json_tree);
+
+  vat_json_init_object (node);
+  deid = format (0, "%U", format_lisp_eid_vat,
+                mp->eid_type, mp->deid, mp->deid_pref_len, 0, 0, 0);
+
+  seid = format (0, "%U", format_lisp_eid_vat,
+                mp->eid_type, mp->seid, mp->seid_pref_len, 0, 0, 0);
+
+  vec_add1 (deid, 0);
+  vec_add1 (seid, 0);
+
+  vat_json_object_add_string_copy (node, "seid", seid);
+  vat_json_object_add_string_copy (node, "deid", deid);
+  vat_json_object_add_uint (node, "vni", clib_net_to_host_u32 (mp->vni));
+
+  if (mp->is_ip4)
+    {
+      clib_memcpy (&ip4, mp->lloc, sizeof (ip4));
+      vat_json_object_add_ip4 (node, "lloc", ip4);
+      clib_memcpy (&ip4, mp->rloc, sizeof (ip4));
+      vat_json_object_add_ip4 (node, "rloc", ip4);
+    }
+  else
+    {
+      clib_memcpy (&ip6, mp->lloc, sizeof (ip6));
+      vat_json_object_add_ip6 (node, "lloc", ip6);
+      clib_memcpy (&ip6, mp->rloc, sizeof (ip6));
+      vat_json_object_add_ip6 (node, "rloc", ip6);
+    }
+  vat_json_object_add_uint (node, "pkt_count",
+                           clib_net_to_host_u32 (mp->pkt_count));
+  vat_json_object_add_uint (node, "bytes", clib_net_to_host_u32 (mp->bytes));
+
+  vec_free (deid);
+  vec_free (seid);
+}
+
 static void
   vl_api_one_eid_table_map_details_t_handler
   (vl_api_one_eid_table_map_details_t * mp)
@@ -2740,6 +2826,42 @@ static void
   vec_free (s);
 }
 
+static void
+  vl_api_show_one_stats_enable_disable_reply_t_handler
+  (vl_api_show_one_stats_enable_disable_reply_t * mp)
+{
+  vat_main_t *vam = &vat_main;
+  int retval = clib_net_to_host_u32 (mp->retval);
+
+  if (retval)
+    goto end;
+
+  print (vam->ofp, "%s", mp->is_en ? "enabled" : "disabled");
+end:
+  vam->retval = retval;
+  vam->result_ready = 1;
+}
+
+static void
+  vl_api_show_one_stats_enable_disable_reply_t_handler_json
+  (vl_api_show_one_stats_enable_disable_reply_t * mp)
+{
+  vat_main_t *vam = &vat_main;
+  vat_json_node_t _node, *node = &_node;
+  int retval = clib_net_to_host_u32 (mp->retval);
+
+  u8 *s = format (0, "%s", mp->is_en ? "enabled" : "disabled");
+  vat_json_init_object (node);
+  vat_json_object_add_string_copy (node, "state", s);
+
+  vat_json_print (vam->ofp, node);
+  vat_json_free (node);
+
+  vam->retval = retval;
+  vam->result_ready = 1;
+  vec_free (s);
+}
+
 static void
 api_gpe_fwd_entry_net_to_host (vl_api_gpe_fwd_entry_t * e)
 {
@@ -4040,6 +4162,7 @@ _(one_map_request_mode_reply)                           \
 _(one_add_del_map_request_itr_rlocs_reply)              \
 _(one_eid_table_add_del_map_reply)                      \
 _(one_use_petr_reply)                                   \
+_(one_stats_enable_disable_reply)                       \
 _(gpe_add_del_fwd_entry_reply)                          \
 _(gpe_enable_disable_reply)                             \
 _(gpe_set_encap_mode_reply)                             \
@@ -4263,6 +4386,10 @@ _(ONE_EID_TABLE_VNI_DETAILS, one_eid_table_vni_details)                 \
 _(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_ENABLE_DISABLE_REPLY, one_stats_enable_disable_reply)       \
+_(SHOW_ONE_STATS_ENABLE_DISABLE_REPLY,                                  \
+  show_one_stats_enable_disable_reply)                                  \
 _(GPE_SET_ENCAP_MODE_REPLY, gpe_set_encap_mode_reply)                   \
 _(GPE_GET_ENCAP_MODE_REPLY, gpe_get_encap_mode_reply)                   \
 _(GPE_ADD_DEL_IFACE_REPLY, gpe_add_del_iface_reply)                     \
@@ -14214,6 +14341,64 @@ api_show_one_rloc_probe_state (vat_main_t * vam)
 
 #define api_show_lisp_rloc_probe_state api_show_one_rloc_probe_state
 
+static int
+api_one_stats_enable_disable (vat_main_t * vam)
+{
+  vl_api_one_stats_enable_disable_t *mp;
+  unformat_input_t *input = vam->input;
+  u8 is_set = 0;
+  u8 is_en = 0;
+  int ret;
+
+  /* Parse args required to build the message */
+  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (input, "enable"))
+       {
+         is_set = 1;
+         is_en = 1;
+       }
+      else if (unformat (input, "disable"))
+       {
+         is_set = 1;
+       }
+      else
+       break;
+    }
+
+  if (!is_set)
+    {
+      errmsg ("Value not set");
+      return -99;
+    }
+
+  M (ONE_STATS_ENABLE_DISABLE, mp);
+  mp->is_en = is_en;
+
+  /* send */
+  S (mp);
+
+  /* wait for reply */
+  W (ret);
+  return ret;
+}
+
+static int
+api_show_one_stats_enable_disable (vat_main_t * vam)
+{
+  vl_api_show_one_stats_enable_disable_t *mp;
+  int ret;
+
+  M (SHOW_ONE_STATS_ENABLE_DISABLE, mp);
+
+  /* send */
+  S (mp);
+
+  /* wait for reply */
+  W (ret);
+  return ret;
+}
+
 static int
 api_show_one_map_request_mode (vat_main_t * vam)
 {
@@ -15421,6 +15606,26 @@ 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_dump (vat_main_t * vam)
+{
+  vl_api_one_stats_dump_t *mp;
+  vl_api_control_ping_t *mp_ping;
+  int ret;
+
+  M (ONE_STATS_DUMP, mp);
+  /* send it... */
+  S (mp);
+
+  /* Use a control ping for synchronization */
+  M (CONTROL_PING, mp_ping);
+  S (mp_ping);
+
+  /* Wait for a reply... */
+  W (ret);
+  return ret;
+}
+
 static int
 api_show_one_status (vat_main_t * vam)
 {
@@ -18389,6 +18594,8 @@ _(one_locator_set_dump, "[local | remote]")                             \
 _(one_locator_dump, "ls_index <index> | ls_name <name>")                \
 _(one_eid_table_dump, "[eid <ipv4|ipv6>/<prefix> | <mac>] [vni] "       \
                        "[local] | [remote]")                            \
+_(one_stats_enable_disable, "enable|disalbe")                           \
+_(show_one_stats_enable_disable, "")                                    \
 _(one_eid_table_vni_dump, "")                                           \
 _(one_eid_table_map_dump, "l2|l3")                                      \
 _(one_map_resolver_dump, "")                                            \
@@ -18397,6 +18604,7 @@ _(one_adjacencies_get, "vni <vni>")                                     \
 _(show_one_rloc_probe_state, "")                                        \
 _(show_one_map_register_state, "")                                      \
 _(show_one_status, "")                                                  \
+_(one_stats_dump, "")                                                   \
 _(one_get_map_request_itr_rlocs, "")                                    \
 _(show_one_pitr, "")                                                    \
 _(show_one_use_petr, "")                                                \
index 5a08364..fb64e50 100644 (file)
@@ -93,6 +93,7 @@ adj_l2_rewrite_inline (vlib_main_t * vm,
            /* Update packet buffer attributes/set output interface. */
            rw_len0 = adj0[0].rewrite_header.data_bytes;
            vnet_buffer(p0)->ip.save_rewrite_length = rw_len0;
+            vnet_buffer(p0)->sw_if_index[VLIB_TX] = adj0->rewrite_header.sw_if_index;
 
            vlib_increment_combined_counter(&adjacency_counters,
                                             cpu_index,
index 5c90c03..47badeb 100644 (file)
@@ -19,6 +19,7 @@
 #include <vnet/lisp-cp/lisp_msg_serdes.h>
 #include <vnet/lisp-gpe/lisp_gpe_fwd_entry.h>
 #include <vnet/lisp-gpe/lisp_gpe_tenant.h>
+#include <vnet/lisp-gpe/lisp_gpe_tunnel.h>
 #include <vnet/fib/fib_entry.h>
 #include <vnet/fib/fib_table.h>
 
@@ -284,6 +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_add_del_fwd_entry (a, &sw_if_index);
 
   /* delete entry in fwd table */
@@ -1228,9 +1230,6 @@ vnet_lisp_add_del_adjacency (vnet_lisp_add_del_adjacency_args_t * a)
 
   if (a->is_add)
     {
-      /* TODO 1) check if src/dst 2) once we have src/dst working, use it in
-       * delete*/
-
       /* check if source eid has an associated mapping. If pitr mode is on,
        * just use the pitr's mapping */
       local_mi = lcm->lisp_pitr ? lcm->pitr_map_index :
@@ -2654,16 +2653,15 @@ lisp_get_vni_from_buffer_eth (lisp_cp_main_t * lcm, vlib_buffer_t * b)
   return vni;
 }
 
-always_inline void
+void
 get_src_and_dst_eids_from_buffer (lisp_cp_main_t * lcm, vlib_buffer_t * b,
-                                 gid_address_t * src, gid_address_t * dst)
+                                 gid_address_t * src, gid_address_t * dst,
+                                 u16 type)
 {
   u32 vni = 0;
-  u16 type;
 
   memset (src, 0, sizeof (*src));
   memset (dst, 0, sizeof (*dst));
-  type = vnet_buffer (b)->lisp.overlay_afi;
 
   if (LISP_AFI_IP == type || LISP_AFI_IP6 == type)
     {
@@ -2742,10 +2740,9 @@ lisp_cp_lookup_inline (vlib_main_t * vm,
 
          b0 = vlib_get_buffer (vm, pi0);
          b0->error = node->errors[LISP_CP_LOOKUP_ERROR_DROP];
-         vnet_buffer (b0)->lisp.overlay_afi = overlay;
 
          /* src/dst eid pair */
-         get_src_and_dst_eids_from_buffer (lcm, b0, &src, &dst);
+         get_src_and_dst_eids_from_buffer (lcm, b0, &src, &dst, overlay);
 
          /* if we have remote mapping for destination already in map-chache
             add forwarding tunnel directly. If not send a map-request */
@@ -3605,6 +3602,55 @@ lisp_cp_init (vlib_main_t * vm)
   return 0;
 }
 
+static int
+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;
+  lisp_gpe_fwd_entry_key_t fwd_key;
+  const lisp_gpe_tunnel_t *lgt;
+  fwd_entry_t *fe;
+
+  memset (stat, 0, sizeof (*stat));
+  memset (&fwd_key, 0, sizeof (fwd_key));
+
+  fe = pool_elt_at_index (lcm->fwd_entry_pool, key->fwd_entry_index);
+  ASSERT (fe != 0);
+
+  gid_to_dp_address (&fe->reid, &stat->deid);
+  gid_to_dp_address (&fe->leid, &stat->seid);
+  stat->vni = gid_address_vni (&fe->reid);
+
+  lgt = lisp_gpe_tunnel_get (key->tunnel_index);
+  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;
+  return 1;
+}
+
+lisp_api_stats_t *
+vnet_lisp_get_stats (void)
+{
+  lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
+  lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+  lisp_api_stats_t *stats = 0, stat;
+  lisp_stats_key_t *key;
+  u32 index;
+
+  /* *INDENT-OFF* */
+  hash_foreach_mem (key, index, lgm->lisp_stats_index_by_key,
+  {
+    if (lisp_stats_api_fill (lcm, lgm, &stat, key, index))
+      vec_add1 (stats, stat);
+  });
+  /* *INDENT-ON* */
+
+  return stats;
+}
+
 static void *
 send_map_request_thread_fn (void *arg)
 {
@@ -3810,7 +3856,11 @@ vnet_lisp_stats_enable_disable (u8 enable)
   if (vnet_lisp_enable_disable_status () == 0)
     return VNET_API_ERROR_LISP_DISABLED;
 
-  lcm->stats_enabled = enable;
+  if (enable)
+    lcm->flags |= LISP_FLAG_STATS_ENABLED;
+  else
+    lcm->flags &= ~LISP_FLAG_STATS_ENABLED;
+
   return 0;
 }
 
@@ -3822,7 +3872,7 @@ vnet_lisp_stats_enable_disable_state (void)
   if (vnet_lisp_enable_disable_status () == 0)
     return VNET_API_ERROR_LISP_DISABLED;
 
-  return lcm->stats_enabled;
+  return lcm->flags & LISP_FLAG_STATS_ENABLED;
 }
 
 /* *INDENT-OFF* */
index 933b34b..eae8a18 100644 (file)
@@ -95,7 +95,8 @@ typedef enum
 } map_request_mode_t;
 
 #define foreach_lisp_flag_bit       \
-  _(USE_PETR, "Use Proxy-ETR")
+  _(USE_PETR, "Use Proxy-ETR")                  \
+  _(STATS_ENABLED, "Statistics enabled")
 
 typedef enum lisp_flag_bits
 {
@@ -210,9 +211,6 @@ typedef struct
   /* timing wheel for mappping timeouts */
   timing_wheel_t wheel;
 
-  /* statistics */
-  u8 stats_enabled;
-
   /* commodity */
   ip4_main_t *im4;
   ip6_main_t *im6;
@@ -235,6 +233,11 @@ vnet_lisp_cp_get_main ()
   return &lisp_control_main;
 }
 
+void
+get_src_and_dst_eids_from_buffer (lisp_cp_main_t * lcm, vlib_buffer_t * b,
+                                 gid_address_t * src, gid_address_t * dst,
+                                 u16 type);
+
 typedef struct
 {
   u8 is_add;
@@ -335,9 +338,6 @@ lisp_get_petr_mapping (lisp_cp_main_t * lcm)
   return pool_elt_at_index (lcm->mapping_pool, lcm->petr_map_index);
 }
 
-u8 vnet_lisp_stats_enable_disable_state (void);
-vnet_api_error_t vnet_lisp_stats_enable_disable (u8 enable);
-
 #endif /* VNET_CONTROL_H_ */
 
 /*
index b646668..ad3a4bd 100644 (file)
@@ -573,6 +573,44 @@ ip_address_parse (void *offset, u16 iana_afi, ip_address_t * dst)
   return (sizeof (u16) + size);
 }
 
+void
+gid_to_dp_address (gid_address_t * g, dp_address_t * d)
+{
+  switch (gid_address_type (g))
+    {
+    case GID_ADDR_SRC_DST:
+      switch (gid_address_sd_dst_type (g))
+       {
+       case FID_ADDR_IP_PREF:
+         ip_prefix_copy (&d->ippref, &gid_address_sd_dst_ippref (g));
+         d->type = FID_ADDR_IP_PREF;
+         break;
+       case FID_ADDR_MAC:
+         mac_copy (&d->mac, &gid_address_sd_dst_mac (g));
+         d->type = FID_ADDR_MAC;
+         break;
+       default:
+         clib_warning ("Source/Dest address type %d not supported!",
+                       gid_address_sd_dst_type (g));
+         break;
+       }
+      break;
+    case GID_ADDR_IP_PREFIX:
+      ip_prefix_copy (&d->ippref, &gid_address_ippref (g));
+      d->type = FID_ADDR_IP_PREF;
+      break;
+    case GID_ADDR_MAC:
+      mac_copy (&d->mac, &gid_address_mac (g));
+      d->type = FID_ADDR_MAC;
+      break;
+    case GID_ADDR_NSH:
+    default:
+      d->nsh = gid_address_nsh (g).spi << 8 | gid_address_nsh (g).si;
+      d->type = FID_ADDR_NSH;
+      break;
+    }
+}
+
 u32
 lcaf_hdr_parse (void *offset, lcaf_t * lcaf)
 {
index 672835b..a65a479 100644 (file)
@@ -126,6 +126,8 @@ typedef struct
 typedef fid_address_t dp_address_t;
 
 #define fid_addr_ippref(_a) (_a)->ippref
+#define fid_addr_prefix_length(_a) ip_prefix_len(&fid_addr_ippref(_a))
+#define fid_addr_ip_version(_a) ip_prefix_version(&fid_addr_ippref(_a))
 #define fid_addr_mac(_a) (_a)->mac
 #define fid_addr_nsh(_a) (_a)->nsh
 #define fid_addr_type(_a) (_a)->type
@@ -359,6 +361,7 @@ void
 build_src_dst (gid_address_t * sd, gid_address_t * src, gid_address_t * dst);
 
 void gid_address_from_ip (gid_address_t * g, ip_address_t * ip);
+void gid_to_dp_address (gid_address_t * g, dp_address_t * d);
 
 #endif /* VNET_LISP_GPE_LISP_TYPES_H_ */
 
index 4faf624..ab9e7a6 100644 (file)
 
 #include <vlibapi/api_helper_macros.h>
 
+#define REPLY_DETAILS(t, body)                                  \
+do {                                                            \
+    unix_shared_memory_queue_t * q;                             \
+    rv = vl_msg_api_pd_handler (mp, rv);                        \
+    q = vl_api_client_index_to_input_queue (mp->client_index);  \
+    if (!q)                                                     \
+        return;                                                 \
+                                                                \
+    rmp = vl_msg_api_alloc (sizeof (*rmp));                     \
+    rmp->_vl_msg_id = ntohs((t));                               \
+    rmp->context = mp->context;                                 \
+    do {body;} while (0);                                       \
+    vl_msg_api_send_shmem (q, (u8 *)&rmp);                      \
+} while(0);
+
 #define foreach_vpe_api_msg                             \
 _(ONE_ADD_DEL_LOCATOR_SET, one_add_del_locator_set)                     \
 _(ONE_ADD_DEL_LOCATOR, one_add_del_locator)                             \
@@ -1300,10 +1315,62 @@ static void
   REPLY_MACRO (VL_API_ONE_ENABLE_DISABLE_REPLY);
 }
 
+static void
+lisp_fid_addr_to_api (fid_address_t * fid, u8 * dst, u8 * api_eid_type,
+                     u8 * prefix_length)
+{
+  switch (fid_addr_type (fid))
+    {
+    case FID_ADDR_IP_PREF:
+      *prefix_length = fid_addr_prefix_length (fid);
+      if (fid_addr_ip_version (fid) == IP4)
+       {
+         *api_eid_type = 0;    /* ipv4 type */
+         clib_memcpy (dst, &fid_addr_ippref (fid), 4);
+       }
+      else
+       {
+         *api_eid_type = 1;    /* ipv6 type */
+         clib_memcpy (dst, &fid_addr_ippref (fid), 16);
+       }
+      break;
+    case FID_ADDR_MAC:
+      *api_eid_type = 2;       /* l2 mac type */
+      mac_copy (dst, fid_addr_mac (fid));
+      break;
+    default:
+      ASSERT (0);
+    }
+}
+
 static void
 vl_api_one_stats_dump_t_handler (vl_api_one_stats_dump_t * mp)
 {
+  vl_api_one_stats_details_t *rmp;
+  lisp_api_stats_t *stats, *stat;
+  u8 rv = 0;
 
+  stats = vnet_lisp_get_stats ();
+  vec_foreach (stat, stats)
+  {
+      /* *INDENT-OFF* */
+      REPLY_DETAILS (VL_API_ONE_STATS_DETAILS,
+      ({
+        lisp_fid_addr_to_api (&stat->deid, rmp->deid, &rmp->eid_type,
+                              &rmp->deid_pref_len);
+        lisp_fid_addr_to_api (&stat->seid, rmp->seid, &rmp->eid_type,
+                              &rmp->seid_pref_len);
+        rmp->vni = clib_host_to_net_u32 (stat->vni);
+
+        rmp->is_ip4 = ip_addr_version (&stat->rmt_rloc) == IP4 ? 1 : 0;
+        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);
+      }));
+      /* *INDENT-ON* */
+  }
 }
 
 /*
index 2ceeaf4..b5bc529 100644 (file)
@@ -352,7 +352,7 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
        }
     }
 
-  if (!eid_set)
+  if (!del_all && !eid_set)
     {
       clib_warning ("missing eid!");
       goto done;
@@ -372,8 +372,6 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
       goto done;
     }
 
-  /* TODO build src/dst with seid */
-
   /* if it's a delete, clean forwarding */
   if (!is_add)
     {
@@ -1654,12 +1652,46 @@ lisp_show_stats_command_fn (vlib_main_t * vm,
 
 /* *INDENT-OFF* */
 VLIB_CLI_COMMAND (one_show_stats_command) = {
-    .path = "show one stats",
-    .short_help = "show ONE statistics",
+    .path = "show one statistics status",
+    .short_help = "show ONE statistics enable/disable status",
     .function = lisp_show_stats_command_fn,
 };
 /* *INDENT-ON* */
 
+static clib_error_t *
+lisp_show_stats_details_command_fn (vlib_main_t * vm,
+                                   unformat_input_t * input,
+                                   vlib_cli_command_t * cmd)
+{
+  lisp_api_stats_t *stat, *stats = vnet_lisp_get_stats ();
+
+  if (vec_len (stats) > 0)
+    vlib_cli_output (vm,
+                    "[src-EID, dst-EID] [loc-rloc, rmt-rloc] count bytes\n");
+  else
+    vlib_cli_output (vm, "No statistics found.\n");
+
+  vec_foreach (stat, stats)
+  {
+    vlib_cli_output (vm, "[%U, %U] [%U, %U] %7u %7u\n",
+                    format_fid_address, &stat->seid,
+                    format_fid_address, &stat->deid,
+                    format_ip_address, &stat->loc_rloc,
+                    format_ip_address, &stat->rmt_rloc,
+                    stat->stats.pkt_count, stat->stats.bytes);
+  }
+  vec_free (stats);
+  return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (one_show_stats_details_command) = {
+    .path = "show one statistics details",
+    .short_help = "show ONE statistics",
+    .function = lisp_show_stats_details_command_fn,
+};
+/* *INDENT-ON* */
+
 static clib_error_t *
 lisp_stats_enable_disable_command_fn (vlib_main_t * vm,
                                      unformat_input_t * input,
@@ -1692,12 +1724,29 @@ done:
 
 /* *INDENT-OFF* */
 VLIB_CLI_COMMAND (one_stats_enable_disable_command) = {
-    .path = "one stats",
+    .path = "one statistics",
     .short_help = "enable/disable ONE statistics collecting",
     .function = lisp_stats_enable_disable_command_fn,
 };
 /* *INDENT-ON* */
 
+static clib_error_t *
+lisp_stats_flush_command_fn (vlib_main_t * vm,
+                            unformat_input_t * input,
+                            vlib_cli_command_t * cmd)
+{
+  vnet_lisp_flush_stats ();
+  return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (one_stats_flush_command) = {
+    .path = "one statistics flush",
+    .short_help = "Flush ONE statistics",
+    .function = lisp_stats_flush_command_fn,
+};
+/* *INDENT-ON* */
+
 /*
  * fd.io coding-style-patch-verification: ON
  *
index 446ad44..1241ab9 100644 (file)
@@ -424,6 +424,8 @@ lisp_gpe_init (vlib_main_t * vm)
   udp_register_dst_port (vm, UDP_DST_PORT_lisp_gpe6,
                         lisp_gpe_ip6_input_node.index, 0 /* is_ip4 */ );
 
+  lgm->lisp_stats_index_by_key =
+    hash_create_mem (0, sizeof (lisp_stats_key_t), sizeof (uword));
   return 0;
 }
 
index b5a50ec..be44702 100644 (file)
@@ -90,6 +90,28 @@ typedef struct tunnel_lookup
   uword *vni_by_sw_if_index;
 } tunnel_lookup_t;
 
+typedef struct
+{
+  u32 fwd_entry_index;
+  u32 tunnel_index;
+} lisp_stats_key_t;
+
+typedef struct
+{
+  u32 pkt_count;
+  u32 bytes;
+} lisp_stats_t;
+
+typedef struct
+{
+  u32 vni;
+  dp_address_t deid;
+  dp_address_t seid;
+  ip_address_t loc_rloc;
+  ip_address_t rmt_rloc;
+
+  lisp_stats_t stats;
+} lisp_api_stats_t;
 
 typedef enum gpe_encap_mode_e
 {
@@ -143,6 +165,9 @@ typedef struct lisp_gpe_main
 
   gpe_encap_mode_t encap_mode;
 
+  lisp_stats_t *lisp_stats_pool;
+  uword *lisp_stats_index_by_key;
+
   /** convenience */
   vlib_main_t *vlib_main;
   vnet_main_t *vnet_main;
@@ -283,6 +308,11 @@ lisp_api_gpe_fwd_entry_t *vnet_lisp_gpe_fwd_entries_get_by_vni (u32 vni);
 gpe_encap_mode_t vnet_gpe_get_encap_mode (void);
 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);
+
 #endif /* included_vnet_lisp_gpe_h */
 
 /*
index dbcf713..50662dd 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include <vnet/dpo/load_balance.h>
+#include <vnet/lisp-cp/control.h>
 #include <vnet/lisp-cp/lisp_types.h>
 #include <vnet/lisp-gpe/lisp_gpe_sub_interface.h>
 #include <vnet/lisp-gpe/lisp_gpe_adjacency.h>
@@ -223,9 +224,108 @@ lisp_gpe_adj_proto_from_vnet_link_type (vnet_link_t linkt)
 
 #define is_v4_packet(_h) ((*(u8*) _h) & 0xF0) == 0x40
 
+static lisp_afi_e
+lisp_afi_from_vnet_link_type (vnet_link_t link)
+{
+  switch (link)
+    {
+    case VNET_LINK_IP4:
+      return LISP_AFI_IP;
+    case VNET_LINK_IP6:
+      return LISP_AFI_IP6;
+    case VNET_LINK_ETHERNET:
+      return LISP_AFI_MAC;
+    default:
+      return LISP_AFI_NO_ADDR;
+    }
+}
+
+static void
+lisp_gpe_increment_stats_counters (lisp_cp_main_t * lcm, ip_adjacency_t * adj,
+                                  vlib_buffer_t * b)
+{
+  lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
+  lisp_gpe_adjacency_t *ladj;
+  ip_address_t rloc;
+  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);
+  si = vnet_buffer (b)->sw_if_index[VLIB_TX];
+  lai = lisp_adj_find (&rloc, si);
+  ASSERT (INDEX_INVALID != lai);
+
+  ladj = pool_elt_at_index (lisp_adj_pool, lai);
+
+  u8 *lisp_data = (u8 *) vlib_buffer_get_current (b);
+
+  /* skip IP header */
+  if (is_v4_packet (lisp_data))
+    lisp_data += sizeof (ip4_header_t);
+  else
+    lisp_data += sizeof (ip6_header_t);
+
+  /* skip UDP header */
+  lisp_data += sizeof (udp_header_t);
+  // TODO: skip TCP?
+
+  /* skip LISP GPE header */
+  lisp_data += sizeof (lisp_gpe_header_t);
+
+  i16 saved_current_data = b->current_data;
+  b->current_data = lisp_data - b->data;
+
+  lisp_afi_e afi = lisp_afi_from_vnet_link_type (adj->ia_link);
+  get_src_and_dst_eids_from_buffer (lcm, b, &src, &dst, afi);
+  b->current_data = saved_current_data;
+  di = gid_dictionary_sd_lookup (&lcm->mapping_index_by_gid, &dst, &src);
+  if (PREDICT_FALSE (~0 == di))
+    {
+      clib_warning ("dst mapping not found (%U, %U)", format_gid_address,
+                   &src, format_gid_address, &dst);
+      return;
+    }
+
+  feip = hash_get (lcm->fwd_entry_by_mapping_index, di);
+  if (PREDICT_FALSE (!feip))
+    return;
+
+  lisp_stats_key_t key;
+  memset (&key, 0, sizeof (key));
+  key.fwd_entry_index = feip[0];
+  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));
+
+      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);
+}
+
 static void
 lisp_gpe_fixup (vlib_main_t * vm, ip_adjacency_t * adj, vlib_buffer_t * b)
 {
+  lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+
+  if (lcm->flags & LISP_FLAG_STATS_ENABLED)
+    lisp_gpe_increment_stats_counters (lcm, adj, b);
+
   /* Fixup the checksum and len fields in the LISP tunnel encap
    * that was applied at the midchain node */
   ip_udp_fixup_one (vm, b, is_v4_packet (vlib_buffer_get_current (b)));
index 2eb5ced..f458a14 100644 (file)
@@ -329,28 +329,6 @@ delete_fib_entries (lisp_gpe_fwd_entry_t * lfe)
                            lfe->eid_fib_index, &lfe->key->rmt.ippref);
 }
 
-static void
-gid_to_dp_address (gid_address_t * g, dp_address_t * d)
-{
-  switch (gid_address_type (g))
-    {
-    case GID_ADDR_IP_PREFIX:
-    case GID_ADDR_SRC_DST:
-      ip_prefix_copy (&d->ippref, &gid_address_ippref (g));
-      d->type = FID_ADDR_IP_PREF;
-      break;
-    case GID_ADDR_MAC:
-      mac_copy (&d->mac, &gid_address_mac (g));
-      d->type = FID_ADDR_MAC;
-      break;
-    case GID_ADDR_NSH:
-    default:
-      d->nsh = gid_address_nsh (g).spi << 8 | gid_address_nsh (g).si;
-      d->type = FID_ADDR_NSH;
-      break;
-    }
-}
-
 static lisp_gpe_fwd_entry_t *
 find_fwd_entry (lisp_gpe_main_t * lgm,
                vnet_lisp_gpe_add_del_fwd_entry_args_t * a,
@@ -1177,6 +1155,70 @@ vnet_lisp_gpe_add_del_fwd_entry (vnet_lisp_gpe_add_del_fwd_entry_args_t * a,
     }
 }
 
+void
+vnet_lisp_flush_stats (void)
+{
+  lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
+  lisp_stats_t *stat;
+
+  /* *INDENT-OFF* */
+  pool_foreach (stat, lgm->lisp_stats_pool,
+  {
+    stat->pkt_count = 0;
+    stat->bytes = 0;
+  });
+  /* *INDENT-ON* */
+}
+
+static void
+lisp_del_adj_stats (lisp_gpe_main_t * lgm, u32 fwd_entry_index, u32 ti)
+{
+  hash_pair_t *hp;
+  lisp_stats_key_t key;
+  void *key_copy;
+  uword *p;
+  lisp_stats_t *s;
+
+  memset (&key, 0, sizeof (key));
+  key.fwd_entry_index = fwd_entry_index;
+  key.tunnel_index = 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]);
+      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);
+    }
+}
+
+void
+vnet_lisp_del_fwd_stats (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;
+  lisp_gpe_fwd_entry_t *lfe;
+  lisp_fwd_path_t *path;
+  const lisp_gpe_adjacency_t *ladj;
+
+  lfe = find_fwd_entry (lgm, a, &fe_key);
+  if (!lfe)
+    return;
+
+  if (LISP_GPE_FWD_ENTRY_TYPE_NORMAL != lfe->type)
+    return;
+
+  vec_foreach (path, lfe->paths)
+  {
+    ladj = lisp_gpe_adjacency_get (path->lisp_adj);
+    lisp_del_adj_stats (lgm, fwd_entry_index, ladj->tunnel_index);
+  }
+}
+
 /**
  * @brief Flush all the forwrding entries
  */
index d58895a..618f7b5 100644 (file)
@@ -206,6 +206,9 @@ 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);
 #endif
 
 /*