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