FD.io VPP  v21.01.1
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 #include <vlib/vlib.h>
19 #include <vlib/unix/unix.h>
20 #include <vlib/pci/pci.h>
21 #include <vnet/ethernet/ethernet.h>
22 #include <vnet/devices/devices.h>
23 
24 #include <rdma/rdma.h>
25 
26 #define foreach_rdma_input_error \
27  _(BUFFER_ALLOC, "buffer alloc error")
28 
29 typedef enum
30 {
31 #define _(f,s) RDMA_INPUT_ERROR_##f,
33 #undef _
36 
37 static __clib_unused char *rdma_input_error_strings[] = {
38 #define _(n,s) s,
40 #undef _
41 };
42 
43 
45 ibv_set_recv_wr_and_sge (struct ibv_recv_wr *w, struct ibv_sge *s, u64 va,
46  u32 data_size, u32 lkey)
47 {
48  s[0].addr = va;
49  s[0].length = data_size;
50  s[0].lkey = lkey;
51  w[0].next = w + 1;
52  w[0].sg_list = s;
53  w[0].num_sge = 1;
54 }
55 
58  rdma_device_t * rd,
59  rdma_rxq_t * rxq,
61  vlib_buffer_t * bt,
62  u32 first_slot, u32 n_alloc)
63 {
64  int i;
65  u8 log_wqe_sz = rxq->log_wqe_sz;
66  u32 *bi = ptd->tmp_bi;
67  vlib_buffer_t **bufs = ptd->tmp_bufs;
68 
69  for (i = 0; i < n_alloc; i++)
70  {
71  u8 chain_sz = rxq->n_used_per_chain[first_slot + i];
72  u8 chain_sz_alloc;
73  mlx5dv_wqe_ds_t *current_wqe =
74  rxq->wqes + ((first_slot + i) << log_wqe_sz);
75  if (chain_sz == 0)
76  continue;
77  if (PREDICT_FALSE ((chain_sz_alloc =
78  vlib_buffer_alloc_from_pool (vm, bi, chain_sz,
79  rd->pool)) !=
80  chain_sz))
81  {
82  vlib_buffer_free (vm, bi, chain_sz_alloc);
83  break;
84  }
85  /*Build the chain */
86  vlib_get_buffers (vm, bi, bufs, chain_sz);
87  for (int j = 0; j < chain_sz - 1; j++)
88  {
89  vlib_buffer_copy_template (bufs[j], bt);
90  bufs[j]->next_buffer = bi[j + 1];
91  bufs[j]->flags |= VLIB_BUFFER_NEXT_PRESENT;
92  }
93  /* The chain starting at the second buffer is pre-initialised */
94  vlib_buffer_copy_template (bufs[chain_sz - 1], bt);
95  /* Stick with the already existing chain */
96  if (chain_sz < rxq->n_ds_per_wqe - 1)
97  {
98  bufs[chain_sz - 1]->next_buffer = rxq->second_bufs[first_slot + i];
99  bufs[chain_sz - 1]->flags |= VLIB_BUFFER_NEXT_PRESENT;
100  }
101  else
102  {
103  bufs[chain_sz - 1]->flags &= ~VLIB_BUFFER_NEXT_PRESENT;
104  }
105 
106  /* Update the wqes */
107  for (int j = 0; j < chain_sz; j++)
108  {
109  u64 addr;
110  vlib_get_buffers_with_offset (vm, bi + j,
111  (void *) &addr, 1,
112  sizeof (vlib_buffer_t));
113  current_wqe[j + 1].addr = clib_host_to_net_u64 (addr);
114  }
115  rxq->n_used_per_chain[first_slot + i] = 0;
116  rxq->n_total_additional_segs -= chain_sz;
117  rxq->second_bufs[first_slot + i] = bi[0];
118  }
119  return i;
120 }
121 
124  rdma_rxq_t * rxq, vlib_buffer_t * bt,
125  const int is_mlx5dv, const int is_striding)
126 {
127  u32 n_alloc, n;
128  u16 ring_space;
129  struct ibv_recv_wr wr[VLIB_FRAME_SIZE], *w = wr;
130  struct ibv_sge sge[VLIB_FRAME_SIZE], *s = sge;
133  u32 mask = rxq->size - 1;
134  u32 slot = rxq->tail & mask;
135  u32 *bufs = rxq->bufs + slot;
136  u32 data_size = rxq->buf_sz;
137  u32 lkey = rd->lkey;
138  const int log_stride_per_wqe = is_striding ? rxq->log_stride_per_wqe : 0;
139  const int log_wqe_sz = rxq->log_wqe_sz;
140 
141  /*In legacy mode, maybe some buffers chains are incomplete? */
142  if (PREDICT_FALSE
143  (is_mlx5dv && !is_striding && (rxq->incomplete_tail != rxq->tail)))
144  {
145  int n_incomplete = rxq->incomplete_tail - rxq->tail;
146  int n_completed =
147  rdma_device_legacy_input_refill_additional (vm, rd, rxq, ptd, bt,
148  slot,
149  n_incomplete);
150  rxq->tail += n_completed;
151  slot = rxq->tail & mask;
152  /* Don't start recycling head buffers if there are incomplete chains */
153  if (n_completed != n_incomplete)
154  return;
155  }
156 
157  /* refilled buffers must be a multiple of 8 and of strides per WQE */
158  u32 alloc_multiple = 1 << (clib_max (3, log_stride_per_wqe));
159 
160  ring_space = rxq->size - (rxq->tail - rxq->head);
161 
162  n_alloc = clib_min (VLIB_FRAME_SIZE, ring_space);
163 
164  /* do not bother to allocate if too small */
165  if (n_alloc < 2 * alloc_multiple)
166  return;
167 
168  /* avoid wrap-around logic in core loop */
169  n_alloc = clib_min (n_alloc, rxq->size - slot);
170 
171  n_alloc &= ~(alloc_multiple - 1); /* round to alloc_multiple */
172 
173  n = vlib_buffer_alloc_to_ring_from_pool (vm, rxq->bufs, slot, rxq->size,
174  n_alloc, rd->pool);
175 
176  if (PREDICT_FALSE (n != n_alloc))
177  {
178  u32 n_free;
179  if (n < alloc_multiple)
180  {
181  if (n)
182  vlib_buffer_free_from_ring (vm, rxq->bufs, slot, rxq->size, n);
183  return;
184  }
185 
186  /* partial allocation, round and return rest */
187  n_free = n & (alloc_multiple - 1);
188  n -= n_free;
189  if (n_free)
190  vlib_buffer_free_from_ring (vm, rxq->bufs, (slot + n) & mask,
191  rxq->size, n_free);
192  }
193 
194  n_alloc = n;
195 
196  if (is_mlx5dv)
197  {
198  u64 __clib_aligned (32) va[8];
199 
200  /* slot does not necessarily correspond to the slot
201  in the wqes ring (in 16B words) */
202  u32 wqes_slot = slot << (log_wqe_sz - log_stride_per_wqe);
203  const u32 wqe_cnt = rxq->wqe_cnt;
204  mlx5dv_wqe_ds_t *wqe = rxq->wqes + wqes_slot;
205  const int wqe_sz = 1 << log_wqe_sz;
206  const int stride_per_wqe = 1 << log_stride_per_wqe;
207  int current_data_seg = 0;
208 
209  /* In legacy mode, this function only refills head descriptors for each
210  WQE, so RDMA_RXQ_MAX_CHAIN_SZ-1 data segments are skipped per WQE */
211  const int log_skip_wqe = is_striding ? 0 : log_wqe_sz;
212 
213  while (n >= 1)
214  {
215  vlib_get_buffers_with_offset (vm, rxq->bufs + slot, (void **) va, 8,
216  sizeof (vlib_buffer_t));
217 #ifdef CLIB_HAVE_VEC256
218  *(u64x4 *) va = u64x4_byte_swap (*(u64x4 *) va);
219  *(u64x4 *) (va + 4) = u64x4_byte_swap (*(u64x4 *) (va + 4));
220 #else
221  for (int i = 0; i < 8; i++)
222  va[i] = clib_host_to_net_u64 (va[i]);
223 #endif
224 
225  /*In striding RQ mode, the first 16B-word of the WQE is the SRQ header.
226  It is initialised as if it were a LINKED_LIST, as we have no guarantee
227  about what RDMA core does (CYCLIC_RQ or LINKED_LIST_RQ). In cyclic
228  mode, the SRQ header is ignored anyways... */
229 
230 /* *INDENT-OFF* */
231  if (is_striding && !(current_data_seg & (wqe_sz - 1)))
233  {
234  .rsvd0 = {0},
235  .next_wqe_index = clib_host_to_net_u16 (((wqes_slot >> log_wqe_sz) + 1) & (wqe_cnt - 1)),
236  .signature = 0,
237  .rsvd1 = {0}
238  };
239 /* *INDENT-ON* */
240 
241  /* TODO: when log_skip_wqe > 2, hw_prefetcher doesn't work, lots of LLC store
242  misses occur for wqes, to be fixed... */
243  if (!is_striding || !(current_data_seg & ~(stride_per_wqe - 1)))
244  {
245  wqe[(0 << log_skip_wqe) + is_striding].addr = va[0];
246  wqe[(1 << log_skip_wqe) + is_striding].addr = va[1];
247  wqe[(2 << log_skip_wqe) + is_striding].addr = va[2];
248  wqe[(3 << log_skip_wqe) + is_striding].addr = va[3];
249  wqe[(4 << log_skip_wqe) + is_striding].addr = va[4];
250  wqe[(5 << log_skip_wqe) + is_striding].addr = va[5];
251  wqe[(6 << log_skip_wqe) + is_striding].addr = va[6];
252  wqe[(7 << log_skip_wqe) + is_striding].addr = va[7];
253  slot += 8;
254  n -= 8;
255  }
256  wqe += 8 << log_skip_wqe;
257  wqes_slot += 8 << log_skip_wqe;
258  current_data_seg += 8;
259  current_data_seg &= wqe_sz - 1;
260  }
261 
262  /* In legacy mode, there is some work required to finish building the SG lists */
263  if (!is_striding)
264  {
265  int first_slot = slot - n_alloc;
266  rxq->incomplete_tail += n_alloc;
268  n_alloc =
270  bt, first_slot,
271  n_alloc);
272  }
274  rxq->tail += n_alloc;
275  if (is_striding)
276  {
277  rxq->striding_wqe_tail += n_alloc >> log_stride_per_wqe;
278  rxq->wq_db[MLX5_RCV_DBR] =
279  clib_host_to_net_u32 (rxq->striding_wqe_tail);
280  }
281  else
282  rxq->wq_db[MLX5_RCV_DBR] = clib_host_to_net_u32 (rxq->tail);
283  return;
284  }
285 
286  while (n >= 8)
287  {
288  u64 va[8];
289  if (PREDICT_TRUE (n >= 16))
290  {
291  clib_prefetch_store (s + 16);
292  clib_prefetch_store (w + 16);
293  }
294 
295  vlib_get_buffers_with_offset (vm, bufs, (void **) va, 8,
296  sizeof (vlib_buffer_t));
297 
298  ibv_set_recv_wr_and_sge (w++, s++, va[0], data_size, lkey);
299  ibv_set_recv_wr_and_sge (w++, s++, va[1], data_size, lkey);
300  ibv_set_recv_wr_and_sge (w++, s++, va[2], data_size, lkey);
301  ibv_set_recv_wr_and_sge (w++, s++, va[3], data_size, lkey);
302  ibv_set_recv_wr_and_sge (w++, s++, va[4], data_size, lkey);
303  ibv_set_recv_wr_and_sge (w++, s++, va[5], data_size, lkey);
304  ibv_set_recv_wr_and_sge (w++, s++, va[6], data_size, lkey);
305  ibv_set_recv_wr_and_sge (w++, s++, va[7], data_size, lkey);
306 
307  bufs += 8;
308  n -= 8;
309  }
310 
311  w[-1].next = 0; /* fix next pointer in WR linked-list last item */
312 
313  n = n_alloc;
314  if (ibv_post_wq_recv (rxq->wq, wr, &w) != 0)
315  {
316  n = w - wr;
317  vlib_buffer_free_from_ring (vm, rxq->bufs, slot + n, rxq->size,
318  n_alloc - n);
319  }
320 
321  rxq->tail += n;
322 }
323 
326  const rdma_device_t * rd, u32 n_left,
327  const u32 * bi, u32 next_index, u16 * cqe_flags,
328  int is_mlx5dv)
329 {
330  u32 n_trace = vlib_get_trace_count (vm, node);
331 
332  if (PREDICT_TRUE (0 == n_trace))
333  return;
334 
335  while (n_trace && n_left)
336  {
337  vlib_buffer_t *b = vlib_get_buffer (vm, bi[0]);
338  if (PREDICT_TRUE
339  (vlib_trace_buffer (vm, node, next_index, b, /* follow_chain */ 0)))
340  {
341  rdma_input_trace_t *tr = vlib_add_trace (vm, node, b, sizeof (*tr));
342  tr->next_index = next_index;
343  tr->hw_if_index = rd->hw_if_index;
344  tr->cqe_flags = is_mlx5dv ? clib_net_to_host_u16 (cqe_flags[0]) : 0;
345  n_trace--;
346  }
347  /* next */
348  n_left--;
349  cqe_flags++;
350  bi++;
351  }
352  vlib_set_trace_count (vm, node, n_trace);
353 }
354 
357  const rdma_device_t * rd, u32 next_index,
358  int skip_ip4_cksum)
359 {
360  vlib_next_frame_t *nf;
361  vlib_frame_t *f;
363 
365  return;
366 
367  nf =
370  f = vlib_get_frame (vm, nf->frame);
372  if (skip_ip4_cksum)
374 
375  ef = vlib_frame_scalar_args (f);
376  ef->sw_if_index = rd->sw_if_index;
377  ef->hw_if_index = rd->hw_if_index;
378 }
379 
382  vlib_buffer_t ** b, struct ibv_wc *wc,
383  u32 n_left_from, vlib_buffer_t * bt)
384 {
385  u32 n_rx_bytes = 0;
386 
387  while (n_left_from >= 4)
388  {
389  if (PREDICT_TRUE (n_left_from >= 8))
390  {
391  CLIB_PREFETCH (&wc[4 + 0], CLIB_CACHE_LINE_BYTES, LOAD);
392  CLIB_PREFETCH (&wc[4 + 1], CLIB_CACHE_LINE_BYTES, LOAD);
393  CLIB_PREFETCH (&wc[4 + 2], CLIB_CACHE_LINE_BYTES, LOAD);
394  CLIB_PREFETCH (&wc[4 + 3], CLIB_CACHE_LINE_BYTES, LOAD);
395  vlib_prefetch_buffer_header (b[4 + 0], STORE);
396  vlib_prefetch_buffer_header (b[4 + 1], STORE);
397  vlib_prefetch_buffer_header (b[4 + 2], STORE);
398  vlib_prefetch_buffer_header (b[4 + 3], STORE);
399  }
400 
401  vlib_buffer_copy_template (b[0], bt);
402  vlib_buffer_copy_template (b[1], bt);
403  vlib_buffer_copy_template (b[2], bt);
404  vlib_buffer_copy_template (b[3], bt);
405 
406  n_rx_bytes += b[0]->current_length = wc[0].byte_len;
407  n_rx_bytes += b[1]->current_length = wc[1].byte_len;
408  n_rx_bytes += b[2]->current_length = wc[2].byte_len;
409  n_rx_bytes += b[3]->current_length = wc[3].byte_len;
410 
411  b += 4;
412  wc += 4;
413  n_left_from -= 4;
414  }
415 
416  while (n_left_from >= 1)
417  {
418  vlib_buffer_copy_template (b[0], bt);
419  n_rx_bytes += b[0]->current_length = wc[0].byte_len;
420 
421  b += 1;
422  wc += 1;
423  n_left_from -= 1;
424  }
425 
426  return n_rx_bytes;
427 }
428 
430 process_mini_cqes (rdma_rxq_t * rxq, u32 skip, u32 n_left, u32 cq_ci,
431  u32 mask, u32 * byte_cnt)
432 {
433  mlx5dv_mini_cqe_t *mcqe;
434  u32 mcqe_array_index = (cq_ci + 1) & mask;
435  mcqe = (mlx5dv_mini_cqe_t *) (rxq->cqes + mcqe_array_index);
436 
437  mcqe_array_index = cq_ci;
438 
439  if (skip)
440  {
441  u32 n = skip & ~7;
442 
443  if (n)
444  {
445  mcqe_array_index = (mcqe_array_index + n) & mask;
446  mcqe = (mlx5dv_mini_cqe_t *) (rxq->cqes + mcqe_array_index);
447  skip -= n;
448  }
449 
450  if (skip)
451  {
452  n = clib_min (8 - skip, n_left);
453  for (int i = 0; i < n; i++)
454  byte_cnt[i] = mcqe[skip + i].byte_count;
455  mcqe_array_index = (mcqe_array_index + 8) & mask;
456  mcqe = (mlx5dv_mini_cqe_t *) (rxq->cqes + mcqe_array_index);
457  n_left -= n;
458  byte_cnt += n;
459  }
460 
461  }
462 
463  while (n_left >= 8)
464  {
465  for (int i = 0; i < 8; i++)
466  byte_cnt[i] = mcqe[i].byte_count;
467 
468  n_left -= 8;
469  byte_cnt += 8;
470  mcqe_array_index = (mcqe_array_index + 8) & mask;
471  mcqe = (mlx5dv_mini_cqe_t *) (rxq->cqes + mcqe_array_index);
472  }
473 
474  if (n_left)
475  {
476  for (int i = 0; i < n_left; i++)
477  byte_cnt[i] = mcqe[i].byte_count;
478  }
479 }
480 
482 cqe_set_owner (mlx5dv_cqe_t * cqe, u32 n_left, u8 owner)
483 {
484  while (n_left >= 8)
485  {
486  cqe[0].opcode_cqefmt_se_owner = owner;
487  cqe[1].opcode_cqefmt_se_owner = owner;
488  cqe[2].opcode_cqefmt_se_owner = owner;
489  cqe[3].opcode_cqefmt_se_owner = owner;
490  cqe[4].opcode_cqefmt_se_owner = owner;
491  cqe[5].opcode_cqefmt_se_owner = owner;
492  cqe[6].opcode_cqefmt_se_owner = owner;
493  cqe[7].opcode_cqefmt_se_owner = owner;
494  n_left -= 8;
495  cqe += 8;
496  }
497  while (n_left)
498  {
499  cqe[0].opcode_cqefmt_se_owner = owner;
500  n_left--;
501  cqe++;
502  }
503 }
504 
506 compressed_cqe_reset_owner (rdma_rxq_t * rxq, u32 n_mini_cqes, u32 cq_ci,
507  u32 mask, u32 log2_cq_size)
508 {
509  u8 owner;
510  u32 offset, cq_size = 1 << log2_cq_size;
511 
512 
513  /* first CQE is reset by hardware */
514  cq_ci++;
515  n_mini_cqes--;
516 
517  offset = cq_ci & mask;
518  owner = 0xf0 | ((cq_ci >> log2_cq_size) & 1);
519 
520  if (offset + n_mini_cqes < cq_size)
521  {
522  cqe_set_owner (rxq->cqes + offset, n_mini_cqes, owner);
523  }
524  else
525  {
526  u32 n = cq_size - offset;
527  cqe_set_owner (rxq->cqes + offset, n, owner);
528  cqe_set_owner (rxq->cqes, n_mini_cqes - n, owner ^ 1);
529  }
530 
531 }
532 
535  u32 * byte_cnt, u16 * cqe_flags)
536 {
537  u32 n_rx_packets = 0;
538  u32 log2_cq_size = rxq->log2_cq_size;
539  u32 mask = pow2_mask (log2_cq_size);
540  u32 cq_ci = rxq->cq_ci;
541 
542  if (rxq->n_mini_cqes_left)
543  {
544  /* partially processed mini-cqe array */
545  u32 n_mini_cqes = rxq->n_mini_cqes;
546  u32 n_mini_cqes_left = rxq->n_mini_cqes_left;
547  process_mini_cqes (rxq, n_mini_cqes - n_mini_cqes_left,
548  n_mini_cqes_left, cq_ci, mask, byte_cnt);
549  compressed_cqe_reset_owner (rxq, n_mini_cqes, cq_ci, mask,
550  log2_cq_size);
551  clib_memset_u16 (cqe_flags, rxq->last_cqe_flags, n_mini_cqes_left);
552  n_rx_packets = n_mini_cqes_left;
553  byte_cnt += n_mini_cqes_left;
554  cqe_flags += n_mini_cqes_left;
555  rxq->n_mini_cqes_left = 0;
556  rxq->cq_ci = cq_ci = cq_ci + n_mini_cqes;
557  }
558 
559  while (n_rx_packets < VLIB_FRAME_SIZE)
560  {
561  u8 cqe_last_byte, owner;
562  mlx5dv_cqe_t *cqe = rxq->cqes + (cq_ci & mask);
563 
564  clib_prefetch_load (rxq->cqes + ((cq_ci + 8) & mask));
565 
566  owner = (cq_ci >> log2_cq_size) & 1;
567  cqe_last_byte = cqe->opcode_cqefmt_se_owner;
568 
569  if ((cqe_last_byte & 0x1) != owner)
570  break;
571 
572  cqe_last_byte &= 0xfc; /* remove owner and solicited bits */
573 
574  if (cqe_last_byte == 0x2c) /* OPCODE = 0x2 (Responder Send), Format = 0x3 (Compressed CQE) */
575  {
576  u32 n_mini_cqes = clib_net_to_host_u32 (cqe->mini_cqe_num);
577  u32 n_left = VLIB_FRAME_SIZE - n_rx_packets;
578  u16 flags = cqe->flags;
579 
580  if (n_left >= n_mini_cqes)
581  {
582  process_mini_cqes (rxq, 0, n_mini_cqes, cq_ci, mask, byte_cnt);
583  clib_memset_u16 (cqe_flags, flags, n_mini_cqes);
584  compressed_cqe_reset_owner (rxq, n_mini_cqes, cq_ci, mask,
585  log2_cq_size);
586  n_rx_packets += n_mini_cqes;
587  byte_cnt += n_mini_cqes;
588  cqe_flags += n_mini_cqes;
589  cq_ci += n_mini_cqes;
590  }
591  else
592  {
593  process_mini_cqes (rxq, 0, n_left, cq_ci, mask, byte_cnt);
594  clib_memset_u16 (cqe_flags, flags, n_left);
595  n_rx_packets = VLIB_FRAME_SIZE;
596  rxq->n_mini_cqes = n_mini_cqes;
597  rxq->n_mini_cqes_left = n_mini_cqes - n_left;
598  rxq->last_cqe_flags = flags;
599  goto done;
600  }
601  continue;
602  }
603 
604  if (cqe_last_byte == 0x20) /* OPCODE = 0x2 (Responder Send), Format = 0x0 (no inline data) */
605  {
606  byte_cnt[0] = cqe->byte_cnt;
607  cqe_flags[0] = cqe->flags;
608  n_rx_packets++;
609  cq_ci++;
610  byte_cnt++;
611  continue;
612  }
613 
614  rd->flags |= RDMA_DEVICE_F_ERROR;
615  break;
616  }
617 
618 done:
619  if (n_rx_packets)
620  rxq->cq_db[0] = rxq->cq_ci = cq_ci;
621  return n_rx_packets;
622 }
623 
625 rdma_device_mlx5dv_striding_rq_parse_bc (int n_rx_packets, int *n_rx_segs,
626  u32 * bc)
627 {
628 /* Determine if slow path is needed */
629  int filler = 0;
630  for (int i = 0; i < n_rx_packets; i++)
631  {
632  *n_rx_segs +=
635  filler |= ! !(bc[i] & CQE_BC_FILLER_MASK);
636  }
637  return n_rx_packets != *n_rx_segs || filler;
638 }
639 
642  u32 * bc)
643 {
644 #if defined CLIB_HAVE_VEC256
645  u32x8 thresh8 = u32x8_splat (buf_sz);
646  for (int i = 0; i < n_rx_packets; i += 8)
647  if (!u32x8_is_all_zero (*(u32x8 *) (bc + i) > thresh8))
648  return 1;
649 #elif defined CLIB_HAVE_VEC128
650  u32x4 thresh4 = u32x4_splat (buf_sz);
651  for (int i = 0; i < n_rx_packets; i += 4)
652  if (!u32x4_is_all_zero (*(u32x4 *) (bc + i) > thresh4))
653  return 1;
654 #else
655  while (n_rx_packets)
656  {
657  if (*bc > buf_sz)
658  return 1;
659  bc++;
660  n_rx_packets--;
661  }
662 #endif
663 
664  return 0;
665 }
666 
669  * ptd, int n_rx_packets, u32 * bc)
670 {
673 
674  /* verify that all ip4 packets have l3_ok flag set and convert packet
675  length from network to host byte order */
676  int skip_ip4_cksum = 1;
677 
678 #if defined CLIB_HAVE_VEC256
679  u16x16 mask16 = u16x16_splat (mask);
680  u16x16 match16 = u16x16_splat (match);
681  u16x16 r = { };
682 
683  for (int i = 0; i * 16 < n_rx_packets; i++)
684  r |= (ptd->cqe_flags16[i] & mask16) != match16;
685 
686  if (!u16x16_is_all_zero (r))
687  skip_ip4_cksum = 0;
688 
689  for (int i = 0; i < n_rx_packets; i += 8)
690  *(u32x8 *) (bc + i) = u32x8_byte_swap (*(u32x8 *) (bc + i));
691 #elif defined CLIB_HAVE_VEC128
692  u16x8 mask8 = u16x8_splat (mask);
693  u16x8 match8 = u16x8_splat (match);
694  u16x8 r = { };
695 
696  for (int i = 0; i * 8 < n_rx_packets; i++)
697  r |= (ptd->cqe_flags8[i] & mask8) != match8;
698 
699  if (!u16x8_is_all_zero (r))
700  skip_ip4_cksum = 0;
701 
702  for (int i = 0; i < n_rx_packets; i += 4)
703  *(u32x4 *) (bc + i) = u32x4_byte_swap (*(u32x4 *) (bc + i));
704 #else
705  for (int i = 0; i < n_rx_packets; i++)
706  if ((ptd->cqe_flags[i] & mask) == match)
707  skip_ip4_cksum = 0;
708 
709  for (int i = 0; i < n_rx_packets; i++)
710  bc[i] = clib_net_to_host_u32 (bc[i]);
711 #endif
712  return skip_ip4_cksum;
713 }
714 
717  vlib_buffer_t ** bufs,
718  u32 qs_mask, vlib_buffer_t * bt,
719  u32 * to_next, u32 n_rx_segs, u32 * bc,
720  u32 bc_mask)
721 {
722  vlib_buffer_t **b = bufs;
723  u32 n_left = n_rx_segs;
724  u32 n_rx_bytes = 0;
726  rxq->head & qs_mask, rxq->size,
727  n_rx_segs);
728  rxq->head += n_rx_segs;
729  vlib_get_buffers (vm, to_next, bufs, n_rx_segs);
730  while (n_left >= 8)
731  {
732  clib_prefetch_store (b[4]);
733  vlib_buffer_copy_template (b[0], bt);
734  n_rx_bytes += b[0]->current_length = bc[0] & bc_mask;
735  clib_prefetch_store (b[5]);
736  vlib_buffer_copy_template (b[1], bt);
737  n_rx_bytes += b[1]->current_length = bc[1] & bc_mask;
738  clib_prefetch_store (b[6]);
739  vlib_buffer_copy_template (b[2], bt);
740  n_rx_bytes += b[2]->current_length = bc[2] & bc_mask;
741  clib_prefetch_store (b[7]);
742  vlib_buffer_copy_template (b[3], bt);
743  n_rx_bytes += b[3]->current_length = bc[3] & bc_mask;
744  /* next */
745  bc += 4;
746  b += 4;
747  n_left -= 4;
748  }
749  while (n_left)
750  {
751  vlib_buffer_copy_template (b[0], bt);
752  n_rx_bytes += b[0]->current_length = bc[0] & bc_mask;
753  /* next */
754  bc++;
755  b++;
756  n_left--;
757  }
758  return n_rx_bytes;
759 }
760 
763  vlib_buffer_t ** bufs, u32 qs_mask,
764  u32 n)
765 {
766  u32 buf_sz = rxq->buf_sz;
767  uword slot = (rxq->head - n) & qs_mask;
768  u32 *second = &rxq->second_bufs[slot];
769  u32 n_wrap_around = (slot + n) & (qs_mask + 1) ? (slot + n) & qs_mask : 0;
770  u8 *n_used_per_chain = &rxq->n_used_per_chain[slot];
771  n -= n_wrap_around;
772 wrap_around:
773  while (n > 0)
774  {
775  u16 total_length = bufs[0]->current_length;
776  if (total_length > buf_sz)
777  {
778  vlib_buffer_t *current_buf = bufs[0];
779  u8 current_chain_sz = 0;
780  current_buf->current_length = buf_sz;
781  total_length -= buf_sz;
782  current_buf->total_length_not_including_first_buffer = total_length;
783  current_buf->flags |= VLIB_BUFFER_NEXT_PRESENT;
784  current_buf->next_buffer = second[0];
785  do
786  {
787  current_buf = vlib_get_buffer (vm, current_buf->next_buffer);
788  current_buf->current_length = clib_min (buf_sz, total_length);
789  total_length -= current_buf->current_length;
790  current_chain_sz++;
791  }
792  while (total_length > 0);
793  current_buf->flags &= ~VLIB_BUFFER_NEXT_PRESENT;
794  second[0] = current_buf->next_buffer;
795  current_buf->next_buffer = 0;
796  rxq->n_total_additional_segs += current_chain_sz;
797  n_used_per_chain[0] = current_chain_sz;
798  }
799  bufs++;
800  second++;
801  n_used_per_chain++;
802  n--;
803  }
804  if (PREDICT_FALSE (n_wrap_around))
805  {
806  n = n_wrap_around;
807  n_wrap_around = 0;
808  second = rxq->second_bufs;
809  n_used_per_chain = rxq->n_used_per_chain;
810  goto wrap_around;
811  }
812 }
813 
817  rdma_rxq_t * rxq,
818  vlib_buffer_t * bt, u32 * to_next,
819  int n_rx_segs, int *n_rx_packets,
820  u32 * bc, int slow_path_needed)
821 {
822  u32 mask = rxq->size - 1;
823  u32 n_rx_bytes = 0;
824  if (PREDICT_TRUE (!slow_path_needed))
825  {
827  n_rx_bytes +=
828  rdma_device_mlx5dv_fast_input (vm, rxq, bufs, mask, bt, to_next,
829  n_rx_segs, bc, CQE_BC_BYTE_COUNT_MASK);
830  }
831  else /* Slow path with multiseg */
832  {
833  vlib_buffer_t *pkt_head; /*Current head buffer */
834  vlib_buffer_t *pkt_prev; /* Buffer processed at the previous iteration */
835  u32 pkt_head_idx;
836  vlib_buffer_t **pkt;
837  uword n_segs_remaining = 0; /*Remaining strides in current buffer */
838  u32 n_bytes_remaining = 0; /*Remaining bytes in current buffer */
839  u32 *next_in_frame = to_next;
840  u32 *next_to_free = ptd->to_free_buffers;
842  do
843  {
845  u32 n_left = clib_min (n_rx_segs, VLIB_FRAME_SIZE);
846  n_rx_segs -= n_left;
848  rxq->bufs, rxq->head & mask,
849  rxq->size, n_left);
850  rxq->head += n_left;
851  vlib_get_buffers (vm, ptd->current_segs, bufs, n_left);
852  pkt = bufs;
853  while (n_left > 0)
854  {
855  /* Initialize the current buffer as full size */
856  vlib_buffer_copy_template (pkt[0], bt);
857  if (!n_segs_remaining) /* No pending chain */
858  {
859  n_segs_remaining =
860  (bc[0] & CQE_BC_CONSUMED_STRIDES_MASK) >>
862  pkt_head = pkt[0];
863  pkt_head_idx = ptd->current_segs[pkt - bufs];
864  n_bytes_remaining = bc[0] & CQE_BC_BYTE_COUNT_MASK;
866  n_segs_remaining >
867  1 ? n_bytes_remaining - pkt[0]->current_length : 0;
868  }
869  else /* Perform chaining if it's a continuation buffer */
870  {
871  pkt_prev->next_buffer = ptd->current_segs[pkt - bufs];
872  pkt_prev->flags |= VLIB_BUFFER_NEXT_PRESENT;
873  pkt[0]->flags &= ~VLIB_BUFFER_TOTAL_LENGTH_VALID;
874  }
875  if (n_segs_remaining == 1) /* Last buffer of the chain */
876  {
877  pkt[0]->current_length = n_bytes_remaining;
878  if (bc[0] & CQE_BC_FILLER_MASK)
879  {
880  (next_to_free++)[0] = pkt_head_idx;
881  (*n_rx_packets)--;
882  }
883 
884  else
885  {
886  (next_in_frame++)[0] = pkt_head_idx;
887  n_rx_bytes +=
888  pkt_head->current_length +
890  }
891  /*Go to next CQE */
892  bc++;
893  }
894  else
895  {
896  n_bytes_remaining -= pkt[0]->current_length;
897  pkt_prev = pkt[0];
898  }
899  n_segs_remaining--;
900  n_left--;
901  pkt++;
902  }
903 
904  }
905  while (n_rx_segs > 0);
907  next_to_free - ptd->to_free_buffers);
908  }
909  return n_rx_bytes;
910 }
911 
915  u16 qid, const int use_mlx5dv)
916 {
917  rdma_main_t *rm = &rdma_main;
918  vnet_main_t *vnm = vnet_get_main ();
920  vm->thread_index);
921  rdma_rxq_t *rxq = vec_elt_at_index (rd->rxqs, qid);
922  struct ibv_wc wc[VLIB_FRAME_SIZE];
923  u32 __clib_aligned (32) byte_cnts[VLIB_FRAME_SIZE];
924  vlib_buffer_t bt;
925  u32 next_index, *to_next, n_left_to_next, n_rx_bytes = 0;
926  int n_rx_packets, skip_ip4_cksum = 0;
927  u32 mask = rxq->size - 1;
928  const int is_striding = ! !(rd->flags & RDMA_DEVICE_F_STRIDING_RQ);
929 
930  if (use_mlx5dv)
931  n_rx_packets = rdma_device_poll_cq_mlx5dv (rd, rxq, byte_cnts,
932  ptd->cqe_flags);
933  else
934  n_rx_packets = ibv_poll_cq (rxq->cq, VLIB_FRAME_SIZE, wc);
935 
936  /* init buffer template */
938  vnet_buffer (&bt)->sw_if_index[VLIB_RX] = rd->sw_if_index;
939  bt.buffer_pool_index = rd->pool;
940 
941  if (PREDICT_FALSE (n_rx_packets <= 0))
942  goto refill;
943 
944  /* update buffer template for input feature arcs if any */
945  next_index = rd->per_interface_next_index;
947  vnet_feature_start_device_input_x1 (rd->sw_if_index, &next_index, &bt);
948 
949  vlib_get_new_next_frame (vm, node, next_index, to_next, n_left_to_next);
950 
951  if (use_mlx5dv)
952  {
953  u32 *bc = byte_cnts;
954  int slow_path_needed;
955  skip_ip4_cksum =
956  rdma_device_mlx5dv_l3_validate_and_swap_bc (ptd, n_rx_packets, bc);
957  if (is_striding)
958  {
959  int n_rx_segs = 0;
960  slow_path_needed =
962  &n_rx_segs, bc);
963  n_rx_bytes =
964  rdma_device_mlx5dv_striding_rq_input (vm, ptd, rxq, &bt,
965  to_next, n_rx_segs,
966  &n_rx_packets, bc,
967  slow_path_needed);
968  }
969  else
970  {
972  slow_path_needed =
974  n_rx_packets, bc);
975  n_rx_bytes =
976  rdma_device_mlx5dv_fast_input (vm, rxq, bufs, mask, &bt, to_next,
977  n_rx_packets, bc, ~0);
978 
979  /* If there are chained buffers, some of the head buffers have a current length
980  higher than buf_sz: it needs to be fixed */
981  if (PREDICT_FALSE (slow_path_needed))
982  rdma_device_mlx5dv_legacy_rq_fix_chains (vm, rxq, bufs, mask,
983  n_rx_packets);
984  }
985  }
986  else
987  {
990  rxq->head & mask,
991  rxq->size, n_rx_packets);
992  vlib_get_buffers (vm, to_next, bufs, n_rx_packets);
993  rxq->head += n_rx_packets;
994  n_rx_bytes =
995  rdma_device_input_bufs (vm, rd, bufs, wc, n_rx_packets, &bt);
996 
997  }
998 
999  rdma_device_input_ethernet (vm, node, rd, next_index, skip_ip4_cksum);
1000  vlib_put_next_frame (vm, node, next_index, n_left_to_next - n_rx_packets);
1001  rdma_device_input_trace (vm, node, rd, n_rx_packets, to_next,
1002  next_index, ptd->cqe_flags, use_mlx5dv);
1003  /* reset flags to zero for the next run */
1004  if (use_mlx5dv)
1005  clib_memset_u16 (ptd->cqe_flags, 0, VLIB_FRAME_SIZE);
1007  combined_sw_if_counters +
1009  vm->thread_index, rd->hw_if_index,
1010  n_rx_packets, n_rx_bytes);
1011 refill:
1012  rdma_device_input_refill (vm, rd, rxq, &bt, use_mlx5dv, is_striding);
1013  return n_rx_packets;
1014 }
1015 
1018  vlib_frame_t * frame)
1019 {
1020  u32 n_rx = 0;
1021  rdma_main_t *rm = &rdma_main;
1022  vnet_device_input_runtime_t *rt = (void *) node->runtime_data;
1024 
1026  {
1027  rdma_device_t *rd;
1028  rd = vec_elt_at_index (rm->devices, dq->dev_instance);
1029  if (PREDICT_TRUE (rd->flags & RDMA_DEVICE_F_ADMIN_UP) == 0)
1030  continue;
1031 
1032  if (PREDICT_TRUE (rd->flags & RDMA_DEVICE_F_ERROR))
1033  continue;
1034 
1035  if (PREDICT_TRUE (rd->flags & RDMA_DEVICE_F_MLX5DV))
1036  n_rx += rdma_device_input_inline (vm, node, frame, rd, dq->queue_id, 1);
1037  else
1038  n_rx += rdma_device_input_inline (vm, node, frame, rd, dq->queue_id, 0);
1039  }
1040  return n_rx;
1041 }
1042 
1043 /* *INDENT-OFF* */
1045  .name = "rdma-input",
1047  .sibling_of = "device-input",
1048  .format_trace = format_rdma_input_trace,
1049  .type = VLIB_NODE_TYPE_INPUT,
1050  .state = VLIB_NODE_STATE_DISABLED,
1051  .n_errors = RDMA_INPUT_N_ERROR,
1052  .error_strings = rdma_input_error_strings,
1053 };
1054 
1055 /* *INDENT-ON* */
1056 
1057 
1058 /*
1059  * fd.io coding-style-patch-verification: ON
1060  *
1061  * Local Variables:
1062  * eval: (c-set-style "gnu")
1063  * End:
1064  */
u32 mini_cqe_num
Definition: rdma_mlx5dv.h:54
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:124
static_always_inline void rdma_device_input_refill(vlib_main_t *vm, rdma_device_t *rd, rdma_rxq_t *rxq, vlib_buffer_t *bt, const int is_mlx5dv, const int is_striding)
Definition: input.c:123
static __clib_warn_unused_result u32 vlib_buffer_alloc_to_ring_from_pool(vlib_main_t *vm, u32 *ring, u32 start, u32 ring_size, u32 n_buffers, u8 buffer_pool_index)
Allocate buffers into ring from specific buffer pool.
Definition: buffer_funcs.h:722
vnet_device_and_queue_t * devices_and_queues
Definition: devices.h:69
#define clib_min(x, y)
Definition: clib.h:328
static_always_inline u32x4 u32x4_byte_swap(u32x4 v)
Definition: vector_neon.h:107
static u32 vlib_get_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt)
Definition: trace_funcs.h:201
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 thread_index, u32 index, u64 n_packets, u64 n_bytes)
Increment a combined counter.
Definition: counter.h:239
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:937
static_always_inline void clib_prefetch_load(void *p)
Definition: cache.h:94
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
vnet_interface_main_t interface_main
Definition: vnet.h:65
volatile u32 * cq_db
Definition: rdma.h:88
#define PREDICT_TRUE(x)
Definition: clib.h:122
unsigned long u64
Definition: types.h:89
#define CLIB_MEMORY_STORE_BARRIER()
Definition: clib.h:136
u32 size
Definition: rdma.h:76
#define VLIB_NODE_FLAG_TRACE_SUPPORTED
Definition: node.h:306
u32 dev_instance
Definition: rdma.h:196
u8 opcode_cqefmt_se_owner
Definition: rdma_mlx5dv.h:59
u32 thread_index
Definition: main.h:250
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
static vlib_frame_t * vlib_get_frame(vlib_main_t *vm, vlib_frame_t *f)
Definition: node_funcs.h:269
static_always_inline uword rdma_device_poll_cq_mlx5dv(rdma_device_t *rd, rdma_rxq_t *rxq, u32 *byte_cnt, u16 *cqe_flags)
Definition: input.c:534
struct ibv_wq * wq
Definition: rdma.h:74
u32 per_interface_next_index
Definition: rdma.h:184
format_function_t format_rdma_input_trace
Definition: rdma.h:281
rdma_main_t rdma_main
Definition: device.c:46
vlib_main_t * vm
Definition: in2out_ed.c:1580
static_always_inline void vlib_get_buffers_with_offset(vlib_main_t *vm, u32 *bi, void **b, int count, i32 offset)
Translate array of buffer indices into buffer pointers with offset.
Definition: buffer_funcs.h:214
#define VLIB_NODE_FN(node)
Definition: node.h:203
u16 mask
Definition: flow_types.api:52
u32 tail
Definition: rdma.h:78
vhost_vring_addr_t addr
Definition: vhost_user.h:111
u16 cqe_flags[VLIB_FRAME_SIZE]
Definition: rdma.h:217
unsigned char u8
Definition: types.h:56
static_always_inline uword rdma_device_input_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, rdma_device_t *rd, u16 qid, const int use_mlx5dv)
Definition: input.c:913
u8 buffer_pool_index
index of buffer pool this buffer belongs.
Definition: buffer.h:133
static_always_inline u32 rdma_device_input_bufs(vlib_main_t *vm, const rdma_device_t *rd, vlib_buffer_t **b, struct ibv_wc *wc, u32 n_left_from, vlib_buffer_t *bt)
Definition: input.c:381
u16x8 cqe_flags8[VLIB_FRAME_SIZE/8]
Definition: rdma.h:218
u32 to_free_buffers[VLIB_FRAME_SIZE]
Definition: rdma.h:226
rdma_per_thread_data_t * per_thread_data
Definition: rdma.h:240
u16 n_mini_cqes_left
Definition: rdma.h:82
#define static_always_inline
Definition: clib.h:109
static_always_inline void rdma_device_input_trace(vlib_main_t *vm, vlib_node_runtime_t *node, const rdma_device_t *rd, u32 n_left, const u32 *bi, u32 next_index, u16 *cqe_flags, int is_mlx5dv)
Definition: input.c:325
static uword pow2_mask(uword x)
Definition: clib.h:238
#define ETH_INPUT_FRAME_F_SINGLE_SW_IF_IDX
Definition: ethernet.h:52
rdma_device_t * devices
Definition: rdma.h:241
#define CQE_FLAG_L3_OK
Definition: rdma_mlx5dv.h:28
#define CQE_FLAG_L3_HDR_TYPE_SHIFT
Definition: rdma_mlx5dv.h:32
#define CQE_FLAG_L3_HDR_TYPE_IP4
Definition: rdma_mlx5dv.h:35
static_always_inline int vnet_device_input_have_features(u32 sw_if_index)
Definition: feature.h:336
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:207
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define vlib_get_new_next_frame(vm, node, next_index, vectors, n_vectors_left)
Definition: node_funcs.h:396
const cJSON *const b
Definition: cJSON.h:255
unsigned int u32
Definition: types.h:88
u16 n_mini_cqes
Definition: rdma.h:81
epu16_epi64 epu8_epi64 epu8_epi64 epi16_epi64 epi8_epi64 epi8_epi64 static_always_inline u64x4 u64x4_byte_swap(u64x4 v)
Definition: vector_avx2.h:136
#define VLIB_FRAME_SIZE
Definition: node.h:378
static vlib_next_frame_t * vlib_node_runtime_get_next_frame(vlib_main_t *vm, vlib_node_runtime_t *n, u32 next_index)
Definition: node_funcs.h:317
u32 flags
Definition: rdma.h:183
static void vlib_buffer_free_from_ring(vlib_main_t *vm, u32 *ring, u32 start, u32 ring_size, u32 n_buffers)
Free buffers from ring.
Definition: buffer_funcs.h:984
u32 * bufs
Definition: rdma.h:75
static_always_inline u32 rdma_device_mlx5dv_striding_rq_input(vlib_main_t *vm, rdma_per_thread_data_t *ptd, rdma_rxq_t *rxq, vlib_buffer_t *bt, u32 *to_next, int n_rx_segs, int *n_rx_packets, u32 *bc, int slow_path_needed)
Definition: input.c:815
static_always_inline void vlib_buffer_copy_template(vlib_buffer_t *b, vlib_buffer_t *bt)
Definition: buffer_funcs.h:181
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:142
u32 * second_bufs
Definition: rdma.h:105
unsigned short u16
Definition: types.h:57
vlib_node_registration_t rdma_input_node
(constructor) VLIB_REGISTER_NODE (rdma_input_node)
Definition: input.c:1044
#define ETH_INPUT_FRAME_F_IP4_CKSUM_OK
Definition: ethernet.h:55
struct ibv_cq * cq
Definition: rdma.h:73
static_always_inline u32x8 u32x8_byte_swap(u32x8 v)
Definition: vector_avx2.h:146
u32 buf_sz
Definition: rdma.h:92
static_always_inline int rdma_device_mlx5dv_l3_validate_and_swap_bc(rdma_per_thread_data_t *ptd, int n_rx_packets, u32 *bc)
Definition: input.c:668
#define PREDICT_FALSE(x)
Definition: clib.h:121
static_always_inline u32 rdma_device_mlx5dv_fast_input(vlib_main_t *vm, rdma_rxq_t *rxq, vlib_buffer_t **bufs, u32 qs_mask, vlib_buffer_t *bt, u32 *to_next, u32 n_rx_segs, u32 *bc, u32 bc_mask)
Definition: input.c:716
#define CQE_FLAG_L3_HDR_TYPE_MASK
Definition: rdma_mlx5dv.h:33
static_always_inline u32 vlib_buffer_get_default_data_size(vlib_main_t *vm)
Definition: buffer_funcs.h:96
static_always_inline void ibv_set_recv_wr_and_sge(struct ibv_recv_wr *w, struct ibv_sge *s, u64 va, u32 data_size, u32 lkey)
Definition: input.c:45
u8 slot
Definition: pci_types.api:22
vlib_buffer_t buffer_template
Definition: rdma.h:235
u32 hw_if_index
Definition: rdma.h:186
u32 tmp_bi[VLIB_FRAME_SIZE]
Definition: rdma.h:230
u32 wqe_cnt
Definition: rdma.h:90
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:170
u8 log_stride_per_wqe
Definition: rdma.h:98
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:219
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
u32 incomplete_tail
Definition: rdma.h:106
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
static_always_inline void process_mini_cqes(rdma_rxq_t *rxq, u32 skip, u32 n_left, u32 cq_ci, u32 mask, u32 *byte_cnt)
Definition: input.c:430
u32 lkey
Definition: rdma.h:187
static void * vlib_frame_scalar_args(vlib_frame_t *f)
Get pointer to frame scalar data.
Definition: node_funcs.h:311
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:483
static __clib_unused char * rdma_input_error_strings[]
Definition: input.c:37
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1580
u32 sw_if_index
Definition: rdma.h:185
u16 log2_cq_size
Definition: rdma.h:80
u32 head
Definition: rdma.h:77
static_always_inline u32 rdma_device_legacy_input_refill_additional(vlib_main_t *vm, rdma_device_t *rd, rdma_rxq_t *rxq, rdma_per_thread_data_t *ptd, vlib_buffer_t *bt, u32 first_slot, u32 n_alloc)
Definition: input.c:57
u8 * n_used_per_chain
Definition: rdma.h:103
static_always_inline int rdma_device_mlx5dv_striding_rq_parse_bc(int n_rx_packets, int *n_rx_segs, u32 *bc)
Definition: input.c:625
vlib_frame_t * frame
Definition: node.h:406
u8 log_wqe_sz
Definition: rdma.h:113
#define CQE_BC_CONSUMED_STRIDES_SHIFT
Definition: rdma_mlx5dv.h:41
vlib_buffer_t * tmp_bufs[VLIB_FRAME_SIZE]
Definition: rdma.h:231
u16 flags
Definition: node.h:388
#define CQE_BC_FILLER_MASK
Definition: rdma_mlx5dv.h:40
#define CQE_BC_BYTE_COUNT_MASK
Definition: rdma_mlx5dv.h:43
rdma_rxq_t * rxqs
Definition: rdma.h:181
static_always_inline void rdma_device_input_ethernet(vlib_main_t *vm, vlib_node_runtime_t *node, const rdma_device_t *rd, u32 next_index, int skip_ip4_cksum)
Definition: input.c:356
#define foreach_rdma_input_error
Definition: input.c:26
#define clib_max(x, y)
Definition: clib.h:321
#define CQE_BC_CONSUMED_STRIDES_MASK
Definition: rdma_mlx5dv.h:42
static_always_inline void clib_memset_u16(void *p, u16 val, uword count)
Definition: string.h:378
#define foreach_device_and_queue(var, vec)
Definition: devices.h:152
mlx5dv_cqe_t * cqes
Definition: rdma.h:84
u32 current_segs[VLIB_FRAME_SIZE]
Definition: rdma.h:225
static_always_inline void rdma_device_mlx5dv_legacy_rq_fix_chains(vlib_main_t *vm, rdma_rxq_t *rxq, vlib_buffer_t **bufs, u32 qs_mask, u32 n)
Definition: input.c:762
static_always_inline void clib_prefetch_store(void *p)
Definition: cache.h:100
static_always_inline void compressed_cqe_reset_owner(rdma_rxq_t *rxq, u32 n_mini_cqes, u32 cq_ci, u32 mask, u32 log2_cq_size)
Definition: input.c:506
u16 n_total_additional_segs
Definition: rdma.h:109
u16x16 cqe_flags16[VLIB_FRAME_SIZE/16]
Definition: rdma.h:219
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:140
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1581
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
u32 striding_wqe_tail
Definition: rdma.h:97
static void vlib_buffer_copy_indices_from_ring(u32 *dst, u32 *ring, u32 start, u32 ring_size, u32 n_buffers)
Definition: buffer_funcs.h:144
volatile u32 * wq_db
Definition: rdma.h:87
static_always_inline int rdma_device_mlx5dv_legacy_rq_slow_path_needed(u32 buf_sz, int n_rx_packets, u32 *bc)
Definition: input.c:641
struct clib_bihash_value offset
template key/value backing page structure
u64x4
Definition: vector_avx2.h:121
#define vnet_buffer(b)
Definition: buffer.h:417
static_always_inline void vnet_feature_start_device_input_x1(u32 sw_if_index, u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:343
static_always_inline void cqe_set_owner(mlx5dv_cqe_t *cqe, u32 n_left, u8 owner)
Definition: input.c:482
u32 cq_ci
Definition: rdma.h:79
unsigned long long u32x4
Definition: ixge.c:28
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:634
u16 last_cqe_flags
Definition: rdma.h:83
static void vlib_set_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt, u32 count)
Definition: trace_funcs.h:215
static_always_inline void vlib_get_buffers(vlib_main_t *vm, u32 *bi, vlib_buffer_t **b, int count)
Translate array of buffer indices into buffer pointers.
Definition: buffer_funcs.h:280
#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:167
epu16_epi64 u16x16
Definition: vector_avx2.h:123
rdma_input_error_t
Definition: input.c:29
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
mlx5dv_wqe_ds_t * wqes
Definition: rdma.h:85
Definition: defs.h:46
static __clib_warn_unused_result u32 vlib_buffer_alloc_from_pool(vlib_main_t *vm, u32 *buffers, u32 n_buffers, u8 buffer_pool_index)
Allocate buffers from specific pool into supplied array.
Definition: buffer_funcs.h:566