LISP: improve updating the dataplne when locators change
[vpp.git] / src / vnet / lisp-cp / control.c
index aeea72c..907e9a0 100644 (file)
@@ -1823,39 +1823,70 @@ is_locator_in_locator_set (lisp_cp_main_t * lcm, locator_set_t * ls,
 }
 
 static void
-update_adjacencies_by_map_index (lisp_cp_main_t * lcm, u8 is_local,
+update_adjacencies_by_map_index (lisp_cp_main_t * lcm,
                                 u32 mapping_index, u8 remove_only)
 {
   fwd_entry_t *fwd;
   mapping_t *map;
+  uword *fei = 0, *rmts_idxp = 0;
+  u32 **rmts = 0, *remote_idxp = 0, *rmts_copy = 0;
   vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
+  memset (a, 0, sizeof (*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);
+  if (map->local)
+    {
+      rmts_idxp = hash_get (lcm->lcl_to_rmt_adjs_by_lcl_idx, mapping_index);
+      if (rmts_idxp)
+       {
+         rmts =
+           pool_elt_at_index (lcm->lcl_to_rmt_adjacencies, rmts_idxp[0]);
+         rmts_copy = vec_dup (rmts[0]);
 
-        vnet_lisp_add_del_adjacency (a);
+         vec_foreach (remote_idxp, rmts_copy)
+         {
+           fei = hash_get (lcm->fwd_entry_by_mapping_index, remote_idxp[0]);
+           if (!fei)
+             continue;
 
-        if (!remove_only)
-          {
-            a->is_add = 1;
-            vnet_lisp_add_del_adjacency (a);
-          }
-      }
-    }));
-  /* *INDENT-ON* */
+           fwd = pool_elt_at_index (lcm->fwd_entry_pool, fei[0]);
+           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);
+             }
+         }
+         vec_free (rmts_copy);
+       }
+    }
+  else
+    {
+      fei = hash_get (lcm->fwd_entry_by_mapping_index, mapping_index);
+      if (!fei)
+       return;
+
+      fwd = pool_elt_at_index (lcm->fwd_entry_pool, fei[0]);
+      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);
+       }
+    }
 }
 
 static void
-update_fwd_entries_by_locator_set (lisp_cp_main_t * lcm, u8 is_local,
+update_fwd_entries_by_locator_set (lisp_cp_main_t * lcm,
                                   u32 ls_index, u8 remove_only)
 {
   u32 i, *map_indexp;
@@ -1869,8 +1900,7 @@ update_fwd_entries_by_locator_set (lisp_cp_main_t * lcm, u8 is_local,
   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);
+      update_adjacencies_by_map_index (lcm, map_indexp[0], remove_only);
     }
 }
 
@@ -1981,7 +2011,7 @@ vnet_lisp_add_del_locator (vnet_lisp_add_del_locator_set_args_t * a,
          if (removed)
            {
              /* update fwd entries using this locator in DP */
-             update_fwd_entries_by_locator_set (lcm, loc->local, ls_index,
+             update_fwd_entries_by_locator_set (lcm, ls_index,
                                                 vec_len (ls->locator_indices)
                                                 == 0);
            }