Separate heap for IPv4 mtries

Change-Id: I497e9f6489dd35219bcf2b51ac992467aac4c8eb
Signed-off-by: Neale Ranns <nranns@cisco.com>
diff --git a/src/vnet/fib/fib.c b/src/vnet/fib/fib.c
index b430e11..413f93e 100644
--- a/src/vnet/fib/fib.c
+++ b/src/vnet/fib/fib.c
@@ -28,8 +28,6 @@
 	return (error);
     if ((error = vlib_call_init_function (vm, adj_module_init)))
 	return (error);
-    if ((error = vlib_call_init_function (vm, ip4_mtrie_module_init)))
-	return (error);
 
     fib_entry_module_init();
     fib_entry_src_module_init();
diff --git a/src/vnet/fib/ip4_fib.c b/src/vnet/fib/ip4_fib.c
index 45f1974..0f2d3f7 100644
--- a/src/vnet/fib/ip4_fib.c
+++ b/src/vnet/fib/ip4_fib.c
@@ -106,11 +106,14 @@
 {
     fib_table_t *fib_table;
     ip4_fib_t *v4_fib;
+    void *old_heap;
 
     pool_get_aligned(ip4_main.fibs, fib_table, CLIB_CACHE_LINE_BYTES);
     memset(fib_table, 0, sizeof(*fib_table));
 
+    old_heap = clib_mem_set_heap (ip4_main.mtrie_mheap);
     pool_get_aligned(ip4_main.v4_fibs, v4_fib, CLIB_CACHE_LINE_BYTES);
+    clib_mem_set_heap (old_heap);
 
     ASSERT((fib_table - ip4_main.fibs) ==
            (v4_fib - ip4_main.v4_fibs));
@@ -326,12 +329,17 @@
 	/*
 	 * adding a new entry
 	 */
+        uword *old_heap;
+        old_heap = clib_mem_set_heap (ip4_main.mtrie_mheap);
+
 	if (NULL == hash) {
 	    hash = hash_create (32 /* elts */, sizeof (uword));
 	    hash_set_flags (hash, HASH_FLAG_NO_AUTO_SHRINK);
+
 	}
 	hash = hash_set(hash, key, fib_entry_index);
 	fib->fib_entry_by_dst_address[len] = hash;
+        clib_mem_set_heap (old_heap);
     }
     else
     {
@@ -359,7 +367,11 @@
     }
     else 
     {
+        uword *old_heap;
+
+        old_heap = clib_mem_set_heap (ip4_main.mtrie_mheap);
 	hash_unset(hash, key);
+        clib_mem_set_heap (old_heap);
     }
 
     fib->fib_entry_by_dst_address[len] = hash;
@@ -484,36 +496,10 @@
 u8 *
 format_ip4_fib_table_memory (u8 * s, va_list * args)
 {
-    fib_table_t *fib_table;
-    u64 total_memory;
-
-    total_memory = 0;
-
-    pool_foreach (fib_table, ip4_main.fibs,
-    ({
-	ip4_fib_t *fib;
-        uword fib_size;
-        int i;
-
-        fib = pool_elt_at_index(ip4_main.v4_fibs, fib_table->ft_index);
-        fib_size = ip4_fib_mtrie_memory_usage(&fib->mtrie);
-
-        for (i = 0; i < ARRAY_LEN (fib->fib_entry_by_dst_address); i++)
-        {
-            uword * hash = fib->fib_entry_by_dst_address[i];
-
-            if (NULL != hash)
-            {
-                fib_size += hash_bytes(hash);
-            }
-        }
-
-        total_memory += fib_size;
-    }));
-
     s = format(s, "%=30s %=6d %=8ld\n",
                "IPv4 unicast",
-               pool_elts(ip4_main.fibs), total_memory);
+               pool_elts(ip4_main.fibs),
+               mheap_bytes(ip4_main.mtrie_mheap));
 
     return (s);
 }
diff --git a/src/vnet/ip/ip4.h b/src/vnet/ip/ip4.h
index 4c5cc05..f7e5fe3 100644
--- a/src/vnet/ip/ip4.h
+++ b/src/vnet/ip/ip4.h
@@ -148,6 +148,12 @@
 
     u8 pad[2];
   } host_config;
+
+  /** Heapsize for the Mtries */
+  uword mtrie_heap_size;
+
+  /** The memory heap for the mtries */
+  void *mtrie_mheap;
 } ip4_main_t;
 
 /** Global ip4 main structure. */
diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c
index d7afc84..c7cf362 100755
--- a/src/vnet/ip/ip4_forward.c
+++ b/src/vnet/ip/ip4_forward.c
@@ -1189,6 +1189,12 @@
 
   if ((error = vlib_call_init_function (vm, vnet_feature_init)))
     return error;
