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 <vlib/vlib.h>
17 #include <vnet/dpo/drop_dpo.h>
19 #include <vnet/fib/fib_table.h>
20 #include <vnet/fib/fib_entry_cover.h>
21 #include <vnet/fib/fib_internal.h>
22 #include <vnet/fib/ip4_fib.h>
23 #include <vnet/fib/ip6_fib.h>
24 #include <vnet/fib/mpls_fib.h>
27 fib_table_get (fib_node_index_t index,
32 case FIB_PROTOCOL_IP4:
33 return (pool_elt_at_index(ip4_main.fibs, index));
34 case FIB_PROTOCOL_IP6:
35 return (pool_elt_at_index(ip6_main.fibs, index));
36 case FIB_PROTOCOL_MPLS:
37 return (pool_elt_at_index(mpls_main.fibs, index));
43 static inline fib_node_index_t
44 fib_table_lookup_i (fib_table_t *fib_table,
45 const fib_prefix_t *prefix)
47 switch (prefix->fp_proto)
49 case FIB_PROTOCOL_IP4:
50 return (ip4_fib_table_lookup(ip4_fib_get(fib_table->ft_index),
53 case FIB_PROTOCOL_IP6:
54 return (ip6_fib_table_lookup(fib_table->ft_index,
57 case FIB_PROTOCOL_MPLS:
58 return (mpls_fib_table_lookup(mpls_fib_get(fib_table->ft_index),
62 return (FIB_NODE_INDEX_INVALID);
66 fib_table_lookup (u32 fib_index,
67 const fib_prefix_t *prefix)
69 return (fib_table_lookup_i(fib_table_get(fib_index, prefix->fp_proto), prefix));
72 static inline fib_node_index_t
73 fib_table_lookup_exact_match_i (const fib_table_t *fib_table,
74 const fib_prefix_t *prefix)
76 switch (prefix->fp_proto)
78 case FIB_PROTOCOL_IP4:
79 return (ip4_fib_table_lookup_exact_match(ip4_fib_get(fib_table->ft_index),
82 case FIB_PROTOCOL_IP6:
83 return (ip6_fib_table_lookup_exact_match(fib_table->ft_index,
86 case FIB_PROTOCOL_MPLS:
87 return (mpls_fib_table_lookup(mpls_fib_get(fib_table->ft_index),
91 return (FIB_NODE_INDEX_INVALID);
95 fib_table_lookup_exact_match (u32 fib_index,
96 const fib_prefix_t *prefix)
98 return (fib_table_lookup_exact_match_i(fib_table_get(fib_index,
103 static fib_node_index_t
104 fib_table_get_less_specific_i (fib_table_t *fib_table,
105 const fib_prefix_t *prefix)
111 if (FIB_PROTOCOL_MPLS == pfx.fp_proto)
113 return (FIB_NODE_INDEX_INVALID);
117 * in the absence of a tree structure for the table that allows for an O(1)
118 * parent get, a cheeky way to find the cover is to LPM for the prefix with
120 * there should always be a cover, though it may be the default route. the
121 * default route's cover is the default route.
123 if (pfx.fp_len != 0) {
127 return (fib_table_lookup_i(fib_table, &pfx));
131 fib_table_get_less_specific (u32 fib_index,
132 const fib_prefix_t *prefix)
134 return (fib_table_get_less_specific_i(fib_table_get(fib_index,
140 fib_table_entry_remove (fib_table_t *fib_table,
141 const fib_prefix_t *prefix,
142 fib_node_index_t fib_entry_index)
144 vlib_smp_unsafe_warning();
146 fib_table->ft_total_route_counts--;
148 switch (prefix->fp_proto)
150 case FIB_PROTOCOL_IP4:
151 ip4_fib_table_entry_remove(ip4_fib_get(fib_table->ft_index),
152 &prefix->fp_addr.ip4,
155 case FIB_PROTOCOL_IP6:
156 ip6_fib_table_entry_remove(fib_table->ft_index,
157 &prefix->fp_addr.ip6,
160 case FIB_PROTOCOL_MPLS:
161 mpls_fib_table_entry_remove(mpls_fib_get(fib_table->ft_index),
167 fib_entry_unlock(fib_entry_index);
171 fib_table_post_insert_actions (fib_table_t *fib_table,
172 const fib_prefix_t *prefix,
173 fib_node_index_t fib_entry_index)
175 fib_node_index_t fib_entry_cover_index;
178 * no cover relationships in the MPLS FIB
180 if (FIB_PROTOCOL_MPLS == prefix->fp_proto)
184 * find and inform the covering entry that a new more specific
185 * has been inserted beneath it
187 fib_entry_cover_index = fib_table_get_less_specific_i(fib_table, prefix);
189 * the indicies are the same when the default route is first added
191 if (fib_entry_cover_index != fib_entry_index)
193 fib_entry_cover_change_notify(fib_entry_cover_index,
199 fib_table_entry_insert (fib_table_t *fib_table,
200 const fib_prefix_t *prefix,
201 fib_node_index_t fib_entry_index)
203 vlib_smp_unsafe_warning();
205 fib_entry_lock(fib_entry_index);
206 fib_table->ft_total_route_counts++;
208 switch (prefix->fp_proto)
210 case FIB_PROTOCOL_IP4:
211 ip4_fib_table_entry_insert(ip4_fib_get(fib_table->ft_index),
212 &prefix->fp_addr.ip4,
216 case FIB_PROTOCOL_IP6:
217 ip6_fib_table_entry_insert(fib_table->ft_index,
218 &prefix->fp_addr.ip6,
222 case FIB_PROTOCOL_MPLS:
223 mpls_fib_table_entry_insert(mpls_fib_get(fib_table->ft_index),
230 fib_table_post_insert_actions(fib_table, prefix, fib_entry_index);
234 fib_table_fwding_dpo_update (u32 fib_index,
235 const fib_prefix_t *prefix,
238 vlib_smp_unsafe_warning();
240 switch (prefix->fp_proto)
242 case FIB_PROTOCOL_IP4:
243 return (ip4_fib_table_fwding_dpo_update(ip4_fib_get(fib_index),
244 &prefix->fp_addr.ip4,
247 case FIB_PROTOCOL_IP6:
248 return (ip6_fib_table_fwding_dpo_update(fib_index,
249 &prefix->fp_addr.ip6,
252 case FIB_PROTOCOL_MPLS:
253 return (mpls_fib_forwarding_table_update(mpls_fib_get(fib_index),
261 fib_table_fwding_dpo_remove (u32 fib_index,
262 const fib_prefix_t *prefix,
265 vlib_smp_unsafe_warning();
267 switch (prefix->fp_proto)
269 case FIB_PROTOCOL_IP4:
270 return (ip4_fib_table_fwding_dpo_remove(ip4_fib_get(fib_index),
271 &prefix->fp_addr.ip4,
274 fib_table_get_less_specific(fib_index,
276 case FIB_PROTOCOL_IP6:
277 return (ip6_fib_table_fwding_dpo_remove(fib_index,
278 &prefix->fp_addr.ip6,
281 case FIB_PROTOCOL_MPLS:
282 return (mpls_fib_forwarding_table_reset(mpls_fib_get(fib_index),
290 fib_table_entry_special_dpo_add (u32 fib_index,
291 const fib_prefix_t *prefix,
293 fib_entry_flag_t flags,
296 fib_node_index_t fib_entry_index;
297 fib_table_t *fib_table;
299 fib_table = fib_table_get(fib_index, prefix->fp_proto);
300 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
302 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
304 fib_entry_index = fib_entry_create_special(fib_index, prefix,
308 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
309 fib_table->ft_src_route_counts[source]++;
315 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
316 fib_entry_special_add(fib_entry_index, source, flags, dpo);
318 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
320 fib_table->ft_src_route_counts[source]++;
325 return (fib_entry_index);
329 fib_table_entry_special_dpo_update (u32 fib_index,
330 const fib_prefix_t *prefix,
332 fib_entry_flag_t flags,
335 fib_node_index_t fib_entry_index;
336 fib_table_t *fib_table;
338 fib_table = fib_table_get(fib_index, prefix->fp_proto);
339 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
341 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
343 fib_entry_index = fib_entry_create_special(fib_index, prefix,
347 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
348 fib_table->ft_src_route_counts[source]++;
354 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
357 fib_entry_special_update(fib_entry_index, source, flags, dpo);
359 fib_entry_special_add(fib_entry_index, source, flags, dpo);
361 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
363 fib_table->ft_src_route_counts[source]++;
367 return (fib_entry_index);
371 fib_table_entry_special_add (u32 fib_index,
372 const fib_prefix_t *prefix,
374 fib_entry_flag_t flags)
376 fib_node_index_t fib_entry_index;
377 dpo_id_t tmp_dpo = DPO_INVALID;
379 dpo_copy(&tmp_dpo, drop_dpo_get(fib_proto_to_dpo(prefix->fp_proto)));
381 fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix, source,
384 dpo_unlock(&tmp_dpo);
386 return (fib_entry_index);
390 fib_table_entry_special_remove (u32 fib_index,
391 const fib_prefix_t *prefix,
396 * yes => remove source
397 * 2 - is it still sourced?
400 fib_node_index_t fib_entry_index;
401 fib_table_t *fib_table;
403 fib_table = fib_table_get(fib_index, prefix->fp_proto);
404 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
406 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
409 * removing an etry that does not exist. i'll allow it.
414 fib_entry_src_flag_t src_flag;
418 * don't nobody go nowhere
420 fib_entry_lock(fib_entry_index);
421 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
423 src_flag = fib_entry_special_remove(fib_entry_index, source);
425 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
428 * last source gone. remove from the table
430 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
433 * now the entry is no longer in the table, we can
434 * inform the entries that it covers to re-calculate their cover
436 fib_entry_cover_change_notify(fib_entry_index,
437 FIB_NODE_INDEX_INVALID);
441 * still has sources, leave it be.
443 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
445 fib_table->ft_src_route_counts[source]--;
448 fib_entry_unlock(fib_entry_index);
453 * fib_table_route_path_fixup
455 * Convert attached hosts to attached next-hops.
457 * This special case is required because an attached path will link to a
458 * glean, and the FIB entry will have the interface or API/CLI source. When
459 * the ARP/ND process is completes then that source (which will provide a
460 * complete adjacency) will be lower priority and so the FIB entry will
461 * remain linked to a glean and traffic will never reach the hosts. For
462 * an ATTAHCED_HOST path we can link the path directly to the [incomplete]
466 fib_table_route_path_fixup (const fib_prefix_t *prefix,
467 fib_entry_flag_t eflags,
468 fib_route_path_t *path)
471 * not all zeros next hop &&
472 * is recursive path &&
473 * nexthop is same as the route's address
475 if ((!ip46_address_is_zero(&path->frp_addr)) &&
476 (~0 == path->frp_sw_if_index) &&
477 (0 == ip46_address_cmp(&path->frp_addr, &prefix->fp_addr)))
479 /* Prefix recurses via itse;f */
480 path->frp_flags |= FIB_ROUTE_PATH_DROP;
482 if (fib_prefix_is_host(prefix) &&
483 ip46_address_is_zero(&path->frp_addr) &&
484 path->frp_sw_if_index != ~0 &&
485 path->frp_proto != DPO_PROTO_ETHERNET)
487 path->frp_addr = prefix->fp_addr;
488 path->frp_flags |= FIB_ROUTE_PATH_ATTACHED;
490 if (eflags & FIB_ENTRY_FLAG_DROP)
492 path->frp_flags |= FIB_ROUTE_PATH_DROP;
494 if (eflags & FIB_ENTRY_FLAG_LOCAL)
496 path->frp_flags |= FIB_ROUTE_PATH_LOCAL;
498 if (eflags & FIB_ENTRY_FLAG_EXCLUSIVE)
500 path->frp_flags |= FIB_ROUTE_PATH_EXCLUSIVE;
505 fib_table_entry_path_add (u32 fib_index,
506 const fib_prefix_t *prefix,
508 fib_entry_flag_t flags,
509 dpo_proto_t next_hop_proto,
510 const ip46_address_t *next_hop,
511 u32 next_hop_sw_if_index,
512 u32 next_hop_fib_index,
514 mpls_label_t *next_hop_labels,
515 fib_route_path_flags_t path_flags)
517 fib_route_path_t path = {
518 .frp_proto = next_hop_proto,
519 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
520 .frp_sw_if_index = next_hop_sw_if_index,
521 .frp_fib_index = next_hop_fib_index,
522 .frp_weight = next_hop_weight,
523 .frp_flags = path_flags,
524 .frp_label_stack = next_hop_labels,
526 fib_node_index_t fib_entry_index;
527 fib_route_path_t *paths = NULL;
529 vec_add1(paths, path);
531 fib_entry_index = fib_table_entry_path_add2(fib_index, prefix,
532 source, flags, paths);
535 return (fib_entry_index);
539 fib_table_entry_path_add2 (u32 fib_index,
540 const fib_prefix_t *prefix,
542 fib_entry_flag_t flags,
543 fib_route_path_t *rpath)
545 fib_node_index_t fib_entry_index;
546 fib_table_t *fib_table;
549 fib_table = fib_table_get(fib_index, prefix->fp_proto);
550 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
552 for (ii = 0; ii < vec_len(rpath); ii++)
554 fib_table_route_path_fixup(prefix, flags, &rpath[ii]);
557 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
559 fib_entry_index = fib_entry_create(fib_index, prefix,
563 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
564 fib_table->ft_src_route_counts[source]++;
570 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
571 fib_entry_path_add(fib_entry_index, source, flags, rpath);;
573 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
575 fib_table->ft_src_route_counts[source]++;
579 return (fib_entry_index);
583 fib_table_entry_path_remove2 (u32 fib_index,
584 const fib_prefix_t *prefix,
586 fib_route_path_t *rpath)
590 * yes => remove source
591 * 2 - is it still sourced?
594 fib_node_index_t fib_entry_index;
595 fib_table_t *fib_table;
598 fib_table = fib_table_get(fib_index, prefix->fp_proto);
599 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
601 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
604 * removing an etry that does not exist. i'll allow it.
609 fib_entry_src_flag_t src_flag;
613 * if it's not sourced, then there's nowt to remove
615 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
622 * don't nobody go nowhere
624 fib_entry_lock(fib_entry_index);
626 for (ii = 0; ii < vec_len(rpath); ii++)
628 fib_table_route_path_fixup(
630 fib_entry_get_flags_for_source(fib_entry_index,
635 src_flag = fib_entry_path_remove(fib_entry_index, source, rpath);
637 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
640 * last source gone. remove from the table
642 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
645 * now the entry is no longer in the table, we can
646 * inform the entries that it covers to re-calculate their cover
648 fib_entry_cover_change_notify(fib_entry_index,
649 FIB_NODE_INDEX_INVALID);
653 * still has sources, leave it be.
655 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
657 fib_table->ft_src_route_counts[source]--;
660 fib_entry_unlock(fib_entry_index);
665 fib_table_entry_path_remove (u32 fib_index,
666 const fib_prefix_t *prefix,
668 dpo_proto_t next_hop_proto,
669 const ip46_address_t *next_hop,
670 u32 next_hop_sw_if_index,
671 u32 next_hop_fib_index,
673 fib_route_path_flags_t path_flags)
677 * yes => remove source
678 * 2 - is it still sourced?
681 fib_route_path_t path = {
682 .frp_proto = next_hop_proto,
683 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
684 .frp_sw_if_index = next_hop_sw_if_index,
685 .frp_fib_index = next_hop_fib_index,
686 .frp_weight = next_hop_weight,
687 .frp_flags = path_flags,
689 fib_route_path_t *paths = NULL;
691 vec_add1(paths, path);
693 fib_table_entry_path_remove2(fib_index, prefix, source, paths);
699 fib_route_path_cmp_for_sort (void * v1,
702 return (fib_route_path_cmp(v1, v2));
706 fib_table_entry_update (u32 fib_index,
707 const fib_prefix_t *prefix,
709 fib_entry_flag_t flags,
710 fib_route_path_t *paths)
712 fib_node_index_t fib_entry_index;
713 fib_table_t *fib_table;
716 fib_table = fib_table_get(fib_index, prefix->fp_proto);
717 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
719 for (ii = 0; ii < vec_len(paths); ii++)
721 fib_table_route_path_fixup(prefix, flags, &paths[ii]);
724 * sort the paths provided by the control plane. this means
725 * the paths and the extension on the entry will be sorted.
727 vec_sort_with_function(paths, fib_route_path_cmp_for_sort);
729 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
731 fib_entry_index = fib_entry_create(fib_index, prefix,
735 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
736 fib_table->ft_src_route_counts[source]++;
742 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
743 fib_entry_update(fib_entry_index, source, flags, paths);
745 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
747 fib_table->ft_src_route_counts[source]++;
751 return (fib_entry_index);
755 fib_table_entry_update_one_path (u32 fib_index,
756 const fib_prefix_t *prefix,
758 fib_entry_flag_t flags,
759 dpo_proto_t next_hop_proto,
760 const ip46_address_t *next_hop,
761 u32 next_hop_sw_if_index,
762 u32 next_hop_fib_index,
764 mpls_label_t *next_hop_labels,
765 fib_route_path_flags_t path_flags)
767 fib_node_index_t fib_entry_index;
768 fib_route_path_t path = {
769 .frp_proto = next_hop_proto,
770 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
771 .frp_sw_if_index = next_hop_sw_if_index,
772 .frp_fib_index = next_hop_fib_index,
773 .frp_weight = next_hop_weight,
774 .frp_flags = path_flags,
775 .frp_label_stack = next_hop_labels,
777 fib_route_path_t *paths = NULL;
779 vec_add1(paths, path);
782 fib_table_entry_update(fib_index, prefix, source, flags, paths);
786 return (fib_entry_index);
790 fib_table_entry_delete_i (u32 fib_index,
791 fib_node_index_t fib_entry_index,
792 const fib_prefix_t *prefix,
795 fib_entry_src_flag_t src_flag;
796 fib_table_t *fib_table;
799 fib_table = fib_table_get(fib_index, prefix->fp_proto);
800 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
803 * don't nobody go nowhere
805 fib_entry_lock(fib_entry_index);
807 src_flag = fib_entry_delete(fib_entry_index, source);
809 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
812 * last source gone. remove from the table
814 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
817 * now the entry is no longer in the table, we can
818 * inform the entries that it covers to re-calculate their cover
820 fib_entry_cover_change_notify(fib_entry_index,
821 FIB_NODE_INDEX_INVALID);
825 * still has sources, leave it be.
827 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
829 fib_table->ft_src_route_counts[source]--;
832 fib_entry_unlock(fib_entry_index);
836 fib_table_entry_delete (u32 fib_index,
837 const fib_prefix_t *prefix,
840 fib_node_index_t fib_entry_index;
842 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
844 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
847 * removing an etry that does not exist.
848 * i'll allow it, but i won't like it.
851 clib_warning("%U not in FIB", format_fib_prefix, prefix);
855 fib_table_entry_delete_i(fib_index, fib_entry_index, prefix, source);
860 fib_table_entry_delete_index (fib_node_index_t fib_entry_index,
865 fib_entry_get_prefix(fib_entry_index, &prefix);
867 fib_table_entry_delete_i(fib_entry_get_fib_index(fib_entry_index),
868 fib_entry_index, &prefix, source);
872 fib_table_entry_local_label_add (u32 fib_index,
873 const fib_prefix_t *prefix,
876 fib_node_index_t fib_entry_index;
878 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
880 if (FIB_NODE_INDEX_INVALID == fib_entry_index ||
881 !fib_entry_is_sourced(fib_entry_index, FIB_SOURCE_MPLS))
884 * only source the prefix once. this allows the label change
887 fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix,
893 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &label);
895 return (fib_entry_index);
899 fib_table_entry_local_label_remove (u32 fib_index,
900 const fib_prefix_t *prefix,
903 fib_node_index_t fib_entry_index;
907 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
909 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
912 data = fib_entry_get_source_data(fib_entry_index, FIB_SOURCE_MPLS);
917 pl = *(mpls_label_t*)data;
922 pl = MPLS_LABEL_INVALID;
924 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &pl);
925 fib_table_entry_special_remove(fib_index,
931 fib_table_get_index_for_sw_if_index (fib_protocol_t proto,
936 case FIB_PROTOCOL_IP4:
937 return (ip4_fib_table_get_index_for_sw_if_index(sw_if_index));
938 case FIB_PROTOCOL_IP6:
939 return (ip6_fib_table_get_index_for_sw_if_index(sw_if_index));
940 case FIB_PROTOCOL_MPLS:
941 return (mpls_fib_table_get_index_for_sw_if_index(sw_if_index));
947 fib_table_get_flow_hash_config (u32 fib_index,
948 fib_protocol_t proto)
952 fib = fib_table_get(fib_index, proto);
954 return (fib->ft_flow_hash_config);
957 fib_table_get_default_flow_hash_config (fib_protocol_t proto)
961 case FIB_PROTOCOL_IP4:
962 case FIB_PROTOCOL_IP6:
963 return (IP_FLOW_HASH_DEFAULT);
965 case FIB_PROTOCOL_MPLS:
966 return (MPLS_FLOW_HASH_DEFAULT);
970 return (IP_FLOW_HASH_DEFAULT);
974 * @brief Table set flow hash config context.
976 typedef struct fib_table_set_flow_hash_config_ctx_t_
979 * the flow hash config to set
981 flow_hash_config_t hash_config;
982 } fib_table_set_flow_hash_config_ctx_t;
985 fib_table_set_flow_hash_config_cb (fib_node_index_t fib_entry_index,
988 fib_table_set_flow_hash_config_ctx_t *ctx = arg;
990 fib_entry_set_flow_hash_config(fib_entry_index, ctx->hash_config);
996 fib_table_set_flow_hash_config (u32 fib_index,
997 fib_protocol_t proto,
998 flow_hash_config_t hash_config)
1000 fib_table_set_flow_hash_config_ctx_t ctx = {
1001 .hash_config = hash_config,
1005 fib = fib_table_get(fib_index, proto);
1006 fib->ft_flow_hash_config = hash_config;
1008 fib_table_walk(fib_index, proto,
1009 fib_table_set_flow_hash_config_cb,
1014 fib_table_get_table_id_for_sw_if_index (fib_protocol_t proto,
1017 fib_table_t *fib_table;
1019 fib_table = fib_table_get(fib_table_get_index_for_sw_if_index(
1020 proto, sw_if_index),
1023 return ((NULL != fib_table ? fib_table->ft_table_id : ~0));
1027 fib_table_find (fib_protocol_t proto,
1032 case FIB_PROTOCOL_IP4:
1033 return (ip4_fib_index_from_table_id(table_id));
1034 case FIB_PROTOCOL_IP6:
1035 return (ip6_fib_index_from_table_id(table_id));
1036 case FIB_PROTOCOL_MPLS:
1037 return (mpls_fib_index_from_table_id(table_id));
1043 fib_table_find_or_create_and_lock_i (fib_protocol_t proto,
1048 fib_table_t *fib_table;
1049 fib_node_index_t fi;
1053 case FIB_PROTOCOL_IP4:
1054 fi = ip4_fib_table_find_or_create_and_lock(table_id, src);
1056 case FIB_PROTOCOL_IP6:
1057 fi = ip6_fib_table_find_or_create_and_lock(table_id, src);
1059 case FIB_PROTOCOL_MPLS:
1060 fi = mpls_fib_table_find_or_create_and_lock(table_id, src);
1066 fib_table = fib_table_get(fi, proto);
1068 if (NULL == fib_table->ft_desc)
1070 if (name && name[0])
1072 fib_table->ft_desc = format(NULL, "%s", name);
1076 fib_table->ft_desc = format(NULL, "%U-VRF:%d",
1077 format_fib_protocol, proto,
1086 fib_table_find_or_create_and_lock (fib_protocol_t proto,
1090 return (fib_table_find_or_create_and_lock_i(proto, table_id,
1095 fib_table_find_or_create_and_lock_w_name (fib_protocol_t proto,
1100 return (fib_table_find_or_create_and_lock_i(proto, table_id,
1105 fib_table_create_and_lock (fib_protocol_t proto,
1107 const char *const fmt,
1110 fib_table_t *fib_table;
1111 fib_node_index_t fi;
1118 case FIB_PROTOCOL_IP4:
1119 fi = ip4_fib_table_create_and_lock(src);
1121 case FIB_PROTOCOL_IP6:
1122 fi = ip6_fib_table_create_and_lock(src);
1124 case FIB_PROTOCOL_MPLS:
1125 fi = mpls_fib_table_create_and_lock(src);
1131 fib_table = fib_table_get(fi, proto);
1133 fib_table->ft_desc = va_format(fib_table->ft_desc, fmt, &ap);
1140 fib_table_destroy (fib_table_t *fib_table)
1142 vec_free(fib_table->ft_desc);
1144 switch (fib_table->ft_proto)
1146 case FIB_PROTOCOL_IP4:
1147 ip4_fib_table_destroy(fib_table->ft_index);
1149 case FIB_PROTOCOL_IP6:
1150 ip6_fib_table_destroy(fib_table->ft_index);
1152 case FIB_PROTOCOL_MPLS:
1153 mpls_fib_table_destroy(fib_table->ft_index);
1159 fib_table_walk (u32 fib_index,
1160 fib_protocol_t proto,
1161 fib_table_walk_fn_t fn,
1166 case FIB_PROTOCOL_IP4:
1167 ip4_fib_table_walk(ip4_fib_get(fib_index), fn, ctx);
1169 case FIB_PROTOCOL_IP6:
1170 ip6_fib_table_walk(fib_index, fn, ctx);
1172 case FIB_PROTOCOL_MPLS:
1173 mpls_fib_table_walk(mpls_fib_get(fib_index), fn, ctx);
1179 fib_table_unlock (u32 fib_index,
1180 fib_protocol_t proto,
1181 fib_source_t source)
1183 fib_table_t *fib_table;
1185 fib_table = fib_table_get(fib_index, proto);
1186 fib_table->ft_locks[source]--;
1187 fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]--;
1189 if (0 == fib_table->ft_locks[source])
1192 * The source no longer needs the table. flush any routes
1193 * from it just in case
1195 fib_table_flush(fib_index, proto, source);
1198 if (0 == fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS])
1201 * no more locak from any source - kill it
1203 fib_table_destroy(fib_table);
1208 fib_table_lock (u32 fib_index,
1209 fib_protocol_t proto,
1210 fib_source_t source)
1212 fib_table_t *fib_table;
1214 fib_table = fib_table_get(fib_index, proto);
1215 fib_table->ft_locks[source]++;
1216 fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]++;
1220 fib_table_get_num_entries (u32 fib_index,
1221 fib_protocol_t proto,
1222 fib_source_t source)
1224 fib_table_t *fib_table;
1226 fib_table = fib_table_get(fib_index, proto);
1228 return (fib_table->ft_src_route_counts[source]);
1232 format_fib_table_name (u8* s, va_list* ap)
1234 fib_node_index_t fib_index = va_arg(*ap, fib_node_index_t);
1235 fib_protocol_t proto = va_arg(*ap, int); // int promotion
1236 fib_table_t *fib_table;
1238 fib_table = fib_table_get(fib_index, proto);
1240 s = format(s, "%v", fib_table->ft_desc);
1246 * @brief Table flush context. Store the indicies of matching FIB entries
1247 * that need to be removed.
1249 typedef struct fib_table_flush_ctx_t_
1252 * The list of entries to flush
1254 fib_node_index_t *ftf_entries;
1257 * The source we are flushing
1259 fib_source_t ftf_source;
1260 } fib_table_flush_ctx_t;
1263 fib_table_flush_cb (fib_node_index_t fib_entry_index,
1266 fib_table_flush_ctx_t *ctx = arg;
1268 if (fib_entry_is_sourced(fib_entry_index, ctx->ftf_source))
1270 vec_add1(ctx->ftf_entries, fib_entry_index);
1277 fib_table_flush (u32 fib_index,
1278 fib_protocol_t proto,
1279 fib_source_t source)
1281 fib_node_index_t *fib_entry_index;
1282 fib_table_flush_ctx_t ctx = {
1283 .ftf_entries = NULL,
1284 .ftf_source = source,
1287 fib_table_walk(fib_index, proto,
1291 vec_foreach(fib_entry_index, ctx.ftf_entries)
1293 fib_table_entry_delete_index(*fib_entry_index, source);
1296 vec_free(ctx.ftf_entries);