diff options
Diffstat (limited to 'src/plugins/odp/buffer.c')
-rw-r--r-- | src/plugins/odp/buffer.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/src/plugins/odp/buffer.c b/src/plugins/odp/buffer.c new file mode 100644 index 00000000..b347bbae --- /dev/null +++ b/src/plugins/odp/buffer.c @@ -0,0 +1,119 @@ +/* Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Allocate/free ODP buffers. + */ + +#include <vlib/vlib.h> +#include <vnet/vnet.h> +#include <odp/odp_packet.h> + +/* Allocate a given number of buffers into given array. + Returns number actually allocated which will be either zero or + number requested. */ +u32 +odp_packet_buffer_alloc (vlib_main_t * vm, u32 * buffers, u32 n_buffers) +{ + odp_packet_main_t *om = &odp_packet_main; + u32 len = SHM_PKT_BUF_SIZE, total = 0; + odp_packet_t pkt; + + do + { + pkt = odp_packet_alloc (om->pool, len); + if (pkt == ODP_PACKET_INVALID) + break; + + buffers[total] = vlib_get_buffer_index (vm, odp_packet_user_area (pkt)); + ((vlib_buffer_t *)odp_packet_user_area (pkt))->l2_priv_data = (void *)pkt; + } + while (++total < n_buffers); + + return total; +} + + +static_always_inline void +odp_buffer_free_inline (vlib_main_t * vm, u32 * buffers, u32 n_buffers, + u32 follow_next) +{ + odp_packet_t pkt; + u32 count = 0, bi; + vlib_buffer_t *buffer; + + do + { + bi = buffers[count]; + do + { + buffer = vlib_get_buffer (vm, bi); + pkt = odp_packet_from_vlib_buffer (buffer); + odp_packet_free (pkt); + if (follow_next == 0) + break; + bi = buffer->next_buffer; + } + while (buffer->flags & VLIB_BUFFER_NEXT_PRESENT); + count++; + } + while (count < n_buffers); +} + +static void +odp_packet_buffer_free (vlib_main_t * vm, u32 * buffers, u32 n_buffers) +{ + odp_buffer_free_inline (vm, buffers, n_buffers, 1); +} + +static void +odp_packet_buffer_free_no_next (vlib_main_t * vm, u32 * buffers, + u32 n_buffers) +{ + odp_buffer_free_inline (vm, buffers, n_buffers, 0); +} + +static void +odp_packet_template_init (vlib_main_t * vm, + void *vt, + void *packet_data, + uword n_packet_data_bytes, + uword min_n_buffers_each_physmem_alloc, u8 * name) +{ + vlib_packet_template_t *t = (vlib_packet_template_t *) vt; + + vlib_worker_thread_barrier_sync (vm); + memset (t, 0, sizeof (t[0])); + + vec_add (t->packet_data, packet_data, n_packet_data_bytes); + + vlib_worker_thread_barrier_release (vm); +} + + +static vlib_buffer_callbacks_t odp_callbacks = { + .vlib_buffer_alloc_cb = &odp_packet_buffer_alloc, + .vlib_buffer_free_cb = &odp_packet_buffer_free, + .vlib_buffer_free_no_next_cb = &odp_packet_buffer_free_no_next, + .vlib_packet_template_init_cb = &odp_packet_template_init, +}; + +static clib_error_t * +odp_buffer_init (vlib_main_t * vm) +{ + vlib_buffer_cb_register (vm, &odp_callbacks); + return 0; +} + +VLIB_INIT_FUNCTION (odp_buffer_init); + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ |