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.
201 * If the prefix that has been inserted is a host route
202 * then it is not possible that it will be the cover for any
203 * other entry, so we can elide the walk. This is particularly
204 * beneficial since there are often many host entries sharing the
205 * same cover (i.e. ADJ or RR sourced entries).
207 if (!fib_entry_is_host(fib_entry_index))
209 fib_entry_cover_change_notify(fib_entry_cover_index,
216 fib_table_entry_insert (fib_table_t *fib_table,
217 const fib_prefix_t *prefix,
218 fib_node_index_t fib_entry_index)
220 vlib_smp_unsafe_warning();
222 fib_entry_lock(fib_entry_index);
223 fib_table->ft_total_route_counts++;
225 switch (prefix->fp_proto)
227 case FIB_PROTOCOL_IP4:
228 ip4_fib_table_entry_insert(ip4_fib_get(fib_table->ft_index),
229 &prefix->fp_addr.ip4,
233 case FIB_PROTOCOL_IP6:
234 ip6_fib_table_entry_insert(fib_table->ft_index,
235 &prefix->fp_addr.ip6,
239 case FIB_PROTOCOL_MPLS:
240 mpls_fib_table_entry_insert(mpls_fib_get(fib_table->ft_index),
247 fib_table_post_insert_actions(fib_table, prefix, fib_entry_index);
251 fib_table_fwding_dpo_update (u32 fib_index,
252 const fib_prefix_t *prefix,
255 vlib_smp_unsafe_warning();
257 switch (prefix->fp_proto)
259 case FIB_PROTOCOL_IP4:
260 return (ip4_fib_table_fwding_dpo_update(ip4_fib_get(fib_index),
261 &prefix->fp_addr.ip4,
264 case FIB_PROTOCOL_IP6:
265 return (ip6_fib_table_fwding_dpo_update(fib_index,
266 &prefix->fp_addr.ip6,
269 case FIB_PROTOCOL_MPLS:
270 return (mpls_fib_forwarding_table_update(mpls_fib_get(fib_index),
278 fib_table_fwding_dpo_remove (u32 fib_index,
279 const fib_prefix_t *prefix,
282 vlib_smp_unsafe_warning();
284 switch (prefix->fp_proto)
286 case FIB_PROTOCOL_IP4:
287 return (ip4_fib_table_fwding_dpo_remove(ip4_fib_get(fib_index),
288 &prefix->fp_addr.ip4,
291 fib_table_get_less_specific(fib_index,
293 case FIB_PROTOCOL_IP6:
294 return (ip6_fib_table_fwding_dpo_remove(fib_index,
295 &prefix->fp_addr.ip6,
298 case FIB_PROTOCOL_MPLS:
299 return (mpls_fib_forwarding_table_reset(mpls_fib_get(fib_index),
307 fib_table_entry_special_dpo_add (u32 fib_index,
308 const fib_prefix_t *prefix,
310 fib_entry_flag_t flags,
313 fib_node_index_t fib_entry_index;
314 fib_table_t *fib_table;
316 fib_table = fib_table_get(fib_index, prefix->fp_proto);
317 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
319 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
321 fib_entry_index = fib_entry_create_special(fib_index, prefix,
325 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
326 fib_table->ft_src_route_counts[source]++;
332 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
333 fib_entry_special_add(fib_entry_index, source, flags, dpo);
335 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
337 fib_table->ft_src_route_counts[source]++;
342 return (fib_entry_index);
346 fib_table_entry_special_dpo_update (u32 fib_index,
347 const fib_prefix_t *prefix,
349 fib_entry_flag_t flags,
352 fib_node_index_t fib_entry_index;
353 fib_table_t *fib_table;
355 fib_table = fib_table_get(fib_index, prefix->fp_proto);
356 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
358 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
360 fib_entry_index = fib_entry_create_special(fib_index, prefix,
364 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
365 fib_table->ft_src_route_counts[source]++;
371 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
374 fib_entry_special_update(fib_entry_index, source, flags, dpo);
376 fib_entry_special_add(fib_entry_index, source, flags, dpo);
378 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
380 fib_table->ft_src_route_counts[source]++;
384 return (fib_entry_index);
388 fib_table_entry_special_add (u32 fib_index,
389 const fib_prefix_t *prefix,
391 fib_entry_flag_t flags)
393 fib_node_index_t fib_entry_index;
394 dpo_id_t tmp_dpo = DPO_INVALID;
396 dpo_copy(&tmp_dpo, drop_dpo_get(fib_proto_to_dpo(prefix->fp_proto)));
398 fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix, source,
401 dpo_unlock(&tmp_dpo);
403 return (fib_entry_index);
407 fib_table_entry_special_remove (u32 fib_index,
408 const fib_prefix_t *prefix,
413 * yes => remove source
414 * 2 - is it still sourced?
417 fib_node_index_t fib_entry_index;
418 fib_table_t *fib_table;
420 fib_table = fib_table_get(fib_index, prefix->fp_proto);
421 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
423 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
426 * removing an etry that does not exist. i'll allow it.
431 fib_entry_src_flag_t src_flag;
435 * don't nobody go nowhere
437 fib_entry_lock(fib_entry_index);
438 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
440 src_flag = fib_entry_special_remove(fib_entry_index, source);
442 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
445 * last source gone. remove from the table
447 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
450 * now the entry is no longer in the table, we can
451 * inform the entries that it covers to re-calculate their cover
453 fib_entry_cover_change_notify(fib_entry_index,
454 FIB_NODE_INDEX_INVALID);
458 * still has sources, leave it be.
460 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
462 fib_table->ft_src_route_counts[source]--;
465 fib_entry_unlock(fib_entry_index);
470 * fib_table_route_path_fixup
472 * Convert attached hosts to attached next-hops.
474 * This special case is required because an attached path will link to a
475 * glean, and the FIB entry will have the interface or API/CLI source. When
476 * the ARP/ND process is completes then that source (which will provide a
477 * complete adjacency) will be lower priority and so the FIB entry will
478 * remain linked to a glean and traffic will never reach the hosts. For
479 * an ATTAHCED_HOST path we can link the path directly to the [incomplete]
483 fib_table_route_path_fixup (const fib_prefix_t *prefix,
484 fib_entry_flag_t *eflags,
485 fib_route_path_t *path)
488 * not all zeros next hop &&
489 * is recursive path &&
490 * nexthop is same as the route's address
492 if ((!ip46_address_is_zero(&path->frp_addr)) &&
493 (~0 == path->frp_sw_if_index) &&
494 (0 == ip46_address_cmp(&path->frp_addr, &prefix->fp_addr)))
496 /* Prefix recurses via itse;f */
497 path->frp_flags |= FIB_ROUTE_PATH_DROP;
499 if (!(path->frp_flags & FIB_ROUTE_PATH_LOCAL) &&
500 fib_prefix_is_host(prefix) &&
501 ip46_address_is_zero(&path->frp_addr) &&
502 path->frp_sw_if_index != ~0 &&
503 path->frp_proto != DPO_PROTO_ETHERNET)
505 path->frp_addr = prefix->fp_addr;
506 path->frp_flags |= FIB_ROUTE_PATH_ATTACHED;
508 if (*eflags & FIB_ENTRY_FLAG_DROP)
510 path->frp_flags |= FIB_ROUTE_PATH_DROP;
512 if (*eflags & FIB_ENTRY_FLAG_LOCAL)
514 path->frp_flags |= FIB_ROUTE_PATH_LOCAL;
516 if (*eflags & FIB_ENTRY_FLAG_EXCLUSIVE)
518 path->frp_flags |= FIB_ROUTE_PATH_EXCLUSIVE;
520 if (path->frp_flags & FIB_ROUTE_PATH_LOCAL)
522 *eflags |= FIB_ENTRY_FLAG_LOCAL;
524 if (path->frp_sw_if_index != ~0)
526 *eflags |= FIB_ENTRY_FLAG_CONNECTED;
532 fib_table_entry_path_add (u32 fib_index,
533 const fib_prefix_t *prefix,
535 fib_entry_flag_t flags,
536 dpo_proto_t next_hop_proto,
537 const ip46_address_t *next_hop,
538 u32 next_hop_sw_if_index,
539 u32 next_hop_fib_index,
541 fib_mpls_label_t *next_hop_labels,
542 fib_route_path_flags_t path_flags)
544 fib_route_path_t path = {
545 .frp_proto = next_hop_proto,
546 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
547 .frp_sw_if_index = next_hop_sw_if_index,
548 .frp_fib_index = next_hop_fib_index,
549 .frp_weight = next_hop_weight,
550 .frp_flags = path_flags,
551 .frp_rpf_id = INDEX_INVALID,
552 .frp_label_stack = next_hop_labels,
554 fib_node_index_t fib_entry_index;
555 fib_route_path_t *paths = NULL;
557 vec_add1(paths, path);
559 fib_entry_index = fib_table_entry_path_add2(fib_index, prefix,
560 source, flags, paths);
563 return (fib_entry_index);
567 fib_table_entry_path_add2 (u32 fib_index,
568 const fib_prefix_t *prefix,
570 fib_entry_flag_t flags,
571 fib_route_path_t *rpaths)
573 fib_node_index_t fib_entry_index;
574 fib_table_t *fib_table;
577 fib_table = fib_table_get(fib_index, prefix->fp_proto);
578 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
580 for (ii = 0; ii < vec_len(rpaths); ii++)
582 fib_table_route_path_fixup(prefix, &flags, &rpaths[ii]);
585 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
587 fib_entry_index = fib_entry_create(fib_index, prefix,
591 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
592 fib_table->ft_src_route_counts[source]++;
598 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
599 fib_entry_path_add(fib_entry_index, source, flags, rpaths);;
601 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
603 fib_table->ft_src_route_counts[source]++;
607 return (fib_entry_index);
611 fib_table_entry_path_remove2 (u32 fib_index,
612 const fib_prefix_t *prefix,
614 fib_route_path_t *rpaths)
618 * yes => remove source
619 * 2 - is it still sourced?
622 fib_node_index_t fib_entry_index;
623 fib_route_path_t *rpath;
624 fib_table_t *fib_table;
626 fib_table = fib_table_get(fib_index, prefix->fp_proto);
627 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
629 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
632 * removing an etry that does not exist. i'll allow it.
637 fib_entry_src_flag_t src_flag;
641 * if it's not sourced, then there's nowt to remove
643 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
650 * don't nobody go nowhere
652 fib_entry_lock(fib_entry_index);
654 vec_foreach(rpath, rpaths)
656 fib_entry_flag_t eflags;
658 eflags = fib_entry_get_flags_for_source(fib_entry_index,
660 fib_table_route_path_fixup(prefix, &eflags, rpath);
663 src_flag = fib_entry_path_remove(fib_entry_index, source, rpaths);
665 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
668 * last source gone. remove from the table
670 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
673 * now the entry is no longer in the table, we can
674 * inform the entries that it covers to re-calculate their cover
676 fib_entry_cover_change_notify(fib_entry_index,
677 FIB_NODE_INDEX_INVALID);
681 * still has sources, leave it be.
683 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
685 fib_table->ft_src_route_counts[source]--;
688 fib_entry_unlock(fib_entry_index);
693 fib_table_entry_path_remove (u32 fib_index,
694 const fib_prefix_t *prefix,
696 dpo_proto_t next_hop_proto,
697 const ip46_address_t *next_hop,
698 u32 next_hop_sw_if_index,
699 u32 next_hop_fib_index,
701 fib_route_path_flags_t path_flags)
705 * yes => remove source
706 * 2 - is it still sourced?
709 fib_route_path_t path = {
710 .frp_proto = next_hop_proto,
711 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
712 .frp_sw_if_index = next_hop_sw_if_index,
713 .frp_fib_index = next_hop_fib_index,
714 .frp_weight = next_hop_weight,
715 .frp_flags = path_flags,
717 fib_route_path_t *paths = NULL;
719 vec_add1(paths, path);
721 fib_table_entry_path_remove2(fib_index, prefix, source, paths);
727 fib_route_path_cmp_for_sort (void * v1,
730 return (fib_route_path_cmp(v1, v2));
734 fib_table_entry_update (u32 fib_index,
735 const fib_prefix_t *prefix,
737 fib_entry_flag_t flags,
738 fib_route_path_t *paths)
740 fib_node_index_t fib_entry_index;
741 fib_table_t *fib_table;
744 fib_table = fib_table_get(fib_index, prefix->fp_proto);
745 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
747 for (ii = 0; ii < vec_len(paths); ii++)
749 fib_table_route_path_fixup(prefix, &flags, &paths[ii]);
752 * sort the paths provided by the control plane. this means
753 * the paths and the extension on the entry will be sorted.
755 vec_sort_with_function(paths, fib_route_path_cmp_for_sort);
757 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
759 fib_entry_index = fib_entry_create(fib_index, prefix,
763 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
764 fib_table->ft_src_route_counts[source]++;
770 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
771 fib_entry_update(fib_entry_index, source, flags, paths);
773 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
775 fib_table->ft_src_route_counts[source]++;
779 return (fib_entry_index);
783 fib_table_entry_update_one_path (u32 fib_index,
784 const fib_prefix_t *prefix,
786 fib_entry_flag_t flags,
787 dpo_proto_t next_hop_proto,
788 const ip46_address_t *next_hop,
789 u32 next_hop_sw_if_index,
790 u32 next_hop_fib_index,
792 fib_mpls_label_t *next_hop_labels,
793 fib_route_path_flags_t path_flags)
795 fib_node_index_t fib_entry_index;
796 fib_route_path_t path = {
797 .frp_proto = next_hop_proto,
798 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
799 .frp_sw_if_index = next_hop_sw_if_index,
800 .frp_fib_index = next_hop_fib_index,
801 .frp_weight = next_hop_weight,
802 .frp_flags = path_flags,
803 .frp_label_stack = next_hop_labels,
805 fib_route_path_t *paths = NULL;
807 vec_add1(paths, path);
810 fib_table_entry_update(fib_index, prefix, source, flags, paths);
814 return (fib_entry_index);
818 fib_table_entry_delete_i (u32 fib_index,
819 fib_node_index_t fib_entry_index,
820 const fib_prefix_t *prefix,
823 fib_entry_src_flag_t src_flag;
824 fib_table_t *fib_table;
827 fib_table = fib_table_get(fib_index, prefix->fp_proto);
828 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
831 * don't nobody go nowhere
833 fib_entry_lock(fib_entry_index);
835 src_flag = fib_entry_delete(fib_entry_index, source);
837 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
840 * last source gone. remove from the table
842 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
845 * now the entry is no longer in the table, we can
846 * inform the entries that it covers to re-calculate their cover
848 fib_entry_cover_change_notify(fib_entry_index,
849 FIB_NODE_INDEX_INVALID);
853 * still has sources, leave it be.
855 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
857 fib_table->ft_src_route_counts[source]--;
860 fib_entry_unlock(fib_entry_index);
864 fib_table_entry_delete (u32 fib_index,
865 const fib_prefix_t *prefix,
868 fib_node_index_t fib_entry_index;
870 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
872 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
875 * removing an etry that does not exist.
876 * i'll allow it, but i won't like it.
879 clib_warning("%U not in FIB", format_fib_prefix, prefix);
883 fib_table_entry_delete_i(fib_index, fib_entry_index, prefix, source);
888 fib_table_entry_delete_index (fib_node_index_t fib_entry_index,
891 const fib_prefix_t *prefix;
893 prefix = fib_entry_get_prefix(fib_entry_index);
895 fib_table_entry_delete_i(fib_entry_get_fib_index(fib_entry_index),
896 fib_entry_index, prefix, source);
900 fib_table_entry_get_stats_index (u32 fib_index,
901 const fib_prefix_t *prefix)
903 return (fib_entry_get_stats_index(
904 fib_table_lookup_exact_match(fib_index, prefix)));
908 fib_table_entry_local_label_add (u32 fib_index,
909 const fib_prefix_t *prefix,
912 fib_node_index_t fib_entry_index;
914 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
916 if (FIB_NODE_INDEX_INVALID == fib_entry_index ||
917 !fib_entry_is_sourced(fib_entry_index, FIB_SOURCE_MPLS))
920 * only source the prefix once. this allows the label change
923 fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix,
929 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &label);
931 return (fib_entry_index);
935 fib_table_entry_local_label_remove (u32 fib_index,
936 const fib_prefix_t *prefix,
939 fib_node_index_t fib_entry_index;
943 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
945 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
948 data = fib_entry_get_source_data(fib_entry_index, FIB_SOURCE_MPLS);
953 pl = *(mpls_label_t*)data;
958 pl = MPLS_LABEL_INVALID;
960 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &pl);
961 fib_table_entry_special_remove(fib_index,
967 fib_table_get_index_for_sw_if_index (fib_protocol_t proto,
972 case FIB_PROTOCOL_IP4:
973 return (ip4_fib_table_get_index_for_sw_if_index(sw_if_index));
974 case FIB_PROTOCOL_IP6:
975 return (ip6_fib_table_get_index_for_sw_if_index(sw_if_index));
976 case FIB_PROTOCOL_MPLS:
977 return (mpls_fib_table_get_index_for_sw_if_index(sw_if_index));
983 fib_table_get_flow_hash_config (u32 fib_index,
984 fib_protocol_t proto)
988 fib = fib_table_get(fib_index, proto);
990 return (fib->ft_flow_hash_config);
994 fib_table_get_default_flow_hash_config (fib_protocol_t proto)
998 case FIB_PROTOCOL_IP4:
999 case FIB_PROTOCOL_IP6:
1000 return (IP_FLOW_HASH_DEFAULT);
1002 case FIB_PROTOCOL_MPLS:
1003 return (MPLS_FLOW_HASH_DEFAULT);
1007 return (IP_FLOW_HASH_DEFAULT);
1011 * @brief Table set flow hash config context.
1013 typedef struct fib_table_set_flow_hash_config_ctx_t_
1016 * the flow hash config to set
1018 flow_hash_config_t hash_config;
1019 } fib_table_set_flow_hash_config_ctx_t;
1021 static fib_table_walk_rc_t
1022 fib_table_set_flow_hash_config_cb (fib_node_index_t fib_entry_index,
1025 fib_table_set_flow_hash_config_ctx_t *ctx = arg;
1027 fib_entry_set_flow_hash_config(fib_entry_index, ctx->hash_config);
1029 return (FIB_TABLE_WALK_CONTINUE);
1033 fib_table_set_flow_hash_config (u32 fib_index,
1034 fib_protocol_t proto,
1035 flow_hash_config_t hash_config)
1037 fib_table_set_flow_hash_config_ctx_t ctx = {
1038 .hash_config = hash_config,
1042 fib = fib_table_get(fib_index, proto);
1043 fib->ft_flow_hash_config = hash_config;
1045 fib_table_walk(fib_index, proto,
1046 fib_table_set_flow_hash_config_cb,
1051 fib_table_get_table_id_for_sw_if_index (fib_protocol_t proto,
1054 fib_table_t *fib_table;
1056 fib_table = fib_table_get(fib_table_get_index_for_sw_if_index(
1057 proto, sw_if_index),
1060 return ((NULL != fib_table ? fib_table->ft_table_id : ~0));
1064 fib_table_get_table_id (u32 fib_index,
1065 fib_protocol_t proto)
1067 fib_table_t *fib_table;
1069 fib_table = fib_table_get(fib_index, proto);
1071 return ((NULL != fib_table ? fib_table->ft_table_id : ~0));
1075 fib_table_find (fib_protocol_t proto,
1080 case FIB_PROTOCOL_IP4:
1081 return (ip4_fib_index_from_table_id(table_id));
1082 case FIB_PROTOCOL_IP6:
1083 return (ip6_fib_index_from_table_id(table_id));
1084 case FIB_PROTOCOL_MPLS:
1085 return (mpls_fib_index_from_table_id(table_id));
1091 fib_table_find_or_create_and_lock_i (fib_protocol_t proto,
1096 fib_table_t *fib_table;
1097 fib_node_index_t fi;
1101 case FIB_PROTOCOL_IP4:
1102 fi = ip4_fib_table_find_or_create_and_lock(table_id, src);
1104 case FIB_PROTOCOL_IP6:
1105 fi = ip6_fib_table_find_or_create_and_lock(table_id, src);
1107 case FIB_PROTOCOL_MPLS:
1108 fi = mpls_fib_table_find_or_create_and_lock(table_id, src);
1114 fib_table = fib_table_get(fi, proto);
1116 if (NULL == fib_table->ft_desc)
1118 if (name && name[0])
1120 fib_table->ft_desc = format(NULL, "%s", name);
1124 fib_table->ft_desc = format(NULL, "%U-VRF:%d",
1125 format_fib_protocol, proto,
1134 fib_table_find_or_create_and_lock (fib_protocol_t proto,
1138 return (fib_table_find_or_create_and_lock_i(proto, table_id,
1143 fib_table_find_or_create_and_lock_w_name (fib_protocol_t proto,
1148 return (fib_table_find_or_create_and_lock_i(proto, table_id,
1153 fib_table_create_and_lock (fib_protocol_t proto,
1155 const char *const fmt,
1158 fib_table_t *fib_table;
1159 fib_node_index_t fi;
1165 case FIB_PROTOCOL_IP4:
1166 fi = ip4_fib_table_create_and_lock(src);
1168 case FIB_PROTOCOL_IP6:
1169 fi = ip6_fib_table_create_and_lock(src, FIB_TABLE_FLAG_NONE, NULL);
1171 case FIB_PROTOCOL_MPLS:
1172 fi = mpls_fib_table_create_and_lock(src);
1178 fib_table = fib_table_get(fi, proto);
1182 fib_table->ft_desc = va_format(fib_table->ft_desc, fmt, &ap);
1189 fib_table_destroy (fib_table_t *fib_table)
1191 vec_free(fib_table->ft_desc);
1193 switch (fib_table->ft_proto)
1195 case FIB_PROTOCOL_IP4:
1196 ip4_fib_table_destroy(fib_table->ft_index);
1198 case FIB_PROTOCOL_IP6:
1199 ip6_fib_table_destroy(fib_table->ft_index);
1201 case FIB_PROTOCOL_MPLS:
1202 mpls_fib_table_destroy(fib_table->ft_index);
1208 fib_table_walk (u32 fib_index,
1209 fib_protocol_t proto,
1210 fib_table_walk_fn_t fn,
1215 case FIB_PROTOCOL_IP4:
1216 ip4_fib_table_walk(ip4_fib_get(fib_index), fn, ctx);
1218 case FIB_PROTOCOL_IP6:
1219 ip6_fib_table_walk(fib_index, fn, ctx);
1221 case FIB_PROTOCOL_MPLS:
1222 mpls_fib_table_walk(mpls_fib_get(fib_index), fn, ctx);
1228 fib_table_sub_tree_walk (u32 fib_index,
1229 fib_protocol_t proto,
1230 const fib_prefix_t *root,
1231 fib_table_walk_fn_t fn,
1236 case FIB_PROTOCOL_IP4:
1237 ip4_fib_table_sub_tree_walk(ip4_fib_get(fib_index), root, fn, ctx);
1239 case FIB_PROTOCOL_IP6:
1240 ip6_fib_table_sub_tree_walk(fib_index, root, fn, ctx);
1242 case FIB_PROTOCOL_MPLS:
1248 fib_table_unlock (u32 fib_index,
1249 fib_protocol_t proto,
1250 fib_source_t source)
1252 fib_table_t *fib_table;
1254 fib_table = fib_table_get(fib_index, proto);
1255 fib_table->ft_locks[source]--;
1256 fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]--;
1258 if (0 == fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS])
1261 * no more locak from any source - kill it
1263 fib_table_destroy(fib_table);
1268 fib_table_lock (u32 fib_index,
1269 fib_protocol_t proto,
1270 fib_source_t source)
1272 fib_table_t *fib_table;
1274 fib_table = fib_table_get(fib_index, proto);
1276 ASSERT(fib_table->ft_locks[source] < (0xffff - 1));
1278 fib_table->ft_locks[source]++;
1279 fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]++;
1283 fib_table_get_num_entries (u32 fib_index,
1284 fib_protocol_t proto,
1285 fib_source_t source)
1287 fib_table_t *fib_table;
1289 fib_table = fib_table_get(fib_index, proto);
1291 return (fib_table->ft_src_route_counts[source]);
1295 format_fib_table_name (u8* s, va_list* ap)
1297 fib_node_index_t fib_index = va_arg(*ap, fib_node_index_t);
1298 fib_protocol_t proto = va_arg(*ap, int); // int promotion
1299 fib_table_t *fib_table;
1301 fib_table = fib_table_get(fib_index, proto);
1303 s = format(s, "%v", fib_table->ft_desc);
1309 * @brief Table flush context. Store the indicies of matching FIB entries
1310 * that need to be removed.
1312 typedef struct fib_table_flush_ctx_t_
1315 * The list of entries to flush
1317 fib_node_index_t *ftf_entries;
1320 * The source we are flushing
1322 fib_source_t ftf_source;
1323 } fib_table_flush_ctx_t;
1325 static fib_table_walk_rc_t
1326 fib_table_flush_cb (fib_node_index_t fib_entry_index,
1329 fib_table_flush_ctx_t *ctx = arg;
1331 if (fib_entry_is_sourced(fib_entry_index, ctx->ftf_source))
1333 vec_add1(ctx->ftf_entries, fib_entry_index);
1335 return (FIB_TABLE_WALK_CONTINUE);
1340 fib_table_flush (u32 fib_index,
1341 fib_protocol_t proto,
1342 fib_source_t source)
1344 fib_node_index_t *fib_entry_index;
1345 fib_table_flush_ctx_t ctx = {
1346 .ftf_entries = NULL,
1347 .ftf_source = source,
1350 fib_table_walk(fib_index, proto,
1354 vec_foreach(fib_entry_index, ctx.ftf_entries)
1356 fib_table_entry_delete_index(*fib_entry_index, source);
1359 vec_free(ctx.ftf_entries);
1363 format_fib_table_memory (u8 *s, va_list *args)
1365 s = format(s, "%U", format_ip4_fib_table_memory);
1366 s = format(s, "%U", format_ip6_fib_table_memory);
1367 s = format(s, "%U", format_mpls_fib_table_memory);