session: segment manager improvements

- cleanup connects segment manager even if first
- fix segment manager allocation for listen sessions
- improve handling of process private segments (mheaps/main heap)
- added segment manager cli

Change-Id: Ic2ca97c3622ab2286d5fb5772aeb57680e64f769
Signed-off-by: Florin Coras <fcoras@cisco.com>
Signed-off-by: Dave Wallace <dwallacelf@gmail.com>
diff --git a/src/svm/svm_fifo_segment.c b/src/svm/svm_fifo_segment.c
index 2094ba7..6600a42 100644
--- a/src/svm/svm_fifo_segment.c
+++ b/src/svm/svm_fifo_segment.c
@@ -188,7 +188,7 @@
       return (rv);
     }
 
-  /* Note; requested_va updated due to seg base addr randomization */
+  /* Note: requested_va updated due to seg base addr randomization */
   sm->next_baseva = s->ssvm.requested_va + a->segment_size;
 
   sh = s->ssvm.sh;
@@ -200,7 +200,6 @@
   sh->opaque[0] = fsh;
   s->h = fsh;
   fsh->segment_name = format (0, "%s%c", a->segment_name, 0);
-
   preallocate_fifo_pairs (fsh, a);
 
   ssvm_pop_heap (oldheap);
@@ -226,25 +225,19 @@
 
   if (a->private_segment_count && a->private_segment_size)
     {
-      void *mem;
       u8 *heap;
       u32 pagesize = clib_mem_get_page_size ();
       u32 rnd_size;
+      rnd_size = (a->private_segment_size + (pagesize - 1)) & ~pagesize;
 
       for (i = 0; i < a->private_segment_count; i++)
 	{
-	  rnd_size = (a->private_segment_size + (pagesize - 1)) & ~pagesize;
-
-	  mem = mmap (0, rnd_size, PROT_READ | PROT_WRITE,
-		      MAP_PRIVATE | MAP_ANONYMOUS,
-		      -1 /* fd */ , 0 /* offset */ );
-
-	  if (mem == MAP_FAILED)
+	  heap = mheap_alloc (0, rnd_size);
+	  if (heap == 0)
 	    {
-	      clib_unix_warning ("mmap");
+	      clib_unix_warning ("mheap alloc");
 	      return -1;
 	    }
-	  heap = mheap_alloc (mem, rnd_size);
 	  heap_header = mheap_header (heap);
 	  heap_header->flags |= MHEAP_FLAG_THREAD_SAFE;
 	  vec_add1 (heaps, heap);
@@ -279,6 +272,9 @@
       memset (fsh, 0, sizeof (*fsh));
       sh->opaque[0] = fsh;
       s->h = fsh;
+      fsh->flags = FIFO_SEGMENT_F_IS_PRIVATE;
+      if (!a->private_segment_count)
+	fsh->flags |= FIFO_SEGMENT_F_IS_MAIN_HEAP;
       fsh->segment_name = format (0, "%s%c", a->segment_name, 0);
 
       if (a->private_segment_count)
@@ -288,7 +284,6 @@
 	  preallocate_fifo_pairs (fsh, a);
 	  clib_mem_set_heap (oldheap);
 	}
-
       sh->ready = 1;
       vec_add1 (a->new_segment_indices, s - sm->segments);
     }
@@ -336,8 +331,20 @@
 svm_fifo_segment_delete (svm_fifo_segment_private_t * s)
 {
   svm_fifo_segment_main_t *sm = &svm_fifo_segment_main;
-  ssvm_delete (&s->ssvm);
-  pool_put (sm->segments, s);
+  if (s->h->flags & FIFO_SEGMENT_F_IS_PRIVATE)
+    {
+      /* Don't try to free vpp's heap! */
+      if (!(s->h->flags & FIFO_SEGMENT_F_IS_MAIN_HEAP))
+	mheap_free (s->ssvm.sh->heap);
+      clib_mem_free (s->ssvm.sh);
+      clib_mem_free (s->h);
+      pool_put (sm->segments, s);
+    }
+  else
+    {
+      ssvm_delete (&s->ssvm);
+      pool_put (sm->segments, s);
+    }
 }
 
 svm_fifo_t *
@@ -352,8 +359,8 @@
   int freelist_index;
 
   /*
-   * 2K minimum. It's not likely that anything good will happen
-   * with a 1K FIFO.
+   * 4K minimum. It's not likely that anything good will happen
+   * with a smaller FIFO.
    */
   if (data_size_in_bytes < FIFO_SEGMENT_MIN_FIFO_SIZE ||
       data_size_in_bytes > FIFO_SEGMENT_MAX_FIFO_SIZE)
@@ -428,6 +435,7 @@
 	}
       fsh->fifos = f;
     }
+  fsh->n_active_fifos++;
 
   ssvm_pop_heap (oldheap);
   ssvm_unlock_non_recursive (sh);
@@ -489,6 +497,7 @@
       f->master_thread_index = ~0;
     }
 
+  fsh->n_active_fifos--;
   ssvm_pop_heap (oldheap);
   ssvm_unlock_non_recursive (sh);
 }
@@ -508,6 +517,25 @@
   return s - svm_fifo_segment_main.segments;
 }
 
