ena: Amazon Elastic Network Adapter (ENA) native driver
[vpp.git] / src / vlib / buffer.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.h: VLIB buffers
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_h
41 #define included_vlib_buffer_h
42
43 #include <vppinfra/types.h>
44 #include <vppinfra/cache.h>
45 #include <vppinfra/serialize.h>
46 #include <vppinfra/vector.h>
47 #include <vppinfra/lock.h>
48 #include <vlib/error.h>         /* for vlib_error_t */
49
50 #include <vlib/config.h>        /* for __PRE_DATA_SIZE */
51 #define VLIB_BUFFER_PRE_DATA_SIZE       __PRE_DATA_SIZE
52
53 #define VLIB_BUFFER_DEFAULT_DATA_SIZE (2048)
54
55 /* Minimum buffer chain segment size. Does not apply to last buffer in chain.
56    Dataplane code can safely asume that specified amount of data is not split
57    into 2 chained buffers */
58 #define VLIB_BUFFER_MIN_CHAIN_SEG_SIZE  (128)
59
60 /* Amount of head buffer data copied to each replica head buffer */
61 #define VLIB_BUFFER_CLONE_HEAD_SIZE (256)
62
63 /** \file
64     vlib buffer structure definition and a few select
65     access methods. This structure and the buffer allocation
66     mechanism should perhaps live in vnet, but it would take a lot
67     of typing to make it so.
68 */
69
70 /**
71  * Buffer Flags
72  */
73 #define foreach_vlib_buffer_flag \
74   _( 0, IS_TRACED, 0)                                   \
75   _( 1, NEXT_PRESENT, "next-present")                   \
76   _( 2, TOTAL_LENGTH_VALID, 0)                          \
77   _( 3, EXT_HDR_VALID, "ext-hdr-valid")
78
79 /* NOTE: only buffer generic flags should be defined here, please consider
80    using user flags. i.e. src/vnet/buffer.h */
81
82 enum
83 {
84 #define _(bit, name, v) VLIB_BUFFER_##name  = (1 << (bit)),
85   foreach_vlib_buffer_flag
86 #undef _
87 };
88
89 enum
90 {
91 #define _(bit, name, v) VLIB_BUFFER_LOG2_##name  = (bit),
92   foreach_vlib_buffer_flag
93 #undef _
94 };
95
96   /* User defined buffer flags. */
97 #define LOG2_VLIB_BUFFER_FLAG_USER(n) (32 - (n))
98 #define VLIB_BUFFER_FLAG_USER(n) (1 << LOG2_VLIB_BUFFER_FLAG_USER(n))
99 #define VLIB_BUFFER_FLAGS_ALL (0x0f)
100
101 /** \brief Compile time buffer trajectory tracing option
102     Turn this on if you run into "bad monkey" contexts,
103     and you want to know exactly which nodes they've visited...
104     See vlib/main.c...
105 */
106 #ifndef VLIB_BUFFER_TRACE_TRAJECTORY
107 #define VLIB_BUFFER_TRACE_TRAJECTORY 0
108 #endif /* VLIB_BUFFER_TRACE_TRAJECTORY */
109
110 #define vlib_buffer_template_fields                                           \
111   /** signed offset in data[], pre_data[] that we are currently               \
112    * processing. If negative current header points into predata area.  */     \
113   i16 current_data;                                                           \
114                                                                               \
115   /** Nbytes between current data and the end of this buffer.  */             \
116   u16 current_length;                                                         \
117   /** buffer flags:                                                           \
118       <br> VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list     \
119      index, <br> VLIB_BUFFER_IS_TRACED: trace this buffer. <br>               \
120      VLIB_BUFFER_NEXT_PRESENT: this is a multi-chunk buffer. <br>             \
121      VLIB_BUFFER_TOTAL_LENGTH_VALID: as it says <br>                          \
122      VLIB_BUFFER_EXT_HDR_VALID: buffer contains valid external buffer manager \
123      header, set to avoid adding it to a flow report <br>                     \
124      VLIB_BUFFER_FLAG_USER(n): user-defined bit N                             \
125    */                                                                         \
126   u32 flags;                                                                  \
127                                                                               \
128   /** Generic flow identifier */                                              \
129   u32 flow_id;                                                                \
130                                                                               \
131   /** Reference count for this buffer. */                                     \
132   volatile u8 ref_count;                                                      \
133                                                                               \
134   /** index of buffer pool this buffer belongs. */                            \
135   u8 buffer_pool_index;                                                       \
136                                                                               \
137   /** Error code for buffers to be enqueued to error handler.  */             \
138   vlib_error_t error;                                                         \
139                                                                               \
140   /** Next buffer for this linked-list of buffers. Only valid if              \
141    * VLIB_BUFFER_NEXT_PRESENT flag is set. */                                 \
142   u32 next_buffer;                                                            \
143                                                                               \
144   /** The following fields can be in a union because once a packet enters     \
145    * the punt path, it is no longer on a feature arc */                       \
146   union                                                                       \
147   {                                                                           \
148     /** Used by feature subgraph arcs to visit enabled feature nodes */       \
149     u32 current_config_index;                                                 \
150     /* the reason the packet once punted */                                   \
151     u32 punt_reason;                                                          \
152   };                                                                          \
153                                                                               \
154   /** Opaque data used by sub-graphs for their own purposes. */               \
155   u32 opaque[10];
156
157 typedef struct
158 {
159   CLIB_ALIGN_MARK (align_mark, 64);
160   vlib_buffer_template_fields
161 } vlib_buffer_template_t;
162
163 STATIC_ASSERT_SIZEOF (vlib_buffer_template_t, 64);
164
165 /** VLIB buffer representation. */
166 typedef union
167 {
168   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
169   struct
170   {
171     union
172     {
173       struct
174       {
175         vlib_buffer_template_fields
176       };
177       vlib_buffer_template_t template;
178     };
179
180     /* Data above is initialized or zeroed on alloc, data bellow is not
181      * and it is app responsibility to ensure data is valid */
182
183     /** start of 2nd half (2nd cacheline on systems where cacheline size is 64) */
184       CLIB_ALIGN_MARK (second_half, 64);
185
186     /** Specifies trace buffer handle if VLIB_PACKET_IS_TRACED flag is
187       * set. */
188     u32 trace_handle;
189
190     /** Only valid for first buffer in chain. Current length plus total length
191       * given here give total number of bytes in buffer chain. */
192     u32 total_length_not_including_first_buffer;
193
194     /**< More opaque data, see ../vnet/vnet/buffer.h */
195     u32 opaque2[14];
196
197 #if VLIB_BUFFER_TRACE_TRAJECTORY > 0
198     /** trace trajectory data - we use a specific cacheline for that in the
199      * buffer when it is compiled-in */
200 #define VLIB_BUFFER_TRACE_TRAJECTORY_MAX     31
201 #define VLIB_BUFFER_TRACE_TRAJECTORY_SZ      64
202 #define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b) (b)->trajectory_nb = 0
203     CLIB_ALIGN_MARK (trajectory, 64);
204     u16 trajectory_nb;
205     u16 trajectory_trace[VLIB_BUFFER_TRACE_TRAJECTORY_MAX];
206 #else /* VLIB_BUFFER_TRACE_TRAJECTORY */
207 #define VLIB_BUFFER_TRACE_TRAJECTORY_SZ 0
208 #define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
209 #endif /* VLIB_BUFFER_TRACE_TRAJECTORY */
210
211     /** start of buffer headroom */
212       CLIB_ALIGN_MARK (headroom, 64);
213
214     /** Space for inserting data before buffer start.  Packet rewrite string
215       * will be rewritten backwards and may extend back before
216       * buffer->data[0].  Must come directly before packet data.  */
217     u8 pre_data[VLIB_BUFFER_PRE_DATA_SIZE];
218
219     /** Packet data */
220     u8 data[];
221   };
222 #ifdef CLIB_HAVE_VEC128
223   u8x16 as_u8x16[4];
224 #endif
225 #ifdef CLIB_HAVE_VEC256
226   u8x32 as_u8x32[2];
227 #endif
228 #ifdef CLIB_HAVE_VEC512
229   u8x64 as_u8x64[1];
230 #endif
231 } vlib_buffer_t;
232
233 STATIC_ASSERT_SIZEOF (vlib_buffer_t, 128 + VLIB_BUFFER_TRACE_TRAJECTORY_SZ +
234                                        VLIB_BUFFER_PRE_DATA_SIZE);
235 STATIC_ASSERT (VLIB_BUFFER_PRE_DATA_SIZE % CLIB_CACHE_LINE_BYTES == 0,
236                "VLIB_BUFFER_PRE_DATA_SIZE must be divisible by cache line size");
237
238 #define VLIB_BUFFER_HDR_SIZE  (sizeof(vlib_buffer_t) - VLIB_BUFFER_PRE_DATA_SIZE)
239 #define VLIB_BUFFER_INVALID_INDEX 0xffffffff
240
241 /** \brief Prefetch buffer metadata.
242     The first 64 bytes of buffer contains most header information
243
244     @param b - (vlib_buffer_t *) pointer to the buffer
245     @param type - LOAD, STORE. In most cases, STORE is the right answer
246 */
247
248 #define vlib_prefetch_buffer_header(b,type) CLIB_PREFETCH (b, 64, type)
249 #define vlib_prefetch_buffer_data(b,type) \
250   CLIB_PREFETCH (vlib_buffer_get_current(b), CLIB_CACHE_LINE_BYTES, type)
251
252 always_inline void
253 vlib_buffer_struct_is_sane (vlib_buffer_t * b)
254 {
255   ASSERT (sizeof (b[0]) % 64 == 0);
256
257   /* Rewrite data must be before and contiguous with packet data. */
258   ASSERT (b->pre_data + VLIB_BUFFER_PRE_DATA_SIZE == b->data);
259 }
260
261 always_inline uword
262 vlib_buffer_get_va (vlib_buffer_t * b)
263 {
264   return pointer_to_uword (b->data);
265 }
266
267 /** \brief Get pointer to current data to process
268
269     @param b - (vlib_buffer_t *) pointer to the buffer
270     @return - (void *) (b->data + b->current_data)
271 */
272
273 always_inline void *
274 vlib_buffer_get_current (vlib_buffer_t * b)
275 {
276   /* Check bounds. */
277   ASSERT ((signed) b->current_data >= (signed) -VLIB_BUFFER_PRE_DATA_SIZE);
278   return b->data + b->current_data;
279 }
280
281 always_inline uword
282 vlib_buffer_get_current_va (vlib_buffer_t * b)
283 {
284   return vlib_buffer_get_va (b) + b->current_data;
285 }
286
287 /** \brief Advance current data pointer by the supplied (signed!) amount
288
289     @param b - (vlib_buffer_t *) pointer to the buffer
290     @param l - (word) signed increment
291 */
292 always_inline void
293 vlib_buffer_advance (vlib_buffer_t * b, word l)
294 {
295   ASSERT (b->current_length >= l);
296   b->current_data += l;
297   b->current_length -= l;
298
299   ASSERT ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0 ||
300           b->current_length >= VLIB_BUFFER_MIN_CHAIN_SEG_SIZE);
301 }
302
303 /** \brief Check if there is enough space in buffer to advance
304
305     @param b - (vlib_buffer_t *) pointer to the buffer
306     @param l - (word) size to check
307     @return - 0 if there is less space than 'l' in buffer
308 */
309 always_inline u8
310 vlib_buffer_has_space (vlib_buffer_t * b, word l)
311 {
312   return b->current_length >= l;
313 }
314
315 /** \brief Reset current header & length to state they were in when
316     packet was received.
317
318     @param b - (vlib_buffer_t *) pointer to the buffer
319 */
320
321 always_inline void
322 vlib_buffer_reset (vlib_buffer_t * b)
323 {
324   b->current_length += clib_max (b->current_data, 0);
325   b->current_data = 0;
326 }
327
328 /** \brief Get pointer to buffer's opaque data array
329
330     @param b - (vlib_buffer_t *) pointer to the buffer
331     @return - (void *) b->opaque
332 */
333 always_inline void *
334 vlib_get_buffer_opaque (vlib_buffer_t * b)
335 {
336   return (void *) b->opaque;
337 }
338
339 /** \brief Get pointer to buffer's opaque2 data array
340
341     @param b - (vlib_buffer_t *) pointer to the buffer
342     @return - (void *) b->opaque2
343 */
344 always_inline void *
345 vlib_get_buffer_opaque2 (vlib_buffer_t * b)
346 {
347   return (void *) b->opaque2;
348 }
349
350 /** \brief Get pointer to the end of buffer's data
351  * @param b     pointer to the buffer
352  * @return      pointer to tail of packet's data
353  */
354 always_inline u8 *
355 vlib_buffer_get_tail (vlib_buffer_t * b)
356 {
357   return b->data + b->current_data + b->current_length;
358 }
359
360 /** \brief Append uninitialized data to buffer
361  * @param b     pointer to the buffer
362  * @param size  number of uninitialized bytes
363  * @return      pointer to beginning of uninitialized data
364  */
365 always_inline void *
366 vlib_buffer_put_uninit (vlib_buffer_t * b, u16 size)
367 {
368   void *p = vlib_buffer_get_tail (b);
369   /* XXX make sure there's enough space */
370   b->current_length += size;
371   return p;
372 }
373
374 /** \brief Prepend uninitialized data to buffer
375  * @param b     pointer to the buffer
376  * @param size  number of uninitialized bytes
377  * @return      pointer to beginning of uninitialized data
378  */
379 always_inline void *
380 vlib_buffer_push_uninit (vlib_buffer_t * b, u8 size)
381 {
382   ASSERT (b->current_data + VLIB_BUFFER_PRE_DATA_SIZE >= size);
383   b->current_data -= size;
384   b->current_length += size;
385
386   return vlib_buffer_get_current (b);
387 }
388
389 /** \brief Make head room, typically for packet headers
390  * @param b     pointer to the buffer
391  * @param size  number of head room bytes
392  * @return      pointer to start of buffer (current data)
393  */
394 always_inline void *
395 vlib_buffer_make_headroom (vlib_buffer_t * b, u8 size)
396 {
397   b->current_data += size;
398   return vlib_buffer_get_current (b);
399 }
400
401 /** \brief Construct a trace handle from thread and pool index
402  * @param thread Thread id
403  * @param pool_index Pool index
404  * @return trace handle
405  */
406 always_inline u32
407 vlib_buffer_make_trace_handle (u32 thread, u32 pool_index)
408 {
409   u32 rv;
410   ASSERT (thread < 0xff);
411   ASSERT (pool_index < 0x00FFFFFF);
412   rv = (thread << 24) | (pool_index & 0x00FFFFFF);
413   return rv;
414 }
415
416 /** \brief Extract the thread id from a trace handle
417  * @param trace_handle the trace handle
418  * @return the thread id
419  */
420 always_inline u32
421 vlib_buffer_get_trace_thread (vlib_buffer_t * b)
422 {
423   u32 trace_handle = b->trace_handle;
424
425   return trace_handle >> 24;
426 }
427
428 /** \brief Extract the trace (pool) index from a trace handle
429  * @param trace_handle the trace handle
430  * @return the trace index
431  */
432 always_inline u32
433 vlib_buffer_get_trace_index (vlib_buffer_t * b)
434 {
435   u32 trace_handle = b->trace_handle;
436   return trace_handle & 0x00FFFFFF;
437 }
438
439 /** \brief Retrieve bytes from buffer head
440  * @param b     pointer to the buffer
441  * @param size  number of bytes to pull
442  * @return      pointer to start of buffer (current data)
443  */
444 always_inline void *
445 vlib_buffer_pull (vlib_buffer_t * b, u8 size)
446 {
447   if (b->current_length + VLIB_BUFFER_PRE_DATA_SIZE < size)
448     return 0;
449
450   void *data = vlib_buffer_get_current (b);
451   vlib_buffer_advance (b, size);
452   return data;
453 }
454
455 /* Forward declaration. */
456 struct vlib_main_t;
457
458 #define VLIB_BUFFER_POOL_PER_THREAD_CACHE_SZ 512
459
460 typedef struct
461 {
462   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
463   u32 cached_buffers[VLIB_BUFFER_POOL_PER_THREAD_CACHE_SZ];
464   u32 n_cached;
465 } vlib_buffer_pool_thread_t;
466
467 typedef struct
468 {
469   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
470   uword start;
471   uword size;
472   u8 log2_page_size;
473   u8 index;
474   u8 numa_node;
475   u32 physmem_map_index;
476   u32 data_size;
477   u32 alloc_size;
478   u32 n_buffers;
479   u32 n_avail;
480   u32 *buffers;
481   u8 *name;
482   clib_spinlock_t lock;
483
484   /* per-thread data */
485   vlib_buffer_pool_thread_t *threads;
486
487   /* buffer metadata template */
488   vlib_buffer_template_t buffer_template;
489 } vlib_buffer_pool_t;
490
491 #define VLIB_BUFFER_MAX_NUMA_NODES 32
492
493 typedef u32 (vlib_buffer_alloc_free_callback_t) (struct vlib_main_t *vm,
494                                                  u8 buffer_pool_index,
495                                                  u32 *buffers, u32 n_buffers);
496
497 typedef struct
498 {
499   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
500   /* Virtual memory address and size of buffer memory, used for calculating
501      buffer index */
502   uword buffer_mem_start;
503   uword buffer_mem_size;
504   vlib_buffer_pool_t *buffer_pools;
505
506   vlib_buffer_alloc_free_callback_t *alloc_callback_fn;
507   vlib_buffer_alloc_free_callback_t *free_callback_fn;
508
509   u8 default_buffer_pool_index_for_numa[VLIB_BUFFER_MAX_NUMA_NODES];
510
511   /* config */
512   u32 buffers_per_numa;
513   u16 ext_hdr_size;
514   u32 default_data_size;
515   clib_mem_page_sz_t log2_page_size;
516
517   /* Hash table mapping buffer index into number
518      0 => allocated but free, 1 => allocated and not-free.
519      If buffer index is not in hash table then this buffer
520      has never been allocated. */
521   uword *buffer_known_hash;
522   clib_spinlock_t buffer_known_hash_lockp;
523
524   /* logging */
525   vlib_log_class_t log_default;
526 } vlib_buffer_main_t;
527
528 clib_error_t *vlib_buffer_main_init (struct vlib_main_t *vm);
529
530 format_function_t format_vlib_buffer_pool_all;
531
532 int vlib_buffer_set_alloc_free_callback (
533   struct vlib_main_t *vm, vlib_buffer_alloc_free_callback_t *alloc_callback_fn,
534   vlib_buffer_alloc_free_callback_t *free_callback_fn);
535
536 extern u16 __vlib_buffer_external_hdr_size;
537 #define VLIB_BUFFER_SET_EXT_HDR_SIZE(x) \
538 static void __clib_constructor \
539 vnet_buffer_set_ext_hdr_size() \
540 { \
541   if (__vlib_buffer_external_hdr_size) \
542     clib_error ("buffer external header space already set"); \
543   __vlib_buffer_external_hdr_size = CLIB_CACHE_LINE_ROUND (x); \
544 }
545
546 #endif /* included_vlib_buffer_h */
547
548 /*
549  * fd.io coding-style-patch-verification: ON
550  *
551  * Local Variables:
552  * eval: (c-set-style "gnu")
553  * End:
554  */