session: add support for memfd segments

- update segment manager and session api to work with both flavors of
  ssvm segments
- added generic ssvm slave/master init and del functions
- cleanup/refactor tcp_echo
- fixed uses of svm fifo pool as vector

Change-Id: Ieee8b163faa407da6e77e657a2322de213a9d2a0
Signed-off-by: Florin Coras <fcoras@cisco.com>
diff --git a/src/vlibmemory/api.h b/src/vlibmemory/api.h
index e86b88c..8d2b191 100644
--- a/src/vlibmemory/api.h
+++ b/src/vlibmemory/api.h
@@ -61,6 +61,44 @@
   return (vl_mem_api_client_index_to_registration (index));
 }
 
+always_inline u32
+vl_api_registration_file_index (vl_api_registration_t * reg)
+{
+  return reg->clib_file_index;
+}
+
+always_inline clib_file_t *
+vl_api_registration_file (vl_api_registration_t * reg)
+{
+  return clib_file_get (&file_main, vl_api_registration_file_index (reg));
+}
+
+always_inline void
+vl_api_registration_del_file (vl_api_registration_t * reg)
+{
+  clib_file_t *cf = vl_api_registration_file (reg);
+  if (cf)
+    clib_file_del (&file_main, cf);
+}
+
+always_inline clib_error_t *
+vl_api_send_fd_msg (vl_api_registration_t * reg, int fd_to_send)
+{
+  clib_file_t *cf = vl_api_registration_file (reg);
+  if (cf)
+    return vl_sock_api_send_fd_msg (cf->file_descriptor, fd_to_send);
+  return 0;
+}
+
+always_inline clib_error_t *
+vl_api_recv_fd_msg (vl_api_registration_t * reg, int *fd_to_recv, u32 wait)
+{
+  clib_file_t *cf = vl_api_registration_file (reg);
+  if (cf)
+    return vl_sock_api_recv_fd_msg (cf->file_descriptor, fd_to_recv, wait);
+  return 0;
+}
+
 /*
  * vl_api_clnt process data used by transports (socket api in particular)
  */
diff --git a/src/vlibmemory/memory_api.c b/src/vlibmemory/memory_api.c
index 752f507..0ee1384 100644
--- a/src/vlibmemory/memory_api.c
+++ b/src/vlibmemory/memory_api.c
@@ -198,6 +198,7 @@
   regp->vl_api_registration_pool_index = regpp - am->vl_clients;
   regp->vlib_rp = svm;
   regp->shmem_hdr = am->shmem_hdr;
+  regp->clib_file_index = am->shmem_hdr->clib_file_index;
 
   q = regp->vl_input_queue = (svm_queue_t *) (uword) mp->input_queue;
 
@@ -273,7 +274,7 @@
       return;
     }
 
-  regpp = am->vl_clients + client_index;
+  regpp = pool_elt_at_index (am->vl_clients, client_index);
 
   if (!pool_is_free (am->vl_clients, regpp))
     {
@@ -509,11 +510,54 @@
   am->shmem_hdr = save_shmem_hdr;
 }
 
