LISP: re-fetch mapping before it expires 48/8048/4
authorFilip Tehlar <ftehlar@cisco.com>
Mon, 14 Aug 2017 17:15:36 +0000 (19:15 +0200)
committerFilip Tehlar <ftehlar@cisco.com>
Mon, 4 Sep 2017 10:13:55 +0000 (12:13 +0200)
Change-Id: I0581a1bddad55d8d573c546ec84b0b2760abab3d
Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
src/vnet/lisp-cp/control.c
src/vnet/lisp-cp/control.h
src/vnet/lisp-cp/lisp_api.c
src/vnet/lisp-cp/lisp_cli.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_fwd_entry.c
src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h
src/vnet/lisp-gpe/lisp_gpe_sub_interface.c

index 59a45ed..c811e78 100644 (file)
 
 #define MAX_VALUE_U24 0xffffff
 
+/* mapping timer control constants (in seconds) */
+#define TIME_UNTIL_REFETCH_OR_DELETE  20
+#define MAPPING_TIMEOUT (((m->ttl) * 60) - TIME_UNTIL_REFETCH_OR_DELETE)
+
 lisp_cp_main_t lisp_control_main;
 
 u8 *format_lisp_cp_input_trace (u8 * s, va_list * args);
+static void *send_map_request_thread_fn (void *arg);
 
 typedef enum
 {
@@ -1102,7 +1107,7 @@ remove_overlapping_sub_prefixes (lisp_cp_main_t * lcm, gid_address_t * eid,
     if (vnet_lisp_add_del_adjacency (adj_args))
       clib_warning ("failed to del adjacency!");
 
-    vnet_lisp_add_del_mapping (e, 0, 0, 0, 0, 0 /* is add */ , 0, 0);
+    vnet_lisp_del_mapping (e, NULL);
   }
 
   vec_free (a.eids_to_be_deleted);
@@ -1129,24 +1134,19 @@ is_local_ip (lisp_cp_main_t * lcm, ip_address_t * addr)
 }
 
 /**
- * Adds/removes/updates mapping. Does not program forwarding.
+ * Adds/updates mapping. Does not program forwarding.
  *
- * @param eid end-host identifier
+ * @param a parameters of the new mapping
  * @param rlocs vector of remote locators
- * @param action action for negative map-reply
- * @param is_add add mapping if non-zero, delete otherwise
- * @param res_map_index the map-index that was created/updated/removed. It is
- *                      set to ~0 if no action is taken.
- * @param is_static used for distinguishing between statically learned
-                    remote mappings and mappings obtained from MR
+ * @param res_map_index index of the newly created mapping
+ * @param locators_changed indicator if locators were updated in the mapping
  * @return return code
  */
 int
-vnet_lisp_add_del_mapping (gid_address_t * eid, locator_t * rlocs, u8 action,
-                          u8 authoritative, u32 ttl, u8 is_add, u8 is_static,
-                          u32 * res_map_index)
+vnet_lisp_add_mapping (vnet_lisp_add_del_mapping_args_t * a,
+                      locator_t * rlocs,
+                      u32 * res_map_index, u8 * is_updated)
 {
-  vnet_lisp_add_del_mapping_args_t _m_args, *m_args = &_m_args;
   vnet_lisp_add_del_locator_set_args_t _ls_args, *ls_args = &_ls_args;
   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
   u32 mi, ls_index = 0, dst_map_index;
@@ -1161,115 +1161,138 @@ vnet_lisp_add_del_mapping (gid_address_t * eid, locator_t * rlocs, u8 action,
 
   if (res_map_index)
     res_map_index[0] = ~0;
+  if (is_updated)
+    is_updated[0] = 0;
 
-  memset (m_args, 0, sizeof (m_args[0]));
   memset (ls_args, 0, sizeof (ls_args[0]));
 
   ls_args->locators = rlocs;
-
-  mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid);
+  mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &a->eid);
   old_map = ((u32) ~ 0 != mi) ? pool_elt_at_index (lcm->mapping_pool, mi) : 0;
 
