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