#include <vlib/unix/unix.h>
vlib_buffer_callbacks_t *vlib_buffer_callbacks = 0;
+static u32 vlib_buffer_physmem_sz = 32 << 20;
uword
vlib_buffer_length_in_chain_slow_path (vlib_main_t * vm,
format_vlib_buffer (u8 * s, va_list * args)
{
vlib_buffer_t *b = va_arg (*args, vlib_buffer_t *);
- uword indent = format_get_indent (s);
-
- s = format (s, "current data %d, length %d, free-list %d, clone-count %u",
- b->current_data, b->current_length,
- vlib_buffer_get_free_list_index (b), b->n_add_refs);
+ u32 indent = format_get_indent (s);
+ u8 *a = 0;
+
+#define _(bit, name, v) \
+ if (v && (b->flags & VLIB_BUFFER_##name)) \
+ a = format (a, "%s ", v);
+ foreach_vlib_buffer_flag
+#undef _
+ s = format (s, "current data %d, length %d, free-list %d, clone-count %u",
+ b->current_data, b->current_length,
+ vlib_buffer_get_free_list_index (b), b->n_add_refs);
if (b->flags & VLIB_BUFFER_TOTAL_LENGTH_VALID)
s = format (s, ", totlen-nifb %d",
if (b->flags & VLIB_BUFFER_IS_TRACED)
s = format (s, ", trace 0x%x", b->trace_index);
+ if (a)
+ s = format (s, "\n%U%v", format_white_space, indent, a);
+ vec_free (a);
+
while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
{
vlib_main_t *vm = vlib_get_main ();
vlib_buffer_known_state_t k;
u8 *msg, *result;
- k = vlib_buffer_is_known (vm, b->next_buffer);
+ k = vlib_buffer_is_known (b->next_buffer);
if (k != VLIB_BUFFER_KNOWN_ALLOCATED)
return format (0, "next 0x%x: %U",
b->next_buffer, format_vlib_buffer_known_state, k);
goto done;
}
- k = vlib_buffer_is_known (vm, bi);
+ k = vlib_buffer_is_known (bi);
if (k != known_state)
{
msg = format (0, "is %U; expected %U",
/* When dubugging validate that given buffers are either known allocated
or known free. */
-static void
+void
vlib_buffer_validate_alloc_free (vlib_main_t * vm,
u32 * buffers,
uword n_buffers,
if (CLIB_DEBUG == 0)
return;
+ if (vlib_buffer_callbacks)
+ return;
+
is_free = expected_state == VLIB_BUFFER_KNOWN_ALLOCATED;
b = buffers;
for (i = 0; i < n_buffers; i++)
bi = b[0];
b += 1;
- known = vlib_buffer_is_known (vm, bi);
+ known = vlib_buffer_is_known (bi);
if (known != expected_state)
{
ASSERT (0);
}
vlib_buffer_set_known_state
- (vm, bi,
- is_free ? VLIB_BUFFER_KNOWN_FREE : VLIB_BUFFER_KNOWN_ALLOCATED);
+ (bi, is_free ? VLIB_BUFFER_KNOWN_FREE : VLIB_BUFFER_KNOWN_ALLOCATED);
}
}
}
/* Add buffer free list. */
-static u32
+static vlib_buffer_free_list_index_t
vlib_buffer_create_free_list_helper (vlib_main_t * vm,
u32 n_data_bytes,
u32 is_public, u32 is_default, u8 * name)
if (!is_default && pool_elts (bm->buffer_free_list_pool) == 0)
{
- u32 default_free_free_list_index;
+ vlib_buffer_free_list_index_t default_free_free_list_index;
/* *INDENT-OFF* */
default_free_free_list_index =
return f->index;
}
-u32
+vlib_buffer_free_list_index_t
vlib_buffer_create_free_list (vlib_main_t * vm, u32 n_data_bytes,
char *fmt, ...)
{
name);
}
-u32
+vlib_buffer_free_list_index_t
vlib_buffer_get_or_create_free_list (vlib_main_t * vm, u32 n_data_bytes,
char *fmt, ...)
{
u32 i;
for (i = 0; i < vec_len (f->buffer_memory_allocated); i++)
- vm->os_physmem_free (f->buffer_memory_allocated[i]);
+ vm->os_physmem_free (vm, vm->buffer_main->buffer_pools[0].physmem_region,
+ f->buffer_memory_allocated[i]);
vec_free (f->name);
vec_free (f->buffer_memory_allocated);
vec_free (f->buffers);
/* Add buffer free list. */
void
-vlib_buffer_delete_free_list_internal (vlib_main_t * vm, u32 free_list_index)
+vlib_buffer_delete_free_list_internal (vlib_main_t * vm,
+ vlib_buffer_free_list_index_t index)
{
vlib_buffer_main_t *bm = vm->buffer_main;
vlib_buffer_free_list_t *f;
- u32 merge_index;
+ vlib_buffer_free_list_index_t merge_index;
int i;
ASSERT (vlib_get_thread_index () == 0);
- f = vlib_buffer_get_free_list (vm, free_list_index);
+ f = vlib_buffer_get_free_list (vm, index);
ASSERT (vec_len (f->buffers) == f->n_alloc);
merge_index = vlib_buffer_get_free_list_with_size (vm, f->n_data_bytes);
- if (merge_index != ~0 && merge_index != free_list_index)
+ if (merge_index != (vlib_buffer_free_list_index_t) ~ 0
+ && merge_index != index)
{
vlib_buffer_merge_free_lists (pool_elt_at_index
(bm->buffer_free_list_pool, merge_index),
for (i = 1; i < vec_len (vlib_mains); i++)
{
bm = vlib_mains[i]->buffer_main;
- f = vlib_buffer_get_free_list (vlib_mains[i], free_list_index);;
+ f = vlib_buffer_get_free_list (vlib_mains[i], index);;
memset (f, 0xab, sizeof (f[0]));
pool_put (bm->buffer_free_list_pool, f);
}
/* Make sure free list has at least given number of free buffers. */
static uword
-fill_free_list (vlib_main_t * vm,
- vlib_buffer_free_list_t * fl, uword min_free_buffers)
+vlib_buffer_fill_free_list_internal (vlib_main_t * vm,
+ vlib_buffer_free_list_t * fl,
+ uword min_free_buffers)
{
vlib_buffer_t *buffers, *b;
vlib_buffer_free_list_t *mfl;
n_bytes = n_this_chunk * (sizeof (b[0]) + fl->n_data_bytes);
/* drb: removed power-of-2 ASSERT */
- buffers = vm->os_physmem_alloc_aligned (&vm->physmem_main,
- n_bytes,
- sizeof (vlib_buffer_t));
+ buffers =
+ vm->os_physmem_alloc_aligned (vm,
+ vm->buffer_main->
+ buffer_pools[0].physmem_region, n_bytes,
+ sizeof (vlib_buffer_t));
if (!buffers)
return n_alloc;
bi[i] = vlib_get_buffer_index (vm, b);
if (CLIB_DEBUG > 0)
- vlib_buffer_set_known_state (vm, bi[i], VLIB_BUFFER_KNOWN_FREE);
+ vlib_buffer_set_known_state (bi[i], VLIB_BUFFER_KNOWN_FREE);
b = vlib_buffer_next_contiguous (b, fl->n_data_bytes);
}
return n_alloc;
}
-static u32
-alloc_from_free_list (vlib_main_t * vm,
- vlib_buffer_free_list_t * free_list,
- u32 * alloc_buffers, u32 n_alloc_buffers)
-{
- u32 *dst, *src;
- uword len;
- uword n_filled;
-
- dst = alloc_buffers;
-
- n_filled = fill_free_list (vm, free_list, n_alloc_buffers);
- if (n_filled == 0)
- return 0;
-
- len = vec_len (free_list->buffers);
- ASSERT (len >= n_alloc_buffers);
-
- src = free_list->buffers + len - n_alloc_buffers;
- clib_memcpy (dst, src, n_alloc_buffers * sizeof (u32));
-
- _vec_len (free_list->buffers) -= n_alloc_buffers;
-
- /* Verify that buffers are known free. */
- vlib_buffer_validate_alloc_free (vm, alloc_buffers,
- n_alloc_buffers, VLIB_BUFFER_KNOWN_FREE);
-
- return n_alloc_buffers;
-}
-
-
-/* Allocate a given number of buffers into given array.
- Returns number actually allocated which will be either zero or
- number requested. */
-static u32
-vlib_buffer_alloc_internal (vlib_main_t * vm, u32 * buffers, u32 n_buffers)
-{
- vlib_buffer_main_t *bm = vm->buffer_main;
-
- return alloc_from_free_list
- (vm,
- pool_elt_at_index (bm->buffer_free_list_pool,
- VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX),
- buffers, n_buffers);
-}
-
-static u32
-vlib_buffer_alloc_from_free_list_internal (vlib_main_t * vm,
- u32 * buffers,
- u32 n_buffers, u32 free_list_index)
-{
- vlib_buffer_main_t *bm = vm->buffer_main;
- vlib_buffer_free_list_t *f;
- f = pool_elt_at_index (bm->buffer_free_list_pool, free_list_index);
- return alloc_from_free_list (vm, f, buffers, n_buffers);
-}
-
void *
vlib_set_buffer_free_callback (vlib_main_t * vm, void *fp)
{
{
vlib_buffer_main_t *bm = vm->buffer_main;
vlib_buffer_free_list_t *fl;
- u32 fi;
+ vlib_buffer_free_list_index_t fi;
int i;
u32 (*cb) (vlib_main_t * vm, u32 * buffers, u32 n_buffers,
u32 follow_buffer_next);
u32 bi = buffers[i];
b = vlib_get_buffer (vm, bi);
-
+ VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b);
fl = vlib_buffer_get_buffer_free_list (vm, b, &fi);
/* The only current use of this callback: multicast recycle */
/* Append given data to end of buffer, possibly allocating new buffers. */
u32
vlib_buffer_add_data (vlib_main_t * vm,
- u32 free_list_index,
+ vlib_buffer_free_list_index_t free_list_index,
u32 buffer_index, void *data, u32 n_data_bytes)
{
u32 n_buffer_bytes, n_left, n_left_this_buffer, bi;
u16
vlib_buffer_chain_append_data_with_alloc (vlib_main_t * vm,
- u32 free_list_index,
+ vlib_buffer_free_list_index_t
+ free_list_index,
vlib_buffer_t * first,
- vlib_buffer_t ** last,
- void *data, u16 data_len)
+ vlib_buffer_t ** last, void *data,
+ u16 data_len)
{
vlib_buffer_t *l = *last;
u32 n_buffer_bytes =
return copied;
}
-void
-vlib_buffer_add_mem_range (vlib_main_t * vm, uword start, uword size)
+u8
+vlib_buffer_add_physmem_region (vlib_main_t * vm,
+ vlib_physmem_region_index_t pri)
{
vlib_buffer_main_t *bm = vm->buffer_main;
+ vlib_physmem_region_t *pr = vlib_physmem_get_region (vm, pri);
+ vlib_buffer_pool_t *p;
+ uword start = pointer_to_uword (pr->mem);
+ uword size = pr->size;
if (bm->buffer_mem_size == 0)
{
{
clib_panic ("buffer memory size out of range!");
}
+
+ vec_add2 (bm->buffer_pools, p, 1);
+ p->start = start;
+ p->size = size;
+ p->physmem_region = pri;
+ return p - bm->buffer_pools;
}
static u8 *
};
/* *INDENT-ON* */
-void
-vlib_buffer_cb_init (struct vlib_main_t *vm)
+clib_error_t *
+vlib_buffer_main_init (struct vlib_main_t * vm)
{
- vlib_buffer_main_t *bm = vm->buffer_main;
+ vlib_buffer_main_t *bm;
+ vlib_physmem_region_index_t pri;
+ clib_error_t *error;
- bm->cb.vlib_buffer_alloc_cb = &vlib_buffer_alloc_internal;
- bm->cb.vlib_buffer_alloc_from_free_list_cb =
- &vlib_buffer_alloc_from_free_list_internal;
+ vec_validate (vm->buffer_main, 0);
+ bm = vm->buffer_main;
+
+ if (vlib_buffer_callbacks)
+ {
+ /* external plugin has registered own buffer callbacks
+ so we just copy them and quit */
+ vlib_buffer_main_t *bm = vm->buffer_main;
+ clib_memcpy (&bm->cb, vlib_buffer_callbacks,
+ sizeof (vlib_buffer_callbacks_t));
+ bm->callbacks_registered = 1;
+ return 0;
+ }
+
+ bm->cb.vlib_buffer_fill_free_list_cb = &vlib_buffer_fill_free_list_internal;
bm->cb.vlib_buffer_free_cb = &vlib_buffer_free_internal;
bm->cb.vlib_buffer_free_no_next_cb = &vlib_buffer_free_no_next_internal;
bm->cb.vlib_buffer_delete_free_list_cb =
&vlib_buffer_delete_free_list_internal;
clib_spinlock_init (&bm->buffer_known_hash_lockp);
+
+ /* allocate default region */
+ error = vlib_physmem_region_alloc (vm, "buffers",
+ vlib_buffer_physmem_sz, 0,
+ VLIB_PHYSMEM_F_INIT_MHEAP, &pri);
+
+ if (error == 0)
+ goto done;
+
+ clib_error_free (error);
+
+ /* we my be running unpriviledged, so try to allocate fake physmem */
+ error = vlib_physmem_region_alloc (vm, "buffers (fake)",
+ vlib_buffer_physmem_sz, 0,
+ VLIB_PHYSMEM_F_FAKE |
+ VLIB_PHYSMEM_F_INIT_MHEAP, &pri);
+done:
+ vlib_buffer_add_physmem_region (vm, pri);
+ return error;
+}
+
+static clib_error_t *
+vlib_buffers_configure (vlib_main_t * vm, unformat_input_t * input)
+{
+ u32 size_in_mb;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "memory-size-in-mb %d", &size_in_mb))
+ vlib_buffer_physmem_sz = size_in_mb << 20;
+ else
+ return unformat_parse_error (input);
+ }
+
+ unformat_free (input);
+ return 0;
}
+VLIB_EARLY_CONFIG_FUNCTION (vlib_buffers_configure, "buffers");
+
+
/** @endcond */
/*
* fd.io coding-style-patch-verification: ON