From 30349b075cf939549980f2a32e030b32f6d07e9a Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Tue, 16 Jan 2018 16:37:16 -0600 Subject: 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 filename vppctl# delete memif id and then referencing it later in a memif interface: vppctl# create memif socket-id mode ... 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 Signed-off-by: Damjan Marion --- src/plugins/memif/cli.c | 207 +++++++++++++++++++++++++++++++++++++++-- src/plugins/memif/device.c | 4 +- src/plugins/memif/memif.api | 52 +++++++++-- src/plugins/memif/memif.c | 172 +++++++++++++++++++++++++--------- src/plugins/memif/memif_api.c | 144 ++++++++++++++++++++++------ src/plugins/memif/memif_test.c | 163 +++++++++++++++++++++++++++++--- src/plugins/memif/private.h | 7 +- 7 files changed, 647 insertions(+), 102 deletions(-) (limited to 'src/plugins') 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 #include + +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 ] [filename ]", + .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 ]", + .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,15 +252,32 @@ 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 ] [socket ] " - "[ring-size ] [buffer-size ] [hw-addr ] " + .path = "create interface memif", + .short_help = "create interface memif [id ] [socket-id ] " + "[ring-size ] [buffer-size ] " + "[hw-addr ] " " [rx-queues ] [tx-queues ] " "[mode ip] [secret ]", .function = memif_create_command_fn, }; /* *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 { | sw_if_index }", + .path = "delete interface memif", + .short_help = "delete interface memif { | sw_if_index }", .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 {] [descriptors]", + .short_help = "show memif [] [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 */ @@ -72,6 +90,28 @@ autoreply define memif_delete u32 sw_if_index; }; +/** \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 @@ -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 #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 ] [socket ] [ring_size ] " \ +_(memif_create, "[id ] [socket-id ] [ring_size ] " \ "[buffer_size ] [hw_addr ] " \ "[secret ] [mode ip] ") \ _(memif_delete, "") \ -_(memif_dump, "") +_(memif_dump, "") \ +_(memif_socket_filename_dump, "") \ +_(memif_socket_filename_add_del, "[add|del] id filename ") 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); -- cgit 1.2.3-korg