FD.io VPP  v18.04-17-g3a0d853
Vector Packet Processing
buffer.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16  * buffer.c: allocate/free network buffers.
17  *
18  * Copyright (c) 2008 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39 
40 /**
41  * @file
42  *
43  * Allocate/free network buffers.
44  */
45 
46 #include <unistd.h>
47 #include <linux/vfio.h>
48 #include <sys/ioctl.h>
49 
50 #include <rte_config.h>
51 
52 #include <rte_common.h>
53 #include <rte_log.h>
54 #include <rte_memory.h>
55 #include <rte_memzone.h>
56 #include <rte_tailq.h>
57 #include <rte_eal.h>
58 #include <rte_per_lcore.h>
59 #include <rte_launch.h>
60 #include <rte_atomic.h>
61 #include <rte_cycles.h>
62 #include <rte_prefetch.h>
63 #include <rte_lcore.h>
64 #include <rte_per_lcore.h>
65 #include <rte_branch_prediction.h>
66 #include <rte_interrupts.h>
67 #include <rte_pci.h>
68 #include <rte_random.h>
69 #include <rte_debug.h>
70 #include <rte_ether.h>
71 #include <rte_ethdev.h>
72 #include <rte_ring.h>
73 #include <rte_mempool.h>
74 #include <rte_mbuf.h>
75 #include <rte_version.h>
76 
77 #include <vlib/vlib.h>
78 #include <vlib/unix/unix.h>
79 #include <vlib/pci/pci.h>
80 #include <vlib/linux/vfio.h>
81 #include <vnet/vnet.h>
82 #include <dpdk/device/dpdk.h>
83 #include <dpdk/device/dpdk_priv.h>
84 
85 STATIC_ASSERT (VLIB_BUFFER_PRE_DATA_SIZE == RTE_PKTMBUF_HEADROOM,
86  "VLIB_BUFFER_PRE_DATA_SIZE must be equal to RTE_PKTMBUF_HEADROOM");
87 
88 typedef struct
89 {
90  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
91  struct rte_mbuf ***mbuf_pending_free_list;
92 
93  /* cached last pool */
94  struct rte_mempool *last_pool;
97 
98 typedef struct
99 {
103 
105 
108 {
109  vlib_buffer_t *hb = b;
111  dpdk_buffer_per_thread_data *d = vec_elt_at_index (dbm->ptd, thread_index);
112  struct rte_mbuf *mb;
113  u32 next, flags;
114  mb = rte_mbuf_from_vlib_buffer (hb);
115 
116 next:
117  flags = b->flags;
118  next = b->next_buffer;
119  mb = rte_mbuf_from_vlib_buffer (b);
120 
121  if (PREDICT_FALSE (b->n_add_refs))
122  {
123  rte_mbuf_refcnt_update (mb, b->n_add_refs);
124  b->n_add_refs = 0;
125  }
126 
127  mb = rte_pktmbuf_prefree_seg (mb);
128  if (mb)
129  {
130  if (mb->pool != d->last_pool)
131  {
132  d->last_pool = mb->pool;
133  dpdk_mempool_private_t *privp = rte_mempool_get_priv (d->last_pool);
138  }
140  }
141 
142  if (flags & VLIB_BUFFER_NEXT_PRESENT)
143  {
144  b = vlib_get_buffer (vm, next);
145  goto next;
146  }
147 }
148 
149 #ifndef CLIB_MULTIARCH_VARIANT
150 static void
152 {
153  u32 i;
154  vlib_buffer_t *b;
155  u32 thread_index = vlib_get_thread_index ();
156 
157  for (i = 0; i < vec_len (f->buffers); i++)
158  {
159  b = vlib_get_buffer (vm, f->buffers[i]);
160  dpdk_rte_pktmbuf_free (vm, thread_index, b);
161  }
162 
163  vec_free (f->name);
164  vec_free (f->buffers);
165  /* Poison it. */
166  memset (f, 0xab, sizeof (f[0]));
167 }
168 
169 /* Add buffer free list. */
170 static void
172  vlib_buffer_free_list_index_t free_list_index)
173 {
175  int i;
176 
177  ASSERT (vlib_get_thread_index () == 0);
178 
179  f = vlib_buffer_get_free_list (vm, free_list_index);
180 
181  del_free_list (vm, f);
182 
184 
185  for (i = 1; i < vec_len (vlib_mains); i++)
186  {
187  vlib_main_t *wvm = vlib_mains[i];
188  f = vlib_buffer_get_free_list (vlib_mains[i], free_list_index);
189  del_free_list (wvm, f);
191  }
192 }
193 #endif
194 
195 /* Make sure free list has at least given number of free buffers. */
196 uword
199  uword min_free_buffers)
200 {
201  dpdk_main_t *dm = &dpdk_main;
202  vlib_buffer_t *b0, *b1, *b2, *b3;
203  int n, i;
204  u32 bi0, bi1, bi2, bi3;
205  unsigned socket_id = rte_socket_id ();
206  struct rte_mempool *rmp = dm->pktmbuf_pools[socket_id];
207  dpdk_mempool_private_t *privp = rte_mempool_get_priv (rmp);
208  struct rte_mbuf *mb0, *mb1, *mb2, *mb3;
209  vlib_buffer_t bt;
210 
211  /* Too early? */
212  if (PREDICT_FALSE (rmp == 0))
213  return 0;
214 
215  /* Already have enough free buffers on free list? */
216  n = min_free_buffers - vec_len (fl->buffers);
217  if (n <= 0)
218  return min_free_buffers;
219 
220  /* Always allocate round number of buffers. */
221  n = round_pow2 (n, CLIB_CACHE_LINE_BYTES / sizeof (u32));
222 
223  /* Always allocate new buffers in reasonably large sized chunks. */
224  n = clib_max (n, fl->min_n_buffers_each_alloc);
225 
227 
228  if (rte_mempool_get_bulk (rmp, vm->mbuf_alloc_list, n) < 0)
229  return 0;
230 
231  memset (&bt, 0, sizeof (vlib_buffer_t));
234 
235  _vec_len (vm->mbuf_alloc_list) = n;
236 
237  i = 0;
238  int f = vec_len (fl->buffers);
240 
241  while (i < (n - 7))
242  {
244  (vm->mbuf_alloc_list[i + 4]), STORE);
246  (vm->mbuf_alloc_list[i + 5]), STORE);
248  (vm->mbuf_alloc_list[i + 6]), STORE);
250  (vm->mbuf_alloc_list[i + 7]), STORE);
251 
252  mb0 = vm->mbuf_alloc_list[i];
253  mb1 = vm->mbuf_alloc_list[i + 1];
254  mb2 = vm->mbuf_alloc_list[i + 2];
255  mb3 = vm->mbuf_alloc_list[i + 3];
256 
257  b0 = vlib_buffer_from_rte_mbuf (mb0);
258  b1 = vlib_buffer_from_rte_mbuf (mb1);
259  b2 = vlib_buffer_from_rte_mbuf (mb2);
260  b3 = vlib_buffer_from_rte_mbuf (mb3);
261 
262  bi0 = vlib_get_buffer_index (vm, b0);
263  bi1 = vlib_get_buffer_index (vm, b1);
264  bi2 = vlib_get_buffer_index (vm, b2);
265  bi3 = vlib_get_buffer_index (vm, b3);
266 
267  fl->buffers[f++] = bi0;
268  fl->buffers[f++] = bi1;
269  fl->buffers[f++] = bi2;
270  fl->buffers[f++] = bi3;
271 
272  clib_memcpy64_x4 (b0, b1, b2, b3, &bt);
273 
274  if (fl->buffer_init_function)
275  {
276  fl->buffer_init_function (vm, fl, &bi0, 1);
277  fl->buffer_init_function (vm, fl, &bi1, 1);
278  fl->buffer_init_function (vm, fl, &bi2, 1);
279  fl->buffer_init_function (vm, fl, &bi3, 1);
280  }
281  i += 4;
282  }
283 
284  while (i < n)
285  {
286  mb0 = vm->mbuf_alloc_list[i];
287 
288  b0 = vlib_buffer_from_rte_mbuf (mb0);
289  bi0 = vlib_get_buffer_index (vm, b0);
290 
291  fl->buffers[f++] = bi0;
292  clib_memcpy (b0, &bt, sizeof (vlib_buffer_t));
293 
294  if (fl->buffer_init_function)
295  fl->buffer_init_function (vm, fl, &bi0, 1);
296  i++;
297  }
298 
299  fl->n_alloc += n;
300 
301  return n;
302 }
303 
306 {
307  vlib_buffer_t *b;
308  struct rte_mbuf *mb;
309  b = vlib_get_buffer (vm, bi);
310  mb = rte_mbuf_from_vlib_buffer (b);
311  CLIB_PREFETCH (mb, 2 * CLIB_CACHE_LINE_BYTES, STORE);
313 }
314 
317  vlib_buffer_t * b)
318 {
320  u32 thread_index = vlib_get_thread_index ();
322  fl = vlib_buffer_get_buffer_free_list (vm, b, &fi);
323 
324  /* The only current use of this callback: multicast recycle */
326  {
327  int j;
328 
329  vlib_buffer_add_to_free_list (vm, fl, bi,
330  (b->flags & VLIB_BUFFER_RECYCLE) == 0);
331 
332  for (j = 0; j < vec_len (vm->buffer_announce_list); j++)
333  {
334  if (fl == vm->buffer_announce_list[j])
335  goto already_announced;
336  }
337  vec_add1 (vm->buffer_announce_list, fl);
338  already_announced:
339  ;
340  }
341  else
342  {
343  if (PREDICT_TRUE ((b->flags & VLIB_BUFFER_RECYCLE) == 0))
344  dpdk_rte_pktmbuf_free (vm, thread_index, b);
345  }
346 }
347 
350  u32 * buffers, u32 n_buffers, u32 follow_buffer_next)
351 {
354  vlib_buffer_t *b0, *b1, *b2, *b3;
355  u32 thread_index = vlib_get_thread_index ();
356  dpdk_buffer_per_thread_data *d = vec_elt_at_index (dbm->ptd, thread_index);
357  int i = 0;
358  u32 (*cb) (vlib_main_t * vm, u32 * buffers, u32 n_buffers,
359  u32 follow_buffer_next);
360 
361  cb = bm->buffer_free_callback;
362 
363  if (PREDICT_FALSE (cb != 0))
364  n_buffers = (*cb) (vm, buffers, n_buffers, follow_buffer_next);
365 
366  if (!n_buffers)
367  return;
368 
369  while (i + 7 < n_buffers)
370  {
371  dpdk_prefetch_buffer_by_index (vm, buffers[i + 4]);
372  dpdk_prefetch_buffer_by_index (vm, buffers[i + 5]);
373  dpdk_prefetch_buffer_by_index (vm, buffers[i + 6]);
374  dpdk_prefetch_buffer_by_index (vm, buffers[i + 7]);
375 
376  b0 = vlib_get_buffer (vm, buffers[i]);
377  b1 = vlib_get_buffer (vm, buffers[i + 1]);
378  b2 = vlib_get_buffer (vm, buffers[i + 2]);
379  b3 = vlib_get_buffer (vm, buffers[i + 3]);
380 
385 
386  recycle_or_free (vm, bm, buffers[i], b0);
387  recycle_or_free (vm, bm, buffers[i + 1], b1);
388  recycle_or_free (vm, bm, buffers[i + 2], b2);
389  recycle_or_free (vm, bm, buffers[i + 3], b3);
390 
391  i += 4;
392  }
393  while (i < n_buffers)
394  {
395  b0 = vlib_get_buffer (vm, buffers[i]);
397  recycle_or_free (vm, bm, buffers[i], b0);
398  i++;
399  }
400  if (vec_len (vm->buffer_announce_list))
401  {
403  for (i = 0; i < vec_len (vm->buffer_announce_list); i++)
404  {
405  fl = vm->buffer_announce_list[i];
407  }
408  _vec_len (vm->buffer_announce_list) = 0;
409  }
410 
412  {
413  int len = vec_len (d->mbuf_pending_free_list[i]);
414  if (len)
415  {
416  rte_mempool_put_bulk (d->mbuf_pending_free_list[i][len - 1]->pool,
417  (void *) d->mbuf_pending_free_list[i], len);
419  }
420  }
421 }
422 
423 void
425  u32 n_buffers)
426 {
427  vlib_buffer_free_inline (vm, buffers, n_buffers, /* follow_buffer_next */
428  1);
429 }
430 
431 void
433  u32 n_buffers)
434 {
435  vlib_buffer_free_inline (vm, buffers, n_buffers, /* follow_buffer_next */
436  0);
437 }
438 
439 #ifndef CLIB_MULTIARCH_VARIANT
440 static void
442  void *vt,
443  void *packet_data,
444  uword n_packet_data_bytes,
445  uword min_n_buffers_each_alloc, u8 * name)
446 {
448 
450  memset (t, 0, sizeof (t[0]));
451 
452  vec_add (t->packet_data, packet_data, n_packet_data_bytes);
453 
455 }
456 
457 static clib_error_t *
458 scan_vfio_fd (void *arg, u8 * path_name, u8 * file_name)
459 {
462  const char fn[] = "/dev/vfio/vfio";
463  char buff[sizeof (fn)] = { 0 };
464  int fd;
465  u8 *path = format (0, "%v%c", path_name, 0);
466 
467  if (readlink ((char *) path, buff, sizeof (fn)) + 1 != sizeof (fn))
468  goto done;
469 
470  if (strncmp (fn, buff, sizeof (fn)))
471  goto done;
472 
473  fd = atoi ((char *) file_name);
474  if (fd != lvm->container_fd)
475  dbm->vfio_container_fd = fd;
476 
477 done:
478  vec_free (path);
479  return 0;
480 }
481 
482 clib_error_t *
483 dpdk_pool_create (vlib_main_t * vm, u8 * pool_name, u32 elt_size,
484  u32 num_elts, u32 pool_priv_size, u16 cache_size, u8 numa,
485  struct rte_mempool ** _mp,
487 {
489  struct rte_mempool *mp;
491  clib_error_t *error = 0;
492  u32 size, obj_size;
493  i32 ret;
494 
495  obj_size = rte_mempool_calc_obj_size (elt_size, 0, 0);
496  size = rte_mempool_xmem_size (num_elts, obj_size, 21, 0);
497 
498  error =
499  vlib_physmem_region_alloc (vm, (i8 *) pool_name, size, numa,
501  pri);
502  if (error)
503  return error;
504 
505  pr = vlib_physmem_get_region (vm, pri[0]);
506 
507  mp =
508  rte_mempool_create_empty ((i8 *) pool_name, num_elts, elt_size,
509  512, pool_priv_size, numa, 0);
510  if (!mp)
511  return clib_error_return (0, "failed to create %s", pool_name);
512 
513  rte_mempool_set_ops_byname (mp, RTE_MBUF_DEFAULT_MEMPOOL_OPS, NULL);
514 
515  ret =
516  rte_mempool_populate_iova_tab (mp, pr->mem, pr->page_table, pr->n_pages,
517  pr->log2_page_size, NULL, NULL);
518  if (ret != (i32) mp->size)
519  {
520  rte_mempool_free (mp);
521  return clib_error_return (0, "failed to populate %s", pool_name);
522  }
523 
524  _mp[0] = mp;
525 
526  /* DPDK currently doesn't provide API to map DMA memory for empty mempool
527  so we are using this hack, will be nice to have at least API to get
528  VFIO container FD */
529  if (dbm->vfio_container_fd == -1)
530  foreach_directory_file ("/proc/self/fd", scan_vfio_fd, 0, 0);
531 
532  if (dbm->vfio_container_fd != -1)
533  {
534  struct vfio_iommu_type1_dma_map dm = { 0 };
535  int i, rv = 0;
536  dm.argsz = sizeof (struct vfio_iommu_type1_dma_map);
537  dm.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE;
538 
539  /* *INDENT-OFF* */
541  {
542  dm.vaddr = pointer_to_uword (pr->mem) + (i << pr->log2_page_size);
543  dm.size = 1 << pr->log2_page_size;
544  dm.iova = pr->page_table[i];
545  if ((rv = ioctl (dbm->vfio_container_fd, VFIO_IOMMU_MAP_DMA, &dm)))
546  break;
547  }
548  /* *INDENT-ON* */
549  if (rv != 0 && rv != EINVAL)
550  clib_unix_warning ("ioctl(VFIO_IOMMU_MAP_DMA) pool '%s'", pool_name);
551  }
552 
553  return 0;
554 }
555 
556 clib_error_t *
557 dpdk_buffer_pool_create (vlib_main_t * vm, unsigned num_mbufs,
558  unsigned socket_id)
559 {
560  dpdk_main_t *dm = &dpdk_main;
561  struct rte_mempool *rmp;
564  clib_error_t *error = 0;
565  u8 *pool_name;
566  u32 elt_size, i;
567 
569 
570  /* pool already exists, nothing to do */
571  if (dm->pktmbuf_pools[socket_id])
572  return 0;
573 
574  pool_name = format (0, "dpdk_mbuf_pool_socket%u%c", socket_id, 0);
575 
576  elt_size = sizeof (struct rte_mbuf) +
577  VLIB_BUFFER_HDR_SIZE /* priv size */ +
578  VLIB_BUFFER_PRE_DATA_SIZE + VLIB_BUFFER_DATA_SIZE; /*data room size */
579 
580  error =
581  dpdk_pool_create (vm, pool_name, elt_size, num_mbufs,
582  sizeof (dpdk_mempool_private_t), 512, socket_id,
583  &rmp, &pri);
584 
585  vec_free (pool_name);
586 
587  if (!error)
588  {
589  priv.mbp_priv.mbuf_data_room_size = VLIB_BUFFER_PRE_DATA_SIZE +
591  priv.mbp_priv.mbuf_priv_size = VLIB_BUFFER_HDR_SIZE;
592 
593  /* call the mempool priv initializer */
594  rte_pktmbuf_pool_init (rmp, &priv);
595 
596  /* call the object initializers */
597  rte_mempool_obj_iter (rmp, rte_pktmbuf_init, 0);
598 
599  dpdk_mempool_private_t *privp = rte_mempool_get_priv (rmp);
600  privp->buffer_pool_index = vlib_buffer_pool_create (vm, pri, 0);
601 
602  dm->pktmbuf_pools[socket_id] = rmp;
603 
604  return 0;
605  }
606 
607  clib_error_report (error);
608 
609  /* no usable pool for this socket, try to use pool from another one */
610  for (i = 0; i < vec_len (dm->pktmbuf_pools); i++)
611  {
612  if (dm->pktmbuf_pools[i])
613  {
614  clib_warning ("WARNING: Failed to allocate mempool for CPU socket "
615  "%u. Threads running on socket %u will use socket %u "
616  "mempool.", socket_id, socket_id, i);
617  dm->pktmbuf_pools[socket_id] = dm->pktmbuf_pools[i];
618  return 0;
619  }
620  }
621 
622  return clib_error_return (0, "failed to allocate mempool on socket %u",
623  socket_id);
624 }
625 
626 #if CLIB_DEBUG > 0
627 
631 
632 static clib_error_t *
634 {
635  void *oldheap;
636 
637  vlib_buffer_state_heap = mheap_alloc (0, 10 << 20);
638 
640 
644  clib_mem_set_heap (oldheap);
645  return 0;
646 }
647 
649 #endif
650 
651 #if CLI_DEBUG
652 struct dpdk_validate_buf_result
653 {
654  u32 invalid;
655  u32 uninitialized;
656 };
657 
658 #define DPDK_TRAJECTORY_POISON 31
659 
660 static void
661 dpdk_buffer_validate_trajectory (struct rte_mempool *mp, void *opaque,
662  void *obj, unsigned obj_idx)
663 {
664  vlib_buffer_t *b;
665  struct dpdk_validate_buf_result *counter = opaque;
666  b = vlib_buffer_from_rte_mbuf ((struct rte_mbuf *) obj);
667  if (b->pre_data[0] != 0)
668  {
669  if (b->pre_data[0] == DPDK_TRAJECTORY_POISON)
670  counter->uninitialized++;
671  else
672  counter->invalid++;
673  }
674 }
675 
676 int
677 dpdk_buffer_validate_trajectory_all (u32 * uninitialized)
678 {
679  dpdk_main_t *dm = &dpdk_main;
680  struct dpdk_validate_buf_result counter = { 0 };
681  int i;
682 
683  for (i = 0; i < vec_len (dm->pktmbuf_pools); i++)
684  rte_mempool_obj_iter (dm->pktmbuf_pools[i],
685  dpdk_buffer_validate_trajectory, &counter);
686  if (uninitialized)
687  *uninitialized = counter.uninitialized;
688  return counter.invalid;
689 }
690 
691 static void
692 dpdk_buffer_poison_trajectory (struct rte_mempool *mp, void *opaque,
693  void *obj, unsigned obj_idx)
694 {
695  vlib_buffer_t *b;
696  b = vlib_buffer_from_rte_mbuf ((struct rte_mbuf *) obj);
697  b->pre_data[0] = DPDK_TRAJECTORY_POISON;
698 }
699 
700 void
701 dpdk_buffer_poison_trajectory_all (void)
702 {
703  dpdk_main_t *dm = &dpdk_main;
704  int i;
705 
706  for (i = 0; i < vec_len (dm->pktmbuf_pools); i++)
707  rte_mempool_obj_iter (dm->pktmbuf_pools[i], dpdk_buffer_poison_trajectory,
708  0);
709 }
710 #endif
711 
712 static clib_error_t *
714 {
717 
718  vec_validate_aligned (dbm->ptd, tm->n_vlib_mains - 1,
720 
721  dbm->vfio_container_fd = -1;
722 
723  return 0;
724 }
725 
727 
728 /* *INDENT-OFF* */
729 VLIB_BUFFER_REGISTER_CALLBACKS (dpdk, static) = {
730  .vlib_buffer_fill_free_list_cb = &dpdk_buffer_fill_free_list,
731  .vlib_buffer_free_cb = &dpdk_buffer_free,
732  .vlib_buffer_free_no_next_cb = &dpdk_buffer_free_no_next,
733  .vlib_packet_template_init_cb = &dpdk_packet_template_init,
734  .vlib_buffer_delete_free_list_cb = &dpdk_buffer_delete_free_list,
735 };
736 /* *INDENT-ON* */
737 
738 #if __x86_64__
745 
746 static void __clib_constructor
748 {
749  vlib_buffer_callbacks_t *cb = &__dpdk_buffer_callbacks;
750  if (dpdk_buffer_fill_free_list_avx512 && clib_cpu_supports_avx512f ())
751  {
755  }
756  else if (dpdk_buffer_fill_free_list_avx2 && clib_cpu_supports_avx2 ())
757  {
761  }
762 }
763 #endif
764 #endif
765 
766 /** @endcond */
767 /*
768  * fd.io coding-style-patch-verification: ON
769  *
770  * Local Variables:
771  * eval: (c-set-style "gnu")
772  * End:
773  */
#define vec_foreach_index(var, v)
Iterate over vector indices.
#define vlib_buffer_from_rte_mbuf(x)
Definition: dpdk_priv.h:17
#define CLIB_CACHE_LINE_ALIGN_MARK(mark)
Definition: cache.h:60
dpdk_buffer_main_t dpdk_buffer_main
Definition: buffer.c:104
static clib_error_t * dpdk_buffer_init(vlib_main_t *vm)
Definition: buffer.c:713
static void dpdk_packet_template_init(vlib_main_t *vm, void *vt, void *packet_data, uword n_packet_data_bytes, uword min_n_buffers_each_alloc, u8 *name)
Definition: buffer.c:441
#define VLIB_PHYSMEM_F_HUGETLB
Definition: physmem.h:58
dpdk_main_t dpdk_main
Definition: init.c:39
#define PREDICT_TRUE(x)
Definition: clib.h:106
void * mheap_alloc(void *memory, uword size)
Definition: mheap.c:947
u32 * vlib_buffer_state_validation_lock
Definition: buffer.c:628
#define NULL
Definition: clib.h:55
vlib_buffer_free_cb_t __clib_weak dpdk_buffer_free_avx512
Definition: buffer.c:741
#define VLIB_BUFFER_PRE_DATA_SIZE
Definition: buffer.h:52
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:520
u8 buffer_pool_index
index of buffer pool this buffer belongs.
Definition: buffer.h:143
static clib_error_t * vlib_physmem_region_alloc(vlib_main_t *vm, char *name, u32 size, u8 numa_node, u32 flags, vlib_physmem_region_index_t *idx)
int i
static void dpdk_buffer_delete_free_list(vlib_main_t *vm, vlib_buffer_free_list_index_t free_list_index)
Definition: buffer.c:171
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
struct rte_mempool * last_pool
Definition: buffer.c:94
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:445
void( vlib_buffer_free_cb_t)(struct vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Definition: buffer.h:391
vlib_main_t ** vlib_mains
Definition: buffer.c:303
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
#define vlib_worker_thread_barrier_sync(X)
Definition: threads.h:212
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:597
vlib_buffer_fill_free_list_cb_t __clib_weak dpdk_buffer_fill_free_list_avx2
Definition: buffer.c:740
#define VLIB_PHYSMEM_F_SHARED
Definition: physmem.h:59
#define static_always_inline
Definition: clib.h:93
uword * vlib_buffer_state_validation_hash
Definition: buffer.c:629
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
u8 vlib_buffer_pool_create(vlib_main_t *vm, vlib_physmem_region_index_t pri, u16 buffer_size)
Definition: buffer.c:904
vlib_buffer_free_no_next_cb_t __clib_weak dpdk_buffer_free_no_next_avx512
Definition: buffer.c:743
int i32
Definition: types.h:81
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:191
vlib_buffer_free_no_next_cb_t * vlib_buffer_free_no_next_cb
Definition: buffer.h:400
static void __clib_constructor dpdk_input_multiarch_select(void)
Definition: buffer.c:747
char i8
Definition: types.h:45
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define clib_error_return(e, args...)
Definition: error.h:99
u8 pre_data[VLIB_BUFFER_PRE_DATA_SIZE]
Space for inserting data before buffer start.
Definition: buffer.h:171
static uword pointer_to_uword(const void *p)
Definition: types.h:131
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
Definition: buffer_funcs.h:74
#define fl(x, y)
static vlib_physmem_region_t * vlib_physmem_get_region(vlib_main_t *vm, u8 index)
Definition: physmem_funcs.h:44
#define rte_mbuf_from_vlib_buffer(x)
Definition: dpdk_priv.h:16
u32 size
clib_error_t * dpdk_buffer_pool_create(vlib_main_t *vm, unsigned num_mbufs, unsigned socket_id)
Definition: buffer.c:557
static clib_error_t * buffer_state_validation_init(vlib_main_t *vm)
Definition: buffer.c:633
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:273
static clib_error_t * scan_vfio_fd(void *arg, u8 *path_name, u8 *file_name)
Definition: buffer.c:458
uword CLIB_MULTIARCH_FN() dpdk_buffer_fill_free_list(vlib_main_t *vm, vlib_buffer_free_list_t *fl, uword min_free_buffers)
Definition: buffer.c:197
#define PREDICT_FALSE(x)
Definition: clib.h:105
vlib_buffer_free_list_t * buffer_free_list_pool
Definition: main.h:108
static void vlib_buffer_add_to_free_list(vlib_main_t *vm, vlib_buffer_free_list_t *f, u32 buffer_index, u8 do_init)
Definition: buffer_funcs.h:955
clib_error_t * dpdk_pool_create(vlib_main_t *vm, u8 *pool_name, u32 elt_size, u32 num_elts, u32 pool_priv_size, u16 cache_size, u8 numa, struct rte_mempool **_mp, vlib_physmem_region_index_t *pri)
Definition: buffer.c:483
struct rte_pktmbuf_pool_private mbp_priv
Definition: dpdk_priv.h:57
STATIC_ASSERT(VLIB_BUFFER_PRE_DATA_SIZE==RTE_PKTMBUF_HEADROOM,"VLIB_BUFFER_PRE_DATA_SIZE must be equal to RTE_PKTMBUF_HEADROOM")
vlib_buffer_fill_free_list_cb_t * vlib_buffer_fill_free_list_cb
Definition: buffer.h:398
static_always_inline void vlib_buffer_free_inline(vlib_main_t *vm, u32 *buffers, u32 n_buffers, u32 follow_buffer_next)
Definition: buffer.c:623
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:221
u32(* buffer_free_callback)(struct vlib_main_t *vm, u32 *buffers, u32 n_buffers, u32 follow_buffer_next)
Definition: buffer.h:443
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:74
vlib_main_t * vm
Definition: buffer.c:294
vlib_buffer_fill_free_list_cb_t __clib_weak dpdk_buffer_fill_free_list_avx512
Definition: buffer.c:739
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:336
static_always_inline void clib_memcpy64_x4(void *d0, void *d1, void *d2, void *d3, void *s)
Definition: string.h:89
static void * clib_mem_set_heap(void *heap)
Definition: mem.h:226
#define clib_warning(format, args...)
Definition: error.h:59
#define clib_memcpy(a, b, c)
Definition: string.h:75
void CLIB_MULTIARCH_FN() dpdk_buffer_free_no_next(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Definition: buffer.c:432
static void del_free_list(vlib_main_t *vm, vlib_buffer_free_list_t *f)
Definition: buffer.c:151
void(* buffers_added_to_freelist_function)(struct vlib_main_t *vm, struct vlib_buffer_free_list_t *fl)
Definition: buffer.h:383
static uword round_pow2(uword x, uword pow2)
Definition: clib.h:286
void * vlib_buffer_state_heap
Definition: buffer.c:630
#define VLIB_BUFFER_DATA_SIZE
Definition: buffer.h:51
#define VLIB_BUFFER_HDR_SIZE
Definition: buffer.h:182
void CLIB_MULTIARCH_FN() dpdk_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Definition: buffer.c:424
void( vlib_buffer_free_no_next_cb_t)(struct vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Definition: buffer.h:393
#define hash_create(elts, value_bytes)
Definition: hash.h:681
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
vlib_buffer_free_cb_t __clib_weak dpdk_buffer_free_avx2
Definition: buffer.c:742
vlib_buffer_free_cb_t * vlib_buffer_free_cb
Definition: buffer.h:399
int vfio_container_fd
Definition: buffer.c:100
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:126
static vlib_buffer_free_list_t * vlib_buffer_get_buffer_free_list(vlib_main_t *vm, vlib_buffer_t *b, vlib_buffer_free_list_index_t *index)
Definition: buffer_funcs.h:509
dpdk_buffer_per_thread_data * ptd
Definition: buffer.c:101
struct rte_mempool ** pktmbuf_pools
Definition: dpdk.h:395
#define clib_error_report(e)
Definition: error.h:113
struct rte_mbuf *** mbuf_pending_free_list
Definition: buffer.c:91
VLIB_BUFFER_REGISTER_CALLBACKS(dpdk, static)
u8 n_add_refs
Number of additional references to this buffer.
Definition: buffer.h:141
#define clib_max(x, y)
Definition: clib.h:333
u64 uword
Definition: types.h:112
void ** mbuf_alloc_list
Definition: main.h:178
unsigned short u16
Definition: types.h:57
static_always_inline void recycle_or_free(vlib_main_t *vm, vlib_buffer_main_t *bm, u32 bi, vlib_buffer_t *b, u32 follow_buffer_next)
Definition: buffer.c:571
static_always_inline void dpdk_prefetch_buffer_by_index(vlib_main_t *vm, u32 bi)
Definition: buffer.c:305
clib_error_t * foreach_directory_file(char *dir_name, clib_error_t *(*f)(void *arg, u8 *path_name, u8 *file_name), void *arg, int scan_dirs)
Definition: util.c:49
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
Definition: buffer.h:553
#define clib_unix_warning(format, args...)
Definition: error.h:68
int container_fd
Definition: vfio.h:31
static void vlib_buffer_init_for_free_list(vlib_buffer_t *dst, vlib_buffer_free_list_t *fl)
Definition: buffer_funcs.h:915
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1497
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
vlib_buffer_main_t buffer_main
Definition: buffer.c:52
u8 vlib_buffer_free_list_index_t
Definition: buffer.h:54
vlib_buffer_free_no_next_cb_t __clib_weak dpdk_buffer_free_no_next_avx2
Definition: buffer.c:744
static vlib_buffer_free_list_t * vlib_buffer_get_free_list(vlib_main_t *vm, vlib_buffer_free_list_index_t free_list_index)
Definition: buffer_funcs.h:519
uword( vlib_buffer_fill_free_list_cb_t)(struct vlib_main_t *vm, vlib_buffer_free_list_t *fl, uword min_free_buffers)
Definition: buffer.h:388
u32 flags
Definition: vhost-user.h:77
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
static_always_inline void dpdk_rte_pktmbuf_free(vlib_main_t *vm, u32 thread_index, vlib_buffer_t *b)
Definition: buffer.c:107
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:111
u8 vlib_physmem_region_index_t
Definition: physmem.h:43
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
vlib_buffer_free_list_t ** buffer_announce_list
Definition: main.h:111
linux_vfio_main_t vfio_main
Definition: vfio.c:35
#define CLIB_MULTIARCH_FN(fn)
Definition: cpu.h:59
#define vec_resize_aligned(V, N, A)
Resize a vector (no header, alignment specified).
Definition: vec.h:250