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