FIB Memory Usage Diagnostics 35/3235/3
authorNeale Ranns <nranns@cisco.com>
Sun, 2 Oct 2016 20:20:15 +0000 (21:20 +0100)
committerDamjan Marion <dmarion.lists@gmail.com>
Mon, 3 Oct 2016 19:15:01 +0000 (19:15 +0000)
add two new CLI commands:
 show fib memory
 show dpo memory
to display the memory usage of the FIB and DPO object types respectively.

Change-Id: I759e149a0b6fbb58d59c139362221dc33531cffa
Signed-off-by: Neale Ranns <nranns@cisco.com>
27 files changed:
vnet/Makefile.am
vnet/vnet/adj/adj.c
vnet/vnet/adj/adj.h
vnet/vnet/adj/adj_alloc.c [deleted file]
vnet/vnet/adj/adj_alloc.h [deleted file]
vnet/vnet/adj/adj_glean.c
vnet/vnet/adj/adj_internal.h
vnet/vnet/adj/adj_midchain.c
vnet/vnet/adj/adj_nbr.c
vnet/vnet/adj/adj_rewrite.c
vnet/vnet/dpo/classify_dpo.c
vnet/vnet/dpo/dpo.c
vnet/vnet/dpo/dpo.h
vnet/vnet/dpo/load_balance.c
vnet/vnet/dpo/lookup_dpo.c
vnet/vnet/dpo/mpls_label_dpo.c
vnet/vnet/dpo/receive_dpo.c
vnet/vnet/fib/fib_entry.c
vnet/vnet/fib/fib_entry.h
vnet/vnet/fib/fib_node.c
vnet/vnet/fib/fib_node.h
vnet/vnet/fib/fib_node_list.c
vnet/vnet/fib/fib_node_list.h
vnet/vnet/fib/fib_path.c
vnet/vnet/fib/fib_path_list.c
vnet/vnet/ip/lookup.c
vnet/vnet/ip/lookup.h

index 6aa4254..1b7b969 100644 (file)
@@ -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                         \
index b552fdb..8f9d96e 100644 (file)
@@ -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;
 }
index 3a12364..002dab3 100644 (file)
@@ -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 (file)
index 5cc8cf6..0000000
+++ /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 (file)
index 7d1a3fb..0000000
+++ /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__ */
index 6eb6718..f5d1810 100644 (file)
@@ -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);
index f2d0ce0..25a477a 100644 (file)
  * 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,
index 562a90d..c40d4e8 100644 (file)
@@ -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);
 }
 
 /**
index 0913cfd..23e40a6 100644 (file)
@@ -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,
index db802e3..eb93f6a 100644 (file)
@@ -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));
 }
index 3b7b98f..93f3f0a 100644 (file)
@@ -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[] =
index 5eff52b..9f09dff 100644 (file)
@@ -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* */
index 452a07e..7ba4756 100644 (file)
@@ -300,6 +300,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
  */
@@ -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
index 1250694..093661d 100644 (file)
@@ -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,
 };
 
 /**
index 6e3f079..f775417 100644 (file)
@@ -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.
index 0ec840e..532d044 100644 (file)
@@ -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[] =
index ee7d82b..ad78850 100644 (file)
@@ -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,
 };
 
 /**
index a75d5c9..1821319 100644 (file)
@@ -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,
 };
 
 /*
@@ -516,14 +545,6 @@ fib_entry_get_path_list (fib_node_index_t fib_entry_index)
     return (fib_entry->fe_parent);
 }
 
-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,
index 1ed9d61..1016bb2 100644 (file)
@@ -261,6 +261,11 @@ _Static_assert (sizeof(fib_entry_src_flag_t) <= 2,
  * Information related to the source of a FIB entry
  */
 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
      */
@@ -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);
 
index 8ac67d2..5ecc9a7 100644 (file)
@@ -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* */
index 6a54c6f..2f9a107 100644 (file)
@@ -219,6 +219,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
  */
@@ -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);
index 1d2e75e..ceb951b 100644 (file)
  */
 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
      */
@@ -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));
+}
index afee3c6..9567b96 100644 (file)
@@ -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
index d5453fd..03cc7be 100644 (file)
@@ -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
index 3523d93..611fe9f 100644 (file)
@@ -451,6 +451,18 @@ fib_path_list_back_walk_notify (fib_node_t *node,
     return (FIB_NODE_BACK_WALK_CONTINUE);
 }
 
+/*
+ * 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
  */
@@ -458,6 +470,7 @@ 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 *
index a695ef7..5cfdc23 100644 (file)
@@ -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 &&
index a21e181..97f776c 100644 (file)
@@ -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;
 }