memif: complete refactor of socket handling code
Change-Id: I4d41def83a23f13701f1ddcea722d481e4c85cbc Signed-off-by: Damjan Marion <damarion@cisco.com>
This commit is contained in:
Damjan Marion
committed by
Damjan Marion
parent
b32fde58fd
commit
d51a1f6ffe
@ -19,6 +19,7 @@ memif_plugin_la_SOURCES = memif/memif.c \
|
||||
memif/cli.c \
|
||||
memif/node.c \
|
||||
memif/device.c \
|
||||
memif/socket.c \
|
||||
memif/memif_plugin.api.h
|
||||
|
||||
memif_test_plugin_la_SOURCES = \
|
||||
|
@ -24,20 +24,7 @@
|
||||
#include <vnet/ethernet/ethernet.h>
|
||||
|
||||
#include <memif/memif.h>
|
||||
|
||||
static uword
|
||||
unformat_memif_queues (unformat_input_t * input, va_list * args)
|
||||
{
|
||||
u32 *rx_queues = va_arg (*args, u32 *);
|
||||
u32 *tx_queues = va_arg (*args, u32 *);
|
||||
|
||||
if (unformat (input, "rx-queues %u", rx_queues))
|
||||
;
|
||||
if (unformat (input, "tx-queues %u", tx_queues))
|
||||
;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#include <memif/private.h>
|
||||
|
||||
static clib_error_t *
|
||||
memif_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
|
||||
@ -57,18 +44,23 @@ memif_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
|
||||
|
||||
while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
|
||||
{
|
||||
if (unformat (line_input, "key 0x%" PRIx64, &args.key))
|
||||
if (unformat (line_input, "id %u", &args.id))
|
||||
;
|
||||
else if (unformat (line_input, "socket %s", &args.socket_filename))
|
||||
;
|
||||
else if (unformat (line_input, "secret %s", &args.secret))
|
||||
;
|
||||
else if (unformat (line_input, "ring-size %u", &ring_size))
|
||||
;
|
||||
else if (unformat (line_input, "rx-queues %u", &rx_queues))
|
||||
;
|
||||
else if (unformat (line_input, "tx-queues %u", &tx_queues))
|
||||
;
|
||||
else if (unformat (line_input, "buffer-size %u", &args.buffer_size))
|
||||
;
|
||||
else if (unformat (line_input, "master"))
|
||||
args.is_master = 1;
|
||||
else if (unformat (line_input, "slave %U",
|
||||
unformat_memif_queues, &rx_queues, &tx_queues))
|
||||
else if (unformat (line_input, "slave"))
|
||||
args.is_master = 0;
|
||||
else if (unformat (line_input, "hw-addr %U",
|
||||
unformat_ethernet_address, args.hw_addr))
|
||||
@ -94,6 +86,9 @@ memif_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
|
||||
|
||||
r = memif_create_if (vm, &args);
|
||||
|
||||
vec_free (args.socket_filename);
|
||||
vec_free (args.secret);
|
||||
|
||||
if (r <= VNET_API_ERROR_SYSCALL_ERROR_1
|
||||
&& r >= VNET_API_ERROR_SYSCALL_ERROR_10)
|
||||
return clib_error_return (0, "%s (errno %d)", strerror (errno), errno);
|
||||
@ -102,7 +97,7 @@ memif_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
|
||||
return clib_error_return (0, "Invalid interface name");
|
||||
|
||||
if (r == VNET_API_ERROR_SUBIF_ALREADY_EXISTS)
|
||||
return clib_error_return (0, "Interface already exists");
|
||||
return clib_error_return (0, "Interface with same id already exists");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -110,9 +105,9 @@ memif_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
|
||||
/* *INDENT-OFF* */
|
||||
VLIB_CLI_COMMAND (memif_create_command, static) = {
|
||||
.path = "create memif",
|
||||
.short_help = "create memif [key <key>] [socket <path>] "
|
||||
.short_help = "create memif [id <id>] [socket <path>] "
|
||||
"[ring-size <size>] [buffer-size <size>] [hw-addr <mac-address>] "
|
||||
"<master|slave [rx-queues <number>] [tx-queues <number>]>",
|
||||
"<master|slave> [rx-queues <number>] [tx-queues <number>]",
|
||||
.function = memif_create_command_fn,
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
@ -122,8 +117,11 @@ memif_delete_command_fn (vlib_main_t * vm, unformat_input_t * input,
|
||||
vlib_cli_command_t * cmd)
|
||||
{
|
||||
unformat_input_t _line_input, *line_input = &_line_input;
|
||||
u64 key = 0;
|
||||
u8 key_defined = 0;
|
||||
u32 sw_if_index = ~0;
|
||||
vnet_hw_interface_t *hw;
|
||||
memif_main_t *mm = &memif_main;
|
||||
memif_if_t *mif;
|
||||
vnet_main_t *vnm = vnet_get_main ();
|
||||
|
||||
/* Get a line of input. */
|
||||
if (!unformat_user (input, unformat_line_input, line_input))
|
||||
@ -131,18 +129,27 @@ memif_delete_command_fn (vlib_main_t * vm, unformat_input_t * input,
|
||||
|
||||
while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
|
||||
{
|
||||
if (unformat (line_input, "key 0x%" PRIx64, &key))
|
||||
key_defined = 1;
|
||||
if (unformat (line_input, "sw_if_index %d", &sw_if_index))
|
||||
;
|
||||
else if (unformat (line_input, "%U", unformat_vnet_sw_interface,
|
||||
vnm, &sw_if_index))
|
||||
;
|
||||
else
|
||||
return clib_error_return (0, "unknown input `%U'",
|
||||
format_unformat_error, input);
|
||||
}
|
||||
unformat_free (line_input);
|
||||
|
||||
if (!key_defined)
|
||||
return clib_error_return (0, "missing key");
|
||||
if (sw_if_index == ~0)
|
||||
return clib_error_return (0,
|
||||
"please specify interface name or sw_if_index");
|
||||
|
||||
memif_delete_if (vm, key);
|
||||
hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
|
||||
if (hw == NULL || memif_device_class.index != hw->dev_class_index)
|
||||
return clib_error_return (0, "not a memif interface");
|
||||
|
||||
mif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
|
||||
memif_delete_if (vm, mif);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -150,11 +157,59 @@ memif_delete_command_fn (vlib_main_t * vm, unformat_input_t * input,
|
||||
/* *INDENT-OFF* */
|
||||
VLIB_CLI_COMMAND (memif_delete_command, static) = {
|
||||
.path = "delete memif",
|
||||
.short_help = "delete memif key <key-value>",
|
||||
.short_help = "delete memif {<interface> | sw_if_index <sw_idx>}",
|
||||
.function = memif_delete_command_fn,
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
static u8 *
|
||||
format_memif_if_flags (u8 * s, va_list * args)
|
||||
{
|
||||
u32 flags = va_arg (*args, u32);
|
||||
#define _(a,b,c) if ( flags & (1 << a)) s = format (s, " %s", c);
|
||||
foreach_memif_if_flag
|
||||
#undef _
|
||||
return s;
|
||||
}
|
||||
|
||||
static u8 *
|
||||
format_memif_if_mode (u8 * s, va_list * args)
|
||||
{
|
||||
memif_if_t *mif = va_arg (*args, memif_if_t *);
|
||||
if (mif->mode == MEMIF_INTERFACE_MODE_ETHERNET)
|
||||
return format (s, "ethernet");
|
||||
if (mif->mode == MEMIF_INTERFACE_MODE_IP)
|
||||
return format (s, "ip");
|
||||
if (mif->mode == MEMIF_INTERFACE_MODE_PUNT_INJECT)
|
||||
return format (s, "punt-inject");
|
||||
return format (s, "unknown mode (%u)", mif->mode);;
|
||||
}
|
||||
|
||||
static u8 *
|
||||
format_memif_queue (u8 * s, va_list * args)
|
||||
{
|
||||
memif_if_t *mif = va_arg (*args, memif_if_t *);
|
||||
memif_queue_t *mq = va_arg (*args, memif_queue_t *);
|
||||
uword i = va_arg (*args, uword);
|
||||
uword indent = format_get_indent (s);
|
||||
|
||||
s = format (s, "%U%s ring %u:\n",
|
||||
format_white_space, indent,
|
||||
(mif->flags & MEMIF_IF_FLAG_IS_SLAVE) ?
|
||||
"slave-to-master" : "master-to-slave", i);
|
||||
s = format (s, "%Uregion %u offset %u ring-size %u int-fd %d\n",
|
||||
format_white_space, indent + 4,
|
||||
mq->region, mq->offset, (1 << mq->log2_ring_size), mq->int_fd);
|
||||
|
||||
if (mq->ring)
|
||||
s = format (s, "%Uhead %u tail %u flags 0x%04x interrupts %u\n",
|
||||
format_white_space, indent + 4,
|
||||
mq->ring->head, mq->ring->tail, mq->ring->flags,
|
||||
mq->int_count);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
memif_show_command_fn (vlib_main_t * vm, unformat_input_t * input,
|
||||
vlib_cli_command_t * cmd)
|
||||
@ -162,39 +217,43 @@ memif_show_command_fn (vlib_main_t * vm, unformat_input_t * input,
|
||||
memif_main_t *mm = &memif_main;
|
||||
memif_if_t *mif;
|
||||
vnet_main_t *vnm = vnet_get_main ();
|
||||
int i;
|
||||
memif_queue_t *mq;
|
||||
uword i;
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
pool_foreach (mif, mm->interfaces,
|
||||
({
|
||||
memif_socket_file_t * msf = vec_elt_at_index (mm->socket_files,
|
||||
mif->socket_file_index);
|
||||
vlib_cli_output (vm, "interface %U", format_vnet_sw_if_index_name,
|
||||
vnm, mif->sw_if_index);
|
||||
vlib_cli_output (vm, " key 0x%" PRIx64 " file %s", mif->key,
|
||||
mif->socket_filename);
|
||||
vlib_cli_output (vm, " listener %d conn-fd %d int-fd %d", mif->listener_index,
|
||||
mif->connection.fd, mif->interrupt_line.fd);
|
||||
vlib_cli_output (vm, " ring-size %u num-s2m-rings %u num-m2s-rings %u buffer_size %u",
|
||||
(1 << mif->log2_ring_size),
|
||||
mif->num_s2m_rings,
|
||||
mif->num_m2s_rings,
|
||||
mif->buffer_size);
|
||||
for (i=0; i < mif->num_s2m_rings; i++)
|
||||
if (mif->remote_name)
|
||||
vlib_cli_output (vm, " remote-name \"%s\"", mif->remote_name);
|
||||
if (mif->remote_if_name)
|
||||
vlib_cli_output (vm, " remote-interface \"%s\"", mif->remote_if_name);
|
||||
vlib_cli_output (vm, " id %d mode %U file %s", mif->id,
|
||||
format_memif_if_mode, mif, msf->filename);
|
||||
vlib_cli_output (vm, " flags%U", format_memif_if_flags, mif->flags);
|
||||
vlib_cli_output (vm, " listener-fd %d conn-fd %d", msf->fd, mif->conn_fd);
|
||||
vlib_cli_output (vm, " num-s2m-rings %u num-m2s-rings %u buffer-size %u",
|
||||
mif->run.num_s2m_rings,
|
||||
mif->run.num_m2s_rings,
|
||||
mif->run.buffer_size);
|
||||
|
||||
if (mif->local_disc_string)
|
||||
vlib_cli_output (vm, " local-disc-reason \"%s\"", mif->local_disc_string);
|
||||
if (mif->remote_disc_string)
|
||||
vlib_cli_output (vm, " remote-disc-reason \"%s\"", mif->remote_disc_string);
|
||||
|
||||
vec_foreach_index (i, mif->tx_queues)
|
||||
{
|
||||
memif_ring_t * ring = memif_get_ring (mif, MEMIF_RING_S2M, i);
|
||||
if (ring)
|
||||
{
|
||||
vlib_cli_output (vm, " slave-to-master ring %u:", i);
|
||||
vlib_cli_output (vm, " head %u tail %u", ring->head, ring->tail);
|
||||
}
|
||||
mq = vec_elt_at_index (mif->tx_queues, i);
|
||||
vlib_cli_output (vm, " %U", format_memif_queue, mif, mq, i);
|
||||
}
|
||||
for (i=0; i < mif->num_m2s_rings; i++)
|
||||
vec_foreach_index (i, mif->rx_queues)
|
||||
{
|
||||
memif_ring_t * ring = memif_get_ring (mif, MEMIF_RING_M2S, i);
|
||||
if (ring)
|
||||
{
|
||||
vlib_cli_output (vm, " master-to-slave ring %u:", i);
|
||||
vlib_cli_output (vm, " head %u tail %u", ring->head, ring->tail);
|
||||
}
|
||||
mq = vec_elt_at_index (mif->rx_queues, i);
|
||||
vlib_cli_output (vm, " %U", format_memif_queue, mif, mq, i);
|
||||
}
|
||||
}));
|
||||
/* *INDENT-ON* */
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <vnet/ethernet/ethernet.h>
|
||||
|
||||
#include <memif/memif.h>
|
||||
#include <memif/private.h>
|
||||
|
||||
#define foreach_memif_tx_func_error \
|
||||
_(NO_FREE_SLOTS, "no free tx slots") \
|
||||
@ -45,8 +46,7 @@ static char *memif_tx_func_error_strings[] = {
|
||||
#undef _
|
||||
};
|
||||
|
||||
|
||||
static u8 *
|
||||
u8 *
|
||||
format_memif_device_name (u8 * s, va_list * args)
|
||||
{
|
||||
u32 i = va_arg (*args, u32);
|
||||
@ -91,27 +91,30 @@ memif_interface_tx_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame, memif_if_t * mif,
|
||||
memif_ring_type_t type)
|
||||
{
|
||||
u8 rid;
|
||||
u8 qid;
|
||||
memif_ring_t *ring;
|
||||
u32 *buffers = vlib_frame_args (frame);
|
||||
u32 n_left = frame->n_vectors;
|
||||
u16 ring_size = 1 << mif->log2_ring_size;
|
||||
u16 mask = ring_size - 1;
|
||||
u16 ring_size, mask;
|
||||
u16 head, tail;
|
||||
u16 free_slots;
|
||||
u32 thread_index = vlib_get_thread_index ();
|
||||
u8 tx_queues = memif_get_tx_queues (mif);
|
||||
u8 tx_queues = vec_len (mif->tx_queues);
|
||||
memif_queue_t *mq;
|
||||
|
||||
if (tx_queues < vec_len (vlib_mains))
|
||||
{
|
||||
rid = thread_index % tx_queues;
|
||||
qid = thread_index % tx_queues;
|
||||
clib_spinlock_lock_if_init (&mif->lockp);
|
||||
}
|
||||
else
|
||||
{
|
||||
rid = thread_index;
|
||||
qid = thread_index;
|
||||
}
|
||||
ring = memif_get_ring (mif, type, rid);
|
||||
mq = vec_elt_at_index (mif->tx_queues, qid);
|
||||
ring = mq->ring;
|
||||
ring_size = 1 << mq->log2_ring_size;
|
||||
mask = ring_size - 1;
|
||||
|
||||
/* free consumed buffers */
|
||||
|
||||
@ -214,10 +217,11 @@ memif_interface_tx_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
}
|
||||
|
||||
vlib_buffer_free (vm, vlib_frame_args (frame), frame->n_vectors);
|
||||
if (mif->interrupt_line.fd > 0)
|
||||
if ((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0 && mq->int_fd > -1)
|
||||
{
|
||||
u8 b = rid;
|
||||
CLIB_UNUSED (int r) = write (mif->interrupt_line.fd, &b, sizeof (b));
|
||||
u64 b = 1;
|
||||
CLIB_UNUSED (int r) = write (mq->int_fd, &b, sizeof (b));
|
||||
mq->int_count++;
|
||||
}
|
||||
|
||||
return frame->n_vectors;
|
||||
@ -262,35 +266,35 @@ memif_clear_hw_interface_counters (u32 instance)
|
||||
/* Nothing for now */
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
memif_interface_rx_mode_change (vnet_main_t * vnm, u32 hw_if_index, u32 qid,
|
||||
vnet_hw_interface_rx_mode mode)
|
||||
{
|
||||
memif_main_t *mm = &memif_main;
|
||||
vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
|
||||
memif_if_t *mif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
|
||||
memif_queue_t *mq = vec_elt_at_index (mif->rx_queues, qid);
|
||||
|
||||
if (mode == VNET_HW_INTERFACE_RX_MODE_POLLING)
|
||||
mq->ring->flags |= MEMIF_RING_FLAG_MASK_INT;
|
||||
else
|
||||
mq->ring->flags &= ~MEMIF_RING_FLAG_MASK_INT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
memif_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
|
||||
{
|
||||
memif_main_t *apm = &memif_main;
|
||||
vlib_main_t *vm = vlib_get_main ();
|
||||
memif_msg_t msg = { 0 };
|
||||
memif_main_t *mm = &memif_main;
|
||||
vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
|
||||
memif_if_t *mif = pool_elt_at_index (apm->interfaces, hw->dev_instance);
|
||||
memif_if_t *mif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
|
||||
static clib_error_t *error = 0;
|
||||
|
||||
if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
|
||||
mif->flags |= MEMIF_IF_FLAG_ADMIN_UP;
|
||||
else
|
||||
{
|
||||
mif->flags &= ~MEMIF_IF_FLAG_ADMIN_UP;
|
||||
if (!(mif->flags & MEMIF_IF_FLAG_DELETING)
|
||||
&& mif->connection.index != ~0)
|
||||
{
|
||||
msg.version = MEMIF_VERSION;
|
||||
msg.type = MEMIF_MSG_TYPE_DISCONNECT;
|
||||
if (send (mif->connection.fd, &msg, sizeof (msg), 0) < 0)
|
||||
{
|
||||
clib_unix_warning ("Failed to send disconnect request");
|
||||
error = clib_error_return_unix (0, "send fd %d",
|
||||
mif->connection.fd);
|
||||
memif_disconnect (vm, mif);
|
||||
}
|
||||
}
|
||||
}
|
||||
mif->flags &= ~MEMIF_IF_FLAG_ADMIN_UP;
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -317,6 +321,7 @@ VNET_DEVICE_CLASS (memif_device_class) = {
|
||||
.clear_counters = memif_clear_hw_interface_counters,
|
||||
.admin_up_down_function = memif_interface_admin_up_down,
|
||||
.subif_add_del_function = memif_subif_add_del_function,
|
||||
.rx_mode_change_function = memif_interface_rx_mode_change,
|
||||
};
|
||||
|
||||
VLIB_DEVICE_TX_FUNCTION_MULTIARCH(memif_device_class,
|
||||
|
@ -17,9 +17,10 @@
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param role - role of the interface in the connection (master/slave)
|
||||
@param mode - interface mode
|
||||
@param rx_queues - number of rx queues (only valid for slave)
|
||||
#param tx_queues - number of tx queues (only valid for slave)
|
||||
@param key - 64bit integer used to authenticate and match opposite sides
|
||||
@param id - 32bit integer used to authenticate and match opposite sides
|
||||
of the connection
|
||||
@param socket_filename - filename of the socket to be used for connection
|
||||
establishment
|
||||
@ -33,12 +34,12 @@ define memif_create
|
||||
u32 context;
|
||||
|
||||
u8 role; /* 0 = master, 1 = slave */
|
||||
u8 mode; /* 0 = ethernet, 1 = ip, 2 = punt/inject */
|
||||
u8 rx_queues; /* optional, default is 1 */
|
||||
u8 tx_queues; /* optional, default is 1 */
|
||||
u64 key; /* optional, default is 0 */
|
||||
u8 socket_filename[128]; /* optional, default is "/var/vpp/memif.sock"
|
||||
and can be changed in VPP startup config */
|
||||
|
||||
u32 id; /* optional, default is 0 */
|
||||
u8 socket_filename[128]; /* optional, default is "/var/vpp/memif.sock" */
|
||||
u8 secret[24]; /* optional, default is "" */
|
||||
u32 ring_size; /* optional, default is 1024 entries, must be power of 2 */
|
||||
u16 buffer_size; /* optional, default is 2048 bytes */
|
||||
u8 hw_addr[6]; /* optional, randomly generated if not defined */
|
||||
@ -74,8 +75,9 @@ autoreply define memif_delete
|
||||
@param sw_if_index - index of the interface
|
||||
@param if_name - name of the interface
|
||||
@param hw_addr - interface MAC address
|
||||
@param key - key associated with the interface
|
||||
@param id - id associated with the interface
|
||||
@param role - role of the interface in the connection (master/slave)
|
||||
@param mode - interface mode
|
||||
@param socket_filename - name of the socket used by this interface
|
||||
to establish new connections
|
||||
@param ring_size - the number of entries of RX/TX rings
|
||||
@ -93,8 +95,9 @@ define memif_details
|
||||
u8 hw_addr[6];
|
||||
|
||||
/* memif specific parameters */
|
||||
u64 key;
|
||||
u32 id;
|
||||
u8 role; /* 0 = master, 1 = slave */
|
||||
u8 mode; /* 0 = ethernet, 1 = ip, 2 = punt/inject */
|
||||
u8 socket_filename[128];
|
||||
u32 ring_size;
|
||||
u16 buffer_size; /* optional, default is 2048 bytes */
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -19,7 +19,9 @@
|
||||
|
||||
#include <vlib/vlib.h>
|
||||
#include <vnet/ethernet/ethernet.h>
|
||||
#include <vlib/unix/unix.h>
|
||||
#include <memif/memif.h>
|
||||
#include <memif/private.h>
|
||||
|
||||
#include <vlibapi/api.h>
|
||||
#include <vlibmemory/api.h>
|
||||
@ -107,8 +109,8 @@ vl_api_memif_create_t_handler (vl_api_memif_create_t * mp)
|
||||
static const u8 empty_hw_addr[6];
|
||||
int rv = 0;
|
||||
|
||||
/* key */
|
||||
args.key = clib_net_to_host_u64 (mp->key);
|
||||
/* id */
|
||||
args.id = clib_net_to_host_u32 (mp->id);
|
||||
|
||||
/* socket filename */
|
||||
mp->socket_filename[ARRAY_LEN (mp->socket_filename) - 1] = 0;
|
||||
@ -120,6 +122,15 @@ vl_api_memif_create_t_handler (vl_api_memif_create_t * mp)
|
||||
vec_len (args.socket_filename));
|
||||
}
|
||||
|
||||
/* secret */
|
||||
mp->secret[ARRAY_LEN (mp->secret) - 1] = 0;
|
||||
if (strlen ((char *) mp->secret) > 0)
|
||||
{
|
||||
vec_validate (args.secret, strlen ((char *) mp->secret));
|
||||
strncpy ((char *) args.secret, (char *) mp->secret,
|
||||
vec_len (args.secret));
|
||||
}
|
||||
|
||||
/* role */
|
||||
args.is_master = (mp->role == 0);
|
||||
if (args.is_master == 0)
|
||||
@ -156,6 +167,9 @@ vl_api_memif_create_t_handler (vl_api_memif_create_t * mp)
|
||||
|
||||
rv = memif_create_if (vm, &args);
|
||||
|
||||
vec_free (args.socket_filename);
|
||||
vec_free (args.secret);
|
||||
|
||||
reply:
|
||||
/* *INDENT-OFF* */
|
||||
REPLY_MACRO2 (VL_API_MEMIF_CREATE_REPLY,
|
||||
@ -173,26 +187,19 @@ void
|
||||
vl_api_memif_delete_t_handler (vl_api_memif_delete_t * mp)
|
||||
{
|
||||
memif_main_t *mm = &memif_main;
|
||||
memif_if_t *mif;
|
||||
vlib_main_t *vm = vlib_get_main ();
|
||||
vnet_main_t *vnm = vnet_get_main ();
|
||||
vl_api_memif_delete_reply_t *rmp;
|
||||
u32 sw_if_index = ntohl (mp->sw_if_index);
|
||||
vnet_hw_interface_t *hi =
|
||||
vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index));
|
||||
memif_if_t *mif = pool_elt_at_index (mm->interfaces, hi->dev_instance);
|
||||
int rv = 0;
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
pool_foreach (mif, mm->interfaces,
|
||||
({
|
||||
if (sw_if_index == mif->sw_if_index)
|
||||
{
|
||||
rv = memif_delete_if (vm, mif->key);
|
||||
goto reply;
|
||||
}
|
||||
}));
|
||||
/* *INDENT-ON* */
|
||||
if (hi == NULL || memif_device_class.index != hi->dev_class_index)
|
||||
rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
|
||||
else
|
||||
rv = memif_delete_if (vm, mif);
|
||||
|
||||
rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
|
||||
|
||||
reply:
|
||||
REPLY_MACRO (VL_API_MEMIF_DELETE_REPLY);
|
||||
}
|
||||
|
||||
@ -205,6 +212,8 @@ send_memif_details (unix_shared_memory_queue_t * q,
|
||||
vl_api_memif_details_t *mp;
|
||||
vnet_main_t *vnm = vnet_get_main ();
|
||||
memif_main_t *mm = &memif_main;
|
||||
memif_socket_file_t *msf = vec_elt_at_index (mm->socket_files,
|
||||
mif->socket_file_index);
|
||||
vnet_hw_interface_t *hwif;
|
||||
|
||||
hwif = vnet_get_sup_hw_interface (vnm, swif->sw_if_index);
|
||||
@ -220,14 +229,13 @@ send_memif_details (unix_shared_memory_queue_t * q,
|
||||
(char *) interface_name, ARRAY_LEN (mp->if_name) - 1);
|
||||
memcpy (mp->hw_addr, hwif->hw_address, ARRAY_LEN (mp->hw_addr));
|
||||
|
||||
mp->key = clib_host_to_net_u64 (mif->key);
|
||||
mp->id = clib_host_to_net_u32 (mif->id);
|
||||
mp->role = (mif->flags & MEMIF_IF_FLAG_IS_SLAVE) ? 1 : 0;
|
||||
strncpy ((char *) mp->socket_filename,
|
||||
(char *) mif->socket_filename,
|
||||
ARRAY_LEN (mp->socket_filename) - 1);
|
||||
(char *) msf->filename, ARRAY_LEN (mp->socket_filename) - 1);
|
||||
|
||||
mp->ring_size = htonl (1 << mif->log2_ring_size);
|
||||
mp->buffer_size = htons (mif->buffer_size);
|
||||
mp->ring_size = htonl (1 << mif->run.log2_ring_size);
|
||||
mp->buffer_size = htons (mif->run.buffer_size);
|
||||
|
||||
mp->admin_up_down = (swif->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? 1 : 0;
|
||||
mp->link_up_down = (hwif->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ? 1 : 0;
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <vppinfra/error.h>
|
||||
#include <vnet/ip/ip.h>
|
||||
#include <memif/memif.h>
|
||||
#include <memif/private.h>
|
||||
|
||||
#define __plugin_msg_base memif_test_main.msg_id_base
|
||||
#include <vlibapi/vat_helper_macros.h>
|
||||
@ -118,8 +119,9 @@ api_memif_create (vat_main_t * vam)
|
||||
{
|
||||
unformat_input_t *i = vam->input;
|
||||
vl_api_memif_create_t *mp;
|
||||
u64 key = 0;
|
||||
u32 id = 0;
|
||||
u8 *socket_filename = 0;
|
||||
u8 *secret = 0;
|
||||
u8 role = 1;
|
||||
u32 ring_size = 0;
|
||||
u32 buffer_size = 0;
|
||||
@ -131,10 +133,12 @@ api_memif_create (vat_main_t * vam)
|
||||
|
||||
while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
|
||||
{
|
||||
if (unformat (i, "key 0x%" PRIx64, &key))
|
||||
if (unformat (i, "id %u", &id))
|
||||
;
|
||||
else if (unformat (i, "socket %s", &socket_filename))
|
||||
;
|
||||
else if (unformat (i, "secret %s", &secret))
|
||||
;
|
||||
else if (unformat (i, "ring_size %u", &ring_size))
|
||||
;
|
||||
else if (unformat (i, "buffer_size %u", &buffer_size))
|
||||
@ -173,7 +177,7 @@ api_memif_create (vat_main_t * vam)
|
||||
|
||||
M (MEMIF_CREATE, mp);
|
||||
|
||||
mp->key = clib_host_to_net_u64 (key);
|
||||
mp->id = clib_host_to_net_u32 (id);
|
||||
mp->role = role;
|
||||
mp->ring_size = clib_host_to_net_u32 (ring_size);
|
||||
mp->buffer_size = clib_host_to_net_u16 (buffer_size & 0xffff);
|
||||
@ -182,6 +186,11 @@ api_memif_create (vat_main_t * vam)
|
||||
strncpy ((char *) mp->socket_filename, (char *) socket_filename, 127);
|
||||
vec_free (socket_filename);
|
||||
}
|
||||
if (socket_filename != 0)
|
||||
{
|
||||
strncpy ((char *) mp->secret, (char *) secret, 16);
|
||||
vec_free (socket_filename);
|
||||
}
|
||||
memcpy (mp->hw_addr, hw_addr, 6);
|
||||
mp->rx_queues = rx_queues;
|
||||
mp->tx_queues = tx_queues;
|
||||
@ -282,11 +291,11 @@ static void vl_api_memif_details_t_handler (vl_api_memif_details_t * mp)
|
||||
vat_main_t *vam = memif_test_main.vat_main;
|
||||
|
||||
fformat (vam->ofp, "%s: sw_if_index %u mac %U\n"
|
||||
" key 0x%" PRIx64 " socket %s role %s\n"
|
||||
" id %u socket %s role %s\n"
|
||||
" ring_size %u buffer_size %u\n"
|
||||
" state %s link %s\n",
|
||||
mp->if_name, ntohl (mp->sw_if_index), format_ethernet_address,
|
||||
mp->hw_addr, clib_net_to_host_u64 (mp->key), mp->socket_filename,
|
||||
mp->hw_addr, clib_net_to_host_u32 (mp->id), mp->socket_filename,
|
||||
mp->role ? "slave" : "master",
|
||||
ntohl (mp->ring_size), ntohs (mp->buffer_size),
|
||||
mp->admin_up_down ? "up" : "down",
|
||||
@ -298,7 +307,7 @@ static void vl_api_memif_details_t_handler (vl_api_memif_details_t * mp)
|
||||
* and that the data plane plugin processes
|
||||
*/
|
||||
#define foreach_vpe_api_msg \
|
||||
_(memif_create, "[key <key>] [socket <path>] [ring_size <size>] " \
|
||||
_(memif_create, "[id <id>] [socket <path>] [ring_size <size>] " \
|
||||
"[buffer_size <size>] [hw_addr <mac_address>] " \
|
||||
"<master|slave>") \
|
||||
_(memif_delete, "<sw_if_index>") \
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <vnet/feature/feature.h>
|
||||
|
||||
#include <memif/memif.h>
|
||||
#include <memif/private.h>
|
||||
|
||||
#define foreach_memif_input_error
|
||||
|
||||
@ -78,11 +79,11 @@ memif_prefetch (vlib_main_t * vm, u32 bi)
|
||||
static_always_inline uword
|
||||
memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame, memif_if_t * mif,
|
||||
memif_ring_type_t type, u16 rid)
|
||||
memif_ring_type_t type, u16 qid)
|
||||
{
|
||||
vnet_main_t *vnm = vnet_get_main ();
|
||||
memif_ring_t *ring = memif_get_ring (mif, type, rid);
|
||||
memif_ring_data_t *rd;
|
||||
memif_ring_t *ring;
|
||||
memif_queue_t *mq;
|
||||
u16 head;
|
||||
u32 next_index = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT;
|
||||
uword n_trace = vlib_get_trace_count (vm, node);
|
||||
@ -94,12 +95,14 @@ memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
u32 thread_index = vlib_get_thread_index ();
|
||||
u32 bi0, bi1;
|
||||
vlib_buffer_t *b0, *b1;
|
||||
u16 ring_size = 1 << mif->log2_ring_size;
|
||||
u16 mask = ring_size - 1;
|
||||
u16 num_slots;
|
||||
u16 ring_size, mask, num_slots;
|
||||
void *mb0, *mb1;
|
||||
|
||||
rd = vec_elt_at_index (mif->ring_data, rid + type * mif->num_s2m_rings);
|
||||
mq = vec_elt_at_index (mif->rx_queues, qid);
|
||||
ring = mq->ring;
|
||||
ring_size = 1 << mq->log2_ring_size;
|
||||
mask = ring_size - 1;
|
||||
|
||||
if (mif->per_interface_next_index != ~0)
|
||||
next_index = mif->per_interface_next_index;
|
||||
|
||||
@ -115,13 +118,13 @@ memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
}
|
||||
|
||||
head = ring->head;
|
||||
if (head == rd->last_head)
|
||||
if (head == mq->last_head)
|
||||
return 0;
|
||||
|
||||
if (head > rd->last_head)
|
||||
num_slots = head - rd->last_head;
|
||||
if (head > mq->last_head)
|
||||
num_slots = head - mq->last_head;
|
||||
else
|
||||
num_slots = ring_size - rd->last_head + head;
|
||||
num_slots = ring_size - mq->last_head + head;
|
||||
|
||||
while (num_slots)
|
||||
{
|
||||
@ -132,28 +135,28 @@ memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
|
||||
while (num_slots > 5 && n_left_to_next > 2)
|
||||
{
|
||||
if (PREDICT_TRUE (rd->last_head + 5 < ring_size))
|
||||
if (PREDICT_TRUE (mq->last_head + 5 < ring_size))
|
||||
{
|
||||
CLIB_PREFETCH (memif_get_buffer (mif, ring, rd->last_head + 2),
|
||||
CLIB_PREFETCH (memif_get_buffer (mif, ring, mq->last_head + 2),
|
||||
CLIB_CACHE_LINE_BYTES, LOAD);
|
||||
CLIB_PREFETCH (memif_get_buffer (mif, ring, rd->last_head + 3),
|
||||
CLIB_PREFETCH (memif_get_buffer (mif, ring, mq->last_head + 3),
|
||||
CLIB_CACHE_LINE_BYTES, LOAD);
|
||||
CLIB_PREFETCH (&ring->desc[rd->last_head + 4],
|
||||
CLIB_PREFETCH (&ring->desc[mq->last_head + 4],
|
||||
CLIB_CACHE_LINE_BYTES, LOAD);
|
||||
CLIB_PREFETCH (&ring->desc[rd->last_head + 5],
|
||||
CLIB_PREFETCH (&ring->desc[mq->last_head + 5],
|
||||
CLIB_CACHE_LINE_BYTES, LOAD);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLIB_PREFETCH (memif_get_buffer
|
||||
(mif, ring, (rd->last_head + 2) % mask),
|
||||
(mif, ring, (mq->last_head + 2) % mask),
|
||||
CLIB_CACHE_LINE_BYTES, LOAD);
|
||||
CLIB_PREFETCH (memif_get_buffer
|
||||
(mif, ring, (rd->last_head + 3) % mask),
|
||||
(mif, ring, (mq->last_head + 3) % mask),
|
||||
CLIB_CACHE_LINE_BYTES, LOAD);
|
||||
CLIB_PREFETCH (&ring->desc[(rd->last_head + 4) % mask],
|
||||
CLIB_PREFETCH (&ring->desc[(mq->last_head + 4) % mask],
|
||||
CLIB_CACHE_LINE_BYTES, LOAD);
|
||||
CLIB_PREFETCH (&ring->desc[(rd->last_head + 5) % mask],
|
||||
CLIB_PREFETCH (&ring->desc[(mq->last_head + 5) % mask],
|
||||
CLIB_CACHE_LINE_BYTES, LOAD);
|
||||
}
|
||||
/* get empty buffer */
|
||||
@ -185,17 +188,17 @@ memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
|
||||
|
||||
/* copy buffer */
|
||||
mb0 = memif_get_buffer (mif, ring, rd->last_head);
|
||||
mb0 = memif_get_buffer (mif, ring, mq->last_head);
|
||||
clib_memcpy (vlib_buffer_get_current (b0), mb0,
|
||||
CLIB_CACHE_LINE_BYTES);
|
||||
b0->current_length = ring->desc[rd->last_head].length;
|
||||
rd->last_head = (rd->last_head + 1) & mask;
|
||||
b0->current_length = ring->desc[mq->last_head].length;
|
||||
mq->last_head = (mq->last_head + 1) & mask;
|
||||
|
||||
mb1 = memif_get_buffer (mif, ring, rd->last_head);
|
||||
mb1 = memif_get_buffer (mif, ring, mq->last_head);
|
||||
clib_memcpy (vlib_buffer_get_current (b1), mb1,
|
||||
CLIB_CACHE_LINE_BYTES);
|
||||
b1->current_length = ring->desc[rd->last_head].length;
|
||||
rd->last_head = (rd->last_head + 1) & mask;
|
||||
b1->current_length = ring->desc[mq->last_head].length;
|
||||
mq->last_head = (mq->last_head + 1) & mask;
|
||||
|
||||
if (b0->current_length > CLIB_CACHE_LINE_BYTES)
|
||||
clib_memcpy (vlib_buffer_get_current (b0) + CLIB_CACHE_LINE_BYTES,
|
||||
@ -221,7 +224,7 @@ memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
|
||||
tr->next_index = next0;
|
||||
tr->hw_if_index = mif->hw_if_index;
|
||||
tr->ring = rid;
|
||||
tr->ring = qid;
|
||||
|
||||
if (n_trace)
|
||||
{
|
||||
@ -233,7 +236,7 @@ memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
tr = vlib_add_trace (vm, node, b1, sizeof (*tr));
|
||||
tr->next_index = next1;
|
||||
tr->hw_if_index = mif->hw_if_index;
|
||||
tr->ring = rid;
|
||||
tr->ring = qid;
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,12 +269,12 @@ memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
|
||||
/* fill buffer metadata */
|
||||
b0 = vlib_get_buffer (vm, bi0);
|
||||
b0->current_length = ring->desc[rd->last_head].length;
|
||||
b0->current_length = ring->desc[mq->last_head].length;
|
||||
vnet_buffer (b0)->sw_if_index[VLIB_RX] = mif->sw_if_index;
|
||||
vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
|
||||
|
||||
/* copy buffer */
|
||||
mb0 = memif_get_buffer (mif, ring, rd->last_head);
|
||||
mb0 = memif_get_buffer (mif, ring, mq->last_head);
|
||||
clib_memcpy (vlib_buffer_get_current (b0), mb0,
|
||||
CLIB_CACHE_LINE_BYTES);
|
||||
if (b0->current_length > CLIB_CACHE_LINE_BYTES)
|
||||
@ -291,7 +294,7 @@ memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
|
||||
tr->next_index = next0;
|
||||
tr->hw_if_index = mif->hw_if_index;
|
||||
tr->ring = rid;
|
||||
tr->ring = qid;
|
||||
}
|
||||
|
||||
|
||||
@ -303,7 +306,7 @@ memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
n_left_to_next, bi0, next0);
|
||||
|
||||
/* next packet */
|
||||
rd->last_head = (rd->last_head + 1) & mask;
|
||||
mq->last_head = (mq->last_head + 1) & mask;
|
||||
num_slots--;
|
||||
n_rx_packets++;
|
||||
n_rx_bytes += b0->current_length;
|
||||
@ -325,30 +328,28 @@ static uword
|
||||
memif_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame)
|
||||
{
|
||||
u32 n_rx_packets = 0;
|
||||
u32 n_rx = 0;
|
||||
memif_main_t *nm = &memif_main;
|
||||
memif_if_t *mif;
|
||||
vnet_device_input_runtime_t *rt = (void *) node->runtime_data;
|
||||
vnet_device_and_queue_t *dq;
|
||||
memif_ring_type_t type;
|
||||
|
||||
foreach_device_and_queue (dq, rt->devices_and_queues)
|
||||
{
|
||||
memif_if_t *mif;
|
||||
mif = vec_elt_at_index (nm->interfaces, dq->dev_instance);
|
||||
if ((mif->flags & MEMIF_IF_FLAG_ADMIN_UP) &&
|
||||
(mif->flags & MEMIF_IF_FLAG_CONNECTED))
|
||||
{
|
||||
if (mif->flags & MEMIF_IF_FLAG_IS_SLAVE)
|
||||
type = MEMIF_RING_M2S;
|
||||
n_rx += memif_device_input_inline (vm, node, frame, mif,
|
||||
MEMIF_RING_M2S, dq->queue_id);
|
||||
else
|
||||
type = MEMIF_RING_S2M;
|
||||
n_rx_packets +=
|
||||
memif_device_input_inline (vm, node, frame, mif, type,
|
||||
dq->queue_id);
|
||||
n_rx += memif_device_input_inline (vm, node, frame, mif,
|
||||
MEMIF_RING_S2M, dq->queue_id);
|
||||
}
|
||||
}
|
||||
|
||||
return n_rx_packets;
|
||||
return n_rx;
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
|
296
src/plugins/memif/private.h
Normal file
296
src/plugins/memif/private.h
Normal file
@ -0,0 +1,296 @@
|
||||
/*
|
||||
*------------------------------------------------------------------
|
||||
* Copyright (c) 2017 Cisco and/or its affiliates.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <vppinfra/lock.h>
|
||||
|
||||
#define MEMIF_DEFAULT_SOCKET_DIR "/run/vpp"
|
||||
#define MEMIF_DEFAULT_SOCKET_FILENAME "memif.sock"
|
||||
#define MEMIF_DEFAULT_RING_SIZE 1024
|
||||
#define MEMIF_DEFAULT_RX_QUEUES 1
|
||||
#define MEMIF_DEFAULT_TX_QUEUES 1
|
||||
#define MEMIF_DEFAULT_BUFFER_SIZE 2048
|
||||
|
||||
#define MEMIF_VERSION_MAJOR 0
|
||||
#define MEMIF_VERSION_MINOR 1
|
||||
#define MEMIF_VERSION ((MEMIF_VERSION_MAJOR << 8) | MEMIF_VERSION_MINOR)
|
||||
#define MEMIF_COOKIE 0xdeadbeef
|
||||
#define MEMIF_MAX_M2S_RING (vec_len (vlib_mains) - 1)
|
||||
#define MEMIF_MAX_S2M_RING (vec_len (vlib_mains) - 1)
|
||||
#define MEMIF_MAX_REGION 255
|
||||
#define MEMIF_MAX_LOG2_RING_SIZE 14
|
||||
|
||||
#define MEMIF_DEBUG 0
|
||||
|
||||
#if MEMIF_DEBUG == 1
|
||||
#define DBG(...) clib_warning(__VA_ARGS__)
|
||||
#define DBG_UNIX_LOG(...) clib_unix_warning(__VA_ARGS__)
|
||||
#else
|
||||
#define DBG(...)
|
||||
#define DBG_UNIX_LOG(...)
|
||||
#endif
|
||||
|
||||
#if MEMIF_DEBUG == 1
|
||||
#define memif_file_add(a, b) do { \
|
||||
ASSERT (*a == ~0); \
|
||||
*a = unix_file_add (&unix_main, b); \
|
||||
clib_warning ("unix_file_add fd %d private_data %u idx %u", \
|
||||
(b)->file_descriptor, (b)->private_data, *a); \
|
||||
} while (0)
|
||||
|
||||
#define memif_file_del(a) do { \
|
||||
clib_warning ("unix_file_del idx %u",a - unix_main.file_pool); \
|
||||
unix_file_del (&unix_main, a); \
|
||||
} while (0)
|
||||
|
||||
#define memif_file_del_by_index(a) do { \
|
||||
clib_warning ("unix_file_del idx %u", a); \
|
||||
unix_file_del_by_index (&unix_main, a); \
|
||||
} while (0)
|
||||
#else
|
||||
#define memif_file_add(a, b) do { \
|
||||
ASSERT (*a == ~0); \
|
||||
*a = unix_file_add (&unix_main, b); \
|
||||
} while (0)
|
||||
#define memif_file_del(a) unix_file_del(&unix_main, a)
|
||||
#define memif_file_del_by_index(a) unix_file_del_by_index(&unix_main, a)
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 *filename;
|
||||
int fd;
|
||||
uword unix_file_index;
|
||||
uword *pending_file_indices;
|
||||
int ref_cnt;
|
||||
int is_listener;
|
||||
|
||||
/* hash of all registered id */
|
||||
mhash_t dev_instance_by_id;
|
||||
|
||||
/* hash of all registered fds */
|
||||
uword *dev_instance_by_fd;
|
||||
} memif_socket_file_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *shm;
|
||||
u32 region_size;
|
||||
int fd;
|
||||
} memif_region_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
memif_msg_t msg;
|
||||
int fd;
|
||||
} memif_msg_fifo_elt_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* ring data */
|
||||
memif_ring_t *ring;
|
||||
u8 log2_ring_size;
|
||||
u8 region;
|
||||
u32 offset;
|
||||
|
||||
u16 last_head;
|
||||
u16 last_tail;
|
||||
|
||||
/* interrupts */
|
||||
int int_fd;
|
||||
uword int_unix_file_index;
|
||||
u64 int_count;
|
||||
} memif_queue_t;
|
||||
|
||||
#define foreach_memif_if_flag \
|
||||
_(0, ADMIN_UP, "admin-up") \
|
||||
_(1, IS_SLAVE, "slave") \
|
||||
_(2, CONNECTING, "connecting") \
|
||||
_(3, CONNECTED, "connected") \
|
||||
_(4, DELETING, "deleting")
|
||||
|
||||
typedef enum
|
||||
{
|
||||
#define _(a, b, c) MEMIF_IF_FLAG_##b = (1 << a),
|
||||
foreach_memif_if_flag
|
||||
#undef _
|
||||
} memif_if_flag_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
|
||||
clib_spinlock_t lockp;
|
||||
u32 flags;
|
||||
memif_interface_id_t id;
|
||||
u32 hw_if_index;
|
||||
u32 sw_if_index;
|
||||
uword dev_instance;
|
||||
memif_interface_mode_t mode:8;
|
||||
|
||||
u32 per_interface_next_index;
|
||||
|
||||
/* socket connection */
|
||||
uword socket_file_index;
|
||||
int conn_fd;
|
||||
uword conn_unix_file_index;
|
||||
memif_msg_fifo_elt_t *msg_queue;
|
||||
u8 *secret;
|
||||
|
||||
memif_region_t *regions;
|
||||
|
||||
memif_queue_t *rx_queues;
|
||||
memif_queue_t *tx_queues;
|
||||
|
||||
/* remote info */
|
||||
pid_t remote_pid;
|
||||
uid_t remote_uid;
|
||||
gid_t remote_gid;
|
||||
u8 *remote_name;
|
||||
u8 *remote_if_name;
|
||||
|
||||
struct
|
||||
{
|
||||
u8 log2_ring_size;
|
||||
u8 num_s2m_rings;
|
||||
u8 num_m2s_rings;
|
||||
u16 buffer_size;
|
||||
} cfg;
|
||||
|
||||
struct
|
||||
{
|
||||
u8 log2_ring_size;
|
||||
u8 num_s2m_rings;
|
||||
u8 num_m2s_rings;
|
||||
u16 buffer_size;
|
||||
} run;
|
||||
|
||||
/* disconnect strings */
|
||||
u8 *local_disc_string;
|
||||
u8 *remote_disc_string;
|
||||
} memif_if_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
|
||||
|
||||
/** API message ID base */
|
||||
u16 msg_id_base;
|
||||
|
||||
/* pool of all memory interfaces */
|
||||
memif_if_t *interfaces;
|
||||
|
||||
/* pool of all unix socket files */
|
||||
memif_socket_file_t *socket_files;
|
||||
mhash_t socket_file_index_by_filename;
|
||||
|
||||
/* rx buffer cache */
|
||||
u32 **rx_buffers;
|
||||
|
||||
} memif_main_t;
|
||||
|
||||
extern memif_main_t memif_main;
|
||||
extern vnet_device_class_t memif_device_class;
|
||||
extern vlib_node_registration_t memif_input_node;
|
||||
|
||||
enum
|
||||
{
|
||||
MEMIF_PROCESS_EVENT_START = 1,
|
||||
MEMIF_PROCESS_EVENT_STOP = 2,
|
||||
} memif_process_event_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
memif_interface_id_t id;
|
||||
u8 *socket_filename;
|
||||
u8 *secret;
|
||||
u8 is_master;
|
||||
memif_interface_mode_t mode:8;
|
||||
u8 log2_ring_size;
|
||||
u16 buffer_size;
|
||||
u8 hw_addr_set;
|
||||
u8 hw_addr[6];
|
||||
u8 rx_queues;
|
||||
u8 tx_queues;
|
||||
|
||||
/* return */
|
||||
u32 sw_if_index;
|
||||
} memif_create_if_args_t;
|
||||
|
||||
int memif_create_if (vlib_main_t * vm, memif_create_if_args_t * args);
|
||||
int memif_delete_if (vlib_main_t * vm, memif_if_t * mif);
|
||||
clib_error_t *memif_plugin_api_hookup (vlib_main_t * vm);
|
||||
|
||||
#ifndef __NR_memfd_create
|
||||
#if defined __x86_64__
|
||||
#define __NR_memfd_create 319
|
||||
#elif defined __arm__
|
||||
#define __NR_memfd_create 385
|
||||
#elif defined __aarch64__
|
||||
#define __NR_memfd_create 279
|
||||
#else
|
||||
#error "__NR_memfd_create unknown for this architecture"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static inline int
|
||||
memfd_create (const char *name, unsigned int flags)
|
||||
{
|
||||
return syscall (__NR_memfd_create, name, flags);
|
||||
}
|
||||
|
||||
static_always_inline void *
|
||||
memif_get_buffer (memif_if_t * mif, memif_ring_t * ring, u16 slot)
|
||||
{
|
||||
u16 region = ring->desc[slot].region;
|
||||
return mif->regions[region].shm + ring->desc[slot].offset;
|
||||
}
|
||||
|
||||
#ifndef F_LINUX_SPECIFIC_BASE
|
||||
#define F_LINUX_SPECIFIC_BASE 1024
|
||||
#endif
|
||||
#define MFD_ALLOW_SEALING 0x0002U
|
||||
#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
|
||||
#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
|
||||
|
||||
#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */
|
||||
#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */
|
||||
#define F_SEAL_GROW 0x0004 /* prevent file from growing */
|
||||
#define F_SEAL_WRITE 0x0008 /* prevent writes */
|
||||
|
||||
/* memif.c */
|
||||
clib_error_t *memif_init_regions_and_queues (memif_if_t * mif);
|
||||
clib_error_t *memif_connect (memif_if_t * mif);
|
||||
void memif_disconnect (memif_if_t * mif, clib_error_t * err);
|
||||
|
||||
/* socket.c */
|
||||
clib_error_t *memif_conn_fd_accept_ready (unix_file_t * uf);
|
||||
clib_error_t *memif_master_conn_fd_read_ready (unix_file_t * uf);
|
||||
clib_error_t *memif_slave_conn_fd_read_ready (unix_file_t * uf);
|
||||
clib_error_t *memif_master_conn_fd_write_ready (unix_file_t * uf);
|
||||
clib_error_t *memif_slave_conn_fd_write_ready (unix_file_t * uf);
|
||||
clib_error_t *memif_master_conn_fd_error (unix_file_t * uf);
|
||||
clib_error_t *memif_slave_conn_fd_error (unix_file_t * uf);
|
||||
clib_error_t *memif_msg_send_disconnect (memif_if_t * mif,
|
||||
clib_error_t * err);
|
||||
u8 *format_memif_device_name (u8 * s, va_list * args);
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
736
src/plugins/memif/socket.c
Normal file
736
src/plugins/memif/socket.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user