MEMIF_INPUT_N_ERROR,
} memif_input_error_t;
-static char *memif_input_error_strings[] = {
+static __clib_unused char *memif_input_error_strings[] = {
#define _(n,s) s,
foreach_memif_input_error
#undef _
u16 ring;
} memif_input_trace_t;
-static u8 *
+static __clib_unused u8 *
format_memif_input_trace (u8 * s, va_list * args)
{
CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
while (*num_slots)
{
- data_len = ring->desc[mq->last_head].length;
+ data_len = ring->desc[mq->last_head & mask].length;
while (data_len && (*n_free_bufs))
{
/* get empty buffer */
prev_bi = *bi;
*bi = nm->rx_buffers[thread_index][last_buf];
b = vlib_get_buffer (vm, *bi);
+ /* Clear the error first to ensure following node forget setting it */
+ /* It will cause null-node error counter increasement instead of potential crash */
+ b->error = 0x0;
_vec_len (nm->rx_buffers[thread_index]) = last_buf;
(*n_free_bufs)--;
if (PREDICT_FALSE (*n_free_bufs == 0))
bytes_to_copy =
data_len > n_buffer_bytes ? n_buffer_bytes : data_len;
b->current_data = 0;
- mb = memif_get_buffer (mif, ring, mq->last_head);
+ mb = memif_get_buffer (mif, ring, mq->last_head & mask);
clib_memcpy (vlib_buffer_get_current (b), mb + offset,
CLIB_CACHE_LINE_BYTES);
if (bytes_to_copy > CLIB_CACHE_LINE_BYTES)
}
last_head = mq->last_head;
/* Advance to next descriptor */
- mq->last_head = (mq->last_head + 1) & mask;
+ mq->last_head++;
offset = 0;
(*num_slots)--;
- if ((ring->desc[last_head].flags & MEMIF_DESC_FLAG_NEXT) == 0)
+ if ((ring->desc[last_head & mask].flags & MEMIF_DESC_FLAG_NEXT) == 0)
break;
}
}
head = ring->head;
+ mq->last_head = ring->tail;
if (head == mq->last_head)
return 0;
- if (head > mq->last_head)
- num_slots = head - mq->last_head;
- else
- num_slots = ring_size - mq->last_head + head;
+ num_slots = head - mq->last_head;
while (num_slots)
{
while (num_slots > 11 && n_left_to_next > 2)
{
- if (PREDICT_TRUE (mq->last_head + 5 < ring_size))
- {
- CLIB_PREFETCH (memif_get_buffer (mif, ring, mq->last_head + 2),
- CLIB_CACHE_LINE_BYTES, LOAD);
- CLIB_PREFETCH (memif_get_buffer (mif, ring, mq->last_head + 3),
- CLIB_CACHE_LINE_BYTES, LOAD);
- CLIB_PREFETCH (&ring->desc[mq->last_head + 4],
- CLIB_CACHE_LINE_BYTES, LOAD);
- CLIB_PREFETCH (&ring->desc[mq->last_head + 5],
- CLIB_CACHE_LINE_BYTES, LOAD);
- }
- else
- {
- CLIB_PREFETCH (memif_get_buffer
- (mif, ring, (mq->last_head + 2) % mask),
- CLIB_CACHE_LINE_BYTES, LOAD);
- CLIB_PREFETCH (memif_get_buffer
- (mif, ring, (mq->last_head + 3) % mask),
- CLIB_CACHE_LINE_BYTES, LOAD);
- CLIB_PREFETCH (&ring->desc[(mq->last_head + 4) % mask],
- CLIB_CACHE_LINE_BYTES, LOAD);
- CLIB_PREFETCH (&ring->desc[(mq->last_head + 5) % mask],
- CLIB_CACHE_LINE_BYTES, LOAD);
- }
+ CLIB_PREFETCH (memif_get_buffer
+ (mif, ring, (mq->last_head + 2) & mask),
+ CLIB_CACHE_LINE_BYTES, LOAD);
+ CLIB_PREFETCH (memif_get_buffer
+ (mif, ring, (mq->last_head + 3) & mask),
+ CLIB_CACHE_LINE_BYTES, LOAD);
+ CLIB_PREFETCH (&ring->desc[(mq->last_head + 4) & mask],
+ CLIB_CACHE_LINE_BYTES, LOAD);
+ CLIB_PREFETCH (&ring->desc[(mq->last_head + 5) & mask],
+ CLIB_CACHE_LINE_BYTES, LOAD);
vlib_buffer_t *first_b0 = 0;
u32 bi0 = 0, first_bi0 = 0;
&first_bi1, &bi1,
&num_slots);
+ if (PREDICT_FALSE (!first_bi0 || !first_bi1))
+ {
+ goto _invalid_pkt01;
+ }
/* enqueue buffer */
to_next[0] = first_bi0;
to_next[1] = first_bi1;
/* next packet */
n_rx_packets += 2;
n_rx_bytes += b0_total + b1_total;
+
+ continue;
+ _invalid_pkt01:
+ if (!first_bi0 && !first_bi1)
+ {
+ continue;
+ }
+ if (first_bi1)
+ {
+ first_bi0 = first_bi1;
+ first_b0 = first_b1;
+ bi0 = bi1;
+ b0_total = b1_total;
+ }
+
+ if (mode == MEMIF_INTERFACE_MODE_IP)
+ {
+ next0 = memif_next_from_ip_hdr (node, first_b0);
+ }
+ else if (mode == MEMIF_INTERFACE_MODE_ETHERNET)
+ {
+ if (PREDICT_FALSE (mif->per_interface_next_index != ~0))
+ next0 = mif->per_interface_next_index;
+ else
+ /* redirect if feature path
+ * enabled */
+ vnet_feature_start_device_input_x1 (mif->sw_if_index, &next0,
+ first_b0);
+ }
+
+ /* trace */
+ VLIB_BUFFER_TRACE_TRAJECTORY_INIT (first_b0);
+
+ if (PREDICT_FALSE (n_trace > 0))
+ {
+ if (PREDICT_TRUE (first_b0 != 0))
+ {
+ memif_input_trace_t *tr;
+ vlib_trace_buffer (vm, node, next0, first_b0,
+ /* follow_chain */ 0);
+ vlib_set_trace_count (vm, node, --n_trace);
+ tr = vlib_add_trace (vm, node, first_b0, sizeof (*tr));
+ tr->next_index = next0;
+ tr->hw_if_index = mif->hw_if_index;
+ tr->ring = qid;
+ }
+ }
+
+ /* enqueue buffer */
+ to_next[0] = first_bi0;
+ to_next += 1;
+ n_left_to_next--;
+
+ /* enqueue */
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
+ n_left_to_next, first_bi0, next0);
+
+ /* next packet */
+ n_rx_packets++;
+ n_rx_bytes += b0_total;
}
while (num_slots && n_left_to_next)
{
&n_free_bufs, &first_b0,
&first_bi0, &bi0,
&num_slots);
+ if (PREDICT_FALSE (!first_bi0))
+ {
+ goto _invalid_pkt0;
+ }
if (mode == MEMIF_INTERFACE_MODE_IP)
{
/* next packet */
n_rx_packets++;
n_rx_bytes += b0_total;
+ continue;
+ _invalid_pkt0:
+ ;
+ }
+ if (PREDICT_TRUE (n_rx_packets != 0))
+ {
+ vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}
CLIB_MEMORY_STORE_BARRIER ();
- ring->tail = head;
+ ring->tail = mq->last_head;
vlib_increment_combined_counter (vnm->interface_main.combined_sw_if_counters
+ VNET_INTERFACE_COUNTER_RX, thread_index,
return n_rx_packets;
}
-static uword
-memif_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * frame)
+uword
+CLIB_MULTIARCH_FN (memif_input_fn) (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
{
u32 n_rx = 0;
memif_main_t *nm = &memif_main;
return n_rx;
}
+#ifndef CLIB_MULTIARCH_VARIANT
/* *INDENT-OFF* */
VLIB_REGISTER_NODE (memif_input_node) = {
.function = memif_input_fn,
.error_strings = memif_input_error_strings,
};
-VLIB_NODE_FUNCTION_MULTIARCH (memif_input_node, memif_input_fn)
+vlib_node_function_t __clib_weak memif_input_fn_avx512;
+vlib_node_function_t __clib_weak memif_input_fn_avx2;
+
+#if __x86_64__
+static void __clib_constructor
+memif_input_multiarch_select (void)
+{
+ if (memif_input_fn_avx512 && clib_cpu_supports_avx512f ())
+ memif_input_node.function = memif_input_fn_avx512;
+ else if (memif_input_fn_avx2 && clib_cpu_supports_avx2 ())
+ memif_input_node.function = memif_input_fn_avx2;
+}
+#endif
+#endif
+
/* *INDENT-ON* */