-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)