aboutsummaryrefslogtreecommitdiffstats
path: root/src/vlibmemory
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2017-12-19 04:50:01 -0800
committerDave Barach <openvpp@barachs.net>2018-01-05 19:00:45 +0000
commit90a63988fa01685626b6d6a01b79ea5370f7fbac (patch)
tree69951111b8f8c43c5dbfc61cc5b133f74a58ddda /src/vlibmemory
parente6bfeab1c352ae73a19361c038e2a06a58c035db (diff)
sock api: add infra for bootstrapping shm clients
- 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>
Diffstat (limited to 'src/vlibmemory')
-rw-r--r--src/vlibmemory/api_common.h38
-rw-r--r--src/vlibmemory/memclnt.api17
-rw-r--r--src/vlibmemory/memory_shared.c82
-rw-r--r--src/vlibmemory/memory_vlib.c4
-rw-r--r--src/vlibmemory/socket_client.c324
-rw-r--r--src/vlibmemory/socksvr_vlib.c200
6 files changed, 514 insertions, 151 deletions
diff --git a/src/vlibmemory/api_common.h b/src/vlibmemory/api_common.h
index 2080a4bb18e..bd0da10d569 100644
--- a/src/vlibmemory/api_common.h
+++ b/src/vlibmemory/api_common.h
@@ -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 */
diff --git a/src/vlibmemory/memclnt.api b/src/vlibmemory/memclnt.api
index 6d6a1fe06dc..20a73f2b3c2 100644
--- a/src/vlibmemory/memclnt.api
+++ b/src/vlibmemory/memclnt.api
@@ -184,6 +184,23 @@ define memfd_segment_create_reply
};
/*
+ * 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
*/
diff --git a/src/vlibmemory/memory_shared.c b/src/vlibmemory/memory_shared.c
index 7af2433b44e..0a3c23cbb3e 100644
--- a/src/vlibmemory/memory_shared.c
+++ b/src/vlibmemory/memory_shared.c
@@ -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;
diff --git a/src/vlibmemory/memory_vlib.c b/src/vlibmemory/memory_vlib.c
index 1c099ed0a3e..805438152ce 100644
--- a/src/vlibmemory/memory_vlib.c
+++ b/src/vlibmemory/memory_vlib.c
@@ -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);
}
diff --git a/src/vlibmemory/socket_client.c b/src/vlibmemory/socket_client.c
index b60fd4f6229..d7a9ad5fe86 100644
--- a/src/vlibmemory/socket_client.c
+++ b/src/vlibmemory/socket_client.c
@@ -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;
}
/*
diff --git a/src/vlibmemory/socksvr_vlib.c b/src/vlibmemory/socksvr_vlib.c
index 1a263e7bf37..314e2eb60d3 100644
--- a/src/vlibmemory/socksvr_vlib.c
+++ b/src/vlibmemory/socksvr_vlib.c
@@ -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 _