#include <vppinfra/cache.h>
#include <vppinfra/serialize.h>
#include <vppinfra/vector.h>
+#include <vppinfra/lock.h>
#include <vlib/error.h> /* for vlib_error_t */
#include <vlib/config.h> /* for __PRE_DATA_SIZE */
typedef struct
{
CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+ STRUCT_MARK (template_start);
/* Offset within data[] that we are currently processing.
If negative current header points into predata area. */
i16 current_data; /**< signed offset in data[], pre_data[]
the end of this buffer.
*/
u32 flags; /**< buffer flags:
+ <br> VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index,
<br> VLIB_BUFFER_IS_TRACED: trace this buffer.
<br> VLIB_BUFFER_NEXT_PRESENT: this is a multi-chunk buffer.
<br> VLIB_BUFFER_TOTAL_LENGTH_VALID: as it says
set to avoid adding it to a flow report
<br> VLIB_BUFFER_FLAG_USER(n): user-defined bit N
*/
-#define VLIB_BUFFER_IS_TRACED (1 << 0)
-#define VLIB_BUFFER_LOG2_NEXT_PRESENT (1)
+
+/* any change to the following line requres update of
+ * vlib_buffer_get_free_list_index(...) and
+ * vlib_buffer_set_free_list_index(...) functions */
+#define VLIB_BUFFER_FREE_LIST_INDEX_MASK ((1 << 5) - 1)
+
+#define VLIB_BUFFER_IS_TRACED (1 << 5)
+#define VLIB_BUFFER_LOG2_NEXT_PRESENT (6)
#define VLIB_BUFFER_NEXT_PRESENT (1 << VLIB_BUFFER_LOG2_NEXT_PRESENT)
-#define VLIB_BUFFER_IS_RECYCLED (1 << 2)
-#define VLIB_BUFFER_TOTAL_LENGTH_VALID (1 << 3)
-#define VLIB_BUFFER_REPL_FAIL (1 << 4)
-#define VLIB_BUFFER_RECYCLE (1 << 5)
-#define VLIB_BUFFER_FLOW_REPORT (1 << 6)
-#define VLIB_BUFFER_EXT_HDR_VALID (1 << 7)
+#define VLIB_BUFFER_IS_RECYCLED (1 << 7)
+#define VLIB_BUFFER_TOTAL_LENGTH_VALID (1 << 8)
+#define VLIB_BUFFER_REPL_FAIL (1 << 9)
+#define VLIB_BUFFER_RECYCLE (1 << 10)
+#define VLIB_BUFFER_FLOW_REPORT (1 << 11)
+#define VLIB_BUFFER_EXT_HDR_VALID (1 << 12)
/* User defined buffer flags. */
#define LOG2_VLIB_BUFFER_FLAG_USER(n) (32 - (n))
#define VLIB_BUFFER_FLAG_USER(n) (1 << LOG2_VLIB_BUFFER_FLAG_USER(n))
- u32 free_list_index; /**< Buffer free list that this buffer was
- allocated from and will be freed to.
- */
-
- u32 total_length_not_including_first_buffer;
- /**< Only valid for first buffer in chain. Current length plus
- total length given here give total number of bytes in buffer chain.
- */
+ STRUCT_MARK (template_end);
u32 next_buffer; /**< Next buffer for this linked-list of buffers.
Only valid if VLIB_BUFFER_NEXT_PRESENT flag is set.
feature node
*/
- u8 dont_waste_me[3]; /**< Available space in the (precious)
+ u8 n_add_refs; /**< Number of additional references to this buffer. */
+
+ u8 dont_waste_me[2]; /**< Available space in the (precious)
first 32 octets of buffer metadata
Before allocating any of it, discussion required!
*/
- u32 opaque[8]; /**< Opaque data used by sub-graphs for their own purposes.
+ u32 opaque[10]; /**< Opaque data used by sub-graphs for their own purposes.
See .../vnet/vnet/buffer.h
*/
CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
if VLIB_PACKET_IS_TRACED flag is set.
*/
u32 recycle_count; /**< Used by L2 path recycle code */
- u32 opaque2[14]; /**< More opaque data, currently unused */
+
+ u32 total_length_not_including_first_buffer;
+ /**< Only valid for first buffer in chain. Current length plus
+ total length given here give total number of bytes in buffer chain.
+ */
+ u32 opaque2[13]; /**< More opaque data, currently unused */
/***** end of second cache line */
CLIB_CACHE_LINE_ALIGN_MARK (cacheline2);
b->current_length -= l;
}
+/** \brief Check if there is enough space in buffer to advance
+
+ @param b - (vlib_buffer_t *) pointer to the buffer
+ @param l - (word) size to check
+ @return - 0 if there is less space than 'l' in buffer
+*/
+always_inline u8
+vlib_buffer_has_space (vlib_buffer_t * b, word l)
+{
+ return b->current_length >= l;
+}
+
/** \brief Reset current header & length to state they were in when
packet was received.
return (void *) b->opaque2;
}
+/** \brief Get pointer to the end of buffer's data
+ * @param b pointer to the buffer
+ * @return pointer to tail of packet's data
+ */
+always_inline u8 *
+vlib_buffer_get_tail (vlib_buffer_t * b)
+{
+ return b->data + b->current_data + b->current_length;
+}
+
+/** \brief Append uninitialized data to buffer
+ * @param b pointer to the buffer
+ * @param size number of uninitialized bytes
+ * @return pointer to beginning of uninitialized data
+ */
+always_inline void *
+vlib_buffer_put_uninit (vlib_buffer_t * b, u8 size)
+{
+ void *p = vlib_buffer_get_tail (b);
+ /* XXX make sure there's enough space */
+ b->current_length += size;
+ return p;
+}
+
+/** \brief Prepend uninitialized data to buffer
+ * @param b pointer to the buffer
+ * @param size number of uninitialized bytes
+ * @return pointer to beginning of uninitialized data
+ */
+always_inline void *
+vlib_buffer_push_uninit (vlib_buffer_t * b, u8 size)
+{
+ ASSERT (b->current_data + VLIB_BUFFER_PRE_DATA_SIZE >= size);
+ b->current_data -= size;
+ b->current_length += size;
+
+ return vlib_buffer_get_current (b);
+}
+
+/** \brief Make head room, typically for packet headers
+ * @param b pointer to the buffer
+ * @param size number of head room bytes
+ * @return pointer to start of buffer (current data)
+ */
+always_inline void *
+vlib_buffer_make_headroom (vlib_buffer_t * b, u8 size)
+{
+ ASSERT (b->current_data + VLIB_BUFFER_PRE_DATA_SIZE >= size);
+ b->current_data += size;
+ return vlib_buffer_get_current (b);
+}
+
+/** \brief Retrieve bytes from buffer head
+ * @param b pointer to the buffer
+ * @param size number of bytes to pull
+ * @return pointer to start of buffer (current data)
+ */
+always_inline void *
+vlib_buffer_pull (vlib_buffer_t * b, u8 size)
+{
+ if (b->current_length + VLIB_BUFFER_PRE_DATA_SIZE < size)
+ return 0;
+
+ void *data = vlib_buffer_get_current (b);
+ vlib_buffer_advance (b, size);
+ return data;
+}
+
/* Forward declaration. */
struct vlib_main_t;
/* Vector of free buffers. Each element is a byte offset into I/O heap. */
u32 *buffers;
+ /* global vector of free buffers, used only on main thread.
+ Bufers are returned to global buffers only in case when number of
+ buffers on free buffers list grows about threshold */
+ u32 *global_buffers;
+ clib_spinlock_t global_buffers_lock;
+
/* Memory chunks allocated for this free list
recorded here so they can be freed when free list
is deleted. */
u32 free_list_index);
} vlib_buffer_callbacks_t;
+extern vlib_buffer_callbacks_t *vlib_buffer_callbacks;
+
typedef struct
{
+ CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+ /* Virtual memory address and size of buffer memory, used for calculating
+ buffer index */
+ uword buffer_mem_start;
+ uword buffer_mem_size;
+ vlib_physmem_region_index_t physmem_region;
+
/* Buffer free callback, for subversive activities */
- u32 (*buffer_free_callback) (struct vlib_main_t * vm,
- u32 * buffers,
- u32 n_buffers, u32 follow_buffer_next);
+ u32 (*buffer_free_callback) (struct vlib_main_t * vm,
+ u32 * buffers,
+ u32 n_buffers, u32 follow_buffer_next);
/* Pool of buffer free lists.
Multiple free lists exist for packet generator which uses
separate free lists for each packet stream --- so as to avoid
If buffer index is not in hash table then this buffer
has never been allocated. */
uword *buffer_known_hash;
+ clib_spinlock_t buffer_known_hash_lockp;
/* List of free-lists needing Blue Light Special announcements */
vlib_buffer_free_list_t **announce_list;
/* Callbacks */
vlib_buffer_callbacks_t cb;
- int extern_buffer_mgmt;
+ int callbacks_registered;
} vlib_buffer_main_t;
-void vlib_buffer_cb_init (struct vlib_main_t *vm);
-int vlib_buffer_cb_register (struct vlib_main_t *vm,
- vlib_buffer_callbacks_t * cb);
+void vlib_buffer_add_mem_range (struct vlib_main_t *vm, uword start,
+ uword size);
+clib_error_t *vlib_buffer_main_init (struct vlib_main_t *vm);
typedef struct
{
#endif /* included_vlib_buffer_h */
+#define VLIB_BUFFER_REGISTER_CALLBACKS(x,...) \
+ __VA_ARGS__ vlib_buffer_callbacks_t __##x##_buffer_callbacks; \
+static void __vlib_add_buffer_callbacks_t_##x (void) \
+ __attribute__((__constructor__)) ; \
+static void __vlib_add_buffer_callbacks_t_##x (void) \
+{ \
+ if (vlib_buffer_callbacks) \
+ clib_panic ("vlib buffer callbacks already registered"); \
+ vlib_buffer_callbacks = &__##x##_buffer_callbacks; \
+} \
+__VA_ARGS__ vlib_buffer_callbacks_t __##x##_buffer_callbacks
+
/*
* fd.io coding-style-patch-verification: ON
*