vlib: add vlib_buffer_alloc_to_ring API

Change-Id: I4e2804754b443f5f41fb25eed8334908c4a70f84
Signed-off-by: Damjan Marion <damarion@cisco.com>
diff --git a/src/vlib/buffer_funcs.h b/src/vlib/buffer_funcs.h
index 1ea3c08..06cc6da 100644
--- a/src/vlib/buffer_funcs.h
+++ b/src/vlib/buffer_funcs.h
@@ -344,6 +344,35 @@
 					   VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
 }
 
+/** \brief Allocate buffers into ring
+
+    @param vm - (vlib_main_t *) vlib main data structure pointer
+    @param buffers - (u32 * ) buffer index ring
+    @param start - (u32) first slot in the ring
+    @param ring_size - (u32) ring size
+    @param n_buffers - (u32) number of buffers requested
+    @return - (u32) number of buffers actually allocated, may be
+    less than the number requested or zero
+*/
+always_inline u32
+vlib_buffer_alloc_to_ring (vlib_main_t * vm, u32 * ring, u32 start,
+			   u32 ring_size, u32 n_buffers)
+{
+  u32 n_alloc;
+
+  ASSERT (n_buffers <= ring_size);
+
+  if (PREDICT_TRUE (start + n_buffers <= ring_size))
+    return vlib_buffer_alloc (vm, ring + start, n_buffers);
+
+  n_alloc = vlib_buffer_alloc (vm, ring + start, ring_size - start);
+
+  if (PREDICT_TRUE (n_alloc == ring_size - start))
+    n_alloc += vlib_buffer_alloc (vm, ring, n_buffers - n_alloc);
+
+  return n_alloc;
+}
+
 /** \brief Free buffers
     Frees the entire buffer chain for each buffer
 
diff --git a/src/vnet/devices/virtio/node.c b/src/vnet/devices/virtio/node.c
index 5ca0636..9477a1c 100644
--- a/src/vnet/devices/virtio/node.c
+++ b/src/vnet/devices/virtio/node.c
@@ -83,10 +83,9 @@
 virtio_refill_vring (vlib_main_t * vm, virtio_vring_t * vring)
 {
   const int hdr_sz = sizeof (struct virtio_net_hdr_v1);
-  u16 used, next, avail, n_slots, n_alloc;
+  u16 used, next, avail, n_slots;
   u16 sz = vring->size;
   u16 mask = sz - 1;
-  int i;
 
   used = vring->desc_in_use;
 
@@ -96,14 +95,8 @@
   n_slots = sz - used;
   next = vring->desc_next;
   avail = vring->avail->idx;
-  n_alloc = vlib_buffer_alloc (vm, &vring->buffers[next], n_slots);
-
-  if (PREDICT_FALSE (n_alloc < n_slots))
-    n_slots = n_alloc;
-
-  i = next + n_slots - sz;
-  if (PREDICT_FALSE (i > 0))
-    clib_memcpy (vring->buffers, &vring->buffers[sz], i * sizeof (u32));
+  n_slots = vlib_buffer_alloc_to_ring (vm, vring->buffers, next, vring->size,
+				       n_slots);
 
   while (n_slots)
     {
diff --git a/src/vnet/devices/virtio/virtio.c b/src/vnet/devices/virtio/virtio.c
index 3867cf0..02ded3f 100644
--- a/src/vnet/devices/virtio/virtio.c
+++ b/src/vnet/devices/virtio/virtio.c
@@ -100,7 +100,7 @@
   memset (vring->used, 0, i);
 
   ASSERT (vring->buffers == 0);
-  vec_validate_aligned (vring->buffers, sz * 2, CLIB_CACHE_LINE_BYTES);
+  vec_validate_aligned (vring->buffers, sz, CLIB_CACHE_LINE_BYTES);
 
   vring->size = sz;
   vring->call_fd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);