-  if (is_add)
-    {
-      /* check if none of the locators match localy configured address */
-      vec_foreach (loc, rlocs)
+  /* check if none of the locators match localy configured address */
+  vec_foreach (loc, rlocs)
+  {
+    ip_prefix_t *p = &gid_address_ippref (&loc->address);
+    if (is_local_ip (lcm, &ip_prefix_addr (p)))
       {
-       ip_prefix_t *p = &gid_address_ippref (&loc->address);
-       if (is_local_ip (lcm, &ip_prefix_addr (p)))
-         {
-           clib_warning ("RLOC %U matches a local address!",
-                         format_gid_address, &loc->address);
-           return VNET_API_ERROR_LISP_RLOC_LOCAL;
-         }
+       clib_warning ("RLOC %U matches a local address!",
+                     format_gid_address, &loc->address);
+       return VNET_API_ERROR_LISP_RLOC_LOCAL;
       }
+  }
 
-      /* overwrite: if mapping already exists, decide if locators should be
-       * updated and be done */
-      if (old_map && gid_address_cmp (&old_map->eid, eid) == 0)
+  /* overwrite: if mapping already exists, decide if locators should be
+   * updated and be done */
+  if (old_map && gid_address_cmp (&old_map->eid, &a->eid) == 0)
+    {
+      if (!a->is_static && (old_map->is_static || old_map->local))
        {
-         if (!is_static && (old_map->is_static || old_map->local))
-           {
-             /* do not overwrite local or static remote mappings */
-             clib_warning ("mapping %U rejected due to collision with local "
-                           "or static remote mapping!", format_gid_address,
-                           eid);
-             return 0;
-           }
-
-         locator_set_t *old_ls;
-
-         /* update mapping attributes */
-         old_map->action = action;
-         old_map->authoritative = authoritative;
-         old_map->ttl = ttl;
-
-         old_ls = pool_elt_at_index (lcm->locator_set_pool,
-                                     old_map->locator_set_index);
-         if (compare_locators (lcm, old_ls->locator_indices,
-                               ls_args->locators))
-           {
-             /* set locator-set index to overwrite */
-             ls_args->is_add = 1;
-             ls_args->index = old_map->locator_set_index;
-             vnet_lisp_add_del_locator_set (ls_args, 0);
-             if (res_map_index)
-               res_map_index[0] = mi;
-           }
+         /* do not overwrite local or static remote mappings */
+         clib_warning ("mapping %U rejected due to collision with local "
+                       "or static remote mapping!", format_gid_address,
+                       &a->eid);
+         return 0;
        }
-      /* new mapping */
-      else
-       {
-         remove_overlapping_sub_prefixes (lcm, eid, 0 == ls_args->locators);
 
-         ls_args->is_add = 1;
-         ls_args->index = ~0;
+      locator_set_t *old_ls;
 
-         vnet_lisp_add_del_locator_set (ls_args, &ls_index);
+      /* update mapping attributes */
+      old_map->action = a->action;
+      if (old_map->action != a->action && NULL != is_updated)
+       is_updated[0] = 1;
 
-         /* add mapping */
-         gid_address_copy (&m_args->eid, eid);
-         m_args->is_add = 1;
-         m_args->action = action;
-         m_args->locator_set_index = ls_index;
-         m_args->is_static = is_static;
-         m_args->ttl = ttl;
-         vnet_lisp_map_cache_add_del (m_args, &dst_map_index);
+      old_map->authoritative = a->authoritative;
+      old_map->ttl = a->ttl;
 
-         if (res_map_index)
-           res_map_index[0] = dst_map_index;
+      old_ls = pool_elt_at_index (lcm->locator_set_pool,
+                                 old_map->locator_set_index);
+      if (compare_locators (lcm, old_ls->locator_indices, ls_args->locators))
+       {
+         /* set locator-set index to overwrite */
+         ls_args->is_add = 1;
+         ls_args->index = old_map->locator_set_index;
+         vnet_lisp_add_del_locator_set (ls_args, 0);
+         if (is_updated)
+           is_updated[0] = 1;
        }
+      if (res_map_index)
+       res_map_index[0] = mi;
     }
+  /* new mapping */
   else
     {
-      if (old_map == 0 || gid_address_cmp (&old_map->eid, eid) != 0)
-       {
-         clib_warning ("cannot delete mapping for eid %U",
-                       format_gid_address, eid);
-         return -1;
-       }
-
-      m_args->is_add = 0;
-      gid_address_copy (&m_args->eid, eid);
-      m_args->locator_set_index = old_map->locator_set_index;
+      remove_overlapping_sub_prefixes (lcm, &a->eid, 0 == ls_args->locators);
 
-      /* delete mapping associated from map-cache */
-      vnet_lisp_map_cache_add_del (m_args, 0);
+      ls_args->is_add = 1;
+      ls_args->index = ~0;
 
-      ls_args->is_add = 0;
-      ls_args->index = old_map->locator_set_index;
-      /* delete locator set */
-      vnet_lisp_add_del_locator_set (ls_args, 0);
+      vnet_lisp_add_del_locator_set (ls_args, &ls_index);
 
-      /* delete timer associated to the mapping if any */
-      if (old_map->timer_set)
-       mapping_delete_timer (lcm, mi);
+      /* add mapping */
+      a->is_add = 1;
+      a->locator_set_index = ls_index;
+      vnet_lisp_map_cache_add_del (a, &dst_map_index);
 
-      /* return old mapping index */
       if (res_map_index)
-       res_map_index[0] = mi;
+       res_map_index[0] = dst_map_index;
+    }
+
+  /* success */
+  return 0;
+}
+
+/**
+ * Removes a mapping. Does not program forwarding.
+ *
+ * @param eid end-host indetifier
+ * @param res_map_index index of the removed mapping
+ * @return return code
+ */
+int
+vnet_lisp_del_mapping (gid_address_t * eid, u32 * res_map_index)
+{
+  lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+  vnet_lisp_add_del_mapping_args_t _m_args, *m_args = &_m_args;
+  vnet_lisp_add_del_locator_set_args_t _ls_args, *ls_args = &_ls_args;
+  mapping_t *old_map;
+  u32 mi;
+
+  memset (m_args, 0, sizeof (m_args[0]));
+  if (res_map_index)
+    res_map_index[0] = ~0;
+
+  mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid);
+  old_map = ((u32) ~ 0 != mi) ? pool_elt_at_index (lcm->mapping_pool, mi) : 0;
+
+  if (old_map == 0 || gid_address_cmp (&old_map->eid, eid) != 0)
+    {
+      clib_warning ("cannot delete mapping for eid %U",
+                   format_gid_address, eid);
+      return -1;
     }
 
+  m_args->is_add = 0;
+  gid_address_copy (&m_args->eid, eid);
+  m_args->locator_set_index = old_map->locator_set_index;
+
+  /* delete mapping associated from map-cache */
+  vnet_lisp_map_cache_add_del (m_args, 0);
+
+  ls_args->is_add = 0;
+  ls_args->index = old_map->locator_set_index;
+
+  /* delete locator set */
+  vnet_lisp_add_del_locator_set (ls_args, 0);
+
+  /* delete timer associated to the mapping if any */
+  if (old_map->timer_set)
+    mapping_delete_timer (lcm, mi);
+
+  /* return old mapping index */
+  if (res_map_index)
+    res_map_index[0] = mi;
+
   /* success */
   return 0;
 }
