diff options
Diffstat (limited to 'hicn-plugin/src/mapme.h')
-rw-r--r-- | hicn-plugin/src/mapme.h | 240 |
1 files changed, 132 insertions, 108 deletions
diff --git a/hicn-plugin/src/mapme.h b/hicn-plugin/src/mapme.h index 17bd9a766..c5567d1d4 100644 --- a/hicn-plugin/src/mapme.h +++ b/hicn-plugin/src/mapme.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -21,9 +21,9 @@ #include <hicn/mapme.h> #include "hicn.h" -#include "route.h" #include "strategy_dpo_ctx.h" -#include "strategy_dpo_manager.h" // dpo_is_hicn +#include "strategy_dpo_manager.h" // dpo_is_hicn +#include "udp_tunnels/udp_tunnel.h" /** * @file @@ -32,53 +32,54 @@ * * Mapme implementation follows the "Anchorless mobility through hICN" document * specification. In particular, the implementation is made of: - * - two internal nodes: hicn-mapme-ctrl and hicn-mapme-ack. The former processes - * IU and the latter IU acknowledgment. - * - a process node, mapme-eventmgr-process, that is signaled every time a face is - * added or deleted, as well as when a new next hop is added to a fib entry as a - * result of a mobility event. + * - two internal nodes: hicn-mapme-ctrl and hicn-mapme-ack. The former + * processes IU and the latter IU acknowledgment. + * - a process node, mapme-eventmgr-process, that is signaled every time a + * face is added or deleted, as well as when a new next hop is added to a fib + * entry as a result of a mobility event. * - * TFIB implementation is done as an extension of an hICN fib entry. In particular, - * the list of next hops hold the list of next hops in the tfib as well (stored at the - * end of the list of regualt next hops). Mapme implementation follows the hICN vrf - * implementation and consider the vrf 0 (default fib) as the control-plane fib to - * update every time a new next hop must be added or removed. + * TFIB implementation is done as an extension of an hICN fib entry. In + * particular, the list of next hops hold the list of next hops in the tfib as + * well (stored at the end of the list of regualt next hops). Mapme + * implementation follows the hICN vrf implementation and consider the vrf 0 + * (default fib) as the control-plane fib to update every time a new next hop + * must be added or removed. */ - #define HICN_MAPME_ALLOW_LOCATORS 1 //#define HICN_MAPME_NOTIFICATIONS 1 #define NOT_A_NOTIFICATION false -#define TIMER_NO_REPEAT false +#define TIMER_NO_REPEAT false #define INVALID_SEQ 0 -STATIC_ASSERT (sizeof(u32) == sizeof(seq_t), - "seq_t is not 4 bytes"); +STATIC_ASSERT (sizeof (u32) == sizeof (seq_t), "seq_t is not 4 bytes"); typedef struct hicn_mapme_conf_s { hicn_mapme_conf_t conf; - bool remove_dpo; // FIXME used ? + bool remove_dpo; // FIXME used ? + fib_prefix_t default_route; vlib_main_t *vm; - vlib_log_class_t log_class; } hicn_mapme_main_t; +extern hicn_mapme_main_t *hicn_mapme_get_main (); + /** * @brief List of event to signat to the procesing node (eventmgr) */ -#define foreach_hicn_mapme_event \ - _(FACE_ADD) \ - _(FACE_DEL) \ - _(FACE_APP_ADD) \ - _(FACE_APP_DEL) \ - _(FACE_NH_SET) \ - _(FACE_NH_ADD) \ - _(FACE_PH_ADD) \ - _(FACE_PH_DEL) +#define foreach_hicn_mapme_event \ + _ (FACE_ADD) \ + _ (FACE_DEL) \ + _ (FACE_APP_ADD) \ + _ (FACE_APP_DEL) \ + _ (FACE_NH_SET) \ + _ (FACE_NH_ADD) \ + _ (FACE_PH_ADD) \ + _ (FACE_PH_DEL) typedef enum { @@ -89,6 +90,21 @@ typedef enum typedef hicn_dpo_ctx_t hicn_mapme_tfib_t; +/** + * FIB Lookup Type + */ +#define foreach_hicn_mapme_fib_lookup_type \ + _ (EPM) \ + _ (LPM) \ + _ (LESSPM) + +typedef enum +{ +#define _(a) HICN_MAPME_FIB_LOOKUP_TYPE_##a, + foreach_hicn_mapme_fib_lookup_type +#undef _ +} hicn_mapme_fib_lookup_type_t; + /* * Ideally we might need to care about alignment, but this struct is only * used for casting hicn_dpo_ctx_t. @@ -99,63 +115,47 @@ typedef hicn_dpo_ctx_t hicn_mapme_tfib_t; STATIC_ASSERT (sizeof (hicn_mapme_tfib_t) <= sizeof (hicn_dpo_ctx_t), "hicn_mapme_tfib_t is greater than hicn_dpo_ctx_t"); -#define TFIB(dpo_ctx) ((hicn_mapme_tfib_t*)(dpo_ctx)) - -static_always_inline int -hicn_mapme_nh_set (hicn_mapme_tfib_t * tfib, hicn_face_id_t face_id) -{ - hicn_dpo_ctx_t * strategy_ctx = (hicn_dpo_ctx_t *)tfib; - const fib_prefix_t * prefix = fib_entry_get_prefix(strategy_ctx->fib_entry_index); - - u32 n_entries = tfib->entry_count; - /* Remove all the existing next hops and set the new one */ - for (int i = 0; i < n_entries; i++) - { - hicn_face_t * face = hicn_dpoi_get_from_idx(strategy_ctx->next_hops[0]); - ip_adjacency_t * adj = adj_get (face->dpo.dpoi_index); - ip_nh_del_helper(face->dpo.dpoi_proto, prefix, &adj->sub_type.nbr.next_hop, face->sw_if); - } - hicn_face_t * face = hicn_dpoi_get_from_idx(face_id); - ip_nh_add_helper(face->dpo.dpoi_proto, prefix, &face->nat_addr, face->sw_if); - return 0; -} +#define TFIB(dpo_ctx) ((hicn_mapme_tfib_t *) (dpo_ctx)) /** - * @brief Add a next hop iif it is not already a next hops + * @brief Check whether a face is already included in the TFIB. + * + * NOTE: linear scan on a contiguous small array should be the most efficient. */ static_always_inline int -hicn_mapme_nh_add (hicn_mapme_tfib_t * tfib, hicn_face_id_t face_id) +hicn_mapme_tfib_has (hicn_mapme_tfib_t *tfib, hicn_face_id_t face_id) { - for (u8 pos = 0; pos < tfib->entry_count; pos++) - if (tfib->next_hops[pos] == face_id) - return 0; - - /* Add the next hop in the vrf 0 which will add it to the entry in the hICN vrf */ - hicn_dpo_ctx_t * strategy_ctx = (hicn_dpo_ctx_t *)tfib; - const fib_prefix_t * prefix = fib_entry_get_prefix(strategy_ctx->fib_entry_index); - hicn_face_t * face = hicn_dpoi_get_from_idx(face_id); - ip_nh_add_helper(face->dpo.dpoi_proto, prefix, &face->nat_addr, face->sw_if); - + u8 pos = HICN_PARAM_FIB_ENTRY_NHOPS_MAX - tfib->tfib_entry_count; + for (u8 pos2 = pos; pos2 < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; pos2++) + if (tfib->next_hops[pos2] == face_id) + return 1; return 0; } /** * Add a 'previous' hop to the TFIB - * - * XXX we should have the for look in the reverse order for simpler code. */ static_always_inline int -hicn_mapme_tfib_add (hicn_mapme_tfib_t * tfib, hicn_face_id_t face_id) +hicn_mapme_tfib_add (hicn_mapme_tfib_t *tfib, hicn_face_id_t face_id) { - u8 pos = HICN_PARAM_FIB_ENTRY_NHOPS_MAX - tfib->tfib_entry_count; + // Don't add if it already exists + // (eg. an old IU received on a face on which we are retransmitting) + if (hicn_mapme_tfib_has (tfib, face_id)) + { + HICN_DEBUG ("Found face %d in tfib."); + return 0; + } - //XXX don 't add if it already exist - // eg.an old IU received on a face on which we are retransmitting - for (u8 pos2 = pos; pos2 < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; pos2++) - if (tfib->next_hops[pos2] == face_id) + // If local face, do not put in in tfib + if (hicn_face_is_local (face_id)) + { + HICN_DEBUG ("Do not add local face %d to TFIB.", face_id); return 0; + } + + u8 pos = HICN_PARAM_FIB_ENTRY_NHOPS_MAX - tfib->tfib_entry_count; - //Make sure we have enough room + // Make sure we have enough room if (pos <= tfib->entry_count) return -1; @@ -166,13 +166,13 @@ hicn_mapme_tfib_add (hicn_mapme_tfib_t * tfib, hicn_face_id_t face_id) * Take a lock on the face as if it will be removed from the next_hops a * lock will be removed. */ - hicn_face_lock_with_id(face_id); + hicn_face_lock_with_id (face_id); return 0; } static_always_inline int -hicn_mapme_tfib_clear (hicn_mapme_tfib_t * tfib) +hicn_mapme_tfib_clear (hicn_mapme_tfib_t *tfib) { hicn_face_id_t invalid = NEXT_HOP_INVALID; /* @@ -182,11 +182,10 @@ hicn_mapme_tfib_clear (hicn_mapme_tfib_t * tfib) u8 start_pos = HICN_PARAM_FIB_ENTRY_NHOPS_MAX - tfib->tfib_entry_count; u8 pos = ~0; for (pos = start_pos; pos < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; pos++) - { - hicn_face_unlock_with_id (tfib->next_hops[pos]); - tfib->next_hops[pos] = invalid; - break; - } + { + hicn_face_unlock_with_id (tfib->next_hops[pos]); + tfib->next_hops[pos] = invalid; + } tfib->tfib_entry_count = 0; @@ -194,7 +193,7 @@ hicn_mapme_tfib_clear (hicn_mapme_tfib_t * tfib) } static_always_inline int -hicn_mapme_tfib_del (hicn_mapme_tfib_t * tfib, hicn_face_id_t face_id) +hicn_mapme_tfib_del (hicn_mapme_tfib_t *tfib, hicn_face_id_t face_id) { hicn_face_id_t invalid = NEXT_HOP_INVALID; /* @@ -203,9 +202,12 @@ hicn_mapme_tfib_del (hicn_mapme_tfib_t * tfib, hicn_face_id_t face_id) */ u8 start_pos = HICN_PARAM_FIB_ENTRY_NHOPS_MAX - tfib->tfib_entry_count; u8 pos = ~0; + for (pos = start_pos; pos < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; pos++) if (tfib->next_hops[pos] == face_id) { + HICN_DEBUG ("Deleted the face_id=%d from TFIB as we received an ack.", + face_id); hicn_face_unlock_with_id (tfib->next_hops[pos]); tfib->next_hops[pos] = invalid; break; @@ -218,37 +220,22 @@ hicn_mapme_tfib_del (hicn_mapme_tfib_t * tfib, hicn_face_id_t face_id) /* Likely we won't receive a new IU twice from the same face */ if (PREDICT_TRUE (pos > start_pos)) - memmove (tfib->next_hops + start_pos +1 , tfib->next_hops + start_pos, + memmove (tfib->next_hops + start_pos + 1, tfib->next_hops + start_pos, (pos - start_pos) * sizeof (hicn_face_id_t)); return 0; } /** - * @brief Performs an Exact Prefix Match lookup on the FIB + * @brief Retrive DPO from fib entry * @returns the corresponding DPO (hICN or IP LB), or NULL */ -static_always_inline - dpo_id_t * fib_epm_lookup (ip46_address_t * addr, u8 plen) +static_always_inline dpo_id_t * +dpo_from_fib_node_index (fib_node_index_t fib_entry_index) { - fib_prefix_t fib_pfx; - fib_node_index_t fib_entry_index; - u32 fib_index; - dpo_id_t *dpo_id; - load_balance_t *lb; - - const dpo_id_t *load_balance_dpo_id; - - /* At this point the face exists in the face table */ - fib_prefix_from_ip46_addr (addr, &fib_pfx); - fib_pfx.fp_len = plen; - - /* Check if the route already exist in the fib : EPM */ - fib_index = fib_table_find (fib_pfx.fp_proto, HICN_FIB_TABLE); - - fib_entry_index = fib_table_lookup_exact_match (fib_index, &fib_pfx); - if (fib_entry_index == FIB_NODE_INDEX_INVALID) - return NULL; + const dpo_id_t *load_balance_dpo_id = NULL; + load_balance_t *lb = NULL; + dpo_id_t *dpo_id = NULL; load_balance_dpo_id = fib_entry_contribute_ip_forwarding (fib_entry_index); @@ -280,6 +267,46 @@ static_always_inline return (dpo_id_t *) load_balance_dpo_id; } +/** + * @brief Performs an Exact Prefix Match lookup on the FIB + * @returns the corresponding DPO (hICN or IP LB), or NULL + */ +static_always_inline dpo_id_t * +fib_lookup (ip46_address_t *addr, u8 plen, + hicn_mapme_fib_lookup_type_t lookup_type) +{ + fib_prefix_t fib_pfx; + fib_node_index_t fib_entry_index; + u32 fib_index; + + /* At this point the face exists in the face table */ + fib_prefix_from_ip46_addr (addr, &fib_pfx); + fib_pfx.fp_len = plen; + + /* Check if the route already exist in the fib : EPM */ + fib_index = fib_table_find (fib_pfx.fp_proto, HICN_FIB_TABLE); + + switch (lookup_type) + { + case HICN_MAPME_FIB_LOOKUP_TYPE_EPM: + fib_entry_index = fib_table_lookup_exact_match (fib_index, &fib_pfx); + break; + case HICN_MAPME_FIB_LOOKUP_TYPE_LPM: + fib_entry_index = fib_table_lookup (fib_index, &fib_pfx); + break; + case HICN_MAPME_FIB_LOOKUP_TYPE_LESSPM: + fib_entry_index = fib_table_get_less_specific (fib_index, &fib_pfx); + break; + default: + return NULL; + } + + if (fib_entry_index == FIB_NODE_INDEX_INVALID) + return NULL; + + return dpo_from_fib_node_index (fib_entry_index); +} + /* DPO types */ extern dpo_type_t hicn_face_udp_type; @@ -294,14 +321,15 @@ extern u32 strategy_face_ip6_vlib_edge; extern u32 strategy_face_udp4_vlib_edge; extern u32 strategy_face_udp6_vlib_edge; - /** - * @brief Returns the next hop vlib edge on which we can send an Interest packet. + * @brief Returns the next hop vlib edge on which we can send an Interest + * packet. * - * This is both used to preprocess a dpo that will be stored as a next hop in the FIB, and to determine on which node to send an Interest Update. + * This is both used to preprocess a dpo that will be stored as a next hop in + * the FIB, and to determine on which node to send an Interest Update. */ always_inline u32 -hicn_mapme_get_dpo_vlib_edge (dpo_id_t * dpo) +hicn_mapme_get_dpo_vlib_edge (dpo_id_t *dpo) { if (dpo->dpoi_type == hicn_face_ip_type) { @@ -339,7 +367,7 @@ hicn_mapme_get_dpo_vlib_edge (dpo_id_t * dpo) always_inline char * hicn_mapme_get_dpo_face_node (hicn_face_id_t face_id) { - hicn_face_t * face = hicn_dpoi_get_from_idx(face_id); + hicn_face_t *face = hicn_dpoi_get_from_idx (face_id); switch (face->dpo.dpoi_proto) { @@ -352,10 +380,6 @@ hicn_mapme_get_dpo_face_node (hicn_face_id_t face_id) } } -#define DEBUG(...) //vlib_log_debug(mapme_main.log_class, __VA_ARGS__) -#define WARN(...) //vlib_log_warn(mapme_main.log_class, __VA_ARGS__) -#define ERROR(...) //vlib_log_err(mapme_main.log_class, __VA_ARGS__) - #endif /* __HICN_MAPME__ */ /* |