Refactor vlib_buffer flags
[vpp.git] / src / vlib / buffer.h
index 77528e7..a1c2db3 100644 (file)
 #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 */
 #define VLIB_BUFFER_DATA_SIZE          (2048)
 #define VLIB_BUFFER_PRE_DATA_SIZE      __PRE_DATA_SIZE
 
+typedef u8 vlib_buffer_free_list_index_t;
+
 /** \file
     vlib buffer structure definition and a few select
     access methods. This structure and the buffer allocation
     of typing to make it so.
 */
 
+/**
+ * Buffer Flags
+ */
+#define foreach_vlib_buffer_flag \
+  _( 0, NON_DEFAULT_FREELIST, "non-default-fl")                \
+  _( 1, IS_TRACED, 0)                                  \
+  _( 2, NEXT_PRESENT, 0)                               \
+  _( 3, IS_RECYCLED, "is-recycled")                    \
+  _( 4, TOTAL_LENGTH_VALID, 0)                         \
+  _( 5, REPL_FAIL, "repl-fail")                                \
+  _( 6, RECYCLE, "recycle")                            \
+  _( 7, EXT_HDR_VALID, "ext-hdr-valid")
+
+/* NOTE: only buffer generic flags should be defined here, please consider
+   using user flags. i.e. src/vnet/buffer.h */
+
+enum
+{
+#define _(bit, name, v) VLIB_BUFFER_##name  = (1 << (bit)),
+  foreach_vlib_buffer_flag
+#undef _
+};
+
+enum
+{
+#define _(bit, name, v) VLIB_BUFFER_LOG2_##name  = (bit),
+  foreach_vlib_buffer_flag
+#undef _
+};
+
+  /* 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))
+
 /* VLIB buffer representation. */
 typedef struct
 {
@@ -78,30 +115,11 @@ typedef struct
                 <br> VLIB_BUFFER_TOTAL_LENGTH_VALID: as it says
                 <br> VLIB_BUFFER_REPL_FAIL: packet replication failure
                 <br> VLIB_BUFFER_RECYCLE: as it says
-                <br> VLIB_BUFFER_FLOW_REPORT: buffer is a flow report,
                 <br> VLIB_BUFFER_EXT_HDR_VALID: buffer contains valid external buffer manager header,
                 set to avoid adding it to a flow report
                 <br> VLIB_BUFFER_FLAG_USER(n): user-defined bit N
              */
 
-/* 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 << 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))
 
     STRUCT_MARK (template_end);
 
@@ -122,7 +140,8 @@ typedef struct
 
   u8 n_add_refs; /**< Number of additional references to this buffer. */
 
-  u8 dont_waste_me[2]; /**< Available space in the (precious)
+  u8 buffer_pool_index;        /**< index of buffer pool this buffer belongs. */
+  u8 dont_waste_me[1]; /**< Available space in the (precious)
                           first 32 octets of buffer metadata
                           Before allocating any of it, discussion required!
                        */
@@ -141,7 +160,11 @@ typedef struct
   /**< 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 */
+  vlib_buffer_free_list_index_t free_list_index; /** < only used if
+                                                  VLIB_BUFFER_NON_DEFAULT_FREELIST
+                                                  flag is set */
+  u8 align_pad[3]; /**< available */
+  u32 opaque2[12];  /**< More opaque data, see ../vnet/vnet/buffer.h */
 
   /***** end of second cache line */
     CLIB_CACHE_LINE_ALIGN_MARK (cacheline2);
@@ -334,7 +357,7 @@ typedef struct vlib_buffer_free_list_t
   vlib_buffer_t buffer_init_template;
 
   /* Our index into vlib_main_t's buffer_free_list_pool. */
-  u32 index;
+  vlib_buffer_free_list_index_t index;
 
   /* Number of data bytes for buffers in this free list. */
   u32 n_data_bytes;
@@ -349,6 +372,12 @@ typedef struct vlib_buffer_free_list_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. */
@@ -371,17 +400,19 @@ typedef struct vlib_buffer_free_list_t
   uword buffer_init_function_opaque;
 } __attribute__ ((aligned (16))) vlib_buffer_free_list_t;
 
