/* * 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_source_names[] = 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_source (u8 * s, va_list * args) { fib_source_t source = va_arg (*args, int); s = format (s, "src:%s", fib_source_names[source]); return (s); } 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_MAX); } static fib_entry_flag_t fib_entry_src_get_flags (const fib_entry_src_t *esrc) { if (NULL != esrc) { return (esrc->fes_entry_flags); } return (FIB_ENTRY_FLAG_NONE); } fib_entry_flag_t fib_entry_get_flags (fib_node_index_t fib_entry_index) { return (fib_entry_get_flags_i(fib_entry_get(fib_entry_index))); } /* * fib_entry_back_walk_notify * * A back walk has reach this entry. */ static fib_node_back_walk_rc_t fib_entry_back_walk_notify (fib_node_t *node, fib_node_back_walk_ctx_t *ctx) { fib_entry_t *fib_entry; fib_entry = fib_entry_from_fib_node(node); if (FIB_NODE_BW_REASON_FLAG_EVALUATE & ctx->fnbw_reason || FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE & ctx->fnbw_reason || FIB_NODE_BW_REASON_FLAG_ADJ_DOWN & ctx->fnbw_reason || FIB_NODE_BW_REASON_FLAG_INTERFACE_UP & ctx->fnbw_reason || FIB_NODE_BW_REASON_FLAG_INTERFACE_DOWN & ctx->fnbw_reason || FIB_NODE_BW_REASON_FLAG_INTERFACE_DELETE & ctx->fnbw_reason) { fib_entry_src_action_reactivate(fib_entry, fib_entry_get_best_source( fib_entry_get_index(fib_entry))); } /* * all other walk types can be reclassifed to a re-evaluate to * all recursive dependents. * By reclassifying we ensure that should any of these walk types meet * they can be merged. */ ctx->fnbw_reason = FIB_NODE_BW_REASON_FLAG_EVALUATE; /* * ... and nothing is forced sync from now on. */ ctx->fnbw_flags &= ~FIB_NODE_BW_FLAG_FORCE_SYNC; FIB_ENTRY_DBG(fib_entry, "bw:%U", format_fib_node_bw_reason, ctx->fnbw_reason); /* * propagate the backwalk further if we haven't already reached the * maximum depth. */ fib_walk_sync(FIB_N
/*
 * Copyright (c) 2015 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.
 */
/*
  Copyright (c) 2005 Eliot Dresselhaus

  Permission is hereby granted, free of charge, to any person obtaining
  a copy of this software and associated documentation files (the
  "Software"), to deal in the Software without restriction, including
  without limitation the rights to use, copy, modify, merge, publish,
  distribute, sublicense, and/or sell copies of the Software, and to
  permit persons to whom the Software is furnished to do so, subject to
  the following conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include <vppinfra/format.h>
#include <vppinfra/socket.h>

static int verbose;
#define if_verbose(format,args...) \
  if (verbose) { clib_warning(format, ## args); }

int
test_socket_main (unformat_input_t * input)
{
  clib_socket_t _s = { 0 }, *s = &_s;
  char *config;
  clib_error_t *error;

  s->config = "localhost:22";
  s->flags = SOCKET_IS_CLIENT;

  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (input, "server %s %=", &config,
		    &s->flags, SOCKET_IS_SERVER))
	;
      else if (unformat (input, "client %s %=", &config,
			 &s->flags, SOCKET_IS_CLIENT))
	;
      else
	{
	  error = clib_error_create ("unknown input `%U'\n",
				     format_unformat_error, input);
	  goto done;
	}
    }

  error = clib_socket_init (s);
  if (error)
    goto done;

  if (0)
    {
      struct
      {
	int a, b;
      } *msg;
      msg = clib_socket_tx_add (s, sizeof (msg[0]));
      msg->a = 99;
      msg->b = 100;
    }
  else
    clib_socket_tx_add_formatted (s, "hello there mr server %d\n", 99);

  error = clib_socket_tx (s);
  if (error)
    goto done;

  while (1)
    {
      error = clib_socket_rx (s, 100);
      if (error)
	break;

      if (clib_socket_rx_end_of_file (s))
	break;

      if_verbose ("%v", s->rx_buffer);
      _vec_len (s->rx_buffer) = 0;
    }

  error = clib_socket_close (s);

done:
  if (error)
    clib_error_report (error);
  return 0;
}

#ifdef CLIB_UNIX
int
main (int argc, char *argv[])
{
  unformat_input_t i;
  int r;

  verbose = (argc > 1);
  unformat_init_command_line (&i, argv);
  r = test_socket_main (&i);
  unformat_free (&i);
  return r;
}
#endif

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */
RC_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); } } else { 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); } } 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_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 back walk flags */ 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 { 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_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_src_i(fib_entry), 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)); } 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)); } 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", };