vlib_buffer_clone: allow client to request the maximum number of clones; 256

Change-Id: Id96dc5d86719546268b50a9999a06387d2d9075c
Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
diff --git a/src/vlib/buffer_funcs.h b/src/vlib/buffer_funcs.h
index cc56db7..b73fb26 100644
--- a/src/vlib/buffer_funcs.h
+++ b/src/vlib/buffer_funcs.h
@@ -585,27 +585,28 @@
   return fd;
 }
 
-/** \brief Create multiple clones of buffer and store them in the supplied array
+/** \brief Create a maximum of 256 clones of buffer and store them
+    in the supplied array
 
     @param vm - (vlib_main_t *) vlib main data structure pointer
     @param src_buffer - (u32) source buffer index
     @param buffers - (u32 * ) buffer index array
-    @param n_buffers - (u8) number of buffer clones requested
+    @param n_buffers - (u16) number of buffer clones requested (<=256)
     @param head_end_offset - (u16) offset relative to current position
            where packet head ends
-    @return - (u8) number of buffers actually cloned, may be
+    @return - (u16) number of buffers actually cloned, may be
     less than the number requested or zero
 */
-
-always_inline u8
-vlib_buffer_clone (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
-		   u8 n_buffers, u16 head_end_offset)
+always_inline u16
+vlib_buffer_clone_256 (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
+		       u16 n_buffers, u16 head_end_offset)
 {
-  u8 i;
+  u16 i;
   vlib_buffer_t *s = vlib_get_buffer (vm, src_buffer);
 
   ASSERT (s->n_add_refs == 0);
   ASSERT (n_buffers);
+  ASSERT (n_buffers <= 256);
 
   if (s->current_length <= head_end_offset + CLIB_CACHE_LINE_BYTES * 2)
     {
@@ -622,15 +623,16 @@
       return n_buffers;
     }
 
-  n_buffers = vlib_buffer_alloc_from_free_list (vm, buffers, n_buffers,
-						vlib_buffer_get_free_list_index
-						(s));
-  if (PREDICT_FALSE (n_buffers == 0))
+  if (PREDICT_FALSE (n_buffers == 1))
     {
       buffers[0] = src_buffer;
       return 1;
     }
 
+  n_buffers = vlib_buffer_alloc_from_free_list (vm, buffers, n_buffers,
+						vlib_buffer_get_free_list_index
+						(s));
+
   for (i = 0; i < n_buffers; i++)
     {
       vlib_buffer_t *d = vlib_get_buffer (vm, buffers[i]);
@@ -659,6 +661,42 @@
   return n_buffers;
 }
 
+/** \brief Create multiple clones of buffer and store them
+    in the supplied array
+
+    @param vm - (vlib_main_t *) vlib main data structure pointer
+    @param src_buffer - (u32) source buffer index
+    @param buffers - (u32 * ) buffer index array
+    @param n_buffers - (u16) number of buffer clones requested (<=256)
+    @param head_end_offset - (u16) offset relative to current position
+           where packet head ends
+    @return - (u16) number of buffers actually cloned, may be
+    less than the number requested or zero
+*/
+always_inline u16
+vlib_buffer_clone (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
+		   u16 n_buffers, u16 head_end_offset)
+{
+  vlib_buffer_t *s = vlib_get_buffer (vm, src_buffer);
+  u16 n_cloned = 0;
+
+  while (n_buffers > 256)
+    {
+      vlib_buffer_t *copy;
+      copy = vlib_buffer_copy (vm, s);
+      n_cloned += vlib_buffer_clone_256 (vm,
+					 vlib_get_buffer_index (vm, copy),
+					 (buffers + n_cloned),
+					 256, head_end_offset);
+      n_buffers -= 256;
+    }
+  n_cloned += vlib_buffer_clone_256 (vm, src_buffer,
+				     buffers + n_cloned,
+				     n_buffers, head_end_offset);
+
+  return n_cloned;
+}
+
 /** \brief Attach cloned tail to the buffer
 
     @param vm - (vlib_main_t *) vlib main data structure pointer