+static void
+vl_mem_send_client_keepalive_w_reg (api_main_t * am, f64 now,
+				    vl_api_registration_t ** regpp,
+				    u32 ** dead_indices,
+				    u32 ** confused_indices)
+{
+  vl_api_registration_t *regp = *regpp;
+  if (regp)
+    {
+      /* If we haven't heard from this client recently... */
+      if (regp->last_heard < (now - 10.0))
+	{
+	  if (regp->unanswered_pings == 2)
+	    {
+	      svm_queue_t *q;
+	      q = regp->vl_input_queue;
+	      if (kill (q->consumer_pid, 0) >= 0)
+		{
+		  clib_warning ("REAPER: lazy binary API client '%s'",
+				regp->name);
+		  regp->unanswered_pings = 0;
+		  regp->last_heard = now;
+		}
+	      else
+		{
+		  clib_warning ("REAPER: binary API client '%s' died",
+				regp->name);
+		  vec_add1 (*dead_indices, regpp - am->vl_clients);
+		}
+	    }
+	  else
+	    send_memclnt_keepalive (regp, now);
+	}
+      else
+	regp->unanswered_pings = 0;
+    }
+  else
+    {
+      clib_warning ("NULL client registration index %d",
+		    regpp - am->vl_clients);
+      vec_add1 (*confused_indices, regpp - am->vl_clients);
+    }
+}
+
 void
 vl_mem_api_dead_client_scan (api_main_t * am, vl_shmem_hdr_t * shm, f64 now)
 {
   vl_api_registration_t **regpp;
-  vl_api_registration_t *regp;
   static u32 *dead_indices;
   static u32 *confused_indices;
 
@@ -521,46 +565,12 @@
   vec_reset_length (confused_indices);
 
   /* *INDENT-OFF* */
-  pool_foreach (regpp, am->vl_clients,
-  ({
-    regp = *regpp;
-    if (regp)
-      {
-        /* If we haven't heard from this client recently... */
-        if (regp->last_heard < (now - 10.0))
-          {
-            if (regp->unanswered_pings == 2)
-              {
-                svm_queue_t *q;
-                q = regp->vl_input_queue;
-                if (kill (q->consumer_pid, 0) >=0)
-                  {
-                    clib_warning ("REAPER: lazy binary API client '%s'",
-                                  regp->name);
-                    regp->unanswered_pings = 0;
-                    regp->last_heard = now;
-                  }
-                else
-                  {
-                    clib_warning ("REAPER: binary API client '%s' died",
-                                  regp->name);
-                    vec_add1(dead_indices, regpp - am->vl_clients);
-                  }
-              }
-            else
-              send_memclnt_keepalive (regp, now);
-          }
-        else
-          regp->unanswered_pings = 0;
-      }
-    else
-      {
-        clib_warning ("NULL client registration index %d",
-                      regpp - am->vl_clients);
-        vec_add1 (confused_indices, regpp - am->vl_clients);
-      }
+  pool_foreach (regpp, am->vl_clients, ({
+      vl_mem_send_client_keepalive_w_reg (am, now, regpp, &dead_indices,
+                                          &confused_indices);
   }));
   /* *INDENT-ON* */
+
   /* This should "never happen," but if it does, fix it... */
   if (PREDICT_FALSE (vec_len (confused_indices) > 0))
     {
@@ -702,16 +712,10 @@
   vl_api_registration_t **regpp;
   vl_api_registration_t *regp;
   api_main_t *am = &api_main;
+  vl_shmem_hdr_t *shmem_hdr;
   u32 index;
 
   index = vl_msg_api_handle_get_index (handle);
-  if ((am->shmem_hdr->application_restarts & VL_API_EPOCH_MASK)
-      != vl_msg_api_handle_get_epoch (handle))
-    {
-      vl_msg_api_increment_missing_client_counter ();
-      return 0;
-    }
-
   regpp = am->vl_clients + index;
 
   if (pool_is_free (am->vl_clients, regpp))
@@ -720,6 +724,14 @@
       return 0;
     }
   regp = *regpp;
+
+  shmem_hdr = (vl_shmem_hdr_t *) regp->shmem_hdr;
+  if (!vl_msg_api_handle_is_valid (handle, shmem_hdr->application_restarts))
+    {
+      vl_msg_api_increment_missing_client_counter ();
+      return 0;
+    }
+
   return (regp);
 }
 
diff --git a/src/vlibmemory/memory_api.h b/src/vlibmemory/memory_api.h
index 58f47d1..4cda04b 100644
--- a/src/vlibmemory/memory_api.h
+++ b/src/vlibmemory/memory_api.h
@@ -58,6 +58,13 @@
   return handle;
 }
 
+static inline u8
+vl_msg_api_handle_is_valid (u32 handle, u32 restarts)
+{
+  u32 epoch = vl_msg_api_handle_get_epoch (handle);
+  return ((restarts & VL_API_EPOCH_MASK) == epoch);
+}
+
 #define VL_MEM_API_LOG_Q_LEN(fmt,qlen)			\
 if (TRACE_VLIB_MEMORY_QUEUE)				\
   do {							\
diff --git a/src/vlibmemory/memory_client.c b/src/vlibmemory/memory_client.c
index deb913b..9f53301 100644
--- a/src/vlibmemory/memory_client.c
+++ b/src/vlibmemory/memory_client.c
@@ -190,8 +190,8 @@
 
   pthread_mutex_lock (&svm->mutex);
   oldheap = svm_push_data_heap (svm);
-  vl_input_queue =
-    svm_queue_init (input_queue_size, sizeof (uword), getpid (), 0);
+  vl_input_queue = svm_queue_init (input_queue_size, sizeof (uword),
+				   getpid (), 0);
   pthread_mutex_unlock (&svm->mutex);
   svm_pop_heap (oldheap);
 
@@ -289,7 +289,6 @@
    * Have to be careful here, in case the client is disconnecting
    * because e.g. the vlib process died, or is unresponsive.
    */
-
   begin = time (0);
   while (1)
     {
@@ -362,7 +361,6 @@
 #undef _
 }
 
-
 int
 vl_client_api_map (const char *region_name)
 {
@@ -381,6 +379,12 @@
   vl_unmap_shmem ();
 }
 
+u8
+vl_mem_client_is_connected (void)
+{
+  return (memory_client_main.connected_to_vlib != 0);
+}
+
 static int
 connect_to_vlib_internal (const char *svm_name,
 			  const char *client_name,
@@ -444,8 +448,8 @@
 				   0 /* dont map */ );
 }
 
-void
-vl_client_disconnect_from_vlib (void)
+static void
+disconnect_from_vlib_internal (u8 do_unmap)
 {
   memory_client_main_t *mm = &memory_client_main;
   api_main_t *am = &api_main;
@@ -462,11 +466,24 @@
   if (mm->connected_to_vlib)
     {
       vl_client_disconnect ();
-      vl_client_api_unmap ();
+      if (do_unmap)
+	vl_client_api_unmap ();
     }
   memset (mm, 0, sizeof (*mm));
 }
 
+void
+vl_client_disconnect_from_vlib (void)
+{
+  disconnect_from_vlib_internal (1);
+}
+
+void
+vl_client_disconnect_from_vlib_no_unmap (void)
+{
+  disconnect_from_vlib_internal (0);
+}
+
 static void vl_api_get_first_msg_id_reply_t_handler
   (vl_api_get_first_msg_id_reply_t * mp)
 {
diff --git a/src/vlibmemory/memory_client.h b/src/vlibmemory/memory_client.h
index 5b4f090..3fcca9e 100644
--- a/src/vlibmemory/memory_client.h
+++ b/src/vlibmemory/memory_client.h
@@ -25,6 +25,7 @@
 int vl_client_api_map (const char *region_name);
 void vl_client_api_unmap (void);
 void vl_client_disconnect_from_vlib (void);
+void vl_client_disconnect_from_vlib_no_unmap (void);
 int vl_client_connect_to_vlib (const char *svm_name, const char *client_name,
 			       int rx_queue_size);
 int vl_client_connect_to_vlib_no_rx_pthread (const char *svm_name,
@@ -34,6 +35,7 @@
 				      const char *client_name,
 				      int rx_queue_size);
 void vl_client_install_client_message_handlers (void);
+u8 vl_mem_client_is_connected (void);
 
 #endif /* SRC_VLIBMEMORY_MEMORY_CLIENT_H_ */
 
diff --git a/src/vlibmemory/memory_shared.c b/src/vlibmemory/memory_shared.c
index 5b7d735..488a302 100644
--- a/src/vlibmemory/memory_shared.c
+++ b/src/vlibmemory/memory_shared.c
@@ -230,6 +230,25 @@
   return vl_msg_api_alloc_internal (nbytes, 0, 1 /* may_return_null */ );
 }
 
+void *
+vl_mem_api_alloc_as_if_client_w_reg (vl_api_registration_t * reg, int nbytes)
+{
+  api_main_t *am = &api_main;
+  vl_shmem_hdr_t *save_shmem_hdr = am->shmem_hdr;
+  svm_region_t *vlib_rp, *save_vlib_rp = am->vlib_rp;
+  void *msg;
+
+  vlib_rp = am->vlib_rp = reg->vlib_rp;
+  am->shmem_hdr = (void *) vlib_rp->user_ctx;
+
+  msg = vl_msg_api_alloc_internal (nbytes, 0, 0 /* may_return_null */ );
+
+  am->shmem_hdr = save_shmem_hdr;
+  am->vlib_rp = save_vlib_rp;
+
+  return msg;
+}
+
 void
 vl_msg_api_free (void *a)
 {
@@ -464,6 +483,7 @@
 
   vec_validate (shmem_hdr, 0);
   shmem_hdr->version = VL_SHM_VERSION;
+  shmem_hdr->clib_file_index = VL_API_INVALID_FI;
 
   /* Set up the queue and msg ring allocator */
   vl_api_mem_config (shmem_hdr, config);
diff --git a/src/vlibmemory/memory_shared.h b/src/vlibmemory/memory_shared.h
index 8a7667c..deaa621 100644
--- a/src/vlibmemory/memory_shared.h
+++ b/src/vlibmemory/memory_shared.h
@@ -99,6 +99,9 @@
 
   /* Number of garbage-collected messages */
   u32 garbage_collects;
+
+  /* Socket file index used to bootstrap shmem region */
+  u32 clib_file_index;
 } vl_shmem_hdr_t;
 
 #define VL_SHM_VERSION 2
@@ -109,6 +112,8 @@
 void *vl_msg_api_alloc_or_null (int nbytes);
 void *vl_msg_api_alloc_as_if_client (int nbytes);
 void *vl_msg_api_alloc_as_if_client_or_null (int nbytes);
+void *vl_mem_api_alloc_as_if_client_w_reg (vl_api_registration_t * reg,
+					   int nbytes);
 void vl_msg_api_free (void *a);
 int vl_map_shmem (const char *region_name, int is_vlib);
 void vl_unmap_shmem (void);
diff --git a/src/vlibmemory/socket_api.c b/src/vlibmemory/socket_api.c
index 9c099b9..8527f1b 100644
--- a/src/vlibmemory/socket_api.c
+++ b/src/vlibmemory/socket_api.c
@@ -52,7 +52,6 @@
 {
   vl_api_registration_t *reg;
   socket_main_t *sm = &socket_main;
-  clib_file_main_t *fm = &file_main;
   clib_file_t *f;
 
   /*
@@ -68,9 +67,8 @@
     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, "%20s %8d",
-                             reg->name, f->file_descriptor);
+            f = vl_api_registration_file (reg);
+            vlib_cli_output (vm, "%20s %8d", reg->name, f->file_descriptor);
         }
     }));
 /* *INDENT-ON* */
@@ -86,9 +84,10 @@
   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;
+  clib_file_t *cf;
 
+  cf = vl_api_registration_file (rp);
   ASSERT (rp->registration_type > REGISTRATION_TYPE_SHMEM);
 
   if (msg_id >= vec_len (am->api_trace_cfg))
@@ -380,7 +379,6 @@
   clib_error_t *error;
 
   error = clib_socket_accept (sock, &client);
-
   if (error)
     return error;
 
@@ -441,8 +439,7 @@
 
       vl_api_send_msg (regp, (u8 *) rp);
 
-      clib_file_del (&file_main, file_main.file_pool + regp->clib_file_index);
-
+      vl_api_registration_del_file (regp);
       vl_socket_free_registration_index (mp->index);
     }
   else
@@ -451,8 +448,8 @@
     }
 }
 
