summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--vnet/Makefile.am1
-rw-r--r--vnet/vnet/adj/adj.c50
-rw-r--r--vnet/vnet/adj/adj.h6
-rw-r--r--vnet/vnet/adj/adj_alloc.c236
-rw-r--r--vnet/vnet/adj/adj_alloc.h53
-rw-r--r--vnet/vnet/adj/adj_glean.c11
-rw-r--r--vnet/vnet/adj/adj_internal.h20
-rw-r--r--vnet/vnet/adj/adj_midchain.c2
-rw-r--r--vnet/vnet/adj/adj_nbr.c22
-rw-r--r--vnet/vnet/adj/adj_rewrite.c5
-rw-r--r--vnet/vnet/dpo/classify_dpo.c10
-rw-r--r--vnet/vnet/dpo/dpo.c44
-rw-r--r--vnet/vnet/dpo/dpo.h19
-rw-r--r--vnet/vnet/dpo/load_balance.c11
-rw-r--r--vnet/vnet/dpo/lookup_dpo.c17
-rw-r--r--vnet/vnet/dpo/mpls_label_dpo.c10
-rw-r--r--vnet/vnet/dpo/receive_dpo.c10
-rw-r--r--vnet/vnet/fib/fib_entry.c37
-rw-r--r--vnet/vnet/fib/fib_entry.h14
-rw-r--r--vnet/vnet/fib/fib_node.c59
-rw-r--r--vnet/vnet/fib/fib_node.h23
-rw-r--r--vnet/vnet/fib/fib_node_list.c23
-rw-r--r--vnet/vnet/fib/fib_node_list.h3
-rw-r--r--vnet/vnet/fib/fib_path.c10
-rw-r--r--vnet/vnet/fib/fib_path_list.c13
-rw-r--r--vnet/vnet/ip/lookup.c7
-rw-r--r--vnet/vnet/ip/lookup.h4
27 files changed, 333 insertions, 387 deletions
diff --git a/vnet/Makefile.am b/vnet/Makefile.am
index 6aa4254f2af..1b7b96911f9 100644
--- a/vnet/Makefile.am
+++ b/vnet/Makefile.am
@@ -777,7 +777,6 @@ nobase_include_HEADERS += \
########################################
libvnet_la_SOURCES += \
- vnet/adj/adj_alloc.c \
vnet/adj/adj_nbr.c \
vnet/adj/adj_rewrite.c \
vnet/adj/adj_glean.c \
diff --git a/vnet/vnet/adj/adj.c b/vnet/vnet/adj/adj.c
index b552fdb2bbc..8f9d96efd60 100644
--- a/vnet/vnet/adj/adj.c
+++ b/vnet/vnet/adj/adj.c
@@ -14,7 +14,6 @@
*/
#include <vnet/adj/adj.h>
-#include <vnet/adj/adj_alloc.h>
#include <vnet/adj/adj_internal.h>
#include <vnet/adj/adj_glean.h>
#include <vnet/adj/adj_midchain.h>
@@ -30,16 +29,17 @@ static ip_adjacency_t *special_v4_miss_adj_with_index_zero;
/* Adjacency packet/byte counters indexed by adjacency index. */
vlib_combined_counter_main_t adjacency_counters;
+/*
+ * the single adj pool
+ */
+ip_adjacency_t *adj_pool;
+
always_inline void
adj_poison (ip_adjacency_t * adj)
{
if (CLIB_DEBUG > 0)
{
- u32 save_handle = adj->heap_handle;;
-
memset (adj, 0xfe, sizeof (adj[0]));
-
- adj->heap_handle = save_handle;
}
}
@@ -48,14 +48,14 @@ adj_alloc (fib_protocol_t proto)
{
ip_adjacency_t *adj;
- adj = aa_alloc();
+ pool_get(adj_pool, adj);
adj_poison(adj);
/* Make sure certain fields are always initialized. */
/* Validate adjacency counters. */
vlib_validate_combined_counter(&adjacency_counters,
- adj->heap_handle);
+ adj_get_index(adj));
adj->rewrite_header.sw_if_index = ~0;
adj->mcast_group_index = ~0;
@@ -66,6 +66,9 @@ adj_alloc (fib_protocol_t proto)
FIB_NODE_TYPE_ADJ);
adj->ia_nh_proto = proto;
+ ip4_main.lookup_main.adjacency_heap = adj_pool;
+ ip6_main.lookup_main.adjacency_heap = adj_pool;
+
return (adj);
}
@@ -166,7 +169,7 @@ adj_last_lock_gone (ip_adjacency_t *adj)
}
fib_node_deinit(&adj->ia_node);
- aa_free(adj);
+ pool_put(adj_pool, adj);
}
void
@@ -181,7 +184,6 @@ adj_lock (adj_index_t adj_index)
adj = adj_get(adj_index);
ASSERT(adj);
- ASSERT(adj->heap_handle!=0);
ADJ_DBG(adj, "lock");
fib_node_lock(&adj->ia_node);
@@ -199,11 +201,9 @@ adj_unlock (adj_index_t adj_index)
adj = adj_get(adj_index);
ASSERT(adj);
- ASSERT(adj->heap_handle!=0);
ADJ_DBG(adj, "unlock");
ASSERT(adj);
- ASSERT(adj->heap_handle!=0);
fib_node_unlock(&adj->ia_node);
}
@@ -291,7 +291,6 @@ adj_module_init (vlib_main_t * vm)
/*
* 4 special adjs for v4 and v6 resp.
*/
- aa_bootstrap(8);
special_v4_miss_adj_with_index_zero = adj_alloc(FIB_PROTOCOL_IP4);
return (NULL);
@@ -311,33 +310,14 @@ ip_add_adjacency (ip_lookup_main_t * lm,
u32 * adj_index_return)
{
ip_adjacency_t * adj;
- u32 ai, i, handle;
ASSERT(1==n_adj);
- adj = aa_alloc ();
- handle = ai = adj->heap_handle;
+ adj = adj_alloc(FIB_PROTOCOL_IP4);
- /* Validate adjacency counters. */
- vlib_validate_combined_counter (&adjacency_counters, ai + n_adj - 1);
-
- for (i = 0; i < n_adj; i++)
- {
- /* Make sure certain fields are always initialized. */
- adj[i].rewrite_header.sw_if_index = ~0;
- adj[i].mcast_group_index = ~0;
- adj[i].saved_lookup_next_index = 0;
-
- if (copy_adj)
- adj[i] = copy_adj[i];
-
- adj[i].heap_handle = handle;
- adj[i].n_adj = n_adj;
-
- /* Zero possibly stale counters for re-used adjacencies. */
- vlib_zero_combined_counter (&adjacency_counters, ai + i);
- }
+ if (copy_adj)
+ *adj = *copy_adj;
- *adj_index_return = ai;
+ *adj_index_return = adj_get_index(adj);
return adj;
}
diff --git a/vnet/vnet/adj/adj.h b/vnet/vnet/adj/adj.h
index 3a1236497e1..002dab359ab 100644
--- a/vnet/vnet/adj/adj.h
+++ b/vnet/vnet/adj/adj.h
@@ -77,9 +77,9 @@ extern void adj_child_remove(adj_index_t adj_index,
/**
* @brief
- * The global adjacnecy heap. Exposed for fast/inline data-plane access
+ * The global adjacnecy pool. Exposed for fast/inline data-plane access
*/
-extern ip_adjacency_t *adj_heap;
+extern ip_adjacency_t *adj_pool;
/**
* @brief
@@ -94,7 +94,7 @@ extern vlib_combined_counter_main_t adjacency_counters;
static inline ip_adjacency_t *
adj_get (adj_index_t adj_index)
{
- return (vec_elt_at_index(adj_heap, adj_index));
+ return (vec_elt_at_index(adj_pool, adj_index));
}
#endif
diff --git a/vnet/vnet/adj/adj_alloc.c b/vnet/vnet/adj/adj_alloc.c
deleted file mode 100644
index 5cc8cf6ef04..00000000000
--- a/vnet/vnet/adj/adj_alloc.c
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * 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 <vnet/adj/adj_alloc.h>
-#include <vnet/ip/ip.h>
-
-/*
- * the single adj heap
- */
-ip_adjacency_t *adj_heap;
-
-/*
- * any operation which could cause the adj vector to be reallocated
- * must have a worker thread barrier
- */
-static inline int will_reallocate (ip_adjacency_t * adjs, u32 n)
-{
- uword aligned_header_bytes, new_data_bytes;
- uword data_bytes;
- aa_header_t * ah = aa_header (adjs);
-
- if (adjs == 0)
- return 1;
-
- data_bytes = (vec_len (adjs) + n) * sizeof (*adjs);
-
- aligned_header_bytes = vec_header_bytes (aa_aligned_header_bytes);
-
- new_data_bytes = data_bytes + aligned_header_bytes;
-
- ASSERT (clib_mem_is_heap_object (_vec_find(ah)));
-
- if (PREDICT_TRUE(new_data_bytes <= clib_mem_size (_vec_find(ah))))
- return 0;
-
- return 1;
-}
-
-ip_adjacency_t *
-aa_alloc (void)
-{
- vlib_main_t * vm = &vlib_global_main;
- aa_header_t * ah = aa_header (adj_heap);
- ip_adjacency_t * adj_block;
- u32 freelist_length;
- int need_barrier_sync = 0;
- u32 n = 1;
-
- ASSERT(os_get_cpu_number() == 0);
- ASSERT (clib_mem_is_heap_object (_vec_find(ah)));
-
- /* If we don't have a freelist of size N, fresh allocation is required */
- if (vec_len (ah->free_indices_by_size) <= n)
- {
- if (will_reallocate (adj_heap, n))
- {
- need_barrier_sync = 1;
- vlib_worker_thread_barrier_sync (vm);
- }
- /* Workers wont look at the freelists... */
- vec_validate (ah->free_indices_by_size, n);
- vec_add2_ha (adj_heap, adj_block, n, aa_aligned_header_bytes,
- CLIB_CACHE_LINE_BYTES);
- if (need_barrier_sync)
- vlib_worker_thread_barrier_release (vm);
- goto out;
- }
- /* See if we have a free adj block to dole out */
- if ((freelist_length = vec_len(ah->free_indices_by_size[n])))
- {
- u32 index = ah->free_indices_by_size[n][freelist_length-1];
-
- adj_block = &adj_heap[index];
- _vec_len(ah->free_indices_by_size[n]) -= 1;
- goto out;
- }
- /* Allocate a new block of size N */
- if (will_reallocate (adj_heap, n))
- {
- need_barrier_sync = 1;
- vlib_worker_thread_barrier_sync (vm);
- }
- vec_add2_ha (adj_heap, adj_block, n, aa_aligned_header_bytes,
- CLIB_CACHE_LINE_BYTES);
-
- if (need_barrier_sync)
- vlib_worker_thread_barrier_release (vm);
-
- out:
- memset (adj_block, 0, n * (sizeof(*adj_block)));
- adj_block->heap_handle = adj_block - adj_heap;
- adj_block->n_adj = n;
-
- /*
- * the adj heap may have realloc'd. recache.
- */
- ip4_main.lookup_main.adjacency_heap = adj_heap;
- ip6_main.lookup_main.adjacency_heap = adj_heap;
-
- return (adj_block);
-}
-
-void aa_free (ip_adjacency_t * adj)
-{
- aa_header_t * ah = aa_header (adj_heap);
-
- ASSERT (adj_heap && adj && (adj->heap_handle < vec_len (adj_heap)));
- ASSERT (adj->heap_handle != 0);
-
- vec_add1 (ah->free_indices_by_size[adj->n_adj], adj->heap_handle);
- adj->heap_handle = 0;
-}
-
-void aa_bootstrap (u32 n)
-{
- ip_adjacency_t * adj_block;
- aa_header_t * ah;
- int i;
-
- vec_add2_ha (adj_heap, adj_block, n, aa_aligned_header_bytes,
- CLIB_CACHE_LINE_BYTES);
-
- memset (adj_block, 0, n * sizeof(*adj_block));
- ah = aa_header (adj_heap);
- memset (ah, 0, sizeof (*ah));
-
- vec_validate (ah->free_indices_by_size, 1);
-
- for (i = 0 ; i < vec_len (adj_heap); i++)
- {
- adj_block->n_adj = 1;
- adj_block->heap_handle = ~0;
- /* Euchre the allocator into returning 0, 1, 2, etc. */
- vec_add1 (ah->free_indices_by_size[1], n - (i+1));
- }
-
- ip4_main.lookup_main.adjacency_heap = adj_heap;
- ip6_main.lookup_main.adjacency_heap = adj_heap;
-}
-
-u8 * format_adjacency_alloc (u8 * s, va_list * args)
-{
- vnet_main_t * vnm = va_arg (*args, vnet_main_t *);
- int verbose = va_arg (*args, int);
- ip_adjacency_t * adj;
- u32 inuse = 0, freed = 0;
- u32 on_freelist = 0;
- int i, j;
- aa_header_t * ah = aa_header (adj_heap);
-
- for (i = 0; i < vec_len (adj_heap); i += adj->n_adj)
- {
- adj = adj_heap + i;
- if ((i == 0) || adj->heap_handle)
- inuse += adj->n_adj;
- else
- freed += adj->n_adj;
- }
-
- for (i = 1; i < vec_len(ah->free_indices_by_size); i++)
- {
- for (j = 0; j < vec_len(ah->free_indices_by_size[i]); j++)
- {
- adj = adj_heap + ah->free_indices_by_size[i][j];
- ASSERT(adj->heap_handle == 0);
- on_freelist += adj->n_adj;
- }
- }
-
- s = format (s, "adj_heap: %d total, %d in use, %d free, %d on freelists\n",
- vec_len(adj_heap), inuse, freed, on_freelist);
- if (verbose)
- {
- for (i = 0; i < vec_len (adj_heap); i += adj->n_adj)
- {
- adj = adj_heap + i;
- if ((i == 0) || adj->heap_handle)
- {
- if (adj->n_adj > 1)
- s = format (s, "[%d-%d] ", i, i+adj->n_adj-1);
- else
- s = format (s, "[%d] ", i);
-
- for (j = 0; j < adj->n_adj; j++)
- {
- if (j > 0)
- s = format (s, " ");
-
- s = format(s, "%U\n", format_ip_adjacency,
- vnm, i+j, FORMAT_IP_ADJACENCY_NONE);
- }
- }
- }
- }
- return s;
-}
-
-static clib_error_t *
-show_adjacency_alloc_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- int verbose = 0;
- vnet_main_t *vnm = vnet_get_main();
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "verbose"))
- verbose = 1;
- else
- return clib_error_return (0, "unknown input `%U'",
- format_unformat_error, input);
- }
-
- vlib_cli_output (vm, "%U", format_adjacency_alloc, vnm, verbose);
-
- return 0;
-}
-
-VLIB_CLI_COMMAND (show_adjacency_alloc_command, static) = {
- .path = "show adjacency alloc",
- .short_help = "show adjacency alloc",
- .function = show_adjacency_alloc_command_fn,
-};
diff --git a/vnet/vnet/adj/adj_alloc.h b/vnet/vnet/adj/adj_alloc.h
deleted file mode 100644
index 7d1a3fb3133..00000000000
--- a/vnet/vnet/adj/adj_alloc.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef __adj_alloc_h__
-#define __adj_alloc_h__
-
-/**
- * @brief
- * Adjacency allocator: heap-like in that the code
- * will dole out contiguous chunks of n items. In the interests of
- * thread safety, we don't bother about coalescing free blocks of size r
- * into free blocks of size s, where r < s.
- *
- * We include explicit references to worker thread barrier synchronization
- * where necessary.
- */
-
-#include <vppinfra/vec.h>
-#include <vlib/vlib.h>
-#include <vnet/ip/lookup.h>
-
-typedef struct {
- u32 ** free_indices_by_size;
-} aa_header_t;
-
-#define aa_aligned_header_bytes \
- vec_aligned_header_bytes (sizeof (aa_header_t), sizeof (void *))
-
-/* Pool header from user pointer */
-static inline aa_header_t * aa_header (void * v)
-{
- return vec_aligned_header (v, sizeof (aa_header_t), sizeof (void *));
-}
-
-extern ip_adjacency_t *aa_alloc(void);
-extern void aa_free (ip_adjacency_t * adj);
-extern void aa_bootstrap (u32 n);
-
-format_function_t format_adj_allocation;
-
-#endif /* __adj_alloc_h__ */
diff --git a/vnet/vnet/adj/adj_glean.c b/vnet/vnet/adj/adj_glean.c
index 6eb6718e216..f5d181018b6 100644
--- a/vnet/vnet/adj/adj_glean.c
+++ b/vnet/vnet/adj/adj_glean.c
@@ -14,7 +14,6 @@
*/
#include <vnet/adj/adj.h>
-#include <vnet/adj/adj_alloc.h>
#include <vnet/adj/adj_internal.h>
#include <vnet/fib/fib_walk.h>
@@ -62,7 +61,7 @@ adj_glean_add_or_lock (fib_protocol_t proto,
adj->lookup_next_index = IP_LOOKUP_NEXT_GLEAN;
adj->ia_nh_proto = proto;
- adj_gleans[proto][sw_if_index] = adj->heap_handle;
+ adj_gleans[proto][sw_if_index] = adj_get_index(adj);
if (NULL != nh_addr)
{
@@ -84,9 +83,9 @@ adj_glean_add_or_lock (fib_protocol_t proto,
adj = adj_get(adj_gleans[proto][sw_if_index]);
}
- adj_lock(adj->heap_handle);
+ adj_lock(adj_get_index(adj));
- return (adj->heap_handle);
+ return (adj_get_index(adj));
}
void
@@ -124,7 +123,7 @@ adj_glean_interface_state_change (vnet_main_t * vnm,
FIB_NODE_BW_REASON_FLAG_INTERFACE_DOWN),
};
- fib_walk_sync(FIB_NODE_TYPE_ADJ, adj->heap_handle, &bw_ctx);
+ fib_walk_sync(FIB_NODE_TYPE_ADJ, adj_get_index(adj), &bw_ctx);
}
return (NULL);
@@ -173,7 +172,7 @@ adj_glean_interface_delete (vnet_main_t * vnm,
.fnbw_reason = FIB_NODE_BW_REASON_FLAG_INTERFACE_DELETE,
};
- fib_walk_sync(FIB_NODE_TYPE_ADJ, adj->heap_handle, &bw_ctx);
+ fib_walk_sync(FIB_NODE_TYPE_ADJ, adj_get_index(adj), &bw_ctx);
}
return (NULL);
diff --git a/vnet/vnet/adj/adj_internal.h b/vnet/vnet/adj/adj_internal.h
index f2d0ce0dbb2..25a477ad007 100644
--- a/vnet/vnet/adj/adj_internal.h
+++ b/vnet/vnet/adj/adj_internal.h
@@ -31,11 +31,11 @@
* Debug macro
*/
#ifdef ADJ_DEBUG
-#define ADJ_DBG(_adj, _fmt, _args...) \
-{ \
- clib_warning("adj:[%d:%p]:" _fmt, \
- _adj->heap_handle, _adj, \
- ##_args); \
+#define ADJ_DBG(_adj, _fmt, _args...) \
+{ \
+ clib_warning("adj:[%d:%p]:" _fmt, \
+ _adj - adj_pool, _adj, \
+ ##_args); \
}
#else
#define ADJ_DBG(_e, _fmt, _args...)
@@ -90,6 +90,16 @@ adj_fib_proto_2_nd (fib_protocol_t fp)
return (0);
}
+/**
+ * @brief
+ * Get a pointer to an adjacency object from its index
+ */
+static inline adj_index_t
+adj_get_index (ip_adjacency_t *adj)
+{
+ return (adj - adj_pool);
+}
+
extern ip_adjacency_t * adj_alloc(fib_protocol_t proto);
extern void adj_nbr_remove(fib_protocol_t nh_proto,
diff --git a/vnet/vnet/adj/adj_midchain.c b/vnet/vnet/adj/adj_midchain.c
index 562a90d6e1d..c40d4e8bca5 100644
--- a/vnet/vnet/adj/adj_midchain.c
+++ b/vnet/vnet/adj/adj_midchain.c
@@ -405,7 +405,7 @@ adj_nbr_midchain_update_rewrite (adj_index_t adj_index,
.fnbw_reason = FIB_NODE_BW_REASON_ADJ_UPDATE,
};
- fib_walk_sync(FIB_NODE_TYPE_ADJ, adj->heap_handle, &bw_ctx);
+ fib_walk_sync(FIB_NODE_TYPE_ADJ, adj_get_index(adj), &bw_ctx);
}
/**
diff --git a/vnet/vnet/adj/adj_nbr.c b/vnet/vnet/adj/adj_nbr.c
index 0913cfd791c..23e40a6850c 100644
--- a/vnet/vnet/adj/adj_nbr.c
+++ b/vnet/vnet/adj/adj_nbr.c
@@ -275,7 +275,7 @@ adj_nbr_alloc (fib_protocol_t nh_proto,
adj_nbr_insert(nh_proto, link_type, nh_addr,
sw_if_index,
- adj->heap_handle);
+ adj_get_index(adj));
/*
* since we just added the ADJ we have no rewrite string for it,
@@ -362,9 +362,9 @@ adj_nbr_add_or_lock (fib_protocol_t nh_proto,
adj = adj_get(adj_index);
}
- adj_lock(adj->heap_handle);
+ adj_lock(adj_get_index(adj));
- return (adj->heap_handle);
+ return (adj_get_index(adj));
}
adj_index_t
@@ -389,10 +389,10 @@ adj_nbr_add_or_lock_w_rewrite (fib_protocol_t nh_proto,
adj = adj_get(adj_index);
}
- adj_lock(adj->heap_handle);
- adj_nbr_update_rewrite(adj->heap_handle, rewrite);
+ adj_lock(adj_get_index(adj));
+ adj_nbr_update_rewrite(adj_get_index(adj), rewrite);
- return (adj->heap_handle);
+ return (adj_get_index(adj));
}
/**
@@ -760,10 +760,20 @@ adj_dpo_unlock (dpo_id_t *dpo)
adj_unlock(dpo->dpoi_index);
}
+static void
+adj_mem_show (void)
+{
+ fib_show_memory_usage("Adjacency",
+ pool_elts(adj_pool),
+ pool_len(adj_pool),
+ sizeof(ip_adjacency_t));
+}
+
const static dpo_vft_t adj_nbr_dpo_vft = {
.dv_lock = adj_dpo_lock,
.dv_unlock = adj_dpo_unlock,
.dv_format = format_adj_nbr,
+ .dv_mem_show = adj_mem_show,
};
const static dpo_vft_t adj_nbr_incompl_dpo_vft = {
.dv_lock = adj_dpo_lock,
diff --git a/vnet/vnet/adj/adj_rewrite.c b/vnet/vnet/adj/adj_rewrite.c
index db802e33665..eb93f6a4377 100644
--- a/vnet/vnet/adj/adj_rewrite.c
+++ b/vnet/vnet/adj/adj_rewrite.c
@@ -14,7 +14,6 @@
*/
#include <vnet/adj/adj.h>
-#include <vnet/adj/adj_alloc.h>
#include <vnet/adj/adj_internal.h>
/**
@@ -46,7 +45,7 @@ adj_rewrite_add_and_lock (fib_protocol_t nh_proto,
&adj->rewrite_header,
sizeof (adj->rewrite_data));
- adj_lock(adj->heap_handle);
+ adj_lock(adj_get_index(adj));
- return (adj->heap_handle);
+ return (adj_get_index(adj));
}
diff --git a/vnet/vnet/dpo/classify_dpo.c b/vnet/vnet/dpo/classify_dpo.c
index 3b7b98f9da8..93f3f0ae275 100644
--- a/vnet/vnet/dpo/classify_dpo.c
+++ b/vnet/vnet/dpo/classify_dpo.c
@@ -90,10 +90,20 @@ classify_dpo_unlock (dpo_id_t *dpo)
}
}
+static void
+classify_dpo_mem_show (void)
+{
+ fib_show_memory_usage("Classify",
+ pool_elts(classify_dpo_pool),
+ pool_len(classify_dpo_pool),
+ sizeof(classify_dpo_t));
+}
+
const static dpo_vft_t cd_vft = {
.dv_lock = classify_dpo_lock,
.dv_unlock = classify_dpo_unlock,
.dv_format = format_classify_dpo,
+ .dv_mem_show = classify_dpo_mem_show,
};
const static char* const classify_ip4_nodes[] =
diff --git a/vnet/vnet/dpo/dpo.c b/vnet/vnet/dpo/dpo.c
index 5eff52b7b8a..9f09dff81d1 100644
--- a/vnet/vnet/dpo/dpo.c
+++ b/vnet/vnet/dpo/dpo.c
@@ -422,3 +422,47 @@ dpo_module_init (vlib_main_t * vm)
}
VLIB_INIT_FUNCTION(dpo_module_init);
+
+static clib_error_t *
+dpo_memory_show (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ dpo_vft_t *vft;
+
+ vlib_cli_output (vm, "DPO memory");
+ vlib_cli_output (vm, "%=30s %=5s %=8s/%=9s totals",
+ "Name","Size", "in-use", "allocated");
+
+ vec_foreach(vft, dpo_vfts)
+ {
+ if (NULL != vft->dv_mem_show)
+ vft->dv_mem_show();
+ }
+
+ return (NULL);
+}
+
+/* *INDENT-OFF* */
+/*?
+ * The '<em>sh dpo memory </em>' command displays the memory usage for each
+ * data-plane object type.
+ *
+ * @cliexpar
+ * @cliexstart{show dpo memory}
+ * DPO memory
+ * Name Size in-use /allocated totals
+ * load-balance 64 12 / 12 768/768
+ * Adjacency 256 1 / 1 256/256
+ * Receive 24 5 / 5 120/120
+ * Lookup 12 0 / 0 0/0
+ * Classify 12 0 / 0 0/0
+ * MPLS label 24 0 / 0 0/0
+ * @cliexend
+?*/
+VLIB_CLI_COMMAND (show_fib_memory, static) = {
+ .path = "show dpo memory",
+ .function = dpo_memory_show,
+ .short_help = "show dpo memory",
+};
+/* *INDENT-ON* */
diff --git a/vnet/vnet/dpo/dpo.h b/vnet/vnet/dpo/dpo.h
index 452a07e3104..7ba47569d8d 100644
--- a/vnet/vnet/dpo/dpo.h
+++ b/vnet/vnet/dpo/dpo.h
@@ -301,6 +301,11 @@ typedef void (*dpo_lock_fn_t)(dpo_id_t *dpo);
typedef void (*dpo_unlock_fn_t)(dpo_id_t *dpo);
/**
+ * @brief An memory usage show command
+ */
+typedef void (*dpo_mem_show_t)(void);
+
+/**
* @brief A virtual function table regisitered for a DPO type
*/
typedef struct dpo_vft_t_
@@ -317,6 +322,10 @@ typedef struct dpo_vft_t_
* A format function
*/
format_function_t *dv_format;
+ /**
+ * A show memory usage function
+ */
+ dpo_mem_show_t dv_mem_show;
} dpo_vft_t;
@@ -337,9 +346,9 @@ typedef struct dpo_vft_t_
* @param nodes
* The string description of the per-protocol VLIB graph nodes.
*/
-void dpo_register(dpo_type_t type,
- const dpo_vft_t *vft,
- const char * const * const * nodes);
+extern void dpo_register(dpo_type_t type,
+ const dpo_vft_t *vft,
+ const char * const * const * nodes);
/**
* @brief Create and register a new DPO type.
@@ -355,7 +364,7 @@ void dpo_register(dpo_type_t type,
*
* @return The new dpo_type_t
*/
-dpo_type_t dpo_register_new_type(const dpo_vft_t *vft,
- const char * const * const * nodes);
+extern dpo_type_t dpo_register_new_type(const dpo_vft_t *vft,
+ const char * const * const * nodes);
#endif
diff --git a/vnet/vnet/dpo/load_balance.c b/vnet/vnet/dpo/load_balance.c
index 1250694a9e3..093661d8578 100644
--- a/vnet/vnet/dpo/load_balance.c
+++ b/vnet/vnet/dpo/load_balance.c
@@ -19,7 +19,6 @@
#include <vnet/dpo/drop_dpo.h>
#include <vppinfra/math.h> /* for fabs */
#include <vnet/adj/adj.h>
-#include <vnet/adj/adj_alloc.h>
#include <vnet/adj/adj_internal.h>
/*
@@ -671,10 +670,20 @@ load_balance_unlock (dpo_id_t *dpo)
}
}
+static void
+load_balance_mem_show (void)
+{
+ fib_show_memory_usage("load-balance",
+ pool_elts(load_balance_pool),
+ pool_len(load_balance_pool),
+ sizeof(load_balance_t));
+}
+
const static dpo_vft_t lb_vft = {
.dv_lock = load_balance_lock,
.dv_unlock = load_balance_unlock,
.dv_format = format_load_balance_dpo,
+ .dv_mem_show = load_balance_mem_show,
};
/**
diff --git a/vnet/vnet/dpo/lookup_dpo.c b/vnet/vnet/dpo/lookup_dpo.c
index 6e3f0792d07..f775417287c 100644
--- a/vnet/vnet/dpo/lookup_dpo.c
+++ b/vnet/vnet/dpo/lookup_dpo.c
@@ -734,11 +734,26 @@ VLIB_REGISTER_NODE (lookup_mpls_dst_itf_node) = {
};
VLIB_NODE_FUNCTION_MULTIARCH (lookup_mpls_dst_itf_node, lookup_mpls_dst_itf)
+static void
+lookup_dpo_mem_show (void)
+{
+ fib_show_memory_usage("Lookup",
+ pool_elts(lookup_dpo_pool),
+ pool_len(lookup_dpo_pool),
+ sizeof(lookup_dpo_t));
+}
+
const static dpo_vft_t lkd_vft = {
.dv_lock = lookup_dpo_lock,
.dv_unlock = lookup_dpo_unlock,
.dv_format = format_lookup_dpo,
};
+const static dpo_vft_t lkd_vft_w_mem_show = {
+ .dv_lock = lookup_dpo_lock,
+ .dv_unlock = lookup_dpo_unlock,
+ .dv_format = format_lookup_dpo,
+ .dv_mem_show = lookup_dpo_mem_show,
+};
const static char* const lookup_src_ip4_nodes[] =
{
@@ -805,7 +820,7 @@ const static char* const * const lookup_dst_from_interface_nodes[DPO_PROTO_NUM]
void
lookup_dpo_module_init (void)
{
- dpo_register(DPO_LOOKUP, &lkd_vft, NULL);
+ dpo_register(DPO_LOOKUP, &lkd_vft_w_mem_show, NULL);
/*
* There are various sorts of lookup; src or dst addr v4 /v6 etc.
diff --git a/vnet/vnet/dpo/mpls_label_dpo.c b/vnet/vnet/dpo/mpls_label_dpo.c
index 0ec840ecfbd..532d0447db6 100644
--- a/vnet/vnet/dpo/mpls_label_dpo.c
+++ b/vnet/vnet/dpo/mpls_label_dpo.c
@@ -227,10 +227,20 @@ VLIB_REGISTER_NODE (mpls_label_imposition_node) = {
};
VLIB_NODE_FUNCTION_MULTIARCH (mpls_label_imposition_node, mpls_label_imposition)
+static void
+mpls_label_dpo_mem_show (void)
+{
+ fib_show_memory_usage("MPLS label",
+ pool_elts(mpls_label_dpo_pool),
+ pool_len(mpls_label_dpo_pool),
+ sizeof(mpls_label_dpo_t));
+}
+
const static dpo_vft_t mld_vft = {
.dv_lock = mpls_label_dpo_lock,
.dv_unlock = mpls_label_dpo_unlock,
.dv_format = format_mpls_label_dpo,
+ .dv_mem_show = mpls_label_dpo_mem_show,
};
const static char* const mpls_label_imp_ip4_nodes[] =
diff --git a/vnet/vnet/dpo/receive_dpo.c b/vnet/vnet/dpo/receive_dpo.c
index ee7d82b0980..ad78850daf3 100644
--- a/vnet/vnet/dpo/receive_dpo.c
+++ b/vnet/vnet/dpo/receive_dpo.c
@@ -117,10 +117,20 @@ format_receive_dpo (u8 *s, va_list *ap)
}
}
+static void
+receive_dpo_mem_show (void)
+{
+ fib_show_memory_usage("Receive",
+ pool_elts(receive_dpo_pool),
+ pool_len(receive_dpo_pool),
+ sizeof(receive_dpo_t));
+}
+
const static dpo_vft_t receive_vft = {
.dv_lock = receive_dpo_lock,
.dv_unlock = receive_dpo_unlock,
.dv_format = format_receive_dpo,
+ .dv_mem_show = receive_dpo_mem_show,
};
/**
diff --git a/vnet/vnet/fib/fib_entry.c b/vnet/vnet/fib/fib_entry.c
index a75d5c9cf8c..1821319dbf7 100644
--- a/vnet/vnet/fib/fib_entry.c
+++ b/vnet/vnet/fib/fib_entry.c
@@ -435,6 +435,34 @@ fib_entry_back_walk_notify (fib_node_t *node,
return (FIB_NODE_BACK_WALK_CONTINUE);
}
+static void
+fib_entry_show_memory (void)
+{
+ u32 n_srcs = 0, n_exts = 0;
+ fib_entry_src_t *esrc;
+ fib_entry_t *entry;
+
+ fib_show_memory_usage("Entry",
+ pool_elts(fib_entry_pool),
+ pool_len(fib_entry_pool),
+ sizeof(fib_entry_t));
+
+ pool_foreach(entry, fib_entry_pool,
+ ({
+ n_srcs += vec_len(entry->fe_srcs);
+ vec_foreach(esrc, entry->fe_srcs)
+ {
+ n_exts += vec_len(esrc->fes_path_exts);
+ }
+ }));
+
+ fib_show_memory_usage("Entry Source",
+ n_srcs, n_srcs, sizeof(fib_entry_src_t));
+ fib_show_memory_usage("Entry Path-Extensions",
+ n_exts, n_exts,
+ sizeof(fib_path_ext_t));
+}
+
/*
* The FIB path-list's graph node virtual function table
*/
@@ -442,6 +470,7 @@ static const fib_node_vft_t fib_entry_vft = {
.fnv_get = fib_entry_get_node,
.fnv_last_lock = fib_entry_last_lock_gone,
.fnv_back_walk = fib_entry_back_walk_notify,
+ .fnv_mem_show = fib_entry_show_memory,
};
/*
@@ -517,14 +546,6 @@ fib_entry_get_path_list (fib_node_index_t fib_entry_index)
}
u32
-fib_entry_get_fib_table_id(fib_node_index_t fib_entry_index)
-{
-
-
- return (0);
-}
-
-u32
fib_entry_child_add (fib_node_index_t fib_entry_index,
fib_node_type_t child_type,
fib_node_index_t child_index)
diff --git a/vnet/vnet/fib/fib_entry.h b/vnet/vnet/fib/fib_entry.h
index 1ed9d619515..1016bb21948 100644
--- a/vnet/vnet/fib/fib_entry.h
+++ b/vnet/vnet/fib/fib_entry.h
@@ -262,6 +262,11 @@ _Static_assert (sizeof(fib_entry_src_flag_t) <= 2,
*/
typedef struct fib_entry_src_t_ {
/**
+ * A vector of path extensions
+ */
+ struct fib_path_ext_t_ *fes_path_exts;
+
+ /**
* The path-list created by the source
*/
fib_node_index_t fes_pl;
@@ -273,10 +278,6 @@ typedef struct fib_entry_src_t_ {
* Flags on the source
*/
fib_entry_src_flag_t fes_flags;
- /**
- * Flags the source contributes to the entry
- */
- fib_entry_flag_t fes_entry_flags;
/**
* 1 bytes ref count. This is not the number of users of the Entry
@@ -286,9 +287,9 @@ typedef struct fib_entry_src_t_ {
u8 fes_ref_count;
/**
- * A vector of path extensions
+ * Flags the source contributes to the entry
*/
- struct fib_path_ext_t_ *fes_path_exts;
+ fib_entry_flag_t fes_entry_flags;
/**
* Source specific info
@@ -502,7 +503,6 @@ extern int fib_entry_is_sourced(fib_node_index_t fib_entry_index,
fib_source_t source);
extern fib_node_index_t fib_entry_get_path_list(fib_node_index_t fib_entry_index);
-extern u32 fib_entry_get_fib_table_id(fib_node_index_t fib_entry_index);
extern void fib_entry_module_init(void);
diff --git a/vnet/vnet/fib/fib_node.c b/vnet/vnet/fib/fib_node.c
index 8ac67d2ef92..5ecc9a7fb2f 100644
--- a/vnet/vnet/fib/fib_node.c
+++ b/vnet/vnet/fib/fib_node.c
@@ -205,3 +205,62 @@ fib_node_unlock (fib_node_t *node)
node->fn_vft->fnv_last_lock(node);
}
}
+
+void
+fib_show_memory_usage (const char *name,
+ u32 in_use_elts,
+ u32 allocd_elts,
+ size_t size_elt)
+{
+ vlib_cli_output (vlib_get_main(), "%=30s %=5d %=8d/%=9d %d/%d ",
+ name, size_elt,
+ in_use_elts, allocd_elts,
+ in_use_elts*size_elt, allocd_elts*size_elt);
+}
+
+static clib_error_t *
+fib_memory_show (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ fib_node_vft_t *vft;
+
+ vlib_cli_output (vm, "FIB memory");
+ vlib_cli_output (vm, "%=30s %=5s %=8s/%=9s totals",
+ "Name","Size", "in-use", "allocated");
+
+ vec_foreach(vft, fn_vfts)
+ {
+ if (NULL != vft->fnv_mem_show)
+ vft->fnv_mem_show();
+ }
+
+ fib_node_list_memory_show();
+
+ return (NULL);
+}
+
+/* *INDENT-OFF* */
+/*?
+ * The '<em>sh fib memory </em>' command displays the memory usage for each
+ * FIB object type.
+ *
+ * @cliexpar
+ * @cliexstart{show fib memory}
+ * FIB memory
+ * Name Size in-use /allocated totals
+ * Entry 120 11 / 11 1320/1320
+ * Entry Source 32 11 / 11 352/352
+ * Entry Path-Extensions 44 0 / 0 0/0
+ * Path-list 40 11 / 11 440/440
+ * Path 88 11 / 11 968/968
+ * Node-list elements 20 11 / 11 220/220
+ * Node-list heads 8 13 / 13 104/104
+ * @cliexend
+?*/
+VLIB_CLI_COMMAND (show_fib_memory, static) = {
+ .path = "show fib memory",
+ .function = fib_memory_show,
+ .short_help = "show fib memory",
+};
+/* *INDENT-ON* */
diff --git a/vnet/vnet/fib/fib_node.h b/vnet/vnet/fib/fib_node.h
index 6a54c6f565b..2f9a107ab8b 100644
--- a/vnet/vnet/fib/fib_node.h
+++ b/vnet/vnet/fib/fib_node.h
@@ -220,6 +220,12 @@ typedef struct fib_node_t_* (*fib_node_get_t)(fib_node_index_t index);
typedef void (*fib_node_last_lock_gone_t)(struct fib_node_t_ *node);
/**
+ * Function definition to display the amount of memory used by a type.
+ * Implementations should call fib_show_memory_usage()
+ */
+typedef void (*fib_node_memory_show_t)(void);
+
+/**
* A FIB graph nodes virtual function table
*/
typedef struct fib_node_vft_t_ {
@@ -227,6 +233,7 @@ typedef struct fib_node_vft_t_ {
fib_node_last_lock_gone_t fnv_last_lock;
fib_node_back_walk_t fnv_back_walk;
format_function_t *fnv_format;
+ fib_node_memory_show_t fnv_mem_show;
} fib_node_vft_t;
/**
@@ -284,6 +291,22 @@ extern void fib_node_register_type (fib_node_type_t ft,
*/
extern fib_node_type_t fib_node_register_new_type (const fib_node_vft_t *vft);
+/**
+ * @brief Show the memory usage for a type
+ *
+ * This should be invoked by the type in response to the infra calling
+ * its registered memory show function
+ *
+ * @param name the name of the type
+ * @param in_use_elts The number of elements in use
+ * @param allocd_elts The number of allocated pool elemenets
+ * @param size_elt The size of one element
+ */
+extern void fib_show_memory_usage(const char *name,
+ u32 in_use_elts,
+ u32 allocd_elts,
+ size_t size_elt);
+
extern void fib_node_init(fib_node_t *node,
fib_node_type_t ft);
extern void fib_node_deinit(fib_node_t *node);
diff --git a/vnet/vnet/fib/fib_node_list.c b/vnet/vnet/fib/fib_node_list.c
index 1d2e75ecec2..ceb951b466b 100644
--- a/vnet/vnet/fib/fib_node_list.c
+++ b/vnet/vnet/fib/fib_node_list.c
@@ -26,12 +26,6 @@
typedef struct fib_node_list_elt_t_
{
/**
- * An opaque indentifier set by the FIB node owning this element
- * that will allow the owner to identify which element it is.
- */
- int fnle_owner_id;
-
- /**
* The index of the list this element is in
*/
fib_node_list_t fnle_list;
@@ -108,7 +102,6 @@ fib_node_list_elt_create (fib_node_list_head_t *head,
pool_get(fib_node_list_elt_pool, elt);
elt->fnle_list = fib_node_list_head_get_index(head);
- elt->fnle_owner_id = id;
elt->fnle_owner.fnp_type = type;
elt->fnle_owner.fnp_index = index;
@@ -126,8 +119,7 @@ fib_node_list_head_init (fib_node_list_head_t *head)
}
/**
- * @brief Create a new node list. The expectation is that these are few in number
- * so straight from the memory subsystem
+ * @brief Create a new node list.
*/
fib_node_list_t
fib_node_list_create (void)
@@ -383,3 +375,16 @@ fib_node_list_walk (fib_node_list_t list,
fn(&elt->fnle_owner, args);
}
}
+
+void
+fib_node_list_memory_show (void)
+{
+ fib_show_memory_usage("Node-list elements",
+ pool_elts(fib_node_list_elt_pool),
+ pool_len(fib_node_list_elt_pool),
+ sizeof(fib_node_list_elt_t));
+ fib_show_memory_usage("Node-list heads",
+ pool_elts(fib_node_list_head_pool),
+ pool_len(fib_node_list_head_pool),
+ sizeof(fib_node_list_head_t));
+}
diff --git a/vnet/vnet/fib/fib_node_list.h b/vnet/vnet/fib/fib_node_list.h
index afee3c6152c..9567b9669e8 100644
--- a/vnet/vnet/fib/fib_node_list.h
+++ b/vnet/vnet/fib/fib_node_list.h
@@ -58,4 +58,7 @@ typedef int (*fib_node_list_walk_cb_t)(fib_node_ptr_t *owner,
extern void fib_node_list_walk(fib_node_list_t head,
fib_node_list_walk_cb_t fn,
void *args);
+
+extern void fib_node_list_memory_show(void);
+
#endif
diff --git a/vnet/vnet/fib/fib_path.c b/vnet/vnet/fib/fib_path.c
index d5453fde256..03cc7be5d9c 100644
--- a/vnet/vnet/fib/fib_path.c
+++ b/vnet/vnet/fib/fib_path.c
@@ -848,6 +848,15 @@ FIXME comment
return (FIB_NODE_BACK_WALK_CONTINUE);
}
+static void
+fib_path_memory_show (void)
+{
+ fib_show_memory_usage("Path",
+ pool_elts(fib_path_pool),
+ pool_len(fib_path_pool),
+ sizeof(fib_path_t));
+}
+
/*
* The FIB path's graph node virtual function table
*/
@@ -855,6 +864,7 @@ static const fib_node_vft_t fib_path_vft = {
.fnv_get = fib_path_get_node,
.fnv_last_lock = fib_path_last_lock_gone,
.fnv_back_walk = fib_path_back_walk_notify,
+ .fnv_mem_show = fib_path_memory_show,
};
static fib_path_cfg_flags_t
diff --git a/vnet/vnet/fib/fib_path_list.c b/vnet/vnet/fib/fib_path_list.c
index 3523d93a7bb..611fe9fb5ae 100644
--- a/vnet/vnet/fib/fib_path_list.c
+++ b/vnet/vnet/fib/fib_path_list.c
@@ -452,12 +452,25 @@ fib_path_list_back_walk_notify (fib_node_t *node,
}
/*
+ * Display the path-list memory usage
+ */
+static void
+fib_path_list_memory_show (void)
+{
+ fib_show_memory_usage("Path-list",
+ pool_elts(fib_path_list_pool),
+ pool_len(fib_path_list_pool),
+ sizeof(fib_path_list_t));
+}
+
+/*
* The FIB path-list's graph node virtual function table
*/
static const fib_node_vft_t fib_path_list_vft = {
.fnv_get = fib_path_list_get_node,
.fnv_last_lock = fib_path_list_last_lock_gone,
.fnv_back_walk = fib_path_list_back_walk_notify,
+ .fnv_mem_show = fib_path_list_memory_show,
};
static fib_path_list_t *
diff --git a/vnet/vnet/ip/lookup.c b/vnet/vnet/ip/lookup.c
index a695ef765a0..5cfdc23ea01 100644
--- a/vnet/vnet/ip/lookup.c
+++ b/vnet/vnet/ip/lookup.c
@@ -38,7 +38,7 @@
*/
#include <vnet/ip/ip.h>
-#include <vnet/adj/adj_alloc.h>
+#include <vnet/adj/adj.h>
#include <vnet/fib/fib_table.h>
#include <vnet/fib/ip4_fib.h>
#include <vnet/fib/ip6_fib.h>
@@ -162,7 +162,7 @@ void ip_lookup_init (ip_lookup_main_t * lm, u32 is_ip6)
ASSERT(STRUCT_OFFSET_OF(ip_adjacency_t, cacheline1) == CLIB_CACHE_LINE_BYTES);
/* Preallocate three "special" adjacencies */
- lm->adjacency_heap = adj_heap;
+ lm->adjacency_heap = adj_pool;
if (! lm->fib_result_n_bytes)
lm->fib_result_n_bytes = sizeof (uword);
@@ -345,6 +345,7 @@ vnet_ip_route_cmd (vlib_main_t * vm,
is_del = 0;
table_id = 0;
count = 1;
+ memset(&pfx, 0, sizeof(pfx));
/* Get a line of input. */
if (! unformat_user (main_input, unformat_line_input, line_input))
@@ -353,7 +354,6 @@ vnet_ip_route_cmd (vlib_main_t * vm,
while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
{
memset(&rpath, 0, sizeof(rpath));
- memset(&pfx, 0, sizeof(pfx));
if (unformat (line_input, "table %d", &table_id))
;
@@ -510,6 +510,7 @@ vnet_ip_route_cmd (vlib_main_t * vm,
{
rpath.frp_label = MPLS_LABEL_INVALID;
rpath.frp_proto = pfx.fp_proto;
+ rpath.frp_sw_if_index = ~0;
vec_add1(rpaths, rpath);
}
else if (vec_len (prefixs) > 0 &&
diff --git a/vnet/vnet/ip/lookup.h b/vnet/vnet/ip/lookup.h
index a21e1810983..97f776cb09d 100644
--- a/vnet/vnet/ip/lookup.h
+++ b/vnet/vnet/ip/lookup.h
@@ -173,8 +173,6 @@ typedef void (*adj_midchain_fixup_t)(vlib_main_t * vm,
*/
typedef struct ip_adjacency_t_ {
CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
- /* Handle for this adjacency in adjacency heap. */
- u32 heap_handle;
/** Number of adjecencies in block. Greater than 1 means multipath;
otherwise equal to 1. */
@@ -399,8 +397,6 @@ ip_get_adjacency (ip_lookup_main_t * lm,
adj = vec_elt_at_index (lm->adjacency_heap, adj_index);
- ASSERT (adj->heap_handle != ~0);
-
return adj;
}