@@ -3372,8 +3395,7 @@ remove_expired_mapping (lisp_cp_main_t * lcm, u32 mi)
   if (vnet_lisp_add_del_adjacency (adj_args))
     clib_warning ("failed to del adjacency!");
 
-  vnet_lisp_add_del_mapping (&m->eid, 0, 0, 0, ~0, 0 /* is_add */ ,
-                            0 /* is_static */ , 0);
+  vnet_lisp_del_mapping (&m->eid, NULL);
   mapping_delete_timer (lcm, mi);
 }
 
@@ -3392,6 +3414,73 @@ mapping_start_expiration_timer (lisp_cp_main_t * lcm, u32 mi,
   timing_wheel_insert (&lcm->wheel, exp_clock_time, mi);
 }
 
+static void
+process_expired_mapping (lisp_cp_main_t * lcm, u32 mi)
+{
+  int rv;
+  vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a;
+  mapping_t *m = pool_elt_at_index (lcm->mapping_pool, mi);
+  uword *fei;
+  fwd_entry_t *fe;
+  vlib_counter_t c;
+  u8 have_stats = 0;
+
+  if (m->delete_after_expiration)
+    {
+      remove_expired_mapping (lcm, mi);
+      return;
+    }
+
+  fei = hash_get (lcm->fwd_entry_by_mapping_index, mi);
+  if (!fei)
+    return;
+
+  fe = pool_elt_at_index (lcm->fwd_entry_pool, fei[0]);
+
+  memset (a, 0, sizeof (*a));
+  a->rmt_eid = fe->reid;
+  if (fe->is_src_dst)
+    a->lcl_eid = fe->leid;
+  a->vni = gid_address_vni (&fe->reid);
+
+  rv = vnet_lisp_gpe_get_fwd_stats (a, &c);
+  if (0 == rv)
+    have_stats = 1;
+
+  if (m->almost_expired)
+    {
+      m->almost_expired = 0;   /* reset flag */
+      if (have_stats)
+       {
+         if (m->packets != c.packets)
+           {
+             /* mapping is in use, re-fetch */
+             map_request_args_t mr_args;
+             memset (&mr_args, 0, sizeof (mr_args));
+             mr_args.seid = fe->leid;
+             mr_args.deid = fe->reid;
+
+             send_map_request_thread_fn (&mr_args);
+           }
+         else
+           remove_expired_mapping (lcm, mi);
+       }
+      else
+       remove_expired_mapping (lcm, mi);
+    }
+  else
+    {
+      m->almost_expired = 1;
+      mapping_start_expiration_timer (lcm, mi, TIME_UNTIL_REFETCH_OR_DELETE);
+
+      if (have_stats)
+       /* save counter */
+       m->packets = c.packets;
+      else
+       m->delete_after_expiration = 1;
+    }
+}
+
 static void
 map_records_arg_free (map_records_arg_t * a)
 {
@@ -3414,6 +3503,7 @@ process_map_reply (map_records_arg_t * a)
   pending_map_request_t *pmr;
   u64 *noncep;
   uword *pmr_index;
+  u8 is_changed = 0;
 
   if (a->is_rloc_probe)
     goto done;
@@ -3429,26 +3519,36 @@ process_map_reply (map_records_arg_t * a)
 
   vec_foreach (m, a->mappings)
   {
+    vnet_lisp_add_del_mapping_args_t _m_args, *m_args = &_m_args;
+    memset (m_args, 0, sizeof (m_args[0]));
+    gid_address_copy (&m_args->eid, &m->eid);
+    m_args->action = m->action;
+    m_args->authoritative = m->authoritative;
+    m_args->ttl = m->ttl;
+    m_args->is_static = 0;
+
     /* insert/update mappings cache */
-    vnet_lisp_add_del_mapping (&m->eid, m->locators, m->action,
-                              m->authoritative, m->ttl,
-                              1, 0 /* is_static */ , &dst_map_index);
+    vnet_lisp_add_mapping (m_args, m->locators, &dst_map_index, &is_changed);
 
     if (dst_map_index == (u32) ~ 0)
       continue;
 
-    /* try to program forwarding only if mapping saved or updated */
-    vnet_lisp_add_del_adjacency_args_t _adj_args, *adj_args = &_adj_args;
-    memset (adj_args, 0, sizeof (adj_args[0]));
+    if (is_changed)
+      {
+       /* try to program forwarding only if mapping saved or updated */
+       vnet_lisp_add_del_adjacency_args_t _adj_args, *adj_args = &_adj_args;
+       memset (adj_args, 0, sizeof (adj_args[0]));
 
-    gid_address_copy (&adj_args->leid, &pmr->src);
-    gid_address_copy (&adj_args->reid, &m->eid);
-    adj_args->is_add = 1;
-    if (vnet_lisp_add_del_adjacency (adj_args))
-      clib_warning ("failed to add adjacency!");
+       gid_address_copy (&adj_args->leid, &pmr->src);
+       gid_address_copy (&adj_args->reid, &m->eid);
+       adj_args->is_add = 1;
+
+       if (vnet_lisp_add_del_adjacency (adj_args))
+         clib_warning ("failed to add adjacency!");
+      }
 
     if ((u32) ~ 0 != m->ttl)
-      mapping_start_expiration_timer (lcm, dst_map_index, m->ttl * 60);
+      mapping_start_expiration_timer (lcm, dst_map_index, MAPPING_TIMEOUT);
   }
 
   /* remove pending map request entry */
@@ -4379,7 +4479,7 @@ send_map_resolver_service (vlib_main_t * vm,
          u32 *mi = 0;
          vec_foreach (mi, expired)
          {
-           remove_expired_mapping (lcm, mi[0]);
+           process_expired_mapping (lcm, mi[0]);
          }
          _vec_len (expired) = 0;
        }
index 7b0380f..a3e2fc2 100644 (file)
@@ -329,9 +329,11 @@ vnet_lisp_add_del_local_mapping (vnet_lisp_add_del_mapping_args_t * a,
                                 u32 * map_index_result);
 
 int
-vnet_lisp_add_del_mapping (gid_address_t * deid, locator_t * dlocs, u8 action,
-                          u8 authoritative, u32 ttl, u8 is_add, u8 is_static,
-                          u32 * res_map_index);
+vnet_lisp_add_mapping (vnet_lisp_add_del_mapping_args_t * a,
+                      locator_t * rlocs, u32 * res_map_index,
+                      u8 * is_changed);
+
+int vnet_lisp_del_mapping (gid_address_t * eid, u32 * res_map_index);
 
 typedef struct
 {
index 6c82d4c..f7c4197 100644 (file)
@@ -521,8 +521,19 @@ static void
 
   /* NOTE: for now this works as a static remote mapping, i.e.,
    * not authoritative and ttl infinite. */
-  rv = vnet_lisp_add_del_mapping (eid, rlocs, mp->action, 0, ~0,
-                                 mp->is_add, 1 /* is_static */ , 0);
+  if (mp->is_add)
+    {
+      vnet_lisp_add_del_mapping_args_t _m_args, *m_args = &_m_args;
+      memset (m_args, 0, sizeof (m_args[0]));
+      gid_address_copy (&m_args->eid, eid);
+      m_args->action = mp->action;
+      m_args->is_static = 1;
+      m_args->ttl = ~0;
+      m_args->authoritative = 0;
+      rv = vnet_lisp_add_mapping (m_args, rlocs, NULL, NULL);
+    }
+  else
+    rv = vnet_lisp_del_mapping (eid, NULL);
 
   if (mp->del_all)
     vnet_lisp_clear_all_remote_adjacencies ();
index 05df9fb..5090460 100644 (file)
@@ -394,8 +394,19 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
 
   /* add as static remote mapping, i.e., not authoritative and infinite
    * ttl */
-  rv = vnet_lisp_add_del_mapping (&eid, rlocs, action, 0, ~0, is_add,
-                                 1 /* is_static */ , 0);
+  if (is_add)
+    {
+      vnet_lisp_add_del_mapping_args_t _map_args, *map_args = &_map_args;
+      memset (map_args, 0, sizeof (map_args[0]));
+      gid_address_copy (&map_args->eid, &eid);
+      map_args->action = action;
+      map_args->is_static = 1;
+      map_args->authoritative = 0;
+      map_args->ttl = ~0;
+      rv = vnet_lisp_add_mapping (map_args, rlocs, NULL, NULL);
+    }
+  else
+    rv = vnet_lisp_del_mapping (&eid, NULL);
 
   if (rv)
     clib_warning ("failed to %s remote mapping!", is_add ? "add" : "delete");
index b7ad0f2..b17110f 100644 (file)
@@ -358,12 +358,14 @@ typedef struct
   u8 is_static:1;
   u8 pitr_set:1;
   u8 nsh_set:1;
-  u8 rsvd:3;
-
+  u8 almost_expired:1;
+  u8 delete_after_expiration:1;
+  u8 rsvd:1;
 
   u8 *key;
   lisp_key_type_t key_id;
   u8 timer_set;
+  counter_t packets;
 } mapping_t;
 
 uword
index 620d56f..b8e3f70 100644 (file)
@@ -620,8 +620,19 @@ static void
 
   /* NOTE: for now this works as a static remote mapping, i.e.,
    * not authoritative and ttl infinite. */
-  rv = vnet_lisp_add_del_mapping (eid, rlocs, mp->action, 0, ~0,
-                                 mp->is_add, 1 /* is_static */ , 0);
+  if (mp->is_add)
+    {
+      vnet_lisp_add_del_mapping_args_t _m_args, *m_args = &_m_args;
+      memset (m_args, 0, sizeof (m_args[0]));
+      gid_address_copy (&m_args->eid, eid);
+      m_args->action = mp->action;
+      m_args->is_static = 1;
+      m_args->ttl = ~0;
+      m_args->authoritative = 0;
+      rv = vnet_lisp_add_mapping (m_args, rlocs, NULL, NULL);
+    }
+  else
+    rv = vnet_lisp_del_mapping (eid, NULL);
 
   if (mp->del_all)
     vnet_lisp_clear_all_remote_adjacencies ();
index e165f71..3e0c4c0 100644 (file)
@@ -487,8 +487,19 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
 
   /* add as static remote mapping, i.e., not authoritative and infinite
    * ttl */
-  rv = vnet_lisp_add_del_mapping (&eid, rlocs, action, 0, ~0, is_add,
-                                 1 /* is_static */ , 0);
+  if (is_add)
+    {
+      vnet_lisp_add_del_mapping_args_t _map_args, *map_args = &_map_args;
+      memset (map_args, 0, sizeof (map_args[0]));
+      gid_address_copy (&map_args->eid, &eid);
+      map_args->action = action;
+      map_args->is_static = 1;
+      map_args->authoritative = 0;
+      map_args->ttl = ~0;
+      rv = vnet_lisp_add_mapping (map_args, rlocs, NULL, NULL);
+    }
+  else
+    rv = vnet_lisp_del_mapping (&eid, NULL);
 
   if (rv)
     clib_warning ("failed to %s remote mapping!", is_add ? "add" : "delete");
index ac04814..d7d3cb8 100644 (file)
@@ -193,12 +193,15 @@ ip_src_dst_fib_del_route (u32 src_fib_index,
  * @param[in]   src_fib_index   The index/ID of the SRC FIB
  * @param[in]   src_prefix      Source IP prefix.
  * @param[in]   src_dpo         The DPO the route will link to.
+ *
+ * @return fib index of the inserted prefix
  */
-static void
+static fib_node_index_t
 ip_src_fib_add_route_w_dpo (u32 src_fib_index,
                            const ip_prefix_t * src_prefix,
                            const dpo_id_t * src_dpo)
 {
+  fib_node_index_t fei = ~0;
   fib_prefix_t src_fib_prefix;
 
   ip_prefix_to_fib_prefix (src_prefix, &src_fib_prefix);
@@ -213,11 +216,13 @@ ip_src_fib_add_route_w_dpo (u32 src_fib_index,
   if (FIB_NODE_INDEX_INVALID == src_fei ||
       !fib_entry_is_sourced (src_fei, FIB_SOURCE_LISP))
     {
-      fib_table_entry_special_dpo_add (src_fib_index,
-                                      &src_fib_prefix,
-                                      FIB_SOURCE_LISP,
-                                      FIB_ENTRY_FLAG_EXCLUSIVE, src_dpo);
+      fei = fib_table_entry_special_dpo_add (src_fib_index,
+                                            &src_fib_prefix,
+                                            FIB_SOURCE_LISP,
+                                            FIB_ENTRY_FLAG_EXCLUSIVE,
+                                            src_dpo);
     }
+  return fei;
 }
 
 static fib_route_path_t *
@@ -262,7 +267,7 @@ lisp_gpe_mk_fib_paths (const lisp_fwd_path_t * paths)
  * @param[in]   paths           The paths from which to construct the
  *                              load balance
  */
-static void
+static fib_node_index_t
 ip_src_fib_add_route (u32 src_fib_index,
                      const ip_prefix_t * src_prefix,
                      const lisp_fwd_path_t * paths)
@@ -274,10 +279,11 @@ ip_src_fib_add_route (u32 src_fib_index,
 
   rpaths = lisp_gpe_mk_fib_paths (paths);
 
-  fib_table_entry_update (src_fib_index,
-                         &src_fib_prefix,
-                         FIB_SOURCE_LISP, FIB_ENTRY_FLAG_NONE, rpaths);
+  fib_node_index_t fib_entry_index =
+    fib_table_entry_update (src_fib_index, &src_fib_prefix, FIB_SOURCE_LISP,
+                           FIB_ENTRY_FLAG_NONE, rpaths);
   vec_free (rpaths);
+  return fib_entry_index;
 }
 
 static void
@@ -311,9 +317,11 @@ gpe_native_fwd_add_del_lfe (lisp_gpe_fwd_entry_t * lfe, u8 is_add)
     }
 }
 
-static void
+static index_t
 create_fib_entries (lisp_gpe_fwd_entry_t * lfe)
 {
+  fib_node_index_t fi;
+  fib_entry_t *fe;
   lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
   dpo_proto_t dproto;
   ip_prefix_t ippref;
@@ -361,13 +369,15 @@ create_fib_entries (lisp_gpe_fwd_entry_t * lfe)
          dpo_copy (&dpo, drop_dpo_get (dproto));
          break;
        }
-      ip_src_fib_add_route_w_dpo (lfe->src_fib_index, &ippref, &dpo);
+      fi = ip_src_fib_add_route_w_dpo (lfe->src_fib_index, &ippref, &dpo);
       dpo_reset (&dpo);
     }
   else
     {
-      ip_src_fib_add_route (lfe->src_fib_index, &ippref, lfe->paths);
+      fi = ip_src_fib_add_route (lfe->src_fib_index, &ippref, lfe->paths);
     }