-static clib_error_t *
-send_fd_msg (int socket_fd, int fd_to_share)
+clib_error_t *
+vl_sock_api_send_fd_msg (int socket_fd, int fd_to_share)
 {
   struct msghdr mh = { 0 };
   struct iovec iov[1];
@@ -535,6 +532,7 @@
   svm_region_t *vlib_rp;
   clib_file_t *cf;
   vl_api_shm_elem_config_t *config = 0;
+  vl_shmem_hdr_t *shmem_hdr;
   int rv;
 
   regp = vl_api_client_index_to_registration (mp->client_index);
@@ -559,7 +557,7 @@
   memfd->i_am_master = 1;
   memfd->name = format (0, "%s%c", regp->name, 0);
 
-  if ((rv = ssvm_master_init_memfd (memfd, mp->client_index)))
+  if ((rv = ssvm_master_init_memfd (memfd)))
     goto reply;
 
   /* Remember to close this fd when the socket connection goes away */
@@ -584,6 +582,11 @@
   vlib_rp = (svm_region_t *) a->baseva;
   vl_init_shmem (vlib_rp, config, 1 /* is_vlib (dont-care) */ ,
 		 1 /* is_private */ );
+
+  /* Remember who created this. Needs to be post vl_init_shmem */
+  shmem_hdr = (vl_shmem_hdr_t *) vlib_rp->user_ctx;
+  shmem_hdr->clib_file_index = vl_api_registration_file_index (regp);
+
   vec_add1 (am->vlib_private_rps, vlib_rp);
   memfd->sh->ready = 1;
   vec_free (config);
@@ -607,11 +610,11 @@
    * 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 = vl_api_registration_file (regp);
   cf->write_function (cf);
 
   /* Send the magic "here's your sign (aka fd)" socket message */
-  send_fd_msg (cf->file_descriptor, memfd->fd);
+  vl_sock_api_send_fd_msg (cf->file_descriptor, memfd->fd);
 }
 
 /*
@@ -640,7 +643,7 @@
   memfd->name = format (0, "%s%c", regp->name, 0);
 
   /* Set up a memfd segment of the requested size */
