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_ */