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 the covering entry
186 fib_entry_cover_index = fib_table_get_less_specific_i(fib_table, prefix);
188 * the indicies are the same when the default route is first added
190 if (fib_entry_cover_index != fib_entry_index)
193 * push any inherting sources from the cover onto the covered
195 fib_entry_inherit(fib_entry_cover_index,
199 * inform the covering entry that a new more specific
200 * has been inserted beneath it
202 fib_entry_cover_change_notify(fib_entry_cover_index,
208 fib_table_entry_insert (fib_table_t *fib_table,
209 const fib_prefix_t *prefix,
210 fib_node_index_t fib_entry_index)
212 vlib_smp_unsafe_warning();
214 fib_entry_lock(fib_entry_index);
215 fib_table->ft_total_route_counts++;
217 switch (prefix->fp_proto)
219 case FIB_PROTOCOL_IP4:
220 ip4_fib_table_entry_insert(ip4_fib_get(fib_table->ft_index),
221 &prefix->fp_addr.ip4,
225 case FIB_PROTOCOL_IP6:
226 ip6_fib_table_entry_insert(fib_table->ft_index,
227 &prefix->fp_addr.ip6,
231 case FIB_PROTOCOL_MPLS:
232 mpls_fib_table_entry_insert(mpls_fib_get(fib_table->ft_index),
239 fib_table_post_insert_actions(fib_table, prefix, fib_entry_index);
243 fib_table_fwding_dpo_update (u32 fib_index,
244 const fib_prefix_t *prefix,
247 vlib_smp_unsafe_warning();
249 switch (prefix->fp_proto)
251 case FIB_PROTOCOL_IP4:
252 return (ip4_fib_table_fwding_dpo_update(ip4_fib_get(fib_index),
253 &prefix->fp_addr.ip4,
256 case FIB_PROTOCOL_IP6:
257 return (ip6_fib_table_fwding_dpo_update(fib_index,
258 &prefix->fp_addr.ip6,
261 case FIB_PROTOCOL_MPLS:
262 return (mpls_fib_forwarding_table_update(mpls_fib_get(fib_index),
270 fib_table_fwding_dpo_remove (u32 fib_index,
271 const fib_prefix_t *prefix,
274 vlib_smp_unsafe_warning();
276 switch (prefix->fp_proto)
278 case FIB_PROTOCOL_IP4:
279 return (ip4_fib_table_fwding_dpo_remove(ip4_fib_get(fib_index),
280 &prefix->fp_addr.ip4,
283 fib_table_get_less_specific(fib_index,
285 case FIB_PROTOCOL_IP6:
286 return (ip6_fib_table_fwding_dpo_remove(fib_index,
287 &prefix->fp_addr.ip6,
290 case FIB_PROTOCOL_MPLS:
291 return (mpls_fib_forwarding_table_reset(mpls_fib_get(fib_index),
299 fib_table_entry_special_dpo_add (u32 fib_index,
300 const fib_prefix_t *prefix,
302 fib_entry_flag_t flags,
305 fib_node_index_t fib_entry_index;
306 fib_table_t *fib_table;
308 fib_table = fib_table_get(fib_index, prefix->fp_proto);
309 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
311 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
313 fib_entry_index = fib_entry_create_special(fib_index, prefix,
317 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
318 fib_table->ft_src_route_counts[source]++;
324 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
325 fib_entry_special_add(fib_entry_index, source, flags, dpo);
327 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
329 fib_table->ft_src_route_counts[source]++;
334 return (fib_entry_index);
338 fib_table_entry_special_dpo_update (u32 fib_index,
339 const fib_prefix_t *prefix,
341 fib_entry_flag_t flags,
344 fib_node_index_t fib_entry_index;
345 fib_table_t *fib_table;
347 fib_table = fib_table_get(fib_index, prefix->fp_proto);
348 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
350 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
352 fib_entry_index = fib_entry_create_special(fib_index, prefix,
356 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
357 fib_table->ft_src_route_counts[source]++;
363 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
366 fib_entry_special_update(fib_entry_index, source, flags, dpo);
368 fib_entry_special_add(fib_entry_index, source, flags, dpo);
370 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
372 fib_table->ft_src_route_counts[source]++;
376 return (fib_entry_index);
380 fib_table_entry_special_add (u32 fib_index,
381 const fib_prefix_t *prefix,
383 fib_entry_flag_t flags)
385 fib_node_index_t fib_entry_index;
386 dpo_id_t tmp_dpo = DPO_INVALID;
388 dpo_copy(&tmp_dpo, drop_dpo_get(fib_proto_to_dpo(prefix->fp_proto)));
390 fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix, source,
393 dpo_unlock(&tmp_dpo);
395 return (fib_entry_index);
399 fib_table_entry_special_remove (u32 fib_index,
400 const fib_prefix_t *prefix,
405 * yes => remove source
406 * 2 - is it still sourced?
409 fib_node_index_t fib_entry_index;
410 fib_table_t *fib_table;
412 fib_table = fib_table_get(fib_index, prefix->fp_proto);
413 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
415 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
418 * removing an etry that does not exist. i'll allow it.
423 fib_entry_src_flag_t src_flag;
427 * don't nobody go nowhere
429 fib_entry_lock(fib_entry_index);
430 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
432 src_flag = fib_entry_special_remove(fib_entry_index, source);
434 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
437 * last source gone. remove from the table
439 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
442 * now the entry is no longer in the table, we can
443 * inform the entries that it covers to re-calculate their cover
445 fib_entry_cover_change_notify(fib_entry_index,
446 FIB_NODE_INDEX_INVALID);
450 * still has sources, leave it be.
452 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
454 fib_table->ft_src_route_counts[source]--;
457 fib_entry_unlock(fib_entry_index);
462 * fib_table_route_path_fixup
464 * Convert attached hosts to attached next-hops.
466 * This special case is required because an attached path will link to a
467 * glean, and the FIB entry will have the interface or API/CLI source. When
468 * the ARP/ND process is completes then that source (which will provide a
469 * complete adjacency) will be lower priority and so the FIB entry will
470 * remain linked to a glean and traffic will never reach the hosts. For
471 * an ATTAHCED_HOST path we can link the path directly to the [incomplete]
475 fib_table_route_path_fixup (const fib_prefix_t *prefix,
476 fib_entry_flag_t eflags,
477 fib_route_path_t *path)
480 * not all zeros next hop &&
481 * is recursive path &&
482 * nexthop is same as the route's address
484 if ((!ip46_address_is_zero(&path->frp_addr)) &&
485 (~0 == path->frp_sw_if_index) &&
486 (0 == ip46_address_cmp(&path->frp_addr, &prefix->fp_addr)))
488 /* Prefix recurses via itse;f */
489 path->frp_flags |= FIB_ROUTE_PATH_DROP;
491 if (fib_prefix_is_host(prefix) &&
492 ip46_address_is_zero(&path->frp_addr) &&
493 path->frp_sw_if_index != ~0 &&
494 path->frp_proto != DPO_PROTO_ETHERNET)
496 path->frp_addr = prefix->fp_addr;
497 path->frp_flags |= FIB_ROUTE_PATH_ATTACHED;
499 if (eflags & FIB_ENTRY_FLAG_DROP)
501 path->frp_flags |= FIB_ROUTE_PATH_DROP;
503 if (eflags & FIB_ENTRY_FLAG_LOCAL)
505 path->frp_flags |= FIB_ROUTE_PATH_LOCAL;
507 if (eflags & FIB_ENTRY_FLAG_EXCLUSIVE)
509 path->frp_flags |= FIB_ROUTE_PATH_EXCLUSIVE;
514 fib_table_entry_path_add (u32 fib_index,
515 const fib_prefix_t *prefix,
517 fib_entry_flag_t flags,
518 dpo_proto_t next_hop_proto,
519 const ip46_address_t *next_hop,
520 u32 next_hop_sw_if_index,
521 u32 next_hop_fib_index,
523 mpls_label_t *next_hop_labels,
524 fib_route_path_flags_t path_flags)
526 fib_route_path_t path = {
527 .frp_proto = next_hop_proto,
528 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
529 .frp_sw_if_index = next_hop_sw_if_index,
530 .frp_fib_index = next_hop_fib_index,
531 .frp_weight = next_hop_weight,
532 .frp_flags = path_flags,
533 .frp_label_stack = next_hop_labels,
535 fib_node_index_t fib_entry_index;
536 fib_route_path_t *paths = NULL;
538 vec_add1(paths, path);
540 fib_entry_index = fib_table_entry_path_add2(fib_index, prefix,
541 source, flags, paths);
544 return (fib_entry_index);
548 fib_table_entry_path_add2 (u32 fib_index,
549 const fib_prefix_t *prefix,
551 fib_entry_flag_t flags,
552 fib_route_path_t *rpath)
554 fib_node_index_t fib_entry_index;
555 fib_table_t *fib_table;
558 fib_table = fib_table_get(fib_index, prefix->fp_proto);
559 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
561 for (ii = 0; ii < vec_len(rpath); ii++)
563 fib_table_route_path_fixup(prefix, flags, &rpath[ii]);
566 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
568 fib_entry_index = fib_entry_create(fib_index, prefix,
572 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
573 fib_table->ft_src_route_counts[source]++;
579 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
580 fib_entry_path_add(fib_entry_index, source, flags, rpath);;
582 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
584 fib_table->ft_src_route_counts[source]++;
588 return (fib_entry_index);
592 fib_table_entry_path_remove2 (u32 fib_index,
593 const fib_prefix_t *prefix,
595 fib_route_path_t *rpath)
599 * yes => remove source
600 * 2 - is it still sourced?
603 fib_node_index_t fib_entry_index;
604 fib_table_t *fib_table;
607 fib_table = fib_table_get(fib_index, prefix->fp_proto);
608 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
610 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
613 * removing an etry that does not exist. i'll allow it.
618 fib_entry_src_flag_t src_flag;
622 * if it's not sourced, then there's nowt to remove
624 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
631 * don't nobody go nowhere
633 fib_entry_lock(fib_entry_index);
635 for (ii = 0; ii < vec_len(rpath); ii++)
637 fib_table_route_path_fixup(
639 fib_entry_get_flags_for_source(fib_entry_index,
644 src_flag = fib_entry_path_remove(fib_entry_index, source, rpath);
646 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
649 * last source gone. remove from the table
651 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
654 * now the entry is no longer in the table, we can
655 * inform the entries that it covers to re-calculate their cover
657 fib_entry_cover_change_notify(fib_entry_index,
658 FIB_NODE_INDEX_INVALID);
662 * still has sources, leave it be.
664 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
666 fib_table->ft_src_route_counts[source]--;
669 fib_entry_unlock(fib_entry_index);
674 fib_table_entry_path_remove (u32 fib_index,
675 const fib_prefix_t *prefix,
677 dpo_proto_t next_hop_proto,
678 const ip46_address_t *next_hop,
679 u32 next_hop_sw_if_index,
680 u32 next_hop_fib_index,
682 fib_route_path_flags_t path_flags)
686 * yes => remove source
687 * 2 - is it still sourced?
690 fib_route_path_t path = {
691 .frp_proto = next_hop_proto,
692 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
693 .frp_sw_if_index = next_hop_sw_if_index,
694 .frp_fib_index = next_hop_fib_index,
695 .frp_weight = next_hop_weight,
696 .frp_flags = path_flags,
698 fib_route_path_t *paths = NULL;
700 vec_add1(paths, path);
702 fib_table_entry_path_remove2(fib_index, prefix, source, paths);
708 fib_route_path_cmp_for_sort (void * v1,
711 return (fib_route_path_cmp(v1, v2));
715 fib_table_entry_update (u32 fib_index,
716 const fib_prefix_t *prefix,
718 fib_entry_flag_t flags,
719 fib_route_path_t *paths)
721 fib_node_index_t fib_entry_index;
722 fib_table_t *fib_table;
725 fib_table = fib_table_get(fib_index, prefix->fp_proto);
726 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
728 for (ii = 0; ii < vec_len(paths); ii++)
730 fib_table_route_path_fixup(prefix, flags, &paths[ii]);
733 * sort the paths provided by the control plane. this means
734 * the paths and the extension on the entry will be sorted.
736 vec_sort_with_function(paths, fib_route_path_cmp_for_sort);
738 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
740 fib_entry_index = fib_entry_create(fib_index, prefix,
744 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
745 fib_table->ft_src_route_counts[source]++;
751 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
752 fib_entry_update(fib_entry_index, source, flags, paths);
754 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
756 fib_table->ft_src_route_counts[source]++;
760 return (fib_entry_index);
764 fib_table_entry_update_one_path (u32 fib_index,
765 const fib_prefix_t *prefix,
767 fib_entry_flag_t flags,
768 dpo_proto_t next_hop_proto,
769 const ip46_address_t *next_hop,
770 u32 next_hop_sw_if_index,
771 u32 next_hop_fib_index,
773 mpls_label_t *next_hop_labels,
774 fib_route_path_flags_t path_flags)
776 fib_node_index_t fib_entry_index;
777 fib_route_path_t path = {
778 .frp_proto = next_hop_proto,
779 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
780 .frp_sw_if_index = next_hop_sw_if_index,
781 .frp_fib_index = next_hop_fib_index,
782 .frp_weight = next_hop_weight,
783 .frp_flags = path_flags,
784 .frp_label_stack = next_hop_labels,
786 fib_route_path_t *paths = NULL;
788 vec_add1(paths, path);
791 fib_table_entry_update(fib_index, prefix, source, flags, paths);
795 return (fib_entry_index);
799 fib_table_entry_delete_i (u32 fib_index,
800 fib_node_index_t fib_entry_index,
801 const fib_prefix_t *prefix,
804 fib_entry_src_flag_t src_flag;
805 fib_table_t *fib_table;
808 fib_table = fib_table_get(fib_index, prefix->fp_proto);
809 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
812 * don't nobody go nowhere
814 fib_entry_lock(fib_entry_index);
816 src_flag = fib_entry_delete(fib_entry_index, source);
818 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
821 * last source gone. remove from the table
823 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
826 * now the entry is no longer in the table, we can
827 * inform the entries that it covers to re-calculate their cover
829 fib_entry_cover_change_notify(fib_entry_index,
830 FIB_NODE_INDEX_INVALID);
834 * still has sources, leave it be.
836 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
838 fib_table->ft_src_route_counts[source]--;
841 fib_entry_unlock(fib_entry_index);
845 fib_table_entry_delete (u32 fib_index,
846 const fib_prefix_t *prefix,
849 fib_node_index_t fib_entry_index;
851 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
853 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
856 * removing an etry that does not exist.
857 * i'll allow it, but i won't like it.
860 clib_warning("%U not in FIB", format_fib_prefix, prefix);
864 fib_table_entry_delete_i(fib_index, fib_entry_index, prefix, source);
869 fib_table_entry_delete_index (fib_node_index_t fib_entry_index,
874 fib_entry_get_prefix(fib_entry_index, &prefix);
876 fib_table_entry_delete_i(fib_entry_get_fib_index(fib_entry_index),
877 fib_entry_index, &prefix, source);
881 fib_table_entry_local_label_add (u32 fib_index,
882 const fib_prefix_t *prefix,
885 fib_node_index_t fib_entry_index;
887 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
889 if (FIB_NODE_INDEX_INVALID == fib_entry_index ||
890 !fib_entry_is_sourced(fib_entry_index, FIB_SOURCE_MPLS))
893 * only source the prefix once. this allows the label change
896 fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix,
902 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &label);
904 return (fib_entry_index);
908 fib_table_entry_local_label_remove (u32 fib_index,
909 const fib_prefix_t *prefix,
912 fib_node_index_t fib_entry_index;
916 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
918 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
921 data = fib_entry_get_source_data(fib_entry_index, FIB_SOURCE_MPLS);
926 pl = *(mpls_label_t*)data;
931 pl = MPLS_LABEL_INVALID;
933 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &pl);
934 fib_table_entry_special_remove(fib_index,
940 fib_table_get_index_for_sw_if_index (fib_protocol_t proto,
945 case FIB_PROTOCOL_IP4:
946 return (ip4_fib_table_get_index_for_sw_if_index(sw_if_index));
947 case FIB_PROTOCOL_IP6:
948 return (ip6_fib_table_get_index_for_sw_if_index(sw_if_index));
949 case FIB_PROTOCOL_MPLS:
950 return (mpls_fib_table_get_index_for_sw_if_index(sw_if_index));
956 fib_table_get_flow_hash_config (u32 fib_index,
957 fib_protocol_t proto)
961 fib = fib_table_get(fib_index, proto);
963 return (fib->ft_flow_hash_config);
967 fib_table_get_default_flow_hash_config (fib_protocol_t proto)
971 case FIB_PROTOCOL_IP4:
972 case FIB_PROTOCOL_IP6:
973 return (IP_FLOW_HASH_DEFAULT);
975 case FIB_PROTOCOL_MPLS:
976 return (MPLS_FLOW_HASH_DEFAULT);
980 return (IP_FLOW_HASH_DEFAULT);
984 * @brief Table set flow hash config context.
986 typedef struct fib_table_set_flow_hash_config_ctx_t_
989 * the flow hash config to set
991 flow_hash_config_t hash_config;
992 } fib_table_set_flow_hash_config_ctx_t;
994 static fib_table_walk_rc_t
995 fib_table_set_flow_hash_config_cb (fib_node_index_t fib_entry_index,
998 fib_table_set_flow_hash_config_ctx_t *ctx = arg;
1000 fib_entry_set_flow_hash_config(fib_entry_index, ctx->hash_config);
1002 return (FIB_TABLE_WALK_CONTINUE);
1006 fib_table_set_flow_hash_config (u32 fib_index,
1007 fib_protocol_t proto,
1008 flow_hash_config_t hash_config)
1010 fib_table_set_flow_hash_config_ctx_t ctx = {
1011 .hash_config = hash_config,
1015 fib = fib_table_get(fib_index, proto);
1016 fib->ft_flow_hash_config = hash_config;
1018 fib_table_walk(fib_index, proto,
1019 fib_table_set_flow_hash_config_cb,
1024 fib_table_get_table_id_for_sw_if_index (fib_protocol_t proto,
1027 fib_table_t *fib_table;
1029 fib_table = fib_table_get(fib_table_get_index_for_sw_if_index(
1030 proto, sw_if_index),
1033 return ((NULL != fib_table ? fib_table->ft_table_id : ~0));
1037 fib_table_find (fib_protocol_t proto,
1042 case FIB_PROTOCOL_IP4:
1043 return (ip4_fib_index_from_table_id(table_id));
1044 case FIB_PROTOCOL_IP6:
1045 return (ip6_fib_index_from_table_id(table_id));
1046 case FIB_PROTOCOL_MPLS:
1047 return (mpls_fib_index_from_table_id(table_id));
1053 fib_table_find_or_create_and_lock_i (fib_protocol_t proto,
1058 fib_table_t *fib_table;
1059 fib_node_index_t fi;
1063 case FIB_PROTOCOL_IP4:
1064 fi = ip4_fib_table_find_or_create_and_lock(table_id, src);
1066 case FIB_PROTOCOL_IP6:
1067 fi = ip6_fib_table_find_or_create_and_lock(table_id, src);
1069 case FIB_PROTOCOL_MPLS:
1070 fi = mpls_fib_table_find_or_create_and_lock(table_id, src);
1076 fib_table = fib_table_get(fi, proto);
1078 if (NULL == fib_table->ft_desc)
1080 if (name && name[0])
1082 fib_table->ft_desc = format(NULL, "%s", name);
1086 fib_table->ft_desc = format(NULL, "%U-VRF:%d",
1087 format_fib_protocol, proto,
1096 fib_table_find_or_create_and_lock (fib_protocol_t proto,
1100 return (fib_table_find_or_create_and_lock_i(proto, table_id,
1105 fib_table_find_or_create_and_lock_w_name (fib_protocol_t proto,
1110 return (fib_table_find_or_create_and_lock_i(proto, table_id,
1115 fib_table_create_and_lock (fib_protocol_t proto,
1117 const char *const fmt,
1120 fib_table_t *fib_table;
1121 fib_node_index_t fi;
1128 case FIB_PROTOCOL_IP4:
1129 fi = ip4_fib_table_create_and_lock(src);
1131 case FIB_PROTOCOL_IP6:
1132 fi = ip6_fib_table_create_and_lock(src);
1134 case FIB_PROTOCOL_MPLS:
1135 fi = mpls_fib_table_create_and_lock(src);
1141 fib_table = fib_table_get(fi, proto);
1143 fib_table->ft_desc = va_format(fib_table->ft_desc, fmt, &ap);
1150 fib_table_destroy (fib_table_t *fib_table)
1152 vec_free(fib_table->ft_desc);
1154 switch (fib_table->ft_proto)
1156 case FIB_PROTOCOL_IP4:
1157 ip4_fib_table_destroy(fib_table->ft_index);
1159 case FIB_PROTOCOL_IP6:
1160 ip6_fib_table_destroy(fib_table->ft_index);
1162 case FIB_PROTOCOL_MPLS:
1163 mpls_fib_table_destroy(fib_table->ft_index);
1169 fib_table_walk (u32 fib_index,
1170 fib_protocol_t proto,
1171 fib_table_walk_fn_t fn,
1176 case FIB_PROTOCOL_IP4:
1177 ip4_fib_table_walk(ip4_fib_get(fib_index), fn, ctx);
1179 case FIB_PROTOCOL_IP6:
1180 ip6_fib_table_walk(fib_index, fn, ctx);
1182 case FIB_PROTOCOL_MPLS:
1183 mpls_fib_table_walk(mpls_fib_get(fib_index), fn, ctx);
1189 fib_table_sub_tree_walk (u32 fib_index,
1190 fib_protocol_t proto,
1191 const fib_prefix_t *root,
1192 fib_table_walk_fn_t fn,
1197 case FIB_PROTOCOL_IP4:
1198 ip4_fib_table_sub_tree_walk(ip4_fib_get(fib_index), root, fn, ctx);
1200 case FIB_PROTOCOL_IP6:
1201 ip6_fib_table_sub_tree_walk(fib_index, root, fn, ctx);
1203 case FIB_PROTOCOL_MPLS:
1209 fib_table_unlock (u32 fib_index,
1210 fib_protocol_t proto,
1211 fib_source_t source)
1213 fib_table_t *fib_table;
1215 fib_table = fib_table_get(fib_index, proto);
1216 fib_table->ft_locks[source]--;
1217 fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]--;
1219 if (0 == fib_table->ft_locks[source])
1222 * The source no longer needs the table. flush any routes
1223 * from it just in case
1225 fib_table_flush(fib_index, proto, source);
1228 if (0 == fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS])
1231 * no more locak from any source - kill it
1233 fib_table_destroy(fib_table);
1238 fib_table_lock (u32 fib_index,
1239 fib_protocol_t proto,
1240 fib_source_t source)
1242 fib_table_t *fib_table;
1244 fib_table = fib_table_get(fib_index, proto);
1245 fib_table->ft_locks[source]++;
1246 fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]++;
1250 fib_table_get_num_entries (u32 fib_index,
1251 fib_protocol_t proto,
1252 fib_source_t source)
1254 fib_table_t *fib_table;
1256 fib_table = fib_table_get(fib_index, proto);
1258 return (fib_table->ft_src_route_counts[source]);
1262 format_fib_table_name (u8* s, va_list* ap)
1264 fib_node_index_t fib_index = va_arg(*ap, fib_node_index_t);
1265 fib_protocol_t proto = va_arg(*ap, int); // int promotion
1266 fib_table_t *fib_table;
1268 fib_table = fib_table_get(fib_index, proto);
1270 s = format(s, "%v", fib_table->ft_desc);
1276 * @brief Table flush context. Store the indicies of matching FIB entries
1277 * that need to be removed.
1279 typedef struct fib_table_flush_ctx_t_
1282 * The list of entries to flush
1284 fib_node_index_t *ftf_entries;
1287 * The source we are flushing
1289 fib_source_t ftf_source;
1290 } fib_table_flush_ctx_t;
1292 static fib_table_walk_rc_t
1293 fib_table_flush_cb (fib_node_index_t fib_entry_index,
1296 fib_table_flush_ctx_t *ctx = arg;
1298 if (fib_entry_is_sourced(fib_entry_index, ctx->ftf_source))
1300 vec_add1(ctx->ftf_entries, fib_entry_index);
1302 return (FIB_TABLE_WALK_CONTINUE);
1307 fib_table_flush (u32 fib_index,
1308 fib_protocol_t proto,
1309 fib_source_t source)
1311 fib_node_index_t *fib_entry_index;
1312 fib_table_flush_ctx_t ctx = {
1313 .ftf_entries = NULL,
1314 .ftf_source = source,
1317 fib_table_walk(fib_index, proto,
1321 vec_foreach(fib_entry_index, ctx.ftf_entries)
1323 fib_table_entry_delete_index(*fib_entry_index, source);
1326 vec_free(ctx.ftf_entries);
1330 format_fib_table_memory (u8 *s, va_list *args)
1332 s = format(s, "%U", format_ip4_fib_table_memory);
1333 s = format(s, "%U", format_ip6_fib_table_memory);
1334 s = format(s, "%U", format_mpls_fib_table_memory);