47 #include <rte_config.h> 49 #include <rte_common.h> 51 #include <rte_memory.h> 52 #include <rte_memzone.h> 53 #include <rte_tailq.h> 55 #include <rte_per_lcore.h> 56 #include <rte_launch.h> 57 #include <rte_atomic.h> 58 #include <rte_cycles.h> 59 #include <rte_prefetch.h> 60 #include <rte_lcore.h> 61 #include <rte_per_lcore.h> 62 #include <rte_branch_prediction.h> 63 #include <rte_interrupts.h> 65 #include <rte_random.h> 66 #include <rte_debug.h> 67 #include <rte_ether.h> 68 #include <rte_ethdev.h> 70 #include <rte_mempool.h> 72 #include <rte_version.h> 76 #pragma weak rte_mem_virt2phy 77 #pragma weak rte_eal_has_hugepages 78 #pragma weak rte_socket_id 79 #pragma weak rte_pktmbuf_pool_create 104 s =
format (s,
"current data %d, length %d, free-list %d",
108 s =
format (s,
", totlen-nifb %d",
120 s =
format (s,
"\n%Unext-buffer 0x%x, segment length %d",
169 ASSERT (n_bytes %
sizeof (dst[0]) == 0);
176 while (n_bytes >= 4 *
sizeof (dst[0]))
180 n_bytes -= 4 *
sizeof (dst[0]);
194 while (n_bytes >= 8 *
sizeof (dst[0]))
198 n_bytes -= 8 *
sizeof (dst[0]);
217 n_bytes -= 1 *
sizeof (dst[0]);
221 #define BUFFERS_PER_COPY (sizeof (vlib_copy_unit_t) / sizeof (u32)) 227 uword n_unaligned_buffers)
235 ASSERT (la >= n_unaligned_buffers);
237 while (lu < n_unaligned_buffers)
312 return p ? p[0] : ~0;
319 u32 is_public,
u32 is_default,
u8 * name)
326 u32 default_free_free_list_index;
329 default_free_free_list_index =
337 ASSERT (default_free_free_list_index ==
341 return default_free_free_list_index;
346 memset (f, 0,
sizeof (f[0]));
417 ASSERT (rte_mbuf_refcnt_read (mb) == 1);
418 rte_pktmbuf_free (mb);
424 ASSERT (rte_mbuf_refcnt_read (mb) == 1);
425 rte_pktmbuf_free (mb);
443 if (merge_index != ~0 && merge_index != free_list_index)
452 memset (f, 0xab,
sizeof (f[0]));
465 u32 n_remaining = 0, n_alloc = 0;
479 return min_free_buffers;
494 for (i = 0; i < n; i++)
498 ASSERT (rte_mbuf_refcnt_read (mb) == 0);
499 rte_mbuf_refcnt_set (mb, 1);
501 mb->data_off = RTE_PKTMBUF_HEADROOM;
531 u32 * alloc_buffers,
u32 n_alloc_buffers)
535 uword n_unaligned_start, n_unaligned_end, n_filled;
537 n_left = n_alloc_buffers;
546 n_left = n_filled < n_left ? n_filled : n_left;
547 n_alloc_buffers = n_left;
549 if (n_unaligned_start >= n_left)
551 n_unaligned_start = n_left;
557 fill_unaligned (vm, free_list, n_unaligned_start + n_unaligned_end);
562 if (n_unaligned_start)
564 uword n_copy = n_unaligned_start;
623 ASSERT (n_unaligned_end == n_left);
636 return n_alloc_buffers;
657 u32 n_buffers,
u32 free_list_index)
668 u32 buffer_index,
u8 do_init)
700 u32 * buffers,
u32 n_buffers,
u32 follow_buffer_next)
707 u32 follow_buffer_next);
712 n_buffers = (*cb) (vm, buffers, n_buffers, follow_buffer_next);
717 for (i = 0; i < n_buffers; i++)
737 goto already_announced;
748 ASSERT (rte_mbuf_refcnt_read (mb) == 1);
749 rte_pktmbuf_free (mb);
780 __attribute__ ((unused))
784 u32 * buffers,
u32 n_buffers)
791 for (i = 0; i < n_buffers; i++)
804 uword n_packet_data_bytes,
805 uword min_n_buffers_each_physmem_alloc,
809 __attribute__ ((unused))
u8 *name;
816 memset (t, 0,
sizeof (t[0]));
853 u32 buffer_index,
void *data,
u32 n_data_bytes)
855 u32 n_buffer_bytes, n_left, n_left_this_buffer, bi;
865 n_left = n_data_bytes;
882 n =
clib_min (n_left_this_buffer, n_left);
912 void *data,
u16 data_len)
932 u16 len = (data_len > max) ? max : data_len;
949 struct rte_mbuf *mb_prev, *mb, *mb_first;
973 struct rte_mempool *rmp;
974 #if RTE_VERSION < RTE_VERSION_NUM(16, 7, 0, 0) 975 uword new_start, new_size;
979 if (!rte_pktmbuf_pool_create)
988 u8 *pool_name =
format (0,
"mbuf_pool_socket%u%c", socket_id, 0);
990 rmp = rte_pktmbuf_pool_create ((
char *) pool_name,
999 #if RTE_VERSION >= RTE_VERSION_NUM(16, 7, 0, 0) 1001 uword this_pool_end;
1002 uword this_pool_start;
1003 uword this_pool_size;
1004 uword save_vpm_start, save_vpm_end, save_vpm_size;
1005 struct rte_mempool_memhdr *memhdr;
1007 this_pool_start = ~0ULL;
1008 this_pool_end = 0LL;
1010 STAILQ_FOREACH (memhdr, &rmp->mem_list, next)
1012 if (((
uword) (memhdr->addr + memhdr->len)) > this_pool_end)
1013 this_pool_end = (
uword) (memhdr->addr + memhdr->len);
1014 if (((
uword) memhdr->addr) < this_pool_start)
1015 this_pool_start = (
uword) (memhdr->addr);
1017 ASSERT (this_pool_start < ~0ULL && this_pool_end > 0);
1018 this_pool_size = this_pool_end - this_pool_start;
1022 clib_warning (
"%s: pool start %llx pool end %llx pool size %lld",
1023 pool_name, this_pool_start, this_pool_end,
1026 (
"before: virtual.start %llx virtual.end %llx virtual.size %lld",
1034 if ((this_pool_start < vpm->
virtual.start) || vpm->
virtual.
start == 0)
1044 (
"after: virtual.start %llx virtual.end %llx virtual.size %lld",
1068 new_size = rmp->elt_va_end - new_start;
1073 if (new_start < vpm->
virtual.start)
1091 bm->pktmbuf_pools[socket_id] = rmp;
1092 vpm->virtual.start = new_start;
1093 vpm->virtual.size = new_size;
1094 vpm->virtual.end = new_start + new_size;
1103 for (
i = 0;
i <
vec_len (bm->pktmbuf_pools);
i++)
1105 if (bm->pktmbuf_pools[
i])
1108 (
"WARNING: Failed to allocate mempool for CPU socket %u. " 1109 "Threads running on socket %u will use socket %u mempool.",
1110 socket_id, socket_id,
i);
1111 bm->pktmbuf_pools[socket_id] = bm->pktmbuf_pools[
i];
1126 uword n, n_bytes_to_write;
1135 ASSERT (sm->
tx.max_n_data_bytes_per_chain > 0);
1137 || sm->
tx.n_total_data_bytes + n_bytes_to_write >
1138 sm->
tx.max_n_data_bytes_per_chain)
1149 sm->
tx.n_total_data_bytes = 0;
1158 sm->
tx.free_list_index);
1162 (
"vlib_buffer_alloc_from_free_list fails"));
1168 if (n_bytes_to_write > 0)
1173 sm->
tx.free_list_index);
1177 (
"vlib_buffer_alloc_from_free_list fails"));
1178 sm->
tx.n_total_data_bytes += n_bytes_to_write;
1225 sm->
rx.ready_one_time_event =
1229 sm->
rx.ready_one_time_event);
1252 memset (m, 0,
sizeof (m[0]));
1255 _vec_len (save) = 0;
1262 sm->
tx.n_total_data_bytes = 0;
1324 u32 threadnum = va_arg (*va,
u32);
1325 uword bytes_alloc, bytes_free, n_free,
size;
1328 return format (s,
"%=7s%=30s%=12s%=12s%=12s%=12s%=12s%=12s",
1329 "Thread",
"Name",
"Index",
"Size",
"Alloc",
"Free",
1334 bytes_alloc = size * f->
n_alloc;
1335 bytes_free = size * n_free;
1337 s =
format (s,
"%7d%30s%12d%12d%=12U%=12U%=12d%=12d",
1359 curr_vm =
vec_len (vlib_mains) ? vlib_mains[vm_index] : vm;
1364 vlib_cli_output (vm,
"%U", format_vlib_buffer_free_list, f, vm_index);
1370 while (vm_index <
vec_len (vlib_mains));
1377 .path =
"show buffers",
1378 .short_help =
"Show packet buffer allocation",
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
void vlib_buffer_chain_validate(vlib_main_t *vm, vlib_buffer_t *b_first)
uword * vlib_buffer_state_validation_hash
#define hash_set(h, key, value)
sll srl srl sll sra u16x4 i
#define rte_mbuf_from_vlib_buffer(x)
vlib_node_runtime_t node_runtime
static vlib_main_t * vlib_get_main(void)
static uword clib_fifo_elts(void *v)
static void vlib_set_next_frame_buffer(vlib_main_t *vm, vlib_node_runtime_t *node, u32 next_index, u32 buffer_index)
static uword vlib_current_process(vlib_main_t *vm)
u32 free_list_index
Buffer free list that this buffer was allocated from and will be freed to.
vlib_physmem_main_t physmem_main
void * mheap_alloc(void *memory, uword size)
void * vlib_buffer_state_heap
serialize_main_header_t header
static void serialize_error(serialize_main_header_t *m, clib_error_t *error)
static vlib_buffer_t * vlib_buffer_chain_buffer(vlib_main_t *vm, vlib_buffer_t *first, vlib_buffer_t *last, u32 next_bi)
#define vec_add2_aligned(V, P, N, A)
Add N elements to end of vector V, return pointer to new elements in P.
static void vlib_buffer_chain_increase_length(vlib_buffer_t *first, vlib_buffer_t *last, i32 len)
vlib_buffer_t buffer_init_template
struct vlib_serialize_buffer_main_t::@22::@24 tx
struct vlib_main_t * vlib_main
void vlib_buffer_free_no_next(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers, does not free the buffer chain for each buffer.
#define clib_error(format, args...)
#define CLIB_LOG2_CACHE_LINE_BYTES
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
static void fill_unaligned(vlib_main_t *vm, vlib_buffer_free_list_t *free_list, uword n_unaligned_buffers)
static heap_elt_t * last(heap_header_t *h)
vlib_buffer_main_t * buffer_main
static u32 vlib_buffer_create_free_list_helper(vlib_main_t *vm, u32 n_data_bytes, u32 is_public, u32 is_default, u8 *name)
u32 min_n_buffers_each_physmem_alloc
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
static_always_inline void vlib_buffer_free_inline(vlib_main_t *vm, u32 *buffers, u32 n_buffers, u32 follow_buffer_next)
struct vlib_serialize_buffer_main_t::@22::@25 rx
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
#define vec_add1_aligned(V, E, A)
Add 1 element to end of vector (alignment specified).
static void vlib_buffer_init_for_free_list(vlib_buffer_t *_dst, vlib_buffer_free_list_t *fl)
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
#define static_always_inline
void unserialize_open_vlib_buffer(serialize_main_t *m, vlib_main_t *vm, vlib_serialize_buffer_main_t *sm)
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
void(* buffer_init_function)(struct vlib_main_t *vm, struct vlib_buffer_free_list_t *fl, u32 *buffers, u32 n_buffers)
#define VLIB_INIT_FUNCTION(x)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
static uword serialize_stream_is_end_of_stream(serialize_stream_t *s)
static void trim_aligned(vlib_buffer_free_list_t *f)
#define clib_warning(format, args...)
#define vec_end(v)
End (last data address) of vector.
void serialize_open_vlib_buffer(serialize_main_t *m, vlib_main_t *vm, vlib_serialize_buffer_main_t *sm)
u8 * format_vlib_buffer_contents(u8 *s, va_list *va)
u8 * format_vlib_buffer(u8 *s, va_list *args)
static uword pointer_to_uword(const void *p)
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
#define VLIB_BUFFER_NEXT_PRESENT
vlib_buffer_free_list_t ** announce_list
static heap_elt_t * first(heap_header_t *h)
vlib_main_t ** vlib_mains
#define VLIB_BUFFER_PRE_DATA_SIZE
static void vlib_packet_template_buffer_init(vlib_main_t *vm, vlib_buffer_free_list_t *fl, u32 *buffers, u32 n_buffers)
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
static void vlib_serialize_rx(serialize_main_header_t *m, serialize_stream_t *s)
uword vlib_buffer_length_in_chain_slow_path(vlib_main_t *vm, vlib_buffer_t *b_first)
#define clib_fifo_sub1(f, e)
#define VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES
u32 serialize_close_vlib_buffer(serialize_main_t *m)
u16 current_length
Nbytes between current data and the end of this buffer.
void vlib_aligned_memcpy(void *_dst, void *_src, int n_bytes)
static clib_error_t * show_buffers(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define pool_put(P, E)
Free an object E in pool P.
#define clib_error_create(args...)
static u32 vlib_buffer_free_list_buffer_size(vlib_main_t *vm, u32 free_list_index)
u32 vlib_buffer_get_or_create_free_list(vlib_main_t *vm, u32 n_data_bytes, char *fmt,...)
static void clib_fifo_reset(void *v)
static vlib_buffer_free_list_t * buffer_get_free_list(vlib_main_t *vm, vlib_buffer_t *b, u32 *index)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
static void vlib_serialize_tx(serialize_main_header_t *m, serialize_stream_t *s)
static uword copy_alignment(u32 *x)
u16 vlib_buffer_chain_append_data_with_alloc(vlib_main_t *vm, u32 free_list_index, vlib_buffer_t *first, vlib_buffer_t **last, void *data, u16 data_len)
clib_error_t * vlib_buffer_pool_create(vlib_main_t *vm, unsigned num_mbufs, unsigned socket_id)
#define uword_to_pointer(u, type)
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P (general version).
#define vec_add_aligned(V, E, N, A)
Add N elements to end of vector V (no header, specified alignment)
struct rte_mempool ** pktmbuf_pools
serialize_stream_t stream
static vlib_process_t * vlib_get_current_process(vlib_main_t *vm)
u32(* buffer_free_callback)(struct vlib_main_t *vm, u32 *buffers, u32 n_buffers, u32 follow_buffer_next)
#define CLIB_PREFETCH(addr, size, type)
u8 * format_vlib_buffer_and_data(u8 *s, va_list *args)
static uword vlib_process_wait_for_one_time_event(vlib_main_t *vm, uword **data_vector, uword with_type_index)
#define vec_free(V)
Free vector's memory (no header).
static void * clib_mem_set_heap(void *heap)
void vlib_buffer_delete_free_list(vlib_main_t *vm, u32 free_list_index)
void unserialize_close_vlib_buffer(serialize_main_t *m)
#define clib_memcpy(a, b, c)
static uword vlib_process_create_one_time_event(vlib_main_t *vm, uword node_index, uword with_type_opaque)
u32 * vlib_buffer_state_validation_lock
serialize_data_function_t * data_function
#define VLIB_BUFFER_RECYCLE
#define VLIB_BUFFER_TOTAL_LENGTH_VALID
void(* buffers_added_to_freelist_function)(struct vlib_main_t *vm, struct vlib_buffer_free_list_t *fl)
void vlib_worker_thread_barrier_sync(vlib_main_t *vm)
static void add_buffer_to_free_list(vlib_main_t *vm, vlib_buffer_free_list_t *f, u32 buffer_index, u8 do_init)
static u8 * format_vlib_buffer_free_list(u8 *s, va_list *va)
static uword round_pow2(uword x, uword pow2)
uword data_function_opaque
#define VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX
#define hash_create(elts, value_bytes)
#define VLIB_BUFFER_HDR_SIZE
static u32 alloc_from_free_list(vlib_main_t *vm, vlib_buffer_free_list_t *free_list, u32 *alloc_buffers, u32 n_alloc_buffers)
void vlib_packet_template_init(vlib_main_t *vm, vlib_packet_template_t *t, void *packet_data, uword n_packet_data_bytes, uword min_n_buffers_each_physmem_alloc, char *fmt,...)
u32 next_buffer
Next buffer for this linked-list of buffers.
static uword clib_mem_is_heap_object(void *p)
static uword fill_free_list(vlib_main_t *vm, vlib_buffer_free_list_t *fl, uword min_free_buffers)
void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
#define VLIB_BUFFER_IS_TRACED
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
static u32 vlib_buffer_get_free_list_with_size(vlib_main_t *vm, u32 size)
VLIB_CLI_COMMAND(set_interface_ip_source_and_port_range_check_command, static)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static void del_free_list(vlib_main_t *vm, vlib_buffer_free_list_t *f)
u32 vlib_buffer_alloc_from_free_list(vlib_main_t *vm, u32 *buffers, u32 n_buffers, u32 free_list_index)
Allocate buffers from specific freelist into supplied array.
vlib_buffer_free_list_t * buffer_free_list_pool
#define VLIB_BUFFER_DATA_SIZE
void * vlib_set_buffer_free_callback(vlib_main_t *vm, void *fp)
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
#define vlib_buffer_from_rte_mbuf(x)
vlib_physmem_region_t virtual
void * vlib_packet_template_get_packet(vlib_main_t *vm, vlib_packet_template_t *t, u32 *bi_result)
u32 vlib_buffer_add_data(vlib_main_t *vm, u32 free_list_index, u32 buffer_index, void *data, u32 n_data_bytes)
uword buffer_init_function_opaque
static void vlib_buffer_free_one(vlib_main_t *vm, u32 buffer_index)
Free one buffer Shorthand to free a single buffer chain.
#define clib_error_return(e, args...)
static vlib_buffer_free_list_t * vlib_buffer_get_free_list(vlib_main_t *vm, u32 free_list_index)
#define CLIB_CACHE_LINE_BYTES
static clib_error_t * buffer_state_validation_init(vlib_main_t *vm)
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
u32 trace_index
Specifies index into trace buffer if VLIB_PACKET_IS_TRACED flag is set.
uword * free_list_by_size
static void merge_free_lists(vlib_buffer_free_list_t *dst, vlib_buffer_free_list_t *src)
static u32 vlib_buffer_round_size(u32 size)
u32 vlib_buffer_create_free_list(vlib_main_t *vm, u32 n_data_bytes, char *fmt,...)
static void serialize_open_vlib_helper(serialize_main_t *m, vlib_main_t *vm, vlib_serialize_buffer_main_t *sm, uword is_read)
static uword pool_elts(void *v)
Number of active elements in a pool.