+typedef uword (vlib_buffer_fill_free_list_cb_t) (struct vlib_main_t * vm,
+                                                vlib_buffer_free_list_t * fl,
+                                                uword min_free_buffers);
+typedef void (vlib_buffer_free_cb_t) (struct vlib_main_t * vm, u32 * buffers,
+                                     u32 n_buffers);
+typedef void (vlib_buffer_free_no_next_cb_t) (struct vlib_main_t * vm,
+                                             u32 * buffers, u32 n_buffers);
+
 typedef struct
 {
-  u32 (*vlib_buffer_alloc_cb) (struct vlib_main_t * vm, u32 * buffers,
-                              u32 n_buffers);
-  u32 (*vlib_buffer_alloc_from_free_list_cb) (struct vlib_main_t * vm,
-                                             u32 * buffers, u32 n_buffers,
-                                             u32 free_list_index);
-  void (*vlib_buffer_free_cb) (struct vlib_main_t * vm, u32 * buffers,
-                              u32 n_buffers);
-  void (*vlib_buffer_free_no_next_cb) (struct vlib_main_t * vm, u32 * buffers,
-                                      u32 n_buffers);
+  vlib_buffer_fill_free_list_cb_t *vlib_buffer_fill_free_list_cb;
+  vlib_buffer_free_cb_t *vlib_buffer_free_cb;
+  vlib_buffer_free_no_next_cb_t *vlib_buffer_free_no_next_cb;
   void (*vlib_packet_template_init_cb) (struct vlib_main_t * vm, void *t,
                                        void *packet_data,
                                        uword n_packet_data_bytes,
@@ -389,11 +420,20 @@ typedef struct
                                        min_n_buffers_each_physmem_alloc,
                                        u8 * name);
   void (*vlib_buffer_delete_free_list_cb) (struct vlib_main_t * vm,
-                                          u32 free_list_index);
+                                          vlib_buffer_free_list_index_t
+                                          free_list_index);
 } vlib_buffer_callbacks_t;
 
 extern vlib_buffer_callbacks_t *vlib_buffer_callbacks;
 
+typedef struct
+{
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+  uword start;
+  uword size;
+  vlib_physmem_region_index_t physmem_region;
+} vlib_buffer_pool_t;
+
 typedef struct
 {
   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
@@ -401,6 +441,7 @@ typedef struct
      buffer index */
   uword buffer_mem_start;
   uword buffer_mem_size;
+  vlib_buffer_pool_t *buffer_pools;
 
   /* Buffer free callback, for subversive activities */
     u32 (*buffer_free_callback) (struct vlib_main_t * vm,
@@ -423,6 +464,7 @@ typedef struct
      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;
@@ -432,9 +474,10 @@ typedef struct
   int callbacks_registered;
 } vlib_buffer_main_t;
 
-void vlib_buffer_add_mem_range (struct vlib_main_t *vm, uword start,
-                               uword size);
-void vlib_buffer_cb_init (struct vlib_main_t *vm);
+u8 vlib_buffer_add_physmem_region (struct vlib_main_t *vm,
+                                  vlib_physmem_region_index_t region);
+
+clib_error_t *vlib_buffer_main_init (struct vlib_main_t *vm);
 
 typedef struct
 {
@@ -457,7 +500,7 @@ typedef struct
       u32 next_index;
 
       /* Free list to use to allocate new buffers. */
-      u32 free_list_index;
+      vlib_buffer_free_list_index_t free_list_index;
     } tx;
 
     struct
@@ -503,7 +546,11 @@ serialize_vlib_buffer_n_bytes (serialize_main_t * m)
 #define VLIB_BUFFER_TRACE_TRAJECTORY 0
 
 #if VLIB_BUFFER_TRACE_TRAJECTORY > 0
-#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b) (b)->pre_data[0]=0
+extern void (*vlib_buffer_trace_trajectory_cb) (vlib_buffer_t * b, u32 index);
+extern void (*vlib_buffer_trace_trajectory_init_cb) (vlib_buffer_t * b);
+extern void vlib_buffer_trace_trajectory_init (vlib_buffer_t * b);
+#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b) \
+  vlib_buffer_trace_trajectory_init (b);
 #else
 #define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
 #endif /* VLIB_BUFFER_TRACE_TRAJECTORY */