FD.io VPP  v21.06-1-gbb7418cf9
Vector Packet Processing
input.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2018 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *------------------------------------------------------------------
16  */
17 
18 #define _GNU_SOURCE
19 #include <stdint.h>
20 #include <net/if.h>
21 #include <sys/ioctl.h>
22 #include <sys/uio.h>
23 
24 #include <vlib/vlib.h>
25 #include <vlib/unix/unix.h>
26 #include <vnet/ethernet/ethernet.h>
27 #include <vnet/devices/devices.h>
29 
30 #include <marvell/pp2/pp2.h>
31 
32 #define foreach_mrvl_pp2_input_error \
33  _(PPIO_RECV, "pp2_ppio_recv error") \
34  _(BPOOL_GET_NUM_BUFFS, "pp2_bpool_get_num_buffs error") \
35  _(BPOOL_PUT_BUFFS, "pp2_bpool_put_buffs error") \
36  _(BUFFER_ALLOC, "buffer alloc error") \
37  _(MAC_CE, "MAC error (CRC error)") \
38  _(MAC_OR, "overrun error") \
39  _(MAC_RSVD, "unknown MAC error") \
40  _(MAC_RE, "resource error") \
41  _(IP_HDR, "ip4 header error")
42 
43 typedef enum
44 {
45 #define _(f,s) MRVL_PP2_INPUT_ERROR_##f,
47 #undef _
50 
51 static __clib_unused char *mrvl_pp2_input_error_strings[] = {
52 #define _(n,s) s,
54 #undef _
55 };
56 
59  vlib_buffer_t * b0, uword * n_trace,
60  mrvl_pp2_if_t * ppif, struct pp2_ppio_desc *d)
61 {
62  if (PREDICT_TRUE (
63  vlib_trace_buffer (vm, node, next0, b0, /* follow_chain */ 0)))
64  {
66  vlib_set_trace_count (vm, node, --(*n_trace));
67  tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
68  tr->next_index = next0;
69  tr->hw_if_index = ppif->hw_if_index;
70  clib_memcpy_fast (&tr->desc, d, sizeof (struct pp2_ppio_desc));
71  }
72 }
73 
75 mrvl_pp2_set_buf_data_len_flags (vlib_buffer_t * b, struct pp2_ppio_desc *d,
76  u32 add_flags)
77 {
78  u16 len;
79  len = pp2_ppio_inq_desc_get_pkt_len (d);
81  b->flags = VLIB_BUFFER_TOTAL_LENGTH_VALID | add_flags;
82 
83  if (add_flags & VNET_BUFFER_F_L2_HDR_OFFSET_VALID)
84  vnet_buffer (b)->l2_hdr_offset = 2;
85 
86  if (add_flags & VNET_BUFFER_F_L3_HDR_OFFSET_VALID)
87  {
88  u16 offset = DM_RXD_GET_L3_OFF (d);
89  vnet_buffer (b)->l3_hdr_offset = offset;
90  b->current_data = offset;
91  b->current_length = len - offset + 2;
92  }
93  else
94  {
95  b->current_data = 2;
96  b->current_length = len;
97  }
98 
99  if (add_flags & VNET_BUFFER_F_L3_HDR_OFFSET_VALID)
100  vnet_buffer (b)->l4_hdr_offset = vnet_buffer (b)->l3_hdr_offset +
101  DM_RXD_GET_IPHDR_LEN (d) * 4;
102 
103  return len;
104 }
105 
107 mrvl_pp2_next_from_desc (vlib_node_runtime_t * node, struct pp2_ppio_desc * d,
108  vlib_buffer_t * b, u32 * next)
109 {
110  u8 l3_info;
111  /* ES bit set means MAC error - drop and count */
112  if (PREDICT_FALSE (DM_RXD_GET_ES (d)))
113  {
115  u8 ec = DM_RXD_GET_EC (d);
116  if (ec == 0)
117  b->error = node->errors[MRVL_PP2_INPUT_ERROR_MAC_CE];
118  else if (ec == 1)
119  b->error = node->errors[MRVL_PP2_INPUT_ERROR_MAC_OR];
120  else if (ec == 2)
121  b->error = node->errors[MRVL_PP2_INPUT_ERROR_MAC_RSVD];
122  else if (ec == 3)
123  b->error = node->errors[MRVL_PP2_INPUT_ERROR_MAC_RE];
124  return mrvl_pp2_set_buf_data_len_flags (b, d, 0);
125  }
126  l3_info = DM_RXD_GET_L3_PRS_INFO (d);
127 
128  /* ipv4 packet can be value 1, 2 or 3 */
129  if (PREDICT_TRUE ((l3_info - 1) < 3))
130  {
131  if (PREDICT_FALSE (DM_RXD_GET_L3_IP4_HDR_ERR (d) != 0))
132  {
134  b->error = node->errors[MRVL_PP2_INPUT_ERROR_IP_HDR];
135  return mrvl_pp2_set_buf_data_len_flags (b, d, 0);
136  }
139  (b, d,
140  VNET_BUFFER_F_L2_HDR_OFFSET_VALID |
141  VNET_BUFFER_F_L3_HDR_OFFSET_VALID |
142  VNET_BUFFER_F_L4_HDR_OFFSET_VALID | VNET_BUFFER_F_IS_IP4);
143  }
144 
145  /* ipv4 packet can be value 4 or 5 */
146  if (PREDICT_TRUE ((l3_info - 4) < 2))
147  {
150  (b, d,
151  VNET_BUFFER_F_L2_HDR_OFFSET_VALID |
152  VNET_BUFFER_F_L3_HDR_OFFSET_VALID |
153  VNET_BUFFER_F_L4_HDR_OFFSET_VALID | VNET_BUFFER_F_IS_IP6);
154  }
155 
157  return mrvl_pp2_set_buf_data_len_flags (b, d,
158  VNET_BUFFER_F_L2_HDR_OFFSET_VALID);
159 }
160 
163  vlib_frame_t * frame, mrvl_pp2_if_t * ppif,
164  u16 qid)
165 {
166  vnet_main_t *vnm = vnet_get_main ();
169  mrvl_pp2_inq_t *inq = vec_elt_at_index (ppif->inqs, qid);
170  uword n_trace = vlib_get_trace_count (vm, node);
172  vec_elt_at_index (ppm->per_thread_data, thread_index);
175  u32 n_rx_packets = 0;
176  u32 n_rx_bytes = 0;
177  u32 *to_next = 0;
178  struct pp2_ppio_desc *d;
179  u16 n_desc = VLIB_FRAME_SIZE;
180  u32 n_bufs;
181  u32 *buffers;
182  int i;
183 
185  if (PREDICT_FALSE (pp2_ppio_recv (ppif->ppio, 0, qid, ptd->descs, &n_desc)))
186  {
187  vlib_error_count (vm, node->node_index, MRVL_PP2_INPUT_ERROR_PPIO_RECV,
188  1);
189  n_desc = 0;
190  }
191  n_rx_packets = n_desc;
192 
193  for (i = 0; i < n_desc; i++)
194  ptd->buffers[i] = pp2_ppio_inq_desc_get_cookie (&ptd->descs[i]);
195 
196  d = ptd->descs;
197  buffers = ptd->buffers;
198  sw_if_index[VLIB_RX] = ppif->sw_if_index;
199  sw_if_index[VLIB_TX] = (u32) ~ 0;
200  while (n_desc)
201  {
202  u32 n_left_to_next;
203  vlib_buffer_t *b0, *b1;
204  u32 bi0, bi1;
205  u32 next0, next1;
206  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
207  while (n_desc >= 4 && n_left_to_next >= 2)
208  {
209  /* prefetch */
210  bi0 = buffers[0];
211  bi1 = buffers[1];
212  to_next[0] = bi0;
213  to_next[1] = bi1;
214  b0 = vlib_get_buffer (vm, bi0);
215  b1 = vlib_get_buffer (vm, bi1);
216 
217  if (PREDICT_TRUE (ppif->per_interface_next_index == ~0))
218  {
219  n_rx_bytes += mrvl_pp2_next_from_desc (node, d, b0, &next0);
220  n_rx_bytes += mrvl_pp2_next_from_desc (node, d + 1, b1, &next1);
222  &next1, b0, b1);
223  }
224  else
225  {
226  n_rx_bytes += mrvl_pp2_set_buf_data_len_flags (b0, d, 0);
227  n_rx_bytes += mrvl_pp2_set_buf_data_len_flags (b1, d + 1, 0);
228  next0 = next1 = ppif->per_interface_next_index;
229  }
230 
231  clib_memcpy_fast (vnet_buffer (b0)->sw_if_index, sw_if_index,
232  sizeof (sw_if_index));
233  clib_memcpy_fast (vnet_buffer (b1)->sw_if_index, sw_if_index,
234  sizeof (sw_if_index));
235 
236  if (PREDICT_FALSE (n_trace > 0))
237  {
238  mrvl_pp2_input_trace (vm, node, next0, b0, &n_trace, ppif, d);
239  if (n_trace > 0)
240  mrvl_pp2_input_trace (vm, node, next1, b1, &n_trace, ppif,
241  d + 1);
242  }
243 
244  to_next += 2;
245  n_left_to_next -= 2;
246  d += 2;
247  buffers += 2;
248  n_desc -= 2;
249 
250  /* enqueue */
251  vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
252  n_left_to_next, bi0, bi1, next0,
253  next1);
254 
255  }
256  while (n_desc && n_left_to_next)
257  {
258  u32 bi0 = buffers[0];
259  to_next[0] = bi0;
260  b0 = vlib_get_buffer (vm, bi0);
261 
262  if (PREDICT_TRUE (ppif->per_interface_next_index == ~0))
263  {
264  n_rx_bytes += mrvl_pp2_next_from_desc (node, d, b0, &next0);
266  b0);
267  }
268  else
269  {
270  n_rx_bytes += mrvl_pp2_set_buf_data_len_flags (b0, d, 0);
271  next0 = ppif->per_interface_next_index;
272  }
273 
274  clib_memcpy_fast (vnet_buffer (b0)->sw_if_index, sw_if_index,
275  sizeof (sw_if_index));
276 
277  if (PREDICT_FALSE (n_trace > 0))
278  mrvl_pp2_input_trace (vm, node, next0, b0, &n_trace, ppif, d);
279 
280  to_next += 1;
281  n_left_to_next--;
282  d++;
283  buffers++;
284  n_desc--;
285 
286  /* enqueue */
287  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
288  n_left_to_next, bi0, next0);
289  }
290  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
291  }
293  interface_main.combined_sw_if_counters +
294  VNET_INTERFACE_COUNTER_RX, thread_index,
295  ppif->hw_if_index, n_rx_packets,
296  n_rx_bytes);
297 
298  if (PREDICT_FALSE (pp2_bpool_get_num_buffs (inq->bpool, &n_bufs)))
299  {
300  vlib_error_count (vm, node->node_index,
301  MRVL_PP2_INPUT_ERROR_BPOOL_GET_NUM_BUFFS, 1);
302  goto done;
303  }
304 
305  n_bufs = inq->size - n_bufs;
306  while (n_bufs >= MRVL_PP2_BUFF_BATCH_SZ)
307  {
308  u16 n_alloc, i;
309  struct buff_release_entry *e = ptd->bre;
310  u32 *buffers = ptd->buffers;
311 
312  n_alloc = vlib_buffer_alloc (vm, ptd->buffers, MRVL_PP2_BUFF_BATCH_SZ);
313  i = n_alloc;
314 
315  if (PREDICT_FALSE (n_alloc == 0))
316  {
317  vlib_error_count (vm, node->node_index,
318  MRVL_PP2_INPUT_ERROR_BUFFER_ALLOC, 1);
319  goto done;
320  }
321 
322  while (i--)
323  {
324  u32 bi = buffers[0];
325  vlib_buffer_t *b = vlib_get_buffer (vm, bi);
326  e->buff.addr = vlib_buffer_get_pa (vm, b) - 64;
327  e->buff.cookie = bi;
328  e->bpool = inq->bpool;
329  e++;
330  buffers++;
331  }
332 
333  i = n_alloc;
334  if (PREDICT_FALSE (pp2_bpool_put_buffs (ptd->hif, ptd->bre, &i)))
335  {
336  vlib_error_count (vm, node->node_index,
337  MRVL_PP2_INPUT_ERROR_BPOOL_PUT_BUFFS, 1);
338  vlib_buffer_free (vm, ptd->buffers, n_alloc);
339  goto done;
340  }
341 
342  if (PREDICT_FALSE (i != n_alloc))
343  vlib_buffer_free (vm, ptd->buffers + i, n_alloc - i);
344 
345  n_bufs -= i;
346  }
347 
348 done:
349  return n_rx_packets;
350 }
351 
352 uword
355 {
356  u32 n_rx = 0;
359 
360  pv = vnet_hw_if_get_rxq_poll_vector (vm, node);
361 
362  for (int i = 0; i < vec_len (pv); i++)
363  {
364  mrvl_pp2_if_t *ppif;
365  ppif = vec_elt_at_index (ppm->interfaces, pv[i].dev_instance);
366  if (ppif->flags & MRVL_PP2_IF_F_ADMIN_UP)
367  n_rx +=
368  mrvl_pp2_device_input_inline (vm, node, frame, ppif, pv[i].queue_id);
369  }
370  return n_rx;
371 }
372 
373 /* *INDENT-OFF* */
375  .function = mrvl_pp2_input_fn,
377  .name = "mrvl-pp2-input",
378  .sibling_of = "device-input",
379  .format_trace = format_mrvl_pp2_input_trace,
380  .type = VLIB_NODE_TYPE_INPUT,
381  .state = VLIB_NODE_STATE_POLLING,
382  .n_errors = MRVL_PP2_INPUT_N_ERROR,
383  .error_strings = mrvl_pp2_input_error_strings,
384 };
385 
386 /* *INDENT-ON* */
387 
388 
389 /*
390  * fd.io coding-style-patch-verification: ON
391  *
392  * Local Variables:
393  * eval: (c-set-style "gnu")
394  * End:
395  */
struct pp2_ppio * ppio
Definition: pp2.h:56
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:133
static u32 vlib_get_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt)
Definition: trace_funcs.h:212
static void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: buffer_funcs.h:982
struct buff_release_entry bre[MRVL_PP2_BUFF_BATCH_SZ]
Definition: pp2.h:74
format_function_t format_mrvl_pp2_input_trace
Definition: pp2.h:136
u32 buffers[VLIB_FRAME_SIZE]
Definition: pp2.h:75
struct pp2_ppio_desc desc
Definition: pp2.h:130
static uword vlib_buffer_get_pa(vlib_main_t *vm, vlib_buffer_t *b)
Definition: buffer_funcs.h:488
u32 thread_index
#define PREDICT_TRUE(x)
Definition: clib.h:125
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:119
struct pp2_ppio_desc * descs
Definition: pp2.h:73
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:57
vlib_increment_combined_counter(ccm, ti, sw_if_index, n_buffers, n_bytes)
#define VLIB_NODE_FLAG_TRACE_SUPPORTED
Definition: node.h:296
static_always_inline vnet_hw_if_rxq_poll_vector_t * vnet_hw_if_get_rxq_poll_vector(vlib_main_t *vm, vlib_node_runtime_t *node)
mrvl_pp2_input_error_t
Definition: input.c:43
u32 thread_index
Definition: main.h:213
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:122
static_always_inline void mrvl_pp2_input_trace(vlib_main_t *vm, vlib_node_runtime_t *node, u32 next0, vlib_buffer_t *b0, uword *n_trace, mrvl_pp2_if_t *ppif, struct pp2_ppio_desc *d)
Definition: input.c:58
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
u32 per_interface_next_index
Definition: pp2.h:57
mrvl_pp2_main_t mrvl_pp2_main
Definition: pp2.c:37
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:535
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:461
#define foreach_mrvl_pp2_input_error
Definition: input.c:32
unsigned char u8
Definition: types.h:56
vlib_buffer_t ** b
u32 hw_if_index
Definition: pp2.h:64
unsigned int u32
Definition: types.h:88
struct pp2_bpool * bpool
Definition: pp2.h:39
#define static_always_inline
Definition: clib.h:112
u32 sw_if_index
Definition: pp2.h:63
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
static_always_inline uword mrvl_pp2_device_input_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, mrvl_pp2_if_t *ppif, u16 qid)
Definition: input.c:162
vnet_main_t * vnet_get_main(void)
#define VLIB_FRAME_SIZE
Definition: node.h:369
struct pp2_hif * hif
Definition: pp2.h:72
#define MRVL_PP2_BUFF_BATCH_SZ
Definition: pp2.h:67
uword mrvl_pp2_input_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: input.c:353
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:145
u16 * next
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
static __clib_warn_unused_result u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:708
static __clib_warn_unused_result int vlib_trace_buffer(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, vlib_buffer_t *b, int follow_chain)
Definition: trace_funcs.h:153
unsigned short u16
Definition: types.h:57
static_always_inline u16 mrvl_pp2_set_buf_data_len_flags(vlib_buffer_t *b, struct pp2_ppio_desc *d, u32 add_flags)
Definition: input.c:75
u32 flags
Definition: pp2.h:54
#define PREDICT_FALSE(x)
Definition: clib.h:124
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
u32 node_index
Node index.
Definition: node.h:479
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:224
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:395
static_always_inline void vnet_feature_start_device_input_x2(u32 sw_if_index, u32 *next0, u32 *next1, vlib_buffer_t *b0, vlib_buffer_t *b1)
Definition: feature.h:373
u8 len
Definition: ip_types.api:103
vlib_node_registration_t mrvl_pp2_input_node
(constructor) VLIB_REGISTER_NODE (mrvl_pp2_input_node)
Definition: input.c:374
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
vlib_put_next_frame(vm, node, next_index, 0)
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
Definition: string.h:92
nat44_ei_hairpin_src_next_t next_index
template key/value backing page structure
Definition: bihash_doc.h:44
Definition: defs.h:47
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
VLIB buffer representation.
Definition: buffer.h:111
u64 uword
Definition: types.h:112
struct clib_bihash_value offset
template key/value backing page structure
#define vnet_buffer(b)
Definition: buffer.h:437
static_always_inline void vnet_feature_start_device_input_x1(u32 sw_if_index, u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:343
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:628
mrvl_pp2_if_t * interfaces
Definition: pp2.h:80
mrvl_pp2_per_thread_data_t * per_thread_data
Definition: pp2.h:81
static_always_inline u16 mrvl_pp2_next_from_desc(vlib_node_runtime_t *node, struct pp2_ppio_desc *d, vlib_buffer_t *b, u32 *next)
Definition: input.c:107
static void vlib_set_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt, u32 count)
Definition: trace_funcs.h:226
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
Definition: buffer.h:176
mrvl_pp2_inq_t * inqs
Definition: pp2.h:59
static __clib_unused char * mrvl_pp2_input_error_strings[]
Definition: input.c:51
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
#define MRVL_PP2_IF_F_ADMIN_UP
Definition: pp2.h:55
Definition: defs.h:46
u16 size
Definition: pp2.h:37