-  if ((rv = ssvm_master_init_memfd (memfd, mp->client_index)))
+  if ((rv = ssvm_master_init_memfd (memfd)))
     goto reply;
 
   /* Remember to close this fd when the socket connection goes away */
@@ -662,11 +665,11 @@
    * We need the reply message to make it out the back door
    * before we send the magic fd message.
    */
-  cf = file_main.file_pool + regp->clib_file_index;
+  cf = vl_api_registration_file (regp);
   cf->write_function (cf);
 
   /* send the magic "here's your sign (aka fd)" socket message */
-  send_fd_msg (cf->file_descriptor, memfd->fd);
+  vl_sock_api_send_fd_msg (cf->file_descriptor, memfd->fd);
 }
 
 #define foreach_vlib_api_msg                    	\
@@ -741,7 +744,6 @@
 static clib_error_t *
 socket_exit (vlib_main_t * vm)
 {
-  clib_file_main_t *fm = &file_main;
   socket_main_t *sm = &socket_main;
   vl_api_registration_t *rp;
 
@@ -751,9 +753,9 @@
       u32 index;
         /* *INDENT-OFF* */
         pool_foreach (rp, sm->registration_pool, ({
-            clib_file_del (fm, fm->file_pool + rp->clib_file_index);
-            index = rp->vl_api_registration_pool_index;
-            vl_socket_free_registration_index (index);
+          vl_api_registration_del_file (rp);
+          index = rp->vl_api_registration_pool_index;
+          vl_socket_free_registration_index (index);
         }));
 /* *INDENT-ON* */
     }
