FD.io VPP  v16.09
Vector Packet Processing
dpdk_buffer.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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  * @cond DPDK
42  * @file
43  *
44  * Allocate/free network buffers with DPDK.
45  */
46 
47 #include <rte_config.h>
48 
49 #include <rte_common.h>
50 #include <rte_log.h>
51 #include <rte_memory.h>
52 #include <rte_memzone.h>
53 #include <rte_tailq.h>
54 #include <rte_eal.h>
55 #include <rte_per_lcore.h>
56 #include <rte_launch.h>
57 #include <rte_atomic.h>
58 #include <rte_cycles.h>
59 #include <rte_prefetch.h>
60 #include <rte_lcore.h>
61 #include <rte_per_lcore.h>
62 #include <rte_branch_prediction.h>
63 #include <rte_interrupts.h>
64 #include <rte_pci.h>
65 #include <rte_random.h>
66 #include <rte_debug.h>
67 #include <rte_ether.h>
68 #include <rte_ethdev.h>
69 #include <rte_ring.h>
70 #include <rte_mempool.h>
71 #include <rte_mbuf.h>
72 #include <rte_version.h>
73 
74 #include <vlib/vlib.h>
75 
76 #pragma weak rte_mem_virt2phy
77 #pragma weak rte_eal_has_hugepages
78 #pragma weak rte_socket_id
79 #pragma weak rte_pktmbuf_pool_create
80 
81 uword
83  vlib_buffer_t * b_first)
84 {
85  vlib_buffer_t *b = b_first;
86  uword l_first = b_first->current_length;
87  uword l = 0;
88  while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
89  {
90  b = vlib_get_buffer (vm, b->next_buffer);
91  l += b->current_length;
92  }
95  return l + l_first;
96 }
97 
98 u8 *
99 format_vlib_buffer (u8 * s, va_list * args)
100 {
101  vlib_buffer_t *b = va_arg (*args, vlib_buffer_t *);
102  uword indent = format_get_indent (s);
103 
104  s = format (s, "current data %d, length %d, free-list %d",
106 
108  s = format (s, ", totlen-nifb %d",
110 
111  if (b->flags & VLIB_BUFFER_IS_TRACED)
112  s = format (s, ", trace 0x%x", b->trace_index);
113 
114  while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
115  {
116  vlib_main_t *vm = vlib_get_main ();
117  u32 next_buffer = b->next_buffer;
118  b = vlib_get_buffer (vm, next_buffer);
119 
120  s = format (s, "\n%Unext-buffer 0x%x, segment length %d",
121  format_white_space, indent, next_buffer, b->current_length);
122  }
123 
124 
125  return s;
126 }
127 
128 u8 *
129 format_vlib_buffer_and_data (u8 * s, va_list * args)
130 {
131  vlib_buffer_t *b = va_arg (*args, vlib_buffer_t *);
132 
133  s = format (s, "%U, %U",
136 
137  return s;
138 }
139 
140 u8 *
141 format_vlib_buffer_contents (u8 * s, va_list * va)
142 {
143  vlib_main_t *vm = va_arg (*va, vlib_main_t *);
144  vlib_buffer_t *b = va_arg (*va, vlib_buffer_t *);
145 
146  while (1)
147  {
149  if (!(b->flags & VLIB_BUFFER_NEXT_PRESENT))
150  break;
151  b = vlib_get_buffer (vm, b->next_buffer);
152  }
153 
154  return s;
155 }
156 
158 
159 /* Aligned copy routine. */
160 void
161 vlib_aligned_memcpy (void *_dst, void *_src, int n_bytes)
162 {
163  vlib_copy_unit_t *dst = _dst;
164  vlib_copy_unit_t *src = _src;
165 
166  /* Arguments must be naturally aligned. */
167  ASSERT (pointer_to_uword (dst) % sizeof (dst[0]) == 0);
168  ASSERT (pointer_to_uword (src) % sizeof (src[0]) == 0);
169  ASSERT (n_bytes % sizeof (dst[0]) == 0);
170 
171  if (4 * sizeof (dst[0]) == CLIB_CACHE_LINE_BYTES)
172  {
173  CLIB_PREFETCH (dst + 0, 4 * sizeof (dst[0]), WRITE);
174  CLIB_PREFETCH (src + 0, 4 * sizeof (src[0]), READ);
175 
176  while (n_bytes >= 4 * sizeof (dst[0]))
177  {
178  dst += 4;
179  src += 4;
180  n_bytes -= 4 * sizeof (dst[0]);
181  CLIB_PREFETCH (dst, 4 * sizeof (dst[0]), WRITE);
182  CLIB_PREFETCH (src, 4 * sizeof (src[0]), READ);
183  dst[-4] = src[-4];
184  dst[-3] = src[-3];
185  dst[-2] = src[-2];
186  dst[-1] = src[-1];
187  }
188  }
189  else if (8 * sizeof (dst[0]) == CLIB_CACHE_LINE_BYTES)
190  {
191  CLIB_PREFETCH (dst + 0, 8 * sizeof (dst[0]), WRITE);
192  CLIB_PREFETCH (src + 0, 8 * sizeof (src[0]), READ);
193 
194  while (n_bytes >= 8 * sizeof (dst[0]))
195  {
196  dst += 8;
197  src += 8;
198  n_bytes -= 8 * sizeof (dst[0]);
199  CLIB_PREFETCH (dst, 8 * sizeof (dst[0]), WRITE);
200  CLIB_PREFETCH (src, 8 * sizeof (src[0]), READ);
201  dst[-8] = src[-8];
202  dst[-7] = src[-7];
203  dst[-6] = src[-6];
204  dst[-5] = src[-5];
205  dst[-4] = src[-4];
206  dst[-3] = src[-3];
207  dst[-2] = src[-2];
208  dst[-1] = src[-1];
209  }
210  }
211  else
212  /* Cache line size unknown: fall back to slow version. */ ;
213 
214  while (n_bytes > 0)
215  {
216  *dst++ = *src++;
217  n_bytes -= 1 * sizeof (dst[0]);
218  }
219 }
220 
221 #define BUFFERS_PER_COPY (sizeof (vlib_copy_unit_t) / sizeof (u32))
222 
223 /* Make sure we have at least given number of unaligned buffers. */
224 static void
226  vlib_buffer_free_list_t * free_list,
227  uword n_unaligned_buffers)
228 {
229  word la = vec_len (free_list->aligned_buffers);
230  word lu = vec_len (free_list->unaligned_buffers);
231 
232  /* Aligned come in aligned copy-sized chunks. */
233  ASSERT (la % BUFFERS_PER_COPY == 0);
234 
235  ASSERT (la >= n_unaligned_buffers);
236 
237  while (lu < n_unaligned_buffers)
238  {
239  /* Copy 4 buffers from end of aligned vector to unaligned vector. */
240  vec_add (free_list->unaligned_buffers,
241  free_list->aligned_buffers + la - BUFFERS_PER_COPY,
243  la -= BUFFERS_PER_COPY;
244  lu += BUFFERS_PER_COPY;
245  }
246  _vec_len (free_list->aligned_buffers) = la;
247 }
248 
249 /* After free aligned buffers may not contain even sized chunks. */
250 static void
252 {
253  uword l, n_trim;
254 
255  /* Add unaligned to aligned before trim. */
256  l = vec_len (f->unaligned_buffers);
257  if (l > 0)
258  {
260  /* align */ sizeof (vlib_copy_unit_t));
261 
262  _vec_len (f->unaligned_buffers) = 0;
263  }
264 
265  /* Remove unaligned buffers from end of aligned vector and save for next trim. */
266  l = vec_len (f->aligned_buffers);
267  n_trim = l % BUFFERS_PER_COPY;
268  if (n_trim)
269  {
270  /* Trim aligned -> unaligned. */
271  vec_add (f->unaligned_buffers, f->aligned_buffers + l - n_trim, n_trim);
272 
273  /* Remove from aligned. */
274  _vec_len (f->aligned_buffers) = l - n_trim;
275  }
276 }
277 
278 static void
281 {
282  uword l;
283  u32 *d;
284 
285  trim_aligned (src);
286  trim_aligned (dst);
287 
288  l = vec_len (src->aligned_buffers);
289  if (l > 0)
290  {
291  vec_add2_aligned (dst->aligned_buffers, d, l,
292  /* align */ sizeof (vlib_copy_unit_t));
293  vlib_aligned_memcpy (d, src->aligned_buffers, l * sizeof (d[0]));
294  vec_free (src->aligned_buffers);
295  }
296 
297  l = vec_len (src->unaligned_buffers);
298  if (l > 0)
299  {
302  }
303 }
304 
307 {
309 
310  size = vlib_buffer_round_size (size);
311  uword *p = hash_get (bm->free_list_by_size, size);
312  return p ? p[0] : ~0;
313 }
314 
315 /* Add buffer free list. */
316 static u32
318  u32 n_data_bytes,
319  u32 is_public, u32 is_default, u8 * name)
320 {
323 
324  if (!is_default && pool_elts (bm->buffer_free_list_pool) == 0)
325  {
326  u32 default_free_free_list_index;
327 
328  /* *INDENT-OFF* */
329  default_free_free_list_index =
331  (vm,
332  /* default buffer size */ VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES,
333  /* is_public */ 1,
334  /* is_default */ 1,
335  (u8 *) "default");
336  /* *INDENT-ON* */
337  ASSERT (default_free_free_list_index ==
339 
340  if (n_data_bytes == VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES && is_public)
341  return default_free_free_list_index;
342  }
343 
345 
346  memset (f, 0, sizeof (f[0]));
347  f->index = f - bm->buffer_free_list_pool;
348  f->n_data_bytes = vlib_buffer_round_size (n_data_bytes);
350  f->name = clib_mem_is_heap_object (name) ? name : format (0, "%s", name);
351 
352  /* Setup free buffer template. */
354 
355  if (is_public)
356  {
358  if (!p)
360  }
361 
362  return f->index;
363 }
364 
365 u32
367  char *fmt, ...)
368 {
369  va_list va;
370  u8 *name;
371 
372  va_start (va, fmt);
373  name = va_format (0, fmt, &va);
374  va_end (va);
375 
376  return vlib_buffer_create_free_list_helper (vm, n_data_bytes,
377  /* is_public */ 0,
378  /* is_default */ 0,
379  name);
380 }
381 
382 u32
384  char *fmt, ...)
385 {
386  u32 i = vlib_buffer_get_free_list_with_size (vm, n_data_bytes);
387 
388  if (i == ~0)
389  {
390  va_list va;
391  u8 *name;
392 
393  va_start (va, fmt);
394  name = va_format (0, fmt, &va);
395  va_end (va);
396 
397  i = vlib_buffer_create_free_list_helper (vm, n_data_bytes,
398  /* is_public */ 1,
399  /* is_default */ 0,
400  name);
401  }
402 
403  return i;
404 }
405 
406 static void
408 {
409  u32 i;
410  struct rte_mbuf *mb;
411  vlib_buffer_t *b;
412 
413  for (i = 0; i < vec_len (f->unaligned_buffers); i++)
414  {
415  b = vlib_get_buffer (vm, f->unaligned_buffers[i]);
416  mb = rte_mbuf_from_vlib_buffer (b);
417  ASSERT (rte_mbuf_refcnt_read (mb) == 1);
418  rte_pktmbuf_free (mb);
419  }
420  for (i = 0; i < vec_len (f->aligned_buffers); i++)
421  {
422  b = vlib_get_buffer (vm, f->aligned_buffers[i]);
423  mb = rte_mbuf_from_vlib_buffer (b);
424  ASSERT (rte_mbuf_refcnt_read (mb) == 1);
425  rte_pktmbuf_free (mb);
426  }
427  vec_free (f->name);
430 }
431 
432 /* Add buffer free list. */
433 void
435 {
438  u32 merge_index;
439 
440  f = vlib_buffer_get_free_list (vm, free_list_index);
441 
442  merge_index = vlib_buffer_get_free_list_with_size (vm, f->n_data_bytes);
443  if (merge_index != ~0 && merge_index != free_list_index)
444  {
446  merge_index), f);
447  }
448 
449  del_free_list (vm, f);
450 
451  /* Poison it. */
452  memset (f, 0xab, sizeof (f[0]));
453 
455 }
456 
457 /* Make sure free list has at least given number of free buffers. */
458 static uword
460  vlib_buffer_free_list_t * fl, uword min_free_buffers)
461 {
462  vlib_buffer_t *b;
463  int n, i;
464  u32 bi;
465  u32 n_remaining = 0, n_alloc = 0;
466  unsigned socket_id = rte_socket_id ? rte_socket_id () : 0;
467  struct rte_mempool *rmp = vm->buffer_main->pktmbuf_pools[socket_id];
468  struct rte_mbuf *mb;
469 
470  /* Too early? */
471  if (PREDICT_FALSE (rmp == 0))
472  return 0;
473 
474  trim_aligned (fl);
475 
476  /* Already have enough free buffers on free list? */
477  n = min_free_buffers - vec_len (fl->aligned_buffers);
478  if (n <= 0)
479  return min_free_buffers;
480 
481  /* Always allocate round number of buffers. */
482  n = round_pow2 (n, BUFFERS_PER_COPY);
483 
484  /* Always allocate new buffers in reasonably large sized chunks. */
486 
487  vec_validate (vm->mbuf_alloc_list, n - 1);
488 
489  if (rte_mempool_get_bulk (rmp, vm->mbuf_alloc_list, n) < 0)
490  return 0;
491 
492  _vec_len (vm->mbuf_alloc_list) = n;
493 
494  for (i = 0; i < n; i++)
495  {
496  mb = vm->mbuf_alloc_list[i];
497 
498  ASSERT (rte_mbuf_refcnt_read (mb) == 0);
499  rte_mbuf_refcnt_set (mb, 1);
500  mb->next = NULL;
501  mb->data_off = RTE_PKTMBUF_HEADROOM;
502  mb->nb_segs = 1;
503 
504  b = vlib_buffer_from_rte_mbuf (mb);
505  bi = vlib_get_buffer_index (vm, b);
506 
508  n_alloc++;
509  n_remaining--;
510 
512 
513  if (fl->buffer_init_function)
514  fl->buffer_init_function (vm, fl, &bi, 1);
515  }
516 
517  fl->n_alloc += n;
518 
519  return n;
520 }
521 
524 {
525  return (pointer_to_uword (x) / sizeof (x[0])) % BUFFERS_PER_COPY;
526 }
527 
528 static u32
530  vlib_buffer_free_list_t * free_list,
531  u32 * alloc_buffers, u32 n_alloc_buffers)
532 {
533  u32 *dst, *u_src;
534  uword u_len, n_left;
535  uword n_unaligned_start, n_unaligned_end, n_filled;
536 
537  n_left = n_alloc_buffers;
538  dst = alloc_buffers;
539  n_unaligned_start = ((BUFFERS_PER_COPY - copy_alignment (dst))
540  & (BUFFERS_PER_COPY - 1));
541 
542  n_filled = fill_free_list (vm, free_list, n_alloc_buffers);
543  if (n_filled == 0)
544  return 0;
545 
546  n_left = n_filled < n_left ? n_filled : n_left;
547  n_alloc_buffers = n_left;
548 
549  if (n_unaligned_start >= n_left)
550  {
551  n_unaligned_start = n_left;
552  n_unaligned_end = 0;
553  }
554  else
555  n_unaligned_end = copy_alignment (dst + n_alloc_buffers);
556 
557  fill_unaligned (vm, free_list, n_unaligned_start + n_unaligned_end);
558 
559  u_len = vec_len (free_list->unaligned_buffers);
560  u_src = free_list->unaligned_buffers + u_len - 1;
561 
562  if (n_unaligned_start)
563  {
564  uword n_copy = n_unaligned_start;
565  if (n_copy > n_left)
566  n_copy = n_left;
567  n_left -= n_copy;
568 
569  while (n_copy > 0)
570  {
571  *dst++ = *u_src--;
572  n_copy--;
573  u_len--;
574  }
575 
576  /* Now dst should be aligned. */
577  if (n_left > 0)
578  ASSERT (pointer_to_uword (dst) % sizeof (vlib_copy_unit_t) == 0);
579  }
580 
581  /* Aligned copy. */
582  {
583  vlib_copy_unit_t *d, *s;
584  uword n_copy;
585 
586  if (vec_len (free_list->aligned_buffers) <
587  ((n_left / BUFFERS_PER_COPY) * BUFFERS_PER_COPY))
588  abort ();
589 
590  n_copy = n_left / BUFFERS_PER_COPY;
591  n_left = n_left % BUFFERS_PER_COPY;
592 
593  /* Remove buffers from aligned free list. */
594  _vec_len (free_list->aligned_buffers) -= n_copy * BUFFERS_PER_COPY;
595 
596  s = (vlib_copy_unit_t *) vec_end (free_list->aligned_buffers);
597  d = (vlib_copy_unit_t *) dst;
598 
599  /* Fast path loop. */
600  while (n_copy >= 4)
601  {
602  d[0] = s[0];
603  d[1] = s[1];
604  d[2] = s[2];
605  d[3] = s[3];
606  n_copy -= 4;
607  s += 4;
608  d += 4;
609  }
610 
611  while (n_copy >= 1)
612  {
613  d[0] = s[0];
614  n_copy -= 1;
615  s += 1;
616  d += 1;
617  }
618 
619  dst = (void *) d;
620  }
621 
622  /* Unaligned copy. */
623  ASSERT (n_unaligned_end == n_left);
624  while (n_left > 0)
625  {
626  *dst++ = *u_src--;
627  n_left--;
628  u_len--;
629  }
630 
631  if (!free_list->unaligned_buffers)
632  ASSERT (u_len == 0);
633  else
634  _vec_len (free_list->unaligned_buffers) = u_len;
635 
636  return n_alloc_buffers;
637 }
638 
639 /* Allocate a given number of buffers into given array.
640  Returns number actually allocated which will be either zero or
641  number requested. */
642 u32
643 vlib_buffer_alloc (vlib_main_t * vm, u32 * buffers, u32 n_buffers)
644 {
646 
647  return alloc_from_free_list
648  (vm,
651  buffers, n_buffers);
652 }
653 
654 u32
656  u32 * buffers,
657  u32 n_buffers, u32 free_list_index)
658 {
661  f = pool_elt_at_index (bm->buffer_free_list_pool, free_list_index);
662  return alloc_from_free_list (vm, f, buffers, n_buffers);
663 }
664 
665 always_inline void
668  u32 buffer_index, u8 do_init)
669 {
670  vlib_buffer_t *b;
671  b = vlib_get_buffer (vm, buffer_index);
672  if (PREDICT_TRUE (do_init))
674  vec_add1_aligned (f->aligned_buffers, buffer_index,
675  sizeof (vlib_copy_unit_t));
676 }
677 
680 {
682  u32 i;
683 
684  *index = i = b->free_list_index;
686 }
687 
688 void *
690 {
692  void *rv = bm->buffer_free_callback;
693 
694  bm->buffer_free_callback = fp;
695  return rv;
696 }
697 
700  u32 * buffers, u32 n_buffers, u32 follow_buffer_next)
701 {
704  u32 fi;
705  int i;
706  u32 (*cb) (vlib_main_t * vm, u32 * buffers, u32 n_buffers,
707  u32 follow_buffer_next);
708 
709  cb = bm->buffer_free_callback;
710 
711  if (PREDICT_FALSE (cb != 0))
712  n_buffers = (*cb) (vm, buffers, n_buffers, follow_buffer_next);
713 
714  if (!n_buffers)
715  return;
716 
717  for (i = 0; i < n_buffers; i++)
718  {
719  vlib_buffer_t *b;
720  struct rte_mbuf *mb;
721 
722  b = vlib_get_buffer (vm, buffers[i]);
723 
724  fl = buffer_get_free_list (vm, b, &fi);
725 
726  /* The only current use of this callback: multicast recycle */
728  {
729  int j;
730 
732  (vm, fl, buffers[i], (b->flags & VLIB_BUFFER_RECYCLE) == 0);
733 
734  for (j = 0; j < vec_len (bm->announce_list); j++)
735  {
736  if (fl == bm->announce_list[j])
737  goto already_announced;
738  }
739  vec_add1 (bm->announce_list, fl);
740  already_announced:
741  ;
742  }
743  else
744  {
745  if (PREDICT_TRUE ((b->flags & VLIB_BUFFER_RECYCLE) == 0))
746  {
747  mb = rte_mbuf_from_vlib_buffer (b);
748  ASSERT (rte_mbuf_refcnt_read (mb) == 1);
749  rte_pktmbuf_free (mb);
750  }
751  }
752  }
753  if (vec_len (bm->announce_list))
754  {
756  for (i = 0; i < vec_len (bm->announce_list); i++)
757  {
758  fl = bm->announce_list[i];
760  }
761  _vec_len (bm->announce_list) = 0;
762  }
763 }
764 
765 void
766 vlib_buffer_free (vlib_main_t * vm, u32 * buffers, u32 n_buffers)
767 {
768  vlib_buffer_free_inline (vm, buffers, n_buffers, /* follow_buffer_next */
769  1);
770 }
771 
772 void
773 vlib_buffer_free_no_next (vlib_main_t * vm, u32 * buffers, u32 n_buffers)
774 {
775  vlib_buffer_free_inline (vm, buffers, n_buffers, /* follow_buffer_next */
776  0);
777 }
778 
779 /* Copy template packet data into buffers as they are allocated. */
780 __attribute__ ((unused))
781  static void
784  u32 * buffers, u32 n_buffers)
785 {
789  uword i;
790 
791  for (i = 0; i < n_buffers; i++)
792  {
793  vlib_buffer_t *b = vlib_get_buffer (vm, buffers[i]);
796  b->current_length);
797  }
798 }
799 
800 void
803  void *packet_data,
804  uword n_packet_data_bytes,
805  uword min_n_buffers_each_physmem_alloc,
806  char *fmt, ...)
807 {
808  va_list va;
809  __attribute__ ((unused)) u8 *name;
810 
811  va_start (va, fmt);
812  name = va_format (0, fmt, &va);
813  va_end (va);
814 
816  memset (t, 0, sizeof (t[0]));
817 
818  vec_add (t->packet_data, packet_data, n_packet_data_bytes);
819 
821 }
822 
823 void *
825  vlib_packet_template_t * t, u32 * bi_result)
826 {
827  u32 bi;
828  vlib_buffer_t *b;
829 
830  if (vlib_buffer_alloc (vm, &bi, 1) != 1)
831  return 0;
832 
833  *bi_result = bi;
834 
835  b = vlib_get_buffer (vm, bi);
837  t->packet_data, vec_len (t->packet_data));
839 
840  /* Fix up mbuf header length fields */
841  struct rte_mbuf *mb;
842  mb = rte_mbuf_from_vlib_buffer (b);
843  mb->data_len = b->current_length;
844  mb->pkt_len = b->current_length;
845 
846  return b->data;
847 }
848 
849 /* Append given data to end of buffer, possibly allocating new buffers. */
850 u32
852  u32 free_list_index,
853  u32 buffer_index, void *data, u32 n_data_bytes)
854 {
855  u32 n_buffer_bytes, n_left, n_left_this_buffer, bi;
856  vlib_buffer_t *b;
857  void *d;
858 
859  bi = buffer_index;
860  if (bi == 0
861  && 1 != vlib_buffer_alloc_from_free_list (vm, &bi, 1, free_list_index))
862  goto out_of_buffers;
863 
864  d = data;
865  n_left = n_data_bytes;
866  n_buffer_bytes = vlib_buffer_free_list_buffer_size (vm, free_list_index);
867 
868  b = vlib_get_buffer (vm, bi);
870 
871  /* Get to the end of the chain before we try to append data... */
872  while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
873  b = vlib_get_buffer (vm, b->next_buffer);
874 
875  while (1)
876  {
877  u32 n;
878 
879  ASSERT (n_buffer_bytes >= b->current_length);
880  n_left_this_buffer =
881  n_buffer_bytes - (b->current_data + b->current_length);
882  n = clib_min (n_left_this_buffer, n_left);
884  b->current_length += n;
885  n_left -= n;
886  if (n_left == 0)
887  break;
888 
889  d += n;
890  if (1 !=
892  free_list_index))
893  goto out_of_buffers;
894 
896 
897  b = vlib_get_buffer (vm, b->next_buffer);
898  }
899 
900  return bi;
901 
902 out_of_buffers:
903  clib_error ("out of buffers");
904  return bi;
905 }
906 
907 u16
909  u32 free_list_index,
911  vlib_buffer_t ** last,
912  void *data, u16 data_len)
913 {
914  vlib_buffer_t *l = *last;
915  u32 n_buffer_bytes =
916  vlib_buffer_free_list_buffer_size (vm, free_list_index);
917  u16 copied = 0;
918  ASSERT (n_buffer_bytes >= l->current_length + l->current_data);
919  while (data_len)
920  {
921  u16 max = n_buffer_bytes - l->current_length - l->current_data;
922  if (max == 0)
923  {
924  if (1 !=
926  free_list_index))
927  return copied;
928  *last = l = vlib_buffer_chain_buffer (vm, first, l, l->next_buffer);
929  max = n_buffer_bytes - l->current_length - l->current_data;
930  }
931 
932  u16 len = (data_len > max) ? max : data_len;
934  data + copied, len);
935  vlib_buffer_chain_increase_length (first, l, len);
936  data_len -= len;
937  copied += len;
938  }
939  return copied;
940 }
941 
942 /*
943  * Fills in the required rte_mbuf fields for chained buffers given a VLIB chain.
944  */
945 void
947 {
948  vlib_buffer_t *b = b_first, *prev = b_first;
949  struct rte_mbuf *mb_prev, *mb, *mb_first;
950 
951  mb_first = rte_mbuf_from_vlib_buffer (b_first);
952 
953  mb_first->pkt_len = mb_first->data_len = b_first->current_length;
954  while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
955  {
956  b = vlib_get_buffer (vm, b->next_buffer);
957  mb = rte_mbuf_from_vlib_buffer (b);
958  mb_prev = rte_mbuf_from_vlib_buffer (prev);
959  mb_first->nb_segs++;
960  mb_first->pkt_len += b->current_length;
961  mb_prev->next = mb;
962  mb->data_len = b->current_length;
963  prev = b;
964  }
965 }
966 
967 clib_error_t *
968 vlib_buffer_pool_create (vlib_main_t * vm, unsigned num_mbufs,
969  unsigned socket_id)
970 {
972  vlib_physmem_main_t *vpm = &vm->physmem_main;
973  struct rte_mempool *rmp;
974 #if RTE_VERSION < RTE_VERSION_NUM(16, 7, 0, 0)
975  uword new_start, new_size;
976 #endif
977  int i;
978 
979  if (!rte_pktmbuf_pool_create)
980  return clib_error_return (0, "not linked with DPDK");
981 
983 
984  /* pool already exists, nothing to do */
985  if (bm->pktmbuf_pools[socket_id])
986  return 0;
987 
988  u8 *pool_name = format (0, "mbuf_pool_socket%u%c", socket_id, 0);
989 
990  rmp = rte_pktmbuf_pool_create ((char *) pool_name, /* pool name */
991  num_mbufs, /* number of mbufs */
992  512, /* cache size */
993  VLIB_BUFFER_HDR_SIZE, /* priv size */
994  VLIB_BUFFER_PRE_DATA_SIZE + VLIB_BUFFER_DATA_SIZE, /* dataroom size */
995  socket_id); /* cpu socket */
996 
997  if (rmp)
998  {
999 #if RTE_VERSION >= RTE_VERSION_NUM(16, 7, 0, 0)
1000  {
1001  uword this_pool_end;
1002  uword this_pool_start;
1003  uword this_pool_size;
1004  uword save_vpm_start, save_vpm_end, save_vpm_size;
1005  struct rte_mempool_memhdr *memhdr;
1006 
1007  this_pool_start = ~0ULL;
1008  this_pool_end = 0LL;
1009 
1010  STAILQ_FOREACH (memhdr, &rmp->mem_list, next)
1011  {
1012  if (((uword) (memhdr->addr + memhdr->len)) > this_pool_end)
1013  this_pool_end = (uword) (memhdr->addr + memhdr->len);
1014  if (((uword) memhdr->addr) < this_pool_start)
1015  this_pool_start = (uword) (memhdr->addr);
1016  }
1017  ASSERT (this_pool_start < ~0ULL && this_pool_end > 0);
1018  this_pool_size = this_pool_end - this_pool_start;
1019 
1020  if (CLIB_DEBUG > 1)
1021  {
1022  clib_warning ("%s: pool start %llx pool end %llx pool size %lld",
1023  pool_name, this_pool_start, this_pool_end,
1024  this_pool_size);
1025  clib_warning
1026  ("before: virtual.start %llx virtual.end %llx virtual.size %lld",
1027  vpm->virtual.start, vpm->virtual.end, vpm->virtual.size);
1028  }
1029 
1030  save_vpm_start = vpm->virtual.start;
1031  save_vpm_end = vpm->virtual.end;
1032  save_vpm_size = vpm->virtual.size;
1033 
1034  if ((this_pool_start < vpm->virtual.start) || vpm->virtual.start == 0)
1035  vpm->virtual.start = this_pool_start;
1036  if (this_pool_end > vpm->virtual.end)
1037  vpm->virtual.end = this_pool_end;
1038 
1039  vpm->virtual.size = vpm->virtual.end - vpm->virtual.start;
1040 
1041  if (CLIB_DEBUG > 1)
1042  {
1043  clib_warning
1044  ("after: virtual.start %llx virtual.end %llx virtual.size %lld",
1045  vpm->virtual.start, vpm->virtual.end, vpm->virtual.size);
1046  }
1047 
1048  /* check if fits into buffer index range */
1049  if ((u64) vpm->virtual.size >
1050  ((u64) 1 << (32 + CLIB_LOG2_CACHE_LINE_BYTES)))
1051  {
1052  clib_warning ("physmem: virtual size out of range!");
1053  vpm->virtual.start = save_vpm_start;
1054  vpm->virtual.end = save_vpm_end;
1055  vpm->virtual.size = save_vpm_size;
1056  rmp = 0;
1057  }
1058  }
1059  if (rmp)
1060  {
1061  bm->pktmbuf_pools[socket_id] = rmp;
1062  vec_free (pool_name);
1063  return 0;
1064  }
1065  }
1066 #else
1067  new_start = pointer_to_uword (rmp);
1068  new_size = rmp->elt_va_end - new_start;
1069 
1070  if (vpm->virtual.size > 0)
1071  {
1072  ASSERT (new_start != vpm->virtual.start);
1073  if (new_start < vpm->virtual.start)
1074  {
1075  new_size = vpm->virtual.size + vpm->virtual.start - new_start;
1076  }
1077  else
1078  {
1079  new_size += new_start - vpm->virtual.start;
1080  new_start = vpm->virtual.start;
1081  }
1082 
1083  /* check if fits into buffer index range */
1084  if ((u64) new_size > ((u64) 1 << (32 + CLIB_LOG2_CACHE_LINE_BYTES)))
1085  rmp = 0;
1086  }
1087  }
1088 
1089  if (rmp)
1090  {
1091  bm->pktmbuf_pools[socket_id] = rmp;
1092  vpm->virtual.start = new_start;
1093  vpm->virtual.size = new_size;
1094  vpm->virtual.end = new_start + new_size;
1095  vec_free (pool_name);
1096  return 0;
1097  }
1098 #endif
1099 
1100  vec_free (pool_name);
1101 
1102  /* no usable pool for this socket, try to use pool from another one */
1103  for (i = 0; i < vec_len (bm->pktmbuf_pools); i++)
1104  {
1105  if (bm->pktmbuf_pools[i])
1106  {
1107  clib_warning
1108  ("WARNING: Failed to allocate mempool for CPU socket %u. "
1109  "Threads running on socket %u will use socket %u mempool.",
1110  socket_id, socket_id, i);
1111  bm->pktmbuf_pools[socket_id] = bm->pktmbuf_pools[i];
1112  return 0;
1113  }
1114  }
1115 
1116  return clib_error_return (0, "failed to allocate mempool on socket %u",
1117  socket_id);
1118 }
1119 
1120 
1121 static void
1123 {
1124  vlib_main_t *vm;
1126  uword n, n_bytes_to_write;
1128 
1129  n_bytes_to_write = s->current_buffer_index;
1130  sm =
1133  vm = sm->vlib_main;
1134 
1135  ASSERT (sm->tx.max_n_data_bytes_per_chain > 0);
1137  || sm->tx.n_total_data_bytes + n_bytes_to_write >
1138  sm->tx.max_n_data_bytes_per_chain)
1139  {
1141 
1142  last = vlib_get_buffer (vm, sm->last_buffer);
1143  last->current_length = n_bytes_to_write;
1144 
1145  vlib_set_next_frame_buffer (vm, &p->node_runtime, sm->tx.next_index,
1146  sm->first_buffer);
1147 
1148  sm->first_buffer = sm->last_buffer = ~0;
1149  sm->tx.n_total_data_bytes = 0;
1150  }
1151 
1152  else if (n_bytes_to_write == 0 && s->n_buffer_bytes == 0)
1153  {
1154  ASSERT (sm->first_buffer == ~0);
1155  ASSERT (sm->last_buffer == ~0);
1156  n =
1158  sm->tx.free_list_index);
1159  if (n != 1)
1160  serialize_error (m,
1162  ("vlib_buffer_alloc_from_free_list fails"));
1163  sm->last_buffer = sm->first_buffer;
1164  s->n_buffer_bytes =
1165  vlib_buffer_free_list_buffer_size (vm, sm->tx.free_list_index);
1166  }
1167 
1168  if (n_bytes_to_write > 0)
1169  {
1170  vlib_buffer_t *prev = vlib_get_buffer (vm, sm->last_buffer);
1171  n =
1173  sm->tx.free_list_index);
1174  if (n != 1)
1175  serialize_error (m,
1177  ("vlib_buffer_alloc_from_free_list fails"));
1178  sm->tx.n_total_data_bytes += n_bytes_to_write;
1179  prev->current_length = n_bytes_to_write;
1180  prev->next_buffer = sm->last_buffer;
1182  }
1183 
1184  if (sm->last_buffer != ~0)
1185  {
1186  last = vlib_get_buffer (vm, sm->last_buffer);
1187  s->buffer = vlib_buffer_get_current (last);
1188  s->current_buffer_index = 0;
1190  }
1191 }
1192 
1193 static void
1195 {
1196  vlib_main_t *vm;
1199 
1200  sm =
1203  vm = sm->vlib_main;
1204 
1206  return;
1207 
1208  if (sm->last_buffer != ~0)
1209  {
1210  last = vlib_get_buffer (vm, sm->last_buffer);
1211 
1212  if (last->flags & VLIB_BUFFER_NEXT_PRESENT)
1213  sm->last_buffer = last->next_buffer;
1214  else
1215  {
1216  vlib_buffer_free (vm, &sm->first_buffer, /* count */ 1);
1217  sm->first_buffer = sm->last_buffer = ~0;
1218  }
1219  }
1220 
1221  if (sm->last_buffer == ~0)
1222  {
1223  while (clib_fifo_elts (sm->rx.buffer_fifo) == 0)
1224  {
1225  sm->rx.ready_one_time_event =
1227  ~0);
1228  vlib_process_wait_for_one_time_event (vm, /* no event data */ 0,
1229  sm->rx.ready_one_time_event);
1230  }
1231 
1232  clib_fifo_sub1 (sm->rx.buffer_fifo, sm->first_buffer);
1233  sm->last_buffer = sm->first_buffer;
1234  }
1235 
1236  ASSERT (sm->last_buffer != ~0);
1237 
1238  last = vlib_get_buffer (vm, sm->last_buffer);
1239  s->current_buffer_index = 0;
1240  s->buffer = vlib_buffer_get_current (last);
1241  s->n_buffer_bytes = last->current_length;
1242 }
1243 
1244 static void
1246  vlib_main_t * vm,
1247  vlib_serialize_buffer_main_t * sm, uword is_read)
1248 {
1249  /* Initialize serialize main but save overflow buffer for re-use between calls. */
1250  {
1251  u8 *save = m->stream.overflow_buffer;
1252  memset (m, 0, sizeof (m[0]));
1253  m->stream.overflow_buffer = save;
1254  if (save)
1255  _vec_len (save) = 0;
1256  }
1257 
1258  sm->first_buffer = sm->last_buffer = ~0;
1259  if (is_read)
1260  clib_fifo_reset (sm->rx.buffer_fifo);
1261  else
1262  sm->tx.n_total_data_bytes = 0;
1263  sm->vlib_main = vm;
1266 }
1267 
1268 void
1271 {
1272  serialize_open_vlib_helper (m, vm, sm, /* is_read */ 0);
1273 }
1274 
1275 void
1278 {
1279  serialize_open_vlib_helper (m, vm, sm, /* is_read */ 1);
1280 }
1281 
1282 u32
1284 {
1289  serialize_stream_t *s = &m->stream;
1290 
1291  last = vlib_get_buffer (sm->vlib_main, sm->last_buffer);
1293 
1294  if (vec_len (s->overflow_buffer) > 0)
1295  {
1296  sm->last_buffer
1297  = vlib_buffer_add_data (sm->vlib_main, sm->tx.free_list_index,
1298  sm->last_buffer == ~0 ? 0 : sm->last_buffer,
1299  s->overflow_buffer,
1300  vec_len (s->overflow_buffer));
1301  _vec_len (s->overflow_buffer) = 0;
1302  }
1303 
1304  return sm->first_buffer;
1305 }
1306 
1307 void
1309 {
1313  if (sm->first_buffer != ~0)
1315  clib_fifo_reset (sm->rx.buffer_fifo);
1316  if (m->stream.overflow_buffer)
1317  _vec_len (m->stream.overflow_buffer) = 0;
1318 }
1319 
1320 static u8 *
1322 {
1323  vlib_buffer_free_list_t *f = va_arg (*va, vlib_buffer_free_list_t *);
1324  u32 threadnum = va_arg (*va, u32);
1325  uword bytes_alloc, bytes_free, n_free, size;
1326 
1327  if (!f)
1328  return format (s, "%=7s%=30s%=12s%=12s%=12s%=12s%=12s%=12s",
1329  "Thread", "Name", "Index", "Size", "Alloc", "Free",
1330  "#Alloc", "#Free");
1331 
1332  size = sizeof (vlib_buffer_t) + f->n_data_bytes;
1333  n_free = vec_len (f->aligned_buffers) + vec_len (f->unaligned_buffers);
1334  bytes_alloc = size * f->n_alloc;
1335  bytes_free = size * n_free;
1336 
1337  s = format (s, "%7d%30s%12d%12d%=12U%=12U%=12d%=12d",
1338  threadnum,
1339  f->name, f->index, f->n_data_bytes,
1340  format_memory_size, bytes_alloc,
1341  format_memory_size, bytes_free, f->n_alloc, n_free);
1342 
1343  return s;
1344 }
1345 
1346 static clib_error_t *
1348  unformat_input_t * input, vlib_cli_command_t * cmd)
1349 {
1350  vlib_buffer_main_t *bm;
1352  vlib_main_t *curr_vm;
1353  u32 vm_index = 0;
1354 
1356 
1357  do
1358  {
1359  curr_vm = vec_len (vlib_mains) ? vlib_mains[vm_index] : vm;
1360  bm = curr_vm->buffer_main;
1361 
1362  /* *INDENT-OFF* */
1364  vlib_cli_output (vm, "%U", format_vlib_buffer_free_list, f, vm_index);
1365  }));
1366  /* *INDENT-ON* */
1367 
1368  vm_index++;
1369  }
1370  while (vm_index < vec_len (vlib_mains));
1371 
1372  return 0;
1373 }
1374 
1375 /* *INDENT-OFF* */
1376 VLIB_CLI_COMMAND (show_buffers_command, static) = {
1377  .path = "show buffers",
1378  .short_help = "Show packet buffer allocation",
1379  .function = show_buffers,
1380 };
1381 /* *INDENT-ON* */
1382 
1383 #if CLIB_DEBUG > 0
1384 
1388 
1389 static clib_error_t *
1391 {
1392  void *oldheap;
1393 
1394  vlib_buffer_state_heap = mheap_alloc (0, 10 << 20);
1395 
1397 
1401  clib_mem_set_heap (oldheap);
1402  return 0;
1403 }
1404 
1406 #endif
1407 
1408 /** @endcond */
1409 /*
1410  * fd.io coding-style-patch-verification: ON
1411  *
1412  * Local Variables:
1413  * eval: (c-set-style "gnu")
1414  * End:
1415  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
void vlib_buffer_chain_validate(vlib_main_t *vm, vlib_buffer_t *b_first)
Definition: dpdk_buffer.c:946
uword * vlib_buffer_state_validation_hash
Definition: dpdk_buffer.c:1386
#define hash_set(h, key, value)
Definition: hash.h:254
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
#define clib_min(x, y)
Definition: clib.h:326
#define rte_mbuf_from_vlib_buffer(x)
Definition: buffer.h:382
vlib_node_runtime_t node_runtime
Definition: node.h:494
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static uword clib_fifo_elts(void *v)
Definition: fifo.h:66
static void vlib_set_next_frame_buffer(vlib_main_t *vm, vlib_node_runtime_t *node, u32 next_index, u32 buffer_index)
Definition: node_funcs.h:381
static uword vlib_current_process(vlib_main_t *vm)
Definition: node_funcs.h:408
u32 free_list_index
Buffer free list that this buffer was allocated from and will be freed to.
Definition: buffer.h:105
#define PREDICT_TRUE(x)
Definition: clib.h:98
vlib_physmem_main_t physmem_main
Definition: main.h:106
void * mheap_alloc(void *memory, uword size)
Definition: mheap.c:953
void * vlib_buffer_state_heap
Definition: dpdk_buffer.c:1387
serialize_main_header_t header
Definition: serialize.h:146
static void serialize_error(serialize_main_header_t *m, clib_error_t *error)
Definition: serialize.h:107
#define NULL
Definition: clib.h:55
static vlib_buffer_t * vlib_buffer_chain_buffer(vlib_main_t *vm, vlib_buffer_t *first, vlib_buffer_t *last, u32 next_bi)
Definition: buffer_funcs.h:447
#define vec_add2_aligned(V, P, N, A)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:533
static void vlib_buffer_chain_increase_length(vlib_buffer_t *first, vlib_buffer_t *last, i32 len)
Definition: buffer_funcs.h:477
vlib_buffer_t buffer_init_template
Definition: buffer.h:249
struct vlib_serialize_buffer_main_t::@22::@24 tx
struct vlib_main_t * vlib_main
Definition: buffer.h:327
void vlib_buffer_free_no_next(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers, does not free the buffer chain for each buffer.
Definition: dpdk_buffer.c:773
#define clib_error(format, args...)
Definition: error.h:62
#define CLIB_LOG2_CACHE_LINE_BYTES
Definition: cache.h:49
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
unsigned rte_socket_id()
static void fill_unaligned(vlib_main_t *vm, vlib_buffer_free_list_t *free_list, uword n_unaligned_buffers)
Definition: dpdk_buffer.c:225
static heap_elt_t * last(heap_header_t *h)
Definition: heap.c:53
vlib_buffer_main_t * buffer_main
Definition: main.h:104
static u32 vlib_buffer_create_free_list_helper(vlib_main_t *vm, u32 n_data_bytes, u32 is_public, u32 is_default, u8 *name)
Definition: dpdk_buffer.c:317
u32 min_n_buffers_each_physmem_alloc
Definition: buffer.h:259
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:407
static_always_inline void vlib_buffer_free_inline(vlib_main_t *vm, u32 *buffers, u32 n_buffers, u32 follow_buffer_next)
Definition: dpdk_buffer.c:699
struct vlib_serialize_buffer_main_t::@22::@25 rx
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:559
#define vec_add1_aligned(V, E, A)
Add 1 element to end of vector (alignment specified).
Definition: vec.h:492
static void vlib_buffer_init_for_free_list(vlib_buffer_t *_dst, vlib_buffer_free_list_t *fl)
Definition: buffer_funcs.h:606
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:78
#define static_always_inline
Definition: clib.h:85
void unserialize_open_vlib_buffer(serialize_main_t *m, vlib_main_t *vm, vlib_serialize_buffer_main_t *sm)
Definition: dpdk_buffer.c:1276
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:348
void(* buffer_init_function)(struct vlib_main_t *vm, struct vlib_buffer_free_list_t *fl, u32 *buffers, u32 n_buffers)
Definition: buffer.h:280
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
#define always_inline
Definition: clib.h:84
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:187
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
static uword serialize_stream_is_end_of_stream(serialize_stream_t *s)
Definition: serialize.h:87
#define BUFFERS_PER_COPY
Definition: dpdk_buffer.c:221
static void trim_aligned(vlib_buffer_free_list_t *f)
Definition: dpdk_buffer.c:251
u8 * format_hex_bytes(u8 *s, va_list *va)
Definition: std-formats.c:84
#define clib_warning(format, args...)
Definition: error.h:59
unsigned long u64
Definition: types.h:89
#define vec_end(v)
End (last data address) of vector.
void serialize_open_vlib_buffer(serialize_main_t *m, vlib_main_t *vm, vlib_serialize_buffer_main_t *sm)
Definition: dpdk_buffer.c:1269
u8 * format_vlib_buffer_contents(u8 *s, va_list *va)
Definition: dpdk_buffer.c:141
u8 * format_vlib_buffer(u8 *s, va_list *args)
Definition: dpdk_buffer.c:99
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:82
#define VLIB_BUFFER_NEXT_PRESENT
Definition: buffer.h:95
vlib_buffer_free_list_t ** announce_list
Definition: buffer.h:317
static heap_elt_t * first(heap_header_t *h)
Definition: heap.c:59
vlib_main_t ** vlib_mains
Definition: dpdk_buffer.c:157
#define VLIB_BUFFER_PRE_DATA_SIZE
Definition: buffer.h:52
static void vlib_packet_template_buffer_init(vlib_main_t *vm, vlib_buffer_free_list_t *fl, u32 *buffers, u32 n_buffers)
Definition: dpdk_buffer.c:782
#define hash_get(h, key)
Definition: hash.h:248
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
static uword format_get_indent(u8 *s)
Definition: format.h:72
static void vlib_serialize_rx(serialize_main_header_t *m, serialize_stream_t *s)
Definition: dpdk_buffer.c:1194
uword vlib_buffer_length_in_chain_slow_path(vlib_main_t *vm, vlib_buffer_t *b_first)
Definition: dpdk_buffer.c:82
#define clib_fifo_sub1(f, e)
Definition: fifo.h:224
#define VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES
Definition: buffer.h:304
u32 serialize_close_vlib_buffer(serialize_main_t *m)
Definition: dpdk_buffer.c:1283
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:82
void vlib_aligned_memcpy(void *_dst, void *_src, int n_bytes)
Definition: dpdk_buffer.c:161
static clib_error_t * show_buffers(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: dpdk_buffer.c:1347
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
#define PREDICT_FALSE(x)
Definition: clib.h:97
#define clib_error_create(args...)
Definition: error.h:108
static u32 vlib_buffer_free_list_buffer_size(vlib_main_t *vm, u32 free_list_index)
Definition: buffer_funcs.h:351
u32 vlib_buffer_get_or_create_free_list(vlib_main_t *vm, u32 n_data_bytes, char *fmt,...)
Definition: dpdk_buffer.c:383
static void clib_fifo_reset(void *v)
Definition: fifo.h:88
static vlib_buffer_free_list_t * buffer_get_free_list(vlib_main_t *vm, vlib_buffer_t *b, u32 *index)
Definition: dpdk_buffer.c:679
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:575
static void vlib_serialize_tx(serialize_main_header_t *m, serialize_stream_t *s)
Definition: dpdk_buffer.c:1122
static uword copy_alignment(u32 *x)
Definition: dpdk_buffer.c:523
u16 vlib_buffer_chain_append_data_with_alloc(vlib_main_t *vm, u32 free_list_index, vlib_buffer_t *first, vlib_buffer_t **last, void *data, u16 data_len)
Definition: dpdk_buffer.c:908
clib_error_t * vlib_buffer_pool_create(vlib_main_t *vm, unsigned num_mbufs, unsigned socket_id)
Definition: dpdk_buffer.c:968
#define uword_to_pointer(u, type)
Definition: types.h:136
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P (general version).
Definition: pool.h:169
#define vec_add_aligned(V, E, N, A)
Add N elements to end of vector V (no header, specified alignment)
Definition: vec.h:569
struct rte_mempool ** pktmbuf_pools
Definition: buffer.h:321
serialize_stream_t stream
Definition: serialize.h:147
u32 current_buffer_index
Definition: serialize.h:62
static vlib_process_t * vlib_get_current_process(vlib_main_t *vm)
Definition: node_funcs.h:395
u32(* buffer_free_callback)(struct vlib_main_t *vm, u32 *buffers, u32 n_buffers, u32 follow_buffer_next)
Definition: buffer.h:295
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
u8 * va_format(u8 *s, char *fmt, va_list *va)
Definition: format.c:386
u8 * format_vlib_buffer_and_data(u8 *s, va_list *args)
Definition: dpdk_buffer.c:129
static uword vlib_process_wait_for_one_time_event(vlib_main_t *vm, uword **data_vector, uword with_type_index)
Definition: node_funcs.h:623
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
static void * clib_mem_set_heap(void *heap)
Definition: mem.h:201
void vlib_buffer_delete_free_list(vlib_main_t *vm, u32 free_list_index)
Definition: dpdk_buffer.c:434
void unserialize_close_vlib_buffer(serialize_main_t *m)
Definition: dpdk_buffer.c:1308
#define clib_memcpy(a, b, c)
Definition: string.h:63
static uword vlib_process_create_one_time_event(vlib_main_t *vm, uword node_index, uword with_type_opaque)
Definition: node_funcs.h:724
u32 * vlib_buffer_state_validation_lock
Definition: dpdk_buffer.c:1385
serialize_data_function_t * data_function
Definition: serialize.h:97
#define VLIB_BUFFER_RECYCLE
Definition: buffer.h:99
#define VLIB_BUFFER_TOTAL_LENGTH_VALID
Definition: buffer.h:97
void(* buffers_added_to_freelist_function)(struct vlib_main_t *vm, struct vlib_buffer_free_list_t *fl)
Definition: buffer.h:287
void vlib_worker_thread_barrier_sync(vlib_main_t *vm)
Definition: threads.c:1144
static void add_buffer_to_free_list(vlib_main_t *vm, vlib_buffer_free_list_t *f, u32 buffer_index, u8 do_init)
Definition: dpdk_buffer.c:666
static u8 * format_vlib_buffer_free_list(u8 *s, va_list *va)
Definition: dpdk_buffer.c:1321
static uword round_pow2(uword x, uword pow2)
Definition: clib.h:272
uword data_function_opaque
Definition: serialize.h:74
u8 * format_memory_size(u8 *s, va_list *va)
Definition: std-formats.c:193
#define VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX
Definition: buffer.h:303
#define hash_create(elts, value_bytes)
Definition: hash.h:647
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
#define VLIB_BUFFER_HDR_SIZE
Definition: buffer.h:154
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
static u32 alloc_from_free_list(vlib_main_t *vm, vlib_buffer_free_list_t *free_list, u32 *alloc_buffers, u32 n_alloc_buffers)
Definition: dpdk_buffer.c:529
void vlib_packet_template_init(vlib_main_t *vm, vlib_packet_template_t *t, void *packet_data, uword n_packet_data_bytes, uword min_n_buffers_each_physmem_alloc, char *fmt,...)
Definition: dpdk_buffer.c:801
u32 size
Definition: vhost-user.h:77
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:114
u64 vlib_copy_unit_t
Definition: buffer.h:62
static uword clib_mem_is_heap_object(void *p)
Definition: mem.h:137
static uword fill_free_list(vlib_main_t *vm, vlib_buffer_free_list_t *fl, uword min_free_buffers)
Definition: dpdk_buffer.c:459
void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: dpdk_buffer.c:766
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:93
#define clib_max(x, y)
Definition: clib.h:319
u64 uword
Definition: types.h:112
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
Definition: buffer.h:109
void ** mbuf_alloc_list
Definition: main.h:161
static u32 vlib_buffer_get_free_list_with_size(vlib_main_t *vm, u32 size)
Definition: dpdk_buffer.c:306
unsigned short u16
Definition: types.h:57
VLIB_CLI_COMMAND(set_interface_ip_source_and_port_range_check_command, static)
i64 word
Definition: types.h:111
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
static void del_free_list(vlib_main_t *vm, vlib_buffer_free_list_t *f)
Definition: dpdk_buffer.c:407
u32 vlib_buffer_alloc_from_free_list(vlib_main_t *vm, u32 *buffers, u32 n_buffers, u32 free_list_index)
Allocate buffers from specific freelist into supplied array.
Definition: dpdk_buffer.c:655
vlib_buffer_free_list_t * buffer_free_list_pool
Definition: buffer.h:302
#define VLIB_BUFFER_DATA_SIZE
Definition: buffer.h:51
void * vlib_set_buffer_free_callback(vlib_main_t *vm, void *fp)
Definition: dpdk_buffer.c:689
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1176
#define vlib_buffer_from_rte_mbuf(x)
Definition: buffer.h:383
vlib_physmem_region_t virtual
Definition: physmem.h:50
u8 data[0]
Packet data.
Definition: buffer.h:151
void * vlib_packet_template_get_packet(vlib_main_t *vm, vlib_packet_template_t *t, u32 *bi_result)
Definition: dpdk_buffer.c:824
u32 vlib_buffer_add_data(vlib_main_t *vm, u32 free_list_index, u32 buffer_index, void *data, u32 n_data_bytes)
Definition: dpdk_buffer.c:851
uword buffer_init_function_opaque
Definition: buffer.h:289
static void vlib_buffer_free_one(vlib_main_t *vm, u32 buffer_index)
Free one buffer Shorthand to free a single buffer chain.
Definition: buffer_funcs.h:322
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
static vlib_buffer_free_list_t * vlib_buffer_get_free_list(vlib_main_t *vm, u32 free_list_index)
Definition: buffer_funcs.h:337
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
static clib_error_t * buffer_state_validation_init(vlib_main_t *vm)
Definition: dpdk_buffer.c:1390
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: dpdk_buffer.c:643
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
u32 trace_index
Specifies index into trace buffer if VLIB_PACKET_IS_TRACED flag is set.
Definition: buffer.h:135
uword * free_list_by_size
Definition: buffer.h:308
static void merge_free_lists(vlib_buffer_free_list_t *dst, vlib_buffer_free_list_t *src)
Definition: dpdk_buffer.c:279
static u32 vlib_buffer_round_size(u32 size)
Definition: buffer_funcs.h:271
u32 vlib_buffer_create_free_list(vlib_main_t *vm, u32 n_data_bytes, char *fmt,...)
Definition: dpdk_buffer.c:366
static void serialize_open_vlib_helper(serialize_main_t *m, vlib_main_t *vm, vlib_serialize_buffer_main_t *sm, uword is_read)
Definition: dpdk_buffer.c:1245
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109