VPP-650: handle buffer failure in vlib_buffer_copy(...) 05/5505/2
authorDave Barach <dave@barachs.net>
Thu, 23 Feb 2017 22:11:26 +0000 (17:11 -0500)
committerDave Barach <openvpp@barachs.net>
Fri, 24 Feb 2017 12:17:01 +0000 (12:17 +0000)
Change-Id: I6aac48d780fcd935818221044eae50067f225175
Signed-off-by: Dave Barach <dave@barachs.net>
src/vlib/buffer_funcs.h
src/vnet/dpo/replicate_dpo.c
src/vnet/lawful-intercept/node.c
src/vnet/span/node.c

index fd051de..0b583a6 100644 (file)
@@ -489,7 +489,15 @@ vlib_buffer_copy (vlib_main_t * vm, vlib_buffer_t * b)
 
   vec_validate (new_buffers, n_buffers - 1);
   n_alloc = vlib_buffer_alloc (vm, new_buffers, n_buffers);
-  ASSERT (n_alloc == n_buffers);
+
+  /* No guarantee that we'll get all the buffers we asked for */
+  if (PREDICT_FALSE (n_alloc < n_buffers))
+    {
+      if (n_alloc > 0)
+       vlib_buffer_free (vm, new_buffers, n_alloc);
+      vec_free (new_buffers);
+      return 0;
+    }
 
   /* 1st segment */
   s = b;
@@ -518,6 +526,7 @@ vlib_buffer_copy (vlib_main_t * vm, vlib_buffer_t * b)
       d->flags = s->flags & flag_mask;
     }
 
+  vec_free (new_buffers);
   return fd;
 }
 
index c779516..a67b19c 100644 (file)
 #define REP_DBG(_p, _fmt, _args...)
 #endif
 
+#define foreach_replicate_dpo_error                       \
+_(BUFFER_ALLOCATION_FAILURE, "Buffer Allocation Failure")
+
+typedef enum {
+#define _(sym,str) REPLICATE_DPO_ERROR_##sym,
+  foreach_replicate_dpo_error
+#undef _
+  REPLICATE_DPO_N_ERROR,
+} replicate_dpo_error_t;
+
+static char * replicate_dpo_error_strings[] = {
+#define _(sym,string) string,
+  foreach_replicate_dpo_error
+#undef _
+};
 
 /**
  * Pool of all DPOs. It's not static so the DP can have fast access
@@ -678,8 +693,17 @@ replicate_inline (vlib_main_t * vm,
                     vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
                 }
 
-                /* Make a copy */
+                /* Make a copy. This can fail, so deal with it. */
                 c0 = vlib_buffer_copy(vm, b0);
+                if (PREDICT_FALSE (c0 == 0))
+                  {
+                    vlib_node_increment_counter 
+                      (vm, node->node_index, 
+                       REPLICATE_DPO_ERROR_BUFFER_ALLOCATION_FAILURE,
+                       1);
+                    continue;
+                  }
+                
                 ci0 = vlib_get_buffer_index(vm, c0);
 
                 to_next[0] = ci0;
@@ -738,6 +762,9 @@ VLIB_REGISTER_NODE (ip4_replicate_node) = {
   .name = "ip4-replicate",
   .vector_size = sizeof (u32),
 
+  .n_errors = ARRAY_LEN(replicate_dpo_error_strings),
+  .error_strings = replicate_dpo_error_strings,
+
   .format_trace = format_replicate_trace,
   .n_next_nodes = 1,
   .next_nodes = {
@@ -761,6 +788,9 @@ VLIB_REGISTER_NODE (ip6_replicate_node) = {
   .name = "ip6-replicate",
   .vector_size = sizeof (u32),
 
+  .n_errors = ARRAY_LEN(replicate_dpo_error_strings),
+  .error_strings = replicate_dpo_error_strings,
+
   .format_trace = format_replicate_trace,
   .n_next_nodes = 1,
   .next_nodes = {
index ea0cd8e..50c76ec 100644 (file)
@@ -42,9 +42,10 @@ static u8 * format_li_hit_trace (u8 * s, va_list * args)
 
 vlib_node_registration_t li_hit_node;
 
-#define foreach_li_hit_error                    \
-_(HITS, "LI packets processed")                 \
-_(NO_COLLECTOR, "No collector configured")
+#define foreach_li_hit_error                                    \
+_(HITS, "LI packets processed")                                 \
+_(NO_COLLECTOR, "No collector configured")                      \
+_(BUFFER_ALLOCATION_FAILURE, "Buffer allocation failure")
 
 typedef enum {
 #define _(sym,str) LI_HIT_ERROR_##sym,
@@ -197,8 +198,16 @@ li_hit_node_fn (vlib_main_t * vm,
          b0 = vlib_get_buffer (vm, bi0);
           if (PREDICT_TRUE(to_int_next != 0))
             {
-              /* Make an intercept copy */
+              /* Make an intercept copy. This can fail. */
               c0 = vlib_buffer_copy (vm, b0);
+
+              if (PREDICT_FALSE (c0 == 0))
+                {
+                  vlib_node_increment_counter 
+                    (vm, node->node_index, 
+                     LI_HIT_ERROR_BUFFER_ALLOCATION_FAILURE, 1);
+                  goto skip;
+                }
               
               vlib_buffer_advance(c0, -sizeof(*iu0));
 
@@ -225,6 +234,7 @@ li_hit_node_fn (vlib_main_t * vm,
               to_int_next++;
             }
 
+        skip:
           if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE) 
                             && (b0->flags & VLIB_BUFFER_IS_TRACED))) 
             {
index 50d642c..5037c12 100644 (file)
@@ -83,11 +83,15 @@ span_mirror (vlib_main_t * vm, span_interface_t * si0, vlib_buffer_t * b0,
        mirror_frames[i] = vnet_get_frame_to_sw_interface (vnm, i);
       to_mirror_next = vlib_frame_vector_args (mirror_frames[i]);
       to_mirror_next += mirror_frames[i]->n_vectors;
+      /* This can fail */
       c0 = vlib_buffer_copy (vm, b0);
-      vnet_buffer (c0)->sw_if_index[VLIB_TX] = i;
-      c0->flags |= VNET_BUFFER_SPAN_CLONE;
-      to_mirror_next[0] = vlib_get_buffer_index (vm, c0);
-      mirror_frames[i]->n_vectors++;
+      if (PREDICT_TRUE(c0 != 0))
+        {
+          vnet_buffer (c0)->sw_if_index[VLIB_TX] = i;
+          c0->flags |= VNET_BUFFER_SPAN_CLONE;
+          to_mirror_next[0] = vlib_get_buffer_index (vm, c0);
+          mirror_frames[i]->n_vectors++;
+        }
     }));
   /* *INDENT-ON* */
 }