diff --git a/src/vlibmemory/socket_api.h b/src/vlibmemory/socket_api.h
index 5cb3c05..d12b427 100644
--- a/src/vlibmemory/socket_api.h
+++ b/src/vlibmemory/socket_api.h
@@ -77,6 +77,9 @@
 				i8 * input_v);
 void vl_sock_api_dump_clients (vlib_main_t * vm, api_main_t * am);
 clib_error_t *vl_sock_api_init (vlib_main_t * vm);
+clib_error_t *vl_sock_api_send_fd_msg (int socket_fd, int fd_to_share);
+clib_error_t *vl_sock_api_recv_fd_msg (int socket_fd, int *fd_to_share,
+				       u32 wait);
 
 #endif /* SRC_VLIBMEMORY_SOCKET_API_H_ */
 
diff --git a/src/vlibmemory/socket_client.c b/src/vlibmemory/socket_client.c
index 44d2122..a49d335 100644
--- a/src/vlibmemory/socket_client.c
+++ b/src/vlibmemory/socket_client.c
@@ -158,6 +158,12 @@
 vl_socket_client_disconnect (void)
 {
   socket_client_main_t *scm = &socket_client_main;
+
+  if (vl_mem_client_is_connected ())
+    {
+      vl_client_disconnect_from_vlib_no_unmap ();
+      ssvm_delete_memfd (&scm->memfd_segment);
+    }
   if (scm->socket_fd && (close (scm->socket_fd) < 0))
     clib_unix_warning ("close");
   scm->socket_fd = 0;
@@ -170,19 +176,21 @@
   scm->socket_enable = enable;
 }
 
-static clib_error_t *
-receive_fd_msg (int socket_fd, int *my_fd)
+clib_error_t *
+vl_sock_api_recv_fd_msg (int socket_fd, int *my_fd, u32 wait)
 {
+  socket_client_main_t *scm = &socket_client_main;
   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;
+  ssize_t size = 0;
   struct ucred *cr = 0;
   struct cmsghdr *cmsg;
   pid_t pid __attribute__ ((unused));
   uid_t uid __attribute__ ((unused));
   gid_t gid __attribute__ ((unused));
+  f64 timeout;
 
   iov[0].iov_base = msgbuf;
   iov[0].iov_len = 5;
@@ -193,8 +201,15 @@
 
   memset (ctl, 0, sizeof (ctl));
 
-  /* receive the incoming message */
-  size = recvmsg (socket_fd, &mh, 0);
+  if (wait != ~0)
+    {
+      timeout = clib_time_now (&scm->clib_time) + wait;
+      while (size != 5 && clib_time_now (&scm->clib_time) < timeout)
+	size = recvmsg (socket_fd, &mh, MSG_DONTWAIT);
+    }
+  else
+    size = recvmsg (socket_fd, &mh, 0);
+
   if (size != 5)
     {
       return (size == 0) ? clib_error_return (0, "disconnected") :
@@ -228,11 +243,11 @@
   (vl_api_sock_init_shm_reply_t * mp)
 {
   socket_client_main_t *scm = &socket_client_main;
-  int my_fd = -1;
-  clib_error_t *error;
+  ssvm_private_t *memfd = &scm->memfd_segment;
   i32 retval = ntohl (mp->retval);
-  ssvm_private_t memfd;
   api_main_t *am = &api_main;
+  clib_error_t *error;
+  int my_fd = -1;
   u8 *new_name;
 
   if (retval)
@@ -244,25 +259,26 @@
   /*
    * Check the socket for the magic fd
    */
-  error = receive_fd_msg (scm->socket_fd, &my_fd);
+  error = vl_sock_api_recv_fd_msg (scm->socket_fd, &my_fd, 5);
   if (error)
     {
+      clib_error_report (error);
       retval = -99;
       return;
     }
 
-  memset (&memfd, 0, sizeof (memfd));
-  memfd.fd = my_fd;
+  memset (memfd, 0, sizeof (*memfd));
+  memfd->fd = my_fd;
 
   /* Note: this closes memfd.fd */
-  retval = ssvm_slave_init_memfd (&memfd);
+  retval = ssvm_slave_init_memfd (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->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);
@@ -392,6 +408,15 @@
   return 0;
 }
 
+clib_error_t *
+vl_socket_client_recv_fd_msg (int *fd_to_recv, u32 wait)
+{
+  socket_client_main_t *scm = &socket_client_main;
+  if (!scm->socket_fd)
+    return clib_error_return (0, "no socket");
+  return vl_sock_api_recv_fd_msg (scm->client_socket.fd, fd_to_recv, wait);
+}
+
 /*
  * fd.io coding-style-patch-verification: ON
  *
diff --git a/src/vlibmemory/socket_client.h b/src/vlibmemory/socket_client.h
index 10191db..74be5a9 100644
--- a/src/vlibmemory/socket_client.h
+++ b/src/vlibmemory/socket_client.h
@@ -38,6 +38,7 @@
 
   u8 *name;
   clib_time_t clib_time;
+  ssvm_private_t memfd_segment;
 } socket_client_main_t;
 
 extern socket_client_main_t socket_client_main;
@@ -52,6 +53,7 @@
 void vl_socket_client_enable_disable (int enable);
 void *vl_socket_client_msg_alloc (int nbytes);
 int vl_socket_client_init_shm (vl_api_shm_elem_config_t * config);
+clib_error_t *vl_socket_client_recv_fd_msg (int *fd_to_recv, u32 wait);
 
 #endif /* SRC_VLIBMEMORY_SOCKET_CLIENT_H_ */