aboutsummaryrefslogtreecommitdiffstats
path: root/vnet/vnet/lisp-gpe/ip_forward.c
diff options
context:
space:
mode:
Diffstat (limited to 'vnet/vnet/lisp-gpe/ip_forward.c')
-rw-r--r--vnet/vnet/lisp-gpe/ip_forward.c1593
1 files changed, 179 insertions, 1414 deletions
diff --git a/vnet/vnet/lisp-gpe/ip_forward.c b/vnet/vnet/lisp-gpe/ip_forward.c
index bd9951ac..8a24ec03 100644
--- a/vnet/vnet/lisp-gpe/ip_forward.c
+++ b/vnet/vnet/lisp-gpe/ip_forward.c
@@ -12,1492 +12,257 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/**
- * @file
- * @brief LISP-GPE overlay IP forwarding logic and lookup data structures.
- *
- * Provides an implementation of a Source/Dest (SD) IP FIB that leverages the
- * existing destination only FIB. Lookups are done in two stages, first the
- * destination FIB looks up a packet's destination address and then if a
- * an SD entry is hit, the destination adjacency will point to the second
- * stage, the source FIB, where the packet's source is looked up. Note that a
- * miss in the source FIB does not result in an overall SD lookup retry with
- * a less specific entry from the destination FIB.
- */
-#include <vnet/lisp-gpe/lisp_gpe.h>
-
-/** Sets adj index for destination address in IP4 FIB. Similar to the function
- * in ip4_forward but this one avoids calling route callbacks */
-static void
-ip4_sd_fib_set_adj_index (lisp_gpe_main_t * lgm, ip4_fib_t * fib, u32 flags,
- u32 dst_address_u32, u32 dst_address_length,
- u32 adj_index)
-{
- ip_lookup_main_t *lm = lgm->lm4;
- uword *hash;
-
- if (vec_bytes (fib->old_hash_values))
- memset (fib->old_hash_values, ~0, vec_bytes (fib->old_hash_values));
- if (vec_bytes (fib->new_hash_values))
- memset (fib->new_hash_values, ~0, vec_bytes (fib->new_hash_values));
- fib->new_hash_values[0] = adj_index;
-
- /* Make sure adj index is valid. */
- if (CLIB_DEBUG > 0)
- (void) ip_get_adjacency (lm, adj_index);
-
- hash = fib->adj_index_by_dst_address[dst_address_length];
-
- hash = _hash_set3 (hash, dst_address_u32,
- fib->new_hash_values, fib->old_hash_values);
-
- fib->adj_index_by_dst_address[dst_address_length] = hash;
-}
-
-/** Initialize the adjacency index by destination address vector for IP4 FIB.
- * Copied from ip4_forward since it's static */
-static void
-ip4_fib_init_adj_index_by_dst_address (ip_lookup_main_t * lm,
- ip4_fib_t * fib, u32 address_length)
-{
- hash_t *h;
- uword max_index;
-
- ASSERT (lm->fib_result_n_bytes >= sizeof (uword));
- lm->fib_result_n_words = round_pow2 (lm->fib_result_n_bytes, sizeof (uword))
- / sizeof (uword);
-
- fib->adj_index_by_dst_address[address_length] =
- hash_create (32 /* elts */ , lm->fib_result_n_words * sizeof (uword));
-
- hash_set_flags (fib->adj_index_by_dst_address[address_length],
- HASH_FLAG_NO_AUTO_SHRINK);
-
- h = hash_header (fib->adj_index_by_dst_address[address_length]);
- max_index = (hash_value_bytes (h) / sizeof (fib->new_hash_values[0])) - 1;
-
- /* Initialize new/old hash value vectors. */
- vec_validate_init_empty (fib->new_hash_values, max_index, ~0);
- vec_validate_init_empty (fib->old_hash_values, max_index, ~0);
-}
-
-/** Add/del src route to IP4 SD FIB. */
-static void
-ip4_sd_fib_add_del_src_route (lisp_gpe_main_t * lgm,
- ip4_add_del_route_args_t * a)
-{
- ip_lookup_main_t *lm = lgm->lm4;
- ip4_fib_t *fib;
- u32 dst_address, dst_address_length, adj_index, old_adj_index;
- uword *hash, is_del;
-
- /* Either create new adjacency or use given one depending on arguments. */
- if (a->n_add_adj > 0)
- ip_add_adjacency (lm, a->add_adj, a->n_add_adj, &adj_index);
- else
- adj_index = a->adj_index;
-
- dst_address = a->dst_address.data_u32;
- dst_address_length = a->dst_address_length;
-
- fib = pool_elt_at_index (lgm->ip4_src_fibs, a->table_index_or_table_id);
-
- if (!fib->adj_index_by_dst_address[dst_address_length])
- ip4_fib_init_adj_index_by_dst_address (lm, fib, dst_address_length);
-
- hash = fib->adj_index_by_dst_address[dst_address_length];
-
- is_del = (a->flags & IP4_ROUTE_FLAG_DEL) != 0;
-
- if (is_del)
- {
- fib->old_hash_values[0] = ~0;
- hash = _hash_unset (hash, dst_address, fib->old_hash_values);
- fib->adj_index_by_dst_address[dst_address_length] = hash;
- }
- else
- ip4_sd_fib_set_adj_index (lgm, fib, a->flags, dst_address,
- dst_address_length, adj_index);
-
- old_adj_index = fib->old_hash_values[0];
-
- /* Avoid spurious reference count increments */
- if (old_adj_index == adj_index
- && adj_index != ~0 && !(a->flags & IP4_ROUTE_FLAG_KEEP_OLD_ADJACENCY))
- {
- ip_adjacency_t *adj = ip_get_adjacency (lm, adj_index);
- if (adj->share_count > 0)
- adj->share_count--;
- }
-
- ip4_fib_mtrie_add_del_route (fib, a->dst_address, dst_address_length,
- is_del ? old_adj_index : adj_index, is_del);
-
- /* Delete old adjacency index if present and changed. */
- if (!(a->flags & IP4_ROUTE_FLAG_KEEP_OLD_ADJACENCY)
- && old_adj_index != ~0 && old_adj_index != adj_index)
- ip_del_adjacency (lm, old_adj_index);
-}
-
-/** Get src route from IP4 SD FIB. */
-static void *
-ip4_sd_get_src_route (lisp_gpe_main_t * lgm, u32 src_fib_index,
- ip4_address_t * src, u32 address_length)
-{
- ip4_fib_t *fib = pool_elt_at_index (lgm->ip4_src_fibs, src_fib_index);
- uword *hash, *p;
- hash = fib->adj_index_by_dst_address[address_length];
- p = hash_get (hash, src->as_u32);
- return (void *) p;
-}
-
-/* *INDENT-OFF* */
-typedef CLIB_PACKED (struct ip4_route {
- ip4_address_t address;
- u32 address_length : 6;
- u32 index : 26;
-}) ip4_route_t;
-/* *INDENT-ON* */
-
-/** Remove all routes from src IP4 FIB */
-void
-ip4_sd_fib_clear_src_fib (lisp_gpe_main_t * lgm, ip4_fib_t * fib)
-{
- ip4_route_t *routes = 0, *r;
- u32 i;
-
- vec_reset_length (routes);
-
- for (i = 0; i < ARRAY_LEN (fib->adj_index_by_dst_address); i++)
- {
- uword *hash = fib->adj_index_by_dst_address[i];
- hash_pair_t *p;
- ip4_route_t x;
-
- x.address_length = i;
- x.index = 0; /* shut up coverity */
-
- /* *INDENT-OFF* */
- hash_foreach_pair (p, hash,
- ({
- x.address.data_u32 = p->key;
- vec_add1 (routes, x);
- }));
- /* *INDENT-ON* */
- }
-
- vec_foreach (r, routes)
- {
- ip4_add_del_route_args_t a;
-
- memset (&a, 0, sizeof (a));
- a.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_DEL;
- a.table_index_or_table_id = fib - lgm->ip4_src_fibs;
- a.dst_address = r->address;
- a.dst_address_length = r->address_length;
- a.adj_index = ~0;
-
- ip4_sd_fib_add_del_src_route (lgm, &a);
- }
-}
-
-/** Test if IP4 FIB is empty */
-static u8
-ip4_fib_is_empty (ip4_fib_t * fib)
-{
- u8 fib_is_empty;
- int i;
-
- fib_is_empty = 1;
- for (i = ARRAY_LEN (fib->adj_index_by_dst_address) - 1; i >= 0; i--)
- {
- uword *hash = fib->adj_index_by_dst_address[i];
- uword n_elts = hash_elts (hash);
- if (n_elts)
- {
- fib_is_empty = 0;
- break;
- }
- }
- return fib_is_empty;
-}
+#include <vnet/lisp-gpe/lisp_gpe_adjacency.h>
+#include <vnet/fib/fib_table.h>
+#include <vnet/fib/fib_entry.h>
+#include <vnet/fib/ip6_fib.h>
+#include <vnet/fib/ip4_fib.h>
+#include <vnet/dpo/lookup_dpo.h>
+#include <vnet/dpo/load_balance.h>
/**
- * @brief Add/del route to IP4 SD FIB.
- *
- * Adds/remove routes to both destination and source FIBs. Entries added
- * to destination FIB are associated to adjacencies that point to the source
- * FIB and store the index of the particular source FIB associated to the
- * destination. Source FIBs are locally managed (see @ref lgm->ip4_src_fibs
- * and @ref lgm->ip6_src_fibs), but the adjacencies are allocated out of the
- * global adjacency pool.
+ * @brief Add route to IP4 or IP6 Destination FIB.
*
- * @param[in] lgm Reference to @ref lisp_gpe_main_t.
- * @param[out] dst_prefix Destination IP4 prefix.
- * @param[in] src_prefix Source IP4 prefix.
- * @param[in] table_id Table id.
- * @param[in] add_adj Pointer to the adjacency to be added.
- * @param[in] is_add Add/del flag.
+ * Add a route to the destination FIB that results in the lookup
+ * in the SRC FIB. The SRC FIB is created is it does not yet exist.
*
- * @return 0 on success.
+ * @param[in] dst_table_id Destination FIB Table-ID
+ * @param[in] dst_prefix Destination IP prefix.
+ * @param[out] src_fib_index The index/ID of the SRC FIB created.
*/
-static int
-ip4_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
- ip_prefix_t * src_prefix, u32 table_id,
- ip_adjacency_t * add_adj, u8 is_add)
-{
- uword *p;
- ip4_add_del_route_args_t a;
- ip_adjacency_t *dst_adjp, dst_adj;
- ip4_address_t dst = ip_prefix_v4 (dst_prefix), src;
- u32 dst_address_length = ip_prefix_len (dst_prefix), src_address_length = 0;
- ip4_fib_t *src_fib;
-
- if (src_prefix)
- {
- src = ip_prefix_v4 (src_prefix);
- src_address_length = ip_prefix_len (src_prefix);
- }
- else
- memset (&src, 0, sizeof (src));
-
- /* lookup dst adj */
- p = ip4_get_route (lgm->im4, table_id, 0, dst.as_u8, dst_address_length);
-
- if (is_add)
- {
- /* insert dst prefix to ip4 fib, if it's not in yet */
- if (p == 0)
- {
- /* allocate and init src ip4 fib */
- pool_get (lgm->ip4_src_fibs, src_fib);
- ip4_mtrie_init (&src_fib->mtrie);
-
- /* configure adjacency */
- memset (&dst_adj, 0, sizeof (dst_adj));
-
- /* reuse rewrite header to store pointer to src fib */
- dst_adj.rewrite_header.sw_if_index = src_fib - lgm->ip4_src_fibs;
-
- /* dst adj should point to lisp gpe lookup */
- dst_adj.lookup_next_index = lgm->ip4_lookup_next_lgpe_ip4_lookup;
-
- /* explicit_fib_index is used in IP6 FIB lookup, don't reuse it */
- dst_adj.explicit_fib_index = ~0;
- dst_adj.n_adj = 1;
-
- /* make sure we have different signatures for adj in different tables
- * but with the same lookup_next_index and for adj in the same table
- * but associated to different destinations */
- dst_adj.if_address_index = table_id;
- dst_adj.indirect.next_hop.ip4 = dst;
-
- memset (&a, 0, sizeof (a));
- a.flags = IP4_ROUTE_FLAG_TABLE_ID;
- a.table_index_or_table_id = table_id; /* vrf */
- a.adj_index = ~0;
- a.dst_address_length = dst_address_length;
- a.dst_address = dst;
- a.flags |= IP4_ROUTE_FLAG_ADD;
- a.add_adj = &dst_adj;
- a.n_add_adj = 1;
-
- ip4_add_del_route (lgm->im4, &a);
-
- /* lookup dst adj to obtain the adj index */
- p = ip4_get_route (lgm->im4, table_id, 0, dst.as_u8,
- dst_address_length);
-
- /* make sure insertion succeeded */
- if (CLIB_DEBUG)
- {
- ASSERT (p != 0);
- dst_adjp = ip_get_adjacency (lgm->lm4, p[0]);
- ASSERT (dst_adjp->rewrite_header.sw_if_index
- == dst_adj.rewrite_header.sw_if_index);
- }
- }
- }
- else
- {
- if (p == 0)
- {
- clib_warning
- ("Trying to delete inexistent dst route for %U. Aborting",
- format_ip4_address_and_length, dst.as_u8, dst_address_length);
- return -1;
- }
- }
-
- dst_adjp = ip_get_adjacency (lgm->lm4, p[0]);
-
- /* add/del src prefix to src fib */
- memset (&a, 0, sizeof (a));
- a.flags = IP4_ROUTE_FLAG_TABLE_ID;
- a.table_index_or_table_id = dst_adjp->rewrite_header.sw_if_index;
- a.adj_index = ~0;
- a.flags |= is_add ? IP4_ROUTE_FLAG_ADD : IP4_ROUTE_FLAG_DEL;
- a.add_adj = add_adj;
- a.n_add_adj = is_add ? 1 : 0;
- /* if src prefix is null, add 0/0 */
- a.dst_address_length = src_address_length;
- a.dst_address = src;
- ip4_sd_fib_add_del_src_route (lgm, &a);
-
- /* make sure insertion succeeded */
- if (CLIB_DEBUG && is_add)
- {
- uword *sai;
- ip_adjacency_t *src_adjp;
- sai = ip4_sd_get_src_route (lgm, dst_adjp->rewrite_header.sw_if_index,
- &src, src_address_length);
- ASSERT (sai != 0);
- src_adjp = ip_get_adjacency (lgm->lm4, sai[0]);
- ASSERT (src_adjp->if_address_index == add_adj->if_address_index);
- }
-
- /* if a delete, check if there are elements left in the src fib */
- if (!is_add)
- {
- src_fib = pool_elt_at_index (lgm->ip4_src_fibs,
- dst_adjp->rewrite_header.sw_if_index);
- if (!src_fib)
- return 0;
-
- /* if there's nothing left */
- if (ip4_fib_is_empty (src_fib))
- {
- /* remove the src fib .. */
- pool_put (lgm->ip4_src_fibs, src_fib);
-
- /* .. and remove dst route */
- memset (&a, 0, sizeof (a));
- a.flags = IP4_ROUTE_FLAG_TABLE_ID;
- a.table_index_or_table_id = table_id; /* vrf */
- a.adj_index = ~0;
- a.dst_address_length = dst_address_length;
- a.dst_address = dst;
- a.flags |= IP4_ROUTE_FLAG_DEL;
-
- ip4_add_del_route (lgm->im4, &a);
- }
- }
-
- return 0;
-}
-
-/**
- * @brief Retrieve IP4 SD FIB entry.
- *
- * Looks up SD IP4 route by first looking up the destination in VPP's main FIB
- * and subsequently the source in the src FIB. The index of the source FIB is
- * stored in the dst adjacency's rewrite_header.sw_if_index. If source is 0
- * do search with 0/0 src.
- *
- * @param[in] lgm Reference to @ref lisp_gpe_main_t.
- * @param[out] dst_prefix Destination IP4 prefix.
- * @param[in] src_prefix Source IP4 prefix.
- * @param[in] table_id Table id.
- *
- * @return pointer to the adjacency if route found.
- */
-static void *
-ip4_sd_fib_get_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
- ip_prefix_t * src_prefix, u32 table_id)
-{
- uword *p;
- ip4_address_t dst = ip_prefix_v4 (dst_prefix), src;
- u32 dst_address_length = ip_prefix_len (dst_prefix), src_address_length = 0;
- ip_adjacency_t *dst_adj;
-
- if (src_prefix)
- {
- src = ip_prefix_v4 (src_prefix);
- src_address_length = ip_prefix_len (src_prefix);
- }
- else
- memset (&src, 0, sizeof (src));
-
- /* lookup dst adj */
- p = ip4_get_route (lgm->im4, table_id, 0, dst.as_u8, dst_address_length);
- if (p == 0)
- return p;
-
- dst_adj = ip_get_adjacency (lgm->lm4, p[0]);
- return ip4_sd_get_src_route (lgm, dst_adj->rewrite_header.sw_if_index, &src,
- src_address_length);
-}
-
-/** Get src route from IP6 SD FIB. */
-static u32
-ip6_sd_get_src_route (lisp_gpe_main_t * lgm, u32 src_fib_index,
- ip6_address_t * src, u32 address_length)
-{
- int rv;
- BVT (clib_bihash_kv) kv, value;
- ip6_src_fib_t *fib = pool_elt_at_index (lgm->ip6_src_fibs, src_fib_index);
-
- ip6_address_t *mask;
-
- ASSERT (address_length <= 128);
-
- mask = &fib->fib_masks[address_length];
-
- kv.key[0] = src->as_u64[0] & mask->as_u64[0];
- kv.key[1] = src->as_u64[1] & mask->as_u64[1];
- kv.key[2] = address_length;
-
- rv = BV (clib_bihash_search_inline_2) (&fib->ip6_lookup_table, &kv, &value);
- if (rv == 0)
- return value.value;
-
- return 0;
-}
-
-static void
-compute_prefix_lengths_in_search_order (ip6_src_fib_t * fib)
-{
- int i;
- vec_reset_length (fib->prefix_lengths_in_search_order);
- /* Note: bitmap reversed so this is in fact a longest prefix match */
-
- /* *INDENT-OFF* */
- clib_bitmap_foreach(i, fib->non_empty_dst_address_length_bitmap, ({
- int dst_address_length = 128 - i;
- vec_add1 (fib->prefix_lengths_in_search_order, dst_address_length);
- }));
- /* *INDENT-ON* */
-}
-
-/** Add/del src route to IP6 SD FIB. Rewrite of ip6_add_del_route() because
- * it uses im6 to find the FIB .*/
-static void
-ip6_sd_fib_add_del_src_route (lisp_gpe_main_t * lgm,
- ip6_add_del_route_args_t * a)
+u32
+ip_dst_fib_add_route (u32 dst_fib_index, const ip_prefix_t * dst_prefix)
{
- ip_lookup_main_t *lm = lgm->lm6;
- ip6_src_fib_t *fib;
- ip6_address_t dst_address;
- u32 dst_address_length, adj_index;
- uword is_del;
- u32 old_adj_index = ~0;
- BVT (clib_bihash_kv) kv, value;
-
- vlib_smp_unsafe_warning ();
-
- is_del = (a->flags & IP6_ROUTE_FLAG_DEL) != 0;
+ fib_node_index_t src_fib_index;
+ fib_prefix_t dst_fib_prefix;
+ fib_node_index_t dst_fei;
- /* Either create new adjacency or use given one depending on arguments. */
- if (a->n_add_adj > 0)
- {
- ip_add_adjacency (lm, a->add_adj, a->n_add_adj, &adj_index);
- }
- else
- adj_index = a->adj_index;
+ ASSERT (NULL != dst_prefix);
- dst_address = a->dst_address;
- dst_address_length = a->dst_address_length;
- fib = pool_elt_at_index (lgm->ip6_src_fibs, a->table_index_or_table_id);
+ ip_prefix_to_fib_prefix (dst_prefix, &dst_fib_prefix);
- ASSERT (dst_address_length < ARRAY_LEN (fib->fib_masks));
- ip6_address_mask (&dst_address, &fib->fib_masks[dst_address_length]);
+ /*
+ * lookup the destination prefix in the VRF table and retrieve the
+ * LISP associated data
+ */
+ dst_fei = fib_table_lookup_exact_match (dst_fib_index, &dst_fib_prefix);
- /* refcount accounting */
- if (is_del)
+ /*
+ * If the FIB entry is not present, or not LISP sourced, add it
+ */
+ if (dst_fei == FIB_NODE_INDEX_INVALID ||
+ NULL == fib_entry_get_source_data (dst_fei, FIB_SOURCE_LISP))
{
- ASSERT (fib->dst_address_length_refcounts[dst_address_length] > 0);
- if (--fib->dst_address_length_refcounts[dst_address_length] == 0)
- {
- fib->non_empty_dst_address_length_bitmap =
- clib_bitmap_set (fib->non_empty_dst_address_length_bitmap,
- 128 - dst_address_length, 0);
- compute_prefix_lengths_in_search_order (fib);
- }
+ dpo_id_t src_lkup_dpo = DPO_NULL;
+
+ /* create a new src FIB. */
+ src_fib_index =
+ fib_table_create_and_lock (dst_fib_prefix.fp_proto,
+ "LISP-src for [%d,%U]",
+ dst_fib_index,
+ format_fib_prefix, &dst_fib_prefix);
+
+ /*
+ * create a data-path object to perform the source address lookup
+ * in the SRC FIB
+ */
+ lookup_dpo_add_or_lock_w_fib_index (src_fib_index,
+ (ip_prefix_version (dst_prefix) ==
+ IP6 ? DPO_PROTO_IP6 :
+ DPO_PROTO_IP4),
+ LOOKUP_INPUT_SRC_ADDR,
+ LOOKUP_TABLE_FROM_CONFIG,
+ &src_lkup_dpo);
+
+ /*
+ * add the entry to the destination FIB that uses the lookup DPO
+ */
+ dst_fei = fib_table_entry_special_dpo_add (dst_fib_index,
+ &dst_fib_prefix,
+ FIB_SOURCE_LISP,
+ FIB_ENTRY_FLAG_EXCLUSIVE,
+ &src_lkup_dpo);
+
+ /*
+ * the DPO is locked by the FIB entry, and we have no further
+ * need for it.
+ */
+ dpo_unlock (&src_lkup_dpo);
+
+ /*
+ * save the SRC FIB index on the entry so we can retrieve it for
+ * subsequent routes.
+ */
+ fib_entry_set_source_data (dst_fei, FIB_SOURCE_LISP, &src_fib_index);
}
else
{
- fib->dst_address_length_refcounts[dst_address_length]++;
-
- fib->non_empty_dst_address_length_bitmap =
- clib_bitmap_set (fib->non_empty_dst_address_length_bitmap,
- 128 - dst_address_length, 1);
- compute_prefix_lengths_in_search_order (fib);
- }
-
- kv.key[0] = dst_address.as_u64[0];
- kv.key[1] = dst_address.as_u64[1];
- kv.key[2] = dst_address_length;
-
- if (BV (clib_bihash_search) (&fib->ip6_lookup_table, &kv, &value) == 0)
- old_adj_index = value.value;
-
- if (is_del)
- BV (clib_bihash_add_del) (&fib->ip6_lookup_table, &kv, 0 /* is_add */ );
- else
- {
- /* Make sure adj index is valid. */
- if (CLIB_DEBUG > 0)
- (void) ip_get_adjacency (lm, adj_index);
-
- kv.value = adj_index;
-
- BV (clib_bihash_add_del) (&fib->ip6_lookup_table, &kv, 1 /* is_add */ );
+ /*
+ * destination FIB entry already present
+ */
+ src_fib_index = *(u32 *) fib_entry_get_source_data (dst_fei,
+ FIB_SOURCE_LISP);
}
- /* Avoid spurious reference count increments */
- if (old_adj_index == adj_index
- && !(a->flags & IP6_ROUTE_FLAG_KEEP_OLD_ADJACENCY))
- {
- ip_adjacency_t *adj = ip_get_adjacency (lm, adj_index);
- if (adj->share_count > 0)
- adj->share_count--;
- }
-
- /* Delete old adjacency index if present and changed. */
- {
- if (!(a->flags & IP6_ROUTE_FLAG_KEEP_OLD_ADJACENCY)
- && old_adj_index != ~0 && old_adj_index != adj_index)
- ip_del_adjacency (lm, old_adj_index);
- }
-}
-
-static void
-ip6_src_fib_init (ip6_src_fib_t * fib)
-{
- uword i;
-
- for (i = 0; i < ARRAY_LEN (fib->fib_masks); i++)
- {
- u32 j, i0, i1;
-
- i0 = i / 32;
- i1 = i % 32;
-
- for (j = 0; j < i0; j++)
- fib->fib_masks[i].as_u32[j] = ~0;
-
- if (i1)
- fib->fib_masks[i].as_u32[i0] =
- clib_host_to_net_u32 (pow2_mask (i1) << (32 - i1));
- }
-
- if (fib->lookup_table_nbuckets == 0)
- fib->lookup_table_nbuckets = IP6_FIB_DEFAULT_HASH_NUM_BUCKETS;
-
- fib->lookup_table_nbuckets = 1 << max_log2 (fib->lookup_table_nbuckets);
-
- if (fib->lookup_table_size == 0)
- fib->lookup_table_size = IP6_FIB_DEFAULT_HASH_MEMORY_SIZE;
-
- BV (clib_bihash_init) (&fib->ip6_lookup_table, "ip6 lookup table",
- fib->lookup_table_nbuckets, fib->lookup_table_size);
-
+ return (src_fib_index);
}
/**
- * @brief Add/del route to IP6 SD FIB.
- *
- * Adds/remove routes to both destination and source FIBs. Entries added
- * to destination FIB are associated to adjacencies that point to the source
- * FIB and store the index of the particular source FIB associated to the
- * destination. Source FIBs are locally managed (see @ref lgm->ip4_src_fibs
- * and @ref lgm->ip6_src_fibs), but the adjacencies are allocated out of the
- * global adjacency pool.
+ * @brief Del route to IP4 or IP6 SD FIB.
*
- * @param[in] lgm Reference to @ref lisp_gpe_main_t.
- * @param[out] dst_prefix Destination IP6 prefix.
- * @param[in] src_prefix Source IP6 prefix.
- * @param[in] table_id Table id.
- * @param[in] add_adj Pointer to the adjacency to be added.
- * @param[in] is_add Add/del flag.
+ * Remove routes from both destination and source FIBs.
*
- * @return 0 on success.
+ * @param[in] src_fib_index The index/ID of the SRC FIB
+ * @param[in] src_prefix Source IP prefix.
+ * @param[in] dst_fib_index The index/ID of the DST FIB
+ * @param[in] dst_prefix Destination IP prefix.
*/
-static int
-ip6_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
- ip_prefix_t * src_prefix, u32 table_id,
- ip_adjacency_t * add_adj, u8 is_add)
+void
+ip_src_dst_fib_del_route (u32 src_fib_index,
+ const ip_prefix_t * src_prefix,
+ u32 dst_fib_index, const ip_prefix_t * dst_prefix)
{
- u32 adj_index;
- ip6_add_del_route_args_t a;
- ip_adjacency_t *dst_adjp, dst_adj;
- ip6_address_t dst = ip_prefix_v6 (dst_prefix), src;
- u32 dst_address_length = ip_prefix_len (dst_prefix), src_address_length = 0;
- ip6_src_fib_t *src_fib;
-
- if (src_prefix)
- {
- src = ip_prefix_v6 (src_prefix);
- src_address_length = ip_prefix_len (src_prefix);
- }
- else
- memset (&src, 0, sizeof (src));
-
- /* lookup dst adj and create it if it doesn't exist */
- adj_index = ip6_get_route (lgm->im6, table_id, 0, &dst, dst_address_length);
+ fib_prefix_t dst_fib_prefix, src_fib_prefix;
- if (is_add)
- {
- /* insert dst prefix to ip6 fib, if it's not in yet */
- if (adj_index == 0)
- {
- /* allocate and init src ip6 fib */
- pool_get (lgm->ip6_src_fibs, src_fib);
- memset (src_fib, 0, sizeof (src_fib[0]));
- ip6_src_fib_init (src_fib);
-
- memset (&dst_adj, 0, sizeof (dst_adj));
-
- /* reuse rewrite header to store pointer to src fib */
- dst_adj.rewrite_header.sw_if_index = src_fib - lgm->ip6_src_fibs;
-
- /* dst adj should point to lisp gpe ip lookup */
- dst_adj.lookup_next_index = lgm->ip6_lookup_next_lgpe_ip6_lookup;
-
- /* explicit_fib_index is used in IP6 FIB lookup, don't reuse it */
- dst_adj.explicit_fib_index = ~0;
- dst_adj.n_adj = 1;
-
- /* make sure we have different signatures for adj in different tables
- * but with the same lookup_next_index and for adj in the same table
- * but associated to different destinations */
- dst_adj.if_address_index = table_id;
- dst_adj.indirect.next_hop.ip6 = dst;
-
- memset (&a, 0, sizeof (a));
- a.flags = IP6_ROUTE_FLAG_TABLE_ID;
- a.table_index_or_table_id = table_id; /* vrf */
- a.adj_index = ~0;
- a.dst_address_length = dst_address_length;
- a.dst_address = dst;
- a.flags |= IP6_ROUTE_FLAG_ADD;
- a.add_adj = &dst_adj;
- a.n_add_adj = 1;
-
- ip6_add_del_route (lgm->im6, &a);
-
- /* lookup dst adj to obtain the adj index */
- adj_index = ip6_get_route (lgm->im6, table_id, 0, &dst,
- dst_address_length);
-
- /* make sure insertion succeeded */
- if (CLIB_DEBUG)
- {
- ASSERT (adj_index != 0);
- dst_adjp = ip_get_adjacency (lgm->lm6, adj_index);
- ASSERT (dst_adjp->rewrite_header.sw_if_index
- == dst_adj.rewrite_header.sw_if_index);
- }
- }
- }
- else
- {
- if (adj_index == 0)
- {
- clib_warning
- ("Trying to delete inexistent dst route for %U. Aborting",
- format_ip_prefix, dst_prefix);
- return -1;
- }
- }
-
- dst_adjp = ip_get_adjacency (lgm->lm6, adj_index);
-
- /* add/del src prefix to src fib */
- memset (&a, 0, sizeof (a));
- a.flags = IP6_ROUTE_FLAG_TABLE_ID;
- a.table_index_or_table_id = dst_adjp->rewrite_header.sw_if_index;
- a.adj_index = ~0;
- a.flags |= is_add ? IP6_ROUTE_FLAG_ADD : IP6_ROUTE_FLAG_DEL;
- a.add_adj = add_adj;
- a.n_add_adj = is_add ? 1 : 0;
- /* if src prefix is null, add ::0 */
- a.dst_address_length = src_address_length;
- a.dst_address = src;
- ip6_sd_fib_add_del_src_route (lgm, &a);
-
- /* make sure insertion succeeded */
- if (CLIB_DEBUG && is_add)
- {
- u32 sai;
- ip_adjacency_t *src_adjp;
- sai = ip6_sd_get_src_route (lgm, dst_adjp->rewrite_header.sw_if_index,
- &src, src_address_length);
- ASSERT (sai != 0);
- src_adjp = ip_get_adjacency (lgm->lm6, sai);
- ASSERT (src_adjp->if_address_index == add_adj->if_address_index);
- }
-
- /* if a delete, check if there are elements left in the src fib */
- if (!is_add)
- {
- src_fib = pool_elt_at_index (lgm->ip6_src_fibs,
- dst_adjp->rewrite_header.sw_if_index);
- if (!src_fib)
- return 0;
-
- /* if there's nothing left */
- if (clib_bitmap_count_set_bits
- (src_fib->non_empty_dst_address_length_bitmap) == 0)
- {
- /* remove src fib .. */
- pool_put (lgm->ip6_src_fibs, src_fib);
+ ASSERT (NULL != dst_prefix);
+ ASSERT (NULL != src_prefix);
- /* .. and remove dst route */
- memset (&a, 0, sizeof (a));
- a.flags = IP6_ROUTE_FLAG_TABLE_ID;
- a.table_index_or_table_id = table_id; /* vrf */
- a.adj_index = ~0;
- a.dst_address_length = dst_address_length;
- a.dst_address = dst;
- a.flags |= IP6_ROUTE_FLAG_DEL;
+ ip_prefix_to_fib_prefix (dst_prefix, &dst_fib_prefix);
+ ip_prefix_to_fib_prefix (src_prefix, &src_fib_prefix);
- ip6_add_del_route (lgm->im6, &a);
- }
- }
-
- return 0;
-}
+ fib_table_entry_delete (src_fib_index, &src_fib_prefix, FIB_SOURCE_LISP);
-/**
- * @brief Retrieve IP6 SD FIB entry.
- *
- * Looks up SD IP6 route by first looking up the destination in VPP's main FIB
- * and subsequently the source in the src FIB. The index of the source FIB is
- * stored in the dst adjacency's @ref rewrite_header.sw_if_index. If source is
- * 0 do search with ::/0 src.
- *
- * @param[in] lgm Reference to @ref lisp_gpe_main_t.
- * @param[out] dst_prefix Destination IP6 prefix.
- * @param[in] src_prefix Source IP6 prefix.
- * @param[in] table_id Table id.
- *
- * @return adjacency index if route found.
- */
-static u32
-ip6_sd_fib_get_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
- ip_prefix_t * src_prefix, u32 table_id)
-{
- u32 adj_index;
- ip6_address_t dst = ip_prefix_v6 (dst_prefix), src;
- u32 dst_address_length = ip_prefix_len (dst_prefix), src_address_length = 0;
- ip_adjacency_t *dst_adj;
-
- if (src_prefix)
+ if (0 == fib_table_get_num_entries (src_fib_index,
+ src_fib_prefix.fp_proto,
+ FIB_SOURCE_LISP))
{
- src = ip_prefix_v6 (src_prefix);
- src_address_length = ip_prefix_len (src_prefix);
+ /*
+ * there's nothing left, unlock the source FIB and the
+ * destination route
+ */
+ fib_table_entry_special_remove (dst_fib_index,
+ &dst_fib_prefix, FIB_SOURCE_LISP);
+ fib_table_unlock (src_fib_index, src_fib_prefix.fp_proto);
}
- else
- memset (&src, 0, sizeof (src));
-
- /* lookup dst adj */
- adj_index = ip6_get_route (lgm->im6, table_id, 0, &dst, dst_address_length);
- if (adj_index == 0)
- return adj_index;
-
- dst_adj = ip_get_adjacency (lgm->lm6, adj_index);
- return ip6_sd_get_src_route (lgm, dst_adj->rewrite_header.sw_if_index, &src,
- src_address_length);
-}
-
-/**
- * @brief Add/del route to IP4 or IP6 SD FIB.
- *
- * Adds/remove routes to both destination and source FIBs. Entries added
- * to destination FIB are associated to adjacencies that point to the source
- * FIB and store the index of the particular source FIB associated to the
- * destination. Source FIBs are locally managed (see @ref lgm->ip4_src_fibs
- * and @ref lgm->ip6_src_fibs), but the adjacencies are allocated out of the
- * global adjacency pool.
- *
- * @param[in] lgm Reference to @ref lisp_gpe_main_t.
- * @param[out] dst_prefix Destination IP prefix.
- * @param[in] src_prefix Source IP prefix.
- * @param[in] table_id Table id.
- * @param[in] add_adj Pointer to the adjacency to be added.
- * @param[in] is_add Add/del flag.
- *
- * @return 0 on success.
- */
-int
-ip_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
- ip_prefix_t * src_prefix, u32 table_id,
- ip_adjacency_t * add_adj, u8 is_add)
-{
- return (ip_prefix_version (dst_prefix) == IP4 ?
- ip4_sd_fib_add_del_route : ip6_sd_fib_add_del_route) (lgm,
- dst_prefix,
- src_prefix,
- table_id,
- add_adj,
- is_add);
}
/**
- * @brief Retrieve IP4 or IP6 SD FIB entry.
+ * @brief Add route to IP4 or IP6 SRC FIB.
*
- * Looks up SD IP route by first looking up the destination in VPP's main FIB
- * and subsequently the source in the src FIB. The index of the source FIB is
- * stored in the dst adjacency's @ref rewrite_header.sw_if_index. If source is
- * 0 do search with ::/0 src.
+ * Adds a route to in the LISP SRC FIB with the result of the route
+ * being the DPO passed.
*
- * @param[in] lgm Reference to @ref lisp_gpe_main_t.
- * @param[out] dst_prefix Destination IP prefix.
+ * @param[in] src_fib_index The index/ID of the SRC FIB
* @param[in] src_prefix Source IP prefix.
- * @param[in] table_id Table id.
- *
- * @return adjacency index if route found.
+ * @param[in] src_dpo The DPO the route will link to.
*/
-u32
-ip_sd_fib_get_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
- ip_prefix_t * src_prefix, u32 table_id)
-{
- if (ip_prefix_version (dst_prefix) == IP4)
- {
- u32 *adj_index = ip4_sd_fib_get_route (lgm, dst_prefix, src_prefix,
- table_id);
- return (adj_index == 0) ? 0 : adj_index[0];
- }
- else
- return ip6_sd_fib_get_route (lgm, dst_prefix, src_prefix, table_id);
-}
-
-always_inline void
-ip4_src_fib_lookup_one (lisp_gpe_main_t * lgm, u32 src_fib_index0,
- ip4_address_t * addr0, u32 * src_adj_index0)
-{
- ip4_fib_mtrie_leaf_t leaf0, leaf1;
- ip4_fib_mtrie_t *mtrie0;
-
- /* if default route not hit in ip4 lookup */
- if (PREDICT_TRUE (src_fib_index0 != (u32) ~ 0))
- {
- mtrie0 = &vec_elt_at_index (lgm->ip4_src_fibs, src_fib_index0)->mtrie;
-
- leaf0 = leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 0);
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 1);
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
-
- /* Handle default route. */
- leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY) ?
- mtrie0->default_leaf : leaf0;
- src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
- }
- else
- src_adj_index0[0] = ~0;
-}
-
-always_inline void
-ip4_src_fib_lookup_two (lisp_gpe_main_t * lgm, u32 src_fib_index0,
- u32 src_fib_index1, ip4_address_t * addr0,
- ip4_address_t * addr1, u32 * src_adj_index0,
- u32 * src_adj_index1)
+void
+ip_src_fib_add_route_w_dpo (u32 src_fib_index,
+ const ip_prefix_t * src_prefix,
+ const dpo_id_t * src_dpo)
{
- ip4_fib_mtrie_leaf_t leaf0, leaf1;
- ip4_fib_mtrie_t *mtrie0, *mtrie1;
-
- /* if default route not hit in ip4 lookup */
- if (PREDICT_TRUE
- (src_fib_index0 != (u32) ~ 0 && src_fib_index1 != (u32) ~ 0))
- {
- mtrie0 = &vec_elt_at_index (lgm->ip4_src_fibs, src_fib_index0)->mtrie;
- mtrie1 = &vec_elt_at_index (lgm->ip4_src_fibs, src_fib_index1)->mtrie;
-
- leaf0 = leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
-
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 0);
- leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 0);
+ fib_prefix_t src_fib_prefix;
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 1);
- leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 1);
+ ip_prefix_to_fib_prefix (src_prefix, &src_fib_prefix);
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
- leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 2);
+ /*
+ * add the entry into the source fib.
+ */
+ fib_node_index_t src_fei;
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
- leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 3);
+ src_fei = fib_table_lookup_exact_match (src_fib_index, &src_fib_prefix);
- /* Handle default route. */
- leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY) ?
- mtrie0->default_leaf : leaf0;
- leaf1 = (leaf1 == IP4_FIB_MTRIE_LEAF_EMPTY) ?
- mtrie1->default_leaf : leaf1;
- src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
- src_adj_index1[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf1);
- }
- else
+ if (FIB_NODE_INDEX_INVALID == src_fei ||
+ !fib_entry_is_sourced (src_fei, FIB_SOURCE_LISP))
{
- ip4_src_fib_lookup_one (lgm, src_fib_index0, addr0, src_adj_index0);
- ip4_src_fib_lookup_one (lgm, src_fib_index1, addr1, src_adj_index1);
+ fib_table_entry_special_dpo_add (src_fib_index,
+ &src_fib_prefix,
+ FIB_SOURCE_LISP,
+ FIB_ENTRY_FLAG_EXCLUSIVE, src_dpo);
}
}
-/**
- * @brief IPv4 src lookup node.
- * @node lgpe-ip4-lookup
- *
- * The LISP IPv4 source lookup dispatch node.
- *
- * This is the IPv4 source lookup dispatch node. It first looks up the
- * adjacency hit in the main (destination) FIB and then uses its
- * <code>rewrite_header.sw_if_index</code>to find the source FIB wherein
- * the source IP is subsequently looked up. Data in the resulting adjacency
- * is used to decide the next node (the lisp_gpe interface) and if a flow
- * hash must be computed, when traffic can be load balanced over multiple
- * tunnels.
- *
- *
- * @param[in] vm vlib_main_t corresponding to current thread.
- * @param[in] node vlib_node_runtime_t data for this node.
- * @param[in] frame vlib_frame_t whose contents should be dispatched.
- *
- * @return number of vectors in frame.
- */
-always_inline uword
-lgpe_ip4_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * from_frame)
+static void
+ip_address_to_46 (const ip_address_t * addr,
+ ip46_address_t * a, fib_protocol_t * proto)
{
- u32 n_left_from, next_index, *from, *to_next;
- lisp_gpe_main_t *lgm = &lisp_gpe_main;
-
- from = vlib_frame_vector_args (from_frame);
- n_left_from = from_frame->n_vectors;
-
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
+ *proto = (IP4 == ip_addr_version (addr) ?
+ FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6);
+ switch (*proto)
{
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
-
- while (n_left_from >= 4 && n_left_to_next >= 2)
- {
- u32 bi0, bi1;
- vlib_buffer_t *b0, *b1;
- ip4_header_t *ip0, *ip1;
- u32 dst_adj_index0, src_adj_index0, src_fib_index0;
- u32 dst_adj_index1, src_adj_index1, src_fib_index1;
- ip_adjacency_t *dst_adj0, *src_adj0, *dst_adj1, *src_adj1;
- u32 next0, next1;
-
- next0 = next1 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
-
- /* Prefetch next iteration. */
- {
- vlib_buffer_t *p2, *p3;
-
- p2 = vlib_get_buffer (vm, from[2]);
- p3 = vlib_get_buffer (vm, from[3]);
-
- vlib_prefetch_buffer_header (p2, LOAD);
- vlib_prefetch_buffer_header (p3, LOAD);
-
- CLIB_PREFETCH (p2->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
- CLIB_PREFETCH (p3->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
- }
-
- bi0 = from[0];
- bi1 = from[1];
- to_next[0] = bi0;
- to_next[1] = bi1;
- from += 2;
- to_next += 2;
- n_left_to_next -= 2;
- n_left_from -= 2;
-
- b0 = vlib_get_buffer (vm, bi0);
- b1 = vlib_get_buffer (vm, bi1);
-
- ip0 = vlib_buffer_get_current (b0);
- ip1 = vlib_buffer_get_current (b1);
-
- /* dst lookup was done by ip4 lookup */
- dst_adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
- dst_adj_index1 = vnet_buffer (b1)->ip.adj_index[VLIB_TX];
-
- dst_adj0 = ip_get_adjacency (lgm->lm4, dst_adj_index0);
- dst_adj1 = ip_get_adjacency (lgm->lm4, dst_adj_index1);
-
- src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
- src_fib_index1 = dst_adj1->rewrite_header.sw_if_index;
-
- ip4_src_fib_lookup_two (lgm, src_fib_index0, src_fib_index1,
- &ip0->src_address, &ip1->src_address,
- &src_adj_index0, &src_adj_index1);
-
- /* if a source fib exists */
- if (PREDICT_TRUE ((u32) ~ 0 != src_adj_index0
- && (u32) ~ 0 != src_adj_index1))
- {
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
- vnet_buffer (b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
-
- src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
- src_adj1 = ip_get_adjacency (lgm->lm4, src_adj_index1);
-
- next0 = src_adj0->explicit_fib_index;
- next1 = src_adj1->explicit_fib_index;
-
- /* prepare buffer for lisp-gpe output node */
- vnet_buffer (b0)->sw_if_index[VLIB_TX] =
- src_adj0->rewrite_header.sw_if_index;
- vnet_buffer (b1)->sw_if_index[VLIB_TX] =
- src_adj1->rewrite_header.sw_if_index;
-
- /* if multipath: saved_lookup_next_index is reused to store
- * nb of sub-tunnels. If greater than 1, multipath is on.
- * Note that flow hash should be 0 after ipx lookup! */
- if (PREDICT_TRUE (src_adj0->saved_lookup_next_index > 1))
- vnet_buffer (b0)->ip.flow_hash =
- ip4_compute_flow_hash (ip0, IP_FLOW_HASH_DEFAULT);
-
- if (PREDICT_TRUE (src_adj1->saved_lookup_next_index > 1))
- vnet_buffer (b1)->ip.flow_hash =
- ip4_compute_flow_hash (ip1, IP_FLOW_HASH_DEFAULT);
- }
- else
- {
- if ((u32) ~ 0 != src_adj_index0)
- {
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
- src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
- next0 = src_adj0->explicit_fib_index;
- vnet_buffer (b0)->sw_if_index[VLIB_TX] =
- src_adj0->rewrite_header.sw_if_index;
-
- if (PREDICT_TRUE (src_adj0->saved_lookup_next_index > 1))
- vnet_buffer (b0)->ip.flow_hash =
- ip4_compute_flow_hash (ip0, IP_FLOW_HASH_DEFAULT);
- }
- else
- {
- next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
- }
-
- if ((u32) ~ 0 != src_adj_index1)
- {
- vnet_buffer (b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
- src_adj1 = ip_get_adjacency (lgm->lm4, src_adj_index1);
- next1 = src_adj1->explicit_fib_index;
- vnet_buffer (b1)->sw_if_index[VLIB_TX] =
- src_adj1->rewrite_header.sw_if_index;
- if (PREDICT_TRUE (src_adj1->saved_lookup_next_index > 1))
- vnet_buffer (b1)->ip.flow_hash =
- ip4_compute_flow_hash (ip1, IP_FLOW_HASH_DEFAULT);
- }
- else
- {
- next1 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
- }
- }
-
- /* mark the packets for CP lookup if needed */
- if (PREDICT_FALSE (LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
- vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
- if (PREDICT_FALSE (LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next1))
- vnet_buffer (b1)->lisp.overlay_afi = LISP_AFI_IP;
-
- vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
- n_left_to_next, bi0, bi1, next0,
- next1);
- }
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- vlib_buffer_t *b0;
- ip4_header_t *ip0;
- u32 bi0, dst_adj_index0, src_adj_index0, src_fib_index0;
- u32 next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
- ip_adjacency_t *dst_adj0, *src_adj0;
-
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
- ip0 = vlib_buffer_get_current (b0);
-
- /* dst lookup was done by ip4 lookup */
- dst_adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
- dst_adj0 = ip_get_adjacency (lgm->lm4, dst_adj_index0);
- src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
-
- /* do src lookup */
- ip4_src_fib_lookup_one (lgm, src_fib_index0, &ip0->src_address,
- &src_adj_index0);
-
- /* if a source fib exists */
- if (PREDICT_TRUE ((u32) ~ 0 != src_adj_index0))
- {
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
- src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
- next0 = src_adj0->explicit_fib_index;
-
- /* prepare packet for lisp-gpe output node */
- vnet_buffer (b0)->sw_if_index[VLIB_TX] =
- src_adj0->rewrite_header.sw_if_index;
-
- /* if multipath: saved_lookup_next_index is reused to store
- * nb of sub-tunnels. If greater than 1, multipath is on */
- if (PREDICT_TRUE (src_adj0->saved_lookup_next_index > 1))
- vnet_buffer (b0)->ip.flow_hash =
- ip4_compute_flow_hash (ip0, IP_FLOW_HASH_DEFAULT);
- }
- else
- {
- next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
- }
-
- if (PREDICT_FALSE (LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
- vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
-
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
- n_left_to_next, bi0, next0);
- }
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
+ case FIB_PROTOCOL_IP4:
+ a->ip4 = addr->ip.v4;
+ break;
+ case FIB_PROTOCOL_IP6:
+ a->ip6 = addr->ip.v6;
+ break;
+ default:
+ ASSERT (0);
+ break;
}
- return from_frame->n_vectors;
}
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (lgpe_ip4_lookup_node) = {
- .function = lgpe_ip4_lookup,
- .name = "lgpe-ip4-lookup",
- .vector_size = sizeof (u32),
-
- .type = VLIB_NODE_TYPE_INTERNAL,
-
- .n_next_nodes = LGPE_IP4_LOOKUP_N_NEXT,
- .next_nodes = {
-#define _(sym,str) [LGPE_IP4_LOOKUP_NEXT_##sym] = str,
- foreach_lgpe_ip4_lookup_next
-#undef _
- },
-};
-/* *INDENT-ON* */
-
-static u32
-ip6_src_fib_lookup (lisp_gpe_main_t * lgm, u32 src_fib_index,
- ip6_address_t * src)
+static fib_route_path_t *
+ip_src_fib_mk_paths (const lisp_fwd_path_t * paths)
{
- int i, len;
- int rv;
- BVT (clib_bihash_kv) kv, value;
- ip6_src_fib_t *fib = pool_elt_at_index (lgm->ip6_src_fibs, src_fib_index);
+ const lisp_gpe_adjacency_t *ladj;
+ fib_route_path_t *rpaths = NULL;
+ u8 best_priority;
+ u32 ii;
- len = vec_len (fib->prefix_lengths_in_search_order);
+ vec_validate (rpaths, vec_len (paths) - 1);
- for (i = 0; i < len; i++)
- {
- int dst_address_length = fib->prefix_lengths_in_search_order[i];
- ip6_address_t *mask;
+ best_priority = paths[0].priority;
- ASSERT (dst_address_length >= 0 && dst_address_length <= 128);
+ vec_foreach_index (ii, paths)
+ {
+ if (paths[0].priority != best_priority)
+ break;
- mask = &fib->fib_masks[dst_address_length];
+ ladj = lisp_gpe_adjacency_get (paths[ii].lisp_adj);
- kv.key[0] = src->as_u64[0] & mask->as_u64[0];
- kv.key[1] = src->as_u64[1] & mask->as_u64[1];
- kv.key[2] = dst_address_length;
+ ip_address_to_46 (&ladj->remote_rloc,
+ &rpaths[ii].frp_addr, &rpaths[ii].frp_proto);
- rv =
- BV (clib_bihash_search_inline_2) (&fib->ip6_lookup_table, &kv,
- &value);
- if (rv == 0)
- return value.value;
- }
-
- return 0;
-}
+ rpaths[ii].frp_sw_if_index = ladj->sw_if_index;
+ rpaths[ii].frp_weight = (paths[ii].weight ? paths[ii].weight : 1);
+ rpaths[ii].frp_label = MPLS_LABEL_INVALID;
+ }
-always_inline void
-ip6_src_fib_lookup_one (lisp_gpe_main_t * lgm, u32 src_fib_index0,
- ip6_address_t * addr0, u32 * src_adj_index0)
-{
- /* if default route not hit in ip6 lookup */
- if (PREDICT_TRUE (src_fib_index0 != (u32) ~ 0))
- src_adj_index0[0] = ip6_src_fib_lookup (lgm, src_fib_index0, addr0);
- else
- src_adj_index0[0] = ~0;
-}
+ ASSERT (0 != vec_len (rpaths));
-always_inline void
-ip6_src_fib_lookup_two (lisp_gpe_main_t * lgm, u32 src_fib_index0,
- u32 src_fib_index1, ip6_address_t * addr0,
- ip6_address_t * addr1, u32 * src_adj_index0,
- u32 * src_adj_index1)
-{
- /* if default route not hit in ip6 lookup */
- if (PREDICT_TRUE
- (src_fib_index0 != (u32) ~ 0 && src_fib_index1 != (u32) ~ 0))
- {
- src_adj_index0[0] = ip6_src_fib_lookup (lgm, src_fib_index0, addr0);
- src_adj_index1[0] = ip6_src_fib_lookup (lgm, src_fib_index1, addr1);
- }
- else
- {
- ip6_src_fib_lookup_one (lgm, src_fib_index0, addr0, src_adj_index0);
- ip6_src_fib_lookup_one (lgm, src_fib_index1, addr1, src_adj_index1);
- }
+ return (rpaths);
}
/**
- * @brief IPv6 src lookup node.
- * @node lgpe-ip6-lookup
- *
- * The LISP IPv6 source lookup dispatch node.
+ * @brief Add route to IP4 or IP6 SRC FIB.
*
- * This is the IPv6 source lookup dispatch node. It first looks up the
- * adjacency hit in the main (destination) FIB and then uses its
- * <code>rewrite_header.sw_if_index</code>to find the source FIB wherein
- * the source IP is subsequently looked up. Data in the resulting adjacency
- * is used to decide the next node (the lisp_gpe interface) and if a flow
- * hash must be computed, when traffic can be load balanced over multiple
- * tunnels.
+ * Adds a route to in the LISP SRC FIB for the tunnel.
*
- * @param[in] vm vlib_main_t corresponding to current thread.
- * @param[in] node vlib_node_runtime_t data for this node.
- * @param[in] frame vlib_frame_t whose contents should be dispatched.
- *
- * @return number of vectors in frame.
+ * @param[in] src_fib_index The index/ID of the SRC FIB
+ * @param[in] src_prefix Source IP prefix.
+ * @param[in] paths The paths from which to construct the
+ * load balance
*/
-always_inline uword
-lgpe_ip6_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * from_frame)
+void
+ip_src_fib_add_route (u32 src_fib_index,
+ const ip_prefix_t * src_prefix,
+ const lisp_fwd_path_t * paths)
{
- u32 n_left_from, next_index, *from, *to_next;
- lisp_gpe_main_t *lgm = &lisp_gpe_main;
-
- from = vlib_frame_vector_args (from_frame);
- n_left_from = from_frame->n_vectors;
-
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
-
- while (n_left_from >= 4 && n_left_to_next >= 2)
- {
- u32 bi0, bi1;
- vlib_buffer_t *b0, *b1;
- ip6_header_t *ip0, *ip1;
- u32 dst_adj_index0, src_adj_index0, src_fib_index0, dst_adj_index1,
- src_adj_index1, src_fib_index1;
- ip_adjacency_t *dst_adj0, *src_adj0, *dst_adj1, *src_adj1;
- u32 next0, next1;
-
- next0 = next1 = LGPE_IP6_LOOKUP_NEXT_LISP_CP_LOOKUP;
-
- /* Prefetch next iteration. */
- {
- vlib_buffer_t *p2, *p3;
-
- p2 = vlib_get_buffer (vm, from[2]);
- p3 = vlib_get_buffer (vm, from[3]);
-
- vlib_prefetch_buffer_header (p2, LOAD);
- vlib_prefetch_buffer_header (p3, LOAD);
-
- CLIB_PREFETCH (p2->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
- CLIB_PREFETCH (p3->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
- }
-
- bi0 = from[0];
- bi1 = from[1];
- to_next[0] = bi0;
- to_next[1] = bi1;
- from += 2;
- to_next += 2;
- n_left_to_next -= 2;
- n_left_from -= 2;
-
- b0 = vlib_get_buffer (vm, bi0);
- b1 = vlib_get_buffer (vm, bi1);
-
- ip0 = vlib_buffer_get_current (b0);
- ip1 = vlib_buffer_get_current (b1);
-
- /* dst lookup was done by ip6 lookup */
- dst_adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
- dst_adj_index1 = vnet_buffer (b1)->ip.adj_index[VLIB_TX];
-
- dst_adj0 = ip_get_adjacency (lgm->lm6, dst_adj_index0);
- dst_adj1 = ip_get_adjacency (lgm->lm6, dst_adj_index1);
-
- src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
- src_fib_index1 = dst_adj1->rewrite_header.sw_if_index;
-
- ip6_src_fib_lookup_two (lgm, src_fib_index0, src_fib_index1,
- &ip0->src_address, &ip1->src_address,
- &src_adj_index0, &src_adj_index1);
-
- /* if a source fib exists */
- if (PREDICT_TRUE ((u32) ~ 0 != src_adj_index0
- && (u32) ~ 0 != src_adj_index1))
- {
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
- vnet_buffer (b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
+ fib_prefix_t src_fib_prefix;
+ fib_route_path_t *rpaths;
- src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
- src_adj1 = ip_get_adjacency (lgm->lm6, src_adj_index1);
+ ip_prefix_to_fib_prefix (src_prefix, &src_fib_prefix);
- next0 = src_adj0->explicit_fib_index;
- next1 = src_adj1->explicit_fib_index;
+ rpaths = ip_src_fib_mk_paths (paths);
- /* prepare buffer for lisp-gpe output node */
- vnet_buffer (b0)->sw_if_index[VLIB_TX] =
- src_adj0->rewrite_header.sw_if_index;
- vnet_buffer (b1)->sw_if_index[VLIB_TX] =
- src_adj1->rewrite_header.sw_if_index;
-
- /* if multipath: saved_lookup_next_index is reused to store
- * nb of sub-tunnels. If greater than 1, multipath is on.
- * Note that flow hash should be 0 after ipx lookup! */
- if (PREDICT_TRUE (src_adj0->saved_lookup_next_index > 1))
- vnet_buffer (b0)->ip.flow_hash =
- ip6_compute_flow_hash (ip0, IP_FLOW_HASH_DEFAULT);
-
- if (PREDICT_TRUE (src_adj1->saved_lookup_next_index > 1))
- vnet_buffer (b1)->ip.flow_hash =
- ip6_compute_flow_hash (ip1, IP_FLOW_HASH_DEFAULT);
- }
- else
- {
- if (src_adj_index0 != (u32) ~ 0)
- {
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
- src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
- next0 = src_adj0->explicit_fib_index;
- vnet_buffer (b0)->sw_if_index[VLIB_TX] =
- src_adj0->rewrite_header.sw_if_index;
-
- if (PREDICT_TRUE (src_adj0->saved_lookup_next_index > 1))
- vnet_buffer (b0)->ip.flow_hash =
- ip6_compute_flow_hash (ip0, IP_FLOW_HASH_DEFAULT);
- }
- else
- {
- next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
- }
-
- if (src_adj_index1 != (u32) ~ 0)
- {
- vnet_buffer (b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
- src_adj1 = ip_get_adjacency (lgm->lm6, src_adj_index1);
- next1 = src_adj1->explicit_fib_index;
- vnet_buffer (b1)->sw_if_index[VLIB_TX] =
- src_adj1->rewrite_header.sw_if_index;
-
- if (PREDICT_TRUE (src_adj1->saved_lookup_next_index > 1))
- vnet_buffer (b1)->ip.flow_hash =
- ip6_compute_flow_hash (ip1, IP_FLOW_HASH_DEFAULT);
- }
- else
- {
- next1 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
- }
- }
-
- /* mark the packets for CP lookup if needed */
- if (PREDICT_FALSE (LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
- vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
- if (PREDICT_FALSE (LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next1))
- vnet_buffer (b1)->lisp.overlay_afi = LISP_AFI_IP;
-
- vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
- n_left_to_next, bi0, bi1, next0,
- next1);
- }
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- vlib_buffer_t *b0;
- ip6_header_t *ip0;
- u32 bi0, dst_adj_index0, src_adj_index0, src_fib_index0;
- u32 next0 = LGPE_IP6_LOOKUP_NEXT_LISP_CP_LOOKUP;
- ip_adjacency_t *dst_adj0, *src_adj0;
-
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
- ip0 = vlib_buffer_get_current (b0);
-
- /* dst lookup was done by ip6 lookup */
- dst_adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
- dst_adj0 = ip_get_adjacency (lgm->lm6, dst_adj_index0);
- src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
-
- /* do src lookup */
- ip6_src_fib_lookup_one (lgm, src_fib_index0, &ip0->src_address,
- &src_adj_index0);
-
- /* if a source fib exists */
- if (PREDICT_TRUE (src_adj_index0 != (u32) ~ 0))
- {
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
- src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
- next0 = src_adj0->explicit_fib_index;
-
- /* prepare packet for lisp-gpe output node */
- vnet_buffer (b0)->sw_if_index[VLIB_TX] =
- src_adj0->rewrite_header.sw_if_index;
-
- /* if multipath: saved_lookup_next_index is reused to store
- * nb of sub-tunnels. If greater than 1, multipath is on */
- if (PREDICT_TRUE (src_adj0->saved_lookup_next_index > 1))
- vnet_buffer (b0)->ip.flow_hash =
- ip6_compute_flow_hash (ip0, IP_FLOW_HASH_DEFAULT);
- }
- else
- {
- next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
- }
-
- /* mark the packets for CP lookup if needed */
- if (PREDICT_FALSE (LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
- vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
-
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
- n_left_to_next, bi0, next0);
- }
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
- return from_frame->n_vectors;
+ fib_table_entry_update (src_fib_index,
+ &src_fib_prefix,
+ FIB_SOURCE_LISP, FIB_ENTRY_FLAG_NONE, rpaths);
+ vec_free (rpaths);
}
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (lgpe_ip6_lookup_node) = {
- .function = lgpe_ip6_lookup,
- .name = "lgpe-ip6-lookup",
- .vector_size = sizeof (u32),
-
- .type = VLIB_NODE_TYPE_INTERNAL,
-
- .n_next_nodes = LGPE_IP6_LOOKUP_N_NEXT,
- .next_nodes = {
-#define _(sym,str) [LGPE_IP6_LOOKUP_NEXT_##sym] = str,
- foreach_lgpe_ip6_lookup_next
-#undef _
- },
-};
-/* *INDENT-ON* */
-
/*
* fd.io coding-style-patch-verification: ON
*