diff options
author | Florin Coras <fcoras@cisco.com> | 2017-12-19 04:50:01 -0800 |
---|---|---|
committer | Dave Barach <openvpp@barachs.net> | 2018-01-05 19:00:45 +0000 |
commit | 90a63988fa01685626b6d6a01b79ea5370f7fbac (patch) | |
tree | 69951111b8f8c43c5dbfc61cc5b133f74a58ddda /src/vlibmemory | |
parent | e6bfeab1c352ae73a19361c038e2a06a58c035db (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.h | 38 | ||||
-rw-r--r-- | src/vlibmemory/memclnt.api | 17 | ||||
-rw-r--r-- | src/vlibmemory/memory_shared.c | 82 | ||||
-rw-r--r-- | src/vlibmemory/memory_vlib.c | 4 | ||||
-rw-r--r-- | src/vlibmemory/socket_client.c | 324 | ||||
-rw-r--r-- | src/vlibmemory/socksvr_vlib.c | 200 |
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 _ |