X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvlib%2Fbuffer_node.h;h=10ebd253c1b6b080e23db8c4b24c07f8969d4738;hb=1b6c7932a8feb419aae73a00a6784d7c110decdc;hp=d2bd32f985a855a0720430aaf4a59e68f91bae16;hpb=1c2297144a37ea6a42f5deec6e1613a297de3321;p=vpp.git diff --git a/src/vlib/buffer_node.h b/src/vlib/buffer_node.h index d2bd32f985a..10ebd253c1b 100644 --- a/src/vlib/buffer_node.h +++ b/src/vlib/buffer_node.h @@ -287,8 +287,8 @@ generic_buffer_node_inline (vlib_main_t * vm, vlib_prefetch_buffer_header (p2, LOAD); vlib_prefetch_buffer_header (p3, LOAD); - CLIB_PREFETCH (p2->data, 64, LOAD); - CLIB_PREFETCH (p3->data, 64, LOAD); + clib_prefetch_load (p2->data); + clib_prefetch_load (p3->data); } pi0 = to_next[0] = from[0]; @@ -335,6 +335,17 @@ generic_buffer_node_inline (vlib_main_t * vm, return frame->n_vectors; } +/* Minimum size for the 'buffers' and 'nexts' arrays to be used when calling + * vlib_buffer_enqueue_to_next(). + * Because of optimizations, vlib_buffer_enqueue_to_next() will access + * past 'count' elements in the 'buffers' and 'nexts' arrays, IOW it + * will overflow. + * Those overflow elements are ignored in the final result so they do not + * need to be properly initialized, however if the array is allocated right + * before the end of a page and the next page is not mapped, accessing the + * overflow elements will trigger a segfault. */ +#define VLIB_BUFFER_ENQUEUE_MIN_SIZE(n) round_pow2 ((n), 64) + static_always_inline void vlib_buffer_enqueue_to_next (vlib_main_t * vm, vlib_node_runtime_t * node, u32 * buffers, u16 * nexts, uword count) @@ -344,6 +355,20 @@ vlib_buffer_enqueue_to_next (vlib_main_t * vm, vlib_node_runtime_t * node, (fn) (vm, node, buffers, nexts, count); } +static_always_inline void +vlib_buffer_enqueue_to_next_vec (vlib_main_t *vm, vlib_node_runtime_t *node, + u32 **buffers, u16 **nexts, uword count) +{ + const u32 bl = vec_len (*buffers), nl = vec_len (*nexts); + const u32 c = VLIB_BUFFER_ENQUEUE_MIN_SIZE (count); + ASSERT (bl >= count && nl >= count); + vec_validate (*buffers, c); + vec_validate (*nexts, c); + vlib_buffer_enqueue_to_next (vm, node, *buffers, *nexts, count); + vec_set_len (*buffers, bl); + vec_set_len (*nexts, nl); +} + static_always_inline void vlib_buffer_enqueue_to_single_next (vlib_main_t * vm, vlib_node_runtime_t * node, u32 * buffers, @@ -355,13 +380,14 @@ vlib_buffer_enqueue_to_single_next (vlib_main_t * vm, } static_always_inline u32 -vlib_buffer_enqueue_to_thread (vlib_main_t * vm, u32 frame_queue_index, - u32 * buffer_indices, u16 * thread_indices, - u32 n_packets, int drop_on_congestion) +vlib_buffer_enqueue_to_thread (vlib_main_t *vm, vlib_node_runtime_t *node, + u32 frame_queue_index, u32 *buffer_indices, + u16 *thread_indices, u32 n_packets, + int drop_on_congestion) { vlib_buffer_enqueue_to_thread_fn_t *fn; fn = vlib_buffer_func_main.buffer_enqueue_to_thread_fn; - return (fn) (vm, frame_queue_index, buffer_indices, thread_indices, + return (fn) (vm, node, frame_queue_index, buffer_indices, thread_indices, n_packets, drop_on_congestion); }