summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--vnet/vnet/lisp-cp/control.c1455
-rw-r--r--vnet/vnet/lisp-cp/control.h53
-rw-r--r--vnet/vnet/lisp-cp/gid_dictionary.c2
-rw-r--r--vnet/vnet/lisp-cp/lisp_msg_serdes.c9
-rw-r--r--vnet/vnet/lisp-cp/lisp_types.c2
-rw-r--r--vnet/vnet/lisp-cp/lisp_types.h2
-rw-r--r--vnet/vnet/lisp-gpe/decap.c12
-rw-r--r--vpp-api-test/vat/api_format.c145
-rw-r--r--vpp/vpp-api/api.c155
-rw-r--r--vpp/vpp-api/vpe.api40
10 files changed, 1111 insertions, 764 deletions
diff --git a/vnet/vnet/lisp-cp/control.c b/vnet/vnet/lisp-cp/control.c
index a820b9cd28f..00317cd871e 100644
--- a/vnet/vnet/lisp-cp/control.c
+++ b/vnet/vnet/lisp-cp/control.c
@@ -18,49 +18,381 @@
#include <vnet/lisp-cp/lisp_msg_serdes.h>
#include <vnet/lisp-gpe/lisp_gpe.h>
+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);
+}
+
+void *
+ip_interface_get_first_address (ip_lookup_main_t * lm, u32 sw_if_index,
+ u8 version)
+{
+ ip_interface_address_t * ia;
+
+ ia = ip_interface_get_first_interface_address (lm, sw_if_index, 1);
+ if (!ia)
+ return 0;
+ return ip_interface_address_get_address (lm, ia);
+}
+
+int
+ip_interface_get_first_ip_address (lisp_cp_main_t * lcm, u32 sw_if_index,
+ u8 version, ip_address_t * result)
+{
+ ip_lookup_main_t * lm;
+ void * addr;
+
+ lm = (version == IP4) ? &lcm->im4->lookup_main : &lcm->im6->lookup_main;
+ addr = ip_interface_get_first_address (lm, sw_if_index, version);
+ if (!addr)
+ return 0;
+
+ ip_address_set (result, addr, version);
+ return 1;
+}
+
+static u32
+ip_fib_lookup_with_table (lisp_cp_main_t * lcm, u32 fib_index,
+ ip_address_t * dst)
+{
+ if (ip_addr_version (dst) == IP4)
+ return ip4_fib_lookup_with_table (lcm->im4, fib_index, &ip_addr_v4(dst),
+ 0);
+ else
+ return ip6_fib_lookup_with_table (lcm->im6, fib_index, &ip_addr_v6(dst));
+}
+
+u32
+ip_fib_get_egress_iface_for_dst_with_lm (lisp_cp_main_t * lcm,
+ ip_address_t * dst,
+ ip_lookup_main_t * lm)
+{
+ u32 adj_index;
+ ip_adjacency_t * adj;
+
+ adj_index = ip_fib_lookup_with_table (lcm, 0, dst);
+ adj = ip_get_adjacency (lm, adj_index);
+
+ if (adj == 0)
+ return ~0;
+
+ /* we only want outgoing routes */
+ if (adj->lookup_next_index != IP_LOOKUP_NEXT_ARP
+ && adj->lookup_next_index != IP_LOOKUP_NEXT_REWRITE)
+ return ~0;
+
+ return adj->rewrite_header.sw_if_index;
+}
+
+/**
+ * Find the sw_if_index of the interface that would be used to egress towards
+ * dst.
+ */
+u32
+ip_fib_get_egress_iface_for_dst (lisp_cp_main_t * lcm, ip_address_t * dst)
+{
+ ip_lookup_main_t * lm;
+
+ lm = ip_addr_version (dst) == IP4 ?
+ &lcm->im4->lookup_main : &lcm->im6->lookup_main;
+
+ return ip_fib_get_egress_iface_for_dst_with_lm (lcm, dst, lm);
+}
+
+/**
+ * Find first IP of the interface that would be used to egress towards dst.
+ * Returns 1 if the address is found 0 otherwise.
+ */
+int
+ip_fib_get_first_egress_ip_for_dst (lisp_cp_main_t * lcm, ip_address_t * dst,
+ ip_address_t * result)
+{
+ u32 si;
+ ip_lookup_main_t * lm;
+ void * addr = 0;
+ u8 ipver;
+
+ ASSERT(result != 0);
+
+ ipver = ip_addr_version(dst);
+
+ lm = (ipver == IP4) ? &lcm->im4->lookup_main : &lcm->im6->lookup_main;
+ si = ip_fib_get_egress_iface_for_dst_with_lm (lcm, dst, lm);
+
+ if ((u32) ~0 == si)
+ return 0;
+
+ /* find the first ip address */
+ addr = ip_interface_get_first_address (lm, si, ipver);
+ if (0 == addr)
+ return 0;
+
+ ip_address_set (result, addr, ipver);
+ return 1;
+}
+
+static int
+dp_add_del_iface (lisp_cp_main_t * lcm, u32 vni, u8 is_add)
+{
+ uword * table_id, * intf;
+ vnet_lisp_gpe_add_del_iface_args_t _ai, *ai = &_ai;
+
+ table_id = hash_get(lcm->table_id_by_vni, vni);
+
+ if (!table_id)
+ {
+ clib_warning ("vni %d not associated to a vrf!", vni);
+ return VNET_API_ERROR_INVALID_VALUE;
+ }
+
+ intf = hash_get(lcm->dp_intf_by_vni, vni);
+
+ /* enable/disable data-plane interface */
+ if (is_add)
+ {
+ /* create interface */
+ if (!intf)
+ {
+ ai->is_add = 1;
+ ai->vni = vni;
+ ai->table_id = table_id[0];
+ vnet_lisp_gpe_add_del_iface (ai, 0);
+
+ /* keep track of vnis for which interfaces have been created */
+ hash_set(lcm->dp_intf_by_vni, vni, 1);
+ }
+ }
+ else
+ {
+ if (intf == 0)
+ {
+ clib_warning("interface for vni %d doesn't exist!", vni);
+ return VNET_API_ERROR_INVALID_VALUE;
+ }
+
+ ai->is_add = 0;
+ ai->vni = vni;
+ ai->table_id = table_id[0];
+ vnet_lisp_gpe_add_del_iface (ai, 0);
+ hash_unset(lcm->dp_intf_by_vni, vni);
+ }
+
+ return 0;
+}
+
static void
-add_fwd_entry (lisp_cp_main_t* lcm, u32 src_map_index, u32 dst_map_index);
+dp_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)
+ {
+ rmt = 0;
+
+ /* 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
-del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index);
+dp_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;
-static u8
-compare_locators (lisp_cp_main_t *lcm, u32 * old_ls_indexes,
- locator_t * new_locators);
+ 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)
+ dp_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);
+}
-/* Stores mapping in map-cache. It does NOT program data plane forwarding for
- * remote/learned mappings. */
+/**
+ * Add/remove mapping to/from map-cache. Overwriting not allowed.
+ */
int
-vnet_lisp_add_del_mapping (vnet_lisp_add_del_mapping_args_t * a,
- u32 * map_index_result)
+vnet_lisp_map_cache_add_del (vnet_lisp_add_del_mapping_args_t * a,
+ u32 * map_index_result)
{
lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
u32 mi, * map_indexp, map_index, i;
mapping_t * m, * old_map;
u32 ** eid_indexes;
- mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &a->deid);
+ mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &a->eid);
old_map = mi != ~0 ? pool_elt_at_index (lcm->mapping_pool, mi) : 0;
if (a->is_add)
{
/* TODO check if overwriting and take appropriate actions */
if (mi != GID_LOOKUP_MISS && !gid_address_cmp (&old_map->eid,
- &a->deid))
+ &a->eid))
{
clib_warning ("eid %U found in the eid-table", format_gid_address,
- &a->deid);
+ &a->eid);
return VNET_API_ERROR_VALUE_EXIST;
}
pool_get(lcm->mapping_pool, m);
- gid_address_copy (&m->eid, &a->deid);
+ gid_address_copy (&m->eid, &a->eid);
m->locator_set_index = a->locator_set_index;
m->ttl = a->ttl;
m->action = a->action;
m->local = a->local;
map_index = m - lcm->mapping_pool;
- gid_dictionary_add_del (&lcm->mapping_index_by_gid, &a->deid, map_index,
+ gid_dictionary_add_del (&lcm->mapping_index_by_gid, &a->eid, map_index,
1);
if (pool_is_free_index(lcm->locator_set_pool, a->locator_set_index))
@@ -88,7 +420,7 @@ vnet_lisp_add_del_mapping (vnet_lisp_add_del_mapping_args_t * a,
if (mi == GID_LOOKUP_MISS)
{
clib_warning("eid %U not found in the eid-table", format_gid_address,
- &a->deid);
+ &a->eid);
return VNET_API_ERROR_INVALID_VALUE;
}
@@ -116,13 +448,9 @@ vnet_lisp_add_del_mapping (vnet_lisp_add_del_mapping_args_t * a,
}
vec_del1(lcm->local_mappings_indexes, k);
}
- else
- {
- /* remove tunnel ??? */
- }
/* remove mapping from dictionary */
- gid_dictionary_add_del (&lcm->mapping_index_by_gid, &a->deid, 0, 0);
+ gid_dictionary_add_del (&lcm->mapping_index_by_gid, &a->eid, 0, 0);
gid_address_free (&m->eid);
pool_put_index (lcm->mapping_pool, mi);
}
@@ -130,14 +458,16 @@ vnet_lisp_add_del_mapping (vnet_lisp_add_del_mapping_args_t * a,
return 0;
}
-/* Stores mapping in map-cache and programs data plane for local mappings. */
+/**
+ * Add/update/delete mapping to/in/from map-cache.
+ */
int
vnet_lisp_add_del_local_mapping (vnet_lisp_add_del_mapping_args_t * a,
u32 * map_index_result)
{
- uword * table_id, * refc;
- u32 rv, vni;
- vnet_lisp_gpe_add_del_iface_args_t _ai, *ai = &_ai;
+ uword * table_id;
+ u32 vni;
+
lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
if (vnet_lisp_enable_disable_status () == 0)
@@ -146,13 +476,7 @@ vnet_lisp_add_del_local_mapping (vnet_lisp_add_del_mapping_args_t * a,
return VNET_API_ERROR_LISP_DISABLED;
}
- vni = gid_address_vni(&a->deid);
-
- /* store/remove mapping from map-cache */
- rv = vnet_lisp_add_del_mapping (a, map_index_result);
- if (rv)
- return rv;
-
+ vni = gid_address_vni(&a->eid);
table_id = hash_get(lcm->table_id_by_vni, vni);
if (!table_id)
@@ -161,45 +485,8 @@ vnet_lisp_add_del_local_mapping (vnet_lisp_add_del_mapping_args_t * a,
return VNET_API_ERROR_INVALID_VALUE;
}
- refc = hash_get(lcm->dp_if_refcount_by_vni, vni);
-
- /* enable/disable data-plane interface */
- if (a->is_add)
- {
- /* create interface or update refcount */
- if (!refc)
- {
- ai->is_add = 1;
- ai->vni = vni;
- ai->table_id = table_id[0];
- vnet_lisp_gpe_add_del_iface (ai, 0);
-
- /* counts the number of eids in a vni that use the interface */
- hash_set(lcm->dp_if_refcount_by_vni, vni, 1);
- }
- else
- {
- refc[0]++;
- }
- }
- else
- {
- /* since this is a remove for an existing eid, the iface should exist */
- ASSERT(refc != 0);
- refc[0]--;
-
- /* remove iface if needed */
- if (refc[0] == 0)
- {
- ai->is_add = 0;
- ai->vni = vni;
- ai->table_id = table_id[0];
- vnet_lisp_gpe_add_del_iface (ai, 0);
- hash_unset (lcm->dp_if_refcount_by_vni, vni);
- }
- }
-
- return rv;
+ /* store/remove mapping from map-cache */
+ return vnet_lisp_map_cache_add_del (a, map_index_result);
}
static clib_error_t *
@@ -263,7 +550,7 @@ lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input,
}
/* XXX treat batch configuration */
- a->deid = eid;
+ a->eid = eid;
a->is_add = is_add;
a->locator_set_index = locator_set_index;
a->local = 1;
@@ -271,14 +558,14 @@ lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input,
rv = vnet_lisp_add_del_local_mapping (a, &map_index);
if (0 != rv)
{
- error = clib_error_return(0, "failed to %s eid-table!",
+ error = clib_error_return(0, "failed to %s local mapping!",
is_add ? "add" : "delete");
}
done:
vec_free(eids);
if (locator_set_name)
vec_free (locator_set_name);
- gid_address_free (&a->deid);
+ gid_address_free (&a->eid);
return error;
}
@@ -320,6 +607,9 @@ vnet_lisp_eid_table_map (u32 vni, u32 vrf, u8 is_add)
}
hash_set (lcm->table_id_by_vni, vni, vrf);
hash_set (lcm->vni_by_table_id, vrf, vni);
+
+ /* create dp iface */
+ dp_add_del_iface (lcm, vni, 1);
}
else
{
@@ -331,6 +621,9 @@ vnet_lisp_eid_table_map (u32 vni, u32 vrf, u8 is_add)
}
hash_unset (lcm->table_id_by_vni, vni);
hash_unset (lcm->vni_by_table_id, vrf);
+
+ /* remove dp iface */
+ dp_add_del_iface (lcm, vni, 0);
}
return 0;
}
@@ -371,123 +664,50 @@ VLIB_CLI_COMMAND (lisp_eid_table_map_command) = {
.function = lisp_eid_table_map_command_fn,
};
-static int
-lisp_add_del_negative_static_mapping (gid_address_t * deid,
- vnet_lisp_add_del_locator_set_args_t * ls, u8 action, u8 is_add)
-{
- uword * p;
- mapping_t * map;
- u32 mi = ~0;
- lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
- uword * refc;
- vnet_lisp_add_del_mapping_args_t _dm_args, * dm_args = &_dm_args;
- int rv = 0;
- u32 ls_index = 0, dst_map_index;
- vnet_lisp_gpe_add_del_iface_args_t _ai, *ai = &_ai;
-
- memset (dm_args, 0, sizeof (dm_args[0]));
- u32 vni = gid_address_vni (deid);
- refc = hash_get (lcm->dp_if_refcount_by_vni, vni);
-
- p = hash_get (lcm->table_id_by_vni, vni);
- if (!p)
- {
- clib_warning ("vni %d not associated to a vrf!", vni);
- return VNET_API_ERROR_INVALID_VALUE;
- }
-
- if (is_add)
- {
- vnet_lisp_add_del_locator_set (ls, &ls_index);
- /* add mapping */
- gid_address_copy (&dm_args->deid, deid);
- dm_args->is_add = 1;
- dm_args->action = action;
- dm_args->locator_set_index = ls_index;
- /* create interface or update refcount */
- if (!refc)
- {
- vnet_lisp_gpe_add_del_iface_args_t _ai, *ai = &_ai;
- ai->is_add = 1;
- ai->vni = vni;
- ai->table_id = p[0];
- vnet_lisp_gpe_add_del_iface (ai, 0);
+/* 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;
- /* counts the number of eids in a vni that use the interface */
- hash_set (lcm->dp_if_refcount_by_vni, vni, 1);
- }
- else
- refc[0]++;
+ if (vec_len (old_ls_indexes) != vec_len(new_locators))
+ return 1;
- rv = vnet_lisp_add_del_local_mapping (dm_args, &dst_map_index);
- if (!rv)
- add_fwd_entry (lcm, lcm->pitr_map_index, dst_map_index);
- }
- else
+ for (i = 0; i < vec_len(new_locators); i++)
{
- mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, deid);
- if ((u32)~0 == mi)
- {
- clib_warning ("eid %U marked for removal, but not found in "
- "map-cache!", unformat_gid_address, deid);
- return VNET_API_ERROR_INVALID_VALUE;
- }
-
- /* delete forwarding entry */
- del_fwd_entry (lcm, 0, mi);
-
- dm_args->is_add = 0;
- gid_address_copy (&dm_args->deid, deid);
- map = pool_elt_at_index (lcm->mapping_pool, mi);
- dm_args->locator_set_index = map->locator_set_index;
-
- /* delete mapping associated to fwd entry */
- vnet_lisp_add_del_mapping (dm_args, 0);
+ old_li = vec_elt(old_ls_indexes, i);
+ old_loc = pool_elt_at_index(lcm->locator_pool, old_li);
- refc = hash_get (lcm->dp_if_refcount_by_vni, vni);
- ASSERT(refc != 0);
- refc[0]--;
+ new_loc = vec_elt_at_index(new_locators, i);
- /* remove iface if needed */
- if (refc[0] == 0)
- {
- ai->is_add = 0;
- ai->vni = vni;
- ai->table_id = p[0];
- vnet_lisp_gpe_add_del_iface (ai, 0);
- hash_unset (lcm->dp_if_refcount_by_vni, vni);
- }
+ if (locator_cmp (old_loc, new_loc))
+ return 1;
}
- return rv;
+ return 0;
}
/**
- * Adds/removes/updates static remote mapping.
- *
- * This function also modifies forwarding entries if needed.
+ * Adds/removes/updates mapping. Does not program forwarding.
*
* @param deid destination EID
- * @param seid source EID
* @param rlocs vector of remote locators
* @param action action for negative map-reply
* @param is_add add mapping if non-zero, delete otherwise
- * @param del_all if set, delete all remote mappings
* @return return code
*/
int
-vnet_lisp_add_del_remote_mapping (gid_address_t * deid, gid_address_t * seid,
- ip_address_t * rlocs, u8 action, u8 is_add,
- u8 del_all)
+vnet_lisp_add_del_mapping (gid_address_t * deid, locator_t * rlocs, u8 action,
+ u8 authoritative, u32 ttl, u8 is_add,
+ u32 * res_map_index)
{
- vnet_lisp_add_del_mapping_args_t _dm_args, * dm_args = &_dm_args;
- vnet_lisp_add_del_mapping_args_t _sm_args, * sm_args = &_sm_args;
- vnet_lisp_add_del_locator_set_args_t _ls, * ls = &_ls;
+ 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, src_map_index;
- locator_t loc;
- ip_address_t * dl;
- int rc = -1;
+ u32 mi, ls_index = 0, dst_map_index;
+ mapping_t * old_map;
if (vnet_lisp_enable_disable_status() == 0)
{
@@ -495,117 +715,90 @@ vnet_lisp_add_del_remote_mapping (gid_address_t * deid, gid_address_t * seid,
return VNET_API_ERROR_LISP_DISABLED;
}
- if (del_all)
- return vnet_lisp_clear_all_remote_mappings ();
+ if (res_map_index)
+ res_map_index[0] = ~0;
- memset (sm_args, 0, sizeof (sm_args[0]));
- memset (dm_args, 0, sizeof (dm_args[0]));
- memset (ls, 0, sizeof (ls[0]));
+ memset (m_args, 0, sizeof (m_args[0]));
+ memset (ls_args, 0, sizeof (ls_args[0]));
- /* prepare remote locator set */
- vec_foreach (dl, rlocs)
- {
- memset (&loc, 0, sizeof (loc));
- gid_address_ip (&loc.address) = dl[0];
- vec_add1 (ls->locators, loc);
- }
- src_map_index = gid_dictionary_lookup (&lcm->mapping_index_by_gid, seid);
+ ls_args->locators = rlocs;
mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, deid);
- /* new mapping */
- if ((u32)~0 == mi)
+ old_map = ((u32) ~0 != mi) ? pool_elt_at_index(lcm->mapping_pool, mi) : 0;
+
+ if (is_add)
{
- ls->is_add = 1;
- ls->index = ~0;
+ /* overwrite: if mapping already exists, decide if locators should be
+ * updated and be done */
+ if (old_map && gid_address_cmp (&old_map->eid, deid) == 0)
+ {
+ locator_set_t * old_ls;
- /* process a negative mapping */
- if (0 == vec_len (rlocs))
- return lisp_add_del_negative_static_mapping (deid, ls,
- action, is_add);
+ /* update mapping attributes */
+ old_map->action = action;
+ old_map->authoritative = authoritative;
+ old_map->ttl = ttl;
- if ((u32)~0 == src_map_index)
- {
- clib_warning ("seid %U not found!", format_gid_address, seid);
- goto done;
+ 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;
+ }
}
-
- if (!is_add)
+ /* new mapping */
+ else
{
- clib_warning ("deid %U marked for removal but not "
- "found!", format_gid_address, deid);
- goto done;
- }
+ ls_args->is_add = 1;
+ ls_args->index = ~0;
- vnet_lisp_add_del_locator_set (ls, &ls_index);
+ vnet_lisp_add_del_locator_set (ls_args, &ls_index);
- /* add mapping */
- gid_address_copy (&dm_args->deid, deid);
- dm_args->is_add = 1;
- dm_args->action = action;
- dm_args->locator_set_index = ls_index;
- vnet_lisp_add_del_mapping (dm_args, &dst_map_index);
+ /* add mapping */
+ gid_address_copy (&m_args->eid, deid);
+ m_args->is_add = 1;
+ m_args->action = action;
+ m_args->locator_set_index = ls_index;
+ vnet_lisp_map_cache_add_del (m_args, &dst_map_index);
- /* add fwd tunnel */
- add_fwd_entry (lcm, src_map_index, dst_map_index);
+ if (res_map_index)
+ res_map_index[0] = dst_map_index;
+ }
}
else
{
- /* delete mapping */
- if (!is_add)
+ if (old_map == 0 || gid_address_cmp (&old_map->eid, deid) != 0)
{
- /* delete forwarding entry */
- del_fwd_entry (lcm, 0, mi);
- dm_args->is_add = 0;
- gid_address_copy (&dm_args->deid, deid);
- mapping_t * map = pool_elt_at_index (lcm->mapping_pool, mi);
- dm_args->locator_set_index = map->locator_set_index;
-
- /* delete mapping associated to fwd entry */
- vnet_lisp_add_del_mapping (dm_args, 0);
-
- ls->is_add = 0;
- ls->index = map->locator_set_index;
- /* delete locator set */
- vnet_lisp_add_del_locator_set (ls, 0);
+ clib_warning("cannot delete mapping for eid %U", format_gid_address,
+ deid);
+ return -1;
}
- /* update existing locator set */
- else
- {
- if ((u32)~0 == src_map_index)
- {
- clib_warning ("seid %U not found!", format_gid_address, seid);
- goto done;
- }
- mapping_t * old_map;
- locator_set_t * old_ls;
- old_map = pool_elt_at_index (lcm->mapping_pool, mi);
+ m_args->is_add = 0;
+ gid_address_copy (&m_args->eid, deid);
+ m_args->locator_set_index = old_map->locator_set_index;
- /* update mapping attributes */
- old_map->action = action;
+ /* delete mapping associated from map-cache */
+ vnet_lisp_map_cache_add_del (m_args, 0);
- old_ls = pool_elt_at_index(lcm->locator_set_pool,
- old_map->locator_set_index);
- if (compare_locators (lcm, old_ls->locator_indices,
- ls->locators))
- {
- /* set locator-set index to overwrite */
- ls->is_add = 1;
- ls->index = old_map->locator_set_index;
- vnet_lisp_add_del_locator_set (ls, 0);
- add_fwd_entry (lcm, src_map_index, mi);
- }
- }
+ 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);
}
+
/* success */
- rc = 0;
-done:
- vec_free (ls->locators);
- return rc;
+ return 0;
}
int
-vnet_lisp_clear_all_remote_mappings (void)
+vnet_lisp_clear_all_remote_adjacencies (void)
{
int rv = 0;
u32 mi, * map_indices = 0, * map_indexp;
@@ -623,14 +816,14 @@ vnet_lisp_clear_all_remote_mappings (void)
mapping_t * map = pool_elt_at_index (lcm->mapping_pool, map_indexp[0]);
if (!map->local)
{
- del_fwd_entry (lcm, 0, map_indexp[0]);
+ dp_del_fwd_entry (lcm, 0, map_indexp[0]);
dm_args->is_add = 0;
- gid_address_copy (&dm_args->deid, &map->eid);
+ gid_address_copy (&dm_args->eid, &map->eid);
dm_args->locator_set_index = map->locator_set_index;
/* delete mapping associated to fwd entry */
- vnet_lisp_add_del_mapping (dm_args, 0);
+ vnet_lisp_map_cache_add_del (dm_args, 0);
ls->is_add = 0;
ls->local = 0;
@@ -649,6 +842,64 @@ cleanup:
}
/**
+ * Adds remote mapping and sets it as adjacency for local eid or removes
+ * forwarding entry associated to remote mapping. Note that adjacencies
+ * are not stored, they only result in forwarding entries being created.
+ */
+int
+lisp_add_del_adjacency (lisp_cp_main_t * lcm,
+ vnet_lisp_add_del_adjacency_args_t * a)
+{
+ u32 src_map_index, dst_map_index = ~0;
+
+ if (vnet_lisp_enable_disable_status () == 0)
+ {
+ clib_warning ("LISP is disabled!");
+ return VNET_API_ERROR_LISP_DISABLED;
+ }
+
+ /* insert/update mappings cache */
+ vnet_lisp_add_del_mapping (&a->deid, a->locators, a->action,
+ a->authoritative, a->ttl, a->is_add,
+ &dst_map_index);
+
+ 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 */
+ src_map_index = lcm->lisp_pitr ? lcm->pitr_map_index :
+ gid_dictionary_lookup (&lcm->mapping_index_by_gid, &a->seid);
+
+
+ if (GID_LOOKUP_MISS == src_map_index)
+ {
+ clib_warning("seid %U not found. Cannot program forwarding!",
+ format_gid_address, &a->seid);
+
+ return -1;
+ }
+
+ /* update forwarding if a destination mapping index was found */
+ if ((u32) ~0 != dst_map_index)
+ dp_add_fwd_entry (lcm, src_map_index, dst_map_index);
+ }
+ else
+ dp_del_fwd_entry (lcm, 0, dst_map_index);
+
+ return 0;
+}
+
+int
+vnet_lisp_add_del_adjacency (vnet_lisp_add_del_adjacency_args_t * a)
+{
+ lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
+ return lisp_add_del_adjacency(lcm, a);
+}
+
+/**
* Handler for add/del remote mapping CLI.
*
* @param vm vlib context
@@ -664,7 +915,7 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
clib_error_t * error = 0;
unformat_input_t _line_input, * line_input = &_line_input;
u8 is_add = 1, del_all = 0;
- ip_address_t rloc, * rlocs = 0;
+ locator_t rloc, * rlocs = 0;
ip_prefix_t * deid_ippref, * seid_ippref;
gid_address_t seid, deid;
u8 * dmac = gid_address_mac (&deid);
@@ -672,13 +923,15 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
u8 deid_set = 0, seid_set = 0;
u8 * s = 0;
u32 vni, action = ~0;
+ int rv;
/* Get a line of input. */
if (! unformat_user (input, unformat_line_input, line_input))
return 0;
- memset (&deid, 0, sizeof (deid));
- memset (&seid, 0, sizeof (seid));
+ memset(&deid, 0, sizeof(deid));
+ memset(&seid, 0, sizeof(seid));
+ memset(&rloc, 0, sizeof(rloc));
seid_ippref = &gid_address_ippref(&seid);
deid_ippref = &gid_address_ippref(&deid);
@@ -720,7 +973,7 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
gid_address_type (&seid) = GID_ADDR_MAC;
seid_set = 1;
}
- else if (unformat (line_input, "rloc %U", unformat_ip_address, &rloc))
+ else if (unformat (line_input, "rloc %U", unformat_ip_address, &rloc.address))
vec_add1 (rlocs, rloc);
else if (unformat (line_input, "action %s", &s))
{
@@ -778,12 +1031,32 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
goto done;
}
}
+ else
+ {
+ vnet_lisp_clear_all_remote_adjacencies ();
+ goto done;
+ }
+
+ /* TODO build src/dst with seid*/
+
+ /* if it's a delete, clean forwarding */
+ if (!is_add)
+ {
+ lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
+ vnet_lisp_add_del_adjacency_args_t _a, * a = &_a;
+ gid_address_copy(&a->deid, &deid);
+ a->is_add = 0;
+ rv = lisp_add_del_adjacency (lcm, a);
+ }
+ else
+ {
+ /* add as static remote mapping, i.e., not authoritative and infinite
+ * ttl */
+ rv = vnet_lisp_add_del_mapping (&deid, rlocs, action, 0, ~0, is_add, 0);
+ }
- int rv = vnet_lisp_add_del_remote_mapping (&deid, &seid, rlocs,
- action, is_add, del_all);
if (rv)
- clib_warning ("failed to %s remote mapping!",
- is_add ? "add" : "delete");
+ clib_warning("failed to %s remote mapping!", is_add ? "add" : "delete");
done:
unformat_free (line_input);
@@ -800,6 +1073,159 @@ VLIB_CLI_COMMAND (lisp_add_del_remote_mapping_command) = {
.function = lisp_add_del_remote_mapping_command_fn,
};
+/**
+ * Handler for add/del adjacency CLI.
+ */
+static clib_error_t *
+lisp_add_del_adjacency_command_fn (vlib_main_t * vm, unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ clib_error_t * error = 0;
+ unformat_input_t _line_input, * line_input = &_line_input;
+ vnet_lisp_add_del_adjacency_args_t _a, * a = &_a;
+ u8 is_add = 1;
+ locator_t rloc, * rlocs = 0;
+ ip_prefix_t * deid_ippref, * seid_ippref;
+ gid_address_t seid, deid;
+ u8 * dmac = gid_address_mac (&deid);
+ u8 * smac = gid_address_mac (&seid);
+ u8 deid_set = 0, seid_set = 0;
+ u8 * s = 0;
+ u32 vni, action = ~0;
+ int rv;
+
+ /* Get a line of input. */
+ if (! unformat_user (input, unformat_line_input, line_input))
+ return 0;
+
+ memset(&deid, 0, sizeof(deid));
+ memset(&seid, 0, sizeof(seid));
+ memset(&rloc, 0, sizeof(rloc));
+
+ seid_ippref = &gid_address_ippref(&seid);
+ deid_ippref = &gid_address_ippref(&deid);
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "del"))
+ is_add = 0;
+ else if (unformat (line_input, "add"))
+ ;
+ else if (unformat (line_input, "deid %U",
+ unformat_ip_prefix, deid_ippref))
+ {
+ gid_address_type (&deid) = GID_ADDR_IP_PREFIX;
+ deid_set = 1;
+ }
+ else if (unformat (line_input, "deid %U",
+ unformat_mac_address, dmac))
+ {
+ gid_address_type (&deid) = GID_ADDR_MAC;
+ deid_set = 1;
+ }
+ else if (unformat (line_input, "vni %u", &vni))
+ {
+ gid_address_vni (&seid) = vni;
+ gid_address_vni (&deid) = vni;
+ }
+ else if (unformat (line_input, "seid %U",
+ unformat_ip_prefix, seid_ippref))
+ {
+ gid_address_type (&seid) = GID_ADDR_IP_PREFIX;
+ seid_set = 1;
+ }
+ else if (unformat (line_input, "seid %U",
+ unformat_mac_address, smac))
+ {
+ gid_address_type (&seid) = GID_ADDR_MAC;
+ seid_set = 1;
+ }
+ else if (unformat (line_input, "rloc %U", unformat_ip_address, &rloc.address))
+ vec_add1 (rlocs, rloc);
+ else if (unformat (line_input, "action %s", &s))
+ {
+ if (!strcmp ((char *)s, "no-action"))
+ action = ACTION_NONE;
+ if (!strcmp ((char *)s, "natively-forward"))
+ action = ACTION_NATIVELY_FORWARDED;
+ if (!strcmp ((char *)s, "send-map-request"))
+ action = ACTION_SEND_MAP_REQUEST;
+ else if (!strcmp ((char *)s, "drop"))
+ action = ACTION_DROP;
+ else
+ {
+ clib_warning ("invalid action: '%s'", s);
+ goto done;
+ }
+ }
+ else
+ {
+ clib_warning ("parse error");
+ goto done;
+ }
+ }
+
+ if (!deid_set)
+ {
+ clib_warning ("missing deid!");
+ goto done;
+ }
+
+ if (GID_ADDR_IP_PREFIX == gid_address_type (&deid))
+ {
+ /* if seid not set, make sure the ip version is the same as that
+ * of the deid. This ensures the seid to be configured will be
+ * either 0/0 or ::/0 */
+ if (!seid_set)
+ ip_prefix_version(seid_ippref) = ip_prefix_version(deid_ippref);
+
+ if (is_add &&
+ (ip_prefix_version (deid_ippref)
+ != ip_prefix_version(seid_ippref)))
+ {
+ clib_warning ("source and destination EIDs are not"
+ " in the same IP family!");
+ goto done;
+ }
+ }
+
+ if (is_add && (~0 == action)
+ && 0 == vec_len (rlocs))
+ {
+ clib_warning ("no action set for negative map-reply!");
+ goto done;
+ }
+
+ memset(a, 0, sizeof(a[0]));
+ a->action = action;
+ a->is_add = is_add;
+
+ /* NOTE: the remote mapping is static, i.e., not authoritative and
+ * ttl is infinite. */
+ a->authoritative = 0;
+ a->ttl = ~0;
+
+ rv = vnet_lisp_add_del_adjacency (a);
+
+ if (rv)
+ clib_warning("failed to %s adjacency!", is_add ? "add" : "delete");
+
+done:
+ unformat_free (line_input);
+ if (s)
+ vec_free (s);
+ return error;
+}
+
+VLIB_CLI_COMMAND (lisp_add_del_adjacency_command) = {
+ .path = "lisp adjacency",
+ .short_help = "lisp adjacency add|del vni <vni>"
+ "deid <dest-eid> seid <src-eid> [action <no-action|natively-forward|"
+ "send-map-request|drop>] rloc <dst-locator> [rloc <dst-locator> ... ]",
+ .function = lisp_add_del_adjacency_command_fn,
+};
+
+
static clib_error_t *
lisp_show_map_resolvers_command_fn (vlib_main_t * vm,
unformat_input_t * input,
@@ -1025,9 +1451,8 @@ clean_locator_to_locator_set (lisp_cp_main_t * lcm, u32 lsi)
}
}
-static inline
-uword *get_locator_set_index(vnet_lisp_add_del_locator_set_args_t * a,
- uword * p)
+static inline uword *
+get_locator_set_index (vnet_lisp_add_del_locator_set_args_t * a, uword * p)
{
lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
@@ -1047,9 +1472,9 @@ uword *get_locator_set_index(vnet_lisp_add_del_locator_set_args_t * a,
return p;
}
-static inline
-int is_locator_in_locator_set(lisp_cp_main_t * lcm, locator_set_t * ls,
- locator_t * loc)
+static inline int
+is_locator_in_locator_set (lisp_cp_main_t * lcm, locator_set_t * ls,
+ locator_t * loc)
{
locator_t * itloc;
u32 * locit;
@@ -1071,9 +1496,9 @@ int is_locator_in_locator_set(lisp_cp_main_t * lcm, locator_set_t * ls,
return 0;
}
-static inline
-void remove_locator_from_locator_set(locator_set_t * ls, u32 * locit,
- u32 ls_index, u32 loc_id)
+static inline void
+remove_locator_from_locator_set (locator_set_t * ls, u32 * locit, u32 ls_index,
+ u32 loc_id)
{
lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
u32 ** ls_indexes = NULL;
@@ -1314,16 +1739,14 @@ vnet_lisp_add_del_locator_set (vnet_lisp_add_del_locator_set_args_t * a,
}
clib_error_t *
-vnet_lisp_enable_disable (u8 is_enabled)
+vnet_lisp_enable_disable (u8 is_enable)
{
- vnet_lisp_gpe_add_del_iface_args_t _ai, * ai= &_ai;
- uword * table_id, * refc;
- u32 i;
+ u32 vni, table_id;
clib_error_t * error = 0;
lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
vnet_lisp_gpe_enable_disable_args_t _a, * a = &_a;
- a->is_en = is_enabled;
+ a->is_en = is_enable;
error = vnet_lisp_gpe_enable_disable (a);
if (error)
{
@@ -1331,54 +1754,30 @@ vnet_lisp_enable_disable (u8 is_enabled)
a->is_en ? "enable" : "disable");
}
- if (is_enabled)
+ if (is_enable)
{
/* enable all ifaces */
- for (i = 0; i < vec_len (lcm->local_mappings_indexes); i++)
- {
- mapping_t * m = vec_elt_at_index (lcm->mapping_pool, i);
- ai->is_add = 1;
- ai->vni = gid_address_vni (&m->eid);
-
- refc = hash_get (lcm->dp_if_refcount_by_vni, ai->vni);
- if (!refc)
- {
- table_id = hash_get (lcm->table_id_by_vni, ai->vni);
- if (table_id)
- {
- ai->table_id = table_id[0];
- /* enables interface and adds defaults */
- vnet_lisp_gpe_add_del_iface (ai, 0);
- }
- else
- return clib_error_return (0, "no table_id found for vni %u!",
- ai->vni);
-
- hash_set (lcm->dp_if_refcount_by_vni, ai->vni, 1);
- }
- else
- {
- refc[0]++;
- }
- }
+ hash_foreach(vni, table_id, lcm->table_id_by_vni, ({
+ dp_add_del_iface(lcm, vni, 1);
+ }));
}
else
{
- /* clear refcount table */
- hash_free (lcm->dp_if_refcount_by_vni);
- hash_free (lcm->fwd_entry_by_mapping_index);
- pool_free (lcm->fwd_entry_pool);
+ /* clear interface table */
+ hash_free(lcm->dp_intf_by_vni);
+ hash_free(lcm->fwd_entry_by_mapping_index);
+ pool_free(lcm->fwd_entry_pool);
}
/* update global flag */
- lcm->is_enabled = is_enabled;
+ lcm->is_enabled = is_enable;
return 0;
}
static clib_error_t *
lisp_enable_disable_command_fn (vlib_main_t * vm, unformat_input_t * input,
- vlib_cli_command_t * cmd)
+ vlib_cli_command_t * cmd)
{
unformat_input_t _line_input, * line_input = &_line_input;
u8 is_enabled = 0;
@@ -1695,8 +2094,8 @@ vnet_lisp_add_del_map_resolver (vnet_lisp_add_del_map_resolver_args_t * a)
static clib_error_t *
lisp_add_del_map_resolver_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
{
unformat_input_t _line_input, * line_input = &_line_input;
u8 is_add = 1;
@@ -1748,12 +2147,11 @@ vnet_lisp_add_del_mreq_itr_rlocs (vnet_lisp_add_del_mreq_itr_rloc_args_t * a)
lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
uword * p = 0;
- //TODO: Wait for merge https://gerrit.fd.io/r/#/c/1427/
-// if (vnet_lisp_enable_disable_status () == 0)
-// {
-// clib_warning ("LISP is disabled!");
-// return VNET_API_ERROR_LISP_DISABLED;
-// }
+ if (vnet_lisp_enable_disable_status () == 0)
+ {
+ clib_warning("LISP is disabled!");
+ return VNET_API_ERROR_LISP_DISABLED;
+ }
if (a->is_add)
{
@@ -1775,9 +2173,9 @@ vnet_lisp_add_del_mreq_itr_rlocs (vnet_lisp_add_del_mreq_itr_rloc_args_t * a)
}
static clib_error_t *
-lisp_add_del_mreq_itr_rlocs_command_fn(vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
+lisp_add_del_mreq_itr_rlocs_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
{
unformat_input_t _line_input, * line_input = &_line_input;
u8 is_add = 1;
@@ -1899,129 +2297,6 @@ format_lisp_cp_lookup_trace (u8 * s, va_list * args)
return s;
}
-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);
-}
-
-void *
-ip_interface_get_first_address (ip_lookup_main_t * lm, u32 sw_if_index,
- u8 version)
-{
- ip_interface_address_t * ia;
-
- ia = ip_interface_get_first_interface_address (lm, sw_if_index, 1);
- if (!ia)
- return 0;
- return ip_interface_address_get_address (lm, ia);
-}
-
-int
-ip_interface_get_first_ip_address (lisp_cp_main_t * lcm, u32 sw_if_index,
- u8 version, ip_address_t * result)
-{
- ip_lookup_main_t * lm;
- void * addr;
-
- lm = (version == IP4) ? &lcm->im4->lookup_main : &lcm->im6->lookup_main;
- addr = ip_interface_get_first_address (lm, sw_if_index, version);
- if (!addr)
- return 0;
-
- ip_address_set (result, addr, version);
- return 1;
-}
-
-static u32
-ip_fib_lookup_with_table (lisp_cp_main_t * lcm, u32 fib_index,
- ip_address_t * dst)
-{
- if (ip_addr_version (dst) == IP4)
- return ip4_fib_lookup_with_table (lcm->im4, fib_index, &ip_addr_v4(dst),
- 0);
- else
- return ip6_fib_lookup_with_table (lcm->im6, fib_index, &ip_addr_v6(dst));
-}
-
-u32
-ip_fib_get_egress_iface_for_dst_with_lm (lisp_cp_main_t * lcm,
- ip_address_t * dst,
- ip_lookup_main_t * lm)
-{
- u32 adj_index;
- ip_adjacency_t * adj;
-
- adj_index = ip_fib_lookup_with_table (lcm, 0, dst);
- adj = ip_get_adjacency (lm, adj_index);
-
- if (adj == 0)
- return ~0;
-
- /* we only want outgoing routes */
- if (adj->lookup_next_index != IP_LOOKUP_NEXT_ARP
- && adj->lookup_next_index != IP_LOOKUP_NEXT_REWRITE)
- return ~0;
-
- return adj->rewrite_header.sw_if_index;
-}
-
-/**
- * Find the sw_if_index of the interface that would be used to egress towards
- * dst.
- */
-u32
-ip_fib_get_egress_iface_for_dst (lisp_cp_main_t * lcm, ip_address_t * dst)
-{
- ip_lookup_main_t * lm;
-
- lm = ip_addr_version (dst) == IP4 ?
- &lcm->im4->lookup_main : &lcm->im6->lookup_main;
-
- return ip_fib_get_egress_iface_for_dst_with_lm (lcm, dst, lm);
-}
-
-/**
- * Find first IP of the interface that would be used to egress towards dst.
- * Returns 1 if the address is found 0 otherwise.
- */
-int
-ip_fib_get_first_egress_ip_for_dst (lisp_cp_main_t * lcm, ip_address_t * dst,
- ip_address_t * result)
-{
- u32 si;
- ip_lookup_main_t * lm;
- void * addr = 0;
- u8 ipver;
-
- ASSERT(result != 0);
-
- ipver = ip_addr_version(dst);
-
- lm = (ipver == IP4) ? &lcm->im4->lookup_main : &lcm->im6->lookup_main;
- si = ip_fib_get_egress_iface_for_dst_with_lm (lcm, dst, lm);
-
- if ((u32) ~0 == si)
- return 0;
-
- /* find the first ip address */
- addr = ip_interface_get_first_address (lm, si, ipver);
- if (0 == addr)
- return 0;
-
- ip_address_set (result, addr, ipver);
- return 1;
-}
-
int
get_mr_and_local_iface_ip (lisp_cp_main_t * lcm, ip_address_t * mr_ip,
ip_address_t * sloc)
@@ -2194,8 +2469,8 @@ send_encapsulated_map_request (vlib_main_t * vm, lisp_cp_main_t *lcm,
if (!b)
return;
- /* set fib index and lookup node */
- vnet_buffer(b)->sw_if_index[VLIB_TX] = ~0;
+ /* set fib index to default and lookup node */
+ vnet_buffer(b)->sw_if_index[VLIB_TX] = 0;
next_index = (ip_addr_version(&mr_ip) == IP4) ?
ip4_lookup_node.index : ip6_lookup_node.index;
@@ -2211,7 +2486,6 @@ send_encapsulated_map_request (vlib_main_t * vm, lisp_cp_main_t *lcm,
pool_get(lcm->pending_map_requests_pool, pmr);
gid_address_copy (&pmr->src, seid);
gid_address_copy (&pmr->dst, deid);
- pmr->src_mapping_index = map_index;
hash_set(lcm->pending_map_requests_by_nonce, nonce,
pmr - lcm->pending_map_requests_pool);
}
@@ -2342,7 +2616,7 @@ lisp_cp_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
&src);
if (~0 != si)
{
- add_fwd_entry (lcm, si, di);
+ dp_add_fwd_entry (lcm, si, di);
}
}
}
@@ -2399,8 +2673,8 @@ VLIB_REGISTER_NODE (lisp_cp_lookup_node) = {
};
/* lisp_cp_input statistics */
-#define foreach_lisp_cp_input_error \
-_(DROP, "drop") \
+#define foreach_lisp_cp_input_error \
+_(DROP, "drop") \
_(MAP_REPLIES_RECEIVED, "map-replies received")
static char * lisp_cp_input_error_strings[] = {
@@ -2440,213 +2714,20 @@ format_lisp_cp_input_trace (u8 * s, va_list * args)
return s;
}
-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)
-{
- 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;
-}
-
void
process_map_reply (lisp_cp_main_t * lcm, vlib_buffer_t * b)
{
- mapping_t * old_map;
- locator_t * loc;
- u32 len = 0, i, ls_index = 0;
+ u32 len = 0, i, ttl;
void * h;
- vnet_lisp_add_del_locator_set_args_t _ls_arg, * ls_arg = &_ls_arg;
- vnet_lisp_add_del_mapping_args_t _m_args, * m_args = &_m_args;
pending_map_request_t * pmr;
locator_t probed;
map_reply_hdr_t * mrep_hdr;
u64 nonce;
- u32 dst_map_index, mi;
+ gid_address_t deid;
uword * pmr_index;
+ u8 authoritative, action;
+ locator_t * locators = 0, * loc;
+ vnet_lisp_add_del_adjacency_args_t _a, * a = &_a;
mrep_hdr = vlib_buffer_get_current (b);
@@ -2664,71 +2745,36 @@ process_map_reply (lisp_cp_main_t * lcm, vlib_buffer_t * b)
for (i = 0; i < MREP_REC_COUNT(mrep_hdr); i++)
{
- memset (ls_arg, 0, sizeof(*ls_arg));
- memset (m_args, 0, sizeof(*m_args));
h = vlib_buffer_get_current (b);
- m_args->ttl = clib_net_to_host_u32 (MAP_REC_TTL(h));
- m_args->action = MAP_REC_ACTION(h);
- m_args->authoritative = MAP_REC_AUTH(h);
+ ttl = clib_net_to_host_u32 (MAP_REC_TTL(h));
+ action = MAP_REC_ACTION(h);
+ authoritative = MAP_REC_AUTH(h);
- len = lisp_msg_parse_mapping_record (b, &m_args->deid, &ls_arg->locators,
- &probed);
+ len = lisp_msg_parse_mapping_record (b, &deid, &locators, &probed);
if (len == ~0)
{
clib_warning ("Failed to parse mapping record!");
- vec_foreach (loc, ls_arg->locators)
+ vec_foreach (loc, locators)
{
locator_free (loc);
}
- vec_free(ls_arg->locators);
+ vec_free(locators);
return;
}
- mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &m_args->deid);
- old_map = mi != ~0 ? pool_elt_at_index(lcm->mapping_pool, mi) : 0;
-
- /* if mapping already exists, decide if locators (and forwarding) should
- * be updated and be done */
- if (old_map != 0 && !gid_address_cmp (&old_map->eid, &m_args->deid))
- {
- locator_set_t * old_ls;
-
- /* update mapping attributes */
- old_map->action = m_args->action;
- old_map->authoritative = m_args->authoritative;
- old_map->ttl = m_args->ttl;
+ memset(a, 0, sizeof(*a));
+ a->action = action;
+ a->authoritative = authoritative;
+ a->ttl = ttl;
+ a->locators = locators;
+ gid_address_copy(&a->seid, &pmr->src);
+ gid_address_copy(&a->deid, &deid);
+ a->is_add = 1;
- old_ls = pool_elt_at_index(lcm->locator_set_pool,
- old_map->locator_set_index);
- /* if the two locators are not equal, update them and forwarding
- * otherwise there's nothing to be done */
- if (compare_locators (lcm, old_ls->locator_indices, ls_arg->locators))
- {
- /* set locator-set index to overwrite */
- ls_arg->is_add = 1;
- ls_arg->index = old_map->locator_set_index;
- vnet_lisp_add_del_locator_set (ls_arg, 0);
- add_fwd_entry (lcm, pmr->src_mapping_index, mi);
- }
- }
- /* new mapping */
- else
- {
- /* add locator-set */
- ls_arg->is_add = 1;
- ls_arg->index = ~0;
- vnet_lisp_add_del_locator_set (ls_arg, &ls_index);
+ lisp_add_del_adjacency (lcm, a);
- /* add mapping */
- m_args->is_add = 1;
- m_args->locator_set_index = ls_index;
- vnet_lisp_add_del_mapping (m_args, &dst_map_index);
-
- /* add forwarding tunnel */
- add_fwd_entry (lcm, pmr->src_mapping_index, dst_map_index);
- }
- vec_free(ls_arg->locators);
+ vec_free(locators);
}
/* remove pending map request entry */
@@ -2876,6 +2922,7 @@ lisp_cp_init (vlib_main_t *vm)
lcm->vlib_main = vm;
lcm->vnet_main = vnet_get_main();
lcm->mreq_itr_rlocs = ~0;
+ lcm->lisp_pitr = 0;
gid_dictionary_init (&lcm->mapping_index_by_gid);
diff --git a/vnet/vnet/lisp-cp/control.h b/vnet/vnet/lisp-cp/control.h
index 7cf39783886..4832f4da479 100644
--- a/vnet/vnet/lisp-cp/control.h
+++ b/vnet/vnet/lisp-cp/control.h
@@ -24,7 +24,6 @@ typedef struct
{
gid_address_t src;
gid_address_t dst;
- u32 src_mapping_index;
} pending_map_request_t;
typedef struct
@@ -104,7 +103,7 @@ typedef struct
uword * vni_by_table_id;
/* Number of src prefixes in a vni that use an interface */
- uword * dp_if_refcount_by_vni;
+ uword * dp_intf_by_vni;
/* Proxy ETR map index */
u32 pitr_map_index;
@@ -128,6 +127,11 @@ extern vlib_node_registration_t lisp_cp_lookup_node;
clib_error_t *
lisp_cp_init ();
+always_inline lisp_cp_main_t *
+vnet_lisp_cp_get_main() {
+ return &lisp_control_main;
+}
+
typedef struct
{
u8 is_add;
@@ -150,7 +154,7 @@ vnet_lisp_add_del_locator (vnet_lisp_add_del_locator_set_args_t * a,
typedef struct
{
u8 is_add;
- gid_address_t deid;
+ gid_address_t eid;
u32 locator_set_index;
u32 ttl;
@@ -161,12 +165,31 @@ typedef struct
} vnet_lisp_add_del_mapping_args_t;
int
-vnet_lisp_add_del_mapping (vnet_lisp_add_del_mapping_args_t *a,
+vnet_lisp_map_cache_add_del (vnet_lisp_add_del_mapping_args_t *a,
u32 * map_index);
int
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,
+ u32 * res_map_index);
+
+typedef struct
+{
+ gid_address_t deid;
+ gid_address_t seid;
+ locator_t * locators;
+ u8 action;
+ u8 authoritative;
+ u32 ttl;
+ u8 is_add;
+} vnet_lisp_add_del_adjacency_args_t;
+
+int
+vnet_lisp_add_del_adjacency (vnet_lisp_add_del_adjacency_args_t * a);
+
typedef struct
{
u8 is_add;
@@ -176,18 +199,10 @@ typedef struct
int
vnet_lisp_add_del_map_resolver (vnet_lisp_add_del_map_resolver_args_t * a);
-always_inline lisp_cp_main_t *
-vnet_lisp_cp_get_main() {
- return &lisp_control_main;
-}
-
-clib_error_t * vnet_lisp_enable_disable (u8 is_enabled);
-u8 vnet_lisp_enable_disable_status (void);
-
-int
-vnet_lisp_add_del_remote_mapping (gid_address_t * deid, gid_address_t * seid,
- ip_address_t * dlocs, u8 action, u8 is_add,
- u8 del_all);
+clib_error_t *
+vnet_lisp_enable_disable (u8 is_enabled);
+u8
+vnet_lisp_enable_disable_status (void);
int
vnet_lisp_pitr_set_locator_set (u8 * locator_set_name, u8 is_add);
@@ -201,8 +216,10 @@ typedef struct
int
vnet_lisp_add_del_mreq_itr_rlocs (vnet_lisp_add_del_mreq_itr_rloc_args_t * a);
-int vnet_lisp_clear_all_remote_mappings (void);
+int
+vnet_lisp_clear_all_remote_adjacencies (void);
-int vnet_lisp_eid_table_map (u32 vni, u32 vrf, u8 is_add);
+int
+vnet_lisp_eid_table_map (u32 vni, u32 vrf, u8 is_add);
#endif /* VNET_CONTROL_H_ */
diff --git a/vnet/vnet/lisp-cp/gid_dictionary.c b/vnet/vnet/lisp-cp/gid_dictionary.c
index 1beac54a5d8..752e1d3c5f4 100644
--- a/vnet/vnet/lisp-cp/gid_dictionary.c
+++ b/vnet/vnet/lisp-cp/gid_dictionary.c
@@ -125,7 +125,7 @@ gid_dictionary_lookup (gid_dictionary_t * db, gid_address_t * key)
clib_warning ("address type %d not supported!", gid_address_type(key));
break;
}
- return ~0;
+ return GID_LOOKUP_MISS;
}
static void
diff --git a/vnet/vnet/lisp-cp/lisp_msg_serdes.c b/vnet/vnet/lisp-cp/lisp_msg_serdes.c
index 6c5546014b1..c1713b36c99 100644
--- a/vnet/vnet/lisp-cp/lisp_msg_serdes.c
+++ b/vnet/vnet/lisp-cp/lisp_msg_serdes.c
@@ -149,7 +149,9 @@ lisp_msg_pull_hdr (vlib_buffer_t * b, lisp_msg_type_e type)
u32
lisp_msg_parse_addr (vlib_buffer_t * b, gid_address_t * eid)
{
- u32 len = gid_address_parse (vlib_buffer_get_current (b), eid);
+ u32 len;
+ memset(eid, 0, sizeof(*eid));
+ len = gid_address_parse (vlib_buffer_get_current (b), eid);
if (len != ~0)
vlib_buffer_pull (b, len);
return len;
@@ -159,7 +161,9 @@ u32
lisp_msg_parse_eid_rec (vlib_buffer_t * b, gid_address_t * eid)
{
eid_record_hdr_t * h = vlib_buffer_get_current (b);
- u32 len = gid_address_parse (EID_REC_ADDR(h), eid);
+ u32 len;
+ memset(eid, 0, sizeof(*eid));
+ len = gid_address_parse (EID_REC_ADDR(h), eid);
if (len == ~0)
return len;
@@ -213,6 +217,7 @@ lisp_msg_parse_mapping_record (vlib_buffer_t * b, gid_address_t * eid,
h = vlib_buffer_get_current (b);
vlib_buffer_pull (b, sizeof(mapping_record_hdr_t));
+ memset(eid, 0, sizeof(*eid));
len = gid_address_parse (vlib_buffer_get_current (b), eid);
if (len == ~0)
return len;
diff --git a/vnet/vnet/lisp-cp/lisp_types.c b/vnet/vnet/lisp-cp/lisp_types.c
index 1608e094f60..25a8271e929 100644
--- a/vnet/vnet/lisp-cp/lisp_types.c
+++ b/vnet/vnet/lisp-cp/lisp_types.c
@@ -782,6 +782,8 @@ gid_address_parse (u8 * offset, gid_address_t *a)
if (!a)
return 0;
+ /* NOTE: since gid_adress_parse may be called by vni_parse, we can't 0
+ * the gid address here */
afi = clib_net_to_host_u16 (*((u16 *) offset));
switch (afi)
diff --git a/vnet/vnet/lisp-cp/lisp_types.h b/vnet/vnet/lisp-cp/lisp_types.h
index 83655d8db9a..f7225908dd6 100644
--- a/vnet/vnet/lisp-cp/lisp_types.h
+++ b/vnet/vnet/lisp-cp/lisp_types.h
@@ -244,6 +244,4 @@ typedef struct
u8 local;
} mapping_t;
-lcaf_t lcaf_iid_init (u32 vni);
-
#endif /* VNET_LISP_GPE_LISP_TYPES_H_ */
diff --git a/vnet/vnet/lisp-gpe/decap.c b/vnet/vnet/lisp-gpe/decap.c
index 23769765ab7..5a9ce84a407 100644
--- a/vnet/vnet/lisp-gpe/decap.c
+++ b/vnet/vnet/lisp-gpe/decap.c
@@ -392,6 +392,12 @@ lisp_gpe_ip6_input (vlib_main_t * vm, vlib_node_runtime_t * node,
return lisp_gpe_input_inline(vm, node, from_frame, 0);
}
+static char * lisp_gpe_ip4_input_error_strings[] = {
+#define lisp_gpe_error(n,s) s,
+#include <vnet/lisp-gpe/lisp_gpe_error.def>
+#undef lisp_gpe_error
+};
+
VLIB_REGISTER_NODE (lisp_gpe_ip4_input_node) = {
.function = lisp_gpe_ip4_input,
.name = "lisp-gpe-ip4-input",
@@ -404,6 +410,9 @@ VLIB_REGISTER_NODE (lisp_gpe_ip4_input_node) = {
#undef _
},
+ .n_errors = ARRAY_LEN (lisp_gpe_ip4_input_error_strings),
+ .error_strings = lisp_gpe_ip4_input_error_strings,
+
.format_buffer = format_lisp_gpe_header_with_length,
.format_trace = format_lisp_gpe_rx_trace,
// $$$$ .unformat_buffer = unformat_lisp_gpe_header,
@@ -421,6 +430,9 @@ VLIB_REGISTER_NODE (lisp_gpe_ip6_input_node) = {
#undef _
},
+ .n_errors = ARRAY_LEN (lisp_gpe_ip4_input_error_strings),
+ .error_strings = lisp_gpe_ip4_input_error_strings,
+
.format_buffer = format_lisp_gpe_header_with_length,
.format_trace = format_lisp_gpe_rx_trace,
// $$$$ .unformat_buffer = unformat_lisp_gpe_header,
diff --git a/vpp-api-test/vat/api_format.c b/vpp-api-test/vat/api_format.c
index 504c3b40854..8c6cb66fea7 100644
--- a/vpp-api-test/vat/api_format.c
+++ b/vpp-api-test/vat/api_format.c
@@ -2029,6 +2029,7 @@ vl_api_lisp_local_eid_table_details_t_handler_json (
case 0:
clib_memcpy(&ip4, mp->eid, sizeof(ip4));
vat_json_object_add_ip4(node, "eid-address", ip4);
+ break;
case 1:
clib_memcpy(&ip6, mp->eid, sizeof(ip6));
vat_json_object_add_ip6(node, "eid-address", ip6);
@@ -2636,6 +2637,8 @@ _(trace_profile_del_reply) \
_(lisp_add_del_locator_set_reply) \
_(lisp_add_del_locator_reply) \
_(lisp_add_del_local_eid_reply) \
+_(lisp_add_del_remote_mapping_reply) \
+_(lisp_add_del_adjacency_reply) \
_(lisp_gpe_add_del_fwd_entry_reply) \
_(lisp_add_del_map_resolver_reply) \
_(lisp_gpe_enable_disable_reply) \
@@ -2817,6 +2820,8 @@ _(TRACE_PROFILE_DEL_REPLY, trace_profile_del_reply) \
_(LISP_ADD_DEL_LOCATOR_SET_REPLY, lisp_add_del_locator_set_reply) \
_(LISP_ADD_DEL_LOCATOR_REPLY, lisp_add_del_locator_reply) \
_(LISP_ADD_DEL_LOCAL_EID_REPLY, lisp_add_del_local_eid_reply) \
+_(LISP_ADD_DEL_REMOTE_MAPPING_REPLY, lisp_add_del_remote_mapping_reply) \
+_(LISP_ADD_DEL_ADJACENCY_REPLY, lisp_add_del_adjacency_reply) \
_(LISP_GPE_ADD_DEL_FWD_ENTRY_REPLY, lisp_gpe_add_del_fwd_entry_reply) \
_(LISP_ADD_DEL_MAP_RESOLVER_REPLY, lisp_add_del_map_resolver_reply) \
_(LISP_GPE_ENABLE_DISABLE_REPLY, lisp_gpe_enable_disable_reply) \
@@ -10565,8 +10570,7 @@ api_lisp_eid_table_add_del_map (vat_main_t * vam)
}
/**
- * Add/del remote mapping from LISP control plane and updates
- * forwarding entries in data-plane accordingly.
+ * Add/del remote mapping to/from LISP control plane
*
* @param vam vpp API test context
* @return return code
@@ -10695,6 +10699,135 @@ api_lisp_add_del_remote_mapping (vat_main_t * vam)
return 0;
}
+/**
+ * Add/del LISP adjacency. Saves mapping in LISP control plane and updates
+ * forwarding entries in data-plane accordingly.
+ *
+ * @param vam vpp API test context
+ * @return return code
+ */
+static int
+api_lisp_add_del_adjacency (vat_main_t * vam)
+{
+ unformat_input_t * input = vam->input;
+ vl_api_lisp_add_del_adjacency_t *mp;
+ f64 timeout = ~0;
+ u32 vni = 0;
+ ip4_address_t seid4, deid4, rloc4;
+ ip6_address_t seid6, deid6, rloc6;
+ u8 deid_mac[6] = {0};
+ u8 seid_mac[6] = {0};
+ u8 deid_type, seid_type;
+ u32 seid_len = 0, deid_len = 0, len;
+ u8 is_add = 1;
+ u32 action = ~0;
+ rloc_t * rlocs = 0, rloc;
+
+ memset(mp, 0, sizeof(mp[0]));
+ seid_type = deid_type = (u8)~0;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
+ if (unformat(input, "del")) {
+ is_add = 0;
+ } else if (unformat(input, "add")) {
+ is_add = 1;
+ } else if (unformat(input, "deid %U/%d", unformat_ip4_address,
+ &deid4, &len)) {
+ deid_type = 0; /* ipv4 */
+ deid_len = len;
+ } else if (unformat(input, "deid %U/%d", unformat_ip6_address,
+ &deid6, &len)) {
+ deid_type = 1; /* ipv6 */
+ deid_len = len;
+ } else if (unformat(input, "deid %U", unformat_ethernet_address,
+ deid_mac)) {
+ deid_type = 2; /* mac */
+ } else if (unformat(input, "seid %U/%d", unformat_ip4_address,
+ &seid4, &len)) {
+ seid_type = 0; /* ipv4 */
+ seid_len = len;
+ } else if (unformat(input, "seid %U/%d", unformat_ip6_address,
+ &seid6, &len)) {
+ seid_type = 1; /* ipv6 */
+ seid_len = len;
+ } else if (unformat(input, "seid %U", unformat_ethernet_address,
+ seid_mac)) {
+ seid_type = 2; /* mac */
+ } else if (unformat(input, "vni %d", &vni)) {
+ ;
+ } else if (unformat(input, "rloc %U", unformat_ip4_address, &rloc4)) {
+ rloc.is_ip4 = 1;
+ clib_memcpy (&rloc.addr, &rloc4, sizeof (rloc4));
+ vec_add1 (rlocs, rloc);
+ } else if (unformat(input, "rloc %U", unformat_ip6_address, &rloc6)) {
+ rloc.is_ip4 = 0;
+ clib_memcpy (&rloc.addr, &rloc6, sizeof (rloc6));
+ vec_add1 (rlocs, rloc);
+ } else if (unformat(input, "action %d", &action)) {
+ ;
+ } else {
+ clib_warning ("parse error '%U'", format_unformat_error, input);
+ return -99;
+ }
+ }
+
+ if ((u8)~0 == deid_type) {
+ errmsg ("missing params!");
+ return -99;
+ }
+
+ if (seid_type != deid_type) {
+ errmsg ("source and destination EIDs are of different types!");
+ return -99;
+ }
+
+ if (is_add && (~0 == action)
+ && 0 == vec_len (rlocs)) {
+ errmsg ("no action set for negative map-reply!");
+ return -99;
+ }
+
+ M(LISP_ADD_DEL_ADJACENCY, lisp_add_del_adjacency);
+ mp->is_add = is_add;
+ mp->vni = htonl (vni);
+ mp->seid_len = seid_len;
+ mp->action = (u8) action;
+ mp->deid_len = deid_len;
+ mp->eid_type = deid_type;
+
+ switch (mp->eid_type) {
+ case 0:
+ clib_memcpy (mp->seid, &seid4, sizeof (seid4));
+ clib_memcpy (mp->deid, &deid4, sizeof (deid4));
+ break;
+ case 1:
+ clib_memcpy (mp->seid, &seid6, sizeof (seid6));
+ clib_memcpy (mp->deid, &deid6, sizeof (deid6));
+ break;
+ case 2:
+ clib_memcpy (mp->seid, seid_mac, 6);
+ clib_memcpy (mp->deid, deid_mac, 6);
+ break;
+ default:
+ errmsg ("unknown EID type %d!", mp->eid_type);
+ return 0;
+ }
+
+ mp->rloc_num = vec_len (rlocs);
+ clib_memcpy (mp->rlocs, rlocs, (sizeof (rloc_t) * vec_len (rlocs)));
+ vec_free (rlocs);
+
+ /* send it... */
+ S;
+
+ /* Wait for a reply... */
+ W;
+
+ /* NOTREACHED */
+ return 0;
+}
+
static int
api_lisp_gpe_add_del_iface(vat_main_t * vam)
{
@@ -12121,10 +12254,12 @@ _(lisp_add_del_map_resolver, "<ip4|6-addr> [del]") \
_(lisp_gpe_enable_disable, "enable|disable") \
_(lisp_enable_disable, "enable|disable") \
_(lisp_gpe_add_del_iface, "up|down") \
-_(lisp_add_del_remote_mapping, "add|del vni <vni> table-id <id> " \
- "deid <dest-eid> seid" \
+_(lisp_add_del_remote_mapping, "add|del vni <vni> deid <dest-eid> seid" \
" <src-eid> rloc <locator> " \
- "[rloc <loc> ... ]") \
+ "[rloc <loc> ... ] action <action>") \
+_(lisp_add_del_adjacency, "add|del vni <vni> deid <dest-eid> seid" \
+ " <src-eid> rloc <locator> " \
+ "[rloc <loc> ... ] action <action>") \
_(lisp_pitr_set_locator_set, "locator-set <loc-set-name> | del") \
_(lisp_add_del_map_request_itr_rlocs, "<loc-set-name> [del]") \
_(lisp_eid_table_add_del_map, "[del] vni <vni> vrf <vrf>") \
diff --git a/vpp/vpp-api/api.c b/vpp/vpp-api/api.c
index 483a804f661..58f7aeff5fd 100644
--- a/vpp/vpp-api/api.c
+++ b/vpp/vpp-api/api.c
@@ -333,6 +333,7 @@ _(LISP_GPE_ENABLE_DISABLE, lisp_gpe_enable_disable) \
_(LISP_ENABLE_DISABLE, lisp_enable_disable) \
_(LISP_GPE_ADD_DEL_IFACE, lisp_gpe_add_del_iface) \
_(LISP_ADD_DEL_REMOTE_MAPPING, lisp_add_del_remote_mapping) \
+_(LISP_ADD_DEL_ADJACENCY, lisp_add_del_adjacency) \
_(LISP_PITR_SET_LOCATOR_SET, lisp_pitr_set_locator_set) \
_(LISP_EID_TABLE_ADD_DEL_MAP, lisp_eid_table_add_del_map) \
_(LISP_LOCATOR_SET_DUMP, lisp_locator_set_dump) \
@@ -4796,16 +4797,12 @@ vl_api_lisp_add_del_local_eid_t_handler(
{
case 0: /* ipv4*/
gid_address_type (&eid) = GID_ADDR_IP_PREFIX;
- clib_memcpy(&ip_addr_v4(ip_eid), mp->eid,
- sizeof(ip_addr_v4(ip_eid)));
- ip_addr_version(ip_eid) = IP4;
+ ip_address_set(ip_eid, mp->eid, IP4);
ip_prefix_len(prefp) = mp->prefix_len;
break;
case 1: /* ipv6 */
gid_address_type (&eid) = GID_ADDR_IP_PREFIX;
- clib_memcpy(&ip_addr_v6(ip_eid), mp->eid,
- sizeof(ip_addr_v6(ip_eid)));
- ip_addr_version(ip_eid) = IP6;
+ ip_address_set(ip_eid, mp->eid, IP6);
ip_prefix_len(prefp) = mp->prefix_len;
break;
case 2: /* l2 mac */
@@ -4828,14 +4825,14 @@ vl_api_lisp_add_del_local_eid_t_handler(
/* XXX treat batch configuration */
a->is_add = mp->is_add;
gid_address_vni (&eid) = clib_net_to_host_u32 (mp->vni);
- gid_address_copy (&a->deid, &eid);
+ gid_address_copy (&a->eid, &eid);
a->locator_set_index = locator_set_index;
a->local = 1;
rv = vnet_lisp_add_del_local_mapping(a, &map_index);
out:
vec_free(name);
- gid_address_free (&a->deid);
+ gid_address_free (&a->eid);
REPLY_MACRO(VL_API_LISP_ADD_DEL_LOCAL_EID_REPLY);
}
@@ -5048,7 +5045,7 @@ vl_api_lisp_add_del_remote_mapping_t_handler (
vl_api_lisp_add_del_remote_mapping_t *mp)
{
u32 i;
- ip_address_t rloc, * rlocs = 0;
+ locator_t rloc, * rlocs = 0;
vl_api_lisp_add_del_remote_mapping_reply_t * rmp;
int rv = 0;
gid_address_t _seid, * seid = &_seid;
@@ -5056,6 +5053,7 @@ vl_api_lisp_add_del_remote_mapping_t_handler (
ip_prefix_t * seid_pref = &gid_address_ippref(seid);
ip_prefix_t * deid_pref = &gid_address_ippref(deid);
+ /* TODO remove seid from API */
memset (seid, 0, sizeof (seid[0]));
memset (deid, 0, sizeof (deid[0]));
ip_address_t * seid_addr = &ip_prefix_addr(seid_pref);
@@ -5072,22 +5070,14 @@ vl_api_lisp_add_del_remote_mapping_t_handler (
case 0: /* ipv4 */
gid_address_type(seid) = GID_ADDR_IP_PREFIX;
gid_address_type(deid) = GID_ADDR_IP_PREFIX;
- ip_prefix_version(seid_pref) = IP4;
- ip_prefix_version(deid_pref) = IP4;
- clib_memcpy (&ip_addr_v4(seid_addr),
- mp->seid, sizeof (ip_addr_v4(seid_addr)));
- clib_memcpy (&ip_addr_v4(deid_addr),
- mp->deid, sizeof (ip_addr_v4(deid_addr)));
+ ip_address_set (seid_addr, mp->seid, IP4);
+ ip_address_set (deid_addr, mp->deid, IP4);
break;
case 1: /* ipv6 */
gid_address_type(seid) = GID_ADDR_IP_PREFIX;
gid_address_type(deid) = GID_ADDR_IP_PREFIX;
- ip_prefix_version(seid_pref) = IP6;
- ip_prefix_version(deid_pref) = IP6;
- clib_memcpy (&ip_addr_v6(seid_addr),
- mp->seid, sizeof (ip_addr_v6(seid_addr)));
- clib_memcpy (&ip_addr_v6(deid_addr),
- mp->deid, sizeof (ip_addr_v6(deid_addr)));
+ ip_address_set (seid_addr, mp->seid, IP6);
+ ip_address_set (deid_addr, mp->deid, IP6);
break;
case 2: /* l2 mac */
gid_address_type(seid) = GID_ADDR_MAC;
@@ -5102,21 +5092,124 @@ vl_api_lisp_add_del_remote_mapping_t_handler (
for (i = 0; i < mp->rloc_num; i++) {
rloc_t * r = &((rloc_t *) mp->rlocs)[i];
- if (r->is_ip4) {
- clib_memcpy (&ip_addr_v4(&rloc), &r->addr, sizeof (rloc_t));
- ip_addr_version (&rloc) = IP4;
- } else {
- clib_memcpy (&ip_addr_v6(&rloc), &r->addr, sizeof (rloc_t));
- ip_addr_version (&rloc) = IP6;
- }
+ memset(&rloc, 0, sizeof(rloc));
+ ip_address_set(&gid_address_ip(&rloc.address), &r->addr,
+ r->is_ip4 ? IP4 : IP6);
+ gid_address_ippref_len(&rloc.address) = r->is_ip4 ? 32: 128;
+ gid_address_type(&rloc.address) = GID_ADDR_IP_PREFIX;
+ /* TODO fix API to pass priority and weight */
+ rloc.priority = 1;
+ rloc.weight = 1;
vec_add1 (rlocs, rloc);
}
- rv = vnet_lisp_add_del_remote_mapping (deid, seid, rlocs, mp->action,
- mp->is_add, mp->del_all);
+ /* TODO Uncomment once https://gerrit.fd.io/r/#/c/1802 is merged and CSIT
+ * is switched to lisp_add_del_adjacency */
+// if (!mp->is_add) {
+// vnet_lisp_add_del_adjacency_args_t _a, * a = &_a;
+// gid_address_copy(&a->deid, deid);
+// a->is_add = 0;
+// rv = vnet_lisp_add_del_adjacency (a);
+// } else {
+// /* NOTE: for now this works as a static remote mapping, i.e.,
+// * not authoritative and ttl infinite. */
+// rv = vnet_lisp_add_del_mapping (deid, rlocs, mp->action, 0, ~0,
+// mp->is_add, 0);
+// }
+
+ /* TODO: remove once the above is merged */
+ vnet_lisp_add_del_adjacency_args_t _a, * a = &_a;
+ a->is_add = mp->is_add;
+ a->authoritative = 0;
+ a->action = mp->action;
+ a->locators = rlocs;
+ gid_address_copy(&a->seid, seid);
+ gid_address_copy(&a->deid, deid);
+ rv = vnet_lisp_add_del_adjacency (a);
+
+ if (mp->del_all)
+ vnet_lisp_clear_all_remote_adjacencies ();
+
vec_free (rlocs);
send_reply:
- REPLY_MACRO(VL_API_LISP_GPE_ADD_DEL_IFACE_REPLY);
+ REPLY_MACRO(VL_API_LISP_ADD_DEL_REMOTE_MAPPING_REPLY);
+}
+
+static void
+vl_api_lisp_add_del_adjacency_t_handler (
+ vl_api_lisp_add_del_adjacency_t *mp)
+{
+ u32 i;
+ locator_t rloc;
+ vl_api_lisp_add_del_adjacency_reply_t * rmp;
+ vnet_lisp_add_del_adjacency_args_t _a, * a = &_a;
+
+ int rv = 0;
+ memset(a, 0, sizeof(a[0]));
+
+ ip_prefix_t * seid_pref = &gid_address_ippref(&a->seid);
+ ip_prefix_t * deid_pref = &gid_address_ippref(&a->deid);
+
+ ip_address_t * seid_addr = &ip_prefix_addr(seid_pref);
+ ip_address_t * deid_addr = &ip_prefix_addr(deid_pref);
+ ip_prefix_len(seid_pref) = mp->seid_len;
+ ip_prefix_len(deid_pref) = mp->deid_len;
+ u8 * seid_mac = gid_address_mac (&a->seid);
+ u8 * deid_mac = gid_address_mac (&a->deid);
+ gid_address_vni(&a->seid) = ntohl (mp->vni);
+ gid_address_vni(&a->deid) = ntohl (mp->vni);
+
+ switch (mp->eid_type)
+ {
+ case 0: /* ipv4 */
+ gid_address_type(&a->seid) = GID_ADDR_IP_PREFIX;
+ gid_address_type(&a->deid) = GID_ADDR_IP_PREFIX;
+ ip_address_set (seid_addr, mp->seid, IP4);
+ ip_address_set (deid_addr, mp->deid, IP4);
+ break;
+ case 1: /* ipv6 */
+ gid_address_type(&a->seid) = GID_ADDR_IP_PREFIX;
+ gid_address_type(&a->deid) = GID_ADDR_IP_PREFIX;
+ ip_address_set (seid_addr, mp->seid, IP6);
+ ip_address_set (deid_addr, mp->deid, IP6);
+ break;
+ case 2: /* l2 mac */
+ gid_address_type(&a->seid) = GID_ADDR_MAC;
+ gid_address_type(&a->deid) = GID_ADDR_MAC;
+ clib_memcpy (seid_mac, mp->seid, 6);
+ clib_memcpy (deid_mac, mp->deid, 6);
+ break;
+ default:
+ rv = VNET_API_ERROR_INVALID_EID_TYPE;
+ goto send_reply;
+ }
+
+ for (i = 0; i < mp->rloc_num; i++) {
+ rloc_t * r = &((rloc_t *) mp->rlocs)[i];
+ memset(&rloc, 0, sizeof(rloc));
+ ip_address_set(&gid_address_ip(&rloc.address), &r->addr,
+ r->is_ip4 ? IP4 : IP6);
+ gid_address_ippref_len(&rloc.address) = r->is_ip4 ? 32: 128;
+ gid_address_type(&rloc.address) = GID_ADDR_IP_PREFIX;
+ /* TODO fix API to pass priority and weight */
+ rloc.priority = 1;
+ rloc.weight = 1;
+ vec_add1 (a->locators, rloc);
+ }
+
+ a->action = mp->action;
+ a->is_add = mp->is_add;
+
+ /* NOTE: the remote mapping is static, i.e., not authoritative and
+ * ttl is infinite. */
+ a->authoritative = 0;
+ a->ttl = ~0;
+
+ rv = vnet_lisp_add_del_adjacency (a);
+
+ vec_free (a->locators);
+send_reply:
+ REPLY_MACRO(VL_API_LISP_ADD_DEL_ADJACENCY_REPLY);
}
static void
diff --git a/vpp/vpp-api/vpe.api b/vpp/vpp-api/vpe.api
index c2fbf2eba89..9057de9d139 100644
--- a/vpp/vpp-api/vpe.api
+++ b/vpp/vpp-api/vpe.api
@@ -2406,12 +2406,50 @@ define lisp_add_del_remote_mapping {
@param context - returned sender context, to match reply w/ request
@param retval - return code
*/
-
define lisp_add_del_remote_mapping_reply {
u32 context;
i32 retval;
};
+/** \brief add or delete LISP adjacency adjacency
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param is_add - add address if non-zero, else delete
+ @param vni - virtual network instance
+ @param action - negative mapping action
+ @param eid_type -
+ 0 : ipv4
+ 1 : ipv6
+ 2 : mac
+ @param deid - destination EID
+ @param seid - source EID
+ @param rloc_num - number of remote locators
+ @param rlocs - remote locator data
+*/
+define lisp_add_del_adjacency {
+ u32 client_index;
+ u32 context;
+ u8 is_add;
+ u32 vni;
+ u8 action;
+ u8 eid_type;
+ u8 deid[16];
+ u8 seid[16];
+ u8 deid_len;
+ u8 seid_len;
+ u32 rloc_num;
+ u8 rlocs[0];
+};
+
+/** \brief Reply for lisp_add_del_adjacency
+ @param context - returned sender context, to match reply w/ request
+ @param retval - return code
+*/
+define lisp_add_del_adjacency_reply {
+ u32 context;
+ i32 retval;
+};
+
/** \brief add or delete map request itr rlocs
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request