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);
}
}
+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;
+}
+
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,
/* 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 = add_adj[0];
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 */
/* lookup dst adj to obtain the adj index */
p = ip4_get_route (lgm->im4, table_id, 0, dst.as_u8,
dst_address_length);
- if (p == 0)
+
+ /* make sure insertion succeeded */
+ if (CLIB_DEBUG)
{
- clib_warning("Failed to insert dst route for eid %U!",
- format_ip4_address_and_length, dst.as_u8,
- dst_address_length);
- return -1;
+ 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);
}
-
- /* allocate and init src ip4 fib */
- pool_get(lgm->ip4_src_fibs, src_fib);
- ip4_mtrie_init (&src_fib->mtrie);
-
- /* reuse rewrite header to store pointer to src fib */
- dst_adjp = ip_get_adjacency (lgm->lm4, p[0]);
- dst_adjp->rewrite_header.sw_if_index = src_fib - lgm->ip4_src_fibs;
}
}
else
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 = 1;
+ 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)
{
return 0;
/* if there's nothing left */
- if (ARRAY_LEN(src_fib->adj_index_by_dst_address) == 0)
+ if (ip4_fib_is_empty(src_fib))
{
/* remove the src fib .. */
pool_put(lgm->ip4_src_fibs, src_fib);
ip6_sd_get_src_route (lisp_gpe_main_t * lgm, u32 src_fib_index,
ip6_address_t * src, u32 address_length)
{
- 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);
- len = vec_len (fib->prefix_lengths_in_search_order);
-
- for (i = 0; i < len; i++)
- {
- int dst_address_length = fib->prefix_lengths_in_search_order[i];
- ip6_address_t * mask;
+ ip6_address_t * mask;
- ASSERT(dst_address_length >= 0 && dst_address_length <= 128);
+ ASSERT(address_length <= 128);
- mask = &fib->fib_masks[dst_address_length];
+ 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] = dst_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;
- }
+ rv = BV(clib_bihash_search_inline_2)(&fib->ip6_lookup_table, &kv, &value);
+ if (rv == 0)
+ return value.value;
return 0;
}
/* 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 = add_adj[0];
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 */
adj_index = ip6_get_route (lgm->im6, table_id, 0, &dst,
dst_address_length);
- ASSERT(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);
-
- /* reuse rewrite header to store pointer to src fib */
- dst_adjp = ip_get_adjacency (lgm->lm6, adj_index);
- dst_adjp->rewrite_header.sw_if_index = src_fib - lgm->ip6_src_fibs;
+ /* 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_ip6_address_and_length, dst.as_u8,
- dst_address_length);
+ format_ip_prefix, dst_prefix);
return -1;
}
}
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 = 1;
+ 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)
{
ip4_fib_mtrie_leaf_t leaf0, leaf1;
ip4_fib_mtrie_t * mtrie0;
- 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);
+ /* 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_fib_mtrie_leaf_t leaf0, leaf1;
ip4_fib_mtrie_t * mtrie0, * mtrie1;
- 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;
+ /* 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 = 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);
+ leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 0);
+ leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 0);
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 1);
- leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 1);
+ leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 1);
+ leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 1);
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
- leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 2);
+ leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
+ leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 2);
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
- leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 3);
+ leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
+ leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 3);
- /* 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);
+ /* 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
+ {
+ 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);
+ }
}
always_inline uword
u32 bi0, bi1;
vlib_buffer_t * b0, * b1;
ip4_header_t * ip0, * ip1;
- u32 dst_adj_index0, src_adj_index0, src_fib_index0, dst_adj_index1,
- src_adj_index1, src_fib_index1;
+ 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;
src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
src_fib_index1 = dst_adj1->rewrite_header.sw_if_index;
- /* if default route not hit in ip4 lookup */
- if (PREDICT_TRUE(src_fib_index0 != (u32) ~0
- && src_fib_index1 != (u32) ~0))
- {
- ip4_src_fib_lookup_two (lgm, src_fib_index0, src_fib_index1,
- &ip0->src_address, &ip1->src_address,
- &src_adj_index0, &src_adj_index1);
+ 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->lookup_next_index;
- next1 = src_adj1->lookup_next_index;
+ 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 (src_fib_index0 != (u32) ~0)
+ if ((u32) ~0 != src_adj_index0)
{
- ip4_src_fib_lookup_one (lgm, src_fib_index0,
- &ip0->src_address, &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->lookup_next_index;
+ 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);
}
- if (src_fib_index1 != (u32) ~0)
+ else
+ {
+ next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
+ }
+
+ if ((u32) ~0 != src_adj_index1)
{
- ip4_src_fib_lookup_one (lgm, src_fib_index1,
- &ip1->src_address, &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->lookup_next_index;
+ 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);
dst_adj0 = ip_get_adjacency (lgm->lm4, dst_adj_index0);
src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
- /* if default route not hit in ip4 lookup */
- if (PREDICT_TRUE(src_fib_index0 != (u32 ) ~0))
+ /* 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))
{
- /* do src lookup */
- ip4_src_fib_lookup_one (lgm, src_fib_index0, &ip0->src_address,
- &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->lookup_next_index;
+ 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);
return 0;
}
+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;
+}
+
+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);
+ }
+}
+
always_inline uword
lgpe_ip6_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
vlib_frame_t * from_frame)
src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
src_fib_index1 = dst_adj1->rewrite_header.sw_if_index;
- /* if default route not hit in ip6 lookup */
- if (PREDICT_TRUE(src_fib_index0 != (u32) ~0
- && src_fib_index1 != (u32) ~0))
- {
- /* do src lookup */
- src_adj_index0 = ip6_src_fib_lookup (lgm, src_fib_index0,
- &ip0->src_address);
- src_adj_index1 = ip6_src_fib_lookup (lgm, src_fib_index1,
- &ip1->src_address);
+ 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;
src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
src_adj1 = ip_get_adjacency (lgm->lm6, src_adj_index1);
- next0 = src_adj0->lookup_next_index;
- next1 = src_adj1->lookup_next_index;
+ 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 = 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_fib_index0 != (u32) ~0)
+ if (src_adj_index0 != (u32) ~0)
{
- src_adj_index0 = ip6_src_fib_lookup (lgm, src_fib_index0,
- &ip0->src_address);
vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
- next0 = src_adj0->lookup_next_index;
+ 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);
}
- if (src_fib_index1 != (u32) ~0)
+ else
+ {
+ next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
+ }
+
+ if (src_adj_index1 != (u32) ~0)
{
- src_adj_index1 = ip6_src_fib_lookup (lgm, src_fib_index1,
- &ip1->src_address);
vnet_buffer(b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
src_adj1 = ip_get_adjacency (lgm->lm6, src_adj_index1);
- next1 = src_adj1->lookup_next_index;
+ 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);
dst_adj0 = ip_get_adjacency (lgm->lm6, dst_adj_index0);
src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
- /* if default route not hit in ip6 lookup */
- if (PREDICT_TRUE(src_fib_index0 != (u32 ) ~0))
- {
- /* do src lookup */
- src_adj_index0 = ip6_src_fib_lookup (lgm, src_fib_index0,
- &ip0->src_address);
+ /* 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->lookup_next_index;
+ 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);