VPP-362 Implement dumping of LISP adjacencies
[vpp.git] / vnet / vnet / lisp-cp / control.c
index 940d589..8dc4207 100644 (file)
@@ -18,6 +18,8 @@
 #include <vnet/lisp-cp/packets.h>
 #include <vnet/lisp-cp/lisp_msg_serdes.h>
 #include <vnet/lisp-gpe/lisp_gpe.h>
+#include <vnet/lisp-gpe/lisp_gpe_fwd_entry.h>
+#include <vnet/lisp-gpe/lisp_gpe_tenant.h>
 #include <vnet/fib/fib_entry.h>
 #include <vnet/fib/fib_table.h>
 
@@ -167,8 +169,7 @@ ip_fib_get_first_egress_ip_for_dst (lisp_cp_main_t * lcm, ip_address_t * dst,
 static int
 dp_add_del_iface (lisp_cp_main_t * lcm, u32 vni, u8 is_l2, u8 is_add)
 {
-  uword *dp_table, *intf;
-  vnet_lisp_gpe_add_del_iface_args_t _ai, *ai = &_ai;
+  uword *dp_table;
 
   if (!is_l2)
     {
@@ -190,38 +191,20 @@ dp_add_del_iface (lisp_cp_main_t * lcm, u32 vni, u8 is_l2, u8 is_add)
        }
     }
 
-  intf = hash_get (is_l2 ? lcm->l2_dp_intf_by_vni : lcm->dp_intf_by_vni, vni);
-
   /* enable/disable data-plane interface */
   if (is_add)
     {
-      /* create interface */
-      if (!intf)
-       {
-         ai->is_add = 1;
-         ai->vni = vni;
-         ai->is_l2 = is_l2;
-         ai->dp_table = dp_table[0];
-
-         vnet_lisp_gpe_add_del_iface (ai, 0);
-
-         /* keep track of vnis for which interfaces have been created */
-         hash_set (lcm->dp_intf_by_vni, vni, 1);
-       }
+      if (is_l2)
+       lisp_gpe_tenant_l2_iface_add_or_lock (vni, dp_table[0]);
+      else
+       lisp_gpe_tenant_l3_iface_add_or_lock (vni, dp_table[0]);
     }
   else
     {
-      if (intf == 0)
-       {
-         clib_warning ("interface for vni %d doesn't exist!", vni);
-         return VNET_API_ERROR_INVALID_VALUE;
-       }
-
-      ai->is_add = 0;
-      ai->vni = vni;
-      ai->dp_table = dp_table[0];
-      vnet_lisp_gpe_add_del_iface (ai, 0);
-      hash_unset (lcm->dp_intf_by_vni, vni);
+      if (is_l2)
+       lisp_gpe_tenant_l2_iface_unlock (vni);
+      else
+       lisp_gpe_tenant_l3_iface_unlock (vni);
     }
 
   return 0;
@@ -385,7 +368,7 @@ dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
   u32 sw_if_index;
   uword *feip = 0, *dpid;
   fwd_entry_t *fe;
-  u8 type;
+  u8 type, is_src_dst = 0;
 
   memset (a, 0, sizeof (*a));
 
@@ -394,7 +377,10 @@ dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
   if (feip)
     dp_del_fwd_entry (lcm, src_map_index, dst_map_index);
 
-  src_map = pool_elt_at_index (lcm->mapping_pool, src_map_index);
+  if (lcm->lisp_pitr)
+    src_map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
+  else
+    src_map = pool_elt_at_index (lcm->mapping_pool, src_map_index);
   dst_map = pool_elt_at_index (lcm->mapping_pool, dst_map_index);
 
   /* insert data plane forwarding entry */
@@ -406,6 +392,7 @@ dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
                              &gid_address_sd_dst (&dst_map->eid));
       gid_address_sd_to_flat (&a->lcl_eid, &dst_map->eid,
                              &gid_address_sd_src (&dst_map->eid));
