vlib: 512-bit SIMD version of vlib_buffer_free
[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 #include <vppinfra/fifo.h>
45 #include <vppinfra/vector/index_to_ptr.h>
46 #include <vlib/buffer.h>
47 #include <vlib/physmem_funcs.h>
48 #include <vlib/main.h>
49 #include <vlib/node.h>
50
51 /** \file
52     vlib buffer access methods.
53 */
54
55 typedef void (vlib_buffer_enqueue_to_next_fn_t) (vlib_main_t *vm,
56                                                  vlib_node_runtime_t *node,
57                                                  u32 *buffers, u16 *nexts,
58                                                  uword count);
59 typedef void (vlib_buffer_enqueue_to_next_with_aux_fn_t) (
60   vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u32 *aux_data,
61   u16 *nexts, uword count);
62 typedef void (vlib_buffer_enqueue_to_single_next_fn_t) (
63   vlib_main_t *vm, vlib_node_runtime_t *node, u32 *ers, u16 next_index,
64   u32 count);
65
66 typedef void (vlib_buffer_enqueue_to_single_next_with_aux_fn_t) (
67   vlib_main_t *vm, vlib_node_runtime_t *node, u32 *ers, u32 *aux_data,
68   u16 next_index, u32 count);
69
70 typedef u32 (vlib_buffer_enqueue_to_thread_fn_t) (
71   vlib_main_t *vm, vlib_node_runtime_t *node, u32 frame_queue_index,
72   u32 *buffer_indices, u16 *thread_indices, u32 n_packets,
73   int drop_on_congestion);
74
75 typedef u32 (vlib_buffer_enqueue_to_thread_with_aux_fn_t) (
76   vlib_main_t *vm, vlib_node_runtime_t *node, u32 frame_queue_index,
77   u32 *buffer_indices, u32 *aux, u16 *thread_indices, u32 n_packets,
78   int drop_on_congestion);
79
80 typedef struct
81 {
82   vlib_buffer_enqueue_to_next_fn_t *buffer_enqueue_to_next_fn;
83   vlib_buffer_enqueue_to_next_with_aux_fn_t
84     *buffer_enqueue_to_next_with_aux_fn;
85   vlib_buffer_enqueue_to_single_next_fn_t *buffer_enqueue_to_single_next_fn;
86   vlib_buffer_enqueue_to_single_next_with_aux_fn_t
87     *buffer_enqueue_to_single_next_with_aux_fn;
88   vlib_buffer_enqueue_to_thread_fn_t *buffer_enqueue_to_thread_fn;
89   vlib_buffer_enqueue_to_thread_with_aux_fn_t
90     *buffer_enqueue_to_thread_with_aux_fn;
91 } vlib_buffer_func_main_t;
92
93 extern vlib_buffer_func_main_t vlib_buffer_func_main;
94
95 always_inline void
96 vlib_buffer_validate (vlib_main_t * vm, vlib_buffer_t * b)
97 {
98   vlib_buffer_main_t *bm = vm->buffer_main;
99   vlib_buffer_pool_t *bp;
100
101   /* reference count in allocated buffer always must be 1 or higher */
102   ASSERT (b->ref_count > 0);
103
104   /* verify that buffer pool index is valid */
105   bp = vec_elt_at_index (bm->buffer_pools, b->buffer_pool_index);
106   ASSERT (pointer_to_uword (b) >= bp->start);
107   ASSERT (pointer_to_uword (b) < bp->start + bp->size -
108           (bp->data_size + sizeof (vlib_buffer_t)));
109 }
110
111 always_inline void *
112 vlib_buffer_ptr_from_index (uword buffer_mem_start, u32 buffer_index,
113                             uword offset)
114 {
115   offset += ((uword) buffer_index) << CLIB_LOG2_CACHE_LINE_BYTES;
116   return uword_to_pointer (buffer_mem_start + offset, vlib_buffer_t *);
117 }
118
119 /** \brief Translate buffer index into buffer pointer
120
121     @param vm - (vlib_main_t *) vlib main data structure pointer
122     @param buffer_index - (u32) buffer index
123     @return - (vlib_buffer_t *) buffer pointer
124 */
125 always_inline vlib_buffer_t *
126 vlib_get_buffer (vlib_main_t * vm, u32 buffer_index)
127 {
128   vlib_buffer_main_t *bm = vm->buffer_main;
129   vlib_buffer_t *b;
130
131   b = vlib_buffer_ptr_from_index (bm->buffer_mem_start, buffer_index, 0);
132   vlib_buffer_validate (vm, b);
133   return b;
134 }
135
136 static_always_inline u32
137 vlib_buffer_get_default_data_size (vlib_main_t * vm)
138 {
139   return vm->buffer_main->default_data_size;
140 }
141
142 static_always_inline void
143 vlib_buffer_copy_indices (u32 * dst, u32 * src, u32 n_indices)
144 {
145   clib_memcpy_u32 (dst, src, n_indices);
146 }
147
148 always_inline void
149 vlib_buffer_copy_indices_from_ring (u32 * dst, u32 * ring, u32 start,
150                                     u32 ring_size, u32 n_buffers)
151 {
152   ASSERT (n_buffers <= ring_size);
153
154   if (PREDICT_TRUE (start + n_buffers <= ring_size))
155     {
156       vlib_buffer_copy_indices (dst, ring + start, n_buffers);
157     }
158   else
159     {
160       u32 n = ring_size - start;
161       vlib_buffer_copy_indices (dst, ring + start, n);
162       vlib_buffer_copy_indices (dst + n, ring, n_buffers - n);
163     }
164 }
165
166 always_inline void
167 vlib_buffer_copy_indices_to_ring (u32 * ring, u32 * src, u32 start,
168                                   u32 ring_size, u32 n_buffers)
169 {
170   ASSERT (n_buffers <= ring_size);
171
172   if (PREDICT_TRUE (start + n_buffers <= ring_size))
173     {
174       vlib_buffer_copy_indices (ring + start, src, n_buffers);
175     }
176   else
177     {
178       u32 n = ring_size - start;
179       vlib_buffer_copy_indices (ring + start, src, n);
180       vlib_buffer_copy_indices (ring, src + n, n_buffers - n);
181     }
182 }
183
184 STATIC_ASSERT_OFFSET_OF (vlib_buffer_t, template_end, 64);
185 static_always_inline void
186 vlib_buffer_copy_template (vlib_buffer_t * b, vlib_buffer_t * bt)
187 {
188 #if defined CLIB_HAVE_VEC512
189   b->as_u8x64[0] = bt->as_u8x64[0];
190 #elif defined (CLIB_HAVE_VEC256)
191   b->as_u8x32[0] = bt->as_u8x32[0];
192   b->as_u8x32[1] = bt->as_u8x32[1];
193 #elif defined (CLIB_HAVE_VEC128)
194   b->as_u8x16[0] = bt->as_u8x16[0];
195   b->as_u8x16[1] = bt->as_u8x16[1];
196   b->as_u8x16[2] = bt->as_u8x16[2];
197   b->as_u8x16[3] = bt->as_u8x16[3];
198 #else
199   clib_memcpy_fast (b, bt, 64);
200 #endif
201 }
202
203 always_inline u8
204 vlib_buffer_pool_get_default_for_numa (vlib_main_t * vm, u32 numa_node)
205 {
206   ASSERT (numa_node < VLIB_BUFFER_MAX_NUMA_NODES);
207   return vm->buffer_main->default_buffer_pool_index_for_numa[numa_node];
208 }
209
210 /** \brief Translate array of buffer indices into buffer pointers with offset
211
212     @param vm - (vlib_main_t *) vlib main data structure pointer
213     @param bi - (u32 *) array of buffer indices
214     @param b - (void **) array to store buffer pointers
215     @param count - (uword) number of elements
216     @param offset - (i32) offset applied to each pointer
217 */
218 static_always_inline void
219 vlib_get_buffers_with_offset (vlib_main_t *vm, u32 *bi, void **b, u32 count,
220                               i32 offset)
221 {
222   uword buffer_mem_start = vm->buffer_main->buffer_mem_start;
223   void *base = (void *) (buffer_mem_start + offset);
224   int objsize = __builtin_object_size (b, 0);
225   const int sh = CLIB_LOG2_CACHE_LINE_BYTES;
226
227   if (COMPILE_TIME_CONST (count) == 0 && objsize >= 64 * sizeof (b[0]) &&
228       (objsize & ((8 * sizeof (b[0])) - 1)) == 0)
229     {
230       u32 n = round_pow2 (count, 8);
231       ASSERT (objsize >= count);
232       CLIB_ASSUME (objsize >= count);
233       while (n >= 64)
234         {
235           clib_index_to_ptr_u32 (bi, base, sh, b, 64);
236           b += 64;
237           bi += 64;
238           n -= 64;
239         }
240
241       while (n)
242         {
243           clib_index_to_ptr_u32 (bi, base, sh, b, 8);
244           b += 8;
245           bi += 8;
246           n -= 8;
247         }
248     }
249   else
250     clib_index_to_ptr_u32 (bi, base, sh, b, count);
251 }
252
253 /** \brief Translate array of buffer indices into buffer pointers
254
255     @param vm - (vlib_main_t *) vlib main data structure pointer
256     @param bi - (u32 *) array of buffer indices
257     @param b - (vlib_buffer_t **) array to store buffer pointers
258     @param count - (uword) number of elements
259 */
260
261 static_always_inline void
262 vlib_get_buffers (vlib_main_t *vm, u32 *bi, vlib_buffer_t **b, u32 count)
263 {
264   vlib_get_buffers_with_offset (vm, bi, (void **) b, count, 0);
265 }
266
267 /** \brief Translate buffer pointer into buffer index
268
269     @param vm - (vlib_main_t *) vlib main data structure pointer
270     @param p - (void *) buffer pointer
271     @return - (u32) buffer index
272 */
273
274 always_inline u32
275 vlib_get_buffer_index (vlib_main_t * vm, void *p)
276 {
277   vlib_buffer_main_t *bm = vm->buffer_main;
278   uword offset = pointer_to_uword (p) - bm->buffer_mem_start;
279   ASSERT (pointer_to_uword (p) >= bm->buffer_mem_start);
280   ASSERT (offset < bm->buffer_mem_size);
281   ASSERT ((offset % (1 << CLIB_LOG2_CACHE_LINE_BYTES)) == 0);
282   return offset >> CLIB_LOG2_CACHE_LINE_BYTES;
283 }
284
285 /** \brief Translate array of buffer pointers into buffer indices with offset
286
287     @param vm - (vlib_main_t *) vlib main data structure pointer
288     @param b - (void **) array of buffer pointers
289     @param bi - (u32 *) array to store buffer indices
290     @param count - (uword) number of elements
291     @param offset - (i32) offset applied to each pointer
292 */
293 static_always_inline void
294 vlib_get_buffer_indices_with_offset (vlib_main_t * vm, void **b, u32 * bi,
295                                      uword count, i32 offset)
296 {
297 #ifdef CLIB_HAVE_VEC256
298   u32x8 mask = { 0, 2, 4, 6, 1, 3, 5, 7 };
299   u64x4 off4 = u64x4_splat (vm->buffer_main->buffer_mem_start - offset);
300
301   while (count >= 8)
302     {
303       /* load 4 pointers into 256-bit register */
304       u64x4 v0 = u64x4_load_unaligned (b);
305       u64x4 v1 = u64x4_load_unaligned (b + 4);
306       u32x8 v2, v3;
307
308       v0 -= off4;
309       v1 -= off4;
310
311       v0 >>= CLIB_LOG2_CACHE_LINE_BYTES;
312       v1 >>= CLIB_LOG2_CACHE_LINE_BYTES;
313
314       /* permute 256-bit register so lower u32s of each buffer index are
315        * placed into lower 128-bits */
316       v2 = u32x8_permute ((u32x8) v0, mask);
317       v3 = u32x8_permute ((u32x8) v1, mask);
318
319       /* extract lower 128-bits and save them to the array of buffer indices */
320       u32x4_store_unaligned (u32x8_extract_lo (v2), bi);
321       u32x4_store_unaligned (u32x8_extract_lo (v3), bi + 4);
322       bi += 8;
323       b += 8;
324       count -= 8;
325     }
326 #endif
327   while (count >= 4)
328     {
329       /* equivalent non-nector implementation */
330       bi[0] = vlib_get_buffer_index (vm, ((u8 *) b[0]) + offset);
331       bi[1] = vlib_get_buffer_index (vm, ((u8 *) b[1]) + offset);
332       bi[2] = vlib_get_buffer_index (vm, ((u8 *) b[2]) + offset);
333       bi[3] = vlib_get_buffer_index (vm, ((u8 *) b[3]) + offset);
334       bi += 4;
335       b += 4;
336       count -= 4;
337     }
338   while (count)
339     {
340       bi[0] = vlib_get_buffer_index (vm, ((u8 *) b[0]) + offset);
341       bi += 1;
342       b += 1;
343       count -= 1;
344     }
345 }
346
347 /** \brief Translate array of buffer pointers into buffer indices
348
349     @param vm - (vlib_main_t *) vlib main data structure pointer
350     @param b - (vlib_buffer_t **) array of buffer pointers
351     @param bi - (u32 *) array to store buffer indices
352     @param count - (uword) number of elements
353 */
354 static_always_inline void
355 vlib_get_buffer_indices (vlib_main_t * vm, vlib_buffer_t ** b, u32 * bi,
356                          uword count)
357 {
358   vlib_get_buffer_indices_with_offset (vm, (void **) b, bi, count, 0);
359 }
360
361 /** \brief Get next buffer in buffer linklist, or zero for end of list.
362
363     @param vm - (vlib_main_t *) vlib main data structure pointer
364     @param b - (void *) buffer pointer
365     @return - (vlib_buffer_t *) next buffer, or NULL
366 */
367 always_inline vlib_buffer_t *
368 vlib_get_next_buffer (vlib_main_t * vm, vlib_buffer_t * b)
369 {
370   return (b->flags & VLIB_BUFFER_NEXT_PRESENT
371           ? vlib_get_buffer (vm, b->next_buffer) : 0);
372 }
373
374 uword vlib_buffer_length_in_chain_slow_path (vlib_main_t * vm,
375                                              vlib_buffer_t * b_first);
376
377 /** \brief Get length in bytes of the buffer chain
378
379     @param vm - (vlib_main_t *) vlib main data structure pointer
380     @param b - (void *) buffer pointer
381     @return - (uword) length of buffer chain
382 */
383 always_inline uword
384 vlib_buffer_length_in_chain (vlib_main_t * vm, vlib_buffer_t * b)
385 {
386   uword len = b->current_length;
387
388   if (PREDICT_TRUE ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0))
389     return len;
390
391   if (PREDICT_TRUE (b->flags & VLIB_BUFFER_TOTAL_LENGTH_VALID))
392     return len + b->total_length_not_including_first_buffer;
393
394   return vlib_buffer_length_in_chain_slow_path (vm, b);
395 }
396
397 /** \brief Get length in bytes of the buffer index buffer chain
398
399     @param vm - (vlib_main_t *) vlib main data structure pointer
400     @param bi - (u32) buffer index
401     @return - (uword) length of buffer chain
402 */
403 always_inline uword
404 vlib_buffer_index_length_in_chain (vlib_main_t * vm, u32 bi)
405 {
406   vlib_buffer_t *b = vlib_get_buffer (vm, bi);
407   return vlib_buffer_length_in_chain (vm, b);
408 }
409
410 /** \brief Copy buffer contents to memory
411
412     @param vm - (vlib_main_t *) vlib main data structure pointer
413     @param buffer_index - (u32) buffer index
414     @param contents - (u8 *) memory, <strong>must be large enough</strong>
415     @return - (uword) length of buffer chain
416 */
417 always_inline uword
418 vlib_buffer_contents (vlib_main_t * vm, u32 buffer_index, u8 * contents)
419 {
420   uword content_len = 0;
421   uword l;
422   vlib_buffer_t *b;
423
424   while (1)
425     {
426       b = vlib_get_buffer (vm, buffer_index);
427       l = b->current_length;
428       clib_memcpy_fast (contents + content_len, b->data + b->current_data, l);
429       content_len += l;
430       if (!(b->flags & VLIB_BUFFER_NEXT_PRESENT))
431         break;
432       buffer_index = b->next_buffer;
433     }
434
435   return content_len;
436 }
437
438 always_inline uword
439 vlib_buffer_get_pa (vlib_main_t * vm, vlib_buffer_t * b)
440 {
441   return vlib_physmem_get_pa (vm, b->data);
442 }
443
444 always_inline uword
445 vlib_buffer_get_current_pa (vlib_main_t * vm, vlib_buffer_t * b)
446 {
447   return vlib_buffer_get_pa (vm, b) + b->current_data;
448 }
449
450 /** \brief Prefetch buffer metadata by buffer index
451     The first 64 bytes of buffer contains most header information
452
453     @param vm - (vlib_main_t *) vlib main data structure pointer
454     @param bi - (u32) buffer index
455     @param type - LOAD, STORE. In most cases, STORE is the right answer
456 */
457 /* Prefetch buffer header given index. */
458 #define vlib_prefetch_buffer_with_index(vm,bi,type)     \
459   do {                                                  \
460     vlib_buffer_t * _b = vlib_get_buffer (vm, bi);      \
461     vlib_prefetch_buffer_header (_b, type);             \
462   } while (0)
463
464 typedef enum
465 {
466   /* Index is unknown. */
467   VLIB_BUFFER_UNKNOWN,
468
469   /* Index is known and free/allocated. */
470   VLIB_BUFFER_KNOWN_FREE,
471   VLIB_BUFFER_KNOWN_ALLOCATED,
472 } vlib_buffer_known_state_t;
473
474 void vlib_buffer_validate_alloc_free (vlib_main_t * vm, u32 * buffers,
475                                       uword n_buffers,
476                                       vlib_buffer_known_state_t
477                                       expected_state);
478
479 always_inline vlib_buffer_known_state_t
480 vlib_buffer_is_known (vlib_main_t * vm, u32 buffer_index)
481 {
482   vlib_buffer_main_t *bm = vm->buffer_main;
483
484   clib_spinlock_lock (&bm->buffer_known_hash_lockp);
485   uword *p = hash_get (bm->buffer_known_hash, buffer_index);
486   clib_spinlock_unlock (&bm->buffer_known_hash_lockp);
487   return p ? p[0] : VLIB_BUFFER_UNKNOWN;
488 }
489
490 /* Validates sanity of a single buffer.
491    Returns format'ed vector with error message if any. */
492 u8 *vlib_validate_buffer (vlib_main_t * vm, u32 buffer_index,
493                           uword follow_chain);
494
495 u8 *vlib_validate_buffers (vlib_main_t * vm,
496                            u32 * buffers,
497                            uword next_buffer_stride,
498                            uword n_buffers,
499                            vlib_buffer_known_state_t known_state,
500                            uword follow_buffer_next);
501
502 static_always_inline vlib_buffer_pool_t *
503 vlib_get_buffer_pool (vlib_main_t * vm, u8 buffer_pool_index)
504 {
505   vlib_buffer_main_t *bm = vm->buffer_main;
506   return vec_elt_at_index (bm->buffer_pools, buffer_pool_index);
507 }
508
509 static_always_inline __clib_warn_unused_result uword
510 vlib_buffer_pool_get (vlib_main_t * vm, u8 buffer_pool_index, u32 * buffers,
511                       u32 n_buffers)
512 {
513   vlib_buffer_pool_t *bp = vlib_get_buffer_pool (vm, buffer_pool_index);
514   u32 len;
515
516   ASSERT (bp->buffers);
517
518   clib_spinlock_lock (&bp->lock);
519   len = bp->n_avail;
520   if (PREDICT_TRUE (n_buffers < len))
521     {
522       len -= n_buffers;
523       vlib_buffer_copy_indices (buffers, bp->buffers + len, n_buffers);
524       bp->n_avail = len;
525       clib_spinlock_unlock (&bp->lock);
526       return n_buffers;
527     }
528   else
529     {
530       vlib_buffer_copy_indices (buffers, bp->buffers, len);
531       bp->n_avail = 0;
532       clib_spinlock_unlock (&bp->lock);
533       return len;
534     }
535 }
536
537
538 /** \brief Allocate buffers from specific pool into supplied array
539
540     @param vm - (vlib_main_t *) vlib main data structure pointer
541     @param buffers - (u32 * ) buffer index array
542     @param n_buffers - (u32) number of buffers requested
543     @return - (u32) number of buffers actually allocated, may be
544     less than the number requested or zero
545 */
546
547 always_inline __clib_warn_unused_result u32
548 vlib_buffer_alloc_from_pool (vlib_main_t * vm, u32 * buffers, u32 n_buffers,
549                              u8 buffer_pool_index)
550 {
551   vlib_buffer_main_t *bm = vm->buffer_main;
552   vlib_buffer_pool_t *bp;
553   vlib_buffer_pool_thread_t *bpt;
554   u32 *src, *dst, len, n_left;
555
556   /* If buffer allocation fault injection is configured */
557   if (VLIB_BUFFER_ALLOC_FAULT_INJECTOR > 0)
558     {
559       u32 vlib_buffer_alloc_may_fail (vlib_main_t *, u32);
560
561       /* See how many buffers we're willing to allocate */
562       n_buffers = vlib_buffer_alloc_may_fail (vm, n_buffers);
563       if (n_buffers == 0)
564         return (n_buffers);
565     }
566
567   bp = vec_elt_at_index (bm->buffer_pools, buffer_pool_index);
568   bpt = vec_elt_at_index (bp->threads, vm->thread_index);
569
570   dst = buffers;
571   n_left = n_buffers;
572   len = bpt->n_cached;
573
574   /* per-thread cache contains enough buffers */
575   if (len >= n_buffers)
576     {
577       src = bpt->cached_buffers + len - n_buffers;
578       vlib_buffer_copy_indices (dst, src, n_buffers);
579       bpt->n_cached -= n_buffers;
580       goto done;
581     }
582
583   /* alloc bigger than cache - take buffers directly from main pool */
584   if (n_buffers >= VLIB_BUFFER_POOL_PER_THREAD_CACHE_SZ)
585     {
586       n_buffers = vlib_buffer_pool_get (vm, buffer_pool_index, buffers,
587                                         n_buffers);
588       goto done;
589     }
590
591   /* take everything available in the cache */
592   if (len)
593     {
594       vlib_buffer_copy_indices (dst, bpt->cached_buffers, len);
595       bpt->n_cached = 0;
596       dst += len;
597       n_left -= len;
598     }
599
600   len = round_pow2 (n_left, 32);
601   len = vlib_buffer_pool_get (vm, buffer_pool_index, bpt->cached_buffers,
602                               len);
603   bpt->n_cached = len;
604
605   if (len)
606     {
607       u32 n_copy = clib_min (len, n_left);
608       src = bpt->cached_buffers + len - n_copy;
609       vlib_buffer_copy_indices (dst, src, n_copy);
610       bpt->n_cached -= n_copy;
611       n_left -= n_copy;
612     }
613
614   n_buffers -= n_left;
615
616 done:
617   /* Verify that buffers are known free. */
618   if (CLIB_DEBUG > 0)
619     vlib_buffer_validate_alloc_free (vm, buffers, n_buffers,
620                                      VLIB_BUFFER_KNOWN_FREE);
621   if (PREDICT_FALSE (bm->alloc_callback_fn != 0))
622     bm->alloc_callback_fn (vm, buffer_pool_index, buffers, n_buffers);
623   return n_buffers;
624 }
625
626 /** \brief Allocate buffers from specific numa node into supplied array
627
628     @param vm - (vlib_main_t *) vlib main data structure pointer
629     @param buffers - (u32 * ) buffer index array
630     @param n_buffers - (u32) number of buffers requested
631     @param numa_node - (u32) numa node
632     @return - (u32) number of buffers actually allocated, may be
633     less than the number requested or zero
634 */
635 always_inline __clib_warn_unused_result u32
636 vlib_buffer_alloc_on_numa (vlib_main_t * vm, u32 * buffers, u32 n_buffers,
637                            u32 numa_node)
638 {
639   u8 index = vlib_buffer_pool_get_default_for_numa (vm, numa_node);
640   return vlib_buffer_alloc_from_pool (vm, buffers, n_buffers, index);
641 }
642
643 /** \brief Allocate buffers into supplied array
644
645     @param vm - (vlib_main_t *) vlib main data structure pointer
646     @param buffers - (u32 * ) buffer index array
647     @param n_buffers - (u32) number of buffers requested
648     @return - (u32) number of buffers actually allocated, may be
649     less than the number requested or zero
650 */
651
652 always_inline __clib_warn_unused_result u32
653 vlib_buffer_alloc (vlib_main_t * vm, u32 * buffers, u32 n_buffers)
654 {
655   return vlib_buffer_alloc_on_numa (vm, buffers, n_buffers, vm->numa_node);
656 }
657
658 /** \brief Allocate buffers into ring
659
660     @param vm - (vlib_main_t *) vlib main data structure pointer
661     @param buffers - (u32 * ) buffer index ring
662     @param start - (u32) first slot in the ring
663     @param ring_size - (u32) ring size
664     @param n_buffers - (u32) number of buffers requested
665     @return - (u32) number of buffers actually allocated, may be
666     less than the number requested or zero
667 */
668 always_inline __clib_warn_unused_result u32
669 vlib_buffer_alloc_to_ring (vlib_main_t * vm, u32 * ring, u32 start,
670                            u32 ring_size, u32 n_buffers)
671 {
672   u32 n_alloc;
673
674   ASSERT (n_buffers <= ring_size);
675
676   if (PREDICT_TRUE (start + n_buffers <= ring_size))
677     return vlib_buffer_alloc (vm, ring + start, n_buffers);
678
679   n_alloc = vlib_buffer_alloc (vm, ring + start, ring_size - start);
680
681   if (PREDICT_TRUE (n_alloc == ring_size - start))
682     n_alloc += vlib_buffer_alloc (vm, ring, n_buffers - n_alloc);
683
684   return n_alloc;
685 }
686
687 /** \brief Allocate buffers into ring from specific buffer pool
688
689     @param vm - (vlib_main_t *) vlib main data structure pointer
690     @param buffers - (u32 * ) buffer index ring
691     @param start - (u32) first slot in the ring
692     @param ring_size - (u32) ring size
693     @param n_buffers - (u32) number of buffers requested
694     @return - (u32) number of buffers actually allocated, may be
695     less than the number requested or zero
696 */
697 always_inline __clib_warn_unused_result u32
698 vlib_buffer_alloc_to_ring_from_pool (vlib_main_t * vm, u32 * ring, u32 start,
699                                      u32 ring_size, u32 n_buffers,
700                                      u8 buffer_pool_index)
701 {
702   u32 n_alloc;
703
704   ASSERT (n_buffers <= ring_size);
705
706   if (PREDICT_TRUE (start + n_buffers <= ring_size))
707     return vlib_buffer_alloc_from_pool (vm, ring + start, n_buffers,
708                                         buffer_pool_index);
709
710   n_alloc = vlib_buffer_alloc_from_pool (vm, ring + start, ring_size - start,
711                                          buffer_pool_index);
712
713   if (PREDICT_TRUE (n_alloc == ring_size - start))
714     n_alloc += vlib_buffer_alloc_from_pool (vm, ring, n_buffers - n_alloc,
715                                             buffer_pool_index);
716
717   return n_alloc;
718 }
719
720 static_always_inline void
721 vlib_buffer_pool_put (vlib_main_t * vm, u8 buffer_pool_index,
722                       u32 * buffers, u32 n_buffers)
723 {
724   vlib_buffer_main_t *bm = vm->buffer_main;
725   vlib_buffer_pool_t *bp = vlib_get_buffer_pool (vm, buffer_pool_index);
726   vlib_buffer_pool_thread_t *bpt = vec_elt_at_index (bp->threads,
727                                                      vm->thread_index);
728   u32 n_cached, n_empty;
729
730   if (CLIB_DEBUG > 0)
731     vlib_buffer_validate_alloc_free (vm, buffers, n_buffers,
732                                      VLIB_BUFFER_KNOWN_ALLOCATED);
733   if (PREDICT_FALSE (bm->free_callback_fn != 0))
734     bm->free_callback_fn (vm, buffer_pool_index, buffers, n_buffers);
735
736   n_cached = bpt->n_cached;
737   n_empty = VLIB_BUFFER_POOL_PER_THREAD_CACHE_SZ - n_cached;
738   if (n_buffers <= n_empty)
739     {
740       vlib_buffer_copy_indices (bpt->cached_buffers + n_cached,
741                                 buffers, n_buffers);
742       bpt->n_cached = n_cached + n_buffers;
743       return;
744     }
745
746   vlib_buffer_copy_indices (bpt->cached_buffers + n_cached,
747                             buffers + n_buffers - n_empty, n_empty);
748   bpt->n_cached = VLIB_BUFFER_POOL_PER_THREAD_CACHE_SZ;
749
750   clib_spinlock_lock (&bp->lock);
751   vlib_buffer_copy_indices (bp->buffers + bp->n_avail, buffers,
752                             n_buffers - n_empty);
753   bp->n_avail += n_buffers - n_empty;
754   clib_spinlock_unlock (&bp->lock);
755 }
756
757 static_always_inline void
758 vlib_buffer_free_inline (vlib_main_t * vm, u32 * buffers, u32 n_buffers,
759                          int maybe_next)
760 {
761   const int queue_size = 128;
762   vlib_buffer_pool_t *bp = 0;
763   u8 buffer_pool_index = ~0;
764   u32 n_queue = 0, queue[queue_size + 4];
765   vlib_buffer_t bt = { };
766 #if defined(CLIB_HAVE_VEC128)
767   vlib_buffer_t bpi_mask = {.buffer_pool_index = ~0 };
768   vlib_buffer_t bpi_vec = {};
769   vlib_buffer_t flags_refs_mask = {
770     .flags = VLIB_BUFFER_NEXT_PRESENT,
771     .ref_count = ~1
772   };
773 #endif
774
775   if (PREDICT_FALSE (n_buffers == 0))
776     return;
777
778   vlib_buffer_t *b = vlib_get_buffer (vm, buffers[0]);
779   buffer_pool_index = b->buffer_pool_index;
780   bp = vlib_get_buffer_pool (vm, buffer_pool_index);
781   vlib_buffer_copy_template (&bt, &bp->buffer_template);
782 #if defined(CLIB_HAVE_VEC128)
783   bpi_vec.buffer_pool_index = buffer_pool_index;
784 #endif
785
786   while (n_buffers)
787     {
788       vlib_buffer_t *b[8];
789       u32 bi, sum = 0, flags, next;
790
791 #if defined(CLIB_HAVE_VEC512)
792       if (n_buffers < 8)
793 #else
794       if (n_buffers < 4)
795 #endif
796         goto one_by_one;
797
798 #if defined(CLIB_HAVE_VEC512)
799       vlib_get_buffers (vm, buffers, b, 8);
800 #else
801       vlib_get_buffers (vm, buffers, b, 4);
802
803       if (n_buffers >= 12)
804         {
805           vlib_get_buffers (vm, buffers + 8, b + 4, 4);
806           vlib_prefetch_buffer_header (b[4], LOAD);
807           vlib_prefetch_buffer_header (b[5], LOAD);
808           vlib_prefetch_buffer_header (b[6], LOAD);
809           vlib_prefetch_buffer_header (b[7], LOAD);
810         }
811 #endif
812
813 #if defined(CLIB_HAVE_VEC512)
814       u8x16 p0, p1, p2, p3, p4, p5, p6, p7, r;
815       p0 = u8x16_load_unaligned (b[0]);
816       p1 = u8x16_load_unaligned (b[1]);
817       p2 = u8x16_load_unaligned (b[2]);
818       p3 = u8x16_load_unaligned (b[3]);
819       p4 = u8x16_load_unaligned (b[4]);
820       p5 = u8x16_load_unaligned (b[5]);
821       p6 = u8x16_load_unaligned (b[6]);
822       p7 = u8x16_load_unaligned (b[7]);
823
824       r = p0 ^ bpi_vec.as_u8x16[0];
825       r |= p1 ^ bpi_vec.as_u8x16[0];
826       r |= p2 ^ bpi_vec.as_u8x16[0];
827       r |= p3 ^ bpi_vec.as_u8x16[0];
828       r |= p4 ^ bpi_vec.as_u8x16[0];
829       r |= p5 ^ bpi_vec.as_u8x16[0];
830       r |= p6 ^ bpi_vec.as_u8x16[0];
831       r |= p7 ^ bpi_vec.as_u8x16[0];
832       r &= bpi_mask.as_u8x16[0];
833       r |=
834         (p0 | p1 | p2 | p3 | p4 | p5 | p6 | p7) & flags_refs_mask.as_u8x16[0];
835
836       sum = !u8x16_is_all_zero (r);
837 #elif defined(CLIB_HAVE_VEC128)
838       u8x16 p0, p1, p2, p3, r;
839       p0 = u8x16_load_unaligned (b[0]);
840       p1 = u8x16_load_unaligned (b[1]);
841       p2 = u8x16_load_unaligned (b[2]);
842       p3 = u8x16_load_unaligned (b[3]);
843
844       r = p0 ^ bpi_vec.as_u8x16[0];
845       r |= p1 ^ bpi_vec.as_u8x16[0];
846       r |= p2 ^ bpi_vec.as_u8x16[0];
847       r |= p3 ^ bpi_vec.as_u8x16[0];
848       r &= bpi_mask.as_u8x16[0];
849       r |= (p0 | p1 | p2 | p3) & flags_refs_mask.as_u8x16[0];
850
851       sum = !u8x16_is_all_zero (r);
852 #else
853       sum |= b[0]->flags;
854       sum |= b[1]->flags;
855       sum |= b[2]->flags;
856       sum |= b[3]->flags;
857       sum &= VLIB_BUFFER_NEXT_PRESENT;
858       sum += b[0]->ref_count - 1;
859       sum += b[1]->ref_count - 1;
860       sum += b[2]->ref_count - 1;
861       sum += b[3]->ref_count - 1;
862       sum |= b[0]->buffer_pool_index ^ buffer_pool_index;
863       sum |= b[1]->buffer_pool_index ^ buffer_pool_index;
864       sum |= b[2]->buffer_pool_index ^ buffer_pool_index;
865       sum |= b[3]->buffer_pool_index ^ buffer_pool_index;
866 #endif
867
868       if (sum)
869         goto one_by_one;
870
871 #if defined(CLIB_HAVE_VEC512)
872       vlib_buffer_copy_indices (queue + n_queue, buffers, 8);
873       vlib_buffer_copy_template (b[0], &bt);
874       vlib_buffer_copy_template (b[1], &bt);
875       vlib_buffer_copy_template (b[2], &bt);
876       vlib_buffer_copy_template (b[3], &bt);
877       vlib_buffer_copy_template (b[4], &bt);
878       vlib_buffer_copy_template (b[5], &bt);
879       vlib_buffer_copy_template (b[6], &bt);
880       vlib_buffer_copy_template (b[7], &bt);
881       n_queue += 8;
882
883       vlib_buffer_validate (vm, b[0]);
884       vlib_buffer_validate (vm, b[1]);
885       vlib_buffer_validate (vm, b[2]);
886       vlib_buffer_validate (vm, b[3]);
887       vlib_buffer_validate (vm, b[4]);
888       vlib_buffer_validate (vm, b[5]);
889       vlib_buffer_validate (vm, b[6]);
890       vlib_buffer_validate (vm, b[7]);
891
892       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[0]);
893       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[1]);
894       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[2]);
895       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[3]);
896       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[4]);
897       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[5]);
898       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[6]);
899       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[7]);
900 #else
901       vlib_buffer_copy_indices (queue + n_queue, buffers, 4);
902       vlib_buffer_copy_template (b[0], &bt);
903       vlib_buffer_copy_template (b[1], &bt);
904       vlib_buffer_copy_template (b[2], &bt);
905       vlib_buffer_copy_template (b[3], &bt);
906       n_queue += 4;
907
908       vlib_buffer_validate (vm, b[0]);
909       vlib_buffer_validate (vm, b[1]);
910       vlib_buffer_validate (vm, b[2]);
911       vlib_buffer_validate (vm, b[3]);
912
913       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[0]);
914       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[1]);
915       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[2]);
916       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[3]);
917 #endif
918
919       if (n_queue >= queue_size)
920         {
921           vlib_buffer_pool_put (vm, buffer_pool_index, queue, n_queue);
922           n_queue = 0;
923         }
924 #if defined(CLIB_HAVE_VEC512)
925       buffers += 8;
926       n_buffers -= 8;
927 #else
928       buffers += 4;
929       n_buffers -= 4;
930 #endif
931       continue;
932
933     one_by_one:
934       bi = buffers[0];
935
936     next_in_chain:
937       b[0] = vlib_get_buffer (vm, bi);
938       flags = b[0]->flags;
939       next = b[0]->next_buffer;
940
941       if (PREDICT_FALSE (buffer_pool_index != b[0]->buffer_pool_index))
942         {
943
944           if (n_queue)
945             {
946               vlib_buffer_pool_put (vm, buffer_pool_index, queue, n_queue);
947               n_queue = 0;
948             }
949
950           buffer_pool_index = b[0]->buffer_pool_index;
951 #if defined(CLIB_HAVE_VEC128)
952           bpi_vec.buffer_pool_index = buffer_pool_index;
953 #endif
954           bp = vlib_get_buffer_pool (vm, buffer_pool_index);
955           vlib_buffer_copy_template (&bt, &bp->buffer_template);
956         }
957
958       vlib_buffer_validate (vm, b[0]);
959
960       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[0]);
961
962       if (clib_atomic_sub_fetch (&b[0]->ref_count, 1) == 0)
963         {
964           vlib_buffer_copy_template (b[0], &bt);
965           queue[n_queue++] = bi;
966         }
967
968       if (n_queue == queue_size)
969         {
970           vlib_buffer_pool_put (vm, buffer_pool_index, queue, queue_size);
971           n_queue = 0;
972         }
973
974       if (maybe_next && (flags & VLIB_BUFFER_NEXT_PRESENT))
975         {
976           bi = next;
977           goto next_in_chain;
978         }
979
980       buffers++;
981       n_buffers--;
982     }
983
984   if (n_queue)
985     vlib_buffer_pool_put (vm, buffer_pool_index, queue, n_queue);
986 }
987
988
989 /** \brief Free buffers
990     Frees the entire buffer chain for each buffer
991
992     @param vm - (vlib_main_t *) vlib main data structure pointer
993     @param buffers - (u32 * ) buffer index array
994     @param n_buffers - (u32) number of buffers to free
995
996 */
997 always_inline void
998 vlib_buffer_free (vlib_main_t * vm,
999                   /* pointer to first buffer */
1000                   u32 * buffers,
1001                   /* number of buffers to free */
1002                   u32 n_buffers)
1003 {
1004   vlib_buffer_free_inline (vm, buffers, n_buffers, /* maybe next */ 1);
1005 }
1006
1007 /** \brief Free buffers, does not free the buffer chain for each buffer
1008
1009     @param vm - (vlib_main_t *) vlib main data structure pointer
1010     @param buffers - (u32 * ) buffer index array
1011     @param n_buffers - (u32) number of buffers to free
1012
1013 */
1014 always_inline void
1015 vlib_buffer_free_no_next (vlib_main_t * vm,
1016                           /* pointer to first buffer */
1017                           u32 * buffers,
1018                           /* number of buffers to free */
1019                           u32 n_buffers)
1020 {
1021   vlib_buffer_free_inline (vm, buffers, n_buffers, /* maybe next */ 0);
1022 }
1023
1024 /** \brief Free one buffer
1025     Shorthand to free a single buffer chain.
1026
1027     @param vm - (vlib_main_t *) vlib main data structure pointer
1028     @param buffer_index - (u32) buffer index to free
1029 */
1030 always_inline void
1031 vlib_buffer_free_one (vlib_main_t * vm, u32 buffer_index)
1032 {
1033   vlib_buffer_free_inline (vm, &buffer_index, 1, /* maybe next */ 1);
1034 }
1035
1036 /** \brief Free buffers from ring
1037
1038     @param vm - (vlib_main_t *) vlib main data structure pointer
1039     @param buffers - (u32 * ) buffer index ring
1040     @param start - (u32) first slot in the ring
1041     @param ring_size - (u32) ring size
1042     @param n_buffers - (u32) number of buffers
1043 */
1044 always_inline void
1045 vlib_buffer_free_from_ring (vlib_main_t * vm, u32 * ring, u32 start,
1046                             u32 ring_size, u32 n_buffers)
1047 {
1048   ASSERT (n_buffers <= ring_size);
1049
1050   if (PREDICT_TRUE (start + n_buffers <= ring_size))
1051     {
1052       vlib_buffer_free (vm, ring + start, n_buffers);
1053     }
1054   else
1055     {
1056       vlib_buffer_free (vm, ring + start, ring_size - start);
1057       vlib_buffer_free (vm, ring, n_buffers - (ring_size - start));
1058     }
1059 }
1060
1061 /** \brief Free buffers from ring without freeing tail buffers
1062
1063     @param vm - (vlib_main_t *) vlib main data structure pointer
1064     @param buffers - (u32 * ) buffer index ring
1065     @param start - (u32) first slot in the ring
1066     @param ring_size - (u32) ring size
1067     @param n_buffers - (u32) number of buffers
1068 */
1069 always_inline void
1070 vlib_buffer_free_from_ring_no_next (vlib_main_t * vm, u32 * ring, u32 start,
1071                                     u32 ring_size, u32 n_buffers)
1072 {
1073   ASSERT (n_buffers <= ring_size);
1074
1075   if (PREDICT_TRUE (start + n_buffers <= ring_size))
1076     {
1077       vlib_buffer_free_no_next (vm, ring + start, n_buffers);
1078     }
1079   else
1080     {
1081       vlib_buffer_free_no_next (vm, ring + start, ring_size - start);
1082       vlib_buffer_free_no_next (vm, ring, n_buffers - (ring_size - start));
1083     }
1084 }
1085
1086 /* Append given data to end of buffer, possibly allocating new buffers. */
1087 int vlib_buffer_add_data (vlib_main_t * vm, u32 * buffer_index, void *data,
1088                           u32 n_data_bytes);
1089
1090 /* Define vlib_buffer and vnet_buffer flags bits preserved for copy/clone */
1091 #define VLIB_BUFFER_COPY_CLONE_FLAGS_MASK                       \
1092   (VLIB_BUFFER_NEXT_PRESENT | VLIB_BUFFER_TOTAL_LENGTH_VALID |  \
1093    VLIB_BUFFER_IS_TRACED | ~VLIB_BUFFER_FLAGS_ALL)
1094
1095 /* duplicate all buffers in chain */
1096 always_inline vlib_buffer_t *
1097 vlib_buffer_copy (vlib_main_t * vm, vlib_buffer_t * b)
1098 {
1099   vlib_buffer_t *s, *d, *fd;
1100   uword n_alloc, n_buffers = 1;
1101   u32 flag_mask = VLIB_BUFFER_COPY_CLONE_FLAGS_MASK;
1102   int i;
1103
1104   s = b;
1105   while (s->flags & VLIB_BUFFER_NEXT_PRESENT)
1106     {
1107       n_buffers++;
1108       s = vlib_get_buffer (vm, s->next_buffer);
1109     }
1110   u32 new_buffers[n_buffers];
1111
1112   n_alloc = vlib_buffer_alloc (vm, new_buffers, n_buffers);
1113
1114   /* No guarantee that we'll get all the buffers we asked for */
1115   if (PREDICT_FALSE (n_alloc < n_buffers))
1116     {
1117       if (n_alloc > 0)
1118         vlib_buffer_free (vm, new_buffers, n_alloc);
1119       return 0;
1120     }
1121
1122   /* 1st segment */
1123   s = b;
1124   fd = d = vlib_get_buffer (vm, new_buffers[0]);
1125   d->current_data = s->current_data;
1126   d->current_length = s->current_length;
1127   d->flags = s->flags & flag_mask;
1128   d->trace_handle = s->trace_handle;
1129   d->total_length_not_including_first_buffer =
1130     s->total_length_not_including_first_buffer;
1131   clib_memcpy_fast (d->opaque, s->opaque, sizeof (s->opaque));
1132   clib_memcpy_fast (d->opaque2, s->opaque2, sizeof (s->opaque2));
1133   clib_memcpy_fast (vlib_buffer_get_current (d),
1134                     vlib_buffer_get_current (s), s->current_length);
1135
1136   /* next segments */
1137   for (i = 1; i < n_buffers; i++)
1138     {
1139       /* previous */
1140       d->next_buffer = new_buffers[i];
1141       /* current */
1142       s = vlib_get_buffer (vm, s->next_buffer);
1143       d = vlib_get_buffer (vm, new_buffers[i]);
1144       d->current_data = s->current_data;
1145       d->current_length = s->current_length;
1146       clib_memcpy_fast (vlib_buffer_get_current (d),
1147                         vlib_buffer_get_current (s), s->current_length);
1148       d->flags = s->flags & flag_mask;
1149     }
1150
1151   return fd;
1152 }
1153
1154 /* duplicate first buffer in chain */
1155 always_inline vlib_buffer_t *
1156 vlib_buffer_copy_no_chain (vlib_main_t * vm, vlib_buffer_t * b, u32 * di)
1157 {
1158   vlib_buffer_t *d;
1159
1160   if ((vlib_buffer_alloc (vm, di, 1)) != 1)
1161     return 0;
1162
1163   d = vlib_get_buffer (vm, *di);
1164   /* 1st segment */
1165   d->current_data = b->current_data;
1166   d->current_length = b->current_length;
1167   clib_memcpy_fast (d->opaque, b->opaque, sizeof (b->opaque));
1168   clib_memcpy_fast (d->opaque2, b->opaque2, sizeof (b->opaque2));
1169   clib_memcpy_fast (vlib_buffer_get_current (d),
1170                     vlib_buffer_get_current (b), b->current_length);
1171
1172   return d;
1173 }
1174
1175 /*  \brief Move packet from current position to offset position in buffer.
1176     Only work for small packet using one buffer with room to fit the move
1177     @param vm - (vlib_main_t *) vlib main data structure pointer
1178     @param b -  (vlib_buffer_t *) pointer to buffer
1179     @param offset - (i16) position to move the packet in buffer
1180  */
1181 always_inline void
1182 vlib_buffer_move (vlib_main_t * vm, vlib_buffer_t * b, i16 offset)
1183 {
1184   ASSERT ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0);
1185   ASSERT (offset + VLIB_BUFFER_PRE_DATA_SIZE >= 0);
1186   ASSERT (offset + b->current_length <
1187           vlib_buffer_get_default_data_size (vm));
1188
1189   u8 *source = vlib_buffer_get_current (b);
1190   b->current_data = offset;
1191   u8 *destination = vlib_buffer_get_current (b);
1192   u16 length = b->current_length;
1193
1194   if (source + length <= destination)   /* no overlap */
1195     clib_memcpy_fast (destination, source, length);
1196   else
1197     memmove (destination, source, length);
1198 }
1199
1200 /** \brief Create a maximum of 256 clones of buffer and store them
1201     in the supplied array
1202
1203     @param vm - (vlib_main_t *) vlib main data structure pointer
1204     @param src_buffer - (u32) source buffer index
1205     @param buffers - (u32 * ) buffer index array
1206     @param n_buffers - (u16) number of buffer clones requested (<=256)
1207     @param head_end_offset - (u16) offset relative to current position
1208            where packet head ends
1209     @param offset - (i16) copy packet head at current position if 0,
1210            else at offset position to change headroom space as specified
1211     @return - (u16) number of buffers actually cloned, may be
1212     less than the number requested or zero
1213 */
1214 always_inline u16
1215 vlib_buffer_clone_256 (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
1216                        u16 n_buffers, u16 head_end_offset, i16 offset)
1217 {
1218   u16 i;
1219   vlib_buffer_t *s = vlib_get_buffer (vm, src_buffer);
1220
1221   ASSERT (s->ref_count == 1);
1222   ASSERT (n_buffers);
1223   ASSERT (n_buffers <= 256);
1224   ASSERT (offset + VLIB_BUFFER_PRE_DATA_SIZE >= 0);
1225   ASSERT ((offset + head_end_offset) <
1226           vlib_buffer_get_default_data_size (vm));
1227
1228   if (s->current_length <= head_end_offset + CLIB_CACHE_LINE_BYTES * 2)
1229     {
1230       buffers[0] = src_buffer;
1231       if (offset)
1232         vlib_buffer_move (vm, s, offset);
1233
1234       for (i = 1; i < n_buffers; i++)
1235         {
1236           vlib_buffer_t *d;
1237           d = vlib_buffer_copy (vm, s);
1238           if (d == 0)
1239             return i;
1240           buffers[i] = vlib_get_buffer_index (vm, d);
1241
1242         }
1243       return n_buffers;
1244     }
1245
1246   if (PREDICT_FALSE ((n_buffers == 1) && (offset == 0)))
1247     {
1248       buffers[0] = src_buffer;
1249       return 1;
1250     }
1251
1252   n_buffers = vlib_buffer_alloc_from_pool (vm, buffers, n_buffers,
1253                                            s->buffer_pool_index);
1254
1255   for (i = 0; i < n_buffers; i++)
1256     {
1257       vlib_buffer_t *d = vlib_get_buffer (vm, buffers[i]);
1258       if (offset)
1259         d->current_data = offset;
1260       else
1261         d->current_data = s->current_data;
1262
1263       d->current_length = head_end_offset;
1264       ASSERT (d->buffer_pool_index == s->buffer_pool_index);
1265
1266       d->total_length_not_including_first_buffer = s->current_length -
1267         head_end_offset;
1268       if (PREDICT_FALSE (s->flags & VLIB_BUFFER_NEXT_PRESENT))
1269         {
1270           d->total_length_not_including_first_buffer +=
1271             s->total_length_not_including_first_buffer;
1272         }
1273       d->flags = (s->flags & VLIB_BUFFER_COPY_CLONE_FLAGS_MASK) |
1274         VLIB_BUFFER_NEXT_PRESENT;
1275       d->trace_handle = s->trace_handle;
1276       clib_memcpy_fast (d->opaque, s->opaque, sizeof (s->opaque));
1277       clib_memcpy_fast (d->opaque2, s->opaque2, sizeof (s->opaque2));
1278       clib_memcpy_fast (vlib_buffer_get_current (d),
1279                         vlib_buffer_get_current (s), head_end_offset);
1280       d->next_buffer = src_buffer;
1281     }
1282   vlib_buffer_advance (s, head_end_offset);
1283   s->ref_count = n_buffers ? n_buffers : s->ref_count;
1284   while (s->flags & VLIB_BUFFER_NEXT_PRESENT)
1285     {
1286       s = vlib_get_buffer (vm, s->next_buffer);
1287       s->ref_count = n_buffers ? n_buffers : s->ref_count;
1288     }
1289
1290   return n_buffers;
1291 }
1292
1293 /** \brief Create multiple clones of buffer and store them
1294     in the supplied array
1295
1296     @param vm - (vlib_main_t *) vlib main data structure pointer
1297     @param src_buffer - (u32) source buffer index
1298     @param buffers - (u32 * ) buffer index array
1299     @param n_buffers - (u16) number of buffer clones requested (<=256)
1300     @param head_end_offset - (u16) offset relative to current position
1301            where packet head ends
1302     @param offset - (i16) copy packet head at current position if 0,
1303            else at offset position to change headroom space as specified
1304     @return - (u16) number of buffers actually cloned, may be
1305     less than the number requested or zero
1306 */
1307 always_inline u16
1308 vlib_buffer_clone_at_offset (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
1309                              u16 n_buffers, u16 head_end_offset, i16 offset)
1310 {
1311   vlib_buffer_t *s = vlib_get_buffer (vm, src_buffer);
1312   u16 n_cloned = 0;
1313
1314   while (n_buffers > 256)
1315     {
1316       vlib_buffer_t *copy;
1317       copy = vlib_buffer_copy (vm, s);
1318       n_cloned += vlib_buffer_clone_256 (vm,
1319                                          vlib_get_buffer_index (vm, copy),
1320                                          (buffers + n_cloned),
1321                                          256, head_end_offset, offset);
1322       n_buffers -= 256;
1323     }
1324   n_cloned += vlib_buffer_clone_256 (vm, src_buffer,
1325                                      buffers + n_cloned,
1326                                      n_buffers, head_end_offset, offset);
1327
1328   return n_cloned;
1329 }
1330
1331 /** \brief Create multiple clones of buffer and store them
1332     in the supplied array
1333
1334     @param vm - (vlib_main_t *) vlib main data structure pointer
1335     @param src_buffer - (u32) source buffer index
1336     @param buffers - (u32 * ) buffer index array
1337     @param n_buffers - (u16) number of buffer clones requested (<=256)
1338     @param head_end_offset - (u16) offset relative to current position
1339            where packet head ends
1340     @return - (u16) number of buffers actually cloned, may be
1341     less than the number requested or zero
1342 */
1343 always_inline u16
1344 vlib_buffer_clone (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
1345                    u16 n_buffers, u16 head_end_offset)
1346 {
1347   return vlib_buffer_clone_at_offset (vm, src_buffer, buffers, n_buffers,
1348                                       head_end_offset, 0);
1349 }
1350
1351 /** \brief Attach cloned tail to the buffer
1352
1353     @param vm - (vlib_main_t *) vlib main data structure pointer
1354     @param head - (vlib_buffer_t *) head buffer
1355     @param tail - (Vlib buffer_t *) tail buffer to clone and attach to head
1356 */
1357
1358 always_inline void
1359 vlib_buffer_attach_clone (vlib_main_t * vm, vlib_buffer_t * head,
1360                           vlib_buffer_t * tail)
1361 {
1362   ASSERT ((head->flags & VLIB_BUFFER_NEXT_PRESENT) == 0);
1363   ASSERT (head->buffer_pool_index == tail->buffer_pool_index);
1364
1365   head->flags |= VLIB_BUFFER_NEXT_PRESENT;
1366   head->flags &= ~VLIB_BUFFER_TOTAL_LENGTH_VALID;
1367   head->flags &= ~VLIB_BUFFER_EXT_HDR_VALID;
1368   head->flags |= (tail->flags & VLIB_BUFFER_TOTAL_LENGTH_VALID);
1369   head->next_buffer = vlib_get_buffer_index (vm, tail);
1370   head->total_length_not_including_first_buffer = tail->current_length +
1371     tail->total_length_not_including_first_buffer;
1372
1373 next_segment:
1374   clib_atomic_add_fetch (&tail->ref_count, 1);
1375
1376   if (tail->flags & VLIB_BUFFER_NEXT_PRESENT)
1377     {
1378       tail = vlib_get_buffer (vm, tail->next_buffer);
1379       goto next_segment;
1380     }
1381 }
1382
1383 /* Initializes the buffer as an empty packet with no chained buffers. */
1384 always_inline void
1385 vlib_buffer_chain_init (vlib_buffer_t * first)
1386 {
1387   first->total_length_not_including_first_buffer = 0;
1388   first->current_length = 0;
1389   first->flags &= ~VLIB_BUFFER_NEXT_PRESENT;
1390   first->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
1391 }
1392
1393 /* The provided next_bi buffer index is appended to the end of the packet. */
1394 always_inline vlib_buffer_t *
1395 vlib_buffer_chain_buffer (vlib_main_t * vm, vlib_buffer_t * last, u32 next_bi)
1396 {
1397   vlib_buffer_t *next_buffer = vlib_get_buffer (vm, next_bi);
1398   last->next_buffer = next_bi;
1399   last->flags |= VLIB_BUFFER_NEXT_PRESENT;
1400   next_buffer->current_length = 0;
1401   next_buffer->flags &= ~VLIB_BUFFER_NEXT_PRESENT;
1402   return next_buffer;
1403 }
1404
1405 /* Increases or decreases the packet length.
1406  * It does not allocate or deallocate new buffers.
1407  * Therefore, the added length must be compatible
1408  * with the last buffer. */
1409 always_inline void
1410 vlib_buffer_chain_increase_length (vlib_buffer_t * first,
1411                                    vlib_buffer_t * last, i32 len)
1412 {
1413   last->current_length += len;
1414   if (first != last)
1415     first->total_length_not_including_first_buffer += len;
1416 }
1417
1418 /* Copy data to the end of the packet and increases its length.
1419  * It does not allocate new buffers.
1420  * Returns the number of copied bytes. */
1421 always_inline u16
1422 vlib_buffer_chain_append_data (vlib_main_t * vm,
1423                                vlib_buffer_t * first,
1424                                vlib_buffer_t * last, void *data, u16 data_len)
1425 {
1426   u32 n_buffer_bytes = vlib_buffer_get_default_data_size (vm);
1427   ASSERT (n_buffer_bytes >= last->current_length + last->current_data);
1428   u16 len = clib_min (data_len,
1429                       n_buffer_bytes - last->current_length -
1430                       last->current_data);
1431   clib_memcpy_fast (vlib_buffer_get_current (last) + last->current_length,
1432                     data, len);
1433   vlib_buffer_chain_increase_length (first, last, len);
1434   return len;
1435 }
1436
1437 /* Copy data to the end of the packet and increases its length.
1438  * Allocates additional buffers from the free list if necessary.
1439  * Returns the number of copied bytes.
1440  * 'last' value is modified whenever new buffers are allocated and
1441  * chained and points to the last buffer in the chain. */
1442 u16
1443 vlib_buffer_chain_append_data_with_alloc (vlib_main_t * vm,
1444                                           vlib_buffer_t * first,
1445                                           vlib_buffer_t ** last, void *data,
1446                                           u16 data_len);
1447 void vlib_buffer_chain_validate (vlib_main_t * vm, vlib_buffer_t * first);
1448
1449 format_function_t format_vlib_buffer, format_vlib_buffer_and_data,
1450   format_vlib_buffer_contents, format_vlib_buffer_no_chain;
1451
1452 typedef struct
1453 {
1454   /* Vector of packet data. */
1455   u8 *packet_data;
1456
1457   /* Number of buffers to allocate in each call to allocator. */
1458   u32 min_n_buffers_each_alloc;
1459
1460   u8 *name;
1461 } vlib_packet_template_t;
1462
1463 void vlib_packet_template_init (vlib_main_t * vm,
1464                                 vlib_packet_template_t * t,
1465                                 void *packet_data,
1466                                 uword n_packet_data_bytes,
1467                                 uword min_n_buffers_each_alloc,
1468                                 char *fmt, ...);
1469
1470 void *vlib_packet_template_get_packet (vlib_main_t * vm,
1471                                        vlib_packet_template_t * t,
1472                                        u32 * bi_result);
1473
1474 always_inline void
1475 vlib_packet_template_free (vlib_main_t * vm, vlib_packet_template_t * t)
1476 {
1477   vec_free (t->packet_data);
1478 }
1479
1480 always_inline u32
1481 vlib_buffer_space_left_at_end (vlib_main_t * vm, vlib_buffer_t * b)
1482 {
1483   return b->data + vlib_buffer_get_default_data_size (vm) -
1484     ((u8 *) vlib_buffer_get_current (b) + b->current_length);
1485 }
1486
1487 #define VLIB_BUFFER_LINEARIZE_MAX 64
1488
1489 always_inline u32
1490 vlib_buffer_chain_linearize (vlib_main_t * vm, vlib_buffer_t * b)
1491 {
1492   vlib_buffer_t *dst_b;
1493   u32 n_buffers = 1, to_free = 0;
1494   u16 rem_len, dst_len, data_size, src_len = 0;
1495   u8 *dst, *src = 0;
1496
1497   if (PREDICT_TRUE ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0))
1498     return 1;
1499
1500   ASSERT (1 == b->ref_count);
1501   if (PREDICT_FALSE (1 != b->ref_count))
1502     return 0;
1503
1504   data_size = vlib_buffer_get_default_data_size (vm);
1505   rem_len = vlib_buffer_length_in_chain (vm, b) - b->current_length;
1506
1507   dst_b = b;
1508   dst = vlib_buffer_get_tail (dst_b);
1509   dst_len = vlib_buffer_space_left_at_end (vm, dst_b);
1510
1511   b->total_length_not_including_first_buffer -= dst_len;
1512
1513   while (rem_len > 0)
1514     {
1515       u16 copy_len;
1516
1517       while (0 == src_len)
1518         {
1519           ASSERT (b->flags & VLIB_BUFFER_NEXT_PRESENT);
1520           if (PREDICT_FALSE (!(b->flags & VLIB_BUFFER_NEXT_PRESENT)))
1521             break; /* malformed chained buffer */
1522
1523           b = vlib_get_buffer (vm, b->next_buffer);
1524           src = vlib_buffer_get_current (b);
1525           src_len = b->current_length;
1526         }
1527
1528       if (0 == dst_len)
1529         {
1530           ASSERT (dst_b->flags & VLIB_BUFFER_NEXT_PRESENT);
1531           if (PREDICT_FALSE (!(dst_b->flags & VLIB_BUFFER_NEXT_PRESENT)))
1532             break; /* malformed chained buffer */
1533
1534           vlib_buffer_t *next_dst_b = vlib_get_buffer (vm, dst_b->next_buffer);
1535
1536           if (PREDICT_TRUE (1 == next_dst_b->ref_count))
1537             {
1538               /* normal case: buffer is not cloned, just use it */
1539               dst_b = next_dst_b;
1540             }
1541           else
1542             {
1543               /* cloned buffer, build a new dest chain from there */
1544               vlib_buffer_t *bufs[VLIB_BUFFER_LINEARIZE_MAX];
1545               u32 bis[VLIB_BUFFER_LINEARIZE_MAX + 1];
1546               const int n = (rem_len + data_size - 1) / data_size;
1547               int n_alloc;
1548               int i;
1549
1550               ASSERT (n <= VLIB_BUFFER_LINEARIZE_MAX);
1551               if (PREDICT_FALSE (n > VLIB_BUFFER_LINEARIZE_MAX))
1552                 return 0;
1553
1554               n_alloc = vlib_buffer_alloc (vm, bis, n);
1555               if (PREDICT_FALSE (n_alloc != n))
1556                 {
1557                   vlib_buffer_free (vm, bis, n_alloc);
1558                   return 0;
1559                 }
1560
1561               vlib_get_buffers (vm, bis, bufs, n);
1562
1563               for (i = 0; i < n - 1; i++)
1564                 {
1565                   bufs[i]->flags |= VLIB_BUFFER_NEXT_PRESENT;
1566                   bufs[i]->next_buffer = bis[i + 1];
1567                 }
1568
1569               to_free = dst_b->next_buffer;
1570               dst_b->next_buffer = bis[0];
1571               dst_b = bufs[0];
1572             }
1573
1574           n_buffers++;
1575
1576           dst_b->current_data = clib_min (0, dst_b->current_data);
1577           dst_b->current_length = 0;
1578
1579           dst = dst_b->data + dst_b->current_data;
1580           dst_len = data_size - dst_b->current_data;
1581         }
1582
1583       copy_len = clib_min (src_len, dst_len);
1584
1585       if (PREDICT_TRUE (src == dst))
1586         {
1587           /* nothing to do */
1588         }
1589       else if (src + copy_len > dst && dst + copy_len > src)
1590         {
1591           /* src and dst overlap */
1592           ASSERT (b == dst_b);
1593           memmove (dst, src, copy_len);
1594         }
1595       else
1596         {
1597           clib_memcpy_fast (dst, src, copy_len);
1598         }
1599
1600       dst_b->current_length += copy_len;
1601
1602       dst += copy_len;
1603       src += copy_len;
1604       dst_len -= copy_len;
1605       src_len -= copy_len;
1606       rem_len -= copy_len;
1607     }
1608
1609   /* in case of a malformed chain buffer, we'll exit early from the loop. */
1610   ASSERT (0 == rem_len);
1611   b->total_length_not_including_first_buffer -= rem_len;
1612
1613   if (to_free)
1614     vlib_buffer_free_one (vm, to_free);
1615
1616   if (dst_b->flags & VLIB_BUFFER_NEXT_PRESENT)
1617     {
1618       /* the resulting chain is smaller than the original, cut it there */
1619       dst_b->flags &= ~VLIB_BUFFER_NEXT_PRESENT;
1620       vlib_buffer_free_one (vm, dst_b->next_buffer);
1621       if (1 == n_buffers)
1622         {
1623           /* no longer a chained buffer */
1624           dst_b->flags &= ~VLIB_BUFFER_TOTAL_LENGTH_VALID;
1625           dst_b->total_length_not_including_first_buffer = 0;
1626         }
1627     }
1628
1629   return n_buffers;
1630 }
1631
1632 #endif /* included_vlib_buffer_funcs_h */
1633
1634 /*
1635  * fd.io coding-style-patch-verification: ON
1636  *
1637  * Local Variables:
1638  * eval: (c-set-style "gnu")
1639  * End:
1640  */