+  if ((error = vlib_call_init_function (vm, ip4_mtrie_module_init)))
+    return (error);
+  if ((error = vlib_call_init_function (vm, fib_module_init)))
+    return error;
+  if ((error = vlib_call_init_function (vm, mfib_module_init)))
+    return error;
 
   for (i = 0; i < ARRAY_LEN (im->fib_masks); i++)
     {
@@ -3166,6 +3172,29 @@
 };
 /* *INDENT-ON* */
 
+static clib_error_t *
+ip4_config (vlib_main_t * vm, unformat_input_t * input)
+{
+  ip4_main_t *im = &ip4_main;
+  uword heapsize = 0;
+
+  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (input, "heap-size %U", unformat_memory_size, &heapsize))
+	;
+      else
+	return clib_error_return (0,
+				  "invalid heap-size parameter `%U'",
+				  format_unformat_error, input);
+    }
+
+  im->mtrie_heap_size = heapsize;
+
+  return 0;
+}
+
+VLIB_EARLY_CONFIG_FUNCTION (ip4_config, "ip");
+
 /*
  * fd.io coding-style-patch-verification: ON
  *
diff --git a/src/vnet/ip/ip4_mtrie.c b/src/vnet/ip/ip4_mtrie.c
index 5b78cbe..5981a3c 100644
--- a/src/vnet/ip/ip4_mtrie.c
+++ b/src/vnet/ip/ip4_mtrie.c
@@ -176,9 +176,12 @@
 	    u32 leaf_prefix_len, u32 ply_base_len)
 {
   ip4_fib_mtrie_8_ply_t *p;
-
+  void *old_heap;
   /* Get cache aligned ply. */
+
+  old_heap = clib_mem_set_heap (ip4_main.mtrie_mheap);
   pool_get_aligned (ip4_ply_pool, p, CLIB_CACHE_LINE_BYTES);
+  clib_mem_set_heap (old_heap);
 
   ply_8_init (p, init_leaf, leaf_prefix_len, ply_base_len);
   return ip4_fib_mtrie_leaf_set_next_ply_index (p - ip4_ply_pool);
@@ -796,15 +799,27 @@
   return s;
 }
 
+/** Default heap size for the IPv4 mtries */
+#define IP4_FIB_DEFAULT_MTRIE_HEAP_SIZE (32<<20)
+
 static clib_error_t *
 ip4_mtrie_module_init (vlib_main_t * vm)
 {
-  /* Burn one ply so index 0 is taken */
   CLIB_UNUSED (ip4_fib_mtrie_8_ply_t * p);
+  ip4_main_t *im = &ip4_main;
+  clib_error_t *error = NULL;
+  uword *old_heap;
 
+  if (0 == im->mtrie_heap_size)
+    im->mtrie_heap_size = IP4_FIB_DEFAULT_MTRIE_HEAP_SIZE;
+  im->mtrie_mheap = mheap_alloc (0, im->mtrie_heap_size);
+
+  /* Burn one ply so index 0 is taken */
+  old_heap = clib_mem_set_heap (ip4_main.mtrie_mheap);
   pool_get (ip4_ply_pool, p);
+  clib_mem_set_heap (old_heap);
 
-  return (NULL);
+  return (error);
 }
 
 VLIB_INIT_FUNCTION (ip4_mtrie_module_init);
diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c
index a14bf09..67fedc9 100644
--- a/src/vnet/ip/ip6_forward.c
+++ b/src/vnet/ip/ip6_forward.c
@@ -3494,14 +3494,9 @@
     {
       if (unformat (input, "hash-buckets %d", &tmp))
 	nbuckets = tmp;
-      else if (unformat (input, "heap-size %dm", &tmp))
-	heapsize = ((u64) tmp) << 20;
-      else if (unformat (input, "heap-size %dM", &tmp))
-	heapsize = ((u64) tmp) << 20;
-      else if (unformat (input, "heap-size %dg", &tmp))
-	heapsize = ((u64) tmp) << 30;
-      else if (unformat (input, "heap-size %dG", &tmp))
-	heapsize = ((u64) tmp) << 30;
+      else if (unformat (input, "heap-size %U",
+			 unformat_memory_size, &heapsize))
+	;
       else
 	return clib_error_return (0, "unknown input '%U'",
 				  format_unformat_error, input);
diff --git a/src/vnet/mfib/mfib_table.c b/src/vnet/mfib/mfib_table.c
index dc51b7c..82431e3 100644
--- a/src/vnet/mfib/mfib_table.c
+++ b/src/vnet/mfib/mfib_table.c
@@ -642,14 +642,14 @@
 {
     clib_error_t * error;
 
+    mfib_entry_module_init();
+    mfib_signal_module_init();
+
     if ((error = vlib_call_init_function (vm, fib_module_init)))
         return (error);
     if ((error = vlib_call_init_function (vm, rn_module_init)))
         return (error);
 
-    mfib_entry_module_init();
-    mfib_signal_module_init();
-
     return (error);
 }