+      is_src_dst = 1;
     }
   else
     gid_address_copy (&a->rmt_eid, &dst_map->eid);
@@ -454,10 +441,94 @@ dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
   pool_get (lcm->fwd_entry_pool, fe);
   fe->locator_pairs = a->locator_pairs;
   gid_address_copy (&fe->reid, &a->rmt_eid);
+  gid_address_copy (&fe->leid, &src_map->eid);
+  fe->is_src_dst = is_src_dst;
   hash_set (lcm->fwd_entry_by_mapping_index, dst_map_index,
            fe - lcm->fwd_entry_pool);
 }
 
+/**
+ * Returns vector of adjacencies.
+ *
+ * The caller must free the vector returned by this function.
+ *
+ * @param vni virtual network identifier
+ * @return vector of adjacencies
+ */
+lisp_adjacency_t *
+vnet_lisp_adjacencies_get_by_vni (u32 vni)
+{
+  lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+  fwd_entry_t *fwd;
+  lisp_adjacency_t *adjs = 0, adj;
+
+  /* *INDENT-OFF* */
+  pool_foreach(fwd, lcm->fwd_entry_pool,
+  ({
+    if (gid_address_vni (&fwd->reid) != vni)
+      continue;
+
+    gid_address_copy (&adj.reid, &fwd->reid);
+    gid_address_copy (&adj.leid, &fwd->leid);
+    vec_add1 (adjs, adj);
+  }));
+  /* *INDENT-ON* */
+
+  return adjs;
+}
+
+static clib_error_t *
+lisp_show_adjacencies_command_fn (vlib_main_t * vm,
+                                 unformat_input_t * input,
+                                 vlib_cli_command_t * cmd)
+{
+  lisp_adjacency_t *adjs, *adj;
+  vlib_cli_output (vm, "%s %40s\n", "leid", "reid");
+  unformat_input_t _line_input, *line_input = &_line_input;
+  u32 vni = ~0;
+
+  /* Get a line of input. */
+  if (!unformat_user (input, unformat_line_input, line_input))
+    return 0;
+
+  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (line_input, "vni %d", &vni))
+       ;
+      else
+       {
+         vlib_cli_output (vm, "parse error: '%U'",
+                          format_unformat_error, line_input);
+         return 0;
+       }
+    }
+
+  if (~0 == vni)
+    {
+      vlib_cli_output (vm, "error: no vni specified!");
+      return 0;
+    }
+
+  adjs = vnet_lisp_adjacencies_get_by_vni (vni);
+
+  vec_foreach (adj, adjs)
+  {
+    vlib_cli_output (vm, "%U %40U\n", format_gid_address, &adj->leid,
+                    format_gid_address, &adj->reid);
+  }
+  vec_free (adjs);
+
+  return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (lisp_show_adjacencies_command) = {
+    .path = "show lisp adjacencies",
+    .short_help = "show lisp adjacencies",
+    .function = lisp_show_adjacencies_command_fn,
+};
+/* *INDENT-ON* */
+
 /**
  * Add/remove mapping to/from map-cache. Overwriting not allowed.
  */
@@ -991,7 +1062,8 @@ lisp_add_del_adjacency (lisp_cp_main_t * lcm, gid_address_t * local_eid,
       return VNET_API_ERROR_LISP_DISABLED;
     }
 
