FD.io VPP  v17.10-9-gd594711
Vector Packet Processing
buffer_funcs.h
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_funcs.h: VLIB buffer related functions/inlines
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 #ifndef included_vlib_buffer_funcs_h
41 #define included_vlib_buffer_funcs_h
42 
43 #include <vppinfra/hash.h>
44 
45 /** \file
46  vlib buffer access methods.
47 */
48 
49 
50 /** \brief Translate buffer index into buffer pointer
51 
52  @param vm - (vlib_main_t *) vlib main data structure pointer
53  @param buffer_index - (u32) buffer index
54  @return - (vlib_buffer_t *) buffer pointer
55 */
57 vlib_get_buffer (vlib_main_t * vm, u32 buffer_index)
58 {
60  uword offset = ((uword) buffer_index) << CLIB_LOG2_CACHE_LINE_BYTES;
61  ASSERT (offset < bm->buffer_mem_size);
62 
63  return uword_to_pointer (bm->buffer_mem_start + offset, void *);
64 }
65 
66 /** \brief Translate buffer pointer into buffer index
67 
68  @param vm - (vlib_main_t *) vlib main data structure pointer
69  @param p - (void *) buffer pointer
70  @return - (u32) buffer index
71 */
72 
75 {
79  ASSERT (offset < bm->buffer_mem_size);
80  ASSERT ((offset % (1 << CLIB_LOG2_CACHE_LINE_BYTES)) == 0);
81  return offset >> CLIB_LOG2_CACHE_LINE_BYTES;
82 }
83 
84 /** \brief Get next buffer in buffer linklist, or zero for end of list.
85 
86  @param vm - (vlib_main_t *) vlib main data structure pointer
87  @param b - (void *) buffer pointer
88  @return - (vlib_buffer_t *) next buffer, or NULL
89 */
92 {
93  return (b->flags & VLIB_BUFFER_NEXT_PRESENT
94  ? vlib_get_buffer (vm, b->next_buffer) : 0);
95 }
96 
98  vlib_buffer_t * b_first);
99 
100 /** \brief Get length in bytes of the buffer chain
101 
102  @param vm - (vlib_main_t *) vlib main data structure pointer
103  @param b - (void *) buffer pointer
104  @return - (uword) length of buffer chain
105 */
108 {
109  uword len = b->current_length;
110 
111  if (PREDICT_TRUE ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0))
112  return len;
113 
116 
118 }
119 
120 /** \brief Get length in bytes of the buffer index buffer chain
121 
122  @param vm - (vlib_main_t *) vlib main data structure pointer
123  @param bi - (u32) buffer index
124  @return - (uword) length of buffer chain
125 */
128 {
129  vlib_buffer_t *b = vlib_get_buffer (vm, bi);
130  return vlib_buffer_length_in_chain (vm, b);
131 }
132 
133 /** \brief Copy buffer contents to memory
134 
135  @param vm - (vlib_main_t *) vlib main data structure pointer
136  @param buffer_index - (u32) buffer index
137  @param contents - (u8 *) memory, <strong>must be large enough</strong>
138  @return - (uword) length of buffer chain
139 */
141 vlib_buffer_contents (vlib_main_t * vm, u32 buffer_index, u8 * contents)
142 {
143  uword content_len = 0;
144  uword l;
145  vlib_buffer_t *b;
146 
147  while (1)
148  {
149  b = vlib_get_buffer (vm, buffer_index);
150  l = b->current_length;
151  clib_memcpy (contents + content_len, b->data + b->current_data, l);
152  content_len += l;
153  if (!(b->flags & VLIB_BUFFER_NEXT_PRESENT))
154  break;
155  buffer_index = b->next_buffer;
156  }
157 
158  return content_len;
159 }
160 
161 /* Return physical address of buffer->data start. */
164 {
166  (((uword) buffer_index) <<
169  data));
170 }
171 
172 /** \brief Prefetch buffer metadata by buffer index
173  The first 64 bytes of buffer contains most header information
174 
175  @param vm - (vlib_main_t *) vlib main data structure pointer
176  @param bi - (u32) buffer index
177  @param type - LOAD, STORE. In most cases, STORE is the right answer
178 */
179 /* Prefetch buffer header given index. */
180 #define vlib_prefetch_buffer_with_index(vm,bi,type) \
181  do { \
182  vlib_buffer_t * _b = vlib_get_buffer (vm, bi); \
183  vlib_prefetch_buffer_header (_b, type); \
184  } while (0)
185 
186 #if 0
187 /* Iterate over known allocated vlib bufs. You probably do not want
188  * to do this!
189  @param vm the vlib_main_t
190  @param bi found allocated buffer index
191  @param body operation to perform on buffer index
192  function executes body for each allocated buffer index
193  */
194 #define vlib_buffer_foreach_allocated(vm,bi,body) \
195 do { \
196  vlib_main_t * _vmain = (vm); \
197  vlib_buffer_main_t * _bmain = &_vmain->buffer_main; \
198  hash_pair_t * _vbpair; \
199  hash_foreach_pair(_vbpair, _bmain->buffer_known_hash, ({ \
200  if (VLIB_BUFFER_KNOWN_ALLOCATED == _vbpair->value[0]) { \
201  (bi) = _vbpair->key; \
202  body; \
203  } \
204  })); \
205 } while (0)
206 #endif
207 
208 typedef enum
209 {
210  /* Index is unknown. */
212 
213  /* Index is known and free/allocated. */
217 
220 {
222 
224  uword *p = hash_get (bm->buffer_known_hash, buffer_index);
226  return p ? p[0] : VLIB_BUFFER_UNKNOWN;
227 }
228 
229 always_inline void
231  u32 buffer_index,
233 {
236  hash_set (bm->buffer_known_hash, buffer_index, state);
238 }
239 
240 /* Validates sanity of a single buffer.
241  Returns format'ed vector with error message if any. */
242 u8 *vlib_validate_buffer (vlib_main_t * vm, u32 buffer_index,
243  uword follow_chain);
244 
245 /** \brief Allocate buffers into supplied array
246 
247  @param vm - (vlib_main_t *) vlib main data structure pointer
248  @param buffers - (u32 * ) buffer index array
249  @param n_buffers - (u32) number of buffers requested
250  @return - (u32) number of buffers actually allocated, may be
251  less than the number requested or zero
252 */
254 vlib_buffer_alloc (vlib_main_t * vm, u32 * buffers, u32 n_buffers)
255 {
257 
259 
260  return bm->cb.vlib_buffer_alloc_cb (vm, buffers, n_buffers);
261 }
262 
265 {
266  return round_pow2 (size, sizeof (vlib_buffer_t));
267 }
268 
271 {
273 }
274 
275 always_inline void
277 {
278  /* if there is an need for more free lists we should consider
279  storig data in the 2nd cacheline */
282 
285 }
286 
287 /** \brief Allocate buffers from specific freelist into supplied array
288 
289  @param vm - (vlib_main_t *) vlib main data structure pointer
290  @param buffers - (u32 * ) buffer index array
291  @param n_buffers - (u32) number of buffers requested
292  @return - (u32) number of buffers actually allocated, may be
293  less than the number requested or zero
294 */
297  u32 * buffers,
298  u32 n_buffers, u32 free_list_index)
299 {
301 
303 
304  return bm->cb.vlib_buffer_alloc_from_free_list_cb (vm, buffers, n_buffers,
305  free_list_index);
306 }
307 
308 /** \brief Free buffers
309  Frees the entire buffer chain for each buffer
310 
311  @param vm - (vlib_main_t *) vlib main data structure pointer
312  @param buffers - (u32 * ) buffer index array
313  @param n_buffers - (u32) number of buffers to free
314 
315 */
316 always_inline void
318  /* pointer to first buffer */
319  u32 * buffers,
320  /* number of buffers to free */
321  u32 n_buffers)
322 {
324 
326 
327  return bm->cb.vlib_buffer_free_cb (vm, buffers, n_buffers);
328 }
329 
330 /** \brief Free buffers, does not free the buffer chain for each buffer
331 
332  @param vm - (vlib_main_t *) vlib main data structure pointer
333  @param buffers - (u32 * ) buffer index array
334  @param n_buffers - (u32) number of buffers to free
335 
336 */
337 always_inline void
339  /* pointer to first buffer */
340  u32 * buffers,
341  /* number of buffers to free */
342  u32 n_buffers)
343 {
345 
347 
348  return bm->cb.vlib_buffer_free_no_next_cb (vm, buffers, n_buffers);
349 }
350 
351 /** \brief Free one buffer
352  Shorthand to free a single buffer chain.
353 
354  @param vm - (vlib_main_t *) vlib main data structure pointer
355  @param buffer_index - (u32) buffer index to free
356 */
357 always_inline void
359 {
360  vlib_buffer_free (vm, &buffer_index, /* n_buffers */ 1);
361 }
362 
363 /* Add/delete buffer free lists. */
364 u32 vlib_buffer_create_free_list (vlib_main_t * vm, u32 n_data_bytes,
365  char *fmt, ...);
366 always_inline void
368 {
370 
372 
373  bm->cb.vlib_buffer_delete_free_list_cb (vm, free_list_index);
374 }
375 
376 /* Find already existing public free list with given size or create one. */
378  char *fmt, ...);
379 
380 /* Merge two free lists */
383 
384 /* Make sure we have at least given number of unaligned buffers. */
387  free_list,
388  uword n_unaligned_buffers);
389 
392 {
394 
395  size = vlib_buffer_round_size (size);
396  uword *p = hash_get (bm->free_list_by_size, size);
397  return p ? p[0] : ~0;
398 }
399 
402  u32 * index)
403 {
405  u32 i;
406 
407  *index = i = vlib_buffer_get_free_list_index (b);
409 }
410 
413 {
416 
417  f = pool_elt_at_index (bm->buffer_free_list_pool, free_list_index);
418 
419  /* Sanity: indices must match. */
420  ASSERT (f->index == free_list_index);
421 
422  return f;
423 }
424 
427 {
429  vlib_buffer_get_free_list (vm, free_list_index);
430  return f->n_data_bytes;
431 }
432 
433 void vlib_aligned_memcpy (void *_dst, void *_src, int n_bytes);
434 
435 /* Reasonably fast buffer copy routine. */
436 always_inline void
437 vlib_copy_buffers (u32 * dst, u32 * src, u32 n)
438 {
439  while (n >= 4)
440  {
441  dst[0] = src[0];
442  dst[1] = src[1];
443  dst[2] = src[2];
444  dst[3] = src[3];
445  dst += 4;
446  src += 4;
447  n -= 4;
448  }
449  while (n > 0)
450  {
451  dst[0] = src[0];
452  dst += 1;
453  src += 1;
454  n -= 1;
455  }
456 }
457 
458 /* Append given data to end of buffer, possibly allocating new buffers. */
460  u32 free_list_index,
461  u32 buffer_index, void *data, u32 n_data_bytes);
462 
463 /* duplicate all buffers in chain */
466 {
467  vlib_buffer_t *s, *d, *fd;
468  uword n_alloc, n_buffers = 1;
470  int i;
471 
472  s = b;
473  while (s->flags & VLIB_BUFFER_NEXT_PRESENT)
474  {
475  n_buffers++;
476  s = vlib_get_buffer (vm, s->next_buffer);
477  }
478  u32 new_buffers[n_buffers];
479 
480  n_alloc = vlib_buffer_alloc (vm, new_buffers, n_buffers);
481 
482  /* No guarantee that we'll get all the buffers we asked for */
483  if (PREDICT_FALSE (n_alloc < n_buffers))
484  {
485  if (n_alloc > 0)
486  vlib_buffer_free (vm, new_buffers, n_alloc);
487  return 0;
488  }
489 
490  /* 1st segment */
491  s = b;
492  fd = d = vlib_get_buffer (vm, new_buffers[0]);
493  d->current_data = s->current_data;
495  d->flags = s->flags & flag_mask;
498  clib_memcpy (d->opaque, s->opaque, sizeof (s->opaque));
501 
502  /* next segments */
503  for (i = 1; i < n_buffers; i++)
504  {
505  /* previous */
506  d->next_buffer = new_buffers[i];
507  /* current */
508  s = vlib_get_buffer (vm, s->next_buffer);
509  d = vlib_get_buffer (vm, new_buffers[i]);
510  d->current_data = s->current_data;
514  d->flags = s->flags & flag_mask;
515  }
516 
517  return fd;
518 }
519 
520 /** \brief Create multiple clones of buffer and store them in the supplied array
521 
522  @param vm - (vlib_main_t *) vlib main data structure pointer
523  @param src_buffer - (u32) source buffer index
524  @param buffers - (u32 * ) buffer index array
525  @param n_buffers - (u8) number of buffer clones requested
526  @param head_end_offset - (u16) offset relative to current position
527  where packet head ends
528  @return - (u8) number of buffers actually cloned, may be
529  less than the number requested or zero
530 */
531 
533 vlib_buffer_clone (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
534  u8 n_buffers, u16 head_end_offset)
535 {
536  u8 i;
537  vlib_buffer_t *s = vlib_get_buffer (vm, src_buffer);
538 
539  ASSERT (s->n_add_refs == 0);
540  ASSERT (n_buffers);
541 
542  if (s->current_length <= head_end_offset + CLIB_CACHE_LINE_BYTES * 2)
543  {
544  buffers[0] = src_buffer;
545  for (i = 1; i < n_buffers; i++)
546  {
547  vlib_buffer_t *d;
548  d = vlib_buffer_copy (vm, s);
549  if (d == 0)
550  return i;
551  buffers[i] = vlib_get_buffer_index (vm, d);
552 
553  }
554  return n_buffers;
555  }
556 
557  n_buffers = vlib_buffer_alloc_from_free_list (vm, buffers, n_buffers,
559  (s));
560  if (PREDICT_FALSE (n_buffers == 0))
561  {
562  buffers[0] = src_buffer;
563  return 1;
564  }
565 
566  for (i = 0; i < n_buffers; i++)
567  {
568  vlib_buffer_t *d = vlib_get_buffer (vm, buffers[i]);
569  d->current_data = s->current_data;
570  d->current_length = head_end_offset;
575  head_end_offset;
578  clib_memcpy (d->opaque, s->opaque, sizeof (s->opaque));
580  head_end_offset);
581  d->next_buffer = src_buffer;
582  }
583  vlib_buffer_advance (s, head_end_offset);
584  s->n_add_refs = n_buffers - 1;
585  while (s->flags & VLIB_BUFFER_NEXT_PRESENT)
586  {
587  s = vlib_get_buffer (vm, s->next_buffer);
588  s->n_add_refs = n_buffers - 1;
589  }
590 
591  return n_buffers;
592 }
593 
594 /** \brief Attach cloned tail to the buffer
595 
596  @param vm - (vlib_main_t *) vlib main data structure pointer
597  @param head - (vlib_buffer_t *) head buffer
598  @param tail - (Vlib buffer_t *) tail buffer to clone and attach to head
599 */
600 
601 always_inline void
603  vlib_buffer_t * tail)
604 {
605  ASSERT ((head->flags & VLIB_BUFFER_NEXT_PRESENT) == 0);
608 
612  head->flags |= (tail->flags & VLIB_BUFFER_TOTAL_LENGTH_VALID);
613  head->next_buffer = vlib_get_buffer_index (vm, tail);
616 
617 next_segment:
618  __sync_add_and_fetch (&tail->n_add_refs, 1);
619 
620  if (tail->flags & VLIB_BUFFER_NEXT_PRESENT)
621  {
622  tail = vlib_get_buffer (vm, tail->next_buffer);
623  goto next_segment;
624  }
625 }
626 
627 /* Initializes the buffer as an empty packet with no chained buffers. */
628 always_inline void
630 {
632  first->current_length = 0;
633  first->flags &= ~VLIB_BUFFER_NEXT_PRESENT;
635 }
636 
637 /* The provided next_bi buffer index is appended to the end of the packet. */
640  vlib_buffer_t * first,
641  vlib_buffer_t * last, u32 next_bi)
642 {
643  vlib_buffer_t *next_buffer = vlib_get_buffer (vm, next_bi);
644  last->next_buffer = next_bi;
646  next_buffer->current_length = 0;
647  next_buffer->flags &= ~VLIB_BUFFER_NEXT_PRESENT;
648  return next_buffer;
649 }
650 
651 /* Increases or decreases the packet length.
652  * It does not allocate or deallocate new buffers.
653  * Therefore, the added length must be compatible
654  * with the last buffer. */
655 always_inline void
657  vlib_buffer_t * last, i32 len)
658 {
659  last->current_length += len;
660  if (first != last)
662 }
663 
664 /* Copy data to the end of the packet and increases its length.
665  * It does not allocate new buffers.
666  * Returns the number of copied bytes. */
669  u32 free_list_index,
670  vlib_buffer_t * first,
671  vlib_buffer_t * last, void *data, u16 data_len)
672 {
673  u32 n_buffer_bytes =
674  vlib_buffer_free_list_buffer_size (vm, free_list_index);
675  ASSERT (n_buffer_bytes >= last->current_length + last->current_data);
676  u16 len = clib_min (data_len,
677  n_buffer_bytes - last->current_length -
678  last->current_data);
679  clib_memcpy (vlib_buffer_get_current (last) + last->current_length, data,
680  len);
681  vlib_buffer_chain_increase_length (first, last, len);
682  return len;
683 }
684 
685 /* Copy data to the end of the packet and increases its length.
686  * Allocates additional buffers from the free list if necessary.
687  * Returns the number of copied bytes.
688  * 'last' value is modified whenever new buffers are allocated and
689  * chained and points to the last buffer in the chain. */
690 u16
692  u32 free_list_index,
693  vlib_buffer_t * first,
694  vlib_buffer_t ** last,
695  void *data, u16 data_len);
697 
700 
701 typedef struct
702 {
703  /* Vector of packet data. */
705 
706  /* Number of buffers to allocate in each call to physmem
707  allocator. */
709 
710  /* Buffer free list for this template. */
712 
715 
718 
721  void *packet_data,
722  uword n_packet_data_bytes,
723  uword min_n_buffers_each_physmem_alloc,
724  char *fmt, ...);
725 
728  u32 * bi_result);
729 
730 always_inline void
732 {
733  vec_free (t->packet_data);
734 }
735 
738 {
739  serialize_stream_t *s = &m->stream;
743  vlib_main_t *vm = sm->vlib_main;
744  u32 n, *f;
745 
747  if (sm->last_buffer != ~0)
748  {
750  while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
751  {
752  b = vlib_get_buffer (vm, b->next_buffer);
753  n += b->current_length;
754  }
755  }
756 
757  /* *INDENT-OFF* */
758  clib_fifo_foreach (f, sm->rx.buffer_fifo, ({
759  n += vlib_buffer_index_length_in_chain (vm, f[0]);
760  }));
761 /* *INDENT-ON* */
762 
763  return n;
764 }
765 
766 /* Set a buffer quickly into "uninitialized" state. We want this to
767  be extremely cheap and arrange for all fields that need to be
768  initialized to be in the first 128 bits of the buffer. */
769 always_inline void
772 {
774 
775  /* Make sure vlib_buffer_t is cacheline aligned and sized */
776  ASSERT (STRUCT_OFFSET_OF (vlib_buffer_t, cacheline0) == 0);
777  ASSERT (STRUCT_OFFSET_OF (vlib_buffer_t, cacheline1) ==
779  ASSERT (STRUCT_OFFSET_OF (vlib_buffer_t, cacheline2) ==
781 
782  /* Make sure buffer template is sane. */
784 
785  clib_memcpy (STRUCT_MARK_PTR (dst, template_start),
786  STRUCT_MARK_PTR (src, template_start),
787  STRUCT_OFFSET_OF (vlib_buffer_t, template_end) -
788  STRUCT_OFFSET_OF (vlib_buffer_t, template_start));
789 
790  /* Not in the first 16 octets. */
791  dst->n_add_refs = src->n_add_refs;
792 
793  /* Make sure it really worked. */
794 #define _(f) ASSERT (dst->f == src->f);
795  _(current_data);
796  _(current_length);
797  _(flags);
798 #undef _
799  /* ASSERT (dst->total_length_not_including_first_buffer == 0); */
800  /* total_length_not_including_first_buffer is not in the template anymore
801  * so it may actually not zeroed for some buffers. One option is to
802  * uncomment the line lower (comes at a cost), the other, is to just not
803  * care */
804  /* dst->total_length_not_including_first_buffer = 0; */
805  ASSERT (dst->n_add_refs == 0);
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->buffers, buffer_index, CLIB_CACHE_LINE_BYTES);
818 
819  if (vec_len (f->buffers) > 4 * VLIB_FRAME_SIZE)
820  {
824  /* keep last stored buffers, as they are more likely hot in the cache */
829  }
830 }
831 
832 always_inline void
834  vlib_buffer_t * dst1,
836 {
838 
839  /* Make sure buffer template is sane. */
841 
842  clib_memcpy (STRUCT_MARK_PTR (dst0, template_start),
843  STRUCT_MARK_PTR (src, template_start),
844  STRUCT_OFFSET_OF (vlib_buffer_t, template_end) -
845  STRUCT_OFFSET_OF (vlib_buffer_t, template_start));
846 
847  clib_memcpy (STRUCT_MARK_PTR (dst1, template_start),
848  STRUCT_MARK_PTR (src, template_start),
849  STRUCT_OFFSET_OF (vlib_buffer_t, template_end) -
850  STRUCT_OFFSET_OF (vlib_buffer_t, template_start));
851 
852  /* Not in the first 16 octets. */
853  dst0->n_add_refs = src->n_add_refs;
854  dst1->n_add_refs = src->n_add_refs;
855 
856  /* Make sure it really worked. */
857 #define _(f) ASSERT (dst0->f == src->f); ASSERT( dst1->f == src->f)
858  _(current_data);
859  _(current_length);
860  _(flags);
861 #undef _
862 
865  ASSERT (dst0->n_add_refs == 0);
866  ASSERT (dst1->n_add_refs == 0);
867 }
868 
869 #if CLIB_DEBUG > 0
872 extern void *vlib_buffer_state_heap;
873 #endif
874 
875 static inline void
877 {
878 #if CLIB_DEBUG > 0
879  uword *p;
880  void *oldheap;
881 
883 
884  while (__sync_lock_test_and_set (vlib_buffer_state_validation_lock, 1))
885  ;
886 
888 
889  /* If we don't know about b, declare it to be in the expected state */
890  if (!p)
891  {
893  goto out;
894  }
895 
896  if (p[0] != expected)
897  {
898  void cj_stop (void);
899  u32 bi;
901 
902  cj_stop ();
903 
904  bi = vlib_get_buffer_index (vm, b);
905 
906  clib_mem_set_heap (oldheap);
907  clib_warning ("%.6f buffer %llx (%d): %s, not %s",
908  vlib_time_now (vm), bi,
909  p[0] ? "busy" : "free", expected ? "busy" : "free");
910  os_panic ();
911  }
912 out:
915  clib_mem_set_heap (oldheap);
916 #endif
917 }
918 
919 static inline void
921 {
922 #if CLIB_DEBUG > 0
923  void *oldheap;
924 
926 
927  while (__sync_lock_test_and_set (vlib_buffer_state_validation_lock, 1))
928  ;
929 
931 
934  clib_mem_set_heap (oldheap);
935 #endif
936 }
937 
938 #endif /* included_vlib_buffer_funcs_h */
939 
940 /*
941  * fd.io coding-style-patch-verification: ON
942  *
943  * Local Variables:
944  * eval: (c-set-style "gnu")
945  * End:
946  */
vlib_main_t vlib_global_main
Definition: main.c:1650
#define hash_set(h, key, value)
Definition: hash.h:254
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
#define clib_min(x, y)
Definition: clib.h:332
static_always_inline void clib_spinlock_unlock(clib_spinlock_t *p)
Definition: lock.h:72
static_always_inline void clib_spinlock_lock(clib_spinlock_t *p)
Definition: lock.h:50
u32 vlib_buffer_get_or_create_free_list(vlib_main_t *vm, u32 n_data_bytes, char *fmt,...)
Definition: buffer.c:436
uword vlib_buffer_length_in_chain_slow_path(vlib_main_t *vm, vlib_buffer_t *b_first)
Definition: buffer.c:53
static void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: buffer_funcs.h:317
static void vlib_buffer_set_known_state(vlib_main_t *vm, u32 buffer_index, vlib_buffer_known_state_t state)
Definition: buffer_funcs.h:230
#define STRUCT_MARK_PTR(v, f)
Definition: clib.h:68
format_function_t format_vlib_buffer_contents
Definition: buffer_funcs.h:698
u32 opaque[10]
Opaque data used by sub-graphs for their own purposes.
Definition: buffer.h:131
#define PREDICT_TRUE(x)
Definition: clib.h:98
format_function_t format_vlib_buffer
Definition: buffer_funcs.h:698
vlib_buffer_callbacks_t cb
Definition: buffer.h:440
void vlib_buffer_merge_free_lists(vlib_buffer_free_list_t *dst, vlib_buffer_free_list_t *src)
Definition: buffer.c:334
static void vlib_buffer_attach_clone(vlib_main_t *vm, vlib_buffer_t *head, vlib_buffer_t *tail)
Attach cloned tail to the buffer.
Definition: buffer_funcs.h:602
static u16 vlib_buffer_chain_append_data(vlib_main_t *vm, u32 free_list_index, vlib_buffer_t *first, vlib_buffer_t *last, void *data, u16 data_len)
Definition: buffer_funcs.h:668
static void vlib_validate_buffer_in_use(vlib_buffer_t *b, u32 expected)
Definition: buffer_funcs.h:876
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:639
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:221
static void vlib_buffer_chain_increase_length(vlib_buffer_t *first, vlib_buffer_t *last, i32 len)
Definition: buffer_funcs.h:656
vlib_buffer_t buffer_init_template
Definition: buffer.h:335
void os_panic(void)
Definition: unix-misc.c:174
struct vlib_main_t * vlib_main
Definition: buffer.h:450
#define CLIB_LOG2_CACHE_LINE_BYTES
Definition: cache.h:49
clib_spinlock_t global_buffers_lock
Definition: buffer.h:357
vlib_buffer_main_t * buffer_main
Definition: main.h:106
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:62
u8 *( format_function_t)(u8 *s, va_list *args)
Definition: format.h:48
static u8 vlib_buffer_clone(vlib_main_t *vm, u32 src_buffer, u32 *buffers, u8 n_buffers, u16 head_end_offset)
Create multiple clones of buffer and store them in the supplied array.
Definition: buffer_funcs.h:533
static vlib_buffer_known_state_t vlib_buffer_is_known(vlib_main_t *vm, u32 buffer_index)
Definition: buffer_funcs.h:219
uword * vlib_buffer_state_validation_hash
Definition: buffer.c:474
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:107
static u64 vlib_get_buffer_data_physical_address(vlib_main_t *vm, u32 buffer_index)
Definition: buffer_funcs.h:163
vlib_main_t ** vlib_mains
Definition: buffer.c:292
static vlib_buffer_t * vlib_buffer_copy(vlib_main_t *vm, vlib_buffer_t *b)
Definition: buffer_funcs.h:465
struct vlib_serialize_buffer_main_t::@27::@30 rx
void cj_stop(void)
Definition: cj.c:58
static void vlib_buffer_delete_free_list(vlib_main_t *vm, u32 free_list_index)
Definition: buffer_funcs.h:367
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: buffer.c:784
#define vec_add1_aligned(V, E, A)
Add 1 element to end of vector (alignment specified).
Definition: vec.h:528
#define VLIB_BUFFER_NEXT_PRESENT
Definition: buffer.h:95
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:68
#define always_inline
Definition: clib.h:84
#define VLIB_BUFFER_TOTAL_LENGTH_VALID
Definition: buffer.h:97
int i32
Definition: types.h:81
void vlib_aligned_memcpy(void *_dst, void *_src, int n_bytes)
u32 * vlib_buffer_state_validation_lock
Definition: buffer.c:473
unsigned long u64
Definition: types.h:89
static void vlib_copy_buffers(u32 *dst, u32 *src, u32 n)
Definition: buffer_funcs.h:437
static uword pointer_to_uword(const void *p)
Definition: types.h:131
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
Definition: buffer_funcs.h:74
#define fl(x, y)
#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:458
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:72
u8 * vlib_validate_buffer(vlib_main_t *vm, u32 buffer_index, uword follow_chain)
Definition: buffer.c:214
static u32 vlib_buffer_get_free_list_with_size(vlib_main_t *vm, u32 size)
Definition: buffer_funcs.h:391
#define VLIB_BUFFER_FREE_LIST_INDEX_MASK
Definition: buffer.h:91
format_function_t format_vlib_buffer_and_data
Definition: buffer_funcs.h:698
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:193
void(* vlib_buffer_delete_free_list_cb)(struct vlib_main_t *vm, u32 free_list_index)
Definition: buffer.h:398
#define PREDICT_FALSE(x)
Definition: clib.h:97
static u32 vlib_buffer_free_list_buffer_size(vlib_main_t *vm, u32 free_list_index)
Definition: buffer_funcs.h:426
#define VLIB_FRAME_SIZE
Definition: node.h:328
#define clib_fifo_foreach(v, f, body)
Definition: fifo.h:279
static void vlib_buffer_add_to_free_list(vlib_main_t *vm, vlib_buffer_free_list_t *f, u32 buffer_index, u8 do_init)
Definition: buffer_funcs.h:809
void(* vlib_buffer_free_cb)(struct vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Definition: buffer.h:388
void(* vlib_buffer_free_no_next_cb)(struct vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Definition: buffer.h:390
#define uword_to_pointer(u, type)
Definition: types.h:136
static uword vlib_buffer_contents(vlib_main_t *vm, u32 buffer_index, u8 *contents)
Copy buffer contents to memory.
Definition: buffer_funcs.h:141
static void vlib_buffer_chain_init(vlib_buffer_t *first)
Definition: buffer_funcs.h:629
#define vec_add_aligned(V, E, N, A)
Add N elements to end of vector V (no header, specified alignment)
Definition: vec.h:605
static u32 vlib_buffer_get_free_list_index(vlib_buffer_t *b)
Definition: buffer_funcs.h:270
serialize_stream_t stream
Definition: serialize.h:147
clib_spinlock_t buffer_known_hash_lockp
Definition: buffer.h:434
static 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: buffer_funcs.h:338
u32 current_buffer_index
Definition: serialize.h:62
void vlib_buffer_chain_validate(vlib_main_t *vm, vlib_buffer_t *first)
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:336
static void * clib_mem_set_heap(void *heap)
Definition: mem.h:226
#define clib_warning(format, args...)
Definition: error.h:59
#define clib_memcpy(a, b, c)
Definition: string.h:69
static vlib_buffer_t * vlib_get_next_buffer(vlib_main_t *vm, vlib_buffer_t *b)
Get next buffer in buffer linklist, or zero for end of list.
Definition: buffer_funcs.h:91
static 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: buffer_funcs.h:296
static uword round_pow2(uword x, uword pow2)
Definition: clib.h:278
vlib_buffer_known_state_t
Definition: buffer_funcs.h:208
uword data_function_opaque
Definition: serialize.h:74
static void vlib_validate_buffer_set_in_use(vlib_buffer_t *b, u32 expected)
Definition: buffer_funcs.h:920
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:781
u32(* vlib_buffer_alloc_cb)(struct vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Definition: buffer.h:383
u32(* vlib_buffer_alloc_from_free_list_cb)(struct vlib_main_t *vm, u32 *buffers, u32 n_buffers, u32 free_list_index)
Definition: buffer.h:385
void vlib_buffer_free_list_fill_unaligned(vlib_main_t *vm, vlib_buffer_free_list_t *free_list, uword n_unaligned_buffers)
vhost_vring_state_t state
Definition: vhost-user.h:82
u64 size
Definition: vhost-user.h:76
static vlib_buffer_free_list_t * vlib_buffer_get_buffer_free_list(vlib_main_t *vm, vlib_buffer_t *b, u32 *index)
Definition: buffer_funcs.h:401
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:109
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: buffer.c:929
u32 vlib_buffer_add_data(vlib_main_t *vm, u32 free_list_index, u32 buffer_index, void *data, u32 n_data_bytes)
Definition: buffer.c:872
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:206
static uword vlib_buffer_index_length_in_chain(vlib_main_t *vm, u32 bi)
Get length in bytes of the buffer index buffer chain.
Definition: buffer_funcs.h:127
static u64 vlib_physmem_offset_to_physical(vlib_main_t *vm, vlib_physmem_region_index_t idx, uword o)
Definition: physmem_funcs.h:51
vlib_physmem_region_index_t physmem_region
Definition: buffer.h:411
u8 n_add_refs
Number of additional references to this buffer.
Definition: buffer.h:124
void * vlib_buffer_state_heap
Definition: buffer.c:475
u64 uword
Definition: types.h:112
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
Definition: buffer.h:141
template key/value backing page structure
Definition: bihash_doc.h:44
unsigned short u16
Definition: types.h:57
static void vlib_buffer_set_free_list_index(vlib_buffer_t *b, u32 index)
Definition: buffer_funcs.h:276
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
vlib_buffer_free_list_t * buffer_free_list_pool
Definition: buffer.h:421
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:833
uword buffer_mem_start
Definition: buffer.h:409
uword * buffer_known_hash
Definition: buffer.h:433
void * vlib_packet_template_get_packet(vlib_main_t *vm, vlib_packet_template_t *t, u32 *bi_result)
Definition: buffer.c:834
static void vlib_buffer_init_for_free_list(vlib_buffer_t *dst, vlib_buffer_free_list_t *fl)
Definition: buffer_funcs.h:770
#define VLIB_BUFFER_EXT_HDR_VALID
Definition: buffer.h:101
u8 data[0]
Packet data.
Definition: buffer.h:157
#define CLIB_MEMORY_BARRIER()
Definition: clib.h:101
static void vlib_packet_template_free(vlib_main_t *vm, vlib_packet_template_t *t)
Definition: buffer_funcs.h:731
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:358
void vlib_packet_template_get_packet_helper(vlib_main_t *vm, vlib_packet_template_t *t)
Definition: buffer.c:854
static vlib_buffer_free_list_t * vlib_buffer_get_free_list(vlib_main_t *vm, u32 free_list_index)
Definition: buffer_funcs.h:412
u32 flags
Definition: vhost-user.h:77
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:75
static u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:254
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
uword * free_list_by_size
Definition: buffer.h:427
u32 vlib_buffer_create_free_list(vlib_main_t *vm, u32 n_data_bytes, char *fmt,...)
Definition: buffer.c:419
static u32 vlib_buffer_round_size(u32 size)
Definition: buffer_funcs.h:264
static u32 unserialize_vlib_buffer_n_bytes(serialize_main_t *m)
Definition: buffer_funcs.h:737