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)
(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,
n_cache += cf->n_elts;
if (n_cache >= VLIB_FRAME_SIZE)
{
- vlib_buffer_enqueue_to_next (vm, node, ct->buffer_indices,
- ct->nexts, n_cache);
+ vlib_buffer_enqueue_to_next_vec (vm, node, &ct->buffer_indices,
+ &ct->nexts, n_cache);
n_cache = 0;
}
}
/* *INDENT-ON* */
if (n_cache)
- vlib_buffer_enqueue_to_next (vm, node, ct->buffer_indices, ct->nexts,
- n_cache);
+ vlib_buffer_enqueue_to_next_vec (vm, node, &ct->buffer_indices, &ct->nexts,
+ n_cache);
return n_dispatched;
}
session_flush_pending_tx_buffers (session_worker_t * wrk,
vlib_node_runtime_t * node)
{
- vlib_buffer_enqueue_to_next (wrk->vm, node, wrk->pending_tx_buffers,
- wrk->pending_tx_nexts,
- vec_len (wrk->pending_tx_nexts));
+ vlib_buffer_enqueue_to_next_vec (wrk->vm, node, &wrk->pending_tx_buffers,
+ &wrk->pending_tx_nexts,
+ vec_len (wrk->pending_tx_nexts));
vec_reset_length (wrk->pending_tx_buffers);
vec_reset_length (wrk->pending_tx_nexts);
}