-  remote_mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, remote_eid);
+  remote_mi = gid_dictionary_sd_lookup (&lcm->mapping_index_by_gid,
+                                       remote_eid, local_eid);
   if (GID_LOOKUP_MISS == remote_mi)
     {
       clib_warning ("Remote eid %U not found. Cannot add adjacency!",
@@ -2038,7 +2110,6 @@ vnet_lisp_enable_disable (u8 is_enable)
   else
     {
       /* clear interface table */
-      hash_free (lcm->dp_intf_by_vni);
       hash_free (lcm->fwd_entry_by_mapping_index);
       pool_free (lcm->fwd_entry_pool);
     }
@@ -2559,7 +2630,7 @@ lisp_add_del_mreq_itr_rlocs_command_fn (vlib_main_t * vm,
     {
       if (unformat (line_input, "del"))
        is_add = 0;
-      else if (unformat (line_input, "add %s", &locator_set_name))
+      else if (unformat (line_input, "add %_%v%_", &locator_set_name))
        is_add = 1;
       else
        {
@@ -2644,8 +2715,6 @@ typedef enum
 typedef enum
 {
   LISP_CP_LOOKUP_NEXT_DROP,
-  LISP_CP_LOOKUP_NEXT_IP4_LOOKUP,
-  LISP_CP_LOOKUP_NEXT_IP6_LOOKUP,
   LISP_CP_LOOKUP_N_NEXT,
 } lisp_cp_lookup_next_t;
 
@@ -3204,6 +3273,13 @@ lisp_cp_lookup_ip6 (vlib_main_t * vm,
   return (lisp_cp_lookup_inline (vm, node, from_frame, LISP_AFI_IP6));
 }
 
+static uword
+lisp_cp_lookup_l2 (vlib_main_t * vm,
+                  vlib_node_runtime_t * node, vlib_frame_t * from_frame)
+{
+  return (lisp_cp_lookup_inline (vm, node, from_frame, LISP_AFI_MAC));
+}
+
 /* *INDENT-OFF* */
 VLIB_REGISTER_NODE (lisp_cp_lookup_ip4_node) = {
   .function = lisp_cp_lookup_ip4,
@@ -3219,8 +3295,6 @@ VLIB_REGISTER_NODE (lisp_cp_lookup_ip4_node) = {
 
   .next_nodes = {
       [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
-      [LISP_CP_LOOKUP_NEXT_IP4_LOOKUP] = "ip4-lookup",
-      [LISP_CP_LOOKUP_NEXT_IP6_LOOKUP] = "ip6-lookup",
   },
 };
 /* *INDENT-ON* */
@@ -3240,8 +3314,25 @@ VLIB_REGISTER_NODE (lisp_cp_lookup_ip6_node) = {
 
   .next_nodes = {
       [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
-      [LISP_CP_LOOKUP_NEXT_IP4_LOOKUP] = "ip4-lookup",
-      [LISP_CP_LOOKUP_NEXT_IP6_LOOKUP] = "ip6-lookup",
+  },
+};
+/* *INDENT-ON* */
+
+/* *INDENT-OFF* */
+VLIB_REGISTER_NODE (lisp_cp_lookup_l2_node) = {
+  .function = lisp_cp_lookup_l2,
+  .name = "lisp-cp-lookup-l2",
+  .vector_size = sizeof (u32),
+  .format_trace = format_lisp_cp_lookup_trace,
+  .type = VLIB_NODE_TYPE_INTERNAL,
+
+  .n_errors = LISP_CP_LOOKUP_N_ERROR,
+  .error_strings = lisp_cp_lookup_error_strings,
+
+  .n_next_nodes = LISP_CP_LOOKUP_N_NEXT,
+
+  .next_nodes = {
+      [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
   },
 };
 /* *INDENT-ON* */
@@ -3557,14 +3648,17 @@ send_map_request_thread_fn (void *arg)
   map_request_args_t *a = arg;
   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
 
-  lisp_pending_map_request_lock (lcm);
-
   if (a->is_resend)
+    /* if resending, we already have the lock */
     resend_encapsulated_map_request (lcm, &a->seid, &a->deid, a->smr_invoked);
   else
-    send_encapsulated_map_request (lcm, &a->seid, &a->deid, a->smr_invoked);
+    {
+      /* get lock before sending map-request */
+      lisp_pending_map_request_lock (lcm);
+      send_encapsulated_map_request (lcm, &a->seid, &a->deid, a->smr_invoked);
+      lisp_pending_map_request_unlock (lcm);
+    }
 
-  lisp_pending_map_request_unlock (lcm);
 
   return 0;
 }