Initial commit of vpp code.
[vpp.git] / vlib / 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   return vlib_physmem_at_offset (&vm->physmem_main, ((uword)buffer_index)
60                                  << CLIB_LOG2_CACHE_LINE_BYTES);
61 }
62
63 /** \brief Translate buffer pointer into buffer index
64
65     @param vm - (vlib_main_t *) vlib main data structure pointer
66     @param b - (void *) buffer pointer
67     @return - (u32) buffer index
68 */    
69 always_inline u32
70 vlib_get_buffer_index (vlib_main_t * vm, void * p)
71 {
72   uword offset = vlib_physmem_offset_of (&vm->physmem_main, p);
73   ASSERT((offset % (1<<CLIB_LOG2_CACHE_LINE_BYTES)) == 0);
74   return offset >> CLIB_LOG2_CACHE_LINE_BYTES;
75 }
76
77 /** \brief Get next buffer in buffer linklist, or zero for end of list.
78
79     @param vm - (vlib_main_t *) vlib main data structure pointer
80     @param b - (void *) buffer pointer
81     @return - (vlib_buffer_t *) next buffer, or NULL
82 */    
83 always_inline vlib_buffer_t *
84 vlib_get_next_buffer (vlib_main_t * vm, vlib_buffer_t * b)
85 {
86   return (b->flags & VLIB_BUFFER_NEXT_PRESENT
87           ? vlib_get_buffer (vm, b->next_buffer)
88           : 0);
89 }
90
91 uword vlib_buffer_length_in_chain_slow_path (vlib_main_t * vm, vlib_buffer_t * b_first);
92
93 /** \brief Get length in bytes of the buffer chain
94
95     @param vm - (vlib_main_t *) vlib main data structure pointer
96     @param b - (void *) buffer pointer
97     @return - (uword) length of buffer chain
98 */    
99 always_inline uword
100 vlib_buffer_length_in_chain (vlib_main_t * vm, vlib_buffer_t * b)
101 {
102   uword l = b->current_length + b->total_length_not_including_first_buffer;
103   if (PREDICT_FALSE ((b->flags & (VLIB_BUFFER_NEXT_PRESENT
104                                   | VLIB_BUFFER_TOTAL_LENGTH_VALID))
105                      == VLIB_BUFFER_NEXT_PRESENT))
106     return vlib_buffer_length_in_chain_slow_path (vm, b);
107   return l;
108 }
109
110 /** \brief Get length in bytes of the buffer index buffer chain
111
112     @param vm - (vlib_main_t *) vlib main data structure pointer
113     @param bi - (u32) buffer index
114     @return - (uword) length of buffer chain
115 */    
116 always_inline uword
117 vlib_buffer_index_length_in_chain (vlib_main_t * vm, u32 bi)
118 {
119   vlib_buffer_t * b = vlib_get_buffer (vm, bi);
120   return vlib_buffer_length_in_chain (vm, b);
121 }
122
123 /** \brief Copy buffer contents to memory
124
125     @param vm - (vlib_main_t *) vlib main data structure pointer
126     @param bi - (u32) buffer index
127     @param contents - (u8 *) memory, <strong>must be large enough</strong>
128     @return - (uword) length of buffer chain
129 */    
130 always_inline uword
131 vlib_buffer_contents (vlib_main_t * vm, u32 buffer_index, u8 * contents)
132 {
133   uword content_len = 0;
134   uword l;
135   vlib_buffer_t * b;
136
137   while (1)
138     {
139       b = vlib_get_buffer (vm, buffer_index);
140       l = b->current_length;
141       memcpy (contents + content_len, b->data + b->current_data, l);
142       content_len += l;
143       if (! (b->flags & VLIB_BUFFER_NEXT_PRESENT))
144         break;
145       buffer_index = b->next_buffer;
146     }
147
148   return content_len;
149 }
150
151 /* Return physical address of buffer->data start. */
152 always_inline u64
153 vlib_get_buffer_data_physical_address (vlib_main_t * vm, u32 buffer_index)
154 {
155   return vlib_physmem_offset_to_physical (&vm->physmem_main,
156                                           (((uword)buffer_index) <<
157                                            CLIB_LOG2_CACHE_LINE_BYTES) +
158                                            STRUCT_OFFSET_OF (vlib_buffer_t, data));
159 }
160
161 /** \brief Prefetch buffer metadata by buffer index
162     The first 64 bytes of buffer contains most header information
163
164     @param vm - (vlib_main_t *) vlib main data structure pointer
165     @param bi - (u32) buffer index
166     @param type - LOAD, STORE. In most cases, STORE is the right answer
167 */
168 /* Prefetch buffer header given index. */
169 #define vlib_prefetch_buffer_with_index(vm,bi,type)     \
170   do {                                                  \
171     vlib_buffer_t * _b = vlib_get_buffer (vm, bi);      \
172     vlib_prefetch_buffer_header (_b, type);             \
173   } while (0)
174
175 #if 0
176 /* Iterate over known allocated vlib bufs. You probably do not want
177  * to do this!
178  @param vm      the vlib_main_t
179  @param bi      found allocated buffer index
180  @param body    operation to perform on buffer index
181  function executes body for each allocated buffer index
182  */
183 #define vlib_buffer_foreach_allocated(vm,bi,body)                \
184 do {                                                             \
185   vlib_main_t * _vmain = (vm);                                   \
186   vlib_buffer_main_t * _bmain = &_vmain->buffer_main;            \
187   hash_pair_t * _vbpair;                                         \
188   hash_foreach_pair(_vbpair, _bmain->buffer_known_hash, ({       \
189     if (VLIB_BUFFER_KNOWN_ALLOCATED == _vbpair->value[0]) {      \
190       (bi) = _vbpair->key;                                       \
191       body;                                                      \
192     }                                                            \
193   }));                                                           \
194 } while (0)
195 #endif
196
197 #if DPDK == 0
198
199 typedef enum {
200   /* Index is unknown. */
201   VLIB_BUFFER_UNKNOWN,
202
203   /* Index is known and free/allocated. */
204   VLIB_BUFFER_KNOWN_FREE,
205   VLIB_BUFFER_KNOWN_ALLOCATED,
206 } vlib_buffer_known_state_t;
207
208 always_inline vlib_buffer_known_state_t
209 vlib_buffer_is_known (vlib_main_t * vm, u32 buffer_index)
210 {
211   vlib_buffer_main_t * bm = vm->buffer_main;
212   ASSERT(os_get_cpu_number() == 0);
213
214   uword * p = hash_get (bm->buffer_known_hash, buffer_index);
215   return p ? p[0] : VLIB_BUFFER_UNKNOWN;
216 }
217
218 always_inline void
219 vlib_buffer_set_known_state (vlib_main_t * vm,
220                              u32 buffer_index,
221                              vlib_buffer_known_state_t state)
222 {
223   vlib_buffer_main_t * bm = vm->buffer_main;
224   ASSERT(os_get_cpu_number() == 0);
225   hash_set (bm->buffer_known_hash, buffer_index, state);
226 }
227
228 /* Validates sanity of a single buffer.
229    Returns format'ed vector with error message if any. */
230 u8 * vlib_validate_buffer (vlib_main_t * vm, u32 buffer_index, uword follow_chain);
231
232 /* Validate an array of buffers.  As above. */
233 u8 * vlib_validate_buffers (vlib_main_t * vm,
234                             u32 * buffers,
235                             uword next_buffer_stride,
236                             uword n_buffers,
237                             vlib_buffer_known_state_t known_state,
238                             uword follow_chain);
239
240 #endif /* DPDK == 0 */
241
242 clib_error_t *
243 vlib_buffer_pool_create(vlib_main_t * vm, unsigned num_mbufs,
244                         unsigned mbuf_size, unsigned socket_id);
245
246 /** \brief Allocate buffers into supplied array
247
248     @param vm - (vlib_main_t *) vlib main data structure pointer
249     @param buffers - (u32 * ) buffer index array
250     @param n_buffers - (u32) number of buffers requested
251     @return - (u32) number of buffers actually allocated, may be 
252     less than the number requested or zero
253 */
254 u32 vlib_buffer_alloc (vlib_main_t * vm, u32 * buffers, u32 n_buffers);
255
256 always_inline u32
257 vlib_buffer_round_size (u32 size)
258 { return round_pow2 (size, sizeof (vlib_buffer_t)); }
259
260 /** \brief Allocate buffers from specific freelist into supplied array
261
262     @param vm - (vlib_main_t *) vlib main data structure pointer
263     @param buffers - (u32 * ) buffer index array
264     @param n_buffers - (u32) number of buffers requested
265     @return - (u32) number of buffers actually allocated, may be 
266     less than the number requested or zero
267 */
268 u32 vlib_buffer_alloc_from_free_list (vlib_main_t * vm,
269                                       u32 * buffers,
270                                       u32 n_buffers,
271                                       u32 free_list_index);
272
273 /** \brief Free buffers
274     Frees the entire buffer chain for each buffer
275
276     @param vm - (vlib_main_t *) vlib main data structure pointer
277     @param buffers - (u32 * ) buffer index array
278     @param n_buffers - (u32) number of buffers to free
279
280 */
281 void vlib_buffer_free (vlib_main_t * vm,
282                        /* pointer to first buffer */
283                        u32 * buffers,
284                        /* number of buffers to free */
285                        u32 n_buffers);
286
287 /** \brief Free buffers, does not free the buffer chain for each buffer
288
289     @param vm - (vlib_main_t *) vlib main data structure pointer
290     @param buffers - (u32 * ) buffer index array
291     @param n_buffers - (u32) number of buffers to free
292
293 */
294 void vlib_buffer_free_no_next (vlib_main_t * vm,
295                                /* pointer to first buffer */
296                                u32 * buffers,
297                                /* number of buffers to free */
298                                u32 n_buffers);
299
300 /** \brief Free one buffer
301     Shorthand to free a single buffer chain. 
302
303     @param vm - (vlib_main_t *) vlib main data structure pointer
304     @param buffer_index - (u32) buffer index to free
305 */
306 always_inline void
307 vlib_buffer_free_one (vlib_main_t * vm, u32 buffer_index)
308 {
309   vlib_buffer_free (vm, &buffer_index, /* n_buffers */ 1);
310 }
311
312 /* Add/delete buffer free lists. */
313 u32 vlib_buffer_create_free_list (vlib_main_t * vm, u32 n_data_bytes, char * fmt, ...);
314 void vlib_buffer_delete_free_list (vlib_main_t * vm, u32 free_list_index);
315
316 /* Find already existing public free list with given size or create one. */
317 u32 vlib_buffer_get_or_create_free_list (vlib_main_t * vm, u32 n_data_bytes, char * fmt, ...);
318
319 always_inline vlib_buffer_free_list_t *
320 vlib_buffer_get_free_list (vlib_main_t * vm, u32 free_list_index)
321 {
322   vlib_buffer_main_t * bm = vm->buffer_main;
323   vlib_buffer_free_list_t * f;
324
325   f = pool_elt_at_index (bm->buffer_free_list_pool, free_list_index);
326
327   /* Sanity: indices must match. */
328   ASSERT (f->index == free_list_index);
329
330   return f;
331 }
332
333 always_inline u32
334 vlib_buffer_free_list_buffer_size (vlib_main_t * vm, u32 free_list_index)
335 {
336   vlib_buffer_free_list_t * f = vlib_buffer_get_free_list (vm, free_list_index);
337   return f->n_data_bytes;
338 }
339
340 void
341 vlib_aligned_memcpy (void * _dst, void * _src, int n_bytes);
342
343 /* Reasonably fast buffer copy routine. */
344 always_inline void
345 vlib_copy_buffers (u32 * dst, u32 * src, u32 n)
346 {
347   while (n >= 4)
348     {
349       dst[0] = src[0];
350       dst[1] = src[1];
351       dst[2] = src[2];
352       dst[3] = src[3];
353       dst += 4;
354       src += 4;
355       n -= 4;
356     }
357   while (n > 0)
358     {
359       dst[0] = src[0];
360       dst += 1;
361       src += 1;
362       n -= 1;
363     }
364 }
365
366 always_inline void *
367 vlib_physmem_alloc_aligned (vlib_main_t * vm, clib_error_t ** error,
368                             uword n_bytes, uword alignment)
369 {
370   void * r = vm->os_physmem_alloc_aligned (&vm->physmem_main, n_bytes, alignment);
371   if (! r)
372     *error = clib_error_return (0, "failed to allocate %wd bytes of I/O memory", n_bytes);
373   else
374     *error = 0;
375   return r;
376 }
377
378 /* By default allocate I/O memory with cache line alignment. */
379 always_inline void *
380 vlib_physmem_alloc (vlib_main_t * vm, clib_error_t ** error, uword n_bytes)
381 { return vlib_physmem_alloc_aligned (vm, error, n_bytes, CLIB_CACHE_LINE_BYTES); }
382
383 always_inline void
384 vlib_physmem_free (vlib_main_t * vm, void * mem)
385 { return vm->os_physmem_free (mem); }
386
387 always_inline u64
388 vlib_physmem_virtual_to_physical (vlib_main_t * vm, void * mem)
389 {
390   vlib_physmem_main_t * pm = &vm->physmem_main;
391   uword o = pointer_to_uword (mem) - pm->virtual.start;
392   return vlib_physmem_offset_to_physical (pm, o);
393 }
394
395 /* Append given data to end of buffer, possibly allocating new buffers. */
396 u32 vlib_buffer_add_data (vlib_main_t * vm,
397                           u32 free_list_index,
398                           u32 buffer_index,
399                           void * data, u32 n_data_bytes);
400
401 format_function_t format_vlib_buffer, format_vlib_buffer_and_data, format_vlib_buffer_contents;
402
403 typedef struct {
404   /* Vector of packet data. */
405   u8 * packet_data;
406
407 #if DPDK == 0
408   /* Number of buffers to allocate in each call to physmem
409      allocator. */
410   u32 min_n_buffers_each_physmem_alloc;
411
412   /* Buffer free list for this template. */
413   u32 free_list_index;
414
415   u32 * free_buffers;
416 #endif
417 } vlib_packet_template_t;
418
419 void vlib_packet_template_get_packet_helper (vlib_main_t * vm,
420                                              vlib_packet_template_t * t);
421
422 void vlib_packet_template_init (vlib_main_t * vm,
423                                 vlib_packet_template_t * t,
424                                 void * packet_data,
425                                 uword n_packet_data_bytes,
426                                 uword min_n_buffers_each_physmem_alloc,
427                                 char * fmt, ...);
428
429 void *
430 vlib_packet_template_get_packet (vlib_main_t * vm, 
431                                  vlib_packet_template_t * t,
432                                  u32 * bi_result);
433
434 always_inline void
435 vlib_packet_template_free (vlib_main_t * vm, vlib_packet_template_t * t)
436 {
437   vec_free (t->packet_data);
438 }
439
440 always_inline u32
441 unserialize_vlib_buffer_n_bytes (serialize_main_t * m)
442 {
443   serialize_stream_t * s = &m->stream;
444   vlib_serialize_buffer_main_t * sm
445     = uword_to_pointer (m->stream.data_function_opaque, vlib_serialize_buffer_main_t *);
446   vlib_main_t * vm = sm->vlib_main;
447   u32 n, * f;
448
449   n = s->n_buffer_bytes - s->current_buffer_index;
450   if (sm->last_buffer != ~0)
451     {
452       vlib_buffer_t * b = vlib_get_buffer (vm, sm->last_buffer);
453       while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
454         {
455           b = vlib_get_buffer (vm, b->next_buffer);
456           n += b->current_length;
457         }
458     }
459
460   clib_fifo_foreach (f, sm->rx.buffer_fifo, ({
461     n += vlib_buffer_index_length_in_chain (vm, f[0]);
462   }));
463
464   return n;
465 }
466
467 typedef union {
468   vlib_buffer_t b;
469   vlib_copy_unit_t i[sizeof (vlib_buffer_t) / sizeof (vlib_copy_unit_t)];
470 } vlib_buffer_union_t;
471
472 /* Set a buffer quickly into "uninitialized" state.  We want this to
473    be extremely cheap and arrange for all fields that need to be
474    initialized to be in the first 128 bits of the buffer. */
475 always_inline void
476 vlib_buffer_init_for_free_list (vlib_buffer_t * _dst,
477                                 vlib_buffer_free_list_t * fl)
478 {
479   vlib_buffer_union_t * dst = (vlib_buffer_union_t *) _dst;
480   vlib_buffer_union_t * src = (vlib_buffer_union_t *) &fl->buffer_init_template;
481
482   /* Make sure buffer template is sane. */
483   ASSERT (fl->index == fl->buffer_init_template.free_list_index);
484
485   /* Copy template from src->current_data thru src->free_list_index */
486   dst->i[0] = src->i[0];
487   if (1 * sizeof (dst->i[0]) < 16)
488     dst->i[1] = src->i[1];
489   if (2 * sizeof (dst->i[0]) < 16)
490     dst->i[2] = src->i[2];
491
492   /* Make sure it really worked. */
493 #define _(f) ASSERT (dst->b.f == src->b.f)
494   _ (current_data);
495   _ (current_length);
496   _ (flags);
497   _ (free_list_index);
498 #undef _
499   ASSERT (dst->b.total_length_not_including_first_buffer == 0);
500 }
501
502 always_inline void
503 vlib_buffer_init_two_for_free_list (vlib_buffer_t * _dst0,
504                                     vlib_buffer_t * _dst1,
505                                     vlib_buffer_free_list_t * fl)
506 {
507   vlib_buffer_union_t * dst0 = (vlib_buffer_union_t *) _dst0;
508   vlib_buffer_union_t * dst1 = (vlib_buffer_union_t *) _dst1;
509   vlib_buffer_union_t * src = (vlib_buffer_union_t *) &fl->buffer_init_template;
510
511   /* Make sure buffer template is sane. */
512   ASSERT (fl->index == fl->buffer_init_template.free_list_index);
513
514   /* Copy template from src->current_data thru src->free_list_index */
515   dst0->i[0] = dst1->i[0] = src->i[0];
516   if (1 * sizeof (dst0->i[0]) < 16)
517     dst0->i[1] = dst1->i[1] = src->i[1];
518   if (2 * sizeof (dst0->i[0]) < 16)
519     dst0->i[2] = dst1->i[2] = src->i[2];
520
521   /* Make sure it really worked. */
522 #define _(f) ASSERT (dst0->b.f == src->b.f && dst1->b.f == src->b.f)
523   _ (current_data);
524   _ (current_length);
525   _ (flags);
526   _ (free_list_index);
527 #undef _
528   ASSERT (dst0->b.total_length_not_including_first_buffer == 0);
529   ASSERT (dst1->b.total_length_not_including_first_buffer == 0);
530 }
531
532 #if CLIB_DEBUG > 0
533 u32 * vlib_buffer_state_validation_lock;
534 uword * vlib_buffer_state_validation_hash;
535 void * vlib_buffer_state_heap;
536 #endif
537
538 static inline void 
539 vlib_validate_buffer_in_use (vlib_buffer_t * b, u32 expected)
540 {
541 #if CLIB_DEBUG > 0
542   uword * p;
543   void * oldheap;
544
545   oldheap = clib_mem_set_heap (vlib_buffer_state_heap);
546
547   while (__sync_lock_test_and_set (vlib_buffer_state_validation_lock, 1))
548     ;
549
550   p = hash_get (vlib_buffer_state_validation_hash, b);
551
552   /* If we don't know about b, declare it to be in the expected state */
553   if (!p)
554     {
555       hash_set (vlib_buffer_state_validation_hash, b, expected);
556       goto out;
557     }
558   
559   if (p[0] != expected)
560     {
561       void cj_stop(void);
562       u32 bi;
563       vlib_main_t * vm = &vlib_global_main;
564       
565       cj_stop();
566       
567       bi = vlib_get_buffer_index (vm, b);
568
569       clib_mem_set_heap (oldheap);
570       clib_warning ("%.6f buffer %llx (%d): %s, not %s", 
571                     vlib_time_now(vm), bi,
572                     p[0] ? "busy" : "free",
573                     expected ? "busy" : "free");
574       os_panic();
575     }
576  out:
577   CLIB_MEMORY_BARRIER();
578   *vlib_buffer_state_validation_lock = 0;
579   clib_mem_set_heap (oldheap);
580 #endif
581 }
582
583 static inline void 
584 vlib_validate_buffer_set_in_use (vlib_buffer_t * b, u32 expected)
585 {
586 #if CLIB_DEBUG > 0
587   void * oldheap;
588
589   oldheap = clib_mem_set_heap (vlib_buffer_state_heap);
590
591   while (__sync_lock_test_and_set (vlib_buffer_state_validation_lock, 1))
592     ;
593
594   hash_set (vlib_buffer_state_validation_hash, b, expected);
595
596   CLIB_MEMORY_BARRIER();
597   *vlib_buffer_state_validation_lock = 0;
598   clib_mem_set_heap (oldheap);
599 #endif  
600 }
601
602 #endif /* included_vlib_buffer_funcs_h */