Fix vnet unit tests
[vpp.git] / src / vnet / lisp-cp / control.c
index c7853ca..c009330 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>
 
@@ -43,13 +44,6 @@ typedef struct
   u8 smr_invoked;
 } map_request_args_t;
 
-typedef struct
-{
-  u64 nonce;
-  u8 is_rloc_probe;
-  mapping_t *mappings;
-} map_records_arg_t;
-
 u8
 vnet_lisp_get_map_request_mode (void)
 {
@@ -284,6 +278,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_gpe_del_fwd_counters (a, feip[0]);
   vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
 
   /* delete entry in fwd table */
@@ -487,6 +482,7 @@ dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
     gid_address_copy (&a->rmt_eid, rmt_eid);
 
   a->vni = gid_address_vni (&a->rmt_eid);
+  a->is_src_dst = is_src_dst;
 
   /* get vrf or bd_index associated to vni */
   type = gid_address_type (&a->rmt_eid);
@@ -529,10 +525,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);
 
@@ -863,11 +867,11 @@ vnet_lisp_eid_table_map (u32 vni, u32 dp_id, u8 is_l2, u8 is_add)
                        "mapping!", vni, dp_id);
          return -1;
        }
-      hash_unset (dp_table_by_vni[0], vni);
-      hash_unset (vni_by_dp_table[0], dp_id);
-
       /* remove dp iface */
       dp_add_del_iface (lcm, vni, is_l2, 0);
+
+      hash_unset (dp_table_by_vni[0], vni);
+      hash_unset (vni_by_dp_table[0], dp_id);
     }
   return 0;
 
@@ -1228,9 +1232,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 :
@@ -1346,6 +1347,7 @@ vnet_lisp_use_petr (ip_address_t * ip, u8 is_add)
   if (is_add)
     {
       /* Create dummy petr locator-set */
+      memset (&loc, 0, sizeof (loc));
       gid_address_from_ip (&loc.address, ip);
       loc.priority = 1;
       loc.state = loc.weight = 1;
@@ -1468,6 +1470,58 @@ is_locator_in_locator_set (lisp_cp_main_t * lcm, locator_set_t * ls,
   return 0;
 }
 
+static void
+update_adjacencies_by_map_index (lisp_cp_main_t * lcm, u8 is_local,
+                                u32 mapping_index, u8 remove_only)
+{
+  fwd_entry_t *fwd;
+  mapping_t *map;
+  vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
+
+  map = pool_elt_at_index (lcm->mapping_pool, mapping_index);
+
+  /* *INDENT-OFF* */
+  pool_foreach(fwd, lcm->fwd_entry_pool,
+  ({
+    if ((is_local && 0 == gid_address_cmp (&map->eid, &fwd->leid)) ||
+        (!is_local && 0 == gid_address_cmp (&map->eid, &fwd->reid)))
+      {
+        a->is_add = 0;
+        gid_address_copy (&a->leid, &fwd->leid);
+        gid_address_copy (&a->reid, &fwd->reid);
+
+        vnet_lisp_add_del_adjacency (a);
+
+        if (!remove_only)
+          {
+            a->is_add = 1;
+            vnet_lisp_add_del_adjacency (a);
+          }
+      }
+    }));
+  /* *INDENT-ON* */
+}
+
+static void
+update_fwd_entries_by_locator_set (lisp_cp_main_t * lcm, u8 is_local,
+                                  u32 ls_index, u8 remove_only)
+{
+  u32 i, *map_indexp;
+  u32 **eid_indexes;
+
+  if (vec_len (lcm->locator_set_to_eids) <= ls_index)
+    return;
+
+  eid_indexes = vec_elt_at_index (lcm->locator_set_to_eids, ls_index);
+
+  for (i = 0; i < vec_len (eid_indexes[0]); i++)
+    {
+      map_indexp = vec_elt_at_index (eid_indexes[0], i);
+      update_adjacencies_by_map_index (lcm, is_local, map_indexp[0],
+                                      remove_only);
+    }
+}
+
 static inline void
 remove_locator_from_locator_set (locator_set_t * ls, u32 * locit,
                                 u32 ls_index, u32 loc_id)
@@ -1550,24 +1604,38 @@ vnet_lisp_add_del_locator (vnet_lisp_add_del_locator_set_args_t * a,
   else
     {
       ls_index = p[0];
+      u8 removed;
 
-      itloc = a->locators;
-      loc_id = 0;
-      vec_foreach (locit, ls->locator_indices)
+      vec_foreach (itloc, a->locators)
       {
-       loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
+       removed = 0;
+       loc_id = 0;
+       vec_foreach (locit, ls->locator_indices)
+       {
+         loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
 
-       if (loc->local && loc->sw_if_index == itloc->sw_if_index)
-         {
-           remove_locator_from_locator_set (ls, locit, ls_index, loc_id);
-         }
-       if (0 == loc->local &&
-           !gid_address_cmp (&loc->address, &itloc->address))
-         {
-           remove_locator_from_locator_set (ls, locit, ls_index, loc_id);
-         }
+         if (loc->local && loc->sw_if_index == itloc->sw_if_index)
+           {
+             removed = 1;
+             remove_locator_from_locator_set (ls, locit, ls_index, loc_id);
+           }
+         if (0 == loc->local &&
+             !gid_address_cmp (&loc->address, &itloc->address))
+           {
+             removed = 1;
+             remove_locator_from_locator_set (ls, locit, ls_index, loc_id);
+           }
 
-       loc_id++;
+         if (removed)
+           {
+             /* update fwd entries using this locator in DP */
+             update_fwd_entries_by_locator_set (lcm, loc->local, ls_index,
+                                                vec_len (ls->locator_indices)
+                                                == 0);
+           }
+
+         loc_id++;
+       }
       }
     }
 
@@ -2653,16 +2721,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)
     {
@@ -2741,10 +2808,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 */
@@ -3412,7 +3478,7 @@ done:
   vec_free (itr_rlocs);
 }
 
-static map_records_arg_t *
+map_records_arg_t *
 parse_map_reply (vlib_buffer_t * b)
 {
   locator_t probed;
@@ -3428,6 +3494,11 @@ parse_map_reply (vlib_buffer_t * b)
   mrep_hdr = vlib_buffer_get_current (b);
   a->nonce = MREP_NONCE (mrep_hdr);
   a->is_rloc_probe = MREP_RLOC_PROBE (mrep_hdr);
+  if (!vlib_buffer_has_space (b, sizeof (*mrep_hdr)))
+    {
+      clib_mem_free (a);
+      return 0;
+    }
   vlib_buffer_pull (b, sizeof (*mrep_hdr));
 
   for (i = 0; i < MREP_REC_COUNT (mrep_hdr); i++)
@@ -3604,6 +3675,56 @@ 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)
+{
+  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;
+
+  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;
+
+  vlib_get_combined_counter (cm, stats_index, &v);
+  stat->counters = v;
+  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)
 {
@@ -3809,7 +3930,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;
 }
 
@@ -3821,7 +3946,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* */