2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
17 * @brief LISP-GPE overlay IP forwarding logic and lookup data structures.
19 * Provides an implementation of a Source/Dest (SD) IP FIB that leverages the
20 * existing destination only FIB. Lookups are done in two stages, first the
21 * destination FIB looks up a packet's destination address and then if a
22 * an SD entry is hit, the destination adjacency will point to the second
23 * stage, the source FIB, where the packet's source is looked up. Note that a
24 * miss in the source FIB does not result in an overall SD lookup retry with
25 * a less specific entry from the destination FIB.
27 #include <vnet/lisp-gpe/lisp_gpe.h>
29 /** Sets adj index for destination address in IP4 FIB. Similar to the function
30 * in ip4_forward but this one avoids calling route callbacks */
32 ip4_sd_fib_set_adj_index (lisp_gpe_main_t * lgm, ip4_fib_t * fib, u32 flags,
33 u32 dst_address_u32, u32 dst_address_length,
36 ip_lookup_main_t *lm = lgm->lm4;
39 if (vec_bytes (fib->old_hash_values))
40 memset (fib->old_hash_values, ~0, vec_bytes (fib->old_hash_values));
41 if (vec_bytes (fib->new_hash_values))
42 memset (fib->new_hash_values, ~0, vec_bytes (fib->new_hash_values));
43 fib->new_hash_values[0] = adj_index;
45 /* Make sure adj index is valid. */
47 (void) ip_get_adjacency (lm, adj_index);
49 hash = fib->adj_index_by_dst_address[dst_address_length];
51 hash = _hash_set3 (hash, dst_address_u32,
52 fib->new_hash_values, fib->old_hash_values);
54 fib->adj_index_by_dst_address[dst_address_length] = hash;
57 /** Initialize the adjacency index by destination address vector for IP4 FIB.
58 * Copied from ip4_forward since it's static */
60 ip4_fib_init_adj_index_by_dst_address (ip_lookup_main_t * lm,
61 ip4_fib_t * fib, u32 address_length)
66 ASSERT (lm->fib_result_n_bytes >= sizeof (uword));
67 lm->fib_result_n_words = round_pow2 (lm->fib_result_n_bytes, sizeof (uword))
70 fib->adj_index_by_dst_address[address_length] =
71 hash_create (32 /* elts */ , lm->fib_result_n_words * sizeof (uword));
73 hash_set_flags (fib->adj_index_by_dst_address[address_length],
74 HASH_FLAG_NO_AUTO_SHRINK);
76 h = hash_header (fib->adj_index_by_dst_address[address_length]);
77 max_index = (hash_value_bytes (h) / sizeof (fib->new_hash_values[0])) - 1;
79 /* Initialize new/old hash value vectors. */
80 vec_validate_init_empty (fib->new_hash_values, max_index, ~0);
81 vec_validate_init_empty (fib->old_hash_values, max_index, ~0);
84 /** Add/del src route to IP4 SD FIB. */
86 ip4_sd_fib_add_del_src_route (lisp_gpe_main_t * lgm,
87 ip4_add_del_route_args_t * a)
89 ip_lookup_main_t *lm = lgm->lm4;
91 u32 dst_address, dst_address_length, adj_index, old_adj_index;
94 /* Either create new adjacency or use given one depending on arguments. */
96 ip_add_adjacency (lm, a->add_adj, a->n_add_adj, &adj_index);
98 adj_index = a->adj_index;
100 dst_address = a->dst_address.data_u32;
101 dst_address_length = a->dst_address_length;
103 fib = pool_elt_at_index (lgm->ip4_src_fibs, a->table_index_or_table_id);
105 if (!fib->adj_index_by_dst_address[dst_address_length])
106 ip4_fib_init_adj_index_by_dst_address (lm, fib, dst_address_length);
108 hash = fib->adj_index_by_dst_address[dst_address_length];
110 is_del = (a->flags & IP4_ROUTE_FLAG_DEL) != 0;
114 fib->old_hash_values[0] = ~0;
115 hash = _hash_unset (hash, dst_address, fib->old_hash_values);
116 fib->adj_index_by_dst_address[dst_address_length] = hash;
119 ip4_sd_fib_set_adj_index (lgm, fib, a->flags, dst_address,
120 dst_address_length, adj_index);
122 old_adj_index = fib->old_hash_values[0];
124 /* Avoid spurious reference count increments */
125 if (old_adj_index == adj_index
126 && adj_index != ~0 && !(a->flags & IP4_ROUTE_FLAG_KEEP_OLD_ADJACENCY))
128 ip_adjacency_t *adj = ip_get_adjacency (lm, adj_index);
129 if (adj->share_count > 0)
133 ip4_fib_mtrie_add_del_route (fib, a->dst_address, dst_address_length,
134 is_del ? old_adj_index : adj_index, is_del);
136 /* Delete old adjacency index if present and changed. */
137 if (!(a->flags & IP4_ROUTE_FLAG_KEEP_OLD_ADJACENCY)
138 && old_adj_index != ~0 && old_adj_index != adj_index)
139 ip_del_adjacency (lm, old_adj_index);
142 /** Get src route from IP4 SD FIB. */
144 ip4_sd_get_src_route (lisp_gpe_main_t * lgm, u32 src_fib_index,
145 ip4_address_t * src, u32 address_length)
147 ip4_fib_t *fib = pool_elt_at_index (lgm->ip4_src_fibs, src_fib_index);
150 hash = fib->adj_index_by_dst_address[address_length];
151 p = hash_get (hash, src->as_u32);
156 typedef CLIB_PACKED (struct ip4_route {
157 ip4_address_t address;
158 u32 address_length : 6;
163 /** Remove all routes from src IP4 FIB */
165 ip4_sd_fib_clear_src_fib (lisp_gpe_main_t * lgm, ip4_fib_t * fib)
167 ip4_route_t *routes = 0, *r;
170 vec_reset_length (routes);
172 for (i = 0; i < ARRAY_LEN (fib->adj_index_by_dst_address); i++)
174 uword *hash = fib->adj_index_by_dst_address[i];
178 x.address_length = i;
179 x.index = 0; /* shut up coverity */
182 hash_foreach_pair (p, hash,
184 x.address.data_u32 = p->key;
185 vec_add1 (routes, x);
190 vec_foreach (r, routes)
192 ip4_add_del_route_args_t a;
194 memset (&a, 0, sizeof (a));
195 a.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_DEL;
196 a.table_index_or_table_id = fib - lgm->ip4_src_fibs;
197 a.dst_address = r->address;
198 a.dst_address_length = r->address_length;
201 ip4_sd_fib_add_del_src_route (lgm, &a);
205 /** Test if IP4 FIB is empty */
207 ip4_fib_is_empty (ip4_fib_t * fib)
213 for (i = ARRAY_LEN (fib->adj_index_by_dst_address) - 1; i >= 0; i--)
215 uword *hash = fib->adj_index_by_dst_address[i];
216 uword n_elts = hash_elts (hash);
227 * @brief Add/del route to IP4 SD FIB.
229 * Adds/remove routes to both destination and source FIBs. Entries added
230 * to destination FIB are associated to adjacencies that point to the source
231 * FIB and store the index of the particular source FIB associated to the
232 * destination. Source FIBs are locally managed (see @ref lgm->ip4_src_fibs
233 * and @ref lgm->ip6_src_fibs), but the adjacencies are allocated out of the
234 * global adjacency pool.
236 * @param[in] lgm Reference to @ref lisp_gpe_main_t.
237 * @param[out] dst_prefix Destination IP4 prefix.
238 * @param[in] src_prefix Source IP4 prefix.
239 * @param[in] table_id Table id.
240 * @param[in] add_adj Pointer to the adjacency to be added.
241 * @param[in] is_add Add/del flag.
243 * @return 0 on success.
246 ip4_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
247 ip_prefix_t * src_prefix, u32 table_id,
248 ip_adjacency_t * add_adj, u8 is_add)
251 ip4_add_del_route_args_t a;
252 ip_adjacency_t *dst_adjp, dst_adj;
253 ip4_address_t dst = ip_prefix_v4 (dst_prefix), src;
254 u32 dst_address_length = ip_prefix_len (dst_prefix), src_address_length = 0;
259 src = ip_prefix_v4 (src_prefix);
260 src_address_length = ip_prefix_len (src_prefix);
263 memset (&src, 0, sizeof (src));
266 p = ip4_get_route (lgm->im4, table_id, 0, dst.as_u8, dst_address_length);
270 /* insert dst prefix to ip4 fib, if it's not in yet */
273 /* allocate and init src ip4 fib */
274 pool_get (lgm->ip4_src_fibs, src_fib);
275 ip4_mtrie_init (&src_fib->mtrie);
277 /* configure adjacency */
278 memset (&dst_adj, 0, sizeof (dst_adj));
280 /* reuse rewrite header to store pointer to src fib */
281 dst_adj.rewrite_header.sw_if_index = src_fib - lgm->ip4_src_fibs;
283 /* dst adj should point to lisp gpe lookup */
284 dst_adj.lookup_next_index = lgm->ip4_lookup_next_lgpe_ip4_lookup;
286 /* explicit_fib_index is used in IP6 FIB lookup, don't reuse it */
287 dst_adj.explicit_fib_index = ~0;
290 /* make sure we have different signatures for adj in different tables
291 * but with the same lookup_next_index and for adj in the same table
292 * but associated to different destinations */
293 dst_adj.if_address_index = table_id;
294 dst_adj.indirect.next_hop.ip4 = dst;
296 memset (&a, 0, sizeof (a));
297 a.flags = IP4_ROUTE_FLAG_TABLE_ID;
298 a.table_index_or_table_id = table_id; /* vrf */
300 a.dst_address_length = dst_address_length;
302 a.flags |= IP4_ROUTE_FLAG_ADD;
303 a.add_adj = &dst_adj;
306 ip4_add_del_route (lgm->im4, &a);
308 /* lookup dst adj to obtain the adj index */
309 p = ip4_get_route (lgm->im4, table_id, 0, dst.as_u8,
312 /* make sure insertion succeeded */
316 dst_adjp = ip_get_adjacency (lgm->lm4, p[0]);
317 ASSERT (dst_adjp->rewrite_header.sw_if_index
318 == dst_adj.rewrite_header.sw_if_index);
327 ("Trying to delete inexistent dst route for %U. Aborting",
328 format_ip4_address_and_length, dst.as_u8, dst_address_length);
333 dst_adjp = ip_get_adjacency (lgm->lm4, p[0]);
335 /* add/del src prefix to src fib */
336 memset (&a, 0, sizeof (a));
337 a.flags = IP4_ROUTE_FLAG_TABLE_ID;
338 a.table_index_or_table_id = dst_adjp->rewrite_header.sw_if_index;
340 a.flags |= is_add ? IP4_ROUTE_FLAG_ADD : IP4_ROUTE_FLAG_DEL;
342 a.n_add_adj = is_add ? 1 : 0;
343 /* if src prefix is null, add 0/0 */
344 a.dst_address_length = src_address_length;
346 ip4_sd_fib_add_del_src_route (lgm, &a);
348 /* make sure insertion succeeded */
349 if (CLIB_DEBUG && is_add)
352 ip_adjacency_t *src_adjp;
353 sai = ip4_sd_get_src_route (lgm, dst_adjp->rewrite_header.sw_if_index,
354 &src, src_address_length);
356 src_adjp = ip_get_adjacency (lgm->lm4, sai[0]);
357 ASSERT (src_adjp->if_address_index == add_adj->if_address_index);
360 /* if a delete, check if there are elements left in the src fib */
363 src_fib = pool_elt_at_index (lgm->ip4_src_fibs,
364 dst_adjp->rewrite_header.sw_if_index);
368 /* if there's nothing left */
369 if (ip4_fib_is_empty (src_fib))
371 /* remove the src fib .. */
372 pool_put (lgm->ip4_src_fibs, src_fib);
374 /* .. and remove dst route */
375 memset (&a, 0, sizeof (a));
376 a.flags = IP4_ROUTE_FLAG_TABLE_ID;
377 a.table_index_or_table_id = table_id; /* vrf */
379 a.dst_address_length = dst_address_length;
381 a.flags |= IP4_ROUTE_FLAG_DEL;
383 ip4_add_del_route (lgm->im4, &a);
391 * @brief Retrieve IP4 SD FIB entry.
393 * Looks up SD IP4 route by first looking up the destination in VPP's main FIB
394 * and subsequently the source in the src FIB. The index of the source FIB is
395 * stored in the dst adjacency's rewrite_header.sw_if_index. If source is 0
396 * do search with 0/0 src.
398 * @param[in] lgm Reference to @ref lisp_gpe_main_t.
399 * @param[out] dst_prefix Destination IP4 prefix.
400 * @param[in] src_prefix Source IP4 prefix.
401 * @param[in] table_id Table id.
403 * @return pointer to the adjacency if route found.
406 ip4_sd_fib_get_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
407 ip_prefix_t * src_prefix, u32 table_id)
410 ip4_address_t dst = ip_prefix_v4 (dst_prefix), src;
411 u32 dst_address_length = ip_prefix_len (dst_prefix), src_address_length = 0;
412 ip_adjacency_t *dst_adj;
416 src = ip_prefix_v4 (src_prefix);
417 src_address_length = ip_prefix_len (src_prefix);
420 memset (&src, 0, sizeof (src));
423 p = ip4_get_route (lgm->im4, table_id, 0, dst.as_u8, dst_address_length);
427 dst_adj = ip_get_adjacency (lgm->lm4, p[0]);
428 return ip4_sd_get_src_route (lgm, dst_adj->rewrite_header.sw_if_index, &src,
432 /** Get src route from IP6 SD FIB. */
434 ip6_sd_get_src_route (lisp_gpe_main_t * lgm, u32 src_fib_index,
435 ip6_address_t * src, u32 address_length)
438 BVT (clib_bihash_kv) kv, value;
439 ip6_src_fib_t *fib = pool_elt_at_index (lgm->ip6_src_fibs, src_fib_index);
443 ASSERT (address_length <= 128);
445 mask = &fib->fib_masks[address_length];
447 kv.key[0] = src->as_u64[0] & mask->as_u64[0];
448 kv.key[1] = src->as_u64[1] & mask->as_u64[1];
449 kv.key[2] = address_length;
451 rv = BV (clib_bihash_search_inline_2) (&fib->ip6_lookup_table, &kv, &value);
459 compute_prefix_lengths_in_search_order (ip6_src_fib_t * fib)
462 vec_reset_length (fib->prefix_lengths_in_search_order);
463 /* Note: bitmap reversed so this is in fact a longest prefix match */
466 clib_bitmap_foreach(i, fib->non_empty_dst_address_length_bitmap, ({
467 int dst_address_length = 128 - i;
468 vec_add1 (fib->prefix_lengths_in_search_order, dst_address_length);
473 /** Add/del src route to IP6 SD FIB. Rewrite of ip6_add_del_route() because
474 * it uses im6 to find the FIB .*/
476 ip6_sd_fib_add_del_src_route (lisp_gpe_main_t * lgm,
477 ip6_add_del_route_args_t * a)
479 ip_lookup_main_t *lm = lgm->lm6;
481 ip6_address_t dst_address;
482 u32 dst_address_length, adj_index;
484 u32 old_adj_index = ~0;
485 BVT (clib_bihash_kv) kv, value;
487 vlib_smp_unsafe_warning ();
489 is_del = (a->flags & IP6_ROUTE_FLAG_DEL) != 0;
491 /* Either create new adjacency or use given one depending on arguments. */
492 if (a->n_add_adj > 0)
494 ip_add_adjacency (lm, a->add_adj, a->n_add_adj, &adj_index);
497 adj_index = a->adj_index;
499 dst_address = a->dst_address;
500 dst_address_length = a->dst_address_length;
501 fib = pool_elt_at_index (lgm->ip6_src_fibs, a->table_index_or_table_id);
503 ASSERT (dst_address_length < ARRAY_LEN (fib->fib_masks));
504 ip6_address_mask (&dst_address, &fib->fib_masks[dst_address_length]);
506 /* refcount accounting */
509 ASSERT (fib->dst_address_length_refcounts[dst_address_length] > 0);
510 if (--fib->dst_address_length_refcounts[dst_address_length] == 0)
512 fib->non_empty_dst_address_length_bitmap =
513 clib_bitmap_set (fib->non_empty_dst_address_length_bitmap,
514 128 - dst_address_length, 0);
515 compute_prefix_lengths_in_search_order (fib);
520 fib->dst_address_length_refcounts[dst_address_length]++;
522 fib->non_empty_dst_address_length_bitmap =
523 clib_bitmap_set (fib->non_empty_dst_address_length_bitmap,
524 128 - dst_address_length, 1);
525 compute_prefix_lengths_in_search_order (fib);
528 kv.key[0] = dst_address.as_u64[0];
529 kv.key[1] = dst_address.as_u64[1];
530 kv.key[2] = dst_address_length;
532 if (BV (clib_bihash_search) (&fib->ip6_lookup_table, &kv, &value) == 0)
533 old_adj_index = value.value;
536 BV (clib_bihash_add_del) (&fib->ip6_lookup_table, &kv, 0 /* is_add */ );
539 /* Make sure adj index is valid. */
541 (void) ip_get_adjacency (lm, adj_index);
543 kv.value = adj_index;
545 BV (clib_bihash_add_del) (&fib->ip6_lookup_table, &kv, 1 /* is_add */ );
548 /* Avoid spurious reference count increments */
549 if (old_adj_index == adj_index
550 && !(a->flags & IP6_ROUTE_FLAG_KEEP_OLD_ADJACENCY))
552 ip_adjacency_t *adj = ip_get_adjacency (lm, adj_index);
553 if (adj->share_count > 0)
557 /* Delete old adjacency index if present and changed. */
559 if (!(a->flags & IP6_ROUTE_FLAG_KEEP_OLD_ADJACENCY)
560 && old_adj_index != ~0 && old_adj_index != adj_index)
561 ip_del_adjacency (lm, old_adj_index);
566 ip6_src_fib_init (ip6_src_fib_t * fib)
570 for (i = 0; i < ARRAY_LEN (fib->fib_masks); i++)
577 for (j = 0; j < i0; j++)
578 fib->fib_masks[i].as_u32[j] = ~0;
581 fib->fib_masks[i].as_u32[i0] =
582 clib_host_to_net_u32 (pow2_mask (i1) << (32 - i1));
585 if (fib->lookup_table_nbuckets == 0)
586 fib->lookup_table_nbuckets = IP6_FIB_DEFAULT_HASH_NUM_BUCKETS;
588 fib->lookup_table_nbuckets = 1 << max_log2 (fib->lookup_table_nbuckets);
590 if (fib->lookup_table_size == 0)
591 fib->lookup_table_size = IP6_FIB_DEFAULT_HASH_MEMORY_SIZE;
593 BV (clib_bihash_init) (&fib->ip6_lookup_table, "ip6 lookup table",
594 fib->lookup_table_nbuckets, fib->lookup_table_size);
599 * @brief Add/del route to IP6 SD FIB.
601 * Adds/remove routes to both destination and source FIBs. Entries added
602 * to destination FIB are associated to adjacencies that point to the source
603 * FIB and store the index of the particular source FIB associated to the
604 * destination. Source FIBs are locally managed (see @ref lgm->ip4_src_fibs
605 * and @ref lgm->ip6_src_fibs), but the adjacencies are allocated out of the
606 * global adjacency pool.
608 * @param[in] lgm Reference to @ref lisp_gpe_main_t.
609 * @param[out] dst_prefix Destination IP6 prefix.
610 * @param[in] src_prefix Source IP6 prefix.
611 * @param[in] table_id Table id.
612 * @param[in] add_adj Pointer to the adjacency to be added.
613 * @param[in] is_add Add/del flag.
615 * @return 0 on success.
618 ip6_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
619 ip_prefix_t * src_prefix, u32 table_id,
620 ip_adjacency_t * add_adj, u8 is_add)
623 ip6_add_del_route_args_t a;
624 ip_adjacency_t *dst_adjp, dst_adj;
625 ip6_address_t dst = ip_prefix_v6 (dst_prefix), src;
626 u32 dst_address_length = ip_prefix_len (dst_prefix), src_address_length = 0;
627 ip6_src_fib_t *src_fib;
631 src = ip_prefix_v6 (src_prefix);
632 src_address_length = ip_prefix_len (src_prefix);
635 memset (&src, 0, sizeof (src));
637 /* lookup dst adj and create it if it doesn't exist */
638 adj_index = ip6_get_route (lgm->im6, table_id, 0, &dst, dst_address_length);
642 /* insert dst prefix to ip6 fib, if it's not in yet */
645 /* allocate and init src ip6 fib */
646 pool_get (lgm->ip6_src_fibs, src_fib);
647 memset (src_fib, 0, sizeof (src_fib[0]));
648 ip6_src_fib_init (src_fib);
650 memset (&dst_adj, 0, sizeof (dst_adj));
652 /* reuse rewrite header to store pointer to src fib */
653 dst_adj.rewrite_header.sw_if_index = src_fib - lgm->ip6_src_fibs;
655 /* dst adj should point to lisp gpe ip lookup */
656 dst_adj.lookup_next_index = lgm->ip6_lookup_next_lgpe_ip6_lookup;
658 /* explicit_fib_index is used in IP6 FIB lookup, don't reuse it */
659 dst_adj.explicit_fib_index = ~0;
662 /* make sure we have different signatures for adj in different tables
663 * but with the same lookup_next_index and for adj in the same table
664 * but associated to different destinations */
665 dst_adj.if_address_index = table_id;
666 dst_adj.indirect.next_hop.ip6 = dst;
668 memset (&a, 0, sizeof (a));
669 a.flags = IP6_ROUTE_FLAG_TABLE_ID;
670 a.table_index_or_table_id = table_id; /* vrf */
672 a.dst_address_length = dst_address_length;
674 a.flags |= IP6_ROUTE_FLAG_ADD;
675 a.add_adj = &dst_adj;
678 ip6_add_del_route (lgm->im6, &a);
680 /* lookup dst adj to obtain the adj index */
681 adj_index = ip6_get_route (lgm->im6, table_id, 0, &dst,
684 /* make sure insertion succeeded */
687 ASSERT (adj_index != 0);
688 dst_adjp = ip_get_adjacency (lgm->lm6, adj_index);
689 ASSERT (dst_adjp->rewrite_header.sw_if_index
690 == dst_adj.rewrite_header.sw_if_index);
699 ("Trying to delete inexistent dst route for %U. Aborting",
700 format_ip_prefix, dst_prefix);
705 dst_adjp = ip_get_adjacency (lgm->lm6, adj_index);
707 /* add/del src prefix to src fib */
708 memset (&a, 0, sizeof (a));
709 a.flags = IP6_ROUTE_FLAG_TABLE_ID;
710 a.table_index_or_table_id = dst_adjp->rewrite_header.sw_if_index;
712 a.flags |= is_add ? IP6_ROUTE_FLAG_ADD : IP6_ROUTE_FLAG_DEL;
714 a.n_add_adj = is_add ? 1 : 0;
715 /* if src prefix is null, add ::0 */
716 a.dst_address_length = src_address_length;
718 ip6_sd_fib_add_del_src_route (lgm, &a);
720 /* make sure insertion succeeded */
721 if (CLIB_DEBUG && is_add)
724 ip_adjacency_t *src_adjp;
725 sai = ip6_sd_get_src_route (lgm, dst_adjp->rewrite_header.sw_if_index,
726 &src, src_address_length);
728 src_adjp = ip_get_adjacency (lgm->lm6, sai);
729 ASSERT (src_adjp->if_address_index == add_adj->if_address_index);
732 /* if a delete, check if there are elements left in the src fib */
735 src_fib = pool_elt_at_index (lgm->ip6_src_fibs,
736 dst_adjp->rewrite_header.sw_if_index);
740 /* if there's nothing left */
741 if (clib_bitmap_count_set_bits
742 (src_fib->non_empty_dst_address_length_bitmap) == 0)
744 /* remove src fib .. */
745 pool_put (lgm->ip6_src_fibs, src_fib);
747 /* .. and remove dst route */
748 memset (&a, 0, sizeof (a));
749 a.flags = IP6_ROUTE_FLAG_TABLE_ID;
750 a.table_index_or_table_id = table_id; /* vrf */
752 a.dst_address_length = dst_address_length;
754 a.flags |= IP6_ROUTE_FLAG_DEL;
756 ip6_add_del_route (lgm->im6, &a);
764 * @brief Retrieve IP6 SD FIB entry.
766 * Looks up SD IP6 route by first looking up the destination in VPP's main FIB
767 * and subsequently the source in the src FIB. The index of the source FIB is
768 * stored in the dst adjacency's @ref rewrite_header.sw_if_index. If source is
769 * 0 do search with ::/0 src.
771 * @param[in] lgm Reference to @ref lisp_gpe_main_t.
772 * @param[out] dst_prefix Destination IP6 prefix.
773 * @param[in] src_prefix Source IP6 prefix.
774 * @param[in] table_id Table id.
776 * @return adjacency index if route found.
779 ip6_sd_fib_get_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
780 ip_prefix_t * src_prefix, u32 table_id)
783 ip6_address_t dst = ip_prefix_v6 (dst_prefix), src;
784 u32 dst_address_length = ip_prefix_len (dst_prefix), src_address_length = 0;
785 ip_adjacency_t *dst_adj;
789 src = ip_prefix_v6 (src_prefix);
790 src_address_length = ip_prefix_len (src_prefix);
793 memset (&src, 0, sizeof (src));
796 adj_index = ip6_get_route (lgm->im6, table_id, 0, &dst, dst_address_length);
800 dst_adj = ip_get_adjacency (lgm->lm6, adj_index);
801 return ip6_sd_get_src_route (lgm, dst_adj->rewrite_header.sw_if_index, &src,
806 * @brief Add/del route to IP4 or IP6 SD FIB.
808 * Adds/remove routes to both destination and source FIBs. Entries added
809 * to destination FIB are associated to adjacencies that point to the source
810 * FIB and store the index of the particular source FIB associated to the
811 * destination. Source FIBs are locally managed (see @ref lgm->ip4_src_fibs
812 * and @ref lgm->ip6_src_fibs), but the adjacencies are allocated out of the
813 * global adjacency pool.
815 * @param[in] lgm Reference to @ref lisp_gpe_main_t.
816 * @param[out] dst_prefix Destination IP prefix.
817 * @param[in] src_prefix Source IP prefix.
818 * @param[in] table_id Table id.
819 * @param[in] add_adj Pointer to the adjacency to be added.
820 * @param[in] is_add Add/del flag.
822 * @return 0 on success.
825 ip_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
826 ip_prefix_t * src_prefix, u32 table_id,
827 ip_adjacency_t * add_adj, u8 is_add)
829 return (ip_prefix_version (dst_prefix) == IP4 ?
830 ip4_sd_fib_add_del_route : ip6_sd_fib_add_del_route) (lgm,
839 * @brief Retrieve IP4 or IP6 SD FIB entry.
841 * Looks up SD IP route by first looking up the destination in VPP's main FIB
842 * and subsequently the source in the src FIB. The index of the source FIB is
843 * stored in the dst adjacency's @ref rewrite_header.sw_if_index. If source is
844 * 0 do search with ::/0 src.
846 * @param[in] lgm Reference to @ref lisp_gpe_main_t.
847 * @param[out] dst_prefix Destination IP prefix.
848 * @param[in] src_prefix Source IP prefix.
849 * @param[in] table_id Table id.
851 * @return adjacency index if route found.
854 ip_sd_fib_get_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
855 ip_prefix_t * src_prefix, u32 table_id)
857 if (ip_prefix_version (dst_prefix) == IP4)
859 u32 *adj_index = ip4_sd_fib_get_route (lgm, dst_prefix, src_prefix,
861 return (adj_index == 0) ? 0 : adj_index[0];
864 return ip6_sd_fib_get_route (lgm, dst_prefix, src_prefix, table_id);
868 ip4_src_fib_lookup_one (lisp_gpe_main_t * lgm, u32 src_fib_index0,
869 ip4_address_t * addr0, u32 * src_adj_index0)
871 ip4_fib_mtrie_leaf_t leaf0, leaf1;
872 ip4_fib_mtrie_t *mtrie0;
874 /* if default route not hit in ip4 lookup */
875 if (PREDICT_TRUE (src_fib_index0 != (u32) ~ 0))
877 mtrie0 = &vec_elt_at_index (lgm->ip4_src_fibs, src_fib_index0)->mtrie;
879 leaf0 = leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
880 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 0);
881 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 1);
882 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
883 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
885 /* Handle default route. */
886 leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY) ?
887 mtrie0->default_leaf : leaf0;
888 src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
891 src_adj_index0[0] = ~0;
895 ip4_src_fib_lookup_two (lisp_gpe_main_t * lgm, u32 src_fib_index0,
896 u32 src_fib_index1, ip4_address_t * addr0,
897 ip4_address_t * addr1, u32 * src_adj_index0,
898 u32 * src_adj_index1)
900 ip4_fib_mtrie_leaf_t leaf0, leaf1;
901 ip4_fib_mtrie_t *mtrie0, *mtrie1;
903 /* if default route not hit in ip4 lookup */
905 (src_fib_index0 != (u32) ~ 0 && src_fib_index1 != (u32) ~ 0))
907 mtrie0 = &vec_elt_at_index (lgm->ip4_src_fibs, src_fib_index0)->mtrie;
908 mtrie1 = &vec_elt_at_index (lgm->ip4_src_fibs, src_fib_index1)->mtrie;
910 leaf0 = leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
912 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 0);
913 leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 0);
915 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 1);
916 leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 1);
918 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
919 leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 2);
921 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
922 leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 3);
924 /* Handle default route. */
925 leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY) ?
926 mtrie0->default_leaf : leaf0;
927 leaf1 = (leaf1 == IP4_FIB_MTRIE_LEAF_EMPTY) ?
928 mtrie1->default_leaf : leaf1;
929 src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
930 src_adj_index1[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf1);
934 ip4_src_fib_lookup_one (lgm, src_fib_index0, addr0, src_adj_index0);
935 ip4_src_fib_lookup_one (lgm, src_fib_index1, addr1, src_adj_index1);
940 * @brief IPv4 src lookup node.
941 * @node lgpe-ip4-lookup
943 * The LISP IPv4 source lookup dispatch node.
945 * This is the IPv4 source lookup dispatch node. It first looks up the
946 * adjacency hit in the main (destination) FIB and then uses its
947 * <code>rewrite_header.sw_if_index</code>to find the source FIB wherein
948 * the source IP is subsequently looked up. Data in the resulting adjacency
949 * is used to decide the next node (the lisp_gpe interface) and if a flow
950 * hash must be computed, when traffic can be load balanced over multiple
954 * @param[in] vm vlib_main_t corresponding to current thread.
955 * @param[in] node vlib_node_runtime_t data for this node.
956 * @param[in] frame vlib_frame_t whose contents should be dispatched.
958 * @return number of vectors in frame.
961 lgpe_ip4_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
962 vlib_frame_t * from_frame)
964 u32 n_left_from, next_index, *from, *to_next;
965 lisp_gpe_main_t *lgm = &lisp_gpe_main;
967 from = vlib_frame_vector_args (from_frame);
968 n_left_from = from_frame->n_vectors;
970 next_index = node->cached_next_index;
972 while (n_left_from > 0)
976 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
978 while (n_left_from >= 4 && n_left_to_next >= 2)
981 vlib_buffer_t *b0, *b1;
982 ip4_header_t *ip0, *ip1;
983 u32 dst_adj_index0, src_adj_index0, src_fib_index0;
984 u32 dst_adj_index1, src_adj_index1, src_fib_index1;
985 ip_adjacency_t *dst_adj0, *src_adj0, *dst_adj1, *src_adj1;
988 next0 = next1 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
990 /* Prefetch next iteration. */
992 vlib_buffer_t *p2, *p3;
994 p2 = vlib_get_buffer (vm, from[2]);
995 p3 = vlib_get_buffer (vm, from[3]);
997 vlib_prefetch_buffer_header (p2, LOAD);
998 vlib_prefetch_buffer_header (p3, LOAD);
1000 CLIB_PREFETCH (p2->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
1001 CLIB_PREFETCH (p3->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
1010 n_left_to_next -= 2;
1013 b0 = vlib_get_buffer (vm, bi0);
1014 b1 = vlib_get_buffer (vm, bi1);
1016 ip0 = vlib_buffer_get_current (b0);
1017 ip1 = vlib_buffer_get_current (b1);
1019 /* dst lookup was done by ip4 lookup */
1020 dst_adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
1021 dst_adj_index1 = vnet_buffer (b1)->ip.adj_index[VLIB_TX];
1023 dst_adj0 = ip_get_adjacency (lgm->lm4, dst_adj_index0);
1024 dst_adj1 = ip_get_adjacency (lgm->lm4, dst_adj_index1);
1026 src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
1027 src_fib_index1 = dst_adj1->rewrite_header.sw_if_index;
1029 ip4_src_fib_lookup_two (lgm, src_fib_index0, src_fib_index1,
1030 &ip0->src_address, &ip1->src_address,
1031 &src_adj_index0, &src_adj_index1);
1033 /* if a source fib exists */
1034 if (PREDICT_TRUE ((u32) ~ 0 != src_adj_index0
1035 && (u32) ~ 0 != src_adj_index1))
1037 vnet_buffer (b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
1038 vnet_buffer (b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
1040 src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
1041 src_adj1 = ip_get_adjacency (lgm->lm4, src_adj_index1);
1043 next0 = src_adj0->explicit_fib_index;
1044 next1 = src_adj1->explicit_fib_index;
1046 /* prepare buffer for lisp-gpe output node */
1047 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1048 src_adj0->rewrite_header.sw_if_index;
1049 vnet_buffer (b1)->sw_if_index[VLIB_TX] =
1050 src_adj1->rewrite_header.sw_if_index;
1052 /* if multipath: saved_lookup_next_index is reused to store
1053 * nb of sub-tunnels. If greater than 1, multipath is on.
1054 * Note that flow hash should be 0 after ipx lookup! */
1055 if (PREDICT_TRUE (src_adj0->saved_lookup_next_index > 1))
1056 vnet_buffer (b0)->ip.flow_hash =
1057 ip4_compute_flow_hash (ip0, IP_FLOW_HASH_DEFAULT);
1059 if (PREDICT_TRUE (src_adj1->saved_lookup_next_index > 1))
1060 vnet_buffer (b1)->ip.flow_hash =
1061 ip4_compute_flow_hash (ip1, IP_FLOW_HASH_DEFAULT);
1065 if ((u32) ~ 0 != src_adj_index0)
1067 vnet_buffer (b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
1068 src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
1069 next0 = src_adj0->explicit_fib_index;
1070 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1071 src_adj0->rewrite_header.sw_if_index;
1073 if (PREDICT_TRUE (src_adj0->saved_lookup_next_index > 1))
1074 vnet_buffer (b0)->ip.flow_hash =
1075 ip4_compute_flow_hash (ip0, IP_FLOW_HASH_DEFAULT);
1079 next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
1082 if ((u32) ~ 0 != src_adj_index1)
1084 vnet_buffer (b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
1085 src_adj1 = ip_get_adjacency (lgm->lm4, src_adj_index1);
1086 next1 = src_adj1->explicit_fib_index;
1087 vnet_buffer (b1)->sw_if_index[VLIB_TX] =
1088 src_adj1->rewrite_header.sw_if_index;
1089 if (PREDICT_TRUE (src_adj1->saved_lookup_next_index > 1))
1090 vnet_buffer (b1)->ip.flow_hash =
1091 ip4_compute_flow_hash (ip1, IP_FLOW_HASH_DEFAULT);
1095 next1 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
1099 /* mark the packets for CP lookup if needed */
1100 if (PREDICT_FALSE (LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
1101 vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
1102 if (PREDICT_FALSE (LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next1))
1103 vnet_buffer (b1)->lisp.overlay_afi = LISP_AFI_IP;
1105 vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
1106 n_left_to_next, bi0, bi1, next0,
1110 while (n_left_from > 0 && n_left_to_next > 0)
1114 u32 bi0, dst_adj_index0, src_adj_index0, src_fib_index0;
1115 u32 next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
1116 ip_adjacency_t *dst_adj0, *src_adj0;
1123 n_left_to_next -= 1;
1125 b0 = vlib_get_buffer (vm, bi0);
1126 ip0 = vlib_buffer_get_current (b0);
1128 /* dst lookup was done by ip4 lookup */
1129 dst_adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
1130 dst_adj0 = ip_get_adjacency (lgm->lm4, dst_adj_index0);
1131 src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
1134 ip4_src_fib_lookup_one (lgm, src_fib_index0, &ip0->src_address,
1137 /* if a source fib exists */
1138 if (PREDICT_TRUE ((u32) ~ 0 != src_adj_index0))
1140 vnet_buffer (b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
1141 src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
1142 next0 = src_adj0->explicit_fib_index;
1144 /* prepare packet for lisp-gpe output node */
1145 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1146 src_adj0->rewrite_header.sw_if_index;
1148 /* if multipath: saved_lookup_next_index is reused to store
1149 * nb of sub-tunnels. If greater than 1, multipath is on */
1150 if (PREDICT_TRUE (src_adj0->saved_lookup_next_index > 1))
1151 vnet_buffer (b0)->ip.flow_hash =
1152 ip4_compute_flow_hash (ip0, IP_FLOW_HASH_DEFAULT);
1156 next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
1159 if (PREDICT_FALSE (LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
1160 vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
1162 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1163 n_left_to_next, bi0, next0);
1165 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1167 return from_frame->n_vectors;
1171 VLIB_REGISTER_NODE (lgpe_ip4_lookup_node) = {
1172 .function = lgpe_ip4_lookup,
1173 .name = "lgpe-ip4-lookup",
1174 .vector_size = sizeof (u32),
1176 .type = VLIB_NODE_TYPE_INTERNAL,
1178 .n_next_nodes = LGPE_IP4_LOOKUP_N_NEXT,
1180 #define _(sym,str) [LGPE_IP4_LOOKUP_NEXT_##sym] = str,
1181 foreach_lgpe_ip4_lookup_next
1188 ip6_src_fib_lookup (lisp_gpe_main_t * lgm, u32 src_fib_index,
1189 ip6_address_t * src)
1193 BVT (clib_bihash_kv) kv, value;
1194 ip6_src_fib_t *fib = pool_elt_at_index (lgm->ip6_src_fibs, src_fib_index);
1196 len = vec_len (fib->prefix_lengths_in_search_order);
1198 for (i = 0; i < len; i++)
1200 int dst_address_length = fib->prefix_lengths_in_search_order[i];
1201 ip6_address_t *mask;
1203 ASSERT (dst_address_length >= 0 && dst_address_length <= 128);
1205 mask = &fib->fib_masks[dst_address_length];
1207 kv.key[0] = src->as_u64[0] & mask->as_u64[0];
1208 kv.key[1] = src->as_u64[1] & mask->as_u64[1];
1209 kv.key[2] = dst_address_length;
1212 BV (clib_bihash_search_inline_2) (&fib->ip6_lookup_table, &kv,
1222 ip6_src_fib_lookup_one (lisp_gpe_main_t * lgm, u32 src_fib_index0,
1223 ip6_address_t * addr0, u32 * src_adj_index0)
1225 /* if default route not hit in ip6 lookup */
1226 if (PREDICT_TRUE (src_fib_index0 != (u32) ~ 0))
1227 src_adj_index0[0] = ip6_src_fib_lookup (lgm, src_fib_index0, addr0);
1229 src_adj_index0[0] = ~0;
1233 ip6_src_fib_lookup_two (lisp_gpe_main_t * lgm, u32 src_fib_index0,
1234 u32 src_fib_index1, ip6_address_t * addr0,
1235 ip6_address_t * addr1, u32 * src_adj_index0,
1236 u32 * src_adj_index1)
1238 /* if default route not hit in ip6 lookup */
1240 (src_fib_index0 != (u32) ~ 0 && src_fib_index1 != (u32) ~ 0))
1242 src_adj_index0[0] = ip6_src_fib_lookup (lgm, src_fib_index0, addr0);
1243 src_adj_index1[0] = ip6_src_fib_lookup (lgm, src_fib_index1, addr1);
1247 ip6_src_fib_lookup_one (lgm, src_fib_index0, addr0, src_adj_index0);
1248 ip6_src_fib_lookup_one (lgm, src_fib_index1, addr1, src_adj_index1);
1253 * @brief IPv6 src lookup node.
1254 * @node lgpe-ip6-lookup
1256 * The LISP IPv6 source lookup dispatch node.
1258 * This is the IPv6 source lookup dispatch node. It first looks up the
1259 * adjacency hit in the main (destination) FIB and then uses its
1260 * <code>rewrite_header.sw_if_index</code>to find the source FIB wherein
1261 * the source IP is subsequently looked up. Data in the resulting adjacency
1262 * is used to decide the next node (the lisp_gpe interface) and if a flow
1263 * hash must be computed, when traffic can be load balanced over multiple
1266 * @param[in] vm vlib_main_t corresponding to current thread.
1267 * @param[in] node vlib_node_runtime_t data for this node.
1268 * @param[in] frame vlib_frame_t whose contents should be dispatched.
1270 * @return number of vectors in frame.
1273 lgpe_ip6_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
1274 vlib_frame_t * from_frame)
1276 u32 n_left_from, next_index, *from, *to_next;
1277 lisp_gpe_main_t *lgm = &lisp_gpe_main;
1279 from = vlib_frame_vector_args (from_frame);
1280 n_left_from = from_frame->n_vectors;
1282 next_index = node->cached_next_index;
1284 while (n_left_from > 0)
1288 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1290 while (n_left_from >= 4 && n_left_to_next >= 2)
1293 vlib_buffer_t *b0, *b1;
1294 ip6_header_t *ip0, *ip1;
1295 u32 dst_adj_index0, src_adj_index0, src_fib_index0, dst_adj_index1,
1296 src_adj_index1, src_fib_index1;
1297 ip_adjacency_t *dst_adj0, *src_adj0, *dst_adj1, *src_adj1;
1300 next0 = next1 = LGPE_IP6_LOOKUP_NEXT_LISP_CP_LOOKUP;
1302 /* Prefetch next iteration. */
1304 vlib_buffer_t *p2, *p3;
1306 p2 = vlib_get_buffer (vm, from[2]);
1307 p3 = vlib_get_buffer (vm, from[3]);
1309 vlib_prefetch_buffer_header (p2, LOAD);
1310 vlib_prefetch_buffer_header (p3, LOAD);
1312 CLIB_PREFETCH (p2->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
1313 CLIB_PREFETCH (p3->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
1322 n_left_to_next -= 2;
1325 b0 = vlib_get_buffer (vm, bi0);
1326 b1 = vlib_get_buffer (vm, bi1);
1328 ip0 = vlib_buffer_get_current (b0);
1329 ip1 = vlib_buffer_get_current (b1);
1331 /* dst lookup was done by ip6 lookup */
1332 dst_adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
1333 dst_adj_index1 = vnet_buffer (b1)->ip.adj_index[VLIB_TX];
1335 dst_adj0 = ip_get_adjacency (lgm->lm6, dst_adj_index0);
1336 dst_adj1 = ip_get_adjacency (lgm->lm6, dst_adj_index1);
1338 src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
1339 src_fib_index1 = dst_adj1->rewrite_header.sw_if_index;
1341 ip6_src_fib_lookup_two (lgm, src_fib_index0, src_fib_index1,
1342 &ip0->src_address, &ip1->src_address,
1343 &src_adj_index0, &src_adj_index1);
1345 /* if a source fib exists */
1346 if (PREDICT_TRUE ((u32) ~ 0 != src_adj_index0
1347 && (u32) ~ 0 != src_adj_index1))
1349 vnet_buffer (b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
1350 vnet_buffer (b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
1352 src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
1353 src_adj1 = ip_get_adjacency (lgm->lm6, src_adj_index1);
1355 next0 = src_adj0->explicit_fib_index;
1356 next1 = src_adj1->explicit_fib_index;
1358 /* prepare buffer for lisp-gpe output node */
1359 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1360 src_adj0->rewrite_header.sw_if_index;
1361 vnet_buffer (b1)->sw_if_index[VLIB_TX] =
1362 src_adj1->rewrite_header.sw_if_index;
1364 /* if multipath: saved_lookup_next_index is reused to store
1365 * nb of sub-tunnels. If greater than 1, multipath is on.
1366 * Note that flow hash should be 0 after ipx lookup! */
1367 if (PREDICT_TRUE (src_adj0->saved_lookup_next_index > 1))
1368 vnet_buffer (b0)->ip.flow_hash =
1369 ip6_compute_flow_hash (ip0, IP_FLOW_HASH_DEFAULT);
1371 if (PREDICT_TRUE (src_adj1->saved_lookup_next_index > 1))
1372 vnet_buffer (b1)->ip.flow_hash =
1373 ip6_compute_flow_hash (ip1, IP_FLOW_HASH_DEFAULT);
1377 if (src_adj_index0 != (u32) ~ 0)
1379 vnet_buffer (b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
1380 src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
1381 next0 = src_adj0->explicit_fib_index;
1382 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1383 src_adj0->rewrite_header.sw_if_index;
1385 if (PREDICT_TRUE (src_adj0->saved_lookup_next_index > 1))
1386 vnet_buffer (b0)->ip.flow_hash =
1387 ip6_compute_flow_hash (ip0, IP_FLOW_HASH_DEFAULT);
1391 next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
1394 if (src_adj_index1 != (u32) ~ 0)
1396 vnet_buffer (b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
1397 src_adj1 = ip_get_adjacency (lgm->lm6, src_adj_index1);
1398 next1 = src_adj1->explicit_fib_index;
1399 vnet_buffer (b1)->sw_if_index[VLIB_TX] =
1400 src_adj1->rewrite_header.sw_if_index;
1402 if (PREDICT_TRUE (src_adj1->saved_lookup_next_index > 1))
1403 vnet_buffer (b1)->ip.flow_hash =
1404 ip6_compute_flow_hash (ip1, IP_FLOW_HASH_DEFAULT);
1408 next1 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
1412 /* mark the packets for CP lookup if needed */
1413 if (PREDICT_FALSE (LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
1414 vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
1415 if (PREDICT_FALSE (LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next1))
1416 vnet_buffer (b1)->lisp.overlay_afi = LISP_AFI_IP;
1418 vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
1419 n_left_to_next, bi0, bi1, next0,
1423 while (n_left_from > 0 && n_left_to_next > 0)
1427 u32 bi0, dst_adj_index0, src_adj_index0, src_fib_index0;
1428 u32 next0 = LGPE_IP6_LOOKUP_NEXT_LISP_CP_LOOKUP;
1429 ip_adjacency_t *dst_adj0, *src_adj0;
1436 n_left_to_next -= 1;
1438 b0 = vlib_get_buffer (vm, bi0);
1439 ip0 = vlib_buffer_get_current (b0);
1441 /* dst lookup was done by ip6 lookup */
1442 dst_adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
1443 dst_adj0 = ip_get_adjacency (lgm->lm6, dst_adj_index0);
1444 src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
1447 ip6_src_fib_lookup_one (lgm, src_fib_index0, &ip0->src_address,
1450 /* if a source fib exists */
1451 if (PREDICT_TRUE (src_adj_index0 != (u32) ~ 0))
1453 vnet_buffer (b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
1454 src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
1455 next0 = src_adj0->explicit_fib_index;
1457 /* prepare packet for lisp-gpe output node */
1458 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1459 src_adj0->rewrite_header.sw_if_index;
1461 /* if multipath: saved_lookup_next_index is reused to store
1462 * nb of sub-tunnels. If greater than 1, multipath is on */
1463 if (PREDICT_TRUE (src_adj0->saved_lookup_next_index > 1))
1464 vnet_buffer (b0)->ip.flow_hash =
1465 ip6_compute_flow_hash (ip0, IP_FLOW_HASH_DEFAULT);
1469 next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
1472 /* mark the packets for CP lookup if needed */
1473 if (PREDICT_FALSE (LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
1474 vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
1476 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1477 n_left_to_next, bi0, next0);
1479 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1481 return from_frame->n_vectors;
1485 VLIB_REGISTER_NODE (lgpe_ip6_lookup_node) = {
1486 .function = lgpe_ip6_lookup,
1487 .name = "lgpe-ip6-lookup",
1488 .vector_size = sizeof (u32),
1490 .type = VLIB_NODE_TYPE_INTERNAL,
1492 .n_next_nodes = LGPE_IP6_LOOKUP_N_NEXT,
1494 #define _(sym,str) [LGPE_IP6_LOOKUP_NEXT_##sym] = str,
1495 foreach_lgpe_ip6_lookup_next
1502 * fd.io coding-style-patch-verification: ON
1505 * eval: (c-set-style "gnu")