-ip_interface_address_t *
-ip_interface_get_first_interface_address (ip_lookup_main_t *lm, u32 sw_if_index,
- u8 loop)
-{
- vnet_main_t *vnm = vnet_get_main ();
- vnet_sw_interface_t * swif = vnet_get_sw_interface (vnm, sw_if_index);
- if (loop && swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
- sw_if_index = swif->unnumbered_sw_if_index;
- u32 ia =
- (vec_len((lm)->if_address_pool_index_by_sw_if_index) > (sw_if_index)) ?
- vec_elt((lm)->if_address_pool_index_by_sw_if_index, (sw_if_index)) :
- (u32) ~0;
- return pool_elt_at_index((lm)->if_address_pool, ia);
-}
-
-int
-ip_interface_get_first_ip_addres (lisp_cp_main_t * lcm, u32 sw_if_index,
- u8 version, ip_address_t * addr)
-{
- if (version == IP4)
- {
- ip4_address_t * l4;
- ip_lookup_main_t * lm = &lcm->im4->lookup_main;
- ip_interface_address_t * ia = ip_interface_get_first_interface_address (
- lm, sw_if_index, 1 /* unnumbered */);
-
- if (!ia)
- return 0;
-
- l4 = ip_interface_address_get_address (lm, ia);
-
- if (!l4)
- return 0;
-
- ip_addr_v4(addr) = *l4;
- ip_addr_version(addr) = IP4;
- }
- else
- {
- ip6_address_t * l6;
- ip_lookup_main_t * lm = &lcm->im6->lookup_main;
- ip_interface_address_t * ia = ip_interface_get_first_interface_address (
- lm, sw_if_index, 1 /* unnumbered */);
- if (!ia)
- return 0;
-
- l6 = ip_interface_address_get_address (lm, ia);
- if (!l6)
- return 0;
-
- ip_addr_v6(addr) = *l6;
- ip_addr_version(addr) = IP6;
- }
- return 1;
-}
-
-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, rv, 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 = 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)
- {
- rv = ip_interface_get_first_ip_addres (lcm, sl->sw_if_index,
- gid_address_ip_version(&rmt->address), lcl);
-
- if (!rv)
- 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)
-{
- u32 i, old_li;
- locator_t * old_loc, * new_loc;
-
- if (vec_len (old_ls_indexes) != vec_len(new_locators))
- return 1;
-
- for (i = 0; i < vec_len(new_locators); i++)
- {
- old_li = vec_elt(old_ls_indexes, i);
- old_loc = pool_elt_at_index(lcm->locator_pool, old_li);
-
- new_loc = vec_elt_at_index(new_locators, i);
-
- if (locator_cmp (old_loc, new_loc))
- return 1;
- }
- return 0;
-}
-