-static void
-del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index,
- u32 dst_map_index)
-{
- vnet_lisp_gpe_add_del_fwd_entry_args_t _a, * a = &_a;
- fwd_entry_t * fe = 0;
- uword * feip = 0;
- memset(a, 0, sizeof(*a));
-
- feip = hash_get(lcm->fwd_entry_by_mapping_index, dst_map_index);
- if (!feip)
- return;
-
- fe = pool_elt_at_index(lcm->fwd_entry_pool, feip[0]);
-
- /* delete dp fwd entry */
- u32 sw_if_index;
- a->is_add = 0;
- a->dlocator = fe->dst_loc;
- a->slocator = fe->src_loc;
- a->vni = gid_address_vni(&a->deid);
- gid_address_copy(&a->deid, &fe->deid);
-
- vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
-
- /* delete entry in fwd table */
- hash_unset(lcm->fwd_entry_by_mapping_index, dst_map_index);
- pool_put(lcm->fwd_entry_pool, fe);
-}
-
-/**
- * Finds first remote locator with best (lowest) priority that has a local
- * peer locator with an underlying route to it.
- *
- */
-static u32
-get_locator_pair (lisp_cp_main_t* lcm, mapping_t * lcl_map, mapping_t * rmt_map,
- ip_address_t * lcl_loc, ip_address_t * rmt_loc)
-{
- u32 i, minp = ~0, limitp = 0, li, check_index = 0, done = 0, esi;
- locator_set_t * rmt_ls, * lcl_ls;
- ip_address_t _lcl, * lcl = &_lcl;
- locator_t * l, * rmt = 0;
- uword * checked = 0;
-
- rmt_ls = pool_elt_at_index(lcm->locator_set_pool, rmt_map->locator_set_index);
- lcl_ls = pool_elt_at_index(lcm->locator_set_pool, lcl_map->locator_set_index);
-
- if (!rmt_ls || vec_len(rmt_ls->locator_indices) == 0)
- return 0;
-
- while (!done)
- {
- /* find unvisited remote locator with best priority */
- for (i = 0; i < vec_len(rmt_ls->locator_indices); i++)
- {
- if (0 != hash_get(checked, i))
- continue;
-
- li = vec_elt(rmt_ls->locator_indices, i);
- l = pool_elt_at_index(lcm->locator_pool, li);
-
- /* we don't support non-IP locators for now */
- if (gid_address_type(&l->address) != GID_ADDR_IP_PREFIX)
- continue;
-
- if (l->priority < minp && l->priority >= limitp)
- {
- minp = l->priority;
- rmt = l;
- check_index = i;
- }
- }
- /* check if a local locator with a route to remote locator exists */
- if (rmt != 0)
- {
- esi = ip_fib_get_egress_iface_for_dst (
- lcm, &gid_address_ip(&rmt->address));
- if ((u32) ~0 == esi)
- continue;
-
- for (i = 0; i < vec_len(lcl_ls->locator_indices); i++)
- {
- li = vec_elt (lcl_ls->locator_indices, i);
- locator_t * sl = pool_elt_at_index (lcm->locator_pool, li);
-
- /* found local locator */
- if (sl->sw_if_index == esi)
- {
- if (0 == ip_interface_get_first_ip_address (lcm,
- sl->sw_if_index,
- gid_address_ip_version(&rmt->address), lcl))
- continue;
-
- ip_address_copy(rmt_loc, &gid_address_ip(&rmt->address));
- ip_address_copy(lcl_loc, lcl);
- done = 2;
- }
- }
-
- /* skip this remote locator in next searches */
- limitp = minp;
- hash_set(checked, check_index, 1);
- }
- else
- done = 1;
- }
- hash_free(checked);
- return (done == 2) ? 1 : 0;
-}
-
-static void
-add_fwd_entry (lisp_cp_main_t* lcm, u32 src_map_index, u32 dst_map_index)
-{
- mapping_t * src_map, * dst_map;
- u32 sw_if_index;
- uword * feip = 0, * tidp;
- fwd_entry_t* fe;
- vnet_lisp_gpe_add_del_fwd_entry_args_t _a, * a = &_a;
-
- memset (a, 0, sizeof(*a));
-
- /* remove entry if it already exists */
- feip = hash_get (lcm->fwd_entry_by_mapping_index, dst_map_index);
- if (feip)
- del_fwd_entry (lcm, src_map_index, dst_map_index);
-
- src_map = pool_elt_at_index (lcm->mapping_pool, src_map_index);
- dst_map = pool_elt_at_index (lcm->mapping_pool, dst_map_index);
-
- gid_address_copy (&a->deid, &dst_map->eid);
- a->vni = gid_address_vni(&a->deid);
-
- tidp = hash_get(lcm->table_id_by_vni, a->vni);
- if (!tidp)
- {
- clib_warning("vni %d not associated to a vrf!", a->vni);
- return;
- }
- a->table_id = tidp[0];
-
- /* insert data plane forwarding entry */
- a->is_add = 1;
-
- /* find best locator pair that 1) verifies LISP policy 2) are connected */
- if (0 == get_locator_pair (lcm, src_map, dst_map, &a->slocator, &a->dlocator))
- {
- /* negative entry */
- a->is_negative = 1;
- a->action = dst_map->action;
- }
-
- /* TODO remove */
- u8 ipver = ip_prefix_version(&gid_address_ippref(&a->deid));
- a->decap_next_index = (ipver == IP4) ?
- LISP_GPE_INPUT_NEXT_IP4_INPUT : LISP_GPE_INPUT_NEXT_IP6_INPUT;
-
- vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
-
- /* add tunnel to fwd entry table XXX check return value from DP insertion */
- pool_get (lcm->fwd_entry_pool, fe);
- fe->dst_loc = a->dlocator;
- fe->src_loc = a->slocator;
- gid_address_copy (&fe->deid, &a->deid);
- hash_set (lcm->fwd_entry_by_mapping_index, dst_map_index,
- fe - lcm->fwd_entry_pool);
-}
-
-/* return 0 if the two locator sets are identical 1 otherwise */
-static u8
-compare_locators (lisp_cp_main_t *lcm, u32 * old_ls_indexes,
- locator_t * new_locators)