+  fe = fib_entry_get (fi);
+  return fe->fe_lb.dpoi_index;
 }
 
 static void
@@ -546,7 +556,7 @@ add_ip_fwd_entry (lisp_gpe_main_t * lgm,
       lfe->action = a->action;
     }
 
-  create_fib_entries (lfe);
+  lfe->dpoi_index = create_fib_entries (lfe);
   return (0);
 }
 
@@ -793,6 +803,7 @@ lisp_gpe_l2_update_fwding (lisp_gpe_fwd_entry_t * lfe)
   lisp_l2_fib_add_del_entry (lfe->l2.eid_bd_index,
                             fid_addr_mac (&lfe->key->lcl),
                             fid_addr_mac (&lfe->key->rmt), &dpo, 1);
+  lfe->dpoi_index = dpo.dpoi_index;
 
   dpo_reset (&dpo);
 }
@@ -1538,6 +1549,29 @@ vnet_lisp_gpe_fwd_entries_get_by_vni (u32 vni)
   return entries;
 }
 
+int
+vnet_lisp_gpe_get_fwd_stats (vnet_lisp_gpe_add_del_fwd_entry_args_t * a,
+                            vlib_counter_t * c)
+{
+  lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
+  lisp_gpe_fwd_entry_t *lfe;
+  lisp_gpe_fwd_entry_key_t unused;
+
+  lfe = find_fwd_entry (lgm, a, &unused);
+  if (NULL == lfe)
+    return -1;
+
+  if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE == lfe->type)
+    return -1;
+
+  if (~0 == lfe->dpoi_index)
+    return -1;
+
+  vlib_get_combined_counter (&load_balance_main.lbm_to_counters,
+                            lfe->dpoi_index, c);
+  return 0;
+}
+
 VLIB_INIT_FUNCTION (lisp_gpe_fwd_entry_init);
 
 /*
index 1580351..dfdb8b9 100644 (file)
@@ -198,6 +198,12 @@ typedef struct lisp_gpe_fwd_entry_t_
      */
     negative_fwd_actions_e action;
   };
