b4015b302c3345105f0cd98b835d863ef4faa2db
[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 <vlib/error.h>         /* for vlib_error_t */
48
49 #include <vlib/config.h>        /* for __PRE_DATA_SIZE */
50 #define VLIB_BUFFER_DATA_SIZE           (2048)
51 #define VLIB_BUFFER_PRE_DATA_SIZE       __PRE_DATA_SIZE
52
53 /** \file
54     vlib buffer structure definition and a few select
55     access methods. This structure and the buffer allocation
56     mechanism should perhaps live in vnet, but it would take a lot
57     of typing to make it so.
58 */
59
60 /* VLIB buffer representation. */
61 typedef struct
62 {
63   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
64   /* Offset within data[] that we are currently processing.
65      If negative current header points into predata area. */
66   i16 current_data;  /**< signed offset in data[], pre_data[]
67                         that we are currently processing.
68                         If negative current header points into predata area.
69                      */
70   u16 current_length;  /**< Nbytes between current data and
71                           the end of this buffer.
72                        */
73   u32 flags; /**< buffer flags:
74                 <br> VLIB_BUFFER_IS_TRACED: trace this buffer.
75                 <br> VLIB_BUFFER_NEXT_PRESENT: this is a multi-chunk buffer.
76                 <br> VLIB_BUFFER_TOTAL_LENGTH_VALID: as it says
77                 <br> VLIB_BUFFER_REPL_FAIL: packet replication failure
78                 <br> VLIB_BUFFER_RECYCLE: as it says
79                 <br> VLIB_BUFFER_FLOW_REPORT: buffer is a flow report,
80                 <br> VLIB_BUFFER_EXT_HDR_VALID: buffer contains valid external buffer manager header,
81                 set to avoid adding it to a flow report
82                 <br> VLIB_BUFFER_FLAG_USER(n): user-defined bit N
83              */
84 #define VLIB_BUFFER_IS_TRACED (1 << 0)
85 #define VLIB_BUFFER_LOG2_NEXT_PRESENT (1)
86 #define VLIB_BUFFER_NEXT_PRESENT (1 << VLIB_BUFFER_LOG2_NEXT_PRESENT)
87 #define VLIB_BUFFER_IS_RECYCLED (1 << 2)
88 #define VLIB_BUFFER_TOTAL_LENGTH_VALID (1 << 3)
89 #define VLIB_BUFFER_REPL_FAIL (1 << 4)
90 #define VLIB_BUFFER_RECYCLE (1 << 5)
91 #define VLIB_BUFFER_FLOW_REPORT (1 << 6)
92 #define VLIB_BUFFER_EXT_HDR_VALID (1 << 7)
93
94   /* User defined buffer flags. */
95 #define LOG2_VLIB_BUFFER_FLAG_USER(n) (32 - (n))
96 #define VLIB_BUFFER_FLAG_USER(n) (1 << LOG2_VLIB_BUFFER_FLAG_USER(n))
97
98   u32 free_list_index; /**< Buffer free list that this buffer was
99                           allocated from and will be freed to.
100                        */
101
102   u32 total_length_not_including_first_buffer;
103   /**< Only valid for first buffer in chain. Current length plus
104      total length given here give total number of bytes in buffer chain.
105   */
106
107   u32 next_buffer;   /**< Next buffer for this linked-list of buffers.
108                         Only valid if VLIB_BUFFER_NEXT_PRESENT flag is set.
109                      */
110
111   vlib_error_t error;   /**< Error code for buffers to be enqueued
112                            to error handler.
113                         */
114   u32 current_config_index; /**< Used by feature subgraph arcs to
115                                visit enabled feature nodes
116                             */
117
118   u8 feature_arc_index; /**< Used to identify feature arcs by intermediate
119                            feature node
120                         */
121
122   u8 n_add_refs; /**< Number of additional references to this buffer. */
123
124   u8 dont_waste_me[2]; /**< Available space in the (precious)
125                           first 32 octets of buffer metadata
126                           Before allocating any of it, discussion required!
127                        */
128
129   u32 opaque[8]; /**< Opaque data used by sub-graphs for their own purposes.
130                     See .../vnet/vnet/buffer.h
131                  */
132     CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
133
134   u32 trace_index; /**< Specifies index into trace buffer
135                       if VLIB_PACKET_IS_TRACED flag is set.
136                    */
137   u32 recycle_count; /**< Used by L2 path recycle code */
138   u32 opaque2[14];  /**< More opaque data, currently unused */
139
140   /***** end of second cache line */
141     CLIB_CACHE_LINE_ALIGN_MARK (cacheline2);
142   u8 pre_data[VLIB_BUFFER_PRE_DATA_SIZE];  /**< Space for inserting data
143                                                before buffer start.
144                                                Packet rewrite string will be
145                                                rewritten backwards and may extend
146                                                back before buffer->data[0].
147                                                Must come directly before packet data.
148                                             */
149
150   u8 data[0]; /**< Packet data. Hardware DMA here */
151 } vlib_buffer_t;                /* Must be a multiple of 64B. */
152
153 #define VLIB_BUFFER_HDR_SIZE  (sizeof(vlib_buffer_t) - VLIB_BUFFER_PRE_DATA_SIZE)
154
155 /** \brief Prefetch buffer metadata.
156     The first 64 bytes of buffer contains most header information
157
158     @param b - (vlib_buffer_t *) pointer to the buffer
159     @param type - LOAD, STORE. In most cases, STORE is the right answer
160 */
161
162 #define vlib_prefetch_buffer_header(b,type) CLIB_PREFETCH (b, 64, type)
163
164 always_inline vlib_buffer_t *
165 vlib_buffer_next_contiguous (vlib_buffer_t * b, u32 buffer_bytes)
166 {
167   return (void *) (b + 1) + buffer_bytes;
168 }
169
170 always_inline void
171 vlib_buffer_struct_is_sane (vlib_buffer_t * b)
172 {
173   ASSERT (sizeof (b[0]) % 64 == 0);
174
175   /* Rewrite data must be before and contiguous with packet data. */
176   ASSERT (b->pre_data + VLIB_BUFFER_PRE_DATA_SIZE == b->data);
177 }
178
179 /** \brief Get pointer to current data to process
180
181     @param b - (vlib_buffer_t *) pointer to the buffer
182     @return - (void *) (b->data + b->current_data)
183 */
184
185 always_inline void *
186 vlib_buffer_get_current (vlib_buffer_t * b)
187 {
188   /* Check bounds. */
189   ASSERT ((signed) b->current_data >= (signed) -VLIB_BUFFER_PRE_DATA_SIZE);
190   return b->data + b->current_data;
191 }
192
193 /** \brief Advance current data pointer by the supplied (signed!) amount
194
195     @param b - (vlib_buffer_t *) pointer to the buffer
196     @param l - (word) signed increment
197 */
198 always_inline void
199 vlib_buffer_advance (vlib_buffer_t * b, word l)
200 {
201   ASSERT (b->current_length >= l);
202   b->current_data += l;
203   b->current_length -= l;
204 }
205
206 /** \brief Reset current header & length to state they were in when
207     packet was received.
208
209     @param b - (vlib_buffer_t *) pointer to the buffer
210 */
211
212 always_inline void
213 vlib_buffer_reset (vlib_buffer_t * b)
214 {
215   b->current_length += clib_max (b->current_data, 0);
216   b->current_data = 0;
217 }
218
219 /** \brief Get pointer to buffer's opaque data array
220
221     @param b - (vlib_buffer_t *) pointer to the buffer
222     @return - (void *) b->opaque
223 */
224 always_inline void *
225 vlib_get_buffer_opaque (vlib_buffer_t * b)
226 {
227   return (void *) b->opaque;
228 }
229
230 /** \brief Get pointer to buffer's opaque2 data array
231
232     @param b - (vlib_buffer_t *) pointer to the buffer
233     @return - (void *) b->opaque2
234 */
235 always_inline void *
236 vlib_get_buffer_opaque2 (vlib_buffer_t * b)
237 {
238   return (void *) b->opaque2;
239 }
240
241 /* Forward declaration. */
242 struct vlib_main_t;
243
244 typedef struct vlib_buffer_free_list_t
245 {
246   /* Template buffer used to initialize first 16 bytes of buffers
247      allocated on this free list. */
248   vlib_buffer_t buffer_init_template;
249
250   /* Our index into vlib_main_t's buffer_free_list_pool. */
251   u32 index;
252
253   /* Number of data bytes for buffers in this free list. */
254   u32 n_data_bytes;
255
256   /* Number of buffers to allocate when we need to allocate new buffers
257      from physmem heap. */
258   u32 min_n_buffers_each_physmem_alloc;
259
260   /* Total number of buffers allocated from this free list. */
261   u32 n_alloc;
262
263   /* Vector of free buffers.  Each element is a byte offset into I/O heap. */
264   u32 *buffers;
265
266   /* Memory chunks allocated for this free list
267      recorded here so they can be freed when free list
268      is deleted. */
269   void **buffer_memory_allocated;
270
271   /* Free list name. */
272   u8 *name;
273
274   /* Callback functions to initialize newly allocated buffers.
275      If null buffers are zeroed. */
276   void (*buffer_init_function) (struct vlib_main_t * vm,
277                                 struct vlib_buffer_free_list_t * fl,
278                                 u32 * buffers, u32 n_buffers);
279
280   /* Callback function to announce that buffers have been
281      added to the freelist */
282   void (*buffers_added_to_freelist_function)
283     (struct vlib_main_t * vm, struct vlib_buffer_free_list_t * fl);
284
285   uword buffer_init_function_opaque;
286 } __attribute__ ((aligned (16))) vlib_buffer_free_list_t;
287
288 typedef struct
289 {
290   u32 (*vlib_buffer_alloc_cb) (struct vlib_main_t * vm, u32 * buffers,
291                                u32 n_buffers);
292   u32 (*vlib_buffer_alloc_from_free_list_cb) (struct vlib_main_t * vm,
293                                               u32 * buffers, u32 n_buffers,
294                                               u32 free_list_index);
295   void (*vlib_buffer_free_cb) (struct vlib_main_t * vm, u32 * buffers,
296                                u32 n_buffers);
297   void (*vlib_buffer_free_no_next_cb) (struct vlib_main_t * vm, u32 * buffers,
298                                        u32 n_buffers);
299   void (*vlib_packet_template_init_cb) (struct vlib_main_t * vm, void *t,
300                                         void *packet_data,
301                                         uword n_packet_data_bytes,
302                                         uword
303                                         min_n_buffers_each_physmem_alloc,
304                                         u8 * name);
305   void (*vlib_buffer_delete_free_list_cb) (struct vlib_main_t * vm,
306                                            u32 free_list_index);
307 } vlib_buffer_callbacks_t;
308
309 typedef struct
310 {
311   /* Buffer free callback, for subversive activities */
312   u32 (*buffer_free_callback) (struct vlib_main_t * vm,
313                                u32 * buffers,
314                                u32 n_buffers, u32 follow_buffer_next);
315   /* Pool of buffer free lists.
316      Multiple free lists exist for packet generator which uses
317      separate free lists for each packet stream --- so as to avoid
318      initializing static data for each packet generated. */
319   vlib_buffer_free_list_t *buffer_free_list_pool;
320 #define VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX (0)
321 #define VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES VLIB_BUFFER_DATA_SIZE
322
323   /* Hash table mapping buffer size (rounded to next unit of
324      sizeof (vlib_buffer_t)) to free list index. */
325   uword *free_list_by_size;
326
327   /* Hash table mapping buffer index into number
328      0 => allocated but free, 1 => allocated and not-free.
329      If buffer index is not in hash table then this buffer
330      has never been allocated. */
331   uword *buffer_known_hash;
332
333   /* List of free-lists needing Blue Light Special announcements */
334   vlib_buffer_free_list_t **announce_list;
335
336   /* Callbacks */
337   vlib_buffer_callbacks_t cb;
338   int extern_buffer_mgmt;
339 } vlib_buffer_main_t;
340
341 void vlib_buffer_cb_init (struct vlib_main_t *vm);
342 int vlib_buffer_cb_register (struct vlib_main_t *vm,
343                              vlib_buffer_callbacks_t * cb);
344
345 typedef struct
346 {
347   struct vlib_main_t *vlib_main;
348
349   u32 first_buffer, last_buffer;
350
351   union
352   {
353     struct
354     {
355       /* Total accumulated bytes in chain starting with first_buffer. */
356       u32 n_total_data_bytes;
357
358       /* Max number of bytes to accumulate in chain starting with first_buffer.
359          As this limit is reached buffers are enqueued to next node. */
360       u32 max_n_data_bytes_per_chain;
361
362       /* Next node to enqueue buffers to relative to current process node. */
363       u32 next_index;
364
365       /* Free list to use to allocate new buffers. */
366       u32 free_list_index;
367     } tx;
368
369     struct
370     {
371       /* CLIB fifo of buffer indices waiting to be unserialized. */
372       u32 *buffer_fifo;
373
374       /* Event type used to signal that RX buffers have been added to fifo. */
375       uword ready_one_time_event;
376     } rx;
377   };
378 } vlib_serialize_buffer_main_t;
379
380 void serialize_open_vlib_buffer (serialize_main_t * m, struct vlib_main_t *vm,
381                                  vlib_serialize_buffer_main_t * sm);
382 void unserialize_open_vlib_buffer (serialize_main_t * m,
383                                    struct vlib_main_t *vm,
384                                    vlib_serialize_buffer_main_t * sm);
385
386 u32 serialize_close_vlib_buffer (serialize_main_t * m);
387 void unserialize_close_vlib_buffer (serialize_main_t * m);
388 void *vlib_set_buffer_free_callback (struct vlib_main_t *vm, void *fp);
389
390 always_inline u32
391 serialize_vlib_buffer_n_bytes (serialize_main_t * m)
392 {
393   serialize_stream_t *s = &m->stream;
394   vlib_serialize_buffer_main_t *sm
395     = uword_to_pointer (m->stream.data_function_opaque,
396                         vlib_serialize_buffer_main_t *);
397   return sm->tx.n_total_data_bytes + s->current_buffer_index +
398     vec_len (s->overflow_buffer);
399 }
400
401 /*
402  */
403
404 /** \brief Compile time buffer trajectory tracing option
405     Turn this on if you run into "bad monkey" contexts,
406     and you want to know exactly which nodes they've visited...
407     See vlib/main.c...
408 */
409 #define VLIB_BUFFER_TRACE_TRAJECTORY 0
410
411 #if VLIB_BUFFER_TRACE_TRAJECTORY > 0
412 #define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b) (b)->pre_data[0]=0
413 #else
414 #define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
415 #endif /* VLIB_BUFFER_TRACE_TRAJECTORY */
416
417 #endif /* included_vlib_buffer_h */
418
419 /*
420  * fd.io coding-style-patch-verification: ON
421  *
422  * Local Variables:
423  * eval: (c-set-style "gnu")
424  * End:
425  */