+ 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 (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;
+}
+
+void
+vl_socket_client_enable_disable (int enable)
+{
+ socket_client_main_t *scm = &socket_client_main;
+ scm->socket_enable = enable;
+}
+
+clib_error_t *
+vl_sock_api_recv_fd_msg (int socket_fd, int fds[], int n_fds, u32 wait)
+{
+ socket_client_main_t *scm = &socket_client_main;
+ char msgbuf[16];
+ char ctl[CMSG_SPACE (sizeof (int) * n_fds)
+ + CMSG_SPACE (sizeof (struct ucred))];
+ struct msghdr mh = { 0 };
+ struct iovec iov[1];
+ 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;
+ mh.msg_iov = iov;
+ mh.msg_iovlen = 1;
+ mh.msg_control = ctl;
+ mh.msg_controllen = sizeof (ctl);
+
+ memset (ctl, 0, sizeof (ctl));
+
+ 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") :
+ 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 (fds, CMSG_DATA (cmsg), sizeof (int) * n_fds);
+ }
+ }
+ 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;
+ ssvm_private_t *memfd = &scm->memfd_segment;
+ i32 retval = ntohl (mp->retval);
+ api_main_t *am = &api_main;
+ clib_error_t *error;
+ int my_fd = -1;
+ u8 *new_name;
+
+ if (retval)
+ {
+ clib_warning ("failed to init shmem");
+ return;
+ }
+
+ /*
+ * Check the socket for the magic fd
+ */
+ error = vl_sock_api_recv_fd_msg (scm->socket_fd, &my_fd, 1, 5);
+ if (error)
+ {
+ clib_error_report (error);
+ retval = -99;
+ return;
+ }
+
+ memset (memfd, 0, sizeof (*memfd));
+ memfd->fd = my_fd;
+
+ /* Note: this closes memfd.fd */
+ 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->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;
+ scm->client_index = clib_net_to_host_u32 (mp->index);