memif: Add new API calls to manage memif socket names. 72/10172/4
authorJon Loeliger <jdl@netgate.com>
Tue, 16 Jan 2018 22:37:16 +0000 (16:37 -0600)
committerDamjan Marion <damarion@cisco.com>
Mon, 29 Jan 2018 12:09:57 +0000 (13:09 +0100)
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>
src/plugins/memif/cli.c
src/plugins/memif/device.c
src/plugins/memif/memif.api
src/plugins/memif/memif.c
src/plugins/memif/memif_api.c
src/plugins/memif/memif_test.c
src/plugins/memif/private.h

index 29d1331..3f0e281 100644 (file)
 #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,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 <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,
 };
 /* *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* */
index 3809061..22f9753 100644 (file)
@@ -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
index cd09b92..6a61ee1 100644 (file)
  * 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 */
 
index aa476be..dc92e7e 100644 (file)
@@ -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);
index f9f74cc..a48cd18 100644 (file)
@@ -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
index 9c80cf3..b1d5632 100644 (file)
@@ -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:
+ */
index 49357dd..5904fc0 100644 (file)
@@ -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);