memif: autogenerate socket_ids 34/34734/5
authorNathan Skrzypczak <nathan.skrzypczak@gmail.com>
Wed, 15 Dec 2021 18:15:32 +0000 (19:15 +0100)
committerDamjan Marion <dmarion@0xa5.net>
Mon, 6 Mar 2023 13:54:06 +0000 (13:54 +0000)
This patch adds an API memif_socket_filename_add_del_v2
that allows autogenerating memif socket_id when passing
~0 in the socket_id field.

It opportunistically walks the hash to find a free ID
to use, and returns it in the reply.

socket_filename also becomes a variable length string,
to accomodate for longer names (in case a netns gets
passed)

Type: feature

Change-Id: I33fc3e1cf553af27579d6bad8691b22b530531cc
Signed-off-by: Nathan Skrzypczak <nathan.skrzypczak@gmail.com>
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 9e32db5..91e72f7 100644 (file)
@@ -51,6 +51,40 @@ autoreply define memif_socket_filename_add_del
   option vat_help = "[add|del] id <id> filename <file>";
 };
 
+/** \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
+          ~0 means autogenerate
+    @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.
+          socket_filename starting with '@' will create an abstract socket
+          in the given namespace
+*/
+define memif_socket_filename_add_del_v2
+{
+  u32 client_index;
+  u32 context;
+  bool is_add;                         /* 0 = remove, 1 = add association */
+  u32 socket_id [default=0xffffffff];  /* unique non-0 id for given socket file name */
+  string socket_filename[];             /* NUL terminated filename */
+  option vat_help = "[add|del] id <id> filename <file>";
+};
+
+/** \brief Create memory interface socket file response
+    @param context - sender context, to match reply w/ request
+    @param retval - return value for request
+    @param socket_id - non-0 32-bit integer used to identify a socket file
+*/
+define memif_socket_filename_add_del_v2_reply
+{
+  u32 context;
+  i32 retval;
+  u32 socket_id;
+};
+
 /** \brief Create memory interface
     @param client_index - opaque cookie to identify the sender
     @param context - sender context, to match reply w/ request
index eee38f0..c9d2f00 100644 (file)
@@ -681,6 +681,36 @@ VLIB_REGISTER_NODE (memif_process_node,static) = {
   .name = "memif-process",
 };
 
+/*
+ * Returns an unused socket id, and ~0 if it can't find one.
+ */
+u32
+memif_get_unused_socket_id ()
+{
+  memif_main_t *mm = &memif_main;
+  uword *p;
+  int i, j;
+
+  static u32 seed = 0;
+  /* limit to 1M tries */
+  for (j = 0; j < 1 << 10; j++)
+    {
+      seed = random_u32 (&seed);
+      for (i = 0; i < 1 << 10; i++)
+       {
+         /* look around randomly generated id */
+         seed += (2 * (i % 2) - 1) * i;
+         if (seed == (u32) ~0)
+           continue;
+         p = hash_get (mm->socket_file_index_by_sock_id, seed);
+         if (!p)
+           return seed;
+       }
+    }
+
+  return ~0;
+}
+
 clib_error_t *
 memif_socket_filename_add_del (u8 is_add, u32 sock_id, char *sock_filename)
 {
index 9a2f42a..819350a 100644 (file)
@@ -72,6 +72,42 @@ reply:
   REPLY_MACRO (VL_API_MEMIF_SOCKET_FILENAME_ADD_DEL_REPLY);
 }
 
+/**
+ * @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_v2_t_handler (
+  vl_api_memif_socket_filename_add_del_v2_t *mp)
+{
+  vl_api_memif_socket_filename_add_del_v2_reply_t *rmp;
+  memif_main_t *mm = &memif_main;
+  char *socket_filename = 0;
+  u32 socket_id;
+  int rv;
+
+  /* socket_id */
+  socket_id = clib_net_to_host_u32 (mp->socket_id);
+  if (socket_id == 0)
+    {
+      rv = VNET_API_ERROR_INVALID_ARGUMENT;
+      goto reply;
+    }
+
+  /* socket filename */
+  socket_filename = vl_api_from_api_to_new_c_string (&mp->socket_filename);
+  if (mp->is_add && socket_id == (u32) ~0)
+    socket_id = memif_get_unused_socket_id ();
+
+  rv = vnet_api_error (
+    memif_socket_filename_add_del (mp->is_add, socket_id, socket_filename));
+
+  vec_free (socket_filename);
+
+reply:
+  REPLY_MACRO2 (VL_API_MEMIF_SOCKET_FILENAME_ADD_DEL_V2_REPLY,
+               ({ rmp->socket_id = htonl (socket_id); }));
+}
 
 /**
  * @brief Message handler for memif_create API.
index 98c9354..07d6892 100644 (file)
@@ -121,6 +121,86 @@ api_memif_socket_filename_add_del (vat_main_t * vam)
   return ret;
 }
 
+/* memif_socket_filename_add_del API */
+static int
+api_memif_socket_filename_add_del_v2 (vat_main_t *vam)
+{
+  unformat_input_t *i = vam->input;
+  vl_api_memif_socket_filename_add_del_v2_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;
+    }
+
+  M2 (MEMIF_SOCKET_FILENAME_ADD_DEL_V2, mp, strlen ((char *) socket_filename));
+
+  mp->is_add = is_add;
+  mp->socket_id = htonl (socket_id);
+  char *p = (char *) &mp->socket_filename;
+  p += vl_api_vec_to_api_string (socket_filename, (vl_api_string_t *) p);
+
+  vec_free (socket_filename);
+
+  S (mp);
+  W (ret);
+
+  return ret;
+}
+
+/* memif socket-create reply handler */
+static void
+vl_api_memif_socket_filename_add_del_v2_reply_t_handler (
+  vl_api_memif_socket_filename_add_del_v2_reply_t *mp)
+{
+  vat_main_t *vam = memif_test_main.vat_main;
+  i32 retval = ntohl (mp->retval);
+
+  if (retval == 0)
+    {
+      fformat (vam->ofp, "created memif socket with socket_id %d\n",
+              ntohl (mp->socket_id));
+    }
+
+  vam->retval = retval;
+  vam->result_ready = 1;
+}
+
 /* memif_socket_filename_add_del reply handler */
 #define VL_API_MEMIF_SOCKET_FILENAME_ADD_DEL_REPLY_T_HANDLER
 static void vl_api_memif_socket_filename_add_del_reply_t_handler
index ba77cc1..5d8718d 100644 (file)
@@ -321,6 +321,7 @@ typedef struct
   u32 sw_if_index;
 } memif_create_if_args_t;
 
+u32 memif_get_unused_socket_id ();
 clib_error_t *memif_socket_filename_add_del (u8 is_add, u32 sock_id,
                                             char *sock_filename);
 clib_error_t *memif_create_if (vlib_main_t *vm, memif_create_if_args_t *args);