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(&fib_table->v4,
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(&fib_table->mpls,
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(&fib_table->v4,
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(&fib_table->mpls,
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(&fib_table->v4,
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(&fib_table->mpls,
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(&fib_table->v4,
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(&fib_table->mpls,
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 case FIB_PROTOCOL_IP6:
275 return (ip6_fib_table_fwding_dpo_remove(fib_index,
276 &prefix->fp_addr.ip6,
279 case FIB_PROTOCOL_MPLS:
280 return (mpls_fib_forwarding_table_reset(mpls_fib_get(fib_index),
288 fib_table_entry_special_dpo_add (u32 fib_index,
289 const fib_prefix_t *prefix,
291 fib_entry_flag_t flags,
294 fib_node_index_t fib_entry_index;
295 fib_table_t *fib_table;
297 fib_table = fib_table_get(fib_index, prefix->fp_proto);
298 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
300 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
302 fib_entry_index = fib_entry_create_special(fib_index, prefix,
306 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
307 fib_table->ft_src_route_counts[source]++;
313 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
314 fib_entry_special_add(fib_entry_index, source, flags, dpo);
316 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
318 fib_table->ft_src_route_counts[source]++;
323 return (fib_entry_index);
327 fib_table_entry_special_dpo_update (u32 fib_index,
328 const fib_prefix_t *prefix,
330 fib_entry_flag_t flags,
333 fib_node_index_t fib_entry_index;
334 fib_table_t *fib_table;
336 fib_table = fib_table_get(fib_index, prefix->fp_proto);
337 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
339 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
341 fib_entry_index = fib_entry_create_special(fib_index, prefix,
345 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
346 fib_table->ft_src_route_counts[source]++;
352 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
355 fib_entry_special_update(fib_entry_index, source, flags, dpo);
357 fib_entry_special_add(fib_entry_index, source, flags, dpo);
359 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
361 fib_table->ft_src_route_counts[source]++;
365 return (fib_entry_index);
369 fib_table_entry_special_add (u32 fib_index,
370 const fib_prefix_t *prefix,
372 fib_entry_flag_t flags,
373 adj_index_t adj_index)
375 fib_node_index_t fib_entry_index;
376 dpo_id_t tmp_dpo = DPO_INVALID;
378 if (ADJ_INDEX_INVALID != adj_index)
387 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_route_path_t *path)
478 if (fib_prefix_is_host(prefix) &&
479 ip46_address_is_zero(&path->frp_addr) &&
480 path->frp_sw_if_index != ~0)
482 path->frp_addr = prefix->fp_addr;
487 fib_table_entry_path_add (u32 fib_index,
488 const fib_prefix_t *prefix,
490 fib_entry_flag_t flags,
491 fib_protocol_t next_hop_proto,
492 const ip46_address_t *next_hop,
493 u32 next_hop_sw_if_index,
494 u32 next_hop_fib_index,
496 mpls_label_t next_hop_label,
497 fib_route_path_flags_t path_flags)
499 fib_route_path_t path = {
500 .frp_proto = next_hop_proto,
501 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
502 .frp_sw_if_index = next_hop_sw_if_index,
503 .frp_fib_index = next_hop_fib_index,
504 .frp_weight = next_hop_weight,
505 .frp_flags = path_flags,
506 .frp_label = next_hop_label,
508 fib_node_index_t fib_entry_index;
509 fib_route_path_t *paths = NULL;
511 fib_table_route_path_fixup(prefix, &path);
512 vec_add1(paths, path);
514 fib_entry_index = fib_table_entry_path_add2(fib_index, prefix,
515 source, flags, paths);
518 return (fib_entry_index);
522 fib_table_entry_path_add2 (u32 fib_index,
523 const fib_prefix_t *prefix,
525 fib_entry_flag_t flags,
526 const fib_route_path_t *rpath)
528 fib_node_index_t fib_entry_index;
529 fib_table_t *fib_table;
531 fib_table = fib_table_get(fib_index, prefix->fp_proto);
532 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
534 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
536 fib_entry_index = fib_entry_create(fib_index, prefix,
540 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
541 fib_table->ft_src_route_counts[source]++;
547 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
548 fib_entry_path_add(fib_entry_index, source, flags, rpath);;
550 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
552 fib_table->ft_src_route_counts[source]++;
556 return (fib_entry_index);
560 fib_table_entry_path_remove2 (u32 fib_index,
561 const fib_prefix_t *prefix,
563 const fib_route_path_t *rpath)
567 * yes => remove source
568 * 2 - is it still sourced?
571 fib_node_index_t fib_entry_index;
572 fib_table_t *fib_table;
574 fib_table = fib_table_get(fib_index, prefix->fp_proto);
575 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
577 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
580 * removing an etry that does not exist. i'll allow it.
585 fib_entry_src_flag_t src_flag;
589 * don't nobody go nowhere
591 fib_entry_lock(fib_entry_index);
592 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
594 src_flag = fib_entry_path_remove(fib_entry_index, source, rpath);
596 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
599 * last source gone. remove from the table
601 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
604 * now the entry is no longer in the table, we can
605 * inform the entries that it covers to re-calculate their cover
607 fib_entry_cover_change_notify(fib_entry_index,
608 FIB_NODE_INDEX_INVALID);
612 * still has sources, leave it be.
614 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
616 fib_table->ft_src_route_counts[source]--;
619 fib_entry_unlock(fib_entry_index);
624 fib_table_entry_path_remove (u32 fib_index,
625 const fib_prefix_t *prefix,
627 fib_protocol_t next_hop_proto,
628 const ip46_address_t *next_hop,
629 u32 next_hop_sw_if_index,
630 u32 next_hop_fib_index,
632 fib_route_path_flags_t path_flags)
636 * yes => remove source
637 * 2 - is it still sourced?
640 fib_route_path_t path = {
641 .frp_proto = next_hop_proto,
642 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
643 .frp_sw_if_index = next_hop_sw_if_index,
644 .frp_fib_index = next_hop_fib_index,
645 .frp_weight = next_hop_weight,
646 .frp_flags = path_flags,
648 fib_route_path_t *paths = NULL;
650 fib_table_route_path_fixup(prefix, &path);
651 vec_add1(paths, path);
653 fib_table_entry_path_remove2(fib_index, prefix, source, paths);
659 fib_route_path_cmp_for_sort (void * v1,
662 return (fib_route_path_cmp(v1, v2));
666 fib_table_entry_update (u32 fib_index,
667 const fib_prefix_t *prefix,
669 fib_entry_flag_t flags,
670 const fib_route_path_t *paths)
672 fib_node_index_t fib_entry_index;
673 fib_table_t *fib_table;
675 fib_table = fib_table_get(fib_index, prefix->fp_proto);
676 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
679 * sort the paths provided by the control plane. this means
680 * the paths and the extension on the entry will be sorted.
682 vec_sort_with_function(((fib_route_path_t*)paths), // const cast
683 fib_route_path_cmp_for_sort);
685 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
687 fib_entry_index = fib_entry_create(fib_index, prefix,
691 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
692 fib_table->ft_src_route_counts[source]++;
698 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
699 fib_entry_update(fib_entry_index, source, flags, paths);
701 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
703 fib_table->ft_src_route_counts[source]++;
707 return (fib_entry_index);
711 fib_table_entry_update_one_path (u32 fib_index,
712 const fib_prefix_t *prefix,
714 fib_entry_flag_t flags,
715 fib_protocol_t next_hop_proto,
716 const ip46_address_t *next_hop,
717 u32 next_hop_sw_if_index,
718 u32 next_hop_fib_index,
720 mpls_label_t next_hop_label,
721 fib_route_path_flags_t path_flags)
723 fib_node_index_t fib_entry_index;
724 fib_route_path_t path = {
725 .frp_proto = next_hop_proto,
726 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
727 .frp_sw_if_index = next_hop_sw_if_index,
728 .frp_fib_index = next_hop_fib_index,
729 .frp_weight = next_hop_weight,
730 .frp_flags = path_flags,
731 .frp_label = next_hop_label,
733 fib_route_path_t *paths = NULL;
735 fib_table_route_path_fixup(prefix, &path);
736 vec_add1(paths, path);
739 fib_table_entry_update(fib_index, prefix, source, flags, paths);
743 return (fib_entry_index);
747 fib_table_entry_delete_i (u32 fib_index,
748 fib_node_index_t fib_entry_index,
749 const fib_prefix_t *prefix,
752 fib_entry_src_flag_t src_flag;
753 fib_table_t *fib_table;
756 fib_table = fib_table_get(fib_index, prefix->fp_proto);
757 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
760 * don't nobody go nowhere
762 fib_entry_lock(fib_entry_index);
764 src_flag = fib_entry_delete(fib_entry_index, source);
766 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
769 * last source gone. remove from the table
771 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
774 * now the entry is no longer in the table, we can
775 * inform the entries that it covers to re-calculate their cover
777 fib_entry_cover_change_notify(fib_entry_index,
778 FIB_NODE_INDEX_INVALID);
782 * still has sources, leave it be.
784 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
786 fib_table->ft_src_route_counts[source]--;
789 fib_entry_unlock(fib_entry_index);
793 fib_table_entry_delete (u32 fib_index,
794 const fib_prefix_t *prefix,
797 fib_node_index_t fib_entry_index;
799 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
801 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
804 * removing an etry that does not exist.
805 * i'll allow it, but i won't like it.
807 clib_warning("%U not in FIB", format_fib_prefix, prefix);
811 fib_table_entry_delete_i(fib_index, fib_entry_index, prefix, source);
816 fib_table_entry_delete_index (fib_node_index_t fib_entry_index,
821 fib_entry_get_prefix(fib_entry_index, &prefix);
823 fib_table_entry_delete_i(fib_entry_get_fib_index(fib_entry_index),
824 fib_entry_index, &prefix, source);
828 fib_table_entry_local_label_add (u32 fib_index,
829 const fib_prefix_t *prefix,
832 fib_node_index_t fib_entry_index;
834 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
836 if (FIB_NODE_INDEX_INVALID == fib_entry_index ||
837 !fib_entry_is_sourced(fib_entry_index, FIB_SOURCE_MPLS))
840 * only source the prefix once. this allows the label change
843 fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix,
849 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &label);
851 return (fib_entry_index);
855 fib_table_entry_local_label_remove (u32 fib_index,
856 const fib_prefix_t *prefix,
859 fib_node_index_t fib_entry_index;
863 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
865 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
868 data = fib_entry_get_source_data(fib_entry_index, FIB_SOURCE_MPLS);
873 pl = *(mpls_label_t*)data;
878 pl = MPLS_LABEL_INVALID;
880 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &pl);
881 fib_table_entry_special_remove(fib_index,
887 fib_table_get_index_for_sw_if_index (fib_protocol_t proto,
892 case FIB_PROTOCOL_IP4:
893 return (ip4_fib_table_get_index_for_sw_if_index(sw_if_index));
894 case FIB_PROTOCOL_IP6:
895 return (ip6_fib_table_get_index_for_sw_if_index(sw_if_index));
896 case FIB_PROTOCOL_MPLS:
897 return (mpls_fib_table_get_index_for_sw_if_index(sw_if_index));
903 fib_table_get_flow_hash_config (u32 fib_index,
904 fib_protocol_t proto)
908 case FIB_PROTOCOL_IP4:
909 return (ip4_fib_table_get_flow_hash_config(fib_index));
910 case FIB_PROTOCOL_IP6:
911 return (ip6_fib_table_get_flow_hash_config(fib_index));
912 case FIB_PROTOCOL_MPLS:
913 return (mpls_fib_table_get_flow_hash_config(fib_index));
920 fib_table_get_table_id_for_sw_if_index (fib_protocol_t proto,
923 fib_table_t *fib_table;
925 fib_table = fib_table_get(fib_table_get_index_for_sw_if_index(
929 return ((NULL != fib_table ? fib_table->ft_table_id : ~0));
933 fib_table_find (fib_protocol_t proto,
938 case FIB_PROTOCOL_IP4:
939 return (ip4_fib_index_from_table_id(table_id));
940 case FIB_PROTOCOL_IP6:
941 return (ip6_fib_index_from_table_id(table_id));
942 case FIB_PROTOCOL_MPLS:
943 return (mpls_fib_index_from_table_id(table_id));
949 fib_table_find_or_create_and_lock (fib_protocol_t proto,
952 fib_table_t *fib_table;
957 case FIB_PROTOCOL_IP4:
958 fi = ip4_fib_table_find_or_create_and_lock(table_id);
960 case FIB_PROTOCOL_IP6:
961 fi = ip6_fib_table_find_or_create_and_lock(table_id);
963 case FIB_PROTOCOL_MPLS:
964 fi = mpls_fib_table_find_or_create_and_lock(table_id);
970 fib_table = fib_table_get(fi, proto);
972 fib_table->ft_desc = format(NULL, "%U-VRF:%d",
973 format_fib_protocol, proto,
980 fib_table_create_and_lock (fib_protocol_t proto,
981 const char *const fmt,
984 fib_table_t *fib_table;
992 case FIB_PROTOCOL_IP4:
993 fi = ip4_fib_table_create_and_lock();
995 case FIB_PROTOCOL_IP6:
996 fi = ip6_fib_table_create_and_lock();
998 case FIB_PROTOCOL_MPLS:
999 fi = mpls_fib_table_create_and_lock();
1005 fib_table = fib_table_get(fi, proto);
1007 fib_table->ft_desc = va_format(fib_table->ft_desc, fmt, &ap);
1014 fib_table_destroy (fib_table_t *fib_table)
1016 vec_free(fib_table->ft_desc);
1018 switch (fib_table->ft_proto)
1020 case FIB_PROTOCOL_IP4:
1021 ip4_fib_table_destroy(&fib_table->v4);
1023 case FIB_PROTOCOL_IP6:
1024 ip6_fib_table_destroy(fib_table->ft_index);
1026 case FIB_PROTOCOL_MPLS:
1027 mpls_fib_table_destroy(&fib_table->mpls);
1033 fib_table_unlock (u32 fib_index,
1034 fib_protocol_t proto)
1036 fib_table_t *fib_table;
1038 fib_table = fib_table_get(fib_index, proto);
1039 fib_table->ft_locks--;
1041 if (0 == fib_table->ft_locks)
1043 fib_table_destroy(fib_table);
1047 fib_table_lock (u32 fib_index,
1048 fib_protocol_t proto)
1050 fib_table_t *fib_table;
1052 fib_table = fib_table_get(fib_index, proto);
1053 fib_table->ft_locks++;
1057 fib_table_get_num_entries (u32 fib_index,
1058 fib_protocol_t proto,
1059 fib_source_t source)
1061 fib_table_t *fib_table;
1063 fib_table = fib_table_get(fib_index, proto);
1065 return (fib_table->ft_src_route_counts[source]);
1069 format_fib_table_name (u8* s, va_list ap)
1071 fib_node_index_t fib_index = va_arg(ap, fib_node_index_t);
1072 fib_protocol_t proto = va_arg(ap, int); // int promotion
1073 fib_table_t *fib_table;
1075 fib_table = fib_table_get(fib_index, proto);
1077 s = format(s, "%v", fib_table->ft_desc);
1083 fib_table_flush (u32 fib_index,
1084 fib_protocol_t proto,
1085 fib_source_t source)