sock api: add infra for bootstrapping shm clients 93/9893/10
authorFlorin Coras <fcoras@cisco.com>
Tue, 19 Dec 2017 12:50:01 +0000 (04:50 -0800)
committerDave Barach <openvpp@barachs.net>
Fri, 5 Jan 2018 19:00:45 +0000 (19:00 +0000)
- add function to sock client that bootstraps shm api
- allow sock clients to request custom shm ring configs

Change-Id: Iabc1dd4f0dc8bbf8ba24de37f4966339fcf86107
Signed-off-by: Florin Coras <fcoras@cisco.com>
13 files changed:
src/tests/vnet/session/tcp_echo.c
src/vat/api_format.c
src/vat/main.c
src/vat/vat.h
src/vlibapi/vat_helper_macros.h
src/vlibmemory/api_common.h
src/vlibmemory/memclnt.api
src/vlibmemory/memory_shared.c
src/vlibmemory/memory_vlib.c
src/vlibmemory/socket_client.c
src/vlibmemory/socksvr_vlib.c
src/vnet/lisp-cp/one_api.c
src/vppinfra/file.h

index 8bdcac3..30eb54d 100644 (file)
 
 #include <stdio.h>
 #include <signal.h>
+
+#include <vnet/session/application_interface.h>
 #include <svm/svm_fifo_segment.h>
 #include <vlibmemory/api.h>
+
 #include <vpp/api/vpe_msg_enum.h>
-#include <vnet/session/application_interface.h>
 
 #define vl_typedefs            /* define message structures */
 #include <vpp/api/vpe_all_api_h.h>
@@ -91,6 +93,8 @@ typedef struct
   /* $$$ single thread only for the moment */
   unix_shared_memory_queue_t *vpp_event_queue;
 
+  u8 *socket_name;
+
   pid_t my_pid;
 
   /* For deadman timers */
@@ -114,6 +118,11 @@ typedef struct
   u8 test_return_packets;
   u64 bytes_to_send;
 
+  /** Flag that decides if socket, instead of svm, api is used to connect to
+   * vpp. If sock api is used, shm binary api is subsequently bootstrapped
+   * and all other messages are exchanged using shm IPC. */
+  u8 use_sock_api;
+
   /* convenience */
   svm_fifo_segment_main_t *segment_main;
 } uri_tcp_test_main_t;
@@ -313,15 +322,33 @@ connect_to_vpp (char *name)
   uri_tcp_test_main_t *utm = &uri_tcp_test_main;
   api_main_t *am = &api_main;
 
-  if (vl_client_connect_to_vlib ("/vpe-api", name, 32) < 0)
-    return -1;
-
-  utm->vl_input_queue = am->shmem_hdr->vl_input_queue;
-  utm->my_client_index = am->my_client_index;
+  if (utm->use_sock_api)
+    {
+      if (vl_socket_client_connect ((char *) utm->socket_name, name,
+                                   0 /* default rx, tx buffer */ ))
+       return -1;
 
+      return vl_socket_client_init_shm (0);
+    }
+  else
+    {
+      if (vl_client_connect_to_vlib ("/vpe-api", name, 32) < 0)
+       return -1;
+      utm->vl_input_queue = am->shmem_hdr->vl_input_queue;
+      utm->my_client_index = am->my_client_index;
+    }
   return 0;
 }
 
+void
+disconnect_from_vpp (uri_tcp_test_main_t * utm)
+{
+  if (utm->use_sock_api)
+    vl_socket_client_disconnect ();
+  else
+    vl_client_disconnect_from_vlib ();
+}
+
 static void
 vl_api_map_another_segment_t_handler (vl_api_map_another_segment_t * mp)
 {
@@ -733,7 +760,7 @@ client_disconnect (uri_tcp_test_main_t * utm)
 }
 
 static void
-client_test (uri_tcp_test_main_t * utm)
+client_run (uri_tcp_test_main_t * utm)
 {
   int i;
 
@@ -1085,8 +1112,20 @@ server_unbind (uri_tcp_test_main_t * utm)
 }
 
 void
-server_test (uri_tcp_test_main_t * utm)
+server_run (uri_tcp_test_main_t * utm)
 {
+  session_t *session;
+  int i;
+
+  /* $$$$ hack preallocation */
+  for (i = 0; i < 200000; i++)
+    {
+      pool_get (utm->sessions, session);
+      memset (session, 0, sizeof (*session));
+    }
+  for (i = 0; i < 200000; i++)
+    pool_put_index (utm->sessions, i);
+
   if (application_attach (utm))
     return;
 
@@ -1124,17 +1163,17 @@ vl_api_disconnect_session_reply_t_handler (vl_api_disconnect_session_reply_t *
     session_print_stats (utm, session);
 }
 
-#define foreach_uri_msg                                 \
-_(BIND_URI_REPLY, bind_uri_reply)                       \
-_(UNBIND_URI_REPLY, unbind_uri_reply)                   \
-_(ACCEPT_SESSION, accept_session)                       \
-_(CONNECT_SESSION_REPLY, connect_session_reply)         \
-_(DISCONNECT_SESSION, disconnect_session)               \
-_(DISCONNECT_SESSION_REPLY, disconnect_session_reply)   \
-_(RESET_SESSION, reset_session)                         \
-_(APPLICATION_ATTACH_REPLY, application_attach_reply)   \
-_(APPLICATION_DETACH_REPLY, application_detach_reply)  \
-_(MAP_ANOTHER_SEGMENT, map_another_segment)            \
+#define foreach_uri_msg                                        \
+_(BIND_URI_REPLY, bind_uri_reply)                              \
+_(UNBIND_URI_REPLY, unbind_uri_reply)                          \
+_(ACCEPT_SESSION, accept_session)                              \
+_(CONNECT_SESSION_REPLY, connect_session_reply)                \
+_(DISCONNECT_SESSION, disconnect_session)                      \
+_(DISCONNECT_SESSION_REPLY, disconnect_session_reply)          \
+_(RESET_SESSION, reset_session)                                \
+_(APPLICATION_ATTACH_REPLY, application_attach_reply)          \
+_(APPLICATION_DETACH_REPLY, application_detach_reply)          \
+_(MAP_ANOTHER_SEGMENT, map_another_segment)                    \
 
 void
 uri_api_hookup (uri_tcp_test_main_t * utm)
@@ -1162,8 +1201,6 @@ main (int argc, char **argv)
   u64 bytes_to_send = 64 << 10, mbytes;
   u32 tmp;
   mheap_t *h;
-  session_t *session;
-  int i;
   int i_am_master = 1, drop_packets = 0, test_return_packets = 0;
 
   clib_mem_init (0, 256 << 20);
@@ -1180,6 +1217,8 @@ main (int argc, char **argv)
 
   utm->my_pid = getpid ();
   utm->configured_segment_size = 1 << 20;
+  utm->socket_name = 0;
+  utm->use_sock_api = 1;
 
   clib_time_init (&utm->clib_time);
   init_error_string_table (utm);
@@ -1214,6 +1253,10 @@ main (int argc, char **argv)
        {
          bytes_to_send = mbytes << 30;
        }
+      else if (unformat (a, "socket-name %s", &utm->socket_name))
+       ;
+      else if (unformat (a, "use-svm-api"))
+       utm->use_sock_api = 0;
       else
        {
          fformat (stderr, "%s: usage [master|slave]\n");
@@ -1221,6 +1264,9 @@ main (int argc, char **argv)
        }
     }
 
+  if (!utm->socket_name)
+    utm->socket_name = format (0, "%s%c", API_SOCKET_FILE, 0);
+
   if (uri)
     {
       utm->uri = format (0, "%s%c", uri, 0);
@@ -1242,7 +1288,8 @@ main (int argc, char **argv)
   setup_signal_handlers ();
   uri_api_hookup (utm);
 
-  if (connect_to_vpp (i_am_master ? "uri_tcp_server" : "uri_tcp_client") < 0)
+  if (connect_to_vpp (i_am_master ? "tcp_echo_server" : "tcp_echo_client") <
+      0)
     {
       svm_region_exit ();
       fformat (stderr, "Couldn't connect to vpe, exiting...\n");
@@ -1250,24 +1297,11 @@ main (int argc, char **argv)
     }
 
   if (i_am_master == 0)
-    {
-      client_test (utm);
-      vl_client_disconnect_from_vlib ();
-      exit (0);
-    }
-
-  /* $$$$ hack preallocation */
-  for (i = 0; i < 200000; i++)
-    {
-      pool_get (utm->sessions, session);
-      memset (session, 0, sizeof (*session));
-    }
-  for (i = 0; i < 200000; i++)
-    pool_put_index (utm->sessions, i);
-
-  server_test (utm);
+    client_run (utm);
+  else
+    server_run (utm);
 
-  vl_client_disconnect_from_vlib ();
+  disconnect_from_vpp (utm);
   exit (0);
 }
 
index 445b496..88c6447 100644 (file)
@@ -88,9 +88,9 @@ vl (void *p)
 int
 vat_socket_connect (vat_main_t * vam)
 {
-  return vl_socket_client_connect
-    (&vam->socket_client_main, (char *) vam->socket_name,
-     "vpp_api_test(s)", 0 /* default socket rx, tx buffer */ );
+  vam->socket_client_main = &socket_client_main;
+  return vl_socket_client_connect ((char *) vam->socket_name, "vpp_api_test",
+                                  0 /* default socket rx, tx buffer */ );
 }
 #else /* vpp built-in case, we don't do sockets... */
 int
@@ -99,10 +99,23 @@ vat_socket_connect (vat_main_t * vam)
   return 0;
 }
 
-void
-vl_socket_client_read_reply (socket_client_main_t * scm)
+int
+vl_socket_client_read (int wait)
+{
+  return -1;
+};
+
+int
+vl_socket_client_write ()
 {
+  return -1;
 };
+
+void *
+vl_socket_client_msg_alloc (int nbytes)
+{
+  return 0;
+}
 #endif
 
 
@@ -1464,7 +1477,8 @@ static void vl_api_control_ping_reply_t_handler
       vam->retval = retval;
       vam->result_ready = 1;
     }
-  vam->socket_client_main.control_pings_outstanding--;
+  if (vam->socket_client_main)
+    vam->socket_client_main->control_pings_outstanding--;
 }
 
 static void vl_api_control_ping_reply_t_handler_json
@@ -2186,7 +2200,7 @@ static void vl_api_memfd_segment_create_reply_t_handler
 #if VPP_API_TEST_BUILTIN == 0
   vat_main_t *vam = &vat_main;
   api_main_t *am = &api_main;
-  socket_client_main_t *scm = &vam->socket_client_main;
+  socket_client_main_t *scm = vam->socket_client_main;
   int my_fd = -1;
   clib_error_t *error;
   memfd_private_t memfd;
@@ -2224,8 +2238,7 @@ static void vl_api_memfd_segment_create_reply_t_handler
                                        32 /* input_queue_length */ );
       vam->vl_input_queue = am->shmem_hdr->vl_input_queue;
 
-      vl_socket_client_enable_disable (&vam->socket_client_main,
-                                      0 /* disable socket */ );
+      vl_socket_client_enable_disable (0 /* disable socket */ );
     }
 
 out:
@@ -21865,6 +21878,46 @@ api_memfd_segment_create (vat_main_t * vam)
 #endif
 }
 
+static int
+api_sock_init_shm (vat_main_t * vam)
+{
+#if VPP_API_TEST_BUILTIN == 0
+  unformat_input_t *i = vam->input;
+  vl_api_shm_elem_config_t *config = 0;
+  u64 size = 64 << 20;
+  int rv;
+
+  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (i, "size %U", unformat_memory_size, &size))
+       ;
+      else
+       break;
+    }
+
+  /* Try customized config to see if it works */
+  vec_validate (config, 3);
+  config[0].type = VL_API_VLIB_RING;
+  config[0].count = 256;
+  config[0].size = 256;
+  config[1].type = VL_API_CLIENT_RING;
+  config[1].count = 256;
+  config[1].size = 1024;
+  config[2].type = VL_API_CLIENT_RING;
+  config[2].count = 8;
+  config[2].size = 4096;
+  config[3].type = VL_API_QUEUE;
+  config[3].count = 256;
+  config[3].size = sizeof (uword);
+  rv = vl_socket_client_init_shm (config);
+  if (!rv)
+    vam->client_index_invalid = 1;
+  return rv;
+#else
+  return -99;
+#endif
+}
+
 static int
 api_dns_enable_disable (vat_main_t * vam)
 {
@@ -23093,6 +23146,7 @@ _(sw_interface_set_lldp, "<intfc> | sw_if_index <nn> [port-desc <description>]\n
   " [mgmt-ip4 <ip4>] [mgmt-ip6 <ip6>] [mgmt-oid <object id>] [disable]") \
 _(tcp_configure_src_addresses, "<ip4|6>first-<ip4|6>last [vrf <id>]")  \
 _(memfd_segment_create,"size <nnn>")                                   \
+_(sock_init_shm, "size <nnn>")                                         \
 _(app_namespace_add_del, "[add] id <ns-id> secret <nn> sw_if_index <nn>")\
 _(dns_enable_disable, "[enable][disable]")                             \
 _(dns_name_server_add_del, "<ip-address> [del]")                       \
index aa990a3..723c5e8 100644 (file)
@@ -389,7 +389,7 @@ main (int argc, char **argv)
   if (vam->socket_name && vat_socket_connect (vam))
     fformat (stderr, "WARNING: socket connection failed");
 
-  if (vam->socket_client_main.socket_fd == 0
+  if ((!vam->socket_client_main || vam->socket_client_main->socket_fd == 0)
       && connect_to_vpe ("vpp_api_test") < 0)
     {
       svm_region_exit ();
index 1ae46f3..ddb4644 100644 (file)
@@ -209,7 +209,7 @@ typedef struct
   ip4_nbr_counter_t **ip4_nbr_counters;
   ip6_nbr_counter_t **ip6_nbr_counters;
 
-  socket_client_main_t socket_client_main;
+  socket_client_main_t *socket_client_main;
   u8 *socket_name;
 
   /* Convenience */
index fd2e563..52fdcb1 100644 (file)
 /* M: construct, but don't yet send a message */
 #define M(T, mp)                                                \
 do {                                                            \
-    socket_client_main_t *scm = &vam->socket_client_main;      \
+    socket_client_main_t *scm = vam->socket_client_main;       \
     vam->result_ready = 0;                                      \
-    if (scm->socket_enable)                                     \
-      {                                                         \
-        mp = (void *)scm->socket_tx_buffer;                     \
-        scm->socket_tx_nbytes = sizeof (*mp);                   \
-      }                                                         \
+    if (scm && scm->socket_enable)                              \
+      mp = vl_socket_client_msg_alloc (sizeof(*mp));           \
     else                                                        \
       mp = vl_msg_api_alloc_as_if_client(sizeof(*mp));          \
     memset (mp, 0, sizeof (*mp));                               \
@@ -39,30 +36,25 @@ do {                                                            \
 /* MPING: construct a control-ping message, don't send it yet */
 #define MPING(T, mp)                                            \
 do {                                                            \
-    socket_client_main_t *scm = &vam->socket_client_main;      \
+    socket_client_main_t *scm = vam->socket_client_main;       \
     vam->result_ready = 0;                                      \
-    if (scm->socket_enable)                                     \
-      {                                                         \
-        mp = (void *)scm->socket_tx_buffer;                     \
-        scm->socket_tx_nbytes = sizeof (*mp);                   \
-      }                                                         \
+    if (scm && scm->socket_enable)                                     \
+      mp = vl_socket_client_msg_alloc (sizeof(*mp));           \
     else                                                        \
       mp = vl_msg_api_alloc_as_if_client(sizeof(*mp));          \
     memset (mp, 0, sizeof (*mp));                               \
     mp->_vl_msg_id = ntohs (VL_API_##T+__plugin_msg_base);      \
     mp->client_index = vam->my_client_index;                    \
-    scm->control_pings_outstanding++;                           \
+    if (scm)                                                   \
+      scm->control_pings_outstanding++;                                \
 } while(0);
 
 #define M2(T, mp, n)                                            \
 do {                                                            \
-    socket_client_main_t *scm = &vam->socket_client_main;      \
+    socket_client_main_t *scm = vam->socket_client_main;       \
     vam->result_ready = 0;                                      \
-    if (scm->socket_enable)                                     \
-      {                                                         \
-        mp = (void *)scm->socket_tx_buffer;                     \
-        scm->socket_tx_nbytes = sizeof (*mp) + n;               \
-      }                                                         \
+    if (scm && scm->socket_enable)                                     \
+      mp = vl_socket_client_msg_alloc (sizeof(*mp));           \
     else                                                        \
       mp = vl_msg_api_alloc_as_if_client(sizeof(*mp) + n);      \
     memset (mp, 0, sizeof (*mp));                               \
@@ -73,27 +65,9 @@ do {                                                            \
 /* S: send a message */
 #define S(mp)                                                   \
 do {                                                            \
-  int n;                                                        \
-  socket_client_main_t *scm = &vam->socket_client_main;         \
-  if (scm->socket_enable)                                       \
-    {                                                           \
-      msgbuf_t msgbuf =                                         \
-        {                                                       \
-          .q = 0,                                               \
-          .gc_mark_timestamp = 0,                               \
-          .data_len = htonl(scm->socket_tx_nbytes),             \
-        };                                                      \
-                                                                \
-      /* coverity[UNINIT] */                                    \
-      n = write (scm->socket_fd, &msgbuf, sizeof (msgbuf));     \
-      if (n < sizeof (msgbuf))                                  \
-        clib_unix_warning ("socket write (msgbuf)");            \
-                                                                \
-      n = write (scm->socket_fd, scm->socket_tx_buffer,         \
-                   scm->socket_tx_nbytes);                      \
-      if (n < scm->socket_tx_nbytes)                            \
-        clib_unix_warning ("socket write (msg)");               \
-    }                                                           \
+  socket_client_main_t *scm = vam->socket_client_main;                 \
+  if (scm && scm->socket_enable)                                       \
+    vl_socket_client_write ();                                 \
   else                                                          \
     vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp);     \
  } while (0);
@@ -102,10 +76,11 @@ do {                                                            \
 #define W(ret)                                                  \
 do {                                                            \
     f64 timeout = vat_time_now (vam) + 1.0;                     \
-    socket_client_main_t *scm = &vam->socket_client_main;      \
+    socket_client_main_t *scm = vam->socket_client_main;       \
     ret = -99;                                                  \
                                                                 \
-    vl_socket_client_read_reply (scm);                          \
+    if (scm && scm->socket_enable)                                     \
+      vl_socket_client_read (5);                                       \
     while (vat_time_now (vam) < timeout) {                      \
         if (vam->result_ready == 1) {                           \
             ret = vam->retval;                                  \
@@ -119,10 +94,11 @@ do {                                                            \
 #define W2(ret, body)                                           \
 do {                                                            \
     f64 timeout = vat_time_now (vam) + 1.0;                     \
-    socket_client_main_t *scm = &vam->socket_client_main;      \
+    socket_client_main_t *scm = vam->socket_client_main;       \
     ret = -99;                                                  \
                                                                 \
-    vl_socket_client_read_reply (scm);                          \
+    if (scm && scm->socket_enable)                                     \
+      vl_socket_client_read (5);                                       \
     while (vat_time_now (vam) < timeout) {                      \
         if (vam->result_ready == 1) {                           \
          (body);                                               \
index 2080a4b..bd0da10 100644 (file)
@@ -43,6 +43,24 @@ typedef struct ring_alloc_
   u32 misses;
 } ring_alloc_t;
 
+typedef enum
+{
+  VL_API_VLIB_RING,
+  VL_API_CLIENT_RING,
+  VL_API_QUEUE
+} vl_api_shm_config_type_t;
+
+typedef struct vl_api_ring_config_
+{
+  u8 type;
+  u8 _pad;
+  u16 count;
+  u32 size;
+} vl_api_shm_elem_config_t;
+
+STATIC_ASSERT (sizeof (vl_api_shm_elem_config_t) == 8,
+              "Size must be exactly 8 bytes");
+
 /*
  * Initializers for the (shared-memory) rings
  * _(size, n). Note: each msg has space for a header.
@@ -129,8 +147,8 @@ u16 vl_client_get_first_plugin_msg_id (const char *plugin_name);
 
 void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length);
 u32 vl_api_memclnt_create_internal (char *, unix_shared_memory_queue_t *);
-void vl_init_shmem (svm_region_t * vlib_rp, int is_vlib,
-                   int is_private_region);
+void vl_init_shmem (svm_region_t * vlib_rp, vl_api_shm_elem_config_t * config,
+                   int is_vlib, int is_private_region);
 void vl_client_install_client_message_handlers (void);
 void vl_api_send_pending_rpc_requests (vlib_main_t * vm);
 
@@ -197,6 +215,9 @@ typedef struct
   u8 *socket_rx_buffer;
   u32 socket_tx_nbytes;
   int control_pings_outstanding;
+
+  u8 *name;
+  clib_time_t clib_time;
 } socket_client_main_t;
 
 extern socket_client_main_t socket_client_main;
@@ -226,11 +247,14 @@ vl_api_registration_t *sockclnt_get_registration (u32 index);
 void vl_api_socket_process_msg (clib_file_t * uf, vl_api_registration_t * rp,
                                i8 * input_v);
 
-int
-vl_socket_client_connect (socket_client_main_t * scm, char *socket_path,
-                         char *client_name, u32 socket_buffer_size);
-void vl_socket_client_read_reply (socket_client_main_t * scm);
-void vl_socket_client_enable_disable (socket_client_main_t * scm, int enable);
+int vl_socket_client_connect (char *socket_path, char *client_name,
+                             u32 socket_buffer_size);
+int vl_socket_client_init_shm (vl_api_shm_elem_config_t * config);
+void vl_socket_client_disconnect (void);
+int vl_socket_client_read (int wait);
+int vl_socket_client_write (void);
+void vl_socket_client_enable_disable (int enable);
+void *vl_socket_client_msg_alloc (int nbytes);
 
 #endif /* included_vlibmemory_api_common_h */
 
index 6d6a1fe..20a73f2 100644 (file)
@@ -183,6 +183,23 @@ define memfd_segment_create_reply
   u32 master_fd;
 };
 
+/*
+ * Initialize shm api over socket api
+ */
+define sock_init_shm {
+    u32 client_index;
+    u32 context;
+    u32 requested_size;
+    u8 nitems;
+    u64 configs[nitems];
+};
+
+define sock_init_shm_reply {
+    u32 client_index;
+    u32 context;
+    i32 retval;
+};
+
 /*
  * Memory client ping / response
  * Only sent on inactive connections
index 7af2433..0a3c23c 100644 (file)
@@ -364,21 +364,11 @@ vl_set_api_pvt_heap_size (u64 size)
   am->api_pvt_heap_size = size;
 }
 
-void
-vl_init_shmem (svm_region_t * vlib_rp, int is_vlib, int is_private_region)
+static void
+vl_api_default_mem_config (vl_shmem_hdr_t * shmem_hdr)
 {
   api_main_t *am = &api_main;
-  vl_shmem_hdr_t *shmem_hdr = 0;
   u32 vlib_input_queue_length;
-  void *oldheap;
-  ASSERT (vlib_rp);
-
-  /* $$$$ need private region config parameters */
-
-  oldheap = svm_push_data_heap (vlib_rp);
-
-  vec_validate (shmem_hdr, 0);
-  shmem_hdr->version = VL_SHM_VERSION;
 
   /* vlib main input queue */
   vlib_input_queue_length = 1024;
@@ -389,7 +379,6 @@ vl_init_shmem (svm_region_t * vlib_rp, int is_vlib, int is_private_region)
     unix_shared_memory_queue_init (vlib_input_queue_length, sizeof (uword),
                                   getpid (), am->vlib_signal);
 
-  /* Set up the msg ring allocator */
 #define _(sz,n)                                                 \
     do {                                                        \
         ring_alloc_t _rp;                                       \
@@ -417,6 +406,70 @@ vl_init_shmem (svm_region_t * vlib_rp, int is_vlib, int is_private_region)
 
   foreach_clnt_aring_size;
 #undef _
+}
+
+void
+vl_api_mem_config (vl_shmem_hdr_t * hdr, vl_api_shm_elem_config_t * config)
+{
+  api_main_t *am = &api_main;
+  vl_api_shm_elem_config_t *c;
+  ring_alloc_t *rp;
+  u32 size;
+
+  if (!config)
+    {
+      vl_api_default_mem_config (hdr);
+      return;
+    }
+
+  vec_foreach (c, config)
+  {
+    switch (c->type)
+      {
+      case VL_API_QUEUE:
+       hdr->vl_input_queue = unix_shared_memory_queue_init (c->count,
+                                                            c->size,
+                                                            getpid (),
+                                                            am->vlib_signal);
+       continue;
+      case VL_API_VLIB_RING:
+       vec_add2 (hdr->vl_rings, rp, 1);
+       break;
+      case VL_API_CLIENT_RING:
+       vec_add2 (hdr->client_rings, rp, 1);
+       break;
+      default:
+       clib_warning ("unknown config type: %d", c->type);
+       continue;
+      }
+
+    size = sizeof (ring_alloc_t) + c->size;
+    rp->rp = unix_shared_memory_queue_init (c->count, size, 0, 0);
+    rp->size = size;
+    rp->nitems = c->count;
+    rp->hits = 0;
+    rp->misses = 0;
+  }
+}
+
+void
+vl_init_shmem (svm_region_t * vlib_rp, vl_api_shm_elem_config_t * config,
+              int is_vlib, int is_private_region)
+{
+  api_main_t *am = &api_main;
+  vl_shmem_hdr_t *shmem_hdr = 0;
+  void *oldheap;
+  ASSERT (vlib_rp);
+
+  /* $$$$ need private region config parameters */
+
+  oldheap = svm_push_data_heap (vlib_rp);
+
+  vec_validate (shmem_hdr, 0);
+  shmem_hdr->version = VL_SHM_VERSION;
+
+  /* Set up the queue and msg ring allocator */
+  vl_api_mem_config (shmem_hdr, config);
 
   if (is_private_region == 0)
     {
@@ -581,7 +634,8 @@ vl_map_shmem (const char *region_name, int is_vlib)
     }
 
   /* Nope, it's our problem... */
-  vl_init_shmem (vlib_rp, 1 /* is vlib */ , 0 /* is_private_region */ );
+  vl_init_shmem (vlib_rp, 0 /* default config */ , 1 /* is vlib */ ,
+                0 /* is_private_region */ );
 
   vec_add1 (am->mapped_shmem_regions, vlib_rp);
   return 0;
index 1c099ed..8054381 100644 (file)
@@ -1426,7 +1426,7 @@ vl_api_client_command (vlib_main_t * vm,
   if (!pool_elts (am->vl_clients))
     goto socket_clients;
   vlib_cli_output (vm, "Shared memory clients");
-  vlib_cli_output (vm, "%16s %8s %14s %18s %s",
+  vlib_cli_output (vm, "%20s %8s %14s %18s %s",
                   "Name", "PID", "Queue Length", "Queue VA", "Health");
 
   /* *INDENT-OFF* */
@@ -1443,7 +1443,7 @@ vl_api_client_command (vlib_main_t * vm,
 
         q = regp->vl_input_queue;
 
-        vlib_cli_output (vm, "%16s %8d %14d 0x%016llx %s\n",
+        vlib_cli_output (vm, "%20s %8d %14d 0x%016llx %s\n",
                          regp->name, q->consumer_pid, q->cursize,
                          q, health);
       }
index b60fd4f..d7a9ad5 100644 (file)
@@ -21,6 +21,8 @@
 #include <stdlib.h>
 #include <setjmp.h>
 #include <sys/types.h>
+#define __USE_GNU
+#include <sys/socket.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <netinet/in.h>
@@ -43,6 +45,7 @@
 
 #include <vlib/vlib.h>
 #include <vlib/unix/unix.h>
+#include <svm/memfd.h>
 #include <vlibmemory/api.h>
 
 #include <vlibmemory/vl_memory_msg_enum.h>
@@ -65,22 +68,26 @@ socket_client_main_t socket_client_main;
 
 /* Debug aid */
 u32 vl (void *p) __attribute__ ((weak));
+
 u32
 vl (void *p)
 {
   return vec_len (p);
 }
 
-void
-vl_socket_client_read_reply (socket_client_main_t * scm)
+int
+vl_socket_client_read (int wait)
 {
+  socket_client_main_t *scm = &socket_client_main;
   int n, current_rx_index;
-  msgbuf_t *mbp;
+  msgbuf_t *mbp = 0;
+  f64 timeout;
 
-  if (scm->socket_fd == 0 || scm->socket_enable == 0)
-    return;
+  if (scm->socket_fd == 0)
+    return -1;
 
-  mbp = 0;
+  if (wait)
+    timeout = clib_time_now (&scm->clib_time) + wait;
 
   while (1)
     {
@@ -96,7 +103,7 @@ vl_socket_client_read_reply (socket_client_main_t * scm)
          if (n < 0)
            {
              clib_unix_warning ("socket_read");
-             return;
+             return -1;
            }
          _vec_len (scm->socket_rx_buffer) += n;
        }
@@ -127,20 +134,207 @@ vl_socket_client_read_reply (socket_client_main_t * scm)
              && scm->control_pings_outstanding == 0)
            break;
        }
+
+      if (wait && clib_time_now (&scm->clib_time) >= timeout)
+       return -1;
+    }
+  return 0;
+}
+
+int
+vl_socket_client_write (void)
+{
+  socket_client_main_t *scm = &socket_client_main;
+  int n;
+
+  msgbuf_t msgbuf = {
+    .q = 0,
+    .gc_mark_timestamp = 0,
+    .data_len = htonl (scm->socket_tx_nbytes),
+  };
+
+  n = write (scm->socket_fd, &msgbuf, sizeof (msgbuf));
+  if (n < sizeof (msgbuf))
+    {
+      clib_unix_warning ("socket write (msgbuf)");
+      return -1;
+    }
+
+  n = write (scm->socket_fd, scm->socket_tx_buffer, scm->socket_tx_nbytes);
+  if (n < scm->socket_tx_nbytes)
+    {
+      clib_unix_warning ("socket write (msg)");
+      return -1;
+    }
+
+  return n;
+}
+
+void *
+vl_socket_client_msg_alloc (int nbytes)
+{
+  socket_client_main.socket_tx_nbytes = nbytes;
+  return ((void *) socket_client_main.socket_tx_buffer);
+}
+
+void
+vl_socket_client_disconnect (void)
+{
+  socket_client_main_t *scm = &socket_client_main;
+  if (scm->socket_fd && (close (scm->socket_fd) < 0))
+    clib_unix_warning ("close");
+  scm->socket_fd = 0;
+}
+
+void
+vl_socket_client_enable_disable (int enable)
+{
+  socket_client_main_t *scm = &socket_client_main;
+  scm->socket_enable = enable;
+}
+
+static clib_error_t *
+receive_fd_msg (int socket_fd, int *my_fd)
+{
+  char msgbuf[16];
+  char ctl[CMSG_SPACE (sizeof (int)) + CMSG_SPACE (sizeof (struct ucred))];
+  struct msghdr mh = { 0 };
+  struct iovec iov[1];
+  ssize_t size;
+  struct ucred *cr = 0;
+  struct cmsghdr *cmsg;
+  pid_t pid __attribute__ ((unused));
+  uid_t uid __attribute__ ((unused));
+  gid_t gid __attribute__ ((unused));
+
+  iov[0].iov_base = msgbuf;
+  iov[0].iov_len = 5;
+  mh.msg_iov = iov;
+  mh.msg_iovlen = 1;
+  mh.msg_control = ctl;
+  mh.msg_controllen = sizeof (ctl);
+
+  memset (ctl, 0, sizeof (ctl));
+
+  /* receive the incoming message */
+  size = recvmsg (socket_fd, &mh, 0);
+  if (size != 5)
+    {
+      return (size == 0) ? clib_error_return (0, "disconnected") :
+       clib_error_return_unix (0, "recvmsg: malformed message (fd %d)",
+                               socket_fd);
+    }
+
+  cmsg = CMSG_FIRSTHDR (&mh);
+  while (cmsg)
+    {
+      if (cmsg->cmsg_level == SOL_SOCKET)
+       {
+         if (cmsg->cmsg_type == SCM_CREDENTIALS)
+           {
+             cr = (struct ucred *) CMSG_DATA (cmsg);
+             uid = cr->uid;
+             gid = cr->gid;
+             pid = cr->pid;
+           }
+         else if (cmsg->cmsg_type == SCM_RIGHTS)
+           {
+             clib_memcpy (my_fd, CMSG_DATA (cmsg), sizeof (int));
+           }
+       }
+      cmsg = CMSG_NXTHDR (&mh, cmsg);
+    }
+  return 0;
+}
+
+static void vl_api_sock_init_shm_reply_t_handler
+  (vl_api_sock_init_shm_reply_t * mp)
+{
+  socket_client_main_t *scm = &socket_client_main;
+  int my_fd = -1;
+  clib_error_t *error;
+  i32 retval = ntohl (mp->retval);
+  memfd_private_t memfd;
+  api_main_t *am = &api_main;
+  u8 *new_name;
+
+  if (retval)
+    {
+      clib_warning ("failed to init shmem");
+      return;
+    }
+
+  /*
+   * Check the socket for the magic fd
+   */
+  error = receive_fd_msg (scm->socket_fd, &my_fd);
+  if (error)
+    {
+      retval = -99;
+      return;
     }
+
+  memset (&memfd, 0, sizeof (memfd));
+  memfd.fd = my_fd;
+
+  /* Note: this closes memfd.fd */
+  retval = memfd_slave_init (&memfd);
+  if (retval)
+    clib_warning ("WARNING: segment map returned %d", retval);
+
+  /*
+   * Pivot to the memory client segment that vpp just created
+   */
+  am->vlib_rp = (void *) (memfd.requested_va + MMAP_PAGESIZE);
+  am->shmem_hdr = (void *) am->vlib_rp->user_ctx;
+
+  new_name = format (0, "%v[shm]%c", scm->name, 0);
+  vl_client_install_client_message_handlers ();
+  vl_client_connect_to_vlib_no_map ("pvt", (char *) new_name,
+                                   32 /* input_queue_length */ );
+  vl_socket_client_enable_disable (0);
+  vec_free (new_name);
+}
+
+static void
+vl_api_sockclnt_create_reply_t_handler (vl_api_sockclnt_create_reply_t * mp)
+{
+  socket_client_main_t *scm = &socket_client_main;
+  if (!mp->response)
+    scm->socket_enable = 1;
+}
+
+#define foreach_sock_client_api_msg                            \
+_(SOCKCLNT_CREATE_REPLY, sockclnt_create_reply)                        \
+_(SOCK_INIT_SHM_REPLY, sock_init_shm_reply)                    \
+
+static void
+noop_handler (void *notused)
+{
+}
+
+void
+vl_sock_client_install_message_handlers (void)
+{
+
+#define _(N,n)                                                  \
+    vl_msg_api_set_handlers(VL_API_##N, #n,                     \
+                            vl_api_##n##_t_handler,             \
+                            noop_handler,                       \
+                            vl_api_##n##_t_endian,              \
+                            vl_api_##n##_t_print,               \
+                            sizeof(vl_api_##n##_t), 1);
+  foreach_sock_client_api_msg;
+#undef _
 }
 
 int
-vl_socket_client_connect (socket_client_main_t * scm, char *socket_path,
-                         char *client_name, u32 socket_buffer_size)
+vl_socket_client_connect (char *socket_path, char *client_name,
+                         u32 socket_buffer_size)
 {
-  char buffer[256];
-  char *rdptr;
-  int n, total_bytes;
-  vl_api_sockclnt_create_reply_t *rp;
+  socket_client_main_t *scm = &socket_client_main;
   vl_api_sockclnt_create_t *mp;
-  clib_socket_t *sock = &scm->client_socket;
-  msgbuf_t *mbp;
+  clib_socket_t *sock;
   clib_error_t *error;
 
   /* Already connected? */
@@ -151,84 +345,74 @@ vl_socket_client_connect (socket_client_main_t * scm, char *socket_path,
   if (socket_path == 0 || client_name == 0)
     return (-3);
 
+  sock = &scm->client_socket;
   sock->config = socket_path;
   sock->flags = CLIB_SOCKET_F_IS_CLIENT | CLIB_SOCKET_F_SEQPACKET;
 
-  error = clib_socket_init (sock);
-
-  if (error)
+  if ((error = clib_socket_init (sock)))
     {
       clib_error_report (error);
       return (-1);
     }
 
-  scm->socket_fd = sock->fd;
+  vl_sock_client_install_message_handlers ();
 
-  mbp = (msgbuf_t *) buffer;
-  mbp->q = 0;
-  mbp->data_len = htonl (sizeof (*mp));
-  mbp->gc_mark_timestamp = 0;
+  scm->socket_fd = sock->fd;
+  scm->socket_buffer_size = socket_buffer_size ? socket_buffer_size :
+    SOCKET_CLIENT_DEFAULT_BUFFER_SIZE;
+  vec_validate (scm->socket_tx_buffer, scm->socket_buffer_size - 1);
+  vec_validate (scm->socket_rx_buffer, scm->socket_buffer_size - 1);
+  _vec_len (scm->socket_rx_buffer) = 0;
+  _vec_len (scm->socket_tx_buffer) = 0;
+  scm->name = format (0, "%s", client_name);
 
-  mp = (vl_api_sockclnt_create_t *) mbp->data;
+  mp = vl_socket_client_msg_alloc (sizeof (*mp));
   mp->_vl_msg_id = htons (VL_API_SOCKCLNT_CREATE);
   strncpy ((char *) mp->name, client_name, sizeof (mp->name) - 1);
   mp->name[sizeof (mp->name) - 1] = 0;
   mp->context = 0xfeedface;
 
-  n = write (scm->socket_fd, mbp, sizeof (*mbp) + sizeof (*mp));
-  if (n < 0)
-    {
-      clib_unix_warning ("socket write (msg)");
-      return (-1);
-    }
+  if (vl_socket_client_write () <= 0)
+    return (-1);
 
-  memset (buffer, 0, sizeof (buffer));
+  if (vl_socket_client_read (1))
+    return (-1);
 
-  total_bytes = 0;
-  rdptr = buffer;
-  do
+  clib_time_init (&scm->clib_time);
+  return (0);
+}
+
+int
+vl_socket_client_init_shm (vl_api_shm_elem_config_t * config)
+{
+  vl_api_sock_init_shm_t *mp;
+  int rv, i;
+  u64 *cfg;
+
+  mp = vl_socket_client_msg_alloc (sizeof (*mp) +
+                                  vec_len (config) * sizeof (u64));
+  memset (mp, 0, sizeof (*mp));
+  mp->_vl_msg_id = clib_host_to_net_u16 (VL_API_SOCK_INIT_SHM);
+  mp->client_index = ~0;
+  mp->requested_size = 64 << 20;
+
+  if (config)
     {
-      n = read (scm->socket_fd, rdptr, sizeof (buffer) - (rdptr - buffer));
-      if (n < 0)
+      for (i = 0; i < vec_len (config); i++)
        {
-         clib_unix_warning ("socket read");
+         cfg = (u64 *) & config[i];
+         mp->configs[i] = *cfg;
        }
-      total_bytes += n;
-      rdptr += n;
-    }
-  while (total_bytes < sizeof (vl_api_sockclnt_create_reply_t)
-        + sizeof (msgbuf_t));
-
-  rp = (vl_api_sockclnt_create_reply_t *) (buffer + sizeof (msgbuf_t));
-  if (ntohs (rp->_vl_msg_id) != VL_API_SOCKCLNT_CREATE_REPLY)
-    {
-      clib_warning ("connect reply got msg id %d\n", ntohs (rp->_vl_msg_id));
-      return (-1);
+      mp->nitems = vec_len (config);
     }
+  rv = vl_socket_client_write ();
+  if (rv <= 0)
+    return rv;
 
-  /* allocate tx, rx buffers */
-  scm->socket_buffer_size = socket_buffer_size ? socket_buffer_size :
-    SOCKET_CLIENT_DEFAULT_BUFFER_SIZE;
-  vec_validate (scm->socket_tx_buffer, scm->socket_buffer_size - 1);
-  vec_validate (scm->socket_rx_buffer, scm->socket_buffer_size - 1);
-  _vec_len (scm->socket_rx_buffer) = 0;
-  scm->socket_enable = 1;
+  if (vl_socket_client_read (1))
+    return -1;
 
-  return (0);
-}
-
-void
-vl_socket_client_disconnect (socket_client_main_t * scm)
-{
-  if (scm->socket_fd && (close (scm->socket_fd) < 0))
-    clib_unix_warning ("close");
-  scm->socket_fd = 0;
-}
-
-void
-vl_socket_client_enable_disable (socket_client_main_t * scm, int enable)
-{
-  scm->socket_enable = enable;
+  return 0;
 }
 
 /*
index 1a263e7..314e2eb 100644 (file)
@@ -62,13 +62,13 @@ dump_socket_clients (vlib_main_t * vm, api_main_t * am)
     return;
 
   vlib_cli_output (vm, "Socket clients");
-  vlib_cli_output (vm, "%16s %8s", "Name", "Fildesc");
+  vlib_cli_output (vm, "%20s %8s", "Name", "Fildesc");
     /* *INDENT-OFF* */
     pool_foreach (reg, sm->registration_pool,
     ({
         if (reg->registration_type == REGISTRATION_TYPE_SOCKET_SERVER) {
             f = pool_elt_at_index (fm->file_pool, reg->clib_file_index);
-            vlib_cli_output (vm, "%16s %8d",
+            vlib_cli_output (vm, "%20s %8d",
                              reg->name, f->file_descriptor);
         }
     }));
@@ -78,13 +78,15 @@ dump_socket_clients (vlib_main_t * vm, api_main_t * am)
 void
 vl_socket_api_send (vl_api_registration_t * rp, u8 * elem)
 {
-  u16 msg_id = ntohs (*(u16 *) elem);
-  api_main_t *am = &api_main;
-  msgbuf_t *mb = (msgbuf_t *) (elem - offsetof (msgbuf_t, data));
 #if CLIB_DEBUG > 1
   u32 output_length;
 #endif
-  clib_file_t *cf = rp->clib_file_index + file_main.file_pool;
+  socket_main_t *sm = &socket_main;
+  u16 msg_id = ntohs (*(u16 *) elem);
+  api_main_t *am = &api_main;
+  msgbuf_t *mb = (msgbuf_t *) (elem - offsetof (msgbuf_t, data));
+  clib_file_t *cf = clib_file_get (&file_main, rp->clib_file_index);
+  vl_api_registration_t *sock_rp;
 
   ASSERT (rp->registration_type > REGISTRATION_TYPE_SHMEM);
 
@@ -95,16 +97,15 @@ vl_socket_api_send (vl_api_registration_t * rp, u8 * elem)
       return;
     }
 
+  sock_rp = pool_elt_at_index (sm->registration_pool,
+                              rp->vl_api_registration_pool_index);
+  ASSERT (sock_rp);
+
   /* Add the msgbuf_t to the output vector */
-  vl_socket_add_pending_output_no_flush (cf,
-                                        rp->vl_api_registration_pool_index +
-                                        socket_main.registration_pool,
-                                        (u8 *) mb, sizeof (*mb));
+  vl_socket_add_pending_output_no_flush (cf, sock_rp, (u8 *) mb,
+                                        sizeof (*mb));
   /* Send the message */
-  vl_socket_add_pending_output (cf,
-                               rp->vl_api_registration_pool_index
-                               + socket_main.registration_pool,
-                               elem, ntohl (mb->data_len));
+  vl_socket_add_pending_output (cf, sock_rp, elem, ntohl (mb->data_len));
 
 #if CLIB_DEBUG > 1
   output_length = sizeof (*mb) + ntohl (mb->data_len);
@@ -318,7 +319,6 @@ vl_socket_write_ready (clib_file_t * uf)
   /* Flush output vector. */
   n = write (uf->file_descriptor,
             rp->output_vector, vec_len (rp->output_vector));
-
   if (n < 0)
     {
 #if DEBUG > 2
@@ -402,7 +402,7 @@ vl_api_sockclnt_create_t_handler (vl_api_sockclnt_create_t * mp)
 {
   vl_api_registration_t *regp;
   vl_api_sockclnt_create_reply_t *rp;
-  int rv = 1;
+  int rv = 0;
 
   regp = socket_main.current_rp;
 
@@ -480,54 +480,93 @@ send_fd_msg (int socket_fd, int fd_to_share)
   return 0;
 }
 
+vl_api_shm_elem_config_t *
+vl_api_make_shm_config (vl_api_sock_init_shm_t * mp)
+{
+  vl_api_shm_elem_config_t *config = 0, *c;
+  u64 cfg;
+  int i;
+
+  if (!mp->nitems)
+    {
+      vec_validate (config, 3);
+      config[0].type = VL_API_VLIB_RING;
+      config[0].count = 128;
+      config[0].size = 256;
+      config[1].type = VL_API_CLIENT_RING;
+      config[1].count = 128;
+      config[1].size = 1024;
+      config[2].type = VL_API_CLIENT_RING;
+      config[2].count = 8;
+      config[2].size = 4096;
+      config[3].type = VL_API_QUEUE;
+      config[3].count = 128;
+      config[3].size = sizeof (uword);
+    }
+  else
+    {
+      vec_validate (config, mp->nitems - 1);
+      for (i = 0; i < mp->nitems; i++)
+       {
+         cfg = mp->configs[i];
+         /* Pretty much a hack but it avoids defining our own api type
+          * in memclnt.api */
+         c = (vl_api_shm_elem_config_t *) & cfg;
+         config[i].type = c->type;
+         config[i].count = c->count;
+         config[i].size = c->size;
+       }
+    }
+  return config;
+}
+
 /*
- * Create a memory-fd segment.
+ * Bootstrap shm api using the socket api
  */
 void
-vl_api_memfd_segment_create_t_handler (vl_api_memfd_segment_create_t * mp)
+vl_api_sock_init_shm_t_handler (vl_api_sock_init_shm_t * mp)
 {
-  vl_api_memfd_segment_create_reply_t *rmp;
-  api_main_t *am = &api_main;
-  clib_file_t *cf;
+  vl_api_sock_init_shm_reply_t *rmp;
   memfd_private_t _memfd_private, *memfd = &_memfd_private;
-  vl_api_registration_t *regp;
-  vlib_main_t *vm = vlib_get_main ();
   svm_map_region_args_t _args, *a = &_args;
+  vl_api_registration_t *regp;
+  api_main_t *am = &api_main;
   svm_region_t *vlib_rp;
+  clib_file_t *cf;
+  vl_api_shm_elem_config_t *config = 0;
   int rv;
 
   regp = vl_api_client_index_to_registration (mp->client_index);
-
   if (regp == 0)
     {
       clib_warning ("API client disconnected");
       return;
     }
-
   if (regp->registration_type != REGISTRATION_TYPE_SOCKET_SERVER)
     {
       rv = -31;                        /* VNET_API_ERROR_INVALID_REGISTRATION */
       goto reply;
     }
 
+  /*
+   * Set up a memfd segment of the requested size wherein the
+   * shmem data structures will be initialized
+   */
   memset (memfd, 0, sizeof (*memfd));
-
-  /* Embed in api_main_t */
   memfd->memfd_size = mp->requested_size;
   memfd->requested_va = 0ULL;
   memfd->i_am_master = 1;
   memfd->name = format (0, "%s%c", regp->name, 0);
 
-  /* Set up a memfd segment of the requested size */
-  rv = memfd_master_init (memfd, mp->client_index);
-
-  if (rv)
+  if ((rv = memfd_master_init (memfd, mp->client_index)))
     goto reply;
 
   /* Remember to close this fd when the socket connection goes away */
   vec_add1 (regp->additional_fds_to_close, memfd->fd);
 
-  /* And create a plausible svm_region in it */
+  /*
+   * Create a plausible svm_region in the memfd backed segment
+   */
   memset (a, 0, sizeof (*a));
   a->baseva = memfd->sh->memfd_va + MMAP_PAGESIZE;
   a->size = memfd->memfd_size - MMAP_PAGESIZE;
@@ -536,24 +575,77 @@ vl_api_memfd_segment_create_t_handler (vl_api_memfd_segment_create_t * mp)
   a->flags = SVM_FLAGS_MHEAP;
   svm_region_init_mapped_region (a, (svm_region_t *) a->baseva);
 
-  vlib_rp = (svm_region_t *) a->baseva;
-
   /*
    * Part deux, initialize the svm_region_t shared-memory header
    * api allocation rings, and so on.
    */
-  vl_init_shmem (vlib_rp, 1 /* is_vlib (dont-care) */ , 1 /* is_private */ );
-
+  config = vl_api_make_shm_config (mp);
+  vlib_rp = (svm_region_t *) a->baseva;
+  vl_init_shmem (vlib_rp, config, 1 /* is_vlib (dont-care) */ ,
+                1 /* is_private */ );
   vec_add1 (am->vlib_private_rps, vlib_rp);
-
   memfd->sh->ready = 1;
+  vec_free (config);
 
   /* Recompute the set of input queues to poll in memclnt_process */
   vec_reset_length (vl_api_queue_cursizes);
 
 reply:
 
-  /* send the reply message */
+  rmp = vl_msg_api_alloc (sizeof (*rmp));
+  rmp->_vl_msg_id = htons (VL_API_SOCK_INIT_SHM_REPLY);
+  rmp->context = mp->context;
+  rmp->retval = htonl (rv);
+
+  vl_msg_api_send (regp, (u8 *) rmp);
+
+  if (rv != 0)
+    return;
+
+  /*
+   * We need the reply message to make it out the back door
+   * before we send the magic fd message so force a flush
+   */
+  cf = clib_file_get (&file_main, regp->clib_file_index);
+  cf->write_function (cf);
+
+  /* Send the magic "here's your sign (aka fd)" socket message */
+  send_fd_msg (cf->file_descriptor, memfd->fd);
+}
+
+/*
+ * Create a memory-fd segment.
+ */
+void
+vl_api_memfd_segment_create_t_handler (vl_api_memfd_segment_create_t * mp)
+{
+  vl_api_memfd_segment_create_reply_t *rmp;
+  clib_file_t *cf;
+  memfd_private_t _memfd_private, *memfd = &_memfd_private;
+  vl_api_registration_t *regp;
+  int rv;
+
+  regp = vl_api_client_index_to_registration (mp->client_index);
+  if (regp == 0)
+    {
+      clib_warning ("API client disconnected");
+      return;
+    }
+
+  memset (memfd, 0, sizeof (*memfd));
+  memfd->memfd_size = mp->requested_size;
+  memfd->requested_va = 0ULL;
+  memfd->i_am_master = 1;
+  memfd->name = format (0, "%s%c", regp->name, 0);
+
+  /* Set up a memfd segment of the requested size */
+  if ((rv = memfd_master_init (memfd, mp->client_index)))
+    goto reply;
+
+  /* Remember to close this fd when the socket connection goes away */
+  vec_add1 (regp->additional_fds_to_close, memfd->fd);
+
+reply:
 
   rmp = vl_msg_api_alloc (sizeof (*rmp));
   rmp->_vl_msg_id = htons (VL_API_MEMFD_SEGMENT_CREATE_REPLY);
@@ -569,17 +661,17 @@ reply:
    * We need the reply message to make it out the back door
    * before we send the magic fd message.
    */
-  vlib_process_suspend (vm, 11e-6);
-
   cf = file_main.file_pool + regp->clib_file_index;
+  cf->write_function (cf);
 
   /* send the magic "here's your sign (aka fd)" socket message */
   send_fd_msg (cf->file_descriptor, memfd->fd);
 }
 
-#define foreach_vlib_api_msg                    \
-_(SOCKCLNT_CREATE, sockclnt_create)             \
-_(SOCKCLNT_DELETE, sockclnt_delete)            \
+#define foreach_vlib_api_msg                           \
+_(SOCKCLNT_CREATE, sockclnt_create)                    \
+_(SOCKCLNT_DELETE, sockclnt_delete)                    \
+_(SOCK_INIT_SHM, sock_init_shm)                        \
 _(MEMFD_SEGMENT_CREATE, memfd_segment_create)
 
 clib_error_t *
@@ -588,8 +680,6 @@ socksvr_api_init (vlib_main_t * vm)
   clib_file_main_t *fm = &file_main;
   clib_file_t template = { 0 };
   vl_api_registration_t *rp;
-  vl_msg_api_msg_config_t cfg;
-  vl_msg_api_msg_config_t *c = &cfg;
   socket_main_t *sm = &socket_main;
   clib_socket_t *sock = &sm->socksvr_listen_socket;
   clib_error_t *error;
@@ -598,19 +688,13 @@ socksvr_api_init (vlib_main_t * vm)
   if (sm->socket_name == 0)
     return 0;
 
-#define _(N,n) do {                                             \
-    c->id = VL_API_##N;                                         \
-    c->name = #n;                                               \
-    c->handler = vl_api_##n##_t_handler;                        \
-    c->cleanup = vl_noop_handler;                               \
-    c->endian = vl_api_##n##_t_endian;                          \
-    c->print = vl_api_##n##_t_print;                            \
-    c->size = sizeof(vl_api_##n##_t);                           \
-    c->traced = 1; /* trace, so these msgs print */             \
-    c->replay = 0; /* don't replay client create/delete msgs */ \
-    c->message_bounce = 0; /* don't bounce this message */     \
-    vl_msg_api_config(c);} while (0);
-
+#define _(N,n)                                                  \
+    vl_msg_api_set_handlers(VL_API_##N, #n,                     \
+                           vl_api_##n##_t_handler,              \
+                           vl_noop_handler,                     \
+                           vl_api_##n##_t_endian,               \
+                           vl_api_##n##_t_print,                \
+                           sizeof(vl_api_##n##_t), 1);
   foreach_vlib_api_msg;
 #undef _
 
index 0def13c..0708bf0 100644 (file)
@@ -1328,16 +1328,9 @@ vl_api_one_eid_table_vni_dump_t_handler (vl_api_one_eid_table_vni_dump_t * mp)
 static void
 vl_api_show_one_status_t_handler (vl_api_show_one_status_t * mp)
 {
-  unix_shared_memory_queue_t *q = NULL;
   vl_api_show_one_status_reply_t *rmp = NULL;
   int rv = 0;
 
-  q = vl_api_client_index_to_input_queue (mp->client_index);
-  if (q == 0)
-    {
-      return;
-    }
-
   /* *INDENT-OFF* */
   REPLY_MACRO2(VL_API_SHOW_ONE_STATUS_REPLY,
   ({
@@ -1351,19 +1344,12 @@ static void
   vl_api_one_get_map_request_itr_rlocs_t_handler
   (vl_api_one_get_map_request_itr_rlocs_t * mp)
 {
-  unix_shared_memory_queue_t *q = NULL;
   vl_api_one_get_map_request_itr_rlocs_reply_t *rmp = NULL;
   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
   locator_set_t *loc_set = 0;
   u8 *tmp_str = 0;
   int rv = 0;
 
-  q = vl_api_client_index_to_input_queue (mp->client_index);
-  if (q == 0)
-    {
-      return;
-    }
-
   if (~0 == lcm->mreq_itr_rlocs)
     {
       tmp_str = format (0, " ");
index 6ebf512..4231a39 100644 (file)
@@ -122,6 +122,13 @@ clib_file_set_data_available_to_write (clib_file_main_t * um,
   return was_available != 0;
 }
 
+always_inline clib_file_t *
+clib_file_get (clib_file_main_t * fm, u32 file_index)
+{
+  if (pool_is_free_index (fm->file_pool, file_index))
+    return 0;
+  return pool_elt_at_index (fm->file_pool, file_index);
+}
 
 #endif /* included_clib_file_h */