summaryrefslogtreecommitdiffstats
path: root/src/vnet/lisp-cp
diff options
context:
space:
mode:
authorFilip Tehlar <ftehlar@cisco.com>2017-08-14 19:15:36 +0200
committerFilip Tehlar <ftehlar@cisco.com>2017-09-04 12:13:55 +0200
commit809bc74b5b73634678e6f1444344fd1c0a89e877 (patch)
treeb21cbb276341223fbbd9b00d23488309bd47840e /src/vnet/lisp-cp
parentdbfa574a1d5ebb68a81fed20dcd4bb2f47c47066 (diff)
LISP: re-fetch mapping before it expires
Change-Id: I0581a1bddad55d8d573c546ec84b0b2760abab3d Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
Diffstat (limited to 'src/vnet/lisp-cp')
-rw-r--r--src/vnet/lisp-cp/control.c322
-rw-r--r--src/vnet/lisp-cp/control.h8
-rw-r--r--src/vnet/lisp-cp/lisp_api.c15
-rw-r--r--src/vnet/lisp-cp/lisp_cli.c15
-rw-r--r--src/vnet/lisp-cp/lisp_types.h6
-rw-r--r--src/vnet/lisp-cp/one_api.c15
-rw-r--r--src/vnet/lisp-cp/one_cli.c15
7 files changed, 272 insertions, 124 deletions
diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c
index 59a45ed8910..c811e789af9 100644
--- a/src/vnet/lisp-cp/control.c
+++ b/src/vnet/lisp-cp/control.c
@@ -30,9 +30,14 @@
#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);
}
@@ -3393,6 +3415,73 @@ mapping_start_expiration_timer (lisp_cp_main_t * lcm, u32 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)
{
lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
@@ -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;
}
diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h
index 7b0380fbc0a..a3e2fc2510a 100644
--- a/src/vnet/lisp-cp/control.h
+++ b/src/vnet/lisp-cp/control.h
@@ -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
{
diff --git a/src/vnet/lisp-cp/lisp_api.c b/src/vnet/lisp-cp/lisp_api.c
index 6c82d4cf049..f7c41971061 100644
--- a/src/vnet/lisp-cp/lisp_api.c
+++ b/src/vnet/lisp-cp/lisp_api.c
@@ -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 ();
diff --git a/src/vnet/lisp-cp/lisp_cli.c b/src/vnet/lisp-cp/lisp_cli.c
index 05df9fb6d2a..509046019ec 100644
--- a/src/vnet/lisp-cp/lisp_cli.c
+++ b/src/vnet/lisp-cp/lisp_cli.c
@@ -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");
diff --git a/src/vnet/lisp-cp/lisp_types.h b/src/vnet/lisp-cp/lisp_types.h
index b7ad0f27dd0..b17110f650a 100644
--- a/src/vnet/lisp-cp/lisp_types.h
+++ b/src/vnet/lisp-cp/lisp_types.h
@@ -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
diff --git a/src/vnet/lisp-cp/one_api.c b/src/vnet/lisp-cp/one_api.c
index 620d56fb568..b8e3f7045a6 100644
--- a/src/vnet/lisp-cp/one_api.c
+++ b/src/vnet/lisp-cp/one_api.c
@@ -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 ();
diff --git a/src/vnet/lisp-cp/one_cli.c b/src/vnet/lisp-cp/one_cli.c
index e165f71c2cc..3e0c4c0a3d7 100644
--- a/src/vnet/lisp-cp/one_cli.c
+++ b/src/vnet/lisp-cp/one_cli.c
@@ -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");