/* * Copyright (c) 2016 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Array of strings/names for the FIB sources */ static const char *fib_attribute_names[] = FIB_ENTRY_ATTRIBUTES; static const char *fib_src_attribute_names[] = FIB_ENTRY_SRC_ATTRIBUTES; /* * Pool for all fib_entries */ static fib_entry_t *fib_entry_pool; /** * the logger */ vlib_log_class_t fib_entry_logger; fib_entry_t * fib_entry_get (fib_node_index_t index) { return (pool_elt_at_index(fib_entry_pool, index)); } static fib_node_t * fib_entry_get_node (fib_node_index_t index) { return ((fib_node_t*)fib_entry_get(index)); } fib_node_index_t fib_entry_get_index (const fib_entry_t * fib_entry) { return (fib_entry - fib_entry_pool); } fib_protocol_t fib_entry_get_proto (const fib_entry_t * fib_entry) { return (fib_entry->fe_prefix.fp_proto); } dpo_proto_t fib_entry_get_dpo_proto (const fib_entry_t * fib_entry) { return (fib_proto_to_dpo(fib_entry->fe_prefix.fp_proto)); } fib_forward_chain_type_t fib_entry_get_default_chain_type (const fib_entry_t *fib_entry) { switch (fib_entry->fe_prefix.fp_proto) { case FIB_PROTOCOL_IP4: return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4); case FIB_PROTOCOL_IP6: return (FIB_FORW_CHAIN_TYPE_UNICAST_IP6); case FIB_PROTOCOL_MPLS: if (MPLS_EOS == fib_entry->fe_prefix.fp_eos) return (FIB_FORW_CHAIN_TYPE_MPLS_EOS); else return (FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS); } return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4); } u8 * format_fib_entry_flags (u8 *s, va_list *args) { fib_entry_attribute_t attr; fib_entry_flag_t flag = va_arg(*args, int); FOR_EACH_FIB_ATTRIBUTE(attr) { if ((1<fe_prefix); if (level >= FIB_ENTRY_FORMAT_DETAIL) { s = format (s, " fib:%d", fib_entry->fe_fib_index); s = format (s, " index:%d", fib_entry_get_index(fib_entry)); s = format (s, " locks:%d", fib_entry->fe_node.fn_locks); FOR_EACH_SRC_ADDED(fib_entry, src, source, ({ s = format (s, "\n %U", format_fib_source, source); s = format (s, " refs:%d", src->fes_ref_count); if (FIB_ENTRY_FLAG_NONE != src->fes_entry_flags) { s = format(s, " entry-flags:%U", format_fib_entry_flags, src->fes_entry_flags); } if (FIB_ENTRY_SRC_FLAG_NONE != src->fes_flags) { s = format(s, " src-flags:%U", format_fib_entry_src_flags, src->fes_flags); } s = fib_entry_src_format(fib_entry, source, s); s = format (s, "\n"); if (FIB_NODE_INDEX_INVALID != src->fes_pl) { s = fib_path_list_format(src->fes_pl, s); } s = format(s, "%U", format_fib_path_ext_list, &src->fes_path_exts); })); s = format (s, "\n forwarding: "); } else { s = format (s, "\n"); } fct = fib_entry_get_default_chain_type(fib_entry); if (!dpo_id_is_valid(&fib_entry->fe_lb)) { s = format (s, " UNRESOLVED\n"); return (s); } else { s = format(s, " %U-chain\n %U", format_fib_forw_chain_type, fct, format_dpo_id, &fib_entry->fe_lb, 2); s = format(s, "\n"); if (level >= FIB_ENTRY_FORMAT_DETAIL2) { index_t *fedi; s = format (s, " Delegates:\n"); vec_foreach(fedi, fib_entry->fe_delegates) { s = format(s, " %U\n", format_fib_entry_delegate, *fedi); } } } if (level >= FIB_ENTRY_FORMAT_DETAIL2) { s = format(s, " Children:"); s = fib_node_children_format(fib_entry->fe_node.fn_children, s); } return (s); } static fib_entry_t* fib_entry_from_fib_node (fib_node_t *node) { ASSERT(FIB_NODE_TYPE_ENTRY == node->fn_type); return ((fib_entry_t*)node); } static void fib_entry_last_lock_gone (fib_node_t *node) { fib_entry_delegate_type_t fdt; fib_entry_delegate_t *fed; fib_entry_t *fib_entry; fib_entry = fib_entry_from_fib_node(node); ASSERT(!dpo_id_is_valid(&fib_entry->fe_lb)); FOR_EACH_DELEGATE_CHAIN(fib_entry, fdt, fed, { dpo_reset(&fed->fd_dpo); fib_entry_delegate_remove(fib_entry, fdt); }); FIB_ENTRY_DBG(fib_entry, "last-lock"); fib_node_deinit(&fib_entry->fe_node); ASSERT(0 == vec_len(fib_entry->fe_delegates)); vec_free(fib_entry->fe_delegates); vec_free(fib_entry->fe_srcs); pool_put(fib_entry_pool, fib_entry); } static fib_entry_src_t* fib_entry_get_best_src_i (const fib_entry_t *fib_entry) { fib_entry_src_t *bsrc; /* * the enum of sources is deliberately arranged in priority order */ if (0 == vec_len(fib_entry->fe_srcs)) { bsrc = NULL; } else { bsrc = vec_elt_at_index(fib_entry->fe_srcs, 0); } return (bsrc); } static fib_source_t fib_entry_src_get_source (const fib_entry_src_t *esrc) { if (NULL != esrc) { return (esrc->fes_src); } return (FIB_SOURCE_INVALID); } static fib_entr
#!/usr/bin/env python3
#  Copyright (c) 2020. Vinci Consulting Corp. All Rights Reserved.
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

import glob
import inspect
import os.path
import re


class ContentRenderer:
    name = ""
    curr_path = os.path.abspath(inspect.getsourcefile(lambda: 0))
    vpp_root = curr_path.rsplit("/", 2)[0]
    output_dir = f"{vpp_root}/docs/dynamic_includes/"

    def render(self):
        raise NotImplementedError


class PluginRenderer(ContentRenderer):
    name = "plugin_list.inc"

    plugin_dir = f"{ContentRenderer.vpp_root}/src/plugins"

    pattern = r'VLIB_PLUGIN_REGISTER\s?\(\)\s*=\s*{.*\.description\s?=\s?"([^"]*)".*};'  # noqa: 501
    regex = re.compile(pattern, re.MULTILINE | re.DOTALL)

    def render(self):
        with open(f"{self.__class__.output_dir}{self.__class__.name}",
                  "w") as output:
            with os.scandir(self.__class__.plugin_dir) as pdir:
                for entry in sorted(pdir, key=lambda entry: entry.name):
                    if not entry.name.startswith('.') and entry.is_dir():
                        description = "<no-description-found>"
                        # we use glob because a plugin can (ioam for now)
                        # define the plugin definition in
                        # a further subdirectory.
                        for f in glob.iglob(f'{self.__class__.plugin_dir}/'
                                            f'{entry.name}/**',
                                            recursive=True):
                            if f.endswith('.c'):
                                with open(f, "r", encoding="utf-8") \
                                        as src:
                                    for match in self.__class__.regex.finditer(
                                            src.read()):
                                        description = "%s" % (match.group(1))

                        output.write(f"* {entry.name} - {description}\n")


# if this list grows substantially, we can move the classes to
# a folder and import them.
renderers = [PluginRenderer,
             ]


def main():
    print("rendering dynamic includes...")
    for renderer in renderers:
        renderer().render()
    print("done.")


if __name__ == "__main__":
    main()
/* * still have sources */ return (FIB_ENTRY_SRC_FLAG_ADDED); } /* * fib_entry_path_remove * * remove a path from the entry. * return the fib_entry's index if it is still present, INVALID otherwise. */ fib_entry_src_flag_t fib_entry_path_remove (fib_node_index_t fib_entry_index, fib_source_t source, const fib_route_path_t *rpaths) { fib_entry_src_flag_t sflag; fib_source_t best_source; fib_entry_flag_t bflags; fib_entry_t *fib_entry; fib_entry_src_t *bsrc; fib_entry = fib_entry_get(fib_entry_index); ASSERT(NULL != fib_entry); bsrc = fib_entry_get_best_src_i(fib_entry); best_source = fib_entry_src_get_source(bsrc); bflags = fib_entry_src_get_flags(bsrc); sflag = fib_entry_src_action_path_remove(fib_entry, source, rpaths); FIB_ENTRY_DBG(fib_entry, "path remove:%U", format_fib_source, source); /* * if the path list for the source passed is invalid, * then we need to create a new one. else we are updating * an existing. */ switch (fib_source_cmp(source, best_source)) { case FIB_SOURCE_CMP_BETTER: /* * Que! removing a path from a source that is better than the * one this entry is using. */ ASSERT(0); break; case FIB_SOURCE_CMP_WORSE: /* * the source is not the best. no need to update forwarding */ if (FIB_ENTRY_SRC_FLAG_ADDED & sflag) { /* * the source being removed still has paths */ return (FIB_ENTRY_SRC_FLAG_ADDED); } else { /* * that was the last path from this source, check if those * that remain are non-inherited */ return (fib_entry_src_burn_only_inherited(fib_entry)); } break; case FIB_SOURCE_CMP_EQUAL: /* * removing a path from the path-list we were using. */ if (!(FIB_ENTRY_SRC_FLAG_ADDED & sflag)) { /* * the last path from the source was removed. * fallback to lower source */ return (fib_entry_source_removed(fib_entry, bflags)); } else { /* * re-install the new forwarding information */ fib_entry_src_action_reactivate(fib_entry, source); } break; } fib_entry_post_update_actions(fib_entry, source, bflags); /* * still have sources */ return (FIB_ENTRY_SRC_FLAG_ADDED); } /* * fib_entry_special_remove * * remove a special source from the entry. * return the fib_entry's index if it is still present, INVALID otherwise. */ fib_entry_src_flag_t fib_entry_special_remove (fib_node_index_t fib_entry_index, fib_source_t source) { fib_entry_src_flag_t sflag; fib_source_t best_source; fib_entry_flag_t bflags; fib_entry_t *fib_entry; fib_entry_src_t *bsrc; fib_entry = fib_entry_get(fib_entry_index); ASSERT(NULL != fib_entry); bsrc = fib_entry_get_best_src_i(fib_entry); best_source = fib_entry_src_get_source(bsrc); bflags = fib_entry_src_get_flags(bsrc); FIB_ENTRY_DBG(fib_entry, "special remove:%U", format_fib_source, source); sflag = fib_entry_src_action_remove_or_update_inherit(fib_entry, source); /* * if the path list for the source passed is invalid, * then we need to create a new one. else we are updating * an existing. */ switch (fib_source_cmp(source, best_source)) { case FIB_SOURCE_CMP_BETTER: /* * Que! removing a path from a source that is better than the * one this entry is using. This can only mean it is a source * this prefix does not have. */ return (FIB_ENTRY_SRC_FLAG_ADDED); case FIB_SOURCE_CMP_WORSE: /* * the source is not the best. no need to update forwarding */ if (FIB_ENTRY_SRC_FLAG_ADDED & sflag) { /* * the source being removed still has paths */ return (FIB_ENTRY_SRC_FLAG_ADDED); } else { /* * that was the last path from this source, check if those * that remain are non-inherited */ if (FIB_ENTRY_SRC_FLAG_NONE == fib_entry_src_burn_only_inherited(fib_entry)) { /* * no more sources left. this entry is toast. */ fib_entry = fib_entry_post_flag_update_actions(fib_entry, bflags); fib_entry_src_action_uninstall(fib_entry); return (FIB_ENTRY_SRC_FLAG_NONE); } /* * reactivate the best source so the interposer gets restacked */ fib_entry_src_action_reactivate(fib_entry, best_source); return (FIB_ENTRY_SRC_FLAG_ADDED); } break; case FIB_SOURCE_CMP_EQUAL: if (!(FIB_ENTRY_SRC_FLAG_ADDED & sflag)) { /* * the source was removed. use the next best. */ return (fib_entry_source_removed(fib_entry, bflags)); } else { /* * re-install the new forwarding information */ fib_entry_src_action_reactivate(fib_entry, source); } break; } fib_entry_post_update_actions(fib_entry, source, bflags); /* * still have sources */ return (FIB_ENTRY_SRC_FLAG_ADDED); } /** * fib_entry_inherit * * If the source on the cover is inheriting then push this source * down to the covered. */ void fib_entry_inherit (fib_node_index_t cover, fib_node_index_t covered) { fib_entry_src_inherit(fib_entry_get(cover), fib_entry_get(covered)); } /** * fib_entry_delete * * The source is withdrawing all the paths it provided */ fib_entry_src_flag_t fib_entry_delete (fib_node_index_t fib_entry_index, fib_source_t source) { return (fib_entry_special_remove(fib_entry_index, source)); } /** * fib_entry_update * * The source has provided a new set of paths that will replace the old. */ void fib_entry_update (fib_node_index_t fib_entry_index, fib_source_t source, fib_entry_flag_t flags, const fib_route_path_t *paths) { fib_source_t best_source; fib_entry_flag_t bflags; fib_entry_t *fib_entry; fib_entry_src_t *bsrc; fib_entry = fib_entry_get(fib_entry_index); ASSERT(NULL != fib_entry); bsrc = fib_entry_get_best_src_i(fib_entry); best_source = fib_entry_src_get_source(bsrc); bflags = fib_entry_get_flags_i(fib_entry); fib_entry = fib_entry_src_action_path_swap(fib_entry, source, flags, paths); fib_entry_source_change_w_flags(fib_entry, best_source, bflags, source); FIB_ENTRY_DBG(fib_entry, "update"); } /* * fib_entry_cover_changed * * this entry is tracking its cover and that cover has changed. */ void fib_entry_cover_changed (fib_node_index_t fib_entry_index) { fib_entry_src_cover_res_t res = { .install = !0, .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE, }; CLIB_UNUSED(fib_source_t source); fib_source_t best_source; fib_entry_flag_t bflags; fib_entry_t *fib_entry; fib_entry_src_t *esrc; u32 index; bflags = FIB_ENTRY_FLAG_NONE; best_source = FIB_SOURCE_FIRST; fib_entry = fib_entry_get(fib_entry_index); fib_attached_export_cover_change(fib_entry); /* * propagate the notification to each of the added sources */ index = 0; FOR_EACH_SRC_ADDED(fib_entry, esrc, source, ({ if (0 == index) { /* * only the best source gets to set the back walk flags */ res = fib_entry_src_action_cover_change(fib_entry, esrc); bflags = fib_entry_src_get_flags(esrc); best_source = fib_entry_src_get_source(esrc); } else { fib_entry_src_action_cover_change(fib_entry, esrc); } index++; })); if (res.install) { fib_entry_src_action_reactivate(fib_entry, fib_entry_src_get_source( fib_entry_get_best_src_i(fib_entry))); fib_entry = fib_entry_post_install_actions(fib_entry, best_source, bflags); } else { fib_entry_src_action_uninstall(fib_entry); } if (FIB_NODE_BW_REASON_FLAG_NONE != res.bw_reason) { /* * time for walkies fido. */ fib_node_back_walk_ctx_t bw_ctx = { .fnbw_reason = res.bw_reason, }; fib_walk_sync(FIB_NODE_TYPE_ENTRY, fib_entry_index, &bw_ctx); } FIB_ENTRY_DBG(fib_entry, "cover-changed"); } /* * fib_entry_cover_updated * * this entry is tracking its cover and that cover has been updated * (i.e. its forwarding information has changed). */ void fib_entry_cover_updated (fib_node_index_t fib_entry_index) { fib_entry_src_cover_res_t res = { .install = !0, .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE, }; CLIB_UNUSED(fib_source_t source); fib_source_t best_source; fib_entry_flag_t bflags; fib_entry_t *fib_entry; fib_entry_src_t *esrc; u32 index; bflags = FIB_ENTRY_FLAG_NONE; best_source = FIB_SOURCE_FIRST; fib_entry = fib_entry_get(fib_entry_index); fib_attached_export_cover_update(fib_entry); /* * propagate the notification to each of the added sources */ index = 0; FOR_EACH_SRC_ADDED(fib_entry, esrc, source, ({ if (0 == index) { /* * only the best source gets to set the install result */ res = fib_entry_src_action_cover_update(fib_entry, esrc); bflags = fib_entry_src_get_flags(esrc); best_source = fib_entry_src_get_source(esrc); } else { /* * contirubting sources can set backwalk flags */ if (esrc->fes_flags & FIB_ENTRY_SRC_FLAG_CONTRIBUTING) { fib_entry_src_cover_res_t tmp = { .install = !0, .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE, }; tmp = fib_entry_src_action_cover_update(fib_entry, esrc); res.bw_reason |= tmp.bw_reason; } else { fib_entry_src_action_cover_update(fib_entry, esrc); } } index++; })); if (res.install) { fib_entry_src_action_reactivate(fib_entry, fib_entry_src_get_source( fib_entry_get_best_src_i(fib_entry))); fib_entry = fib_entry_post_install_actions(fib_entry, best_source, bflags); } else { fib_entry_src_action_uninstall(fib_entry); } if (FIB_NODE_BW_REASON_FLAG_NONE != res.bw_reason) { /* * time for walkies fido. */ fib_node_back_walk_ctx_t bw_ctx = { .fnbw_reason = res.bw_reason, }; fib_walk_sync(FIB_NODE_TYPE_ENTRY, fib_entry_index, &bw_ctx); } FIB_ENTRY_DBG(fib_entry, "cover-updated"); } int fib_entry_recursive_loop_detect (fib_node_index_t entry_index, fib_node_index_t **entry_indicies) { fib_entry_t *fib_entry; int was_looped, is_looped; fib_entry = fib_entry_get(entry_index); if (FIB_NODE_INDEX_INVALID != fib_entry->fe_parent) { fib_node_index_t *entries = *entry_indicies; vec_add1(entries, entry_index); was_looped = fib_path_list_is_looped(fib_entry->fe_parent); is_looped = fib_path_list_recursive_loop_detect(fib_entry->fe_parent, &entries); *entry_indicies = entries; if (!!was_looped != !!is_looped) { /* * re-evaluate all the entry's forwarding * NOTE: this is an inplace modify */ fib_entry_delegate_type_t fdt; fib_entry_delegate_t *fed; FOR_EACH_DELEGATE_CHAIN(fib_entry, fdt, fed, { fib_entry_src_mk_lb(fib_entry, fib_entry_get_best_source(entry_index), fib_entry_delegate_type_to_chain_type(fdt), &fed->fd_dpo); }); } } else { /* * the entry is currently not linked to a path-list. this happens * when it is this entry that is re-linking path-lists and has thus * broken the loop */ is_looped = 0; } return (is_looped); } u32 fib_entry_get_resolving_interface (fib_node_index_t entry_index) { fib_entry_t *fib_entry; fib_entry = fib_entry_get(entry_index); return (fib_path_list_get_resolving_interface(fib_entry->fe_parent)); } u32 fib_entry_get_any_resolving_interface (fib_node_index_t entry_index) { const fib_entry_src_t *src; fib_entry_t *fib_entry; fib_source_t source; u32 sw_if_index; fib_entry = fib_entry_get(entry_index); FOR_EACH_SRC_ADDED(fib_entry, src, source, ({ sw_if_index = fib_entry_get_resolving_interface_for_source (entry_index, source); if (~0 != sw_if_index) break; })); return (sw_if_index); } fib_source_t fib_entry_get_best_source (fib_node_index_t entry_index) { fib_entry_t *fib_entry; fib_entry_src_t *bsrc; fib_entry = fib_entry_get(entry_index); bsrc = fib_entry_get_best_src_i(fib_entry); return (fib_entry_src_get_source(bsrc)); } /** * Return !0 is the entry represents a host prefix */ int fib_entry_is_host (fib_node_index_t fib_entry_index) { return (fib_prefix_is_host(fib_entry_get_prefix(fib_entry_index))); } /** * Return !0 is the entry is resolved, i.e. will return a valid forwarding * chain */ int fib_entry_is_resolved (fib_node_index_t fib_entry_index) { fib_entry_delegate_t *fed; fib_entry_t *fib_entry; fib_entry = fib_entry_get(fib_entry_index); fed = fib_entry_delegate_find(fib_entry, FIB_ENTRY_DELEGATE_BFD); if (NULL == fed) { /* * no BFD tracking - consider it resolved. */ return (!0); } else { /* * defer to the state of the BFD tracking */ return (FIB_BFD_STATE_UP == fed->fd_bfd_state); } } void fib_entry_set_flow_hash_config (fib_node_index_t fib_entry_index, flow_hash_config_t hash_config) { fib_entry_t *fib_entry; fib_entry = fib_entry_get(fib_entry_index); /* * pass the hash-config on to the load-balance object where it is cached. * we can ignore LBs in the delegate chains, since they will not be of the * correct protocol type (i.e. they are not IP) * There's no way, nor need, to change the hash config for MPLS. */ if (dpo_id_is_valid(&fib_entry->fe_lb)) { load_balance_t *lb; ASSERT(DPO_LOAD_BALANCE == fib_entry->fe_lb.dpoi_type); lb = load_balance_get(fib_entry->fe_lb.dpoi_index); /* * atomic update for packets in flight */ lb->lb_hash_config = hash_config; } } u32 fib_entry_get_stats_index (fib_node_index_t fib_entry_index) { fib_entry_t *fib_entry; fib_entry = fib_entry_get(fib_entry_index); return (fib_entry->fe_lb.dpoi_index); } static int fib_ip4_address_compare (const ip4_address_t * a1, const ip4_address_t * a2) { /* * IP addresses are unsigned ints. the return value here needs to be signed * a simple subtraction won't cut it. * If the addresses are the same, the sort order is undefined, so phoey. */ return ((clib_net_to_host_u32(a1->data_u32) > clib_net_to_host_u32(a2->data_u32) ) ? 1 : -1); } static int fib_ip6_address_compare (const ip6_address_t * a1, const ip6_address_t * a2) { int i; for (i = 0; i < ARRAY_LEN (a1->as_u16); i++) { int cmp = (clib_net_to_host_u16 (a1->as_u16[i]) - clib_net_to_host_u16 (a2->as_u16[i])); if (cmp != 0) return cmp; } return 0; } static int fib_entry_cmp (fib_node_index_t fib_entry_index1, fib_node_index_t fib_entry_index2) { fib_entry_t *fib_entry1, *fib_entry2; int cmp = 0; fib_entry1 = fib_entry_get(fib_entry_index1); fib_entry2 = fib_entry_get(fib_entry_index2); switch (fib_entry1->fe_prefix.fp_proto) { case FIB_PROTOCOL_IP4: cmp = fib_ip4_address_compare(&fib_entry1->fe_prefix.fp_addr.ip4, &fib_entry2->fe_prefix.fp_addr.ip4); break; case FIB_PROTOCOL_IP6: cmp = fib_ip6_address_compare(&fib_entry1->fe_prefix.fp_addr.ip6, &fib_entry2->fe_prefix.fp_addr.ip6); break; case FIB_PROTOCOL_MPLS: cmp = (fib_entry1->fe_prefix.fp_label - fib_entry2->fe_prefix.fp_label); if (0 == cmp) { cmp = (fib_entry1->fe_prefix.fp_eos - fib_entry2->fe_prefix.fp_eos); } break; } if (0 == cmp) { cmp = (fib_entry1->fe_prefix.fp_len - fib_entry2->fe_prefix.fp_len); } return (cmp); } int fib_entry_cmp_for_sort (void *i1, void *i2) { fib_node_index_t *fib_entry_index1 = i1, *fib_entry_index2 = i2; return (fib_entry_cmp(*fib_entry_index1, *fib_entry_index2)); } void fib_entry_lock (fib_node_index_t fib_entry_index) { fib_entry_t *fib_entry; fib_entry = fib_entry_get(fib_entry_index); fib_node_lock(&fib_entry->fe_node); } void fib_entry_unlock (fib_node_index_t fib_entry_index) { fib_entry_t *fib_entry; fib_entry = fib_entry_get(fib_entry_index); fib_node_unlock(&fib_entry->fe_node); } void fib_entry_module_init (void) { fib_node_register_type(FIB_NODE_TYPE_ENTRY, &fib_entry_vft); fib_entry_logger = vlib_log_register_class("fib", "entry"); fib_entry_track_module_init(); } fib_route_path_t * fib_entry_encode (fib_node_index_t fib_entry_index) { fib_path_ext_list_t *ext_list; fib_path_encode_ctx_t ctx = { .rpaths = NULL, }; fib_entry_t *fib_entry; fib_entry_src_t *bsrc; ext_list = NULL; fib_entry = fib_entry_get(fib_entry_index); bsrc = fib_entry_get_best_src_i(fib_entry); if (bsrc) { ext_list = &bsrc->fes_path_exts; } if (FIB_NODE_INDEX_INVALID != fib_entry->fe_parent) { fib_path_list_walk_w_ext(fib_entry->fe_parent, ext_list, fib_path_encode, &ctx); } return (ctx.rpaths); } const fib_prefix_t * fib_entry_get_prefix (fib_node_index_t fib_entry_index) { fib_entry_t *fib_entry; fib_entry = fib_entry_get(fib_entry_index); return (&fib_entry->fe_prefix); } u32 fib_entry_get_fib_index (fib_node_index_t fib_entry_index) { fib_entry_t *fib_entry; fib_entry = fib_entry_get(fib_entry_index); return (fib_entry->fe_fib_index); } u32 fib_entry_pool_size (void) { return (pool_elts(fib_entry_pool)); } #if CLIB_DEBUG > 0 void fib_table_assert_empty (const fib_table_t *fib_table) { fib_node_index_t *fei, *feis = NULL; fib_entry_t *fib_entry; pool_foreach (fib_entry, fib_entry_pool) { if (fib_entry->fe_fib_index == fib_table->ft_index) vec_add1 (feis, fib_entry_get_index(fib_entry)); } if (vec_len(feis)) { vec_foreach (fei, feis) clib_error ("%U", format_fib_entry, *fei, FIB_ENTRY_FORMAT_DETAIL); } ASSERT(0); } #endif static clib_error_t * show_fib_entry_command (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { fib_node_index_t fei; if (unformat (input, "%d", &fei)) { /* * show one in detail */ if (!pool_is_free_index(fib_entry_pool, fei)) { vlib_cli_output (vm, "%d@%U", fei, format_fib_entry, fei, FIB_ENTRY_FORMAT_DETAIL2); } else { vlib_cli_output (vm, "entry %d invalid", fei); } } else { /* * show all */ vlib_cli_output (vm, "FIB Entries:"); pool_foreach_index (fei, fib_entry_pool) { vlib_cli_output (vm, "%d@%U", fei, format_fib_entry, fei, FIB_ENTRY_FORMAT_BRIEF); } } return (NULL); } VLIB_CLI_COMMAND (show_fib_entry, static) = { .path = "show fib entry", .function = show_fib_entry_command, .short_help = "show fib entry", };