+
+  /**
+   * used for getting load balance statistics
+   */
+  index_t dpoi_index;
+
 } lisp_gpe_fwd_entry_t;
 
 extern int
@@ -219,6 +225,10 @@ vnet_lisp_gpe_add_fwd_counters (vnet_lisp_gpe_add_del_fwd_entry_args_t * a,
                                u32 fwd_entry_index);
 extern u32 *vnet_lisp_gpe_get_fwd_entry_vnis (void);
 
+int
+vnet_lisp_gpe_get_fwd_stats (vnet_lisp_gpe_add_del_fwd_entry_args_t * a,
+                            vlib_counter_t * c);
+
 #endif
 
 /*
index 7146b38..b234d9d 100644 (file)
@@ -192,7 +192,7 @@ lisp_gpe_sub_interface_unlock (index_t l3si)
       lisp_gpe_sub_interface_unset_table (l3s->sw_if_index,
                                          l3s->eid_table_id);
 
-      lisp_gpe_tenant_l3_iface_unlock (clib_net_to_host_u32 (l3s->key->vni));
+      lisp_gpe_tenant_l3_iface_unlock (l3s->key->vni);
       vnet_sw_interface_set_flags (vnet_get_main (), l3s->sw_if_index, 0);
       vnet_delete_sub_interface (l3s->sw_if_index);