+/**
+ * Retrieve svm segments pool. Used only for debug purposes.
+ */
+svm_fifo_segment_private_t *
+svm_fifo_segment_segments_pool (void)
+{
+  svm_fifo_segment_main_t *sm = &svm_fifo_segment_main;
+  return sm->segments;
+}
+
+/**
+ * Get number of active fifos
+ */
+u32
+svm_fifo_segment_num_fifos (svm_fifo_segment_private_t * fifo_segment)
+{
+  return fifo_segment->h->n_active_fifos;
+}
+
 /*
  * fd.io coding-style-patch-verification: ON
  *
diff --git a/src/svm/svm_fifo_segment.h b/src/svm/svm_fifo_segment.h
index 68bb4d3..5cc4754 100644
--- a/src/svm/svm_fifo_segment.h
+++ b/src/svm/svm_fifo_segment.h
@@ -27,15 +27,20 @@
   FIFO_SEGMENT_N_FREELISTS
 } svm_fifo_segment_freelist_t;
 
-#define FIFO_SEGMENT_MIN_FIFO_SIZE 2048
+#define FIFO_SEGMENT_MIN_FIFO_SIZE 4096
 #define FIFO_SEGMENT_MAX_FIFO_SIZE (8<<20)	/* 8mb max fifo size */
-#define FIFO_SEGMENT_ALLOC_CHUNK_SIZE 32	/* allocation quantum */
+#define FIFO_SEGMENT_ALLOC_CHUNK_SIZE 32	/* Allocation quantum */
+
+#define FIFO_SEGMENT_F_IS_PRIVATE 	1 << 0	/* Private segment */
+#define FIFO_SEGMENT_F_IS_MAIN_HEAP	1 << 1	/* Segment is main heap */
 
 typedef struct
 {
   svm_fifo_t *fifos;		/**< Linked list of active RX fifos */
   u8 *segment_name;		/**< Segment name */
   svm_fifo_t **free_fifos;	/**< Freelists, by fifo size  */
+  u32 n_active_fifos;		/**< Number of active fifos */
+  u8 flags;			/**< Segment flags */
 } svm_fifo_segment_header_t;
 
 typedef struct
@@ -70,7 +75,7 @@
 } svm_fifo_segment_create_args_t;
 
 static inline svm_fifo_segment_private_t *
-svm_fifo_get_segment (u32 segment_index)
+svm_fifo_segment_get_segment (u32 segment_index)
 {
   svm_fifo_segment_main_t *ssm = &svm_fifo_segment_main;
   return vec_elt_at_index (ssm->segments, segment_index);
@@ -112,6 +117,8 @@
 				 svm_fifo_segment_freelist_t index);
 void svm_fifo_segment_init (u64 baseva, u32 timeout_in_seconds);
 u32 svm_fifo_segment_index (svm_fifo_segment_private_t * s);
+u32 svm_fifo_segment_num_fifos (svm_fifo_segment_private_t * fifo_segment);
+svm_fifo_segment_private_t *svm_fifo_segment_segments_pool (void);
 
 #endif /* __included_ssvm_fifo_segment_h__ */
 
diff --git a/src/svm/test_svm_fifo1.c b/src/svm/test_svm_fifo1.c
index 63d7584..3bdca94 100644
--- a/src/svm/test_svm_fifo1.c
+++ b/src/svm/test_svm_fifo1.c
@@ -39,7 +39,7 @@
   if (rv)
     return clib_error_return (0, "svm_fifo_segment_create returned %d", rv);
 
-  sp = svm_fifo_get_segment (a->new_segment_indices[0]);
+  sp = svm_fifo_segment_get_segment (a->new_segment_indices[0]);
 
   f = svm_fifo_segment_alloc_fifo (sp, 4096, FIFO_SEGMENT_RX_FREELIST);
 
@@ -92,7 +92,7 @@
   if (rv)
     return clib_error_return (0, "svm_fifo_segment_create returned %d", rv);
 
-  sp = svm_fifo_get_segment (a->new_segment_indices[0]);
+  sp = svm_fifo_segment_get_segment (a->new_segment_indices[0]);
 
   f = svm_fifo_segment_alloc_fifo (sp, 4096, FIFO_SEGMENT_RX_FREELIST);
 
@@ -128,7 +128,7 @@
   if (rv)
     return clib_error_return (0, "svm_fifo_segment_create returned %d", rv);
 
-  sp = svm_fifo_get_segment (a->new_segment_indices[0]);
+  sp = svm_fifo_segment_get_segment (a->new_segment_indices[0]);
 
   for (i = 0; i < 1000; i++)
     {
@@ -186,7 +186,7 @@
   if (rv)
     return clib_error_return (0, "svm_fifo_segment_create returned %d", rv);
 
-  sp = svm_fifo_get_segment (a->new_segment_indices[0]);
+  sp = svm_fifo_segment_get_segment (a->new_segment_indices[0]);
 
   f = svm_fifo_segment_alloc_fifo (sp, 200 << 10, FIFO_SEGMENT_RX_FREELIST);
 
@@ -246,7 +246,7 @@
   if (rv)
     return clib_error_return (0, "svm_fifo_segment_attach returned %d", rv);
 
-  sp = svm_fifo_get_segment (a->new_segment_indices[0]);
+  sp = svm_fifo_segment_get_segment (a->new_segment_indices[0]);
   sh = sp->ssvm.sh;
   fsh = (svm_fifo_segment_header_t *) sh->opaque[0];