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.
16 #include <vnet/lisp-gpe/lisp_gpe.h>
18 /* avoids calling route callbacks for src fib */
20 ip4_sd_fib_set_adj_index (lisp_gpe_main_t * lgm, ip4_fib_t * fib, u32 flags,
21 u32 dst_address_u32, u32 dst_address_length,
24 ip_lookup_main_t * lm = lgm->lm4;
27 if (vec_bytes(fib->old_hash_values))
28 memset (fib->old_hash_values, ~0, vec_bytes (fib->old_hash_values));
29 if (vec_bytes(fib->new_hash_values))
30 memset (fib->new_hash_values, ~0, vec_bytes (fib->new_hash_values));
31 fib->new_hash_values[0] = adj_index;
33 /* Make sure adj index is valid. */
35 (void) ip_get_adjacency (lm, adj_index);
37 hash = fib->adj_index_by_dst_address[dst_address_length];
39 hash = _hash_set3 (hash, dst_address_u32,
41 fib->old_hash_values);
43 fib->adj_index_by_dst_address[dst_address_length] = hash;
46 /* copied from ip4_forward since it's static */
48 ip4_fib_init_adj_index_by_dst_address (ip_lookup_main_t * lm,
55 ASSERT (lm->fib_result_n_bytes >= sizeof (uword));
56 lm->fib_result_n_words = round_pow2 (lm->fib_result_n_bytes, sizeof(uword))
59 fib->adj_index_by_dst_address[address_length] =
60 hash_create (32 /* elts */, lm->fib_result_n_words * sizeof (uword));
62 hash_set_flags (fib->adj_index_by_dst_address[address_length],
63 HASH_FLAG_NO_AUTO_SHRINK);
65 h = hash_header (fib->adj_index_by_dst_address[address_length]);
66 max_index = (hash_value_bytes (h) / sizeof (fib->new_hash_values[0])) - 1;
68 /* Initialize new/old hash value vectors. */
69 vec_validate_init_empty (fib->new_hash_values, max_index, ~0);
70 vec_validate_init_empty (fib->old_hash_values, max_index, ~0);
74 ip4_sd_fib_add_del_src_route (lisp_gpe_main_t * lgm,
75 ip4_add_del_route_args_t * a)
77 ip_lookup_main_t * lm = lgm->lm4;
79 u32 dst_address, dst_address_length, adj_index, old_adj_index;
82 /* Either create new adjacency or use given one depending on arguments. */
84 ip_add_adjacency (lm, a->add_adj, a->n_add_adj, &adj_index);
86 adj_index = a->adj_index;
88 dst_address = a->dst_address.data_u32;
89 dst_address_length = a->dst_address_length;
91 fib = pool_elt_at_index(lgm->ip4_src_fibs, a->table_index_or_table_id);
93 if (! fib->adj_index_by_dst_address[dst_address_length])
94 ip4_fib_init_adj_index_by_dst_address (lm, fib, dst_address_length);
96 hash = fib->adj_index_by_dst_address[dst_address_length];
98 is_del = (a->flags & IP4_ROUTE_FLAG_DEL) != 0;
102 fib->old_hash_values[0] = ~0;
103 hash = _hash_unset (hash, dst_address, fib->old_hash_values);
104 fib->adj_index_by_dst_address[dst_address_length] = hash;
107 ip4_sd_fib_set_adj_index (lgm, fib, a->flags, dst_address,
108 dst_address_length, adj_index);
110 old_adj_index = fib->old_hash_values[0];
112 /* Avoid spurious reference count increments */
113 if (old_adj_index == adj_index
115 && !(a->flags & IP4_ROUTE_FLAG_KEEP_OLD_ADJACENCY))
117 ip_adjacency_t * adj = ip_get_adjacency (lm, adj_index);
118 if (adj->share_count > 0)
122 ip4_fib_mtrie_add_del_route (fib, a->dst_address, dst_address_length,
123 is_del ? old_adj_index : adj_index,
126 /* Delete old adjacency index if present and changed. */
127 if (! (a->flags & IP4_ROUTE_FLAG_KEEP_OLD_ADJACENCY)
128 && old_adj_index != ~0
129 && old_adj_index != adj_index)
130 ip_del_adjacency (lm, old_adj_index);
134 ip4_sd_get_src_route (lisp_gpe_main_t * lgm, u32 src_fib_index,
135 ip4_address_t * src, u32 address_length)
137 ip4_fib_t * fib = pool_elt_at_index (lgm->ip4_src_fibs, src_fib_index);
140 hash = fib->adj_index_by_dst_address[address_length];
141 p = hash_get (hash, src->as_u32);
145 typedef CLIB_PACKED (struct ip4_route {
146 ip4_address_t address;
147 u32 address_length : 6;
152 ip4_sd_fib_clear_src_fib (lisp_gpe_main_t * lgm, ip4_fib_t * fib)
154 ip4_route_t * routes = 0, * r;
157 vec_reset_length (routes);
159 for (i = 0; i < ARRAY_LEN (fib->adj_index_by_dst_address); i++) {
160 uword * hash = fib->adj_index_by_dst_address[i];
164 x.address_length = i;
166 hash_foreach_pair (p, hash,
168 x.address.data_u32 = p->key;
169 vec_add1 (routes, x);
173 vec_foreach (r, routes) {
174 ip4_add_del_route_args_t a;
176 memset (&a, 0, sizeof (a));
177 a.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_DEL;
178 a.table_index_or_table_id = fib - lgm->ip4_src_fibs;
179 a.dst_address = r->address;
180 a.dst_address_length = r->address_length;
183 ip4_sd_fib_add_del_src_route (lgm, &a);
188 ip4_fib_is_empty (ip4_fib_t * fib)
194 for (i = ARRAY_LEN (fib->adj_index_by_dst_address) - 1; i >= 0; i--)
196 uword * hash = fib->adj_index_by_dst_address[i];
197 uword n_elts = hash_elts (hash);
208 ip4_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
209 ip_prefix_t * src_prefix, u32 table_id,
210 ip_adjacency_t * add_adj, u8 is_add)
213 ip4_add_del_route_args_t a;
214 ip_adjacency_t * dst_adjp, dst_adj;
215 ip4_address_t dst = ip_prefix_v4(dst_prefix), src;
216 u32 dst_address_length = ip_prefix_len(dst_prefix), src_address_length = 0;
221 src = ip_prefix_v4(src_prefix);
222 src_address_length = ip_prefix_len(src_prefix);
225 memset(&src, 0, sizeof(src));
228 p = ip4_get_route (lgm->im4, table_id, 0, dst.as_u8, dst_address_length);
232 /* insert dst prefix to ip4 fib, if it's not in yet */
235 /* allocate and init src ip4 fib */
236 pool_get(lgm->ip4_src_fibs, src_fib);
237 ip4_mtrie_init (&src_fib->mtrie);
239 /* configure adjacency */
240 memset(&dst_adj, 0, sizeof(dst_adj));
242 /* reuse rewrite header to store pointer to src fib */
243 dst_adj.rewrite_header.sw_if_index = src_fib - lgm->ip4_src_fibs;
245 /* dst adj should point to lisp gpe lookup */
246 dst_adj.lookup_next_index = lgm->ip4_lookup_next_lgpe_ip4_lookup;
248 /* explicit_fib_index is used in IP6 FIB lookup, don't reuse it */
249 dst_adj.explicit_fib_index = ~0;
252 /* make sure we have different signatures for adj in different tables
253 * but with the same lookup_next_index and for adj in the same table
254 * but associated to different destinations */
255 dst_adj.if_address_index = table_id;
256 dst_adj.indirect.next_hop.ip4 = dst;
258 memset(&a, 0, sizeof(a));
259 a.flags = IP4_ROUTE_FLAG_TABLE_ID;
260 a.table_index_or_table_id = table_id; /* vrf */
262 a.dst_address_length = dst_address_length;
264 a.flags |= IP4_ROUTE_FLAG_ADD;
265 a.add_adj = &dst_adj;
268 ip4_add_del_route (lgm->im4, &a);
270 /* lookup dst adj to obtain the adj index */
271 p = ip4_get_route (lgm->im4, table_id, 0, dst.as_u8,
274 /* make sure insertion succeeded */
278 dst_adjp = ip_get_adjacency (lgm->lm4, p[0]);
279 ASSERT(dst_adjp->rewrite_header.sw_if_index
280 == dst_adj.rewrite_header.sw_if_index);
288 clib_warning("Trying to delete inexistent dst route for %U. Aborting",
289 format_ip4_address_and_length, dst.as_u8,
295 dst_adjp = ip_get_adjacency (lgm->lm4, p[0]);
297 /* add/del src prefix to src fib */
298 memset(&a, 0, sizeof(a));
299 a.flags = IP4_ROUTE_FLAG_TABLE_ID;
300 a.table_index_or_table_id = dst_adjp->rewrite_header.sw_if_index;
302 a.flags |= is_add ? IP4_ROUTE_FLAG_ADD : IP4_ROUTE_FLAG_DEL;
304 a.n_add_adj = is_add ? 1 : 0;
305 /* if src prefix is null, add 0/0 */
306 a.dst_address_length = src_address_length;
308 ip4_sd_fib_add_del_src_route (lgm, &a);
310 /* make sure insertion succeeded */
311 if (CLIB_DEBUG && is_add)
314 ip_adjacency_t * src_adjp;
315 sai = ip4_sd_get_src_route (lgm, dst_adjp->rewrite_header.sw_if_index,
316 &src, src_address_length);
318 src_adjp = ip_get_adjacency(lgm->lm4, sai[0]);
319 ASSERT(src_adjp->if_address_index == add_adj->if_address_index);
322 /* if a delete, check if there are elements left in the src fib */
325 src_fib = pool_elt_at_index(lgm->ip4_src_fibs,
326 dst_adjp->rewrite_header.sw_if_index);
330 /* if there's nothing left */
331 if (ip4_fib_is_empty(src_fib))
333 /* remove the src fib .. */
334 pool_put(lgm->ip4_src_fibs, src_fib);
336 /* .. and remove dst route */
337 memset(&a, 0, sizeof(a));
338 a.flags = IP4_ROUTE_FLAG_TABLE_ID;
339 a.table_index_or_table_id = table_id; /* vrf */
341 a.dst_address_length = dst_address_length;
343 a.flags |= IP4_ROUTE_FLAG_DEL;
345 ip4_add_del_route (lgm->im4, &a);
353 ip4_sd_fib_get_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
354 ip_prefix_t * src_prefix, u32 table_id)
357 ip4_address_t dst = ip_prefix_v4(dst_prefix), src;
358 u32 dst_address_length = ip_prefix_len(dst_prefix), src_address_length = 0;
359 ip_adjacency_t * dst_adj;
363 src = ip_prefix_v4(src_prefix);
364 src_address_length = ip_prefix_len(src_prefix);
367 memset(&src, 0, sizeof(src));
370 p = ip4_get_route (lgm->im4, table_id, 0, dst.as_u8, dst_address_length);
374 dst_adj = ip_get_adjacency (lgm->lm4, p[0]);
375 return ip4_sd_get_src_route (lgm, dst_adj->rewrite_header.sw_if_index, &src,
380 ip6_sd_get_src_route (lisp_gpe_main_t * lgm, u32 src_fib_index,
381 ip6_address_t * src, u32 address_length)
384 BVT(clib_bihash_kv) kv, value;
385 ip6_src_fib_t * fib = pool_elt_at_index (lgm->ip6_src_fibs, src_fib_index);
387 ip6_address_t * mask;
389 ASSERT(address_length <= 128);
391 mask = &fib->fib_masks[address_length];
393 kv.key[0] = src->as_u64[0] & mask->as_u64[0];
394 kv.key[1] = src->as_u64[1] & mask->as_u64[1];
395 kv.key[2] = address_length;
397 rv = BV(clib_bihash_search_inline_2)(&fib->ip6_lookup_table, &kv, &value);
405 compute_prefix_lengths_in_search_order (ip6_src_fib_t * fib)
408 vec_reset_length(fib->prefix_lengths_in_search_order);
409 /* Note: bitmap reversed so this is in fact a longest prefix match */
410 clib_bitmap_foreach(i, fib->non_empty_dst_address_length_bitmap, ({
411 int dst_address_length = 128 - i;
412 vec_add1 (fib->prefix_lengths_in_search_order, dst_address_length);
416 /* Rewrite of ip6_add_del_route() because it uses im6 to find the fib */
418 ip6_sd_fib_add_del_src_route (lisp_gpe_main_t * lgm,
419 ip6_add_del_route_args_t * a)
421 ip_lookup_main_t * lm = lgm->lm6;
423 ip6_address_t dst_address;
424 u32 dst_address_length, adj_index;
426 u32 old_adj_index = ~0;
427 BVT(clib_bihash_kv) kv, value;
429 vlib_smp_unsafe_warning();
431 is_del = (a->flags & IP6_ROUTE_FLAG_DEL) != 0;
433 /* Either create new adjacency or use given one depending on arguments. */
434 if (a->n_add_adj > 0)
436 ip_add_adjacency (lm, a->add_adj, a->n_add_adj, &adj_index);
439 adj_index = a->adj_index;
441 dst_address = a->dst_address;
442 dst_address_length = a->dst_address_length;
443 fib = pool_elt_at_index(lgm->ip6_src_fibs, a->table_index_or_table_id);
445 ASSERT (dst_address_length < ARRAY_LEN (fib->fib_masks));
446 ip6_address_mask (&dst_address, &fib->fib_masks[dst_address_length]);
448 /* refcount accounting */
451 ASSERT(fib->dst_address_length_refcounts[dst_address_length] > 0);
452 if (--fib->dst_address_length_refcounts[dst_address_length] == 0)
454 fib->non_empty_dst_address_length_bitmap = clib_bitmap_set (
455 fib->non_empty_dst_address_length_bitmap,
456 128 - dst_address_length, 0);
457 compute_prefix_lengths_in_search_order (fib);
462 fib->dst_address_length_refcounts[dst_address_length]++;
464 fib->non_empty_dst_address_length_bitmap =
465 clib_bitmap_set (fib->non_empty_dst_address_length_bitmap,
466 128 - dst_address_length, 1);
467 compute_prefix_lengths_in_search_order (fib);
470 kv.key[0] = dst_address.as_u64[0];
471 kv.key[1] = dst_address.as_u64[1];
472 kv.key[2] = dst_address_length;
474 if (BV(clib_bihash_search)(&fib->ip6_lookup_table, &kv, &value) == 0)
475 old_adj_index = value.value;
478 BV(clib_bihash_add_del) (&fib->ip6_lookup_table, &kv, 0 /* is_add */);
481 /* Make sure adj index is valid. */
483 (void) ip_get_adjacency (lm, adj_index);
485 kv.value = adj_index;
487 BV(clib_bihash_add_del) (&fib->ip6_lookup_table, &kv, 1 /* is_add */);
490 /* Avoid spurious reference count increments */
491 if (old_adj_index == adj_index
492 && !(a->flags & IP6_ROUTE_FLAG_KEEP_OLD_ADJACENCY))
494 ip_adjacency_t * adj = ip_get_adjacency (lm, adj_index);
495 if (adj->share_count > 0)
499 /* Delete old adjacency index if present and changed. */
501 if (! (a->flags & IP6_ROUTE_FLAG_KEEP_OLD_ADJACENCY)
502 && old_adj_index != ~0
503 && old_adj_index != adj_index)
504 ip_del_adjacency (lm, old_adj_index);
509 ip6_src_fib_init (ip6_src_fib_t * fib)
513 for (i = 0; i < ARRAY_LEN (fib->fib_masks); i++)
520 for (j = 0; j < i0; j++)
521 fib->fib_masks[i].as_u32[j] = ~0;
524 fib->fib_masks[i].as_u32[i0] = clib_host_to_net_u32 (
525 pow2_mask (i1) << (32 - i1));
528 if (fib->lookup_table_nbuckets == 0)
529 fib->lookup_table_nbuckets = IP6_FIB_DEFAULT_HASH_NUM_BUCKETS;
531 fib->lookup_table_nbuckets = 1 << max_log2 (fib->lookup_table_nbuckets);
533 if (fib->lookup_table_size == 0)
534 fib->lookup_table_size = IP6_FIB_DEFAULT_HASH_MEMORY_SIZE;
536 BV(clib_bihash_init) (&fib->ip6_lookup_table, "ip6 lookup table",
537 fib->lookup_table_nbuckets,
538 fib->lookup_table_size);
543 ip6_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
544 ip_prefix_t * src_prefix, u32 table_id,
545 ip_adjacency_t * add_adj, u8 is_add)
548 ip6_add_del_route_args_t a;
549 ip_adjacency_t * dst_adjp, dst_adj;
550 ip6_address_t dst = ip_prefix_v6(dst_prefix), src;
551 u32 dst_address_length = ip_prefix_len(dst_prefix), src_address_length = 0;
552 ip6_src_fib_t * src_fib;
556 src = ip_prefix_v6(src_prefix);
557 src_address_length = ip_prefix_len(src_prefix);
560 memset(&src, 0, sizeof(src));
562 /* lookup dst adj and create it if it doesn't exist */
563 adj_index = ip6_get_route (lgm->im6, table_id, 0, &dst, dst_address_length);
567 /* insert dst prefix to ip6 fib, if it's not in yet */
570 /* allocate and init src ip6 fib */
571 pool_get(lgm->ip6_src_fibs, src_fib);
572 memset(src_fib, 0, sizeof(src_fib[0]));
573 ip6_src_fib_init (src_fib);
575 memset(&dst_adj, 0, sizeof(dst_adj));
577 /* reuse rewrite header to store pointer to src fib */
578 dst_adj.rewrite_header.sw_if_index = src_fib - lgm->ip6_src_fibs;
580 /* dst adj should point to lisp gpe ip lookup */
581 dst_adj.lookup_next_index = lgm->ip6_lookup_next_lgpe_ip6_lookup;
583 /* explicit_fib_index is used in IP6 FIB lookup, don't reuse it */
584 dst_adj.explicit_fib_index = ~0;
587 /* make sure we have different signatures for adj in different tables
588 * but with the same lookup_next_index and for adj in the same table
589 * but associated to different destinations */
590 dst_adj.if_address_index = table_id;
591 dst_adj.indirect.next_hop.ip6 = dst;
593 memset(&a, 0, sizeof(a));
594 a.flags = IP6_ROUTE_FLAG_TABLE_ID;
595 a.table_index_or_table_id = table_id; /* vrf */
597 a.dst_address_length = dst_address_length;
599 a.flags |= IP6_ROUTE_FLAG_ADD;
600 a.add_adj = &dst_adj;
603 ip6_add_del_route (lgm->im6, &a);
605 /* lookup dst adj to obtain the adj index */
606 adj_index = ip6_get_route (lgm->im6, table_id, 0, &dst,
609 /* make sure insertion succeeded */
612 ASSERT(adj_index != 0);
613 dst_adjp = ip_get_adjacency (lgm->lm6, adj_index);
614 ASSERT(dst_adjp->rewrite_header.sw_if_index
615 == dst_adj.rewrite_header.sw_if_index);
623 clib_warning("Trying to delete inexistent dst route for %U. Aborting",
624 format_ip_prefix, dst_prefix);
629 dst_adjp = ip_get_adjacency (lgm->lm6, adj_index);
631 /* add/del src prefix to src fib */
632 memset(&a, 0, sizeof(a));
633 a.flags = IP6_ROUTE_FLAG_TABLE_ID;
634 a.table_index_or_table_id = dst_adjp->rewrite_header.sw_if_index;
636 a.flags |= is_add ? IP6_ROUTE_FLAG_ADD : IP6_ROUTE_FLAG_DEL;
638 a.n_add_adj = is_add ? 1 : 0;
639 /* if src prefix is null, add ::0 */
640 a.dst_address_length = src_address_length;
642 ip6_sd_fib_add_del_src_route (lgm, &a);
644 /* make sure insertion succeeded */
645 if (CLIB_DEBUG && is_add)
648 ip_adjacency_t * src_adjp;
649 sai = ip6_sd_get_src_route (lgm, dst_adjp->rewrite_header.sw_if_index,
650 &src, src_address_length);
652 src_adjp = ip_get_adjacency(lgm->lm6, sai);
653 ASSERT(src_adjp->if_address_index == add_adj->if_address_index);
656 /* if a delete, check if there are elements left in the src fib */
659 src_fib = pool_elt_at_index(lgm->ip6_src_fibs,
660 dst_adjp->rewrite_header.sw_if_index);
664 /* if there's nothing left */
665 if (clib_bitmap_count_set_bits (
666 src_fib->non_empty_dst_address_length_bitmap) == 0)
668 /* remove src fib .. */
669 pool_put(lgm->ip6_src_fibs, src_fib);
671 /* .. and remove dst route */
672 memset(&a, 0, sizeof(a));
673 a.flags = IP6_ROUTE_FLAG_TABLE_ID;
674 a.table_index_or_table_id = table_id; /* vrf */
676 a.dst_address_length = dst_address_length;
678 a.flags |= IP6_ROUTE_FLAG_DEL;
680 ip6_add_del_route (lgm->im6, &a);
688 ip6_sd_fib_get_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
689 ip_prefix_t * src_prefix, u32 table_id)
692 ip6_address_t dst = ip_prefix_v6(dst_prefix), src;
693 u32 dst_address_length = ip_prefix_len(dst_prefix), src_address_length = 0;
694 ip_adjacency_t * dst_adj;
698 src = ip_prefix_v6(src_prefix);
699 src_address_length = ip_prefix_len(src_prefix);
702 memset(&src, 0, sizeof(src));
705 adj_index = ip6_get_route (lgm->im6, table_id, 0, &dst, dst_address_length);
709 dst_adj = ip_get_adjacency (lgm->lm6, adj_index);
710 return ip6_sd_get_src_route (lgm, dst_adj->rewrite_header.sw_if_index, &src,
715 ip_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
716 ip_prefix_t * src_prefix, u32 table_id,
717 ip_adjacency_t * add_adj, u8 is_add)
720 ip_prefix_version(dst_prefix) == IP4 ?
721 ip4_sd_fib_add_del_route : ip6_sd_fib_add_del_route) (lgm, dst_prefix,
728 ip_sd_fib_get_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
729 ip_prefix_t * src_prefix, u32 table_id)
731 if (ip_prefix_version(dst_prefix) == IP4)
733 u32 * adj_index = ip4_sd_fib_get_route (lgm, dst_prefix, src_prefix,
735 return (adj_index == 0) ? 0 : adj_index[0];
738 return ip6_sd_fib_get_route (lgm, dst_prefix, src_prefix, table_id);
742 ip4_src_fib_lookup_one (lisp_gpe_main_t * lgm, u32 src_fib_index0,
743 ip4_address_t * addr0, u32 * src_adj_index0)
745 ip4_fib_mtrie_leaf_t leaf0, leaf1;
746 ip4_fib_mtrie_t * mtrie0;
748 /* if default route not hit in ip4 lookup */
749 if (PREDICT_TRUE(src_fib_index0 != (u32 ) ~0))
751 mtrie0 = &vec_elt_at_index(lgm->ip4_src_fibs, src_fib_index0)->mtrie;
753 leaf0 = leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
754 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 0);
755 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 1);
756 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
757 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
759 /* Handle default route. */
760 leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY) ?
761 mtrie0->default_leaf : leaf0;
762 src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
765 src_adj_index0[0] = ~0;
769 ip4_src_fib_lookup_two (lisp_gpe_main_t * lgm, u32 src_fib_index0,
770 u32 src_fib_index1, ip4_address_t * addr0,
771 ip4_address_t * addr1, u32 * src_adj_index0,
772 u32 * src_adj_index1)
774 ip4_fib_mtrie_leaf_t leaf0, leaf1;
775 ip4_fib_mtrie_t * mtrie0, * mtrie1;
777 /* if default route not hit in ip4 lookup */
778 if (PREDICT_TRUE(src_fib_index0 != (u32 ) ~0 && src_fib_index1 != (u32 ) ~0))
780 mtrie0 = &vec_elt_at_index(lgm->ip4_src_fibs, src_fib_index0)->mtrie;
781 mtrie1 = &vec_elt_at_index(lgm->ip4_src_fibs, src_fib_index1)->mtrie;
783 leaf0 = leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
785 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 0);
786 leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 0);
788 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 1);
789 leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 1);
791 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
792 leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 2);
794 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
795 leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 3);
797 /* Handle default route. */
798 leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY) ?
799 mtrie0->default_leaf : leaf0;
800 leaf1 = (leaf1 == IP4_FIB_MTRIE_LEAF_EMPTY) ?
801 mtrie1->default_leaf : leaf1;
802 src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
803 src_adj_index1[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf1);
807 ip4_src_fib_lookup_one (lgm, src_fib_index0, addr0, src_adj_index0);
808 ip4_src_fib_lookup_one (lgm, src_fib_index1, addr1, src_adj_index1);
813 lgpe_ip4_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
814 vlib_frame_t * from_frame)
816 u32 n_left_from, next_index, * from, * to_next;
817 lisp_gpe_main_t * lgm = &lisp_gpe_main;
819 from = vlib_frame_vector_args (from_frame);
820 n_left_from = from_frame->n_vectors;
822 next_index = node->cached_next_index;
824 while (n_left_from > 0)
828 vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
830 while (n_left_from >= 4 && n_left_to_next >= 2)
833 vlib_buffer_t * b0, * b1;
834 ip4_header_t * ip0, * ip1;
835 u32 dst_adj_index0, src_adj_index0, src_fib_index0;
836 u32 dst_adj_index1, src_adj_index1, src_fib_index1;
837 ip_adjacency_t * dst_adj0, * src_adj0, * dst_adj1, * src_adj1;
840 next0 = next1 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
842 /* Prefetch next iteration. */
844 vlib_buffer_t * p2, * p3;
846 p2 = vlib_get_buffer (vm, from[2]);
847 p3 = vlib_get_buffer (vm, from[3]);
849 vlib_prefetch_buffer_header (p2, LOAD);
850 vlib_prefetch_buffer_header (p3, LOAD);
852 CLIB_PREFETCH (p2->data, 2*CLIB_CACHE_LINE_BYTES, LOAD);
853 CLIB_PREFETCH (p3->data, 2*CLIB_CACHE_LINE_BYTES, LOAD);
865 b0 = vlib_get_buffer (vm, bi0);
866 b1 = vlib_get_buffer (vm, bi1);
868 ip0 = vlib_buffer_get_current (b0);
869 ip1 = vlib_buffer_get_current (b1);
871 /* dst lookup was done by ip4 lookup */
872 dst_adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
873 dst_adj_index1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
875 dst_adj0 = ip_get_adjacency (lgm->lm4, dst_adj_index0);
876 dst_adj1 = ip_get_adjacency (lgm->lm4, dst_adj_index1);
878 src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
879 src_fib_index1 = dst_adj1->rewrite_header.sw_if_index;
881 ip4_src_fib_lookup_two (lgm, src_fib_index0, src_fib_index1,
882 &ip0->src_address, &ip1->src_address,
883 &src_adj_index0, &src_adj_index1);
885 /* if a source fib exists */
886 if (PREDICT_TRUE((u32) ~0 != src_adj_index0
887 && (u32) ~0 != src_adj_index1))
889 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
890 vnet_buffer(b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
892 src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
893 src_adj1 = ip_get_adjacency (lgm->lm4, src_adj_index1);
895 next0 = src_adj0->explicit_fib_index;
896 next1 = src_adj1->explicit_fib_index;
898 /* prepare buffer for lisp-gpe output node */
899 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
900 src_adj0->rewrite_header.sw_if_index;
901 vnet_buffer (b1)->sw_if_index[VLIB_TX] =
902 src_adj1->rewrite_header.sw_if_index;
904 /* if multipath: saved_lookup_next_index is reused to store
905 * nb of sub-tunnels. If greater than 1, multipath is on.
906 * Note that flow hash should be 0 after ipx lookup! */
907 if (PREDICT_TRUE(src_adj0->saved_lookup_next_index > 1))
908 vnet_buffer (b0)->ip.flow_hash = ip4_compute_flow_hash (
909 ip0, IP_FLOW_HASH_DEFAULT);
911 if (PREDICT_TRUE(src_adj1->saved_lookup_next_index > 1))
912 vnet_buffer (b1)->ip.flow_hash = ip4_compute_flow_hash (
913 ip1, IP_FLOW_HASH_DEFAULT);
917 if ((u32) ~0 != src_adj_index0)
919 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
920 src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
921 next0 = src_adj0->explicit_fib_index;
922 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
923 src_adj0->rewrite_header.sw_if_index;
925 if (PREDICT_TRUE(src_adj0->saved_lookup_next_index > 1))
926 vnet_buffer (b0)->ip.flow_hash = ip4_compute_flow_hash (
927 ip0, IP_FLOW_HASH_DEFAULT);
931 next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
934 if ((u32) ~0 != src_adj_index1)
936 vnet_buffer(b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
937 src_adj1 = ip_get_adjacency (lgm->lm4, src_adj_index1);
938 next1 = src_adj1->explicit_fib_index;
939 vnet_buffer (b1)->sw_if_index[VLIB_TX] =
940 src_adj1->rewrite_header.sw_if_index;
941 if (PREDICT_TRUE(src_adj1->saved_lookup_next_index > 1))
942 vnet_buffer (b1)->ip.flow_hash = ip4_compute_flow_hash (
943 ip1, IP_FLOW_HASH_DEFAULT);
947 next1 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
951 /* mark the packets for CP lookup if needed*/
952 if (PREDICT_FALSE(LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
953 vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
954 if (PREDICT_FALSE(LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next1))
955 vnet_buffer (b1)->lisp.overlay_afi = LISP_AFI_IP;
957 vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
958 n_left_to_next, bi0, bi1, next0,
962 while (n_left_from > 0 && n_left_to_next > 0)
966 u32 bi0, dst_adj_index0, src_adj_index0, src_fib_index0;
967 u32 next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
968 ip_adjacency_t * dst_adj0, * src_adj0;
977 b0 = vlib_get_buffer (vm, bi0);
978 ip0 = vlib_buffer_get_current (b0);
980 /* dst lookup was done by ip4 lookup */
981 dst_adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
982 dst_adj0 = ip_get_adjacency (lgm->lm4, dst_adj_index0);
983 src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
986 ip4_src_fib_lookup_one (lgm, src_fib_index0, &ip0->src_address,
989 /* if a source fib exists */
990 if (PREDICT_TRUE((u32) ~0 != src_adj_index0))
992 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
993 src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
994 next0 = src_adj0->explicit_fib_index;
996 /* prepare packet for lisp-gpe output node */
997 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
998 src_adj0->rewrite_header.sw_if_index;
1000 /* if multipath: saved_lookup_next_index is reused to store
1001 * nb of sub-tunnels. If greater than 1, multipath is on */
1002 if (PREDICT_TRUE(src_adj0->saved_lookup_next_index > 1))
1003 vnet_buffer (b0)->ip.flow_hash = ip4_compute_flow_hash (
1004 ip0, IP_FLOW_HASH_DEFAULT);
1008 next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
1011 if (PREDICT_FALSE(LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
1012 vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
1014 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
1015 n_left_to_next, bi0, next0);
1017 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1019 return from_frame->n_vectors;
1022 VLIB_REGISTER_NODE (lgpe_ip4_lookup_node) = {
1023 .function = lgpe_ip4_lookup,
1024 .name = "lgpe-ip4-lookup",
1025 .vector_size = sizeof (u32),
1027 .type = VLIB_NODE_TYPE_INTERNAL,
1029 .n_next_nodes = LGPE_IP4_LOOKUP_N_NEXT,
1031 #define _(sym,str) [LGPE_IP4_LOOKUP_NEXT_##sym] = str,
1032 foreach_lgpe_ip4_lookup_next
1038 ip6_src_fib_lookup (lisp_gpe_main_t * lgm, u32 src_fib_index,
1039 ip6_address_t * src)
1043 BVT(clib_bihash_kv) kv, value;
1044 ip6_src_fib_t * fib = pool_elt_at_index (lgm->ip6_src_fibs, src_fib_index);
1046 len = vec_len (fib->prefix_lengths_in_search_order);
1048 for (i = 0; i < len; i++)
1050 int dst_address_length = fib->prefix_lengths_in_search_order[i];
1051 ip6_address_t * mask;
1053 ASSERT(dst_address_length >= 0 && dst_address_length <= 128);
1055 mask = &fib->fib_masks[dst_address_length];
1057 kv.key[0] = src->as_u64[0] & mask->as_u64[0];
1058 kv.key[1] = src->as_u64[1] & mask->as_u64[1];
1059 kv.key[2] = dst_address_length;
1061 rv = BV(clib_bihash_search_inline_2)(&fib->ip6_lookup_table, &kv, &value);
1070 ip6_src_fib_lookup_one (lisp_gpe_main_t * lgm, u32 src_fib_index0,
1071 ip6_address_t * addr0, u32 * src_adj_index0)
1073 /* if default route not hit in ip6 lookup */
1074 if (PREDICT_TRUE(src_fib_index0 != (u32 ) ~0))
1075 src_adj_index0[0] = ip6_src_fib_lookup (lgm, src_fib_index0, addr0);
1077 src_adj_index0[0] = ~0;
1081 ip6_src_fib_lookup_two (lisp_gpe_main_t * lgm, u32 src_fib_index0,
1082 u32 src_fib_index1, ip6_address_t * addr0,
1083 ip6_address_t * addr1, u32 * src_adj_index0,
1084 u32 * src_adj_index1)
1086 /* if default route not hit in ip6 lookup */
1087 if (PREDICT_TRUE(src_fib_index0 != (u32 ) ~0 && src_fib_index1 != (u32 ) ~0))
1089 src_adj_index0[0] = ip6_src_fib_lookup(lgm, src_fib_index0, addr0);
1090 src_adj_index1[0] = ip6_src_fib_lookup(lgm, src_fib_index1, addr1);
1094 ip6_src_fib_lookup_one (lgm, src_fib_index0, addr0, src_adj_index0);
1095 ip6_src_fib_lookup_one (lgm, src_fib_index1, addr1, src_adj_index1);
1100 lgpe_ip6_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
1101 vlib_frame_t * from_frame)
1103 u32 n_left_from, next_index, * from, * to_next;
1104 lisp_gpe_main_t * lgm = &lisp_gpe_main;
1106 from = vlib_frame_vector_args (from_frame);
1107 n_left_from = from_frame->n_vectors;
1109 next_index = node->cached_next_index;
1111 while (n_left_from > 0)
1115 vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
1117 while (n_left_from >= 4 && n_left_to_next >= 2)
1120 vlib_buffer_t * b0, * b1;
1121 ip6_header_t * ip0, * ip1;
1122 u32 dst_adj_index0, src_adj_index0, src_fib_index0, dst_adj_index1,
1123 src_adj_index1, src_fib_index1;
1124 ip_adjacency_t * dst_adj0, * src_adj0, * dst_adj1, * src_adj1;
1127 next0 = next1 = LGPE_IP6_LOOKUP_NEXT_LISP_CP_LOOKUP;
1129 /* Prefetch next iteration. */
1131 vlib_buffer_t * p2, * p3;
1133 p2 = vlib_get_buffer (vm, from[2]);
1134 p3 = vlib_get_buffer (vm, from[3]);
1136 vlib_prefetch_buffer_header (p2, LOAD);
1137 vlib_prefetch_buffer_header (p3, LOAD);
1139 CLIB_PREFETCH (p2->data, 2*CLIB_CACHE_LINE_BYTES, LOAD);
1140 CLIB_PREFETCH (p3->data, 2*CLIB_CACHE_LINE_BYTES, LOAD);
1149 n_left_to_next -= 2;
1152 b0 = vlib_get_buffer (vm, bi0);
1153 b1 = vlib_get_buffer (vm, bi1);
1155 ip0 = vlib_buffer_get_current (b0);
1156 ip1 = vlib_buffer_get_current (b1);
1158 /* dst lookup was done by ip6 lookup */
1159 dst_adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
1160 dst_adj_index1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
1162 dst_adj0 = ip_get_adjacency (lgm->lm6, dst_adj_index0);
1163 dst_adj1 = ip_get_adjacency (lgm->lm6, dst_adj_index1);
1165 src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
1166 src_fib_index1 = dst_adj1->rewrite_header.sw_if_index;
1168 ip6_src_fib_lookup_two (lgm, src_fib_index0, src_fib_index1,
1169 &ip0->src_address, &ip1->src_address,
1170 &src_adj_index0, &src_adj_index1);
1172 /* if a source fib exists */
1173 if (PREDICT_TRUE((u32) ~0 != src_adj_index0
1174 && (u32) ~0 != src_adj_index1))
1176 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
1177 vnet_buffer(b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
1179 src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
1180 src_adj1 = ip_get_adjacency (lgm->lm6, src_adj_index1);
1182 next0 = src_adj0->explicit_fib_index;
1183 next1 = src_adj1->explicit_fib_index;
1185 /* prepare buffer for lisp-gpe output node */
1186 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1187 src_adj0->rewrite_header.sw_if_index;
1188 vnet_buffer (b1)->sw_if_index[VLIB_TX] =
1189 src_adj1->rewrite_header.sw_if_index;
1191 /* if multipath: saved_lookup_next_index is reused to store
1192 * nb of sub-tunnels. If greater than 1, multipath is on.
1193 * Note that flow hash should be 0 after ipx lookup! */
1194 if (PREDICT_TRUE(src_adj0->saved_lookup_next_index > 1))
1195 vnet_buffer (b0)->ip.flow_hash = ip6_compute_flow_hash (
1196 ip0, IP_FLOW_HASH_DEFAULT);
1198 if (PREDICT_TRUE(src_adj1->saved_lookup_next_index > 1))
1199 vnet_buffer (b1)->ip.flow_hash = ip6_compute_flow_hash (
1200 ip1, IP_FLOW_HASH_DEFAULT);
1204 if (src_adj_index0 != (u32) ~0)
1206 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
1207 src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
1208 next0 = src_adj0->explicit_fib_index;
1209 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1210 src_adj0->rewrite_header.sw_if_index;
1212 if (PREDICT_TRUE(src_adj0->saved_lookup_next_index > 1))
1213 vnet_buffer (b0)->ip.flow_hash = ip6_compute_flow_hash (
1214 ip0, IP_FLOW_HASH_DEFAULT);
1218 next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
1221 if (src_adj_index1 != (u32) ~0)
1223 vnet_buffer(b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
1224 src_adj1 = ip_get_adjacency (lgm->lm6, src_adj_index1);
1225 next1 = src_adj1->explicit_fib_index;
1226 vnet_buffer (b1)->sw_if_index[VLIB_TX] =
1227 src_adj1->rewrite_header.sw_if_index;
1229 if (PREDICT_TRUE(src_adj1->saved_lookup_next_index > 1))
1230 vnet_buffer (b1)->ip.flow_hash = ip6_compute_flow_hash (
1231 ip1, IP_FLOW_HASH_DEFAULT);
1235 next1 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
1239 /* mark the packets for CP lookup if needed*/
1240 if (PREDICT_FALSE(LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
1241 vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
1242 if (PREDICT_FALSE(LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next1))
1243 vnet_buffer (b1)->lisp.overlay_afi = LISP_AFI_IP;
1245 vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
1246 n_left_to_next, bi0, bi1, next0,
1250 while (n_left_from > 0 && n_left_to_next > 0)
1254 u32 bi0, dst_adj_index0, src_adj_index0, src_fib_index0;
1255 u32 next0 = LGPE_IP6_LOOKUP_NEXT_LISP_CP_LOOKUP;
1256 ip_adjacency_t * dst_adj0, * src_adj0;
1263 n_left_to_next -= 1;
1265 b0 = vlib_get_buffer (vm, bi0);
1266 ip0 = vlib_buffer_get_current (b0);
1268 /* dst lookup was done by ip6 lookup */
1269 dst_adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
1270 dst_adj0 = ip_get_adjacency (lgm->lm6, dst_adj_index0);
1271 src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
1274 ip6_src_fib_lookup_one (lgm, src_fib_index0, &ip0->src_address,
1277 /* if a source fib exists */
1278 if (PREDICT_TRUE(src_adj_index0 != (u32 ) ~0))
1280 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
1281 src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
1282 next0 = src_adj0->explicit_fib_index;
1284 /* prepare packet for lisp-gpe output node */
1285 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1286 src_adj0->rewrite_header.sw_if_index;
1288 /* if multipath: saved_lookup_next_index is reused to store
1289 * nb of sub-tunnels. If greater than 1, multipath is on */
1290 if (PREDICT_TRUE(src_adj0->saved_lookup_next_index > 1))
1291 vnet_buffer (b0)->ip.flow_hash = ip6_compute_flow_hash (
1292 ip0, IP_FLOW_HASH_DEFAULT);
1296 next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
1299 /* mark the packets for CP lookup if needed*/
1300 if (PREDICT_FALSE(LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
1301 vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
1303 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
1304 n_left_to_next, bi0, next0);
1306 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1308 return from_frame->n_vectors;
1311 VLIB_REGISTER_NODE (lgpe_ip6_lookup_node) = {
1312 .function = lgpe_ip6_lookup,
1313 .name = "lgpe-ip6-lookup",
1314 .vector_size = sizeof (u32),
1316 .type = VLIB_NODE_TYPE_INTERNAL,
1318 .n_next_nodes = LGPE_IP6_LOOKUP_N_NEXT,
1320 #define _(sym,str) [LGPE_IP6_LOOKUP_NEXT_##sym] = str,
1321 foreach_lgpe_ip6_lookup_next