diff options
author | Jon Loeliger <jdl@netgate.com> | 2018-01-16 16:37:16 -0600 |
---|---|---|
committer | Damjan Marion <damarion@cisco.com> | 2018-01-29 13:09:57 +0100 |
commit | 30349b075cf939549980f2a32e030b32f6d07e9a (patch) | |
tree | ebf4a6e10c49cd9657cefeadafbaa44f07c5c021 /src/plugins/memif/memif.c | |
parent | b4d43d7901b49bdda4345adb86b4d15a5d72f7ff (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>
Diffstat (limited to 'src/plugins/memif/memif.c')
-rw-r--r-- | src/plugins/memif/memif.c | 172 |
1 files changed, 129 insertions, 43 deletions
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); |