diff options
author | Dave Barach <dave@barachs.net> | 2017-02-23 17:11:26 -0500 |
---|---|---|
committer | Dave Barach <openvpp@barachs.net> | 2017-02-24 12:17:01 +0000 |
commit | 26cd8c129567b48ed0e3610293251ca78fa67103 (patch) | |
tree | 627830df91fa440ebbf4635a72848f80d1c85de9 /src | |
parent | 02767e9f2eaf7ccfc4079f83d467ad2d3faee203 (diff) |
VPP-650: handle buffer failure in vlib_buffer_copy(...)
Change-Id: I6aac48d780fcd935818221044eae50067f225175
Signed-off-by: Dave Barach <dave@barachs.net>
Diffstat (limited to 'src')
-rw-r--r-- | src/vlib/buffer_funcs.h | 11 | ||||
-rw-r--r-- | src/vnet/dpo/replicate_dpo.c | 32 | ||||
-rw-r--r-- | src/vnet/lawful-intercept/node.c | 18 | ||||
-rw-r--r-- | src/vnet/span/node.c | 12 |
4 files changed, 63 insertions, 10 deletions
diff --git a/src/vlib/buffer_funcs.h b/src/vlib/buffer_funcs.h index fd051de53de..0b583a61994 100644 --- a/src/vlib/buffer_funcs.h +++ b/src/vlib/buffer_funcs.h @@ -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; } diff --git a/src/vnet/dpo/replicate_dpo.c b/src/vnet/dpo/replicate_dpo.c index c779516f3d4..a67b19c893f 100644 --- a/src/vnet/dpo/replicate_dpo.c +++ b/src/vnet/dpo/replicate_dpo.c @@ -34,6 +34,21 @@ #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 = { diff --git a/src/vnet/lawful-intercept/node.c b/src/vnet/lawful-intercept/node.c index ea0cd8efcdd..50c76ec5a7f 100644 --- a/src/vnet/lawful-intercept/node.c +++ b/src/vnet/lawful-intercept/node.c @@ -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))) { diff --git a/src/vnet/span/node.c b/src/vnet/span/node.c index 50d642c2f8b..5037c120ba5 100644 --- a/src/vnet/span/node.c +++ b/src/vnet/span/node.c @@ -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* */ } |