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