Buffer clone: copy opaque2
[vpp.git] / src / vlib / buffer_funcs.h
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 */
56 always_inline vlib_buffer_t *
57 vlib_get_buffer (vlib_main_t * vm, u32 buffer_index)
58 {
59   vlib_buffer_main_t *bm = &buffer_main;
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 array of buffer indices into buffer pointers with offset
67
68     @param vm - (vlib_main_t *) vlib main data structure pointer
69     @param bi - (u32 *) array of buffer indices
70     @param b - (void **) array to store buffer pointers
71     @param count - (uword) number of elements
72     @param offset - (i32) offset applied to each pointer
73 */
74 static_always_inline void
75 vlib_get_buffers_with_offset (vlib_main_t * vm, u32 * bi, void **b, int count,
76                               i32 offset)
77 {
78 #ifdef CLIB_HAVE_VEC256
79   u64x4 off = u64x4_splat (buffer_main.buffer_mem_start + offset);
80   /* if count is not const, compiler will not unroll while loop
81      se we maintain two-in-parallel variant */
82   while (count >= 8)
83     {
84       u64x4 b0 = u32x4_extend_to_u64x4 (u32x4_load_unaligned (bi));
85       u64x4 b1 = u32x4_extend_to_u64x4 (u32x4_load_unaligned (bi + 4));
86       /* shift and add to get vlib_buffer_t pointer */
87       u64x4_store_unaligned ((b0 << CLIB_LOG2_CACHE_LINE_BYTES) + off, b);
88       u64x4_store_unaligned ((b1 << CLIB_LOG2_CACHE_LINE_BYTES) + off, b + 4);
89       b += 8;
90       bi += 8;
91       count -= 8;
92     }
93 #endif
94   while (count >= 4)
95     {
96 #ifdef CLIB_HAVE_VEC256
97       u64x4 b0 = u32x4_extend_to_u64x4 (u32x4_load_unaligned (bi));
98       /* shift and add to get vlib_buffer_t pointer */
99       u64x4_store_unaligned ((b0 << CLIB_LOG2_CACHE_LINE_BYTES) + off, b);
100 #else
101       b[0] = ((u8 *) vlib_get_buffer (vm, bi[0])) + offset;
102       b[1] = ((u8 *) vlib_get_buffer (vm, bi[1])) + offset;
103       b[2] = ((u8 *) vlib_get_buffer (vm, bi[2])) + offset;
104       b[3] = ((u8 *) vlib_get_buffer (vm, bi[3])) + offset;
105 #endif
106       b += 4;
107       bi += 4;
108       count -= 4;
109     }
110   while (count)
111     {
112       b[0] = ((u8 *) vlib_get_buffer (vm, bi[0])) + offset;
113       b += 1;
114       bi += 1;
115       count -= 1;
116     }
117 }
118
119 /** \brief Translate array of buffer indices into buffer pointers
120
121     @param vm - (vlib_main_t *) vlib main data structure pointer
122     @param bi - (u32 *) array of buffer indices
123     @param b - (vlib_buffer_t **) array to store buffer pointers
124     @param count - (uword) number of elements
125 */
126
127 static_always_inline void
128 vlib_get_buffers (vlib_main_t * vm, u32 * bi, vlib_buffer_t ** b, int count)
129 {
130   vlib_get_buffers_with_offset (vm, bi, (void **) b, count, 0);
131 }
132
133 /** \brief Translate buffer pointer into buffer index
134
135     @param vm - (vlib_main_t *) vlib main data structure pointer
136     @param p - (void *) buffer pointer
137     @return - (u32) buffer index
138 */
139
140 always_inline u32
141 vlib_get_buffer_index (vlib_main_t * vm, void *p)
142 {
143   vlib_buffer_main_t *bm = &buffer_main;
144   uword offset = pointer_to_uword (p) - bm->buffer_mem_start;
145   ASSERT (pointer_to_uword (p) >= bm->buffer_mem_start);
146   ASSERT (offset < bm->buffer_mem_size);
147   ASSERT ((offset % (1 << CLIB_LOG2_CACHE_LINE_BYTES)) == 0);
148   return offset >> CLIB_LOG2_CACHE_LINE_BYTES;
149 }
150
151 /** \brief Translate array of buffer pointers into buffer indices with offset
152
153     @param vm - (vlib_main_t *) vlib main data structure pointer
154     @param b - (void **) array of buffer pointers
155     @param bi - (u32 *) array to store buffer indices
156     @param count - (uword) number of elements
157     @param offset - (i32) offset applied to each pointer
158 */
159 static_always_inline void
160 vlib_get_buffer_indices_with_offset (vlib_main_t * vm, void **b, u32 * bi,
161                                      uword count, i32 offset)
162 {
163 #ifdef CLIB_HAVE_VEC256
164   u32x8 mask = { 0, 2, 4, 6, 1, 3, 5, 7 };
165   u64x4 off4 = u64x4_splat (buffer_main.buffer_mem_start - offset);
166
167   while (count >= 8)
168     {
169       /* load 4 pointers into 256-bit register */
170       u64x4 v0 = u64x4_load_unaligned (b);
171       u64x4 v1 = u64x4_load_unaligned (b + 4);
172       u32x8 v2, v3;
173
174       v0 -= off4;
175       v1 -= off4;
176
177       v0 >>= CLIB_LOG2_CACHE_LINE_BYTES;
178       v1 >>= CLIB_LOG2_CACHE_LINE_BYTES;
179
180       /* permute 256-bit register so lower u32s of each buffer index are
181        * placed into lower 128-bits */
182       v2 = u32x8_permute ((u32x8) v0, mask);
183       v3 = u32x8_permute ((u32x8) v1, mask);
184
185       /* extract lower 128-bits and save them to the array of buffer indices */
186       u32x4_store_unaligned (u32x8_extract_lo (v2), bi);
187       u32x4_store_unaligned (u32x8_extract_lo (v3), bi + 4);
188       bi += 8;
189       b += 8;
190       count -= 8;
191     }
192 #endif
193   while (count >= 4)
194     {
195       /* equivalent non-nector implementation */
196       bi[0] = vlib_get_buffer_index (vm, ((u8 *) b[0]) + offset);
197       bi[1] = vlib_get_buffer_index (vm, ((u8 *) b[1]) + offset);
198       bi[2] = vlib_get_buffer_index (vm, ((u8 *) b[2]) + offset);
199       bi[3] = vlib_get_buffer_index (vm, ((u8 *) b[3]) + offset);
200       bi += 4;
201       b += 4;
202       count -= 4;
203     }
204   while (count)
205     {
206       bi[0] = vlib_get_buffer_index (vm, ((u8 *) b[0]) + offset);
207       bi += 1;
208       b += 1;
209       count -= 1;
210     }
211 }
212
213 /** \brief Translate array of buffer pointers into buffer indices
214
215     @param vm - (vlib_main_t *) vlib main data structure pointer
216     @param b - (vlib_buffer_t **) array of buffer pointers
217     @param bi - (u32 *) array to store buffer indices
218     @param count - (uword) number of elements
219 */
220 static_always_inline void
221 vlib_get_buffer_indices (vlib_main_t * vm, vlib_buffer_t ** b, u32 * bi,
222                          uword count)
223 {
224   vlib_get_buffer_indices_with_offset (vm, (void **) b, bi, count, 0);
225 }
226
227 /** \brief Get next buffer in buffer linklist, or zero for end of list.
228
229     @param vm - (vlib_main_t *) vlib main data structure pointer
230     @param b - (void *) buffer pointer
231     @return - (vlib_buffer_t *) next buffer, or NULL
232 */
233 always_inline vlib_buffer_t *
234 vlib_get_next_buffer (vlib_main_t * vm, vlib_buffer_t * b)
235 {
236   return (b->flags & VLIB_BUFFER_NEXT_PRESENT
237           ? vlib_get_buffer (vm, b->next_buffer) : 0);
238 }
239
240 uword vlib_buffer_length_in_chain_slow_path (vlib_main_t * vm,
241                                              vlib_buffer_t * b_first);
242
243 /** \brief Get length in bytes of the buffer chain
244
245     @param vm - (vlib_main_t *) vlib main data structure pointer
246     @param b - (void *) buffer pointer
247     @return - (uword) length of buffer chain
248 */
249 always_inline uword
250 vlib_buffer_length_in_chain (vlib_main_t * vm, vlib_buffer_t * b)
251 {
252   uword len = b->current_length;
253
254   if (PREDICT_TRUE ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0))
255     return len;
256
257   if (PREDICT_TRUE (b->flags & VLIB_BUFFER_TOTAL_LENGTH_VALID))
258     return len + b->total_length_not_including_first_buffer;
259
260   return vlib_buffer_length_in_chain_slow_path (vm, b);
261 }
262
263 /** \brief Get length in bytes of the buffer index buffer chain
264
265     @param vm - (vlib_main_t *) vlib main data structure pointer
266     @param bi - (u32) buffer index
267     @return - (uword) length of buffer chain
268 */
269 always_inline uword
270 vlib_buffer_index_length_in_chain (vlib_main_t * vm, u32 bi)
271 {
272   vlib_buffer_t *b = vlib_get_buffer (vm, bi);
273   return vlib_buffer_length_in_chain (vm, b);
274 }
275
276 /** \brief Copy buffer contents to memory
277
278     @param vm - (vlib_main_t *) vlib main data structure pointer
279     @param buffer_index - (u32) buffer index
280     @param contents - (u8 *) memory, <strong>must be large enough</strong>
281     @return - (uword) length of buffer chain
282 */
283 always_inline uword
284 vlib_buffer_contents (vlib_main_t * vm, u32 buffer_index, u8 * contents)
285 {
286   uword content_len = 0;
287   uword l;
288   vlib_buffer_t *b;
289
290   while (1)
291     {
292       b = vlib_get_buffer (vm, buffer_index);
293       l = b->current_length;
294       clib_memcpy (contents + content_len, b->data + b->current_data, l);
295       content_len += l;
296       if (!(b->flags & VLIB_BUFFER_NEXT_PRESENT))
297         break;
298       buffer_index = b->next_buffer;
299     }
300
301   return content_len;
302 }
303
304 /* Return physical address of buffer->data start. */
305 always_inline u64
306 vlib_get_buffer_data_physical_address (vlib_main_t * vm, u32 buffer_index)
307 {
308   vlib_buffer_main_t *bm = &buffer_main;
309   vlib_buffer_t *b = vlib_get_buffer (vm, buffer_index);
310   vlib_buffer_pool_t *pool = vec_elt_at_index (bm->buffer_pools,
311                                                b->buffer_pool_index);
312
313   return vlib_physmem_virtual_to_physical (vm, pool->physmem_region, b->data);
314 }
315
316 /** \brief Prefetch buffer metadata by buffer index
317     The first 64 bytes of buffer contains most header information
318
319     @param vm - (vlib_main_t *) vlib main data structure pointer
320     @param bi - (u32) buffer index
321     @param type - LOAD, STORE. In most cases, STORE is the right answer
322 */
323 /* Prefetch buffer header given index. */
324 #define vlib_prefetch_buffer_with_index(vm,bi,type)     \
325   do {                                                  \
326     vlib_buffer_t * _b = vlib_get_buffer (vm, bi);      \
327     vlib_prefetch_buffer_header (_b, type);             \
328   } while (0)
329
330 #if 0
331 /* Iterate over known allocated vlib bufs. You probably do not want
332  * to do this!
333  @param vm      the vlib_main_t
334  @param bi      found allocated buffer index
335  @param body    operation to perform on buffer index
336  function executes body for each allocated buffer index
337  */
338 #define vlib_buffer_foreach_allocated(vm,bi,body)                \
339 do {                                                             \
340   vlib_main_t * _vmain = (vm);                                   \
341   vlib_buffer_main_t * _bmain = &_vmain->buffer_main;            \
342   hash_pair_t * _vbpair;                                         \
343   hash_foreach_pair(_vbpair, _bmain->buffer_known_hash, ({       \
344     if (VLIB_BUFFER_KNOWN_ALLOCATED == _vbpair->value[0]) {      \
345       (bi) = _vbpair->key;                                       \
346       body;                                                      \
347     }                                                            \
348   }));                                                           \
349 } while (0)
350 #endif
351
352 typedef enum
353 {
354   /* Index is unknown. */
355   VLIB_BUFFER_UNKNOWN,
356
357   /* Index is known and free/allocated. */
358   VLIB_BUFFER_KNOWN_FREE,
359   VLIB_BUFFER_KNOWN_ALLOCATED,
360 } vlib_buffer_known_state_t;
361
362 void vlib_buffer_validate_alloc_free (vlib_main_t * vm, u32 * buffers,
363                                       uword n_buffers,
364                                       vlib_buffer_known_state_t
365                                       expected_state);
366
367 always_inline vlib_buffer_known_state_t
368 vlib_buffer_is_known (u32 buffer_index)
369 {
370   vlib_buffer_main_t *bm = &buffer_main;
371
372   clib_spinlock_lock (&bm->buffer_known_hash_lockp);
373   uword *p = hash_get (bm->buffer_known_hash, buffer_index);
374   clib_spinlock_unlock (&bm->buffer_known_hash_lockp);
375   return p ? p[0] : VLIB_BUFFER_UNKNOWN;
376 }
377
378 always_inline void
379 vlib_buffer_set_known_state (u32 buffer_index,
380                              vlib_buffer_known_state_t state)
381 {
382   vlib_buffer_main_t *bm = &buffer_main;
383
384   clib_spinlock_lock (&bm->buffer_known_hash_lockp);
385   hash_set (bm->buffer_known_hash, buffer_index, state);
386   clib_spinlock_unlock (&bm->buffer_known_hash_lockp);
387 }
388
389 /* Validates sanity of a single buffer.
390    Returns format'ed vector with error message if any. */
391 u8 *vlib_validate_buffer (vlib_main_t * vm, u32 buffer_index,
392                           uword follow_chain);
393
394 always_inline u32
395 vlib_buffer_round_size (u32 size)
396 {
397   return round_pow2 (size, sizeof (vlib_buffer_t));
398 }
399
400 always_inline vlib_buffer_free_list_index_t
401 vlib_buffer_get_free_list_index (vlib_buffer_t * b)
402 {
403   if (PREDICT_FALSE (b->flags & VLIB_BUFFER_NON_DEFAULT_FREELIST))
404     return b->free_list_index;
405
406   return 0;
407 }
408
409 always_inline void
410 vlib_buffer_set_free_list_index (vlib_buffer_t * b,
411                                  vlib_buffer_free_list_index_t index)
412 {
413   if (PREDICT_FALSE (index))
414     {
415       b->flags |= VLIB_BUFFER_NON_DEFAULT_FREELIST;
416       b->free_list_index = index;
417     }
418   else
419     b->flags &= ~VLIB_BUFFER_NON_DEFAULT_FREELIST;
420 }
421
422 /** \brief Allocate buffers from specific freelist into supplied array
423
424     @param vm - (vlib_main_t *) vlib main data structure pointer
425     @param buffers - (u32 * ) buffer index array
426     @param n_buffers - (u32) number of buffers requested
427     @return - (u32) number of buffers actually allocated, may be
428     less than the number requested or zero
429 */
430 always_inline u32
431 vlib_buffer_alloc_from_free_list (vlib_main_t * vm,
432                                   u32 * buffers,
433                                   u32 n_buffers,
434                                   vlib_buffer_free_list_index_t index)
435 {
436   vlib_buffer_main_t *bm = &buffer_main;
437   vlib_buffer_free_list_t *fl;
438   u32 *src;
439   uword len;
440
441   ASSERT (bm->cb.vlib_buffer_fill_free_list_cb);
442
443   fl = pool_elt_at_index (vm->buffer_free_list_pool, index);
444
445   len = vec_len (fl->buffers);
446
447   if (PREDICT_FALSE (len < n_buffers))
448     {
449       bm->cb.vlib_buffer_fill_free_list_cb (vm, fl, n_buffers);
450       if (PREDICT_FALSE ((len = vec_len (fl->buffers)) == 0))
451         return 0;
452
453       /* even if fill free list didn't manage to refill free list
454          we should give what we have */
455       n_buffers = clib_min (len, n_buffers);
456
457       /* following code is intentionaly duplicated to allow compiler
458          to optimize fast path when n_buffers is constant value */
459       src = fl->buffers + len - n_buffers;
460       clib_memcpy (buffers, src, n_buffers * sizeof (u32));
461       _vec_len (fl->buffers) -= n_buffers;
462
463       /* Verify that buffers are known free. */
464       vlib_buffer_validate_alloc_free (vm, buffers, n_buffers,
465                                        VLIB_BUFFER_KNOWN_FREE);
466
467       return n_buffers;
468     }
469
470   src = fl->buffers + len - n_buffers;
471   clib_memcpy (buffers, src, n_buffers * sizeof (u32));
472   _vec_len (fl->buffers) -= n_buffers;
473
474   /* Verify that buffers are known free. */
475   vlib_buffer_validate_alloc_free (vm, buffers, n_buffers,
476                                    VLIB_BUFFER_KNOWN_FREE);
477
478   return n_buffers;
479 }
480
481 /** \brief Allocate buffers into supplied array
482
483     @param vm - (vlib_main_t *) vlib main data structure pointer
484     @param buffers - (u32 * ) buffer index array
485     @param n_buffers - (u32) number of buffers requested
486     @return - (u32) number of buffers actually allocated, may be
487     less than the number requested or zero
488 */
489 always_inline u32
490 vlib_buffer_alloc (vlib_main_t * vm, u32 * buffers, u32 n_buffers)
491 {
492   return vlib_buffer_alloc_from_free_list (vm, buffers, n_buffers,
493                                            VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
494 }
495
496 /** \brief Allocate buffers into ring
497
498     @param vm - (vlib_main_t *) vlib main data structure pointer
499     @param buffers - (u32 * ) buffer index ring
500     @param start - (u32) first slot in the ring
501     @param ring_size - (u32) ring size
502     @param n_buffers - (u32) number of buffers requested
503     @return - (u32) number of buffers actually allocated, may be
504     less than the number requested or zero
505 */
506 always_inline u32
507 vlib_buffer_alloc_to_ring (vlib_main_t * vm, u32 * ring, u32 start,
508                            u32 ring_size, u32 n_buffers)
509 {
510   u32 n_alloc;
511
512   ASSERT (n_buffers <= ring_size);
513
514   if (PREDICT_TRUE (start + n_buffers <= ring_size))
515     return vlib_buffer_alloc (vm, ring + start, n_buffers);
516
517   n_alloc = vlib_buffer_alloc (vm, ring + start, ring_size - start);
518
519   if (PREDICT_TRUE (n_alloc == ring_size - start))
520     n_alloc += vlib_buffer_alloc (vm, ring, n_buffers - n_alloc);
521
522   return n_alloc;
523 }
524
525 /** \brief Free buffers
526     Frees the entire buffer chain for each buffer
527
528     @param vm - (vlib_main_t *) vlib main data structure pointer
529     @param buffers - (u32 * ) buffer index array
530     @param n_buffers - (u32) number of buffers to free
531
532 */
533 always_inline void
534 vlib_buffer_free (vlib_main_t * vm,
535                   /* pointer to first buffer */
536                   u32 * buffers,
537                   /* number of buffers to free */
538                   u32 n_buffers)
539 {
540   vlib_buffer_main_t *bm = &buffer_main;
541
542   ASSERT (bm->cb.vlib_buffer_free_cb);
543
544   return bm->cb.vlib_buffer_free_cb (vm, buffers, n_buffers);
545 }
546
547 /** \brief Free buffers, does not free the buffer chain for each buffer
548
549     @param vm - (vlib_main_t *) vlib main data structure pointer
550     @param buffers - (u32 * ) buffer index array
551     @param n_buffers - (u32) number of buffers to free
552
553 */
554 always_inline void
555 vlib_buffer_free_no_next (vlib_main_t * vm,
556                           /* pointer to first buffer */
557                           u32 * buffers,
558                           /* number of buffers to free */
559                           u32 n_buffers)
560 {
561   vlib_buffer_main_t *bm = &buffer_main;
562
563   ASSERT (bm->cb.vlib_buffer_free_no_next_cb);
564
565   return bm->cb.vlib_buffer_free_no_next_cb (vm, buffers, n_buffers);
566 }
567
568 /** \brief Free one buffer
569     Shorthand to free a single buffer chain.
570
571     @param vm - (vlib_main_t *) vlib main data structure pointer
572     @param buffer_index - (u32) buffer index to free
573 */
574 always_inline void
575 vlib_buffer_free_one (vlib_main_t * vm, u32 buffer_index)
576 {
577   vlib_buffer_free (vm, &buffer_index, /* n_buffers */ 1);
578 }
579
580 /** \brief Free buffers from ring
581
582     @param vm - (vlib_main_t *) vlib main data structure pointer
583     @param buffers - (u32 * ) buffer index ring
584     @param start - (u32) first slot in the ring
585     @param ring_size - (u32) ring size
586     @param n_buffers - (u32) number of buffers
587 */
588 always_inline void
589 vlib_buffer_free_from_ring (vlib_main_t * vm, u32 * ring, u32 start,
590                             u32 ring_size, u32 n_buffers)
591 {
592   ASSERT (n_buffers <= ring_size);
593
594   if (PREDICT_TRUE (start + n_buffers <= ring_size))
595     {
596       vlib_buffer_free (vm, ring + start, n_buffers);
597     }
598   else
599     {
600       vlib_buffer_free (vm, ring + start, ring_size - start);
601       vlib_buffer_free (vm, ring, n_buffers - (ring_size - start));
602     }
603 }
604
605 /** \brief Free buffers from ring without freeing tail buffers
606
607     @param vm - (vlib_main_t *) vlib main data structure pointer
608     @param buffers - (u32 * ) buffer index ring
609     @param start - (u32) first slot in the ring
610     @param ring_size - (u32) ring size
611     @param n_buffers - (u32) number of buffers
612 */
613 always_inline void
614 vlib_buffer_free_from_ring_no_next (vlib_main_t * vm, u32 * ring, u32 start,
615                                     u32 ring_size, u32 n_buffers)
616 {
617   ASSERT (n_buffers <= ring_size);
618
619   if (PREDICT_TRUE (start + n_buffers <= ring_size))
620     {
621       vlib_buffer_free_no_next (vm, ring + start, n_buffers);
622     }
623   else
624     {
625       vlib_buffer_free_no_next (vm, ring + start, ring_size - start);
626       vlib_buffer_free_no_next (vm, ring, n_buffers - (ring_size - start));
627     }
628 }
629
630 /* Add/delete buffer free lists. */
631 vlib_buffer_free_list_index_t vlib_buffer_create_free_list (vlib_main_t * vm,
632                                                             u32 n_data_bytes,
633                                                             char *fmt, ...);
634 always_inline void
635 vlib_buffer_delete_free_list (vlib_main_t * vm,
636                               vlib_buffer_free_list_index_t free_list_index)
637 {
638   vlib_buffer_main_t *bm = &buffer_main;
639
640   ASSERT (bm->cb.vlib_buffer_delete_free_list_cb);
641
642   bm->cb.vlib_buffer_delete_free_list_cb (vm, free_list_index);
643 }
644
645 /* Make sure we have at least given number of unaligned buffers. */
646 void vlib_buffer_free_list_fill_unaligned (vlib_main_t * vm,
647                                            vlib_buffer_free_list_t *
648                                            free_list,
649                                            uword n_unaligned_buffers);
650
651 always_inline vlib_buffer_free_list_t *
652 vlib_buffer_get_buffer_free_list (vlib_main_t * vm, vlib_buffer_t * b,
653                                   vlib_buffer_free_list_index_t * index)
654 {
655   vlib_buffer_free_list_index_t i;
656
657   *index = i = vlib_buffer_get_free_list_index (b);
658   return pool_elt_at_index (vm->buffer_free_list_pool, i);
659 }
660
661 always_inline vlib_buffer_free_list_t *
662 vlib_buffer_get_free_list (vlib_main_t * vm,
663                            vlib_buffer_free_list_index_t free_list_index)
664 {
665   vlib_buffer_free_list_t *f;
666
667   f = pool_elt_at_index (vm->buffer_free_list_pool, free_list_index);
668
669   /* Sanity: indices must match. */
670   ASSERT (f->index == free_list_index);
671
672   return f;
673 }
674
675 always_inline u32
676 vlib_buffer_free_list_buffer_size (vlib_main_t * vm,
677                                    vlib_buffer_free_list_index_t index)
678 {
679   vlib_buffer_free_list_t *f = vlib_buffer_get_free_list (vm, index);
680   return f->n_data_bytes;
681 }
682
683 void vlib_aligned_memcpy (void *_dst, void *_src, int n_bytes);
684
685 /* Reasonably fast buffer copy routine. */
686 always_inline void
687 vlib_copy_buffers (u32 * dst, u32 * src, u32 n)
688 {
689   while (n >= 4)
690     {
691       dst[0] = src[0];
692       dst[1] = src[1];
693       dst[2] = src[2];
694       dst[3] = src[3];
695       dst += 4;
696       src += 4;
697       n -= 4;
698     }
699   while (n > 0)
700     {
701       dst[0] = src[0];
702       dst += 1;
703       src += 1;
704       n -= 1;
705     }
706 }
707
708 /* Append given data to end of buffer, possibly allocating new buffers. */
709 u32 vlib_buffer_add_data (vlib_main_t * vm,
710                           vlib_buffer_free_list_index_t free_list_index,
711                           u32 buffer_index, void *data, u32 n_data_bytes);
712
713 /* duplicate all buffers in chain */
714 always_inline vlib_buffer_t *
715 vlib_buffer_copy (vlib_main_t * vm, vlib_buffer_t * b)
716 {
717   vlib_buffer_t *s, *d, *fd;
718   uword n_alloc, n_buffers = 1;
719   u32 flag_mask = VLIB_BUFFER_NEXT_PRESENT | VLIB_BUFFER_TOTAL_LENGTH_VALID;
720   int i;
721
722   s = b;
723   while (s->flags & VLIB_BUFFER_NEXT_PRESENT)
724     {
725       n_buffers++;
726       s = vlib_get_buffer (vm, s->next_buffer);
727     }
728   u32 new_buffers[n_buffers];
729
730   n_alloc = vlib_buffer_alloc (vm, new_buffers, n_buffers);
731
732   /* No guarantee that we'll get all the buffers we asked for */
733   if (PREDICT_FALSE (n_alloc < n_buffers))
734     {
735       if (n_alloc > 0)
736         vlib_buffer_free (vm, new_buffers, n_alloc);
737       return 0;
738     }
739
740   /* 1st segment */
741   s = b;
742   fd = d = vlib_get_buffer (vm, new_buffers[0]);
743   d->current_data = s->current_data;
744   d->current_length = s->current_length;
745   d->flags = s->flags & flag_mask;
746   d->total_length_not_including_first_buffer =
747     s->total_length_not_including_first_buffer;
748   clib_memcpy (d->opaque, s->opaque, sizeof (s->opaque));
749   clib_memcpy (d->opaque2, s->opaque2, sizeof (s->opaque2));
750   clib_memcpy (vlib_buffer_get_current (d),
751                vlib_buffer_get_current (s), s->current_length);
752
753   /* next segments */
754   for (i = 1; i < n_buffers; i++)
755     {
756       /* previous */
757       d->next_buffer = new_buffers[i];
758       /* current */
759       s = vlib_get_buffer (vm, s->next_buffer);
760       d = vlib_get_buffer (vm, new_buffers[i]);
761       d->current_data = s->current_data;
762       d->current_length = s->current_length;
763       clib_memcpy (vlib_buffer_get_current (d),
764                    vlib_buffer_get_current (s), s->current_length);
765       d->flags = s->flags & flag_mask;
766     }
767
768   return fd;
769 }
770
771 /** \brief Create a maximum of 256 clones of buffer and store them
772     in the supplied array
773
774     @param vm - (vlib_main_t *) vlib main data structure pointer
775     @param src_buffer - (u32) source buffer index
776     @param buffers - (u32 * ) buffer index array
777     @param n_buffers - (u16) number of buffer clones requested (<=256)
778     @param head_end_offset - (u16) offset relative to current position
779            where packet head ends
780     @return - (u16) number of buffers actually cloned, may be
781     less than the number requested or zero
782 */
783 always_inline u16
784 vlib_buffer_clone_256 (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
785                        u16 n_buffers, u16 head_end_offset)
786 {
787   u16 i;
788   vlib_buffer_t *s = vlib_get_buffer (vm, src_buffer);
789
790   ASSERT (s->n_add_refs == 0);
791   ASSERT (n_buffers);
792   ASSERT (n_buffers <= 256);
793
794   if (s->current_length <= head_end_offset + CLIB_CACHE_LINE_BYTES * 2)
795     {
796       buffers[0] = src_buffer;
797       for (i = 1; i < n_buffers; i++)
798         {
799           vlib_buffer_t *d;
800           d = vlib_buffer_copy (vm, s);
801           if (d == 0)
802             return i;
803           buffers[i] = vlib_get_buffer_index (vm, d);
804
805         }
806       return n_buffers;
807     }
808
809   if (PREDICT_FALSE (n_buffers == 1))
810     {
811       buffers[0] = src_buffer;
812       return 1;
813     }
814
815   n_buffers = vlib_buffer_alloc_from_free_list (vm, buffers, n_buffers,
816                                                 vlib_buffer_get_free_list_index
817                                                 (s));
818
819   for (i = 0; i < n_buffers; i++)
820     {
821       vlib_buffer_t *d = vlib_get_buffer (vm, buffers[i]);
822       d->current_data = s->current_data;
823       d->current_length = head_end_offset;
824       vlib_buffer_set_free_list_index (d,
825                                        vlib_buffer_get_free_list_index (s));
826
827       d->total_length_not_including_first_buffer = s->current_length -
828         head_end_offset;
829       if (PREDICT_FALSE (s->flags & VLIB_BUFFER_NEXT_PRESENT))
830         {
831           d->total_length_not_including_first_buffer +=
832             s->total_length_not_including_first_buffer;
833         }
834       d->flags = s->flags | VLIB_BUFFER_NEXT_PRESENT;
835       d->flags &= ~VLIB_BUFFER_EXT_HDR_VALID;
836       clib_memcpy (d->opaque, s->opaque, sizeof (s->opaque));
837       clib_memcpy (d->opaque2, s->opaque2, sizeof (s->opaque2));
838       clib_memcpy (vlib_buffer_get_current (d), vlib_buffer_get_current (s),
839                    head_end_offset);
840       d->next_buffer = src_buffer;
841     }
842   vlib_buffer_advance (s, head_end_offset);
843   s->n_add_refs = n_buffers - 1;
844   while (s->flags & VLIB_BUFFER_NEXT_PRESENT)
845     {
846       s = vlib_get_buffer (vm, s->next_buffer);
847       s->n_add_refs = n_buffers - 1;
848     }
849
850   return n_buffers;
851 }
852
853 /** \brief Create multiple clones of buffer and store them
854     in the supplied array
855
856     @param vm - (vlib_main_t *) vlib main data structure pointer
857     @param src_buffer - (u32) source buffer index
858     @param buffers - (u32 * ) buffer index array
859     @param n_buffers - (u16) number of buffer clones requested (<=256)
860     @param head_end_offset - (u16) offset relative to current position
861            where packet head ends
862     @return - (u16) number of buffers actually cloned, may be
863     less than the number requested or zero
864 */
865 always_inline u16
866 vlib_buffer_clone (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
867                    u16 n_buffers, u16 head_end_offset)
868 {
869   vlib_buffer_t *s = vlib_get_buffer (vm, src_buffer);
870   u16 n_cloned = 0;
871
872   while (n_buffers > 256)
873     {
874       vlib_buffer_t *copy;
875       copy = vlib_buffer_copy (vm, s);
876       n_cloned += vlib_buffer_clone_256 (vm,
877                                          vlib_get_buffer_index (vm, copy),
878                                          (buffers + n_cloned),
879                                          256, head_end_offset);
880       n_buffers -= 256;
881     }
882   n_cloned += vlib_buffer_clone_256 (vm, src_buffer,
883                                      buffers + n_cloned,
884                                      n_buffers, head_end_offset);
885
886   return n_cloned;
887 }
888
889 /** \brief Attach cloned tail to the buffer
890
891     @param vm - (vlib_main_t *) vlib main data structure pointer
892     @param head - (vlib_buffer_t *) head buffer
893     @param tail - (Vlib buffer_t *) tail buffer to clone and attach to head
894 */
895
896 always_inline void
897 vlib_buffer_attach_clone (vlib_main_t * vm, vlib_buffer_t * head,
898                           vlib_buffer_t * tail)
899 {
900   ASSERT ((head->flags & VLIB_BUFFER_NEXT_PRESENT) == 0);
901   ASSERT (vlib_buffer_get_free_list_index (head) ==
902           vlib_buffer_get_free_list_index (tail));
903
904   head->flags |= VLIB_BUFFER_NEXT_PRESENT;
905   head->flags &= ~VLIB_BUFFER_TOTAL_LENGTH_VALID;
906   head->flags &= ~VLIB_BUFFER_EXT_HDR_VALID;
907   head->flags |= (tail->flags & VLIB_BUFFER_TOTAL_LENGTH_VALID);
908   head->next_buffer = vlib_get_buffer_index (vm, tail);
909   head->total_length_not_including_first_buffer = tail->current_length +
910     tail->total_length_not_including_first_buffer;
911
912 next_segment:
913   __sync_add_and_fetch (&tail->n_add_refs, 1);
914
915   if (tail->flags & VLIB_BUFFER_NEXT_PRESENT)
916     {
917       tail = vlib_get_buffer (vm, tail->next_buffer);
918       goto next_segment;
919     }
920 }
921
922 /* Initializes the buffer as an empty packet with no chained buffers. */
923 always_inline void
924 vlib_buffer_chain_init (vlib_buffer_t * first)
925 {
926   first->total_length_not_including_first_buffer = 0;
927   first->current_length = 0;
928   first->flags &= ~VLIB_BUFFER_NEXT_PRESENT;
929   first->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
930 }
931
932 /* The provided next_bi buffer index is appended to the end of the packet. */
933 always_inline vlib_buffer_t *
934 vlib_buffer_chain_buffer (vlib_main_t * vm,
935                           vlib_buffer_t * first,
936                           vlib_buffer_t * last, u32 next_bi)
937 {
938   vlib_buffer_t *next_buffer = vlib_get_buffer (vm, next_bi);
939   last->next_buffer = next_bi;
940   last->flags |= VLIB_BUFFER_NEXT_PRESENT;
941   next_buffer->current_length = 0;
942   next_buffer->flags &= ~VLIB_BUFFER_NEXT_PRESENT;
943   return next_buffer;
944 }
945
946 /* Increases or decreases the packet length.
947  * It does not allocate or deallocate new buffers.
948  * Therefore, the added length must be compatible
949  * with the last buffer. */
950 always_inline void
951 vlib_buffer_chain_increase_length (vlib_buffer_t * first,
952                                    vlib_buffer_t * last, i32 len)
953 {
954   last->current_length += len;
955   if (first != last)
956     first->total_length_not_including_first_buffer += len;
957 }
958
959 /* Copy data to the end of the packet and increases its length.
960  * It does not allocate new buffers.
961  * Returns the number of copied bytes. */
962 always_inline u16
963 vlib_buffer_chain_append_data (vlib_main_t * vm,
964                                vlib_buffer_free_list_index_t free_list_index,
965                                vlib_buffer_t * first,
966                                vlib_buffer_t * last, void *data, u16 data_len)
967 {
968   u32 n_buffer_bytes =
969     vlib_buffer_free_list_buffer_size (vm, free_list_index);
970   ASSERT (n_buffer_bytes >= last->current_length + last->current_data);
971   u16 len = clib_min (data_len,
972                       n_buffer_bytes - last->current_length -
973                       last->current_data);
974   clib_memcpy (vlib_buffer_get_current (last) + last->current_length, data,
975                len);
976   vlib_buffer_chain_increase_length (first, last, len);
977   return len;
978 }
979
980 /* Copy data to the end of the packet and increases its length.
981  * Allocates additional buffers from the free list if necessary.
982  * Returns the number of copied bytes.
983  * 'last' value is modified whenever new buffers are allocated and
984  * chained and points to the last buffer in the chain. */
985 u16
986 vlib_buffer_chain_append_data_with_alloc (vlib_main_t * vm,
987                                           vlib_buffer_free_list_index_t
988                                           free_list_index,
989                                           vlib_buffer_t * first,
990                                           vlib_buffer_t ** last, void *data,
991                                           u16 data_len);
992 void vlib_buffer_chain_validate (vlib_main_t * vm, vlib_buffer_t * first);
993
994 format_function_t format_vlib_buffer, format_vlib_buffer_and_data,
995   format_vlib_buffer_contents;
996
997 typedef struct
998 {
999   /* Vector of packet data. */
1000   u8 *packet_data;
1001
1002   /* Number of buffers to allocate in each call to allocator. */
1003   u32 min_n_buffers_each_alloc;
1004
1005   /* Buffer free list for this template. */
1006   vlib_buffer_free_list_index_t free_list_index;
1007
1008   u32 *free_buffers;
1009 } vlib_packet_template_t;
1010
1011 void vlib_packet_template_get_packet_helper (vlib_main_t * vm,
1012                                              vlib_packet_template_t * t);
1013
1014 void vlib_packet_template_init (vlib_main_t * vm,
1015                                 vlib_packet_template_t * t,
1016                                 void *packet_data,
1017                                 uword n_packet_data_bytes,
1018                                 uword min_n_buffers_each_alloc,
1019                                 char *fmt, ...);
1020
1021 void *vlib_packet_template_get_packet (vlib_main_t * vm,
1022                                        vlib_packet_template_t * t,
1023                                        u32 * bi_result);
1024
1025 always_inline void
1026 vlib_packet_template_free (vlib_main_t * vm, vlib_packet_template_t * t)
1027 {
1028   vec_free (t->packet_data);
1029 }
1030
1031 always_inline u32
1032 unserialize_vlib_buffer_n_bytes (serialize_main_t * m)
1033 {
1034   serialize_stream_t *s = &m->stream;
1035   vlib_serialize_buffer_main_t *sm
1036     = uword_to_pointer (m->stream.data_function_opaque,
1037                         vlib_serialize_buffer_main_t *);
1038   vlib_main_t *vm = sm->vlib_main;
1039   u32 n, *f;
1040
1041   n = s->n_buffer_bytes - s->current_buffer_index;
1042   if (sm->last_buffer != ~0)
1043     {
1044       vlib_buffer_t *b = vlib_get_buffer (vm, sm->last_buffer);
1045       while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
1046         {
1047           b = vlib_get_buffer (vm, b->next_buffer);
1048           n += b->current_length;
1049         }
1050     }
1051
1052   /* *INDENT-OFF* */
1053   clib_fifo_foreach (f, sm->rx.buffer_fifo, ({
1054     n += vlib_buffer_index_length_in_chain (vm, f[0]);
1055   }));
1056 /* *INDENT-ON* */
1057
1058   return n;
1059 }
1060
1061 /* Set a buffer quickly into "uninitialized" state.  We want this to
1062    be extremely cheap and arrange for all fields that need to be
1063    initialized to be in the first 128 bits of the buffer. */
1064 always_inline void
1065 vlib_buffer_init_for_free_list (vlib_buffer_t * dst,
1066                                 vlib_buffer_free_list_t * fl)
1067 {
1068   vlib_buffer_t *src = &fl->buffer_init_template;
1069
1070   /* Make sure vlib_buffer_t is cacheline aligned and sized */
1071   ASSERT (STRUCT_OFFSET_OF (vlib_buffer_t, cacheline0) == 0);
1072   ASSERT (STRUCT_OFFSET_OF (vlib_buffer_t, cacheline1) ==
1073           CLIB_CACHE_LINE_BYTES);
1074   ASSERT (STRUCT_OFFSET_OF (vlib_buffer_t, cacheline2) ==
1075           CLIB_CACHE_LINE_BYTES * 2);
1076
1077   /* Make sure buffer template is sane. */
1078   ASSERT (fl->index == vlib_buffer_get_free_list_index (src));
1079
1080   clib_memcpy (STRUCT_MARK_PTR (dst, template_start),
1081                STRUCT_MARK_PTR (src, template_start),
1082                STRUCT_OFFSET_OF (vlib_buffer_t, template_end) -
1083                STRUCT_OFFSET_OF (vlib_buffer_t, template_start));
1084
1085   /* Not in the first 16 octets. */
1086   dst->n_add_refs = src->n_add_refs;
1087   vlib_buffer_set_free_list_index (dst, fl->index);
1088
1089   /* Make sure it really worked. */
1090 #define _(f) ASSERT (dst->f == src->f);
1091   _(current_data);
1092   _(current_length);
1093   _(flags);
1094 #undef _
1095   /* ASSERT (dst->total_length_not_including_first_buffer == 0); */
1096   /* total_length_not_including_first_buffer is not in the template anymore
1097    * so it may actually not zeroed for some buffers. One option is to
1098    * uncomment the line lower (comes at a cost), the other, is to just  not
1099    * care */
1100   /* dst->total_length_not_including_first_buffer = 0; */
1101   ASSERT (dst->n_add_refs == 0);
1102 }
1103
1104 always_inline void
1105 vlib_buffer_add_to_free_list (vlib_main_t * vm,
1106                               vlib_buffer_free_list_t * f,
1107                               u32 buffer_index, u8 do_init)
1108 {
1109   vlib_buffer_pool_t *bp = vlib_buffer_pool_get (f->buffer_pool_index);
1110   vlib_buffer_t *b;
1111   b = vlib_get_buffer (vm, buffer_index);
1112   if (PREDICT_TRUE (do_init))
1113     vlib_buffer_init_for_free_list (b, f);
1114   vec_add1_aligned (f->buffers, buffer_index, CLIB_CACHE_LINE_BYTES);
1115
1116   if (vec_len (f->buffers) > 4 * VLIB_FRAME_SIZE)
1117     {
1118       clib_spinlock_lock (&bp->lock);
1119       /* keep last stored buffers, as they are more likely hot in the cache */
1120       vec_add_aligned (bp->buffers, f->buffers, VLIB_FRAME_SIZE,
1121                        CLIB_CACHE_LINE_BYTES);
1122       vec_delete (f->buffers, VLIB_FRAME_SIZE, 0);
1123       f->n_alloc -= VLIB_FRAME_SIZE;
1124       clib_spinlock_unlock (&bp->lock);
1125     }
1126 }
1127
1128 #if CLIB_DEBUG > 0
1129 extern u32 *vlib_buffer_state_validation_lock;
1130 extern uword *vlib_buffer_state_validation_hash;
1131 extern void *vlib_buffer_state_heap;
1132 #endif
1133
1134 static inline void
1135 vlib_validate_buffer_in_use (vlib_buffer_t * b, u32 expected)
1136 {
1137 #if CLIB_DEBUG > 0
1138   uword *p;
1139   void *oldheap;
1140
1141   oldheap = clib_mem_set_heap (vlib_buffer_state_heap);
1142
1143   while (__sync_lock_test_and_set (vlib_buffer_state_validation_lock, 1))
1144     ;
1145
1146   p = hash_get (vlib_buffer_state_validation_hash, b);
1147
1148   /* If we don't know about b, declare it to be in the expected state */
1149   if (!p)
1150     {
1151       hash_set (vlib_buffer_state_validation_hash, b, expected);
1152       goto out;
1153     }
1154
1155   if (p[0] != expected)
1156     {
1157       void cj_stop (void);
1158       u32 bi;
1159       vlib_main_t *vm = &vlib_global_main;
1160
1161       cj_stop ();
1162
1163       bi = vlib_get_buffer_index (vm, b);
1164
1165       clib_mem_set_heap (oldheap);
1166       clib_warning ("%.6f buffer %llx (%d): %s, not %s",
1167                     vlib_time_now (vm), bi,
1168                     p[0] ? "busy" : "free", expected ? "busy" : "free");
1169       os_panic ();
1170     }
1171 out:
1172   CLIB_MEMORY_BARRIER ();
1173   *vlib_buffer_state_validation_lock = 0;
1174   clib_mem_set_heap (oldheap);
1175 #endif
1176 }
1177
1178 static inline void
1179 vlib_validate_buffer_set_in_use (vlib_buffer_t * b, u32 expected)
1180 {
1181 #if CLIB_DEBUG > 0
1182   void *oldheap;
1183
1184   oldheap = clib_mem_set_heap (vlib_buffer_state_heap);
1185
1186   while (__sync_lock_test_and_set (vlib_buffer_state_validation_lock, 1))
1187     ;
1188
1189   hash_set (vlib_buffer_state_validation_hash, b, expected);
1190
1191   CLIB_MEMORY_BARRIER ();
1192   *vlib_buffer_state_validation_lock = 0;
1193   clib_mem_set_heap (oldheap);
1194 #endif
1195 }
1196
1197 /** minimum data size of first buffer in a buffer chain */
1198 #define VLIB_BUFFER_CHAIN_MIN_FIRST_DATA_SIZE (256)
1199
1200 /**
1201  * @brief compress buffer chain in a way where the first buffer is at least
1202  * VLIB_BUFFER_CHAIN_MIN_FIRST_DATA_SIZE long
1203  *
1204  * @param[in] vm - vlib_main
1205  * @param[in,out] first - first buffer in chain
1206  * @param[in,out] discard_vector - vector of buffer indexes which were removed
1207  * from the chain
1208  */
1209 always_inline void
1210 vlib_buffer_chain_compress (vlib_main_t * vm,
1211                             vlib_buffer_t * first, u32 ** discard_vector)
1212 {
1213   if (first->current_length >= VLIB_BUFFER_CHAIN_MIN_FIRST_DATA_SIZE ||
1214       !(first->flags & VLIB_BUFFER_NEXT_PRESENT))
1215     {
1216       /* this is already big enough or not a chain */
1217       return;
1218     }
1219   /* probe free list to find allocated buffer size to avoid overfill */
1220   vlib_buffer_free_list_index_t index;
1221   vlib_buffer_free_list_t *free_list =
1222     vlib_buffer_get_buffer_free_list (vm, first, &index);
1223
1224   u32 want_first_size = clib_min (VLIB_BUFFER_CHAIN_MIN_FIRST_DATA_SIZE,
1225                                   free_list->n_data_bytes -
1226                                   first->current_data);
1227   do
1228     {
1229       vlib_buffer_t *second = vlib_get_buffer (vm, first->next_buffer);
1230       u32 need = want_first_size - first->current_length;
1231       u32 amount_to_copy = clib_min (need, second->current_length);
1232       clib_memcpy (((u8 *) vlib_buffer_get_current (first)) +
1233                    first->current_length,
1234                    vlib_buffer_get_current (second), amount_to_copy);
1235       first->current_length += amount_to_copy;
1236       vlib_buffer_advance (second, amount_to_copy);
1237       if (first->flags & VLIB_BUFFER_TOTAL_LENGTH_VALID)
1238         {
1239           first->total_length_not_including_first_buffer -= amount_to_copy;
1240         }
1241       if (!second->current_length)
1242         {
1243           vec_add1 (*discard_vector, first->next_buffer);
1244           if (second->flags & VLIB_BUFFER_NEXT_PRESENT)
1245             {
1246               first->next_buffer = second->next_buffer;
1247             }
1248           else
1249             {
1250               first->flags &= ~VLIB_BUFFER_NEXT_PRESENT;
1251             }
1252           second->flags &= ~VLIB_BUFFER_NEXT_PRESENT;
1253         }
1254     }
1255   while ((first->current_length < want_first_size) &&
1256          (first->flags & VLIB_BUFFER_NEXT_PRESENT));
1257 }
1258
1259 #endif /* included_vlib_buffer_funcs_h */
1260
1261 /*
1262  * fd.io coding-style-patch-verification: ON
1263  *
1264  * Local Variables:
1265  * eval: (c-set-style "gnu")
1266  * End:
1267  */