buffers: configurable buffer fault injector

When configured at compile time via the cmake
VPP_BUFFER_FAULT_INJECTOR option, the buffer allocator will appear to
fail a certain fraction of the time.

By default, the allocator succeeds 80% of the time. Detailed command
line configuration options are available, but only when the image has
been compiled with cmake option described above:

    vlib { buffer-alloc-success-rate [0.0 ... 1.0]
           buffer-alloc-success-seed <nnnn> }

Modify vlib_buffer_pool_create(...) so 0 is always an invalid buffer
index.

Debug images: add checks for bad buffer index enqueues, and also
verify that f->n_vectors doesn't accidentally map one or more
instances of the frame poison pattern 0xfefefefe.

Type: improvement

Signed-off-by: Dave Barach <dave@barachs.net>
Change-Id: Iab939858014463d1e664682805013d334d6fcbe5
diff --git a/src/vlib/buffer.c b/src/vlib/buffer.c
index 43b1dd6..f5b8137 100644
--- a/src/vlib/buffer.c
+++ b/src/vlib/buffer.c
@@ -578,6 +578,14 @@
 	p = m->base + (j << m->log2_page_size) + i * alloc_size;
 	p += bm->ext_hdr_size;
 
+	/*
+	 * Waste 1 buffer (maximum) so that 0 is never a valid buffer index.
+	 * Allows various places to ASSERT (bi != 0). Much easier
+	 * than debugging downstream crashes in successor nodes.
+	 */
+	if (p == m->base)
+	  continue;
+
 	vlib_buffer_copy_template ((vlib_buffer_t *) p, &bp->buffer_template);
 
 	bi = vlib_get_buffer_index (vm, (vlib_buffer_t *) p);
@@ -923,6 +931,24 @@
 
 VLIB_EARLY_CONFIG_FUNCTION (vlib_buffers_configure, "buffers");
 
+#if VLIB_BUFFER_ALLOC_FAULT_INJECTOR > 0
+u32
+vlib_buffer_alloc_may_fail (vlib_main_t * vm, u32 n_buffers)
+{
+  f64 r;
+
+  r = random_f64 (&vm->buffer_alloc_success_seed);
+
+  /* Fail this request? */
+  if (r > vm->buffer_alloc_success_rate)
+    n_buffers--;
+  /* 5% chance of returning nothing at all */
+  if (r > vm->buffer_alloc_success_rate && r > 0.95)
+    n_buffers = 0;
+
+  return n_buffers;
+}
+#endif
 
 /** @endcond */
 /*