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