always_inline uword
ip4_input_inline (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * frame, int verify_checksum)
{
vnet_main_t *vnm = vnet_get_main ();
u32 n_left_from, *from;
u32 thread_index = vm->thread_index;
vlib_node_runtime_t *error_node =
vlib_node_get_runtime (vm, ip4_input_node.index);
vlib_simple_counter_main_t *cm;
vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
ip4_header_t *ip[4];
u16 nexts[VLIB_FRAME_SIZE], *next;
u32 sw_if_index[4];
u32 last_sw_if_index = ~0;
u32 cnt = 0;
int arc_enabled = 0;
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
if (node->flags & VLIB_NODE_FLAG_TRACE)
vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
/* stride */ 1,
sizeof (ip4_input_trace_t));
cm = vec_elt_at_index (vnm->interface_main.sw_if_counters,
VNET_INTERFACE_COUNTER_IP4);
vlib_get_buffers (vm, from, bufs, n_left_from);
b = bufs;
next = nexts;
while (n_left_from >= 4)
{
u32 x = 0;
/* Prefetch next iteration. */
if (n_left_from >= 12)
{
vlib_prefetch_buffer_header (b[8], LOAD);
vlib_prefetch_buffer_header (b[9], LOAD);
vlib_prefetch_buffer_header (b[10], LOAD);
vlib_prefetch_buffer_header (b[11], LOAD);
vlib_prefetch_buffer_data (b[4], LOAD);
vlib_prefetch_buffer_data (b[5], LOAD);
vlib_prefetch_buffer_data (b[6], LOAD);
vlib_prefetch_buffer_data (b[7], LOAD);
}
vnet_buffer (b[0])->ip.adj_index[VLIB_RX] = ~0;
vnet_buffer (b[1])->ip.adj_index[VLIB_RX] = ~0;
vnet_buffer (b[2])->ip.adj_index[VLIB_RX] = ~0;
vnet_buffer (b[3])->ip.adj_index[VLIB_RX] = ~0;
sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
sw_if_index[1] = vnet_buffer (b[1])->sw_if_index[VLIB_RX];
sw_if_index[2] = vnet_buffer (b[2])->sw_if_index[VLIB_RX];
sw_if_index[3] = vnet_buffer (b[3])->sw_if_index[VLIB_RX];
x |= sw_if_index[0] ^ last_sw_if_index;
x |= sw_if_index[1] ^ last_sw_if_index;
x |= sw_if_index[2] ^ last_sw_if_index;
x |= sw_if_index[3] ^ last_sw_if_index;
if (PREDICT_TRUE (x == 0))
{
/* we deal with 4 more packets sharing the same sw_if_index
with the previous one, so we can optimize */
cnt += 4;
if (arc_enabled)
{
next[0] = ip4_input_set_next (sw_if_index[0], b[0], 1);
next[1] = ip4_input_set_next (sw_if_index[1], b[1], 1);
next[2] = ip4_input_set_next (sw_if_index[2], b[2], 1);
next[3] = ip4_input_set_next (sw_if_index[3], b[3], 1);
}
else
{
next[0] = ip4_input_set_next (sw_if_index[0], b[0], 0);
next[1] = ip4_input_set_next (sw_if_index[1], b[1], 0);
next[2] = ip4_input_set_next (sw_if_index[2], b[2], 0);
next[3] = ip4_input_set_next (sw_if_index[3], b[3], 0);
}
}
else
{
ip4_input_check_sw_if_index (vm, cm, sw_if_index[0],
&last_sw_if_index, &cnt, &arc_enabled);
ip4_input_check_sw_if_index (vm, cm, sw_if_index[1],
&last_sw_if_index, &cnt, &arc_enabled);
ip4_input_check_sw_if_index (vm, cm, sw_if_index[2],
&last_sw_if_index, &cnt, &arc_enabled);
ip4_input_check_sw_if_index (vm, cm, sw_if_index[3],
&last_sw_if_index, &cnt, &arc_enabled);
next[0] = ip4_input_set_next (sw_if_index[0], b[0], 1);
next[1] = ip4_input_set_next (sw_if_index[1], b[1], 1);
next[2] = ip4_input_set_next (sw_if_index[2], b[2], 1);
next[3] = ip4_input_set_next (sw_if_index[3], b[3], 1);
}
ip[0] = vlib_buffer_get_current (b[0]);
ip[1] = vlib_buffer_get_current (b[1]);
ip[2] = vlib_buffer_get_current (b[2]);
ip[3] = vlib_buffer_get_current (b[3]);
ip4_input_check_x4 (vm, error_node, b, ip, next, verify_checksum);
/* next */
b += 4;
next += 4;
n_left_from -= 4;
}
while (n_left_from)
{
u32 next0;
vnet_buffer (b[0])->ip.adj_index[VLIB_RX] = ~0;
sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
ip4_input_check_sw_if_index (vm, cm, sw_if_index[0], &last_sw_if_index,
&cnt, &arc_enabled);
next0 = ip4_input_set_next (sw_if_index[0], b[0], arc_enabled);
ip[0] = vlib_buffer_get_current (b[0]);
ip4_input_check_x1 (vm, error_node, b[0], ip[0], &next0,
verify_checksum);
next[0] = next0;
/* next */
b += 1;
next += 1;
n_left_from -= 1;
}
vlib_increment_simple_counter (cm, thread_index, last_sw_if_index, cnt);
vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
return frame->n_vectors;
}