#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
{
}
static void
-dp_del_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 dst_map_index)
{
vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a;
fwd_entry_t *fe = 0;
vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a;
gid_address_t *rmt_eid, *lcl_eid;
mapping_t *lcl_map, *rmt_map;
- u32 sw_if_index;
- uword *feip = 0, *dpid;
+ u32 sw_if_index, **rmts, rmts_idx;
+ uword *feip = 0, *dpid, *rmts_stored_idxp = 0;
fwd_entry_t *fe;
u8 type, is_src_dst = 0;
int rv;
/* 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);
+ dp_del_fwd_entry (lcm, dst_map_index);
/*
* Determine local mapping and eid
fe->is_src_dst = is_src_dst;
hash_set (lcm->fwd_entry_by_mapping_index, dst_map_index,
fe - lcm->fwd_entry_pool);
+
+ /* Add rmt mapping to the vector of adjacent mappings to lcl mapping */
+ rmts_stored_idxp =
+ hash_get (lcm->lcl_to_rmt_adjs_by_lcl_idx, src_map_index);
+ if (!rmts_stored_idxp)
+ {
+ pool_get (lcm->lcl_to_rmt_adjacencies, rmts);
+ memset (rmts, 0, sizeof (*rmts));
+ rmts_idx = rmts - lcm->lcl_to_rmt_adjacencies;
+ hash_set (lcm->lcl_to_rmt_adjs_by_lcl_idx, src_map_index, rmts_idx);
+ }
+ else
+ {
+ rmts_idx = (u32) (*rmts_stored_idxp);
+ rmts = pool_elt_at_index (lcm->lcl_to_rmt_adjacencies, rmts_idx);
+ }
+ vec_add1 (rmts[0], dst_map_index);
}
typedef struct
memset (ms, 0, sizeof (*ms));
ip_address_copy (&ms->address, addr);
vec_add1 (lcm->map_servers, ms[0]);
+
+ if (vec_len (lcm->map_servers) == 1)
+ lcm->do_map_server_election = 1;
}
else
{
ms = vec_elt_at_index (lcm->map_servers, i);
if (!ip_address_cmp (&ms->address, addr))
{
+ if (!ip_address_cmp (&ms->address, &lcm->active_map_server))
+ lcm->do_map_server_election = 1;
+
vec_del1 (lcm->map_servers, i);
break;
}
{
lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
u32 mi, *map_indexp, map_index, i;
+ u32 **rmts = 0, *remote_idxp, rmts_itr, remote_idx;
+ uword *rmts_idxp;
mapping_t *m, *old_map;
u32 **eid_indexes;
m = pool_elt_at_index (lcm->mapping_pool, mi);
if (m->local)
{
+ /* Remove adjacencies associated with the local mapping */
+ rmts_idxp = hash_get (lcm->lcl_to_rmt_adjs_by_lcl_idx, mi);
+ if (rmts_idxp)
+ {
+ rmts =
+ pool_elt_at_index (lcm->lcl_to_rmt_adjacencies, rmts_idxp[0]);
+ vec_foreach (remote_idxp, rmts[0])
+ {
+ dp_del_fwd_entry (lcm, remote_idxp[0]);
+ }
+ vec_free (rmts[0]);
+ pool_put (lcm->lcl_to_rmt_adjacencies, rmts);
+ hash_unset (lcm->lcl_to_rmt_adjs_by_lcl_idx, mi);
+ }
+
u32 k, *lm_indexp;
for (k = 0; k < vec_len (lcm->local_mappings_indexes); k++)
{
}
vec_del1 (lcm->local_mappings_indexes, k);
}
+ else
+ {
+ /* Remove remote (if present) from the vectors of lcl-to-rmts
+ * TODO: Address this in a more efficient way.
+ */
+ /* *INDENT-OFF* */
+ pool_foreach (rmts, lcm->lcl_to_rmt_adjacencies,
+ ({
+ vec_foreach_index (rmts_itr, rmts[0])
+ {
+ remote_idx = vec_elt (rmts[0], rmts_itr);
+ if (mi == remote_idx)
+ {
+ vec_del1 (rmts[0], rmts_itr);
+ break;
+ }
+ }
+ }));
+ /* *INDENT-ON* */
+ }
/* remove mapping from dictionary */
gid_dictionary_add_del (&lcm->mapping_index_by_gid, &a->eid, 0, 0);
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);
}
/**
- * 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;
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;
- }
+ remove_overlapping_sub_prefixes (lcm, &a->eid, 0 == ls_args->locators);
- 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 = 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;
}
mapping_t *map = pool_elt_at_index (lcm->mapping_pool, map_indexp[0]);
if (!map->local)
{
- dp_del_fwd_entry (lcm, 0, map_indexp[0]);
+ dp_del_fwd_entry (lcm, map_indexp[0]);
dm_args->is_add = 0;
gid_address_copy (&dm_args->eid, &map->eid);
dp_add_fwd_entry (lcm, local_mi, remote_mi);
}
else
- dp_del_fwd_entry (lcm, 0, remote_mi);
+ dp_del_fwd_entry (lcm, remote_mi);
return 0;
}
return 0;
}
+int
+vnet_lisp_map_register_fallback_threshold_set (u32 value)
+{
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ if (0 == value)
+ {
+ return VNET_API_ERROR_INVALID_ARGUMENT;
+ }
+
+ lcm->max_expired_map_registers = value;
+ return 0;
+}
+
+u32
+vnet_lisp_map_register_fallback_threshold_get (void)
+{
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ return lcm->max_expired_map_registers;
+}
+
/**
* Configure Proxy-ETR
*
clib_error_t *
vnet_lisp_enable_disable (u8 is_enable)
{
- u32 vni, dp_table;
+ u32 vni, dp_table, **rmts;
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;
/* clear interface table */
hash_free (lcm->fwd_entry_by_mapping_index);
pool_free (lcm->fwd_entry_pool);
+ /* Clear state tracking rmt-lcl fwd entries */
+ /* *INDENT-OFF* */
+ pool_foreach(rmts, lcm->lcl_to_rmt_adjacencies,
+ {
+ vec_free(rmts[0]);
+ });
+ /* *INDENT-ON* */
+ hash_free (lcm->lcl_to_rmt_adjs_by_lcl_idx);
+ pool_free (lcm->lcl_to_rmt_adjacencies);
}
/* update global flag */
return 0;
}
+int
+vnet_lisp_map_register_set_ttl (u32 ttl)
+{
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ lcm->map_register_ttl = ttl;
+ return 0;
+}
+
+u32
+vnet_lisp_map_register_get_ttl (void)
+{
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ return lcm->map_register_ttl;
+}
+
int
vnet_lisp_add_del_mreq_itr_rlocs (vnet_lisp_add_del_mreq_itr_rloc_args_t * a)
{
/* push outer ip header */
pkt_push_udp_and_ip (vm, b, LISP_CONTROL_PORT, LISP_CONTROL_PORT, sloc,
- rloc);
+ rloc, 1);
bi_res[0] = bi;
}
b = vlib_get_buffer (vm, bi);
+ b->flags = 0;
/* leave some space for the encap headers */
vlib_buffer_make_headroom (b, MAX_LISP_MSG_ENCAP_LEN);
/* push outer ip header */
pkt_push_udp_and_ip (vm, b, LISP_CONTROL_PORT, LISP_CONTROL_PORT, sloc,
- mr_ip);
+ mr_ip, 1);
bi_res[0] = bi;
r->retries_num = 0;
}
-static int
-elect_map_resolver (lisp_cp_main_t * lcm)
-{
- lisp_msmr_t *mr;
-
- vec_foreach (mr, lcm->map_resolvers)
- {
- if (!mr->is_down)
- {
- ip_address_copy (&lcm->active_map_resolver, &mr->address);
- lcm->do_map_resolver_election = 0;
- return 1;
- }
- }
- return 0;
+#define foreach_msmr \
+ _(server) \
+ _(resolver)
+
+#define _(name) \
+static int \
+elect_map_ ## name (lisp_cp_main_t * lcm) \
+{ \
+ lisp_msmr_t *mr; \
+ vec_foreach (mr, lcm->map_ ## name ## s) \
+ { \
+ if (!mr->is_down) \
+ { \
+ ip_address_copy (&lcm->active_map_ ##name, &mr->address); \
+ lcm->do_map_ ## name ## _election = 0; \
+ return 1; \
+ } \
+ } \
+ return 0; \
}
-
-static void
+foreach_msmr
+#undef _
+ static void
free_map_register_records (mapping_t * maps)
{
mapping_t *map;
/* push outer ip header */
pkt_push_udp_and_ip (vm, b, LISP_CONTROL_PORT, LISP_CONTROL_PORT, sloc,
- ms_ip);
+ ms_ip, 1);
bi_res[0] = bi;
return b;
}
-static int
-get_egress_map_resolver_ip (lisp_cp_main_t * lcm, ip_address_t * ip)
-{
- lisp_msmr_t *mr;
- while (lcm->do_map_resolver_election
- | (0 == ip_fib_get_first_egress_ip_for_dst (lcm,
- &lcm->active_map_resolver,
- ip)))
- {
- if (0 == elect_map_resolver (lcm))
- /* all map resolvers are down */
- {
- /* restart MR checking by marking all of them up */
- vec_foreach (mr, lcm->map_resolvers) mr->is_down = 0;
- return -1;
- }
- }
- return 0;
+#define _(name) \
+static int \
+get_egress_map_ ##name## _ip (lisp_cp_main_t * lcm, ip_address_t * ip) \
+{ \
+ lisp_msmr_t *mr; \
+ while (lcm->do_map_ ## name ## _election \
+ | (0 == ip_fib_get_first_egress_ip_for_dst \
+ (lcm, &lcm->active_map_ ##name, ip))) \
+ { \
+ if (0 == elect_map_ ## name (lcm)) \
+ /* all map resolvers/servers are down */ \
+ { \
+ /* restart MR/MS checking by marking all of them up */ \
+ vec_foreach (mr, lcm->map_ ## name ## s) mr->is_down = 0; \
+ return -1; \
+ } \
+ } \
+ return 0; \
}
+foreach_msmr
+#undef _
/* CP output statistics */
#define foreach_lisp_cp_output_error \
_(MAP_REGISTERS_SENT, "map-registers sent") \
_(RLOC_PROBES_SENT, "rloc-probes sent")
-
static char *lisp_cp_output_error_strings[] = {
#define _(sym,string) string,
foreach_lisp_cp_output_error
f->n_vectors = 1;
vlib_put_frame_to_node (lcm->vlib_main, next_index, f);
- hash_set (lcm->map_register_messages_by_nonce, nonce, 0);
return 0;
}
static int
send_map_register (lisp_cp_main_t * lcm, u8 want_map_notif)
{
+ pending_map_register_t *pmr;
u32 bi, map_registers_sent = 0;
vlib_buffer_t *b;
ip_address_t sloc;
vlib_frame_t *f;
u64 nonce = 0;
u32 next_index, *to_next;
- ip_address_t *ms = 0;
mapping_t *records, *r, *group, *k;
- // TODO: support multiple map servers and do election
- if (0 == vec_len (lcm->map_servers))
+ if (get_egress_map_server_ip (lcm, &sloc) < 0)
return -1;
- ms = &lcm->map_servers[0].address;
-
- if (0 == ip_fib_get_first_egress_ip_for_dst (lcm, ms, &sloc))
- {
- clib_warning ("no eligible interface address found for %U!",
- format_ip_address, &lcm->map_servers[0]);
- return -1;
- }
-
records = build_map_register_record_list (lcm);
if (!records)
return -1;
}
}
- b = build_map_register (lcm, &sloc, ms, &nonce, want_map_notif, group,
- key_id, key, &bi);
+ b = build_map_register (lcm, &sloc, &lcm->active_map_server, &nonce,
+ want_map_notif, group, key_id, key, &bi);
vec_free (group);
if (!b)
continue;
vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
- next_index = (ip_addr_version (&lcm->active_map_resolver) == IP4) ?
+ next_index = (ip_addr_version (&lcm->active_map_server) == IP4) ?
ip4_lookup_node.index : ip6_lookup_node.index;
f = vlib_get_frame_to_node (lcm->vlib_main, next_index);
vlib_put_frame_to_node (lcm->vlib_main, next_index, f);
map_registers_sent++;
- hash_set (lcm->map_register_messages_by_nonce, nonce, 0);
+ pool_get (lcm->pending_map_registers_pool, pmr);
+ memset (pmr, 0, sizeof (*pmr));
+ pmr->time_to_expire = PENDING_MREG_EXPIRATION_TIME;
+ hash_set (lcm->map_register_messages_by_nonce, nonce,
+ pmr - lcm->pending_map_registers_pool);
}
free_map_register_records (records);
to_next,
n_left_to_next, pi0,
next0);
+ continue;
}
- continue;
+ goto done;
}
/* if we have remote mapping for destination already in map-chache
pkts_mapped++;
}
+ done:
b0->error = node->errors[LISP_CP_LOOKUP_ERROR_DROP];
if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
{
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);
}
timing_wheel_insert (&lcm->wheel, exp_clock_time, 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 ();
mapping_t *m;
vec_foreach (m, a->mappings)
{
vec_free (m->locators);
gid_address_free (&m->eid);
}
-
- clib_mem_free (a);
+ pool_put (lcm->map_records_args_pool[vlib_get_thread_index ()], a);
}
void *
pending_map_request_t *pmr;
u64 *noncep;
uword *pmr_index;
+ u8 is_changed = 0;
if (a->is_rloc_probe)
goto done;
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 */
pool_put (lcm->pending_map_requests_pool, pmr);
done:
- map_records_arg_free (a);
+ a->is_free = 1;
return 0;
}
return;
}
- map_records_arg_free (a);
+ a->is_free = 1;
+ pool_put_index (lcm->pending_map_registers_pool, pmr_index[0]);
hash_unset (lcm->map_register_messages_by_nonce, a->nonce);
+
+ /* reset map-notify counter */
+ lcm->expired_map_registers = 0;
}
static mapping_t *
return 0;
}
+static map_records_arg_t *
+map_record_args_get ()
+{
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ map_records_arg_t *rec;
+
+ /* Cleanup first */
+ /* *INDENT-OFF* */
+ pool_foreach (rec, lcm->map_records_args_pool[vlib_get_thread_index()], ({
+ if (rec->is_free)
+ map_records_arg_free (rec);
+ }));
+ /* *INDENT-ON* */
+
+ pool_get (lcm->map_records_args_pool[vlib_get_thread_index ()], rec);
+ return rec;
+}
+
static map_records_arg_t *
parse_map_notify (vlib_buffer_t * b)
{
gid_address_t deid;
u16 auth_data_len = 0;
u8 record_count;
- map_records_arg_t *a = clib_mem_alloc (sizeof (*a));
+ map_records_arg_t *a;
+ a = map_record_args_get ();
memset (a, 0, sizeof (*a));
mnotif_hdr = vlib_buffer_get_current (b);
vlib_buffer_pull (b, sizeof (*mnotif_hdr));
if (!is_auth_data_valid (mnotif_hdr, vlib_buffer_get_tail (b)
- (u8 *) mnotif_hdr, key_id, key))
{
- clib_warning ("Map-notify auth data verification failed for nonce %lu!",
- a->nonce);
+ clib_warning ("Map-notify auth data verification failed for nonce "
+ "0x%lx!", a->nonce);
map_records_arg_free (a);
return 0;
}
lisp_msg_put_map_reply (b, records, nonce, probe_bit);
/* push outer ip header */
- pkt_push_udp_and_ip (vm, b, LISP_CONTROL_PORT, dst_port, sloc, dst);
+ pkt_push_udp_and_ip (vm, b, LISP_CONTROL_PORT, dst_port, sloc, dst, 1);
bi_res[0] = bi;
return b;
static void
find_ip_header (vlib_buffer_t * b, u8 ** ip_hdr)
{
- const i32 start = vnet_buffer (b)->ip.start_of_ip_header;
+ const i32 start = vnet_buffer (b)->l3_hdr_offset;
if (start < 0 && start < -sizeof (b->pre_data))
{
*ip_hdr = 0;
u32 i, len = 0;
mapping_t m;
map_reply_hdr_t *mrep_hdr;
- map_records_arg_t *a = clib_mem_alloc (sizeof (*a));
+ map_records_arg_t *a;
+
+ a = map_record_args_get ();
memset (a, 0, sizeof (*a));
+
locator_t *locators;
mrep_hdr = vlib_buffer_get_current (b);
{
lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
clib_error_t *error = 0;
+ vlib_thread_main_t *vtm = vlib_get_thread_main ();
+ u32 num_threads;
if ((error = vlib_call_init_function (vm, lisp_gpe_init)))
return error;
lcm->lisp_pitr = 0;
lcm->flags = 0;
memset (&lcm->active_map_resolver, 0, sizeof (lcm->active_map_resolver));
+ memset (&lcm->active_map_server, 0, sizeof (lcm->active_map_server));
gid_dictionary_init (&lcm->mapping_index_by_gid);
lcm->do_map_resolver_election = 1;
+ lcm->do_map_server_election = 1;
lcm->map_request_mode = MR_MODE_DST_ONLY;
+ num_threads = 1 /* main thread */ + vtm->n_threads;
+ vec_validate (lcm->map_records_args_pool, num_threads - 1);
+
/* default vrf mapped to vni 0 */
hash_set (lcm->table_id_by_vni, 0, 0);
hash_set (lcm->vni_by_table_id, 0, 0);
u64 now = clib_cpu_time_now ();
timing_wheel_init (&lcm->wheel, now, vm->clib_time.clocks_per_second);
lcm->nsh_map_index = ~0;
+ lcm->map_register_ttl = MAP_REGISTER_DEFAULT_TTL;
+ lcm->max_expired_map_registers = MAX_EXPIRED_MAP_REGISTERS_DEFAULT;
+ lcm->expired_map_registers = 0;
return 0;
}
/* *INDENT-ON* */
vec_foreach (pmr_index, to_be_removed)
- pool_put_index (lcm->pending_map_requests_by_nonce, pmr_index[0]);
+ pool_put_index (lcm->pending_map_requests_pool, pmr_index[0]);
vec_free (to_be_removed);
}
}
}
+static int
+update_pending_map_register (pending_map_register_t * r, f64 dt, u8 * del_all)
+{
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ lisp_msmr_t *ms;
+ del_all[0] = 0;
+
+ r->time_to_expire -= dt;
+
+ if (r->time_to_expire < 0)
+ {
+ lcm->expired_map_registers++;
+
+ if (lcm->expired_map_registers >= lcm->max_expired_map_registers)
+ {
+ ms = get_map_server (&lcm->active_map_server);
+ if (!ms)
+ {
+ clib_warning ("Map server %U not found - probably deleted "
+ "by the user recently.", format_ip_address,
+ &lcm->active_map_server);
+ }
+ else
+ {
+ clib_warning ("map server %U is unreachable, ignoring",
+ format_ip_address, &lcm->active_map_server);
+
+ /* mark current map server unavailable so it won't be
+ * elected next time */
+ ms->is_down = 1;
+ ms->last_update = vlib_time_now (lcm->vlib_main);
+ }
+
+ elect_map_server (lcm);
+
+ /* indication for deleting all pending map registers */
+ del_all[0] = 1;
+ lcm->expired_map_registers = 0;
+ return 0;
+ }
+ else
+ {
+ /* delete pending map register */
+ return 0;
+ }
+ }
+ return 1;
+}
+
static void
update_map_register (lisp_cp_main_t * lcm, f64 dt)
{
+ u32 *to_be_removed = 0, *pmr_index;
static f64 time_left = QUICK_MAP_REGISTER_INTERVAL;
static u64 mreg_sent_counter = 0;
+ pending_map_register_t *pmr;
+ u8 del_all = 0;
+
if (!lcm->is_enabled || !lcm->map_registering)
return;
+ /* *INDENT-OFF* */
+ pool_foreach (pmr, lcm->pending_map_registers_pool,
+ ({
+ if (!update_pending_map_register (pmr, dt, &del_all))
+ {
+ if (del_all)
+ break;
+ vec_add1 (to_be_removed, pmr - lcm->pending_map_registers_pool);
+ }
+ }));
+ /* *INDENT-ON* */
+
+ if (del_all)
+ {
+ /* delete all pending map register messages so they won't
+ * trigger another map server election.. */
+ pool_free (lcm->pending_map_registers_pool);
+ hash_free (lcm->map_register_messages_by_nonce);
+
+ /* ..and trigger registration against next map server (if any) */
+ time_left = 0;
+ }
+ else
+ {
+ vec_foreach (pmr_index, to_be_removed)
+ pool_put_index (lcm->pending_map_registers_pool, pmr_index[0]);
+ }
+
+ vec_free (to_be_removed);
+
time_left -= dt;
if (time_left <= 0)
{
u32 *mi = 0;
vec_foreach (mi, expired)
{
- remove_expired_mapping (lcm, mi[0]);
+ process_expired_mapping (lcm, mi[0]);
}
_vec_len (expired) = 0;
}