FD.io VPP  v16.09
Vector Packet Processing
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.
45  */
46 
47 #include <vlib/vlib.h>
48 
49 uword
51  vlib_buffer_t * b_first)
52 {
53  vlib_buffer_t *b = b_first;
54  uword l_first = b_first->current_length;
55  uword l = 0;
56  while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
57  {
58  b = vlib_get_buffer (vm, b->next_buffer);
59  l += b->current_length;
60  }
63  return l + l_first;
64 }
65 
66 u8 *
67 format_vlib_buffer (u8 * s, va_list * args)
68 {
69  vlib_buffer_t *b = va_arg (*args, vlib_buffer_t *);
70 
71  s = format (s, "current data %d, length %d, free-list %d",
73 
75  s = format (s, ", trace 0x%x", b->trace_index);
76 
78  s = format (s, ", next-buffer 0x%x", b->next_buffer);
79 
80  return s;
81 }
82 
83 u8 *
84 format_vlib_buffer_and_data (u8 * s, va_list * args)
85 {
86  vlib_buffer_t *b = va_arg (*args, vlib_buffer_t *);
87 
88  s = format (s, "%U, %U",
91 
92  return s;
93 }
94 
95 static u8 *
96 format_vlib_buffer_known_state (u8 * s, va_list * args)
97 {
98  vlib_buffer_known_state_t state = va_arg (*args, vlib_buffer_known_state_t);
99  char *t;
100 
101  switch (state)
102  {
103  case VLIB_BUFFER_UNKNOWN:
104  t = "unknown";
105  break;
106 
107  case VLIB_BUFFER_KNOWN_ALLOCATED:
108  t = "known-allocated";
109  break;
110 
111  case VLIB_BUFFER_KNOWN_FREE:
112  t = "known-free";
113  break;
114 
115  default:
116  t = "invalid";
117  break;
118  }
119 
120  return format (s, "%s", t);
121 }
122 
123 u8 *
124 format_vlib_buffer_contents (u8 * s, va_list * va)
125 {
126  vlib_main_t *vm = va_arg (*va, vlib_main_t *);
127  vlib_buffer_t *b = va_arg (*va, vlib_buffer_t *);
128 
129  while (1)
130  {
132  if (!(b->flags & VLIB_BUFFER_NEXT_PRESENT))
133  break;
134  b = vlib_get_buffer (vm, b->next_buffer);
135  }
136 
137  return s;
138 }
139 
140 static u8 *
141 vlib_validate_buffer_helper (vlib_main_t * vm,
142  u32 bi,
143  uword follow_buffer_next, uword ** unique_hash)
144 {
145  vlib_buffer_t *b = vlib_get_buffer (vm, bi);
148 
150  return format (0, "unknown free list 0x%x", b->free_list_index);
151 
153 
154  if ((signed) b->current_data < (signed) -VLIB_BUFFER_PRE_DATA_SIZE)
155  return format (0, "current data %d before pre-data", b->current_data);
156 #if DPDK == 0
157  if (b->current_data + b->current_length > fl->n_data_bytes)
158  return format (0, "%d-%d beyond end of buffer %d",
160 #endif
161 
162  if (follow_buffer_next && (b->flags & VLIB_BUFFER_NEXT_PRESENT))
163  {
164  vlib_buffer_known_state_t k;
165  u8 *msg, *result;
166 
167  k = vlib_buffer_is_known (vm, b->next_buffer);
168  if (k != VLIB_BUFFER_KNOWN_ALLOCATED)
169  return format (0, "next 0x%x: %U",
170  b->next_buffer, format_vlib_buffer_known_state, k);
171 
172  if (unique_hash)
173  {
174  if (hash_get (*unique_hash, b->next_buffer))
175  return format (0, "duplicate buffer 0x%x", b->next_buffer);
176 
177  hash_set1 (*unique_hash, b->next_buffer);
178  }
179 
180  msg = vlib_validate_buffer (vm, b->next_buffer, follow_buffer_next);
181  if (msg)
182  {
183  result = format (0, "next 0x%x: %v", b->next_buffer, msg);
184  vec_free (msg);
185  return result;
186  }
187  }
188 
189  return 0;
190 }
191 
192 u8 *
193 vlib_validate_buffer (vlib_main_t * vm, u32 bi, uword follow_buffer_next)
194 {
195  return vlib_validate_buffer_helper (vm, bi, follow_buffer_next,
196  /* unique_hash */ 0);
197 }
198 
199 u8 *
200 vlib_validate_buffers (vlib_main_t * vm,
201  u32 * buffers,
202  uword next_buffer_stride,
203  uword n_buffers,
204  vlib_buffer_known_state_t known_state,
205  uword follow_buffer_next)
206 {
207  uword i, *hash;
208  u32 bi, *b = buffers;
209  vlib_buffer_known_state_t k;
210  u8 *msg = 0, *result = 0;
211 
212  hash = hash_create (0, 0);
213  for (i = 0; i < n_buffers; i++)
214  {
215  bi = b[0];
216  b += next_buffer_stride;
217 
218  /* Buffer is not unique. */
219  if (hash_get (hash, bi))
220  {
221  msg = format (0, "not unique");
222  goto done;
223  }
224 
225  k = vlib_buffer_is_known (vm, bi);
226  if (k != known_state)
227  {
228  msg = format (0, "is %U; expected %U",
229  format_vlib_buffer_known_state, k,
230  format_vlib_buffer_known_state, known_state);
231  goto done;
232  }
233 
234  msg = vlib_validate_buffer_helper (vm, bi, follow_buffer_next, &hash);
235  if (msg)
236  goto done;
237 
238  hash_set1 (hash, bi);
239  }
240 
241 done:
242  if (msg)
243  {
244  result = format (0, "0x%x: %v", bi, msg);
245  vec_free (msg);
246  }
247  hash_free (hash);
248  return result;
249 }
250 
252 
253 /* When dubugging validate that given buffers are either known allocated
254  or known free. */
255 static void
256 vlib_buffer_validate_alloc_free (vlib_main_t * vm,
257  u32 * buffers,
258  uword n_buffers,
259  vlib_buffer_known_state_t expected_state)
260 {
261  u32 *b;
262  uword i, bi, is_free;
263 
264  if (CLIB_DEBUG == 0)
265  return;
266 
267  ASSERT (os_get_cpu_number () == 0);
268 
269  /* smp disaster check */
270  if (vlib_mains)
271  ASSERT (vm == vlib_mains[0]);
272 
273  is_free = expected_state == VLIB_BUFFER_KNOWN_ALLOCATED;
274  b = buffers;
275  for (i = 0; i < n_buffers; i++)
276  {
277  vlib_buffer_known_state_t known;
278 
279  bi = b[0];
280  b += 1;
281  known = vlib_buffer_is_known (vm, bi);
282  if (known != expected_state)
283  {
284  ASSERT (0);
286  (vm, "%s %U buffer 0x%x",
287  is_free ? "freeing" : "allocating",
288  format_vlib_buffer_known_state, known, bi);
289  }
290 
291  vlib_buffer_set_known_state
292  (vm, bi,
293  is_free ? VLIB_BUFFER_KNOWN_FREE : VLIB_BUFFER_KNOWN_ALLOCATED);
294  }
295 }
296 
297 /* Aligned copy routine. */
298 void
299 vlib_aligned_memcpy (void *_dst, void *_src, int n_bytes)
300 {
301  vlib_copy_unit_t *dst = _dst;
302  vlib_copy_unit_t *src = _src;
303 
304  /* Arguments must be naturally aligned. */
305  ASSERT (pointer_to_uword (dst) % sizeof (dst[0]) == 0);
306  ASSERT (pointer_to_uword (src) % sizeof (src[0]) == 0);
307  ASSERT (n_bytes % sizeof (dst[0]) == 0);
308 
309  if (4 * sizeof (dst[0]) == CLIB_CACHE_LINE_BYTES)
310  {
311  CLIB_PREFETCH (dst + 0, 4 * sizeof (dst[0]), WRITE);
312  CLIB_PREFETCH (src + 0, 4 * sizeof (src[0]), READ);
313 
314  while (n_bytes >= 4 * sizeof (dst[0]))
315  {
316  dst += 4;
317  src += 4;
318  n_bytes -= 4 * sizeof (dst[0]);
319  CLIB_PREFETCH (dst, 4 * sizeof (dst[0]), WRITE);
320  CLIB_PREFETCH (src, 4 * sizeof (src[0]), READ);
321  dst[-4] = src[-4];
322  dst[-3] = src[-3];
323  dst[-2] = src[-2];
324  dst[-1] = src[-1];
325  }
326  }
327  else if (8 * sizeof (dst[0]) == CLIB_CACHE_LINE_BYTES)
328  {
329  CLIB_PREFETCH (dst + 0, 8 * sizeof (dst[0]), WRITE);
330  CLIB_PREFETCH (src + 0, 8 * sizeof (src[0]), READ);
331 
332  while (n_bytes >= 8 * sizeof (dst[0]))
333  {
334  dst += 8;
335  src += 8;
336  n_bytes -= 8 * sizeof (dst[0]);
337  CLIB_PREFETCH (dst, 8 * sizeof (dst[0]), WRITE);
338  CLIB_PREFETCH (src, 8 * sizeof (src[0]), READ);
339  dst[-8] = src[-8];
340  dst[-7] = src[-7];
341  dst[-6] = src[-6];
342  dst[-5] = src[-5];
343  dst[-4] = src[-4];
344  dst[-3] = src[-3];
345  dst[-2] = src[-2];
346  dst[-1] = src[-1];
347  }
348  }
349  else
350  /* Cache line size unknown: fall back to slow version. */ ;
351 
352  while (n_bytes > 0)
353  {
354  *dst++ = *src++;
355  n_bytes -= 1 * sizeof (dst[0]);
356  }
357 }
358 
359 #define BUFFERS_PER_COPY (sizeof (vlib_copy_unit_t) / sizeof (u32))
360 
361 /* Make sure we have at least given number of unaligned buffers. */
362 static void
364  vlib_buffer_free_list_t * free_list,
365  uword n_unaligned_buffers)
366 {
367  word la = vec_len (free_list->aligned_buffers);
368  word lu = vec_len (free_list->unaligned_buffers);
369 
370  /* Aligned come in aligned copy-sized chunks. */
371  ASSERT (la % BUFFERS_PER_COPY == 0);
372 
373  ASSERT (la >= n_unaligned_buffers);
374 
375  while (lu < n_unaligned_buffers)
376  {
377  /* Copy 4 buffers from end of aligned vector to unaligned vector. */
378  vec_add (free_list->unaligned_buffers,
379  free_list->aligned_buffers + la - BUFFERS_PER_COPY,
380  BUFFERS_PER_COPY);
381  la -= BUFFERS_PER_COPY;
382  lu += BUFFERS_PER_COPY;
383  }
384  _vec_len (free_list->aligned_buffers) = la;
385 }
386 
387 /* After free aligned buffers may not contain even sized chunks. */
388 static void
390 {
391  uword l, n_trim;
392 
393  /* Add unaligned to aligned before trim. */
394  l = vec_len (f->unaligned_buffers);
395  if (l > 0)
396  {
398  /* align */ sizeof (vlib_copy_unit_t));
399 
400  _vec_len (f->unaligned_buffers) = 0;
401  }
402 
403  /* Remove unaligned buffers from end of aligned vector and save for next trim. */
404  l = vec_len (f->aligned_buffers);
405  n_trim = l % BUFFERS_PER_COPY;
406  if (n_trim)
407  {
408  /* Trim aligned -> unaligned. */
409  vec_add (f->unaligned_buffers, f->aligned_buffers + l - n_trim, n_trim);
410 
411  /* Remove from aligned. */
412  _vec_len (f->aligned_buffers) = l - n_trim;
413  }
414 }
415 
416 static void
419 {
420  uword l;
421  u32 *d;
422 
423  trim_aligned (src);
424  trim_aligned (dst);
425 
426  l = vec_len (src->aligned_buffers);
427  if (l > 0)
428  {
429  vec_add2_aligned (dst->aligned_buffers, d, l,
430  /* align */ sizeof (vlib_copy_unit_t));
431  vlib_aligned_memcpy (d, src->aligned_buffers, l * sizeof (d[0]));
432  vec_free (src->aligned_buffers);
433  }
434 
435  l = vec_len (src->unaligned_buffers);
436  if (l > 0)
437  {
440  }
441 }
442 
445 {
447 
448  size = vlib_buffer_round_size (size);
449  uword *p = hash_get (bm->free_list_by_size, size);
450  return p ? p[0] : ~0;
451 }
452 
453 /* Add buffer free list. */
454 static u32
456  u32 n_data_bytes,
457  u32 is_public, u32 is_default, u8 * name)
458 {
461 
462  if (!is_default && pool_elts (bm->buffer_free_list_pool) == 0)
463  {
464  u32 default_free_free_list_index;
465 
466  default_free_free_list_index = vlib_buffer_create_free_list_helper (vm,
467  /* default buffer size */
469  /* is_public */
470  1,
471  /* is_default */
472  1,
473  (u8
474  *)
475  "default");
476  ASSERT (default_free_free_list_index ==
478 
479  if (n_data_bytes == VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES && is_public)
480  return default_free_free_list_index;
481  }
482 
484 
485  memset (f, 0, sizeof (f[0]));
486  f->index = f - bm->buffer_free_list_pool;
487  f->n_data_bytes = vlib_buffer_round_size (n_data_bytes);
489  f->name = clib_mem_is_heap_object (name) ? name : format (0, "%s", name);
490 
491  /* Setup free buffer template. */
493 
494  if (is_public)
495  {
497  if (!p)
499  }
500 
501  return f->index;
502 }
503 
504 u32
505 vlib_buffer_create_free_list (vlib_main_t * vm, u32 n_data_bytes,
506  char *fmt, ...)
507 {
508  va_list va;
509  u8 *name;
510 
511  va_start (va, fmt);
512  name = va_format (0, fmt, &va);
513  va_end (va);
514 
515  return vlib_buffer_create_free_list_helper (vm, n_data_bytes,
516  /* is_public */ 0,
517  /* is_default */ 0,
518  name);
519 }
520 
521 u32
523  char *fmt, ...)
524 {
525  u32 i = vlib_buffer_get_free_list_with_size (vm, n_data_bytes);
526 
527  if (i == ~0)
528  {
529  va_list va;
530  u8 *name;
531 
532  va_start (va, fmt);
533  name = va_format (0, fmt, &va);
534  va_end (va);
535 
536  i = vlib_buffer_create_free_list_helper (vm, n_data_bytes,
537  /* is_public */ 1,
538  /* is_default */ 0,
539  name);
540  }
541 
542  return i;
543 }
544 
545 static void
547 {
548  u32 i;
549 
550  for (i = 0; i < vec_len (f->buffer_memory_allocated); i++)
552  vec_free (f->name);
556 }
557 
558 /* Add buffer free list. */
559 void
560 vlib_buffer_delete_free_list (vlib_main_t * vm, u32 free_list_index)
561 {
564  u32 merge_index;
565 
566  f = vlib_buffer_get_free_list (vm, free_list_index);
567 
569  f->n_alloc);
570  merge_index = vlib_buffer_get_free_list_with_size (vm, f->n_data_bytes);
571  if (merge_index != ~0 && merge_index != free_list_index)
572  {
574  merge_index), f);
575  }
576 
577  del_free_list (vm, f);
578 
579  /* Poison it. */
580  memset (f, 0xab, sizeof (f[0]));
581 
583 }
584 
585 /* Make sure free list has at least given number of free buffers. */
586 static uword
588  vlib_buffer_free_list_t * fl, uword min_free_buffers)
589 {
590  vlib_buffer_t *buffers, *b;
591  int n, n_bytes, i;
592  u32 *bi;
593  u32 n_remaining, n_alloc, n_this_chunk;
594 
595  trim_aligned (fl);
596 
597  /* Already have enough free buffers on free list? */
598  n = min_free_buffers - vec_len (fl->aligned_buffers);
599  if (n <= 0)
600  return min_free_buffers;
601 
602  /* Always allocate round number of buffers. */
603  n = round_pow2 (n, BUFFERS_PER_COPY);
604 
605  /* Always allocate new buffers in reasonably large sized chunks. */
607 
608  n_remaining = n;
609  n_alloc = 0;
610  while (n_remaining > 0)
611  {
612  n_this_chunk = clib_min (n_remaining, 16);
613 
614  n_bytes = n_this_chunk * (sizeof (b[0]) + fl->n_data_bytes);
615 
616  /* drb: removed power-of-2 ASSERT */
617  buffers = vm->os_physmem_alloc_aligned (&vm->physmem_main,
618  n_bytes,
619  sizeof (vlib_buffer_t));
620  if (!buffers)
621  return n_alloc;
622 
623  /* Record chunk as being allocated so we can free it later. */
624  vec_add1 (fl->buffer_memory_allocated, buffers);
625 
626  fl->n_alloc += n_this_chunk;
627  n_alloc += n_this_chunk;
628  n_remaining -= n_this_chunk;
629 
630  b = buffers;
631  vec_add2_aligned (fl->aligned_buffers, bi, n_this_chunk,
632  sizeof (vlib_copy_unit_t));
633  for (i = 0; i < n_this_chunk; i++)
634  {
635  bi[i] = vlib_get_buffer_index (vm, b);
636 
637  if (CLIB_DEBUG > 0)
638  vlib_buffer_set_known_state (vm, bi[i], VLIB_BUFFER_KNOWN_FREE);
640  }
641 
642  memset (buffers, 0, n_bytes);
643 
644  /* Initialize all new buffers. */
645  b = buffers;
646  for (i = 0; i < n_this_chunk; i++)
647  {
650  }
651 
652  if (fl->buffer_init_function)
653  fl->buffer_init_function (vm, fl, bi, n_this_chunk);
654  }
655  return n_alloc;
656 }
657 
659 copy_alignment (u32 * x)
660 {
661  return (pointer_to_uword (x) / sizeof (x[0])) % BUFFERS_PER_COPY;
662 }
663 
664 static u32
666  vlib_buffer_free_list_t * free_list,
667  u32 * alloc_buffers, u32 n_alloc_buffers)
668 {
669  u32 *dst, *u_src;
670  uword u_len, n_left;
671  uword n_unaligned_start, n_unaligned_end, n_filled;
672 
673  ASSERT (os_get_cpu_number () == 0);
674 
675  n_left = n_alloc_buffers;
676  dst = alloc_buffers;
677  n_unaligned_start = ((BUFFERS_PER_COPY - copy_alignment (dst))
678  & (BUFFERS_PER_COPY - 1));
679 
680  n_filled = fill_free_list (vm, free_list, n_alloc_buffers);
681  if (n_filled == 0)
682  return 0;
683 
684  n_left = n_filled < n_left ? n_filled : n_left;
685  n_alloc_buffers = n_left;
686 
687  if (n_unaligned_start >= n_left)
688  {
689  n_unaligned_start = n_left;
690  n_unaligned_end = 0;
691  }
692  else
693  n_unaligned_end = copy_alignment (dst + n_alloc_buffers);
694 
695  fill_unaligned (vm, free_list, n_unaligned_start + n_unaligned_end);
696 
697  u_len = vec_len (free_list->unaligned_buffers);
698  u_src = free_list->unaligned_buffers + u_len - 1;
699 
700  if (n_unaligned_start)
701  {
702  uword n_copy = n_unaligned_start;
703  if (n_copy > n_left)
704  n_copy = n_left;
705  n_left -= n_copy;
706 
707  while (n_copy > 0)
708  {
709  *dst++ = *u_src--;
710  n_copy--;
711  u_len--;
712  }
713 
714  /* Now dst should be aligned. */
715  if (n_left > 0)
716  ASSERT (pointer_to_uword (dst) % sizeof (vlib_copy_unit_t) == 0);
717  }
718 
719  /* Aligned copy. */
720  {
721  vlib_copy_unit_t *d, *s;
722  uword n_copy;
723 
724  if (vec_len (free_list->aligned_buffers) <
725  ((n_left / BUFFERS_PER_COPY) * BUFFERS_PER_COPY))
726  abort ();
727 
728  n_copy = n_left / BUFFERS_PER_COPY;
729  n_left = n_left % BUFFERS_PER_COPY;
730 
731  /* Remove buffers from aligned free list. */
732  _vec_len (free_list->aligned_buffers) -= n_copy * BUFFERS_PER_COPY;
733 
734  s = (vlib_copy_unit_t *) vec_end (free_list->aligned_buffers);
735  d = (vlib_copy_unit_t *) dst;
736 
737  /* Fast path loop. */
738  while (n_copy >= 4)
739  {
740  d[0] = s[0];
741  d[1] = s[1];
742  d[2] = s[2];
743  d[3] = s[3];
744  n_copy -= 4;
745  s += 4;
746  d += 4;
747  }
748 
749  while (n_copy >= 1)
750  {
751  d[0] = s[0];
752  n_copy -= 1;
753  s += 1;
754  d += 1;
755  }
756 
757  dst = (void *) d;
758  }
759 
760  /* Unaligned copy. */
761  ASSERT (n_unaligned_end == n_left);
762  while (n_left > 0)
763  {
764  *dst++ = *u_src--;
765  n_left--;
766  u_len--;
767  }
768 
769  if (!free_list->unaligned_buffers)
770  ASSERT (u_len == 0);
771  else
772  _vec_len (free_list->unaligned_buffers) = u_len;
773 
774  /* Verify that buffers are known free. */
775  vlib_buffer_validate_alloc_free (vm, alloc_buffers,
776  n_alloc_buffers, VLIB_BUFFER_KNOWN_FREE);
777 
778  return n_alloc_buffers;
779 }
780 
781 /* Allocate a given number of buffers into given array.
782  Returns number actually allocated which will be either zero or
783  number requested. */
784 u32
785 vlib_buffer_alloc (vlib_main_t * vm, u32 * buffers, u32 n_buffers)
786 {
788  ASSERT (os_get_cpu_number () == 0);
789 
790  return alloc_from_free_list
791  (vm,
794  buffers, n_buffers);
795 }
796 
797 u32
799  u32 * buffers,
800  u32 n_buffers, u32 free_list_index)
801 {
804  f = pool_elt_at_index (bm->buffer_free_list_pool, free_list_index);
805  return alloc_from_free_list (vm, f, buffers, n_buffers);
806 }
807 
808 always_inline void
811  u32 buffer_index, u8 do_init)
812 {
813  vlib_buffer_t *b;
814  b = vlib_get_buffer (vm, buffer_index);
815  if (PREDICT_TRUE (do_init))
817  vec_add1_aligned (f->aligned_buffers, buffer_index,
818  sizeof (vlib_copy_unit_t));
819 }
820 
823 {
825  u32 i;
826 
827  *index = i = b->free_list_index;
829 }
830 
831 void *
833 {
835  void *rv = bm->buffer_free_callback;
836 
837  bm->buffer_free_callback = fp;
838  return rv;
839 }
840 
841 void vnet_buffer_free_dpdk_mb (vlib_buffer_t * b) __attribute__ ((weak));
842 void
843 vnet_buffer_free_dpdk_mb (vlib_buffer_t * b)
844 {
845 }
846 
849  u32 * buffers, u32 n_buffers, u32 follow_buffer_next)
850 {
853  static u32 *next_to_free[2]; /* smp bad */
854  u32 i_next_to_free, *b, *n, *f, fi;
855  uword n_left;
856  int i;
857  static vlib_buffer_free_list_t **announce_list;
858  vlib_buffer_free_list_t *fl0 = 0, *fl1 = 0;
859  u32 bi0 = (u32) ~ 0, bi1 = (u32) ~ 0, fi0, fi1 = (u32) ~ 0;
860  u8 free0, free1 = 0, free_next0, free_next1;
861  u32 (*cb) (vlib_main_t * vm, u32 * buffers, u32 n_buffers,
862  u32 follow_buffer_next);
863 
864  ASSERT (os_get_cpu_number () == 0);
865 
866  cb = bm->buffer_free_callback;
867 
868  if (PREDICT_FALSE (cb != 0))
869  n_buffers = (*cb) (vm, buffers, n_buffers, follow_buffer_next);
870 
871  if (!n_buffers)
872  return;
873 
874  /* Use first buffer to get default free list. */
875  {
876  u32 bi0 = buffers[0];
877  vlib_buffer_t *b0;
878 
879  b0 = vlib_get_buffer (vm, bi0);
880  fl = buffer_get_free_list (vm, b0, &fi);
882  vec_add1 (announce_list, fl);
883  }
884 
885  vec_validate (next_to_free[0], n_buffers - 1);
886  vec_validate (next_to_free[1], n_buffers - 1);
887 
888  i_next_to_free = 0;
889  n_left = n_buffers;
890  b = buffers;
891 
892 again:
893  /* Verify that buffers are known allocated. */
894  vlib_buffer_validate_alloc_free (vm, b,
895  n_left, VLIB_BUFFER_KNOWN_ALLOCATED);
896 
897  vec_add2_aligned (fl->aligned_buffers, f, n_left,
898  /* align */ sizeof (vlib_copy_unit_t));
899 
900  n = next_to_free[i_next_to_free];
901  while (n_left >= 4)
902  {
903  vlib_buffer_t *b0, *b1, *binit0, *binit1, dummy_buffers[2];
904 
905  bi0 = b[0];
906  bi1 = b[1];
907 
908  f[0] = bi0;
909  f[1] = bi1;
910  f += 2;
911  b += 2;
912  n_left -= 2;
913 
914  /* Prefetch buffers for next iteration. */
915  vlib_prefetch_buffer_with_index (vm, b[0], WRITE);
916  vlib_prefetch_buffer_with_index (vm, b[1], WRITE);
917 
918  b0 = vlib_get_buffer (vm, bi0);
919  b1 = vlib_get_buffer (vm, bi1);
920 
921  free0 = (b0->flags & VLIB_BUFFER_RECYCLE) == 0;
922  free1 = (b1->flags & VLIB_BUFFER_RECYCLE) == 0;
923 
924  /* Must be before init which will over-write buffer flags. */
925  if (follow_buffer_next)
926  {
927  n[0] = b0->next_buffer;
928  free_next0 = free0 && (b0->flags & VLIB_BUFFER_NEXT_PRESENT) != 0;
929  n += free_next0;
930 
931  n[0] = b1->next_buffer;
932  free_next1 = free1 && (b1->flags & VLIB_BUFFER_NEXT_PRESENT) != 0;
933  n += free_next1;
934  }
935  else
936  free_next0 = free_next1 = 0;
937 
938  /* Must be before init which will over-write buffer free list. */
939  fi0 = b0->free_list_index;
940  fi1 = b1->free_list_index;
941 
942  if (PREDICT_FALSE (fi0 != fi || fi1 != fi))
943  goto slow_path_x2;
944 
945  binit0 = free0 ? b0 : &dummy_buffers[0];
946  binit1 = free1 ? b1 : &dummy_buffers[1];
947 
948  vlib_buffer_init_two_for_free_list (binit0, binit1, fl);
949  continue;
950 
951  slow_path_x2:
952  /* Backup speculation. */
953  f -= 2;
954  n -= free_next0 + free_next1;
955 
956  _vec_len (fl->aligned_buffers) = f - fl->aligned_buffers;
957 
958  fl0 = pool_elt_at_index (bm->buffer_free_list_pool, fi0);
959  fl1 = pool_elt_at_index (bm->buffer_free_list_pool, fi1);
960 
961  add_buffer_to_free_list (vm, fl0, bi0, free0);
963  {
964  int i;
965  for (i = 0; i < vec_len (announce_list); i++)
966  if (fl0 == announce_list[i])
967  goto no_fl0;
968  vec_add1 (announce_list, fl0);
969  }
970  no_fl0:
971  if (PREDICT_FALSE (fl1->buffers_added_to_freelist_function != 0))
972  {
973  int i;
974  for (i = 0; i < vec_len (announce_list); i++)
975  if (fl1 == announce_list[i])
976  goto no_fl1;
977  vec_add1 (announce_list, fl1);
978  }
979 
980  no_fl1:
981  add_buffer_to_free_list (vm, fl1, bi1, free1);
982 
983  /* Possibly change current free list. */
984  if (fi0 != fi && fi1 != fi)
985  {
986  fi = fi1;
988  }
989 
990  vec_add2_aligned (fl->aligned_buffers, f, n_left,
991  /* align */ sizeof (vlib_copy_unit_t));
992  }
993 
994  while (n_left >= 1)
995  {
996  vlib_buffer_t *b0, *binit0, dummy_buffers[1];
997 
998  bi0 = b[0];
999  f[0] = bi0;
1000  f += 1;
1001  b += 1;
1002  n_left -= 1;
1003 
1004  b0 = vlib_get_buffer (vm, bi0);
1005 
1006  free0 = (b0->flags & VLIB_BUFFER_RECYCLE) == 0;
1007 
1008  /* Must be before init which will over-write buffer flags. */
1009  if (follow_buffer_next)
1010  {
1011  n[0] = b0->next_buffer;
1012  free_next0 = free0 && (b0->flags & VLIB_BUFFER_NEXT_PRESENT) != 0;
1013  n += free_next0;
1014  }
1015  else
1016  free_next0 = 0;
1017 
1018  /* Must be before init which will over-write buffer free list. */
1019  fi0 = b0->free_list_index;
1020 
1021  if (PREDICT_FALSE (fi0 != fi))
1022  goto slow_path_x1;
1023 
1024  binit0 = free0 ? b0 : &dummy_buffers[0];
1025 
1026  vlib_buffer_init_for_free_list (binit0, fl);
1027  continue;
1028 
1029  slow_path_x1:
1030  /* Backup speculation. */
1031  f -= 1;
1032  n -= free_next0;
1033 
1034  _vec_len (fl->aligned_buffers) = f - fl->aligned_buffers;
1035 
1036  fl0 = pool_elt_at_index (bm->buffer_free_list_pool, fi0);
1037 
1038  add_buffer_to_free_list (vm, fl0, bi0, free0);
1040  {
1041  int i;
1042  for (i = 0; i < vec_len (announce_list); i++)
1043  if (fl0 == announce_list[i])
1044  goto no_fl00;
1045  vec_add1 (announce_list, fl0);
1046  }
1047 
1048  no_fl00:
1049  fi = fi0;
1051 
1052  vec_add2_aligned (fl->aligned_buffers, f, n_left,
1053  /* align */ sizeof (vlib_copy_unit_t));
1054  }
1055 
1056  if (follow_buffer_next && ((n_left = n - next_to_free[i_next_to_free]) > 0))
1057  {
1058  b = next_to_free[i_next_to_free];
1059  i_next_to_free ^= 1;
1060  goto again;
1061  }
1062 
1063  _vec_len (fl->aligned_buffers) = f - fl->aligned_buffers;
1064 
1065  if (vec_len (announce_list))
1066  {
1068  for (i = 0; i < vec_len (announce_list); i++)
1069  {
1070  fl = announce_list[i];
1072  }
1073  _vec_len (announce_list) = 0;
1074  }
1075 }
1076 
1077 void
1078 vlib_buffer_free (vlib_main_t * vm, u32 * buffers, u32 n_buffers)
1079 {
1080  vlib_buffer_free_inline (vm, buffers, n_buffers, /* follow_buffer_next */
1081  1);
1082 }
1083 
1084 void
1085 vlib_buffer_free_no_next (vlib_main_t * vm, u32 * buffers, u32 n_buffers)
1086 {
1087  vlib_buffer_free_inline (vm, buffers, n_buffers, /* follow_buffer_next */
1088  0);
1089 }
1090 
1091 /* Copy template packet data into buffers as they are allocated. */
1092 static void
1095  u32 * buffers, u32 n_buffers)
1096 {
1100  uword i;
1101 
1102  for (i = 0; i < n_buffers; i++)
1103  {
1104  vlib_buffer_t *b = vlib_get_buffer (vm, buffers[i]);
1107  b->current_length);
1108  }
1109 }
1110 
1111 void
1114  void *packet_data,
1115  uword n_packet_data_bytes,
1116  uword min_n_buffers_each_physmem_alloc,
1117  char *fmt, ...)
1118 {
1120  va_list va;
1121  u8 *name;
1122 
1123  va_start (va, fmt);
1124  name = va_format (0, fmt, &va);
1125  va_end (va);
1126 
1127  memset (t, 0, sizeof (t[0]));
1128 
1129  vec_add (t->packet_data, packet_data, n_packet_data_bytes);
1130  t->min_n_buffers_each_physmem_alloc = min_n_buffers_each_physmem_alloc;
1131 
1133  (vm, n_packet_data_bytes,
1134  /* is_public */ 1,
1135  /* is_default */ 0,
1136  name);
1137 
1138  ASSERT (t->free_list_index != 0);
1141 
1144 
1146  fl->buffer_init_template.current_length = n_packet_data_bytes;
1147  fl->buffer_init_template.flags = 0;
1148 }
1149 
1150 void *
1152  vlib_packet_template_t * t, u32 * bi_result)
1153 {
1154  u32 bi;
1155  vlib_buffer_t *b;
1156 
1157  if (vlib_buffer_alloc (vm, &bi, 1) != 1)
1158  return 0;
1159 
1160  *bi_result = bi;
1161 
1162  b = vlib_get_buffer (vm, bi);
1164  t->packet_data, vec_len (t->packet_data));
1166 
1167  return b->data;
1168 }
1169 
1170 void
1173 {
1175  word l = vec_len (t->packet_data);
1176  word n_alloc;
1177 
1178  ASSERT (l > 0);
1179  ASSERT (vec_len (t->free_buffers) == 0);
1180 
1181  vec_validate (t->free_buffers, n - 1);
1183  n, t->free_list_index);
1184  _vec_len (t->free_buffers) = n_alloc;
1185 }
1186 
1187 /* Append given data to end of buffer, possibly allocating new buffers. */
1188 u32
1190  u32 free_list_index,
1191  u32 buffer_index, void *data, u32 n_data_bytes)
1192 {
1193  u32 n_buffer_bytes, n_left, n_left_this_buffer, bi;
1194  vlib_buffer_t *b;
1195  void *d;
1196 
1197  bi = buffer_index;
1198  if (bi == 0
1199  && 1 != vlib_buffer_alloc_from_free_list (vm, &bi, 1, free_list_index))
1200  goto out_of_buffers;
1201 
1202  d = data;
1203  n_left = n_data_bytes;
1204  n_buffer_bytes = vlib_buffer_free_list_buffer_size (vm, free_list_index);
1205 
1206  b = vlib_get_buffer (vm, bi);
1208 
1209  /* Get to the end of the chain before we try to append data... */
1210  while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
1211  b = vlib_get_buffer (vm, b->next_buffer);
1212 
1213  while (1)
1214  {
1215  u32 n;
1216 
1217  ASSERT (n_buffer_bytes >= b->current_length);
1218  n_left_this_buffer =
1219  n_buffer_bytes - (b->current_data + b->current_length);
1220  n = clib_min (n_left_this_buffer, n_left);
1222  b->current_length += n;
1223  n_left -= n;
1224  if (n_left == 0)
1225  break;
1226 
1227  d += n;
1228  if (1 !=
1230  free_list_index))
1231  goto out_of_buffers;
1232 
1234 
1235  b = vlib_get_buffer (vm, b->next_buffer);
1236  }
1237 
1238  return bi;
1239 
1240 out_of_buffers:
1241  clib_error ("out of buffers");
1242  return bi;
1243 }
1244 
1245 u16
1247  u32 free_list_index,
1248  vlib_buffer_t * first,
1249  vlib_buffer_t ** last,
1250  void *data, u16 data_len)
1251 {
1252  vlib_buffer_t *l = *last;
1253  u32 n_buffer_bytes =
1254  vlib_buffer_free_list_buffer_size (vm, free_list_index);
1255  u16 copied = 0;
1256  ASSERT (n_buffer_bytes >= l->current_length + l->current_data);
1257  while (data_len)
1258  {
1259  u16 max = n_buffer_bytes - l->current_length - l->current_data;
1260  if (max == 0)
1261  {
1262  if (1 !=
1264  free_list_index))
1265  return copied;
1266  *last = l = vlib_buffer_chain_buffer (vm, first, l, l->next_buffer);
1267  max = n_buffer_bytes - l->current_length - l->current_data;
1268  }
1269 
1270  u16 len = (data_len > max) ? max : data_len;
1272  data + copied, len);
1273  vlib_buffer_chain_increase_length (first, l, len);
1274  data_len -= len;
1275  copied += len;
1276  }
1277  return copied;
1278 }
1279 
1280 /*
1281  * Fills in the required rte_mbuf fields for chained buffers given a VLIB chain.
1282  */
1283 void
1285 {
1286  return;
1287 }
1288 
1289 static void
1291 {
1292  vlib_main_t *vm;
1294  uword n, n_bytes_to_write;
1296 
1297  n_bytes_to_write = s->current_buffer_index;
1298  sm =
1301  vm = sm->vlib_main;
1302 
1303  ASSERT (sm->tx.max_n_data_bytes_per_chain > 0);
1305  || sm->tx.n_total_data_bytes + n_bytes_to_write >
1306  sm->tx.max_n_data_bytes_per_chain)
1307  {
1309 
1310  last = vlib_get_buffer (vm, sm->last_buffer);
1311  last->current_length = n_bytes_to_write;
1312 
1313  vlib_set_next_frame_buffer (vm, &p->node_runtime, sm->tx.next_index,
1314  sm->first_buffer);
1315 
1316  sm->first_buffer = sm->last_buffer = ~0;
1317  sm->tx.n_total_data_bytes = 0;
1318  }
1319 
1320  else if (n_bytes_to_write == 0 && s->n_buffer_bytes == 0)
1321  {
1322  ASSERT (sm->first_buffer == ~0);
1323  ASSERT (sm->last_buffer == ~0);
1324  n =
1326  sm->tx.free_list_index);
1327  if (n != 1)
1328  serialize_error (m,
1330  ("vlib_buffer_alloc_from_free_list fails"));
1331  sm->last_buffer = sm->first_buffer;
1332  s->n_buffer_bytes =
1333  vlib_buffer_free_list_buffer_size (vm, sm->tx.free_list_index);
1334  }
1335 
1336  if (n_bytes_to_write > 0)
1337  {
1338  vlib_buffer_t *prev = vlib_get_buffer (vm, sm->last_buffer);
1339  n =
1341  sm->tx.free_list_index);
1342  if (n != 1)
1343  serialize_error (m,
1345  ("vlib_buffer_alloc_from_free_list fails"));
1346  sm->tx.n_total_data_bytes += n_bytes_to_write;
1347  prev->current_length = n_bytes_to_write;
1348  prev->next_buffer = sm->last_buffer;
1350  }
1351 
1352  if (sm->last_buffer != ~0)
1353  {
1354  last = vlib_get_buffer (vm, sm->last_buffer);
1355  s->buffer = vlib_buffer_get_current (last);
1356  s->current_buffer_index = 0;
1358  }
1359 }
1360 
1361 static void
1363 {
1364  vlib_main_t *vm;
1367 
1368  sm =
1371  vm = sm->vlib_main;
1372 
1374  return;
1375 
1376  if (sm->last_buffer != ~0)
1377  {
1378  last = vlib_get_buffer (vm, sm->last_buffer);
1379 
1380  if (last->flags & VLIB_BUFFER_NEXT_PRESENT)
1381  sm->last_buffer = last->next_buffer;
1382  else
1383  {
1384  vlib_buffer_free (vm, &sm->first_buffer, /* count */ 1);
1385  sm->first_buffer = sm->last_buffer = ~0;
1386  }
1387  }
1388 
1389  if (sm->last_buffer == ~0)
1390  {
1391  while (clib_fifo_elts (sm->rx.buffer_fifo) == 0)
1392  {
1393  sm->rx.ready_one_time_event =
1395  ~0);
1396  vlib_process_wait_for_one_time_event (vm, /* no event data */ 0,
1397  sm->rx.ready_one_time_event);
1398  }
1399 
1400  clib_fifo_sub1 (sm->rx.buffer_fifo, sm->first_buffer);
1401  sm->last_buffer = sm->first_buffer;
1402  }
1403 
1404  ASSERT (sm->last_buffer != ~0);
1405 
1406  last = vlib_get_buffer (vm, sm->last_buffer);
1407  s->current_buffer_index = 0;
1408  s->buffer = vlib_buffer_get_current (last);
1409  s->n_buffer_bytes = last->current_length;
1410 }
1411 
1412 static void
1414  vlib_main_t * vm,
1415  vlib_serialize_buffer_main_t * sm, uword is_read)
1416 {
1417  /* Initialize serialize main but save overflow buffer for re-use between calls. */
1418  {
1419  u8 *save = m->stream.overflow_buffer;
1420  memset (m, 0, sizeof (m[0]));
1421  m->stream.overflow_buffer = save;
1422  if (save)
1423  _vec_len (save) = 0;
1424  }
1425 
1426  sm->first_buffer = sm->last_buffer = ~0;
1427  if (is_read)
1428  clib_fifo_reset (sm->rx.buffer_fifo);
1429  else
1430  sm->tx.n_total_data_bytes = 0;
1431  sm->vlib_main = vm;
1434 }
1435 
1436 void
1439 {
1440  serialize_open_vlib_helper (m, vm, sm, /* is_read */ 0);
1441 }
1442 
1443 void
1446 {
1447  serialize_open_vlib_helper (m, vm, sm, /* is_read */ 1);
1448 }
1449 
1450 u32
1452 {
1457  serialize_stream_t *s = &m->stream;
1458 
1459  last = vlib_get_buffer (sm->vlib_main, sm->last_buffer);
1461 
1462  if (vec_len (s->overflow_buffer) > 0)
1463  {
1464  sm->last_buffer
1465  = vlib_buffer_add_data (sm->vlib_main, sm->tx.free_list_index,
1466  sm->last_buffer == ~0 ? 0 : sm->last_buffer,
1467  s->overflow_buffer,
1468  vec_len (s->overflow_buffer));
1469  _vec_len (s->overflow_buffer) = 0;
1470  }
1471 
1472  return sm->first_buffer;
1473 }
1474 
1475 void
1477 {
1481  if (sm->first_buffer != ~0)
1483  clib_fifo_reset (sm->rx.buffer_fifo);
1484  if (m->stream.overflow_buffer)
1485  _vec_len (m->stream.overflow_buffer) = 0;
1486 }
1487 
1488 static u8 *
1489 format_vlib_buffer_free_list (u8 * s, va_list * va)
1490 {
1491  vlib_buffer_free_list_t *f = va_arg (*va, vlib_buffer_free_list_t *);
1492  uword bytes_alloc, bytes_free, n_free, size;
1493 
1494  if (!f)
1495  return format (s, "%=30s%=12s%=12s%=12s%=12s%=12s%=12s",
1496  "Name", "Index", "Size", "Alloc", "Free", "#Alloc",
1497  "#Free");
1498 
1499  size = sizeof (vlib_buffer_t) + f->n_data_bytes;
1500  n_free = vec_len (f->aligned_buffers) + vec_len (f->unaligned_buffers);
1501  bytes_alloc = size * f->n_alloc;
1502  bytes_free = size * n_free;
1503 
1504  s = format (s, "%30s%12d%12d%=12U%=12U%=12d%=12d",
1505  f->name, f->index, f->n_data_bytes,
1506  format_memory_size, bytes_alloc,
1507  format_memory_size, bytes_free, f->n_alloc, n_free);
1508 
1509  return s;
1510 }
1511 
1512 static clib_error_t *
1514  unformat_input_t * input, vlib_cli_command_t * cmd)
1515 {
1516  vlib_buffer_main_t *bm = vm->buffer_main;
1518 
1520  /* *INDENT-OFF* */
1522  vlib_cli_output (vm, "%U", format_vlib_buffer_free_list, f);
1523  }));
1524 /* *INDENT-ON* */
1525 
1526  return 0;
1527 }
1528 
1529 /* *INDENT-OFF* */
1530 VLIB_CLI_COMMAND (show_buffers_command, static) = {
1531  .path = "show buffers",
1532  .short_help = "Show packet buffer allocation",
1533  .function = show_buffers,
1534 };
1535 /* *INDENT-ON* */
1536 
1537 /** @endcond */
1538 /*
1539  * fd.io coding-style-patch-verification: ON
1540  *
1541  * Local Variables:
1542  * eval: (c-set-style "gnu")
1543  * End:
1544  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
#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
u32 vlib_buffer_get_or_create_free_list(vlib_main_t *vm, u32 n_data_bytes, char *fmt,...)
Definition: dpdk_buffer.c:383
uword vlib_buffer_length_in_chain_slow_path(vlib_main_t *vm, vlib_buffer_t *b_first)
Definition: dpdk_buffer.c:82
vlib_node_runtime_t node_runtime
Definition: node.h:494
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
format_function_t format_vlib_buffer_contents
Definition: buffer_funcs.h:525
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
format_function_t format_vlib_buffer
Definition: buffer_funcs.h:525
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
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
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
#define clib_error(format, args...)
Definition: error.h:62
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
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
u32 serialize_close_vlib_buffer(serialize_main_t *m)
Definition: dpdk_buffer.c:1283
void ** buffer_memory_allocated
Definition: buffer.h:273
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
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
void * vlib_set_buffer_free_callback(struct vlib_main_t *vm, void *fp)
Definition: dpdk_buffer.c:689
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
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
#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
#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_prefetch_buffer_with_index(vm, bi, type)
Prefetch buffer metadata by buffer index The first 64 bytes of buffer contains most header informatio...
Definition: buffer_funcs.h:182
void unserialize_close_vlib_buffer(serialize_main_t *m)
Definition: dpdk_buffer.c:1308
#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
static void vlib_buffer_init_two_for_free_list(vlib_buffer_t *_dst0, vlib_buffer_t *_dst1, vlib_buffer_free_list_t *fl)
Definition: buffer_funcs.h:641
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
void vlib_aligned_memcpy(void *_dst, void *_src, int n_bytes)
Definition: dpdk_buffer.c:161
u8 * format_hex_bytes(u8 *s, va_list *va)
Definition: std-formats.c:84
#define vec_end(v)
End (last data address) of vector.
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_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 void vlib_serialize_rx(serialize_main_header_t *m, serialize_stream_t *s)
Definition: dpdk_buffer.c:1194
#define clib_fifo_sub1(f, e)
Definition: fifo.h:224
#define VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES
Definition: buffer.h:304
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:82
format_function_t format_vlib_buffer_and_data
Definition: buffer_funcs.h:525
static clib_error_t * show_buffers(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: dpdk_buffer.c:1347
uword os_get_cpu_number(void)
Definition: unix-misc.c:224
#define hash_free(h)
Definition: hash.h:286
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
void serialize_open_vlib_buffer(serialize_main_t *m, struct vlib_main_t *vm, vlib_serialize_buffer_main_t *sm)
Definition: dpdk_buffer.c:1269
#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
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
#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
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
void *(* os_physmem_alloc_aligned)(vlib_physmem_main_t *pm, uword n_bytes, uword alignment)
Definition: main.h:110
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
void vlib_buffer_chain_validate(vlib_main_t *vm, vlib_buffer_t *first)
Definition: dpdk_buffer.c:946
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
#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
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
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:211
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 hash_set1(h, key)
Definition: hash.h:257
#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
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
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
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
u32 size
Definition: vhost-user.h:77
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:114
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
u64 vlib_copy_unit_t
Definition: buffer.h:62
void unserialize_open_vlib_buffer(serialize_main_t *m, struct vlib_main_t *vm, vlib_serialize_buffer_main_t *sm)
Definition: dpdk_buffer.c:1276
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
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
u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: dpdk_buffer.c:643
void(* os_physmem_free)(void *x)
Definition: main.h:112
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:93
#define clib_max(x, y)
Definition: clib.h:319
void vlib_buffer_delete_free_list(vlib_main_t *vm, u32 free_list_index)
Definition: dpdk_buffer.c:434
u64 uword
Definition: types.h:112
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
Definition: buffer.h:109
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
static vlib_buffer_t * vlib_buffer_next_contiguous(vlib_buffer_t *b, u32 buffer_bytes)
Definition: buffer.h:166
#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
vlib_buffer_free_list_t * buffer_free_list_pool
Definition: buffer.h:302
void * vlib_packet_template_get_packet(vlib_main_t *vm, vlib_packet_template_t *t, u32 *bi_result)
Definition: dpdk_buffer.c:824
u8 data[0]
Packet data.
Definition: buffer.h:151
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
void vlib_packet_template_get_packet_helper(vlib_main_t *vm, vlib_packet_template_t *t)
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
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_CACHE_LINE_BYTES
Definition: cache.h:67
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
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
u32 vlib_buffer_create_free_list(vlib_main_t *vm, u32 n_data_bytes, char *fmt,...)
Definition: dpdk_buffer.c:366
#define vlib_panic_with_msg(vm, args...)
Definition: main.h:233
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
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