sctp: move to plugins, disabled by default
[vpp.git] / src / svm / fifo_segment.c
index 04b3f5a..eeb2746 100644 (file)
@@ -248,7 +248,7 @@ fs_try_alloc_fifo_freelist_multi_chunk (fifo_segment_t * fs, u32 data_bytes)
            last = c;
          c->next = first;
          first = c;
-         n_alloc += c->length;
+         n_alloc += fl_size;
          c->length = clib_min (fl_size, data_bytes);
          data_bytes -= c->length;
        }
@@ -394,6 +394,14 @@ fifo_segment_alloc_fifo (fifo_segment_t * fs, u32 data_bytes,
   /* (re)initialize the fifo, as in svm_fifo_create */
   svm_fifo_init (f, data_bytes);
 
+  /* Initialize chunks and rbtree for multi-chunk fifos */
+  if (f->start_chunk->next != f->start_chunk)
+    {
+      void *oldheap = ssvm_push_heap (fs->ssvm.sh);
+      svm_fifo_init_chunks (f);
+      ssvm_pop_heap (oldheap);
+    }
+
   /* If rx fifo type add to active fifos list. When cleaning up segment,
    * we need a list of active sessions that should be disconnected. Since
    * both rx and tx fifos keep pointers to the session, it's enough to track
@@ -468,6 +476,9 @@ fifo_segment_free_fifo (fifo_segment_t * fs, svm_fifo_t * f)
     }
   while (cur != f->start_chunk);
 
+  f->start_chunk = f->end_chunk = f->new_chunks = 0;
+  f->head_chunk = f->tail_chunk = f->ooo_enq = f->ooo_deq = 0;
+
   oldheap = ssvm_push_heap (sh);
   svm_fifo_free_chunk_lookup (f);
   ssvm_pop_heap (oldheap);
@@ -610,12 +621,16 @@ fifo_segment_preallocate_fifo_pairs (fifo_segment_t * fs,
   /* Calculate space requirements */
   pair_size = 2 * hdrs + rx_rounded_data_size + tx_rounded_data_size;
   space_available = fs_free_space (fs);
-  pairs_to_alloc = clib_min (space_available / pair_size, *n_fifo_pairs);
+  pairs_to_alloc = space_available / pair_size;
+  pairs_to_alloc = clib_min (pairs_to_alloc, *n_fifo_pairs);
+
+  if (!pairs_to_alloc)
+    return;
 
   if (fs_try_alloc_fifo_batch (fs, rx_fl_index, pairs_to_alloc))
-    clib_warning ("rx prealloc failed");
+    clib_warning ("rx prealloc failed: pairs %u", pairs_to_alloc);
   if (fs_try_alloc_fifo_batch (fs, tx_fl_index, pairs_to_alloc))
-    clib_warning ("tx prealloc failed");
+    clib_warning ("tx prealloc failed: pairs %u", pairs_to_alloc);
 
   /* Account for the pairs allocated */
   *n_fifo_pairs -= pairs_to_alloc;
@@ -632,7 +647,7 @@ fifo_segment_grow_fifo (fifo_segment_t * fs, svm_fifo_t * f, u32 chunk_size)
   if (!fs_chunk_size_is_valid (chunk_size))
     {
       clib_warning ("chunk size out of range %d", chunk_size);
-      return 0;
+      return -1;
     }
 
   fl_index = fs_freelist_for_size (chunk_size);
@@ -651,6 +666,7 @@ fifo_segment_grow_fifo (fifo_segment_t * fs, svm_fifo_t * f, u32 chunk_size)
       if (!c)
        {
          ssvm_pop_heap (oldheap);
+         ssvm_unlock_non_recursive (sh);
          return -1;
        }
     }
@@ -658,6 +674,7 @@ fifo_segment_grow_fifo (fifo_segment_t * fs, svm_fifo_t * f, u32 chunk_size)
     {
       fs->h->free_chunks[fl_index] = c->next;
       c->next = 0;
+      fs->h->n_fl_chunk_bytes -= fs_freelist_index_to_size (fl_index);
     }
 
   svm_fifo_add_chunk (f, c);
@@ -783,7 +800,7 @@ fifo_segment_free_bytes (fifo_segment_t * fs)
 }
 
 u32
-fifo_segment_chunk_prealloc_bytes (fifo_segment_t * fs)
+fifo_segment_fl_chunk_bytes (fifo_segment_t * fs)
 {
   return fs->h->n_fl_chunk_bytes;
 }
@@ -824,21 +841,45 @@ format_fifo_segment_type (u8 * s, va_list * args)
 u8 *
 format_fifo_segment (u8 * s, va_list * args)
 {
-  fifo_segment_t *sp = va_arg (*args, fifo_segment_t *);
+  fifo_segment_t *fs = va_arg (*args, fifo_segment_t *);
   int verbose __attribute__ ((unused)) = va_arg (*args, int);
-  fifo_segment_header_t *fsh = sp->h;
-  u32 count, indent;
+  fifo_segment_header_t *fsh;
   svm_fifo_chunk_t *c;
+  u32 count, indent;
+  u32 active_fifos;
+  u32 free_fifos;
+  char *address;
+  size_t size;
   int i;
 
   indent = format_get_indent (s) + 2;
 #if USE_DLMALLOC == 0
   s = format (s, "%U segment heap: %U\n", format_white_space, indent,
-             format_mheap, svm_fifo_segment_heap (sp), verbose);
+             format_mheap, svm_fifo_segment_heap (fs), verbose);
   s = format (s, "%U segment has %u active fifos\n",
-             format_white_space, indent, fifo_segment_num_fifos (sp));
+             format_white_space, indent, fifo_segment_num_fifos (fs));
 #endif
 
+  if (fs == 0)
+    {
+      s = format (s, "%-15s%15s%15s%15s%15s%15s", "Name", "Type",
+                 "HeapSize (M)", "ActiveFifos", "FreeFifos", "Address");
+      return s;
+    }
+
+  fsh = fs->h;
+  fifo_segment_info (fs, &address, &size);
+  active_fifos = fifo_segment_num_fifos (fs);
+  free_fifos = fifo_segment_num_free_fifos (fs);
+
+  s = format (s, "%-15v%15U%15llu%15u%15u%15llx", ssvm_name (&fs->ssvm),
+             format_fifo_segment_type, fs, size >> 20ULL, active_fifos,
+             free_fifos, address);
+
+  if (!verbose)
+    return s;
+
+  s = format (s, "\n");
   for (i = 0; i < vec_len (fsh->free_chunks); i++)
     {
       c = fsh->free_chunks[i];
@@ -851,11 +892,13 @@ format_fifo_segment (u8 * s, va_list * args)
          count++;
        }
 
-      s = format (s, "%U%-5u Kb: %u free",
-                 format_white_space, indent + 2,
+      s = format (s, "%U%-5u Kb: %u free", format_white_space, indent + 2,
                  1 << (i + max_log2 (FIFO_SEGMENT_MIN_FIFO_SIZE) - 10),
                  count);
     }
+  s = format (s, "%Ufree bytes %U", format_white_space, indent + 2,
+             format_memory_size, fsh->n_free_bytes);
+
   return s;
 }