aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Loeliger <jdl@netgate.com>2018-01-16 16:37:16 -0600
committerDamjan Marion <damarion@cisco.com>2018-01-29 13:09:57 +0100
commit30349b075cf939549980f2a32e030b32f6d07e9a (patch)
treeebf4a6e10c49cd9657cefeadafbaa44f07c5c021
parentb4d43d7901b49bdda4345adb86b4d15a5d72f7ff (diff)
memif: Add new API calls to manage memif socket names.
New API calls and corresponding CLI commands allow the user to manage the socket filenames for memif connections using: vppctl# create memif id <u32> filename <socket-filename> vppctl# delete memif id <u32> and then referencing it later in a memif interface: vppctl# create memif <u32> socket-id <id> mode <mode> <master|slave> ... Corresponding VAT cli entries have also been added. The default memif socket file at id 0 are still always present. The existing memif create/delete CLI commands have been slightly altered into the new syntax: vppctl# create interface memif ... vppctl# delete interface memif ... Change-Id: If2bdc7eac3d81e1d9011a5869747e52fc5e11639 Signed-off-by: Jon Loeliger <jdl@netgate.com> Signed-off-by: Damjan Marion <damarion@cisco.com>
-rw-r--r--src/plugins/memif/cli.c207
-rw-r--r--src/plugins/memif/device.c4
-rw-r--r--src/plugins/memif/memif.api52
-rw-r--r--src/plugins/memif/memif.c172
-rw-r--r--src/plugins/memif/memif_api.c144
-rw-r--r--src/plugins/memif/memif_test.c163
-rw-r--r--src/plugins/memif/private.h7
7 files changed, 647 insertions, 102 deletions
diff --git a/src/plugins/memif/cli.c b/src/plugins/memif/cli.c
index 29d13310776..3f0e28179e2 100644
--- a/src/plugins/memif/cli.c
+++ b/src/plugins/memif/cli.c
@@ -26,6 +26,147 @@
#include <memif/memif.h>
#include <memif/private.h>
+
+static clib_error_t *
+memif_socket_filename_create_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ unformat_input_t _line_input, *line_input = &_line_input;
+ int r;
+ u32 socket_id;
+ u8 *socket_filename;
+
+ /* Get a line of input. */
+ if (!unformat_user (input, unformat_line_input, line_input))
+ return 0;
+
+ socket_id = ~0;
+ socket_filename = 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "id %u", &socket_id))
+ ;
+ else if (unformat (line_input, "filename %s", &socket_filename))
+ ;
+ else
+ {
+ vec_free (socket_filename);
+ return clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, input);
+ }
+ }
+
+ unformat_free (line_input);
+
+ if (socket_id == 0 || socket_id == ~0)
+ {
+ vec_free (socket_filename);
+ return clib_error_return (0, "Invalid socket id");
+ }
+
+ if (!socket_filename || *socket_filename == 0)
+ {
+ vec_free (socket_filename);
+ return clib_error_return (0, "Invalid socket filename");
+ }
+
+ r = memif_socket_filename_add_del (1, socket_id, socket_filename);
+
+ vec_free (socket_filename);
+
+ if (r < 0)
+ {
+ switch (r)
+ {
+ case VNET_API_ERROR_INVALID_ARGUMENT:
+ return clib_error_return (0, "Invalid argument");
+ case VNET_API_ERROR_SYSCALL_ERROR_1:
+ return clib_error_return (0, "Syscall error 1");
+ case VNET_API_ERROR_ENTRY_ALREADY_EXISTS:
+ return clib_error_return (0, "Already exists");
+ case VNET_API_ERROR_UNEXPECTED_INTF_STATE:
+ return clib_error_return (0, "Interface still in use");
+ default:
+ return clib_error_return (0, "Unknown error");
+ }
+ }
+
+ return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (memif_socket_filename_create_command, static) = {
+ .path = "create memif socket",
+ .short_help = "create memif socket [id <id>] [filename <path>]",
+ .function = memif_socket_filename_create_command_fn,
+};
+/* *INDENT-ON* */
+
+static clib_error_t *
+memif_socket_filename_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;
+ int r;
+ u32 socket_id;
+
+ /* Get a line of input. */
+ if (!unformat_user (input, unformat_line_input, line_input))
+ return 0;
+
+ socket_id = ~0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "id %u", &socket_id))
+ ;
+ else
+ {
+ return clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, input);
+ }
+ }
+
+ unformat_free (line_input);
+
+ if (socket_id == 0 || socket_id == ~0)
+ {
+ return clib_error_return (0, "Invalid socket id");
+ }
+
+ r = memif_socket_filename_add_del (0, socket_id, 0);
+
+ if (r < 0)
+ {
+ switch (r)
+ {
+ case VNET_API_ERROR_INVALID_ARGUMENT:
+ return clib_error_return (0, "Invalid argument");
+ case VNET_API_ERROR_SYSCALL_ERROR_1:
+ return clib_error_return (0, "Syscall error 1");
+ case VNET_API_ERROR_ENTRY_ALREADY_EXISTS:
+ return clib_error_return (0, "Already exists");
+ case VNET_API_ERROR_UNEXPECTED_INTF_STATE:
+ return clib_error_return (0, "Interface still in use");
+ default:
+ return clib_error_return (0, "Unknown error");
+ }
+ }
+
+ return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (memif_socket_filename_delete_command, static) = {
+ .path = "delete memif socket",
+ .short_help = "delete memif socket [id <id>]",
+ .function = memif_socket_filename_delete_command_fn,
+};
+/* *INDENT-ON* */
+
static clib_error_t *
memif_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
vlib_cli_command_t * cmd)
@@ -46,7 +187,7 @@ memif_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
{
if (unformat (line_input, "id %u", &args.id))
;
- else if (unformat (line_input, "socket %s", &args.socket_filename))
+ else if (unformat (line_input, "socket-id %u", &args.socket_id))
;
else if (unformat (line_input, "secret %s", &args.secret))
;
@@ -91,13 +232,15 @@ 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);
+ if (r == VNET_API_ERROR_INVALID_ARGUMENT)
+ return clib_error_return (0, "Invalid argument");
+
if (r == VNET_API_ERROR_INVALID_INTERFACE)
return clib_error_return (0, "Invalid interface name");
@@ -109,9 +252,10 @@ 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 [id <id>] [socket <path>] "
- "[ring-size <size>] [buffer-size <size>] [hw-addr <mac-address>] "
+ .path = "create interface memif",
+ .short_help = "create interface memif [id <id>] [socket-id <socket-id>] "
+ "[ring-size <size>] [buffer-size <size>] "
+ "[hw-addr <mac-address>] "
"<master|slave> [rx-queues <number>] [tx-queues <number>] "
"[mode ip] [secret <string>]",
.function = memif_create_command_fn,
@@ -119,6 +263,22 @@ VLIB_CLI_COMMAND (memif_create_command, static) = {
/* *INDENT-ON* */
static clib_error_t *
+create_memif_command_fn (vlib_main_t * vm, unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ vlib_cli_output (vm, "command deprecated. Please use "
+ "'create interface memif' instead.\n");
+ return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (create_memif_command, static) = {
+ .path = "create memif",
+ .function = create_memif_command_fn,
+};
+/* *INDENT-ON* */
+
+static clib_error_t *
memif_delete_command_fn (vlib_main_t * vm, unformat_input_t * input,
vlib_cli_command_t * cmd)
{
@@ -162,8 +322,8 @@ 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 {<interface> | sw_if_index <sw_idx>}",
+ .path = "delete interface memif",
+ .short_help = "delete interface memif {<interface> | sw_if_index <sw_idx>}",
.function = memif_delete_command_fn,
};
/* *INDENT-ON* */
@@ -267,6 +427,9 @@ memif_show_command_fn (vlib_main_t * vm, unformat_input_t * input,
int show_descr = 0;
clib_error_t *error = 0;
u32 hw_if_index, *hw_if_indices = 0;
+ u32 sock_id;
+ u32 msf_idx;
+ u8 *s = 0;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
@@ -283,6 +446,30 @@ memif_show_command_fn (vlib_main_t * vm, unformat_input_t * input,
}
}
+ vlib_cli_output (vm, "sockets\n");
+ vlib_cli_output (vm, " %-3s %-11s %s\n", "id", "listener", "filename");
+
+ /* *INDENT-OFF* */
+ hash_foreach (sock_id, msf_idx, mm->socket_file_index_by_sock_id,
+ ({
+ memif_socket_file_t *msf;
+ u8 *filename;
+
+ msf = pool_elt_at_index(mm->socket_files, msf_idx);
+ filename = msf->filename;
+ if (msf->is_listener)
+ s = format (s, "yes (%u)", msf->ref_cnt);
+ else
+ s = format (s, "no");
+
+ vlib_cli_output(vm, " %-3u %-11v %s\n", sock_id, s, filename);
+ vec_reset_length (s);
+ }));
+ /* *INDENT-ON* */
+ vec_free (s);
+
+ vlib_cli_output (vm, "\n");
+
if (vec_len (hw_if_indices) == 0)
{
/* *INDENT-OFF* */
@@ -306,8 +493,8 @@ memif_show_command_fn (vlib_main_t * vm, unformat_input_t * input,
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, " socket-id %u id %u mode %U", msf->socket_id,
+ mif->id, format_memif_if_mode, mif);
vlib_cli_output (vm, " flags%U", format_memif_if_flags, mif->flags);
vlib_cli_output (vm, " listener-fd %d conn-fd %d",
msf->sock ? msf->sock->fd : 0,
@@ -347,7 +534,7 @@ done:
/* *INDENT-OFF* */
VLIB_CLI_COMMAND (memif_show_command, static) = {
.path = "show memif",
- .short_help = "show memif {<interface>] [descriptors]",
+ .short_help = "show memif [<interface>] [descriptors]",
.function = memif_show_command_fn,
};
/* *INDENT-ON* */
diff --git a/src/plugins/memif/device.c b/src/plugins/memif/device.c
index 3809061e434..22f9753dc42 100644
--- a/src/plugins/memif/device.c
+++ b/src/plugins/memif/device.c
@@ -54,8 +54,10 @@ format_memif_device_name (u8 * s, va_list * args)
u32 dev_instance = va_arg (*args, u32);
memif_main_t *mm = &memif_main;
memif_if_t *mif = pool_elt_at_index (mm->interfaces, dev_instance);
+ memif_socket_file_t *msf;
- s = format (s, "memif%lu/%lu", mif->socket_file_index, mif->id);
+ msf = pool_elt_at_index (mm->socket_files, mif->socket_file_index);
+ s = format (s, "memif%lu/%lu", msf->socket_id, mif->id);
return s;
}
#endif
diff --git a/src/plugins/memif/memif.api b/src/plugins/memif/memif.api
index cd09b92dc9c..6a61ee110ae 100644
--- a/src/plugins/memif/memif.api
+++ b/src/plugins/memif/memif.api
@@ -13,7 +13,25 @@
* limitations under the License.
*/
-option version = "1.0.0";
+option version = "2.0.0";
+
+/** \brief Create or remove named socket file for memif interfaces
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param is_add - 0 = remove, 1 = add association
+ @param socket_id - non-0 32-bit integer used to identify a socket file
+ @param socket_filename - filename of the socket to be used for connection
+ establishment; id 0 always maps to default "/var/vpp/memif.sock";
+ no socket filename needed when is_add == 0.
+*/
+autoreply define memif_socket_filename_add_del
+{
+ u32 client_index;
+ u32 context;
+ u8 is_add; /* 0 = remove, 1 = add association */
+ u32 socket_id; /* unique non-0 id for given socket file name */
+ u8 socket_filename[128]; /* NUL terminated filename */
+};
/** \brief Create memory interface
@param client_index - opaque cookie to identify the sender
@@ -21,10 +39,10 @@ option version = "1.0.0";
@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 tx_queues - number of tx queues (only valid for slave)
@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
+ @param socket_id - socket filename id to be used for connection
establishment
@param ring_size - the number of entries of RX/TX rings
@param buffer_size - size of the buffer allocated for each ring entry
@@ -40,7 +58,7 @@ define memif_create
u8 rx_queues; /* optional, default is 1 */
u8 tx_queues; /* optional, default is 1 */
u32 id; /* optional, default is 0 */
- u8 socket_filename[128]; /* optional, default is "/var/vpp/memif.sock" */
+ u32 socket_id; /* optional, default is 0, "/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 */
@@ -73,6 +91,28 @@ autoreply define memif_delete
};
/** \brief Memory interface details structure
+ @param context - sender context, to match reply w/ request
+ @param socket_id - u32 used to identify the given socket filename
+ @param socket_filename - correpsonding NUL terminated socket filename
+*/
+define memif_socket_filename_details
+{
+ u32 context;
+ u32 socket_id;
+ u8 socket_filename[128];
+};
+
+/** \brief Dump the table of socket ids and corresponding filenames
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+*/
+define memif_socket_filename_dump
+{
+ u32 client_index;
+ u32 context;
+};
+
+/** \brief Memory interface details structure
@param context - sender context, to match reply w/ request (memif_dump)
@param sw_if_index - index of the interface
@param if_name - name of the interface
@@ -80,7 +120,7 @@ autoreply define memif_delete
@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
+ @param socket_id - id of the socket filename used by this interface
to establish new connections
@param ring_size - the number of entries of RX/TX rings
@param buffer_size - size of the buffer allocated for each ring entry
@@ -100,7 +140,7 @@ define memif_details
u32 id;
u8 role; /* 0 = master, 1 = slave */
u8 mode; /* 0 = ethernet, 1 = ip, 2 = punt/inject */
- u8 socket_filename[128];
+ u32 socket_id;
u32 ring_size;
u16 buffer_size; /* optional, default is 2048 bytes */
diff --git a/src/plugins/memif/memif.c b/src/plugins/memif/memif.c
index aa476be9a98..dc92e7e24ad 100644
--- a/src/plugins/memif/memif.c
+++ b/src/plugins/memif/memif.c
@@ -462,6 +462,109 @@ VLIB_REGISTER_NODE (memif_process_node,static) = {
};
/* *INDENT-ON* */
+
+static int
+memif_add_socket_file (u32 sock_id, u8 * socket_filename)
+{
+ memif_main_t *mm = &memif_main;
+ uword *p;
+ memif_socket_file_t *msf;
+
+ p = hash_get (mm->socket_file_index_by_sock_id, sock_id);
+ if (p)
+ {
+ msf = pool_elt_at_index (mm->socket_files, *p);
+ if (strcmp ((char *) msf->filename, (char *) socket_filename) == 0)
+ {
+ /* Silently accept identical "add". */
+ return 0;
+ }
+
+ /* But don't allow a direct add of a different filename. */
+ return VNET_API_ERROR_ENTRY_ALREADY_EXISTS;
+ }
+
+ DBG ("creating socket file (uninitialized) %s", msf->filename);
+
+ pool_get (mm->socket_files, msf);
+ memset (msf, 0, sizeof (memif_socket_file_t));
+
+ msf->filename = socket_filename;
+ msf->socket_id = sock_id;
+
+ hash_set (mm->socket_file_index_by_sock_id, sock_id,
+ msf - mm->socket_files);
+
+ return 0;
+}
+
+static int
+memif_delete_socket_file (u32 sock_id)
+{
+ memif_main_t *mm = &memif_main;
+ uword *p;
+ memif_socket_file_t *msf;
+
+ p = hash_get (mm->socket_file_index_by_sock_id, sock_id);
+ if (!p)
+ {
+ /* Don't delete non-existent entries. */
+ return VNET_API_ERROR_INVALID_ARGUMENT;
+ }
+
+ msf = pool_elt_at_index (mm->socket_files, *p);
+ if (msf->ref_cnt > 0)
+ {
+ return VNET_API_ERROR_UNEXPECTED_INTF_STATE;
+ }
+
+ vec_free (msf->filename);
+ pool_put (mm->socket_files, msf);
+
+ hash_unset (mm->socket_file_index_by_sock_id, sock_id);
+
+ return 0;
+}
+
+int
+memif_socket_filename_add_del (u8 is_add, u32 sock_id, u8 * sock_filename)
+{
+ if (sock_id == 0 || sock_id == ~0)
+ {
+ return VNET_API_ERROR_INVALID_ARGUMENT;
+ }
+
+ if (is_add == 0)
+ {
+ return memif_delete_socket_file (sock_id);
+ }
+
+ if (sock_filename == 0 || sock_filename[0] == 0)
+ {
+ return VNET_API_ERROR_INVALID_ARGUMENT;
+ }
+
+ if (sock_filename[0] != '/')
+ {
+ clib_error_t *error;
+ error = vlib_unix_recursive_mkdir (vlib_unix_get_runtime_dir ());
+ if (error)
+ {
+ clib_error_free (error);
+ return VNET_API_ERROR_SYSCALL_ERROR_1;
+ }
+
+ sock_filename = format (0, "%s/%s%c", vlib_unix_get_runtime_dir (),
+ sock_filename, 0);
+ }
+ else
+ {
+ sock_filename = vec_dup (sock_filename);
+ }
+
+ return memif_add_socket_file (sock_id, sock_filename);
+}
+
int
memif_delete_if (vlib_main_t * vm, memif_if_t * mif)
{
@@ -509,8 +612,6 @@ memif_delete_if (vlib_main_t * vm, memif_if_t * mif)
}
mhash_free (&msf->dev_instance_by_id);
hash_free (msf->dev_instance_by_fd);
- mhash_unset (&mm->socket_file_index_by_filename, msf->filename, 0);
- vec_free (msf->filename);
if (msf->sock)
{
err = clib_socket_close (msf->sock);
@@ -518,7 +619,6 @@ memif_delete_if (vlib_main_t * vm, memif_if_t * mif)
clib_error_report (err);
clib_mem_free (msf->sock);
}
- pool_put (mm->socket_files, msf);
}
memset (mif, 0, sizeof (*mif));
@@ -552,38 +652,21 @@ memif_create_if (vlib_main_t * vm, memif_create_if_args_t * args)
uword *p;
vnet_hw_interface_t *hw;
memif_socket_file_t *msf = 0;
- u8 *socket_filename;
int rv = 0;
- if (args->socket_filename == 0 || args->socket_filename[0] != '/')
+ p = hash_get (mm->socket_file_index_by_sock_id, args->socket_id);
+ if (p == 0)
{
- clib_error_t *error;
- error = vlib_unix_recursive_mkdir (vlib_unix_get_runtime_dir ());
- if (error)
- {
- clib_error_free (error);
- return VNET_API_ERROR_SYSCALL_ERROR_1;
- }
-
- if (args->socket_filename == 0)
- socket_filename = format (0, "%s/%s%c", vlib_unix_get_runtime_dir (),
- MEMIF_DEFAULT_SOCKET_FILENAME, 0);
- else
- socket_filename = format (0, "%s/%s%c", vlib_unix_get_runtime_dir (),
- args->socket_filename, 0);
-
+ rv = VNET_API_ERROR_INVALID_ARGUMENT;
+ goto done;
}
- else
- socket_filename = vec_dup (args->socket_filename);
- p = mhash_get (&mm->socket_file_index_by_filename, socket_filename);
+ msf = vec_elt_at_index (mm->socket_files, p[0]);
- if (p)
+ /* existing socket file can be either master or slave but cannot be both */
+ if (msf->ref_cnt > 0)
{
- msf = vec_elt_at_index (mm->socket_files, p[0]);
-
- /* existing socket file can be either master or slave but cannot be both */
- if (!msf->is_listener != !args->is_master)
+ if ((!msf->is_listener != !args->is_master))
{
rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
goto done;
@@ -598,38 +681,34 @@ memif_create_if (vlib_main_t * vm, memif_create_if_args_t * args)
}
/* Create new socket file */
- if (msf == 0)
+ if (msf->ref_cnt == 0)
{
struct stat file_stat;
+
/* If we are creating listener make sure file doesn't exist or if it
* exists thn delete it if it is old socket file */
- if (args->is_master &&
- (stat ((char *) socket_filename, &file_stat) == 0))
+ if (args->is_master && (stat ((char *) msf->filename, &file_stat) == 0))
{
if (S_ISSOCK (file_stat.st_mode))
{
- unlink ((char *) socket_filename);
+ unlink ((char *) msf->filename);
}
else
{
error = clib_error_return (0, "File exists for %s",
- socket_filename);
+ msf->filename);
clib_error_report (error);
rv = VNET_API_ERROR_VALUE_EXIST;
goto done;
}
}
- pool_get (mm->socket_files, msf);
- memset (msf, 0, sizeof (memif_socket_file_t));
+
mhash_init (&msf->dev_instance_by_id, sizeof (uword),
sizeof (memif_interface_id_t));
msf->dev_instance_by_fd = hash_create (0, sizeof (uword));
- msf->filename = socket_filename;
msf->is_listener = (args->is_master != 0);
- socket_filename = 0;
- mhash_set (&mm->socket_file_index_by_filename, msf->filename,
- msf - mm->socket_files, 0);
- DBG ("creating socket file %s", msf->filename);
+
+ DBG ("initializing socket file %s", msf->filename);
}
pool_get (mm->interfaces, mif);
@@ -645,7 +724,6 @@ memif_create_if (vlib_main_t * vm, memif_create_if_args_t * args)
if (tm->n_vlib_mains > 1)
clib_spinlock_init (&mif->lockp);
-
if (mif->mode == MEMIF_INTERFACE_MODE_ETHERNET)
{
@@ -762,7 +840,6 @@ error:
return ret;
done:
- vec_free (socket_filename);
return rv;
}
@@ -772,13 +849,22 @@ memif_init (vlib_main_t * vm)
{
memif_main_t *mm = &memif_main;
vlib_thread_main_t *tm = vlib_get_thread_main ();
+ u8 *filename;
memset (mm, 0, sizeof (memif_main_t));
/* initialize binary API */
memif_plugin_api_hookup (vm);
- mhash_init_c_string (&mm->socket_file_index_by_filename, sizeof (uword));
+ /*
+ * Pre-stuff socket filename pool with a non-modifieable mapping
+ * for socket-id 0 to MEMIF_DEFAULT_SOCKET_FILENAME in the
+ * default run-time directory.
+ */
+ filename = format (0, "%s/%s%c",
+ vlib_unix_get_runtime_dir (),
+ MEMIF_DEFAULT_SOCKET_FILENAME, 0);
+ memif_add_socket_file (0, filename);
vec_validate_aligned (mm->rx_buffers, tm->n_vlib_mains - 1,
CLIB_CACHE_LINE_BYTES);
diff --git a/src/plugins/memif/memif_api.c b/src/plugins/memif/memif_api.c
index f9f74ccdcb3..a48cd188f04 100644
--- a/src/plugins/memif/memif_api.c
+++ b/src/plugins/memif/memif_api.c
@@ -88,10 +88,59 @@ do { \
vl_msg_api_send_shmem (q, (u8 *)&rmp); \
} while(0);
-#define foreach_memif_plugin_api_msg \
-_(MEMIF_CREATE, memif_create) \
-_(MEMIF_DELETE, memif_delete) \
-_(MEMIF_DUMP, memif_dump) \
+#define foreach_memif_plugin_api_msg \
+_(MEMIF_SOCKET_FILENAME_ADD_DEL, memif_socket_filename_add_del) \
+_(MEMIF_CREATE, memif_create) \
+_(MEMIF_DELETE, memif_delete) \
+_(MEMIF_SOCKET_FILENAME_DUMP, memif_socket_filename_dump) \
+_(MEMIF_DUMP, memif_dump) \
+
+
+/**
+ * @brief Message handler for memif_socket_filename_add_del API.
+ * @param mp the vl_api_memif_socket_filename_add_del_t API message
+ */
+void
+ vl_api_memif_socket_filename_add_del_t_handler
+ (vl_api_memif_socket_filename_add_del_t * mp)
+{
+ memif_main_t *mm = &memif_main;
+ u8 is_add;
+ u32 socket_id;
+ u32 len;
+ u8 *socket_filename;
+ vl_api_memif_socket_filename_add_del_reply_t *rmp;
+ int rv;
+
+ /* is_add */
+ is_add = mp->is_add;
+
+ /* socket_id */
+ socket_id = clib_net_to_host_u32 (mp->socket_id);
+ if (socket_id == 0 || socket_id == ~0)
+ {
+ rv = VNET_API_ERROR_INVALID_ARGUMENT;
+ goto reply;
+ }
+
+ /* socket filename */
+ socket_filename = 0;
+ mp->socket_filename[ARRAY_LEN (mp->socket_filename) - 1] = 0;
+ len = strlen ((char *) mp->socket_filename);
+ if (len > 0)
+ {
+ vec_validate (socket_filename, len);
+ strncpy ((char *) socket_filename, (char *) mp->socket_filename, len);
+ }
+
+ rv = memif_socket_filename_add_del (is_add, socket_id, socket_filename);
+
+ vec_free (socket_filename);
+
+reply:
+ REPLY_MACRO (VL_API_MEMIF_SOCKET_FILENAME_ADD_DEL_REPLY);
+}
+
/**
* @brief Message handler for memif_create API.
@@ -111,15 +160,8 @@ vl_api_memif_create_t_handler (vl_api_memif_create_t * mp)
/* id */
args.id = clib_net_to_host_u32 (mp->id);
- /* socket filename */
- mp->socket_filename[ARRAY_LEN (mp->socket_filename) - 1] = 0;
- if (strlen ((char *) mp->socket_filename) > 0)
- {
- vec_validate (args.socket_filename,
- strlen ((char *) mp->socket_filename));
- strncpy ((char *) args.socket_filename, (char *) mp->socket_filename,
- vec_len (args.socket_filename));
- }
+ /* socket-id */
+ args.socket_id = clib_net_to_host_u32 (mp->socket_id);
/* secret */
mp->secret[ARRAY_LEN (mp->secret) - 1] = 0;
@@ -179,16 +221,10 @@ 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,
- ({
- rmp->sw_if_index = htonl (args.sw_if_index);
- }));
- /* *INDENT-ON* */
+ REPLY_MACRO (VL_API_MEMIF_CREATE_REPLY);
}
/**
@@ -227,9 +263,8 @@ send_memif_details (vl_api_registration_t * reg,
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;
+ memif_socket_file_t *msf;
hwif = vnet_get_sup_hw_interface (vnm, swif->sw_if_index);
@@ -242,13 +277,18 @@ send_memif_details (vl_api_registration_t * reg,
mp->sw_if_index = htonl (swif->sw_if_index);
strncpy ((char *) mp->if_name,
(char *) interface_name, ARRAY_LEN (mp->if_name) - 1);
- memcpy (mp->hw_addr, hwif->hw_address, ARRAY_LEN (mp->hw_addr));
+
+ if (hwif->hw_address)
+ {
+ memcpy (mp->hw_addr, hwif->hw_address, ARRAY_LEN (mp->hw_addr));
+ }
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 *) msf->filename, ARRAY_LEN (mp->socket_filename) - 1);
+ msf = pool_elt_at_index (mm->socket_files, mif->socket_file_index);
+ mp->socket_id = clib_host_to_net_u32 (msf->socket_id);
+
+ mp->role = (mif->flags & MEMIF_IF_FLAG_IS_SLAVE) ? 1 : 0;
mp->ring_size = htonl (1 << mif->run.log2_ring_size);
mp->buffer_size = htons (mif->run.buffer_size);
@@ -293,6 +333,58 @@ vl_api_memif_dump_t_handler (vl_api_memif_dump_t * mp)
vec_free (if_name);
}
+static void
+send_memif_socket_filename_details (vl_api_registration_t * reg,
+ u32 socket_id,
+ u8 * socket_filename, u32 context)
+{
+ vl_api_memif_socket_filename_details_t *mp;
+ memif_main_t *mm = &memif_main;
+
+ mp = vl_msg_api_alloc (sizeof (*mp));
+ memset (mp, 0, sizeof (*mp));
+
+ mp->_vl_msg_id = htons (VL_API_MEMIF_SOCKET_FILENAME_DETAILS
+ + mm->msg_id_base);
+ mp->context = context;
+
+ mp->socket_id = clib_host_to_net_u32 (socket_id);
+ strncpy ((char *) mp->socket_filename,
+ (char *) socket_filename, ARRAY_LEN (mp->socket_filename) - 1);
+
+ vl_api_send_msg (reg, (u8 *) mp);
+}
+
+/**
+ * @brief Message handler for memif_socket_filename_dump API.
+ * @param mp vl_api_memif_socket_filename_dump_t api message
+ */
+void
+ vl_api_memif_socket_filename_dump_t_handler
+ (vl_api_memif_socket_filename_dump_t * mp)
+{
+ memif_main_t *mm = &memif_main;
+ vl_api_registration_t *reg;
+ u32 sock_id;
+ u32 msf_idx;
+
+ reg = vl_api_client_index_to_registration (mp->client_index);
+ if (!reg)
+ return;
+
+ /* *INDENT-OFF* */
+ hash_foreach (sock_id, msf_idx, mm->socket_file_index_by_sock_id,
+ ({
+ memif_socket_file_t *msf;
+ u8 *filename;
+
+ msf = pool_elt_at_index(mm->socket_files, msf_idx);
+ filename = msf->filename;
+ send_memif_socket_filename_details(reg, sock_id, filename, mp->context);
+ }));
+ /* *INDENT-ON* */
+}
+
#define vl_msg_name_crc_list
#include <memif/memif_all_api_h.h>
#undef vl_msg_name_crc_list
diff --git a/src/plugins/memif/memif_test.c b/src/plugins/memif/memif_test.c
index 9c80cf3d9f4..b1d563218d9 100644
--- a/src/plugins/memif/memif_test.c
+++ b/src/plugins/memif/memif_test.c
@@ -97,7 +97,9 @@ foreach_standard_reply_retval_handler;
#define foreach_vpe_api_reply_msg \
_(MEMIF_CREATE_REPLY, memif_create_reply) \
_(MEMIF_DELETE_REPLY, memif_delete_reply) \
-_(MEMIF_DETAILS, memif_details)
+_(MEMIF_DETAILS, memif_details) \
+_(MEMIF_SOCKET_FILENAME_DETAILS, memif_socket_filename_details) \
+_(MEMIF_SOCKET_FILENAME_ADD_DEL_REPLY, memif_socket_filename_add_del_reply)
static uword
unformat_memif_queues (unformat_input_t * input, va_list * args)
@@ -113,6 +115,81 @@ unformat_memif_queues (unformat_input_t * input, va_list * args)
return 1;
}
+/* memif_socket_filename_add_del API */
+static int
+api_memif_socket_filename_add_del (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_memif_socket_filename_add_del_t *mp;
+ u8 is_add;
+ u32 socket_id;
+ u8 *socket_filename;
+ int ret;
+
+ is_add = 1;
+ socket_id = ~0;
+ socket_filename = 0;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "id %u", &socket_id))
+ ;
+ else if (unformat (i, "filename %s", &socket_filename))
+ ;
+ else if (unformat (i, "del"))
+ is_add = 0;
+ else if (unformat (i, "add"))
+ is_add = 1;
+ else
+ {
+ vec_free (socket_filename);
+ clib_warning ("unknown input `%U'", format_unformat_error, i);
+ return -99;
+ }
+ }
+
+ if (socket_id == 0 || socket_id == ~0)
+ {
+ vec_free (socket_filename);
+ errmsg ("Invalid socket id");
+ return -99;
+ }
+
+ if (is_add && (!socket_filename || *socket_filename == 0))
+ {
+ vec_free (socket_filename);
+ errmsg ("Invalid socket filename");
+ return -99;
+ }
+
+ M (MEMIF_SOCKET_FILENAME_ADD_DEL, mp);
+
+ memset (mp, 0, sizeof (*mp));
+ mp->is_add = is_add;
+ mp->socket_id = htonl (socket_id);
+ memcpy (mp->socket_filename,
+ socket_filename, sizeof (mp->socket_filename) - 1);
+
+ vec_free (socket_filename);
+
+ S (mp);
+ W (ret);
+
+ return ret;
+}
+
+/* memif_socket_filename_add_del reply handler */
+static void vl_api_memif_socket_filename_add_del_reply_t_handler
+ (vl_api_memif_socket_filename_add_del_reply_t * mp)
+{
+ vat_main_t *vam = memif_test_main.vat_main;
+ i32 retval = ntohl (mp->retval);
+
+ vam->retval = retval;
+ vam->result_ready = 1;
+ vam->regenerate_interface_table = 1;
+}
+
/* memif-create API */
static int
api_memif_create (vat_main_t * vam)
@@ -120,7 +197,7 @@ api_memif_create (vat_main_t * vam)
unformat_input_t *i = vam->input;
vl_api_memif_create_t *mp;
u32 id = 0;
- u8 *socket_filename = 0;
+ u32 socket_id = 0;
u8 *secret = 0;
u8 role = 1;
u32 ring_size = 0;
@@ -135,7 +212,7 @@ api_memif_create (vat_main_t * vam)
{
if (unformat (i, "id %u", &id))
;
- else if (unformat (i, "socket %s", &socket_filename))
+ else if (unformat (i, "socket-id %u", &socket_id))
;
else if (unformat (i, "secret %s", &secret))
;
@@ -159,6 +236,12 @@ api_memif_create (vat_main_t * vam)
}
}
+ if (socket_id == ~0)
+ {
+ errmsg ("invalid socket-id\n");
+ return -99;
+ }
+
if (!is_pow2 (ring_size))
{
errmsg ("ring size must be power of 2\n");
@@ -184,11 +267,7 @@ api_memif_create (vat_main_t * vam)
mp->role = role;
mp->ring_size = clib_host_to_net_u32 (ring_size);
mp->buffer_size = clib_host_to_net_u16 (buffer_size & 0xffff);
- if (socket_filename != 0)
- {
- strncpy ((char *) mp->socket_filename, (char *) socket_filename, 127);
- vec_free (socket_filename);
- }
+ mp->socket_id = clib_host_to_net_u32 (socket_id);
if (secret != 0)
{
strncpy ((char *) mp->secret, (char *) secret, 16);
@@ -290,32 +369,80 @@ api_memif_dump (vat_main_t * vam)
}
/* memif-details message handler */
-static void vl_api_memif_details_t_handler (vl_api_memif_details_t * mp)
+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"
- " id %u socket %s role %s\n"
+ " id %u socket-id %u 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_u32 (mp->id), mp->socket_filename,
+ mp->hw_addr, clib_net_to_host_u32 (mp->id),
+ clib_net_to_host_u32 (mp->socket_id),
mp->role ? "slave" : "master",
ntohl (mp->ring_size), ntohs (mp->buffer_size),
mp->admin_up_down ? "up" : "down",
mp->link_up_down ? "up" : "down");
}
+/* memif_socket_filename_dump API */
+static int
+api_memif_socket_filename_dump (vat_main_t * vam)
+{
+ memif_test_main_t *mm = &memif_test_main;
+ vl_api_memif_socket_filename_dump_t *mp;
+ vl_api_control_ping_t *mp_ping;
+ int ret;
+
+ if (vam->json_output)
+ {
+ clib_warning
+ ("JSON output not supported for memif_socket_filename_dump");
+ return -99;
+ }
+
+ M (MEMIF_SOCKET_FILENAME_DUMP, mp);
+ S (mp);
+
+ /* Use a control ping for synchronization */
+ mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping));
+ mp_ping->_vl_msg_id = htons (mm->ping_id);
+ mp_ping->client_index = vam->my_client_index;
+
+ fformat (vam->ofp, "Sending ping id=%d\n", mm->ping_id);
+
+ vam->result_ready = 0;
+ S (mp_ping);
+
+ W (ret);
+ return ret;
+}
+
+/* memif_socket_format_details message handler */
+static void vl_api_memif_socket_filename_details_t_handler
+ (vl_api_memif_socket_filename_details_t * mp)
+{
+ vat_main_t *vam = memif_test_main.vat_main;
+
+ fformat (vam->ofp,
+ "id %u : filename %s\n",
+ ntohl (mp->socket_id), mp->socket_filename);
+}
+
/*
* List of messages that the api test plugin sends,
* and that the data plane plugin processes
*/
#define foreach_vpe_api_msg \
-_(memif_create, "[id <id>] [socket <path>] [ring_size <size>] " \
+_(memif_create, "[id <id>] [socket-id <id>] [ring_size <size>] " \
"[buffer_size <size>] [hw_addr <mac_address>] " \
"[secret <string>] [mode ip] <master|slave>") \
_(memif_delete, "<sw_if_index>") \
-_(memif_dump, "")
+_(memif_dump, "") \
+_(memif_socket_filename_dump, "") \
+_(memif_socket_filename_add_del, "[add|del] id <id> filename <file>")
static void
memif_vat_api_hookup (vat_main_t * vam)
@@ -364,10 +491,18 @@ vat_plugin_register (vat_main_t * vam)
#undef _
mm->ping_id = vl_msg_api_get_msg_index ((u8 *) (VL_API_CONTROL_PING_CRC));
- if (mm->msg_id_base != (u16) ~0)
+ if (mm->msg_id_base != (u16) ~ 0)
memif_vat_api_hookup (vam);
vec_free (name);
return 0;
}
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/src/plugins/memif/private.h b/src/plugins/memif/private.h
index 49357ddc617..5904fc09cd6 100644
--- a/src/plugins/memif/private.h
+++ b/src/plugins/memif/private.h
@@ -65,6 +65,7 @@
typedef struct
{
u8 *filename;
+ u32 socket_id;
clib_socket_t *sock;
clib_socket_t **pending_clients;
int ref_cnt;
@@ -182,7 +183,7 @@ typedef struct
/* pool of all unix socket files */
memif_socket_file_t *socket_files;
- mhash_t socket_file_index_by_filename;
+ uword *socket_file_index_by_sock_id; /* map user socket id to pool idx */
/* rx buffer cache */
u32 **rx_buffers;
@@ -202,7 +203,7 @@ enum
typedef struct
{
memif_interface_id_t id;
- u8 *socket_filename;
+ u32 socket_id;
u8 *secret;
u8 is_master;
memif_interface_mode_t mode:8;
@@ -217,6 +218,8 @@ typedef struct
u32 sw_if_index;
} memif_create_if_args_t;
+int memif_socket_filename_add_del (u8 is_add, u32 sock_id,
+ u8 * sock_filename);
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);