summaryrefslogtreecommitdiffstats
path: root/src/vcl
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2018-11-26 17:01:36 -0800
committerDamjan Marion <dmarion@me.com>2018-11-29 11:27:18 +0000
commit47c40e2d944c9a29677d0542103207ba8372b66a (patch)
treee43cf5361213d119df53fb16c15cf0dca550f2d4 /src/vcl
parent743ee3e12531ec3c6ba2e2add694dde3361b0e03 (diff)
vcl: basic support for apps that fork
- intercept fork and register a new worker with vpp - share sessions between parent and forked child - keep binary api state per worker Change-Id: Ib177517d661724fa042bd2d98d18e777056352a2 Signed-off-by: Florin Coras <fcoras@cisco.com>
Diffstat (limited to 'src/vcl')
-rw-r--r--src/vcl/ldp.c6
-rw-r--r--src/vcl/vcl_bapi.c46
-rw-r--r--src/vcl/vcl_cfg.c1
-rw-r--r--src/vcl/vcl_debug.h11
-rw-r--r--src/vcl/vcl_private.c164
-rw-r--r--src/vcl/vcl_private.h38
-rw-r--r--src/vcl/vppcom.c255
-rw-r--r--src/vcl/vppcom.h1
8 files changed, 356 insertions, 166 deletions
diff --git a/src/vcl/ldp.c b/src/vcl/ldp.c
index 5c70643ed24..915d1caa40c 100644
--- a/src/vcl/ldp.c
+++ b/src/vcl/ldp.c
@@ -346,7 +346,7 @@ ldp_init (void)
int
close (int fd)
{
- int rv;
+ int rv, refcnt;
const char *func_str;
u32 sid = ldp_sid_from_fd (fd);
@@ -388,13 +388,15 @@ close (int fd)
LDBG (0, "LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x)",
getpid (), fd, fd, func_str, sid, sid);
+ refcnt = vppcom_session_attr (sid, VPPCOM_ATTR_GET_REFCNT, 0, 0);
rv = vppcom_session_close (sid);
if (rv != VPPCOM_OK)
{
errno = -rv;
rv = -1;
}
- ldp_fd_free_w_sid (sid);
+ if (refcnt == 1)
+ ldp_fd_free_w_sid (sid);
}
else
{
diff --git a/src/vcl/vcl_bapi.c b/src/vcl/vcl_bapi.c
index cc494ed3b6d..93ba0ab6c4d 100644
--- a/src/vcl/vcl_bapi.c
+++ b/src/vcl/vcl_bapi.c
@@ -354,20 +354,22 @@ vppcom_api_hookup (void)
void
vppcom_send_session_enable_disable (u8 is_enable)
{
+ vcl_worker_t *wrk = vcl_worker_get_current ();
vl_api_session_enable_disable_t *bmp;
bmp = vl_msg_api_alloc (sizeof (*bmp));
memset (bmp, 0, sizeof (*bmp));
bmp->_vl_msg_id = ntohs (VL_API_SESSION_ENABLE_DISABLE);
- bmp->client_index = vcm->my_client_index;
+ bmp->client_index = wrk->my_client_index;
bmp->context = htonl (0xfeedface);
bmp->is_enable = is_enable;
- vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & bmp);
+ vl_msg_api_send_shmem (wrk->vl_input_queue, (u8 *) & bmp);
}
void
vppcom_app_send_attach (void)
{
+ vcl_worker_t *wrk = vcl_worker_get_current ();
vl_api_application_attach_t *bmp;
u8 nsid_len = vec_len (vcm->cfg.namespace_id);
u8 app_is_proxy = (vcm->cfg.app_proxy_transport_tcp ||
@@ -377,7 +379,7 @@ vppcom_app_send_attach (void)
memset (bmp, 0, sizeof (*bmp));
bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_ATTACH);
- bmp->client_index = vcm->my_client_index;
+ bmp->client_index = wrk->my_client_index;
bmp->context = htonl (0xfeedface);
bmp->options[APP_OPTIONS_FLAGS] =
APP_OPTIONS_FLAGS_ACCEPT_REDIRECT | APP_OPTIONS_FLAGS_ADD_SEGMENT |
@@ -402,20 +404,21 @@ vppcom_app_send_attach (void)
clib_memcpy_fast (bmp->namespace_id, vcm->cfg.namespace_id, nsid_len);
bmp->options[APP_OPTIONS_NAMESPACE_SECRET] = vcm->cfg.namespace_secret;
}
- vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & bmp);
+ vl_msg_api_send_shmem (wrk->vl_input_queue, (u8 *) & bmp);
}
void
vppcom_app_send_detach (void)
{
+ vcl_worker_t *wrk = vcl_worker_get_current ();
vl_api_application_detach_t *bmp;
bmp = vl_msg_api_alloc (sizeof (*bmp));
memset (bmp, 0, sizeof (*bmp));
bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_DETACH);
- bmp->client_index = vcm->my_client_index;
+ bmp->client_index = wrk->my_client_index;
bmp->context = htonl (0xfeedface);
- vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & bmp);
+ vl_msg_api_send_shmem (wrk->vl_input_queue, (u8 *) & bmp);
}
void
@@ -429,14 +432,14 @@ vcl_send_app_worker_add_del (u8 is_add)
memset (mp, 0, sizeof (*mp));
mp->_vl_msg_id = ntohs (VL_API_APP_WORKER_ADD_DEL);
- mp->client_index = vcm->my_client_index;
+ mp->client_index = wrk->my_client_index;
mp->app_index = clib_host_to_net_u32 (vcm->app_index);
mp->context = wrk_index;
mp->is_add = is_add;
if (!is_add)
mp->wrk_index = clib_host_to_net_u32 (wrk_index);
- vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & mp);
+ vl_msg_api_send_shmem (wrk->vl_input_queue, (u8 *) & mp);
}
void
@@ -448,7 +451,7 @@ vppcom_send_connect_sock (vcl_session_t * session)
cmp = vl_msg_api_alloc (sizeof (*cmp));
memset (cmp, 0, sizeof (*cmp));
cmp->_vl_msg_id = ntohs (VL_API_CONNECT_SOCK);
- cmp->client_index = vcm->my_client_index;
+ cmp->client_index = wrk->my_client_index;
cmp->context = session->session_index;
cmp->wrk_index = wrk->vpp_wrk_index;
cmp->is_ip4 = session->transport.is_ip4;
@@ -456,20 +459,21 @@ vppcom_send_connect_sock (vcl_session_t * session)
cmp->port = session->transport.rmt_port;
cmp->proto = session->session_type;
clib_memcpy_fast (cmp->options, session->options, sizeof (cmp->options));
- vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & cmp);
+ vl_msg_api_send_shmem (wrk->vl_input_queue, (u8 *) & cmp);
}
void
vppcom_send_disconnect_session (u64 vpp_handle)
{
+ vcl_worker_t *wrk = vcl_worker_get_current ();
vl_api_disconnect_session_t *dmp;
dmp = vl_msg_api_alloc (sizeof (*dmp));
memset (dmp, 0, sizeof (*dmp));
dmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION);
- dmp->client_index = vcm->my_client_index;
+ dmp->client_index = wrk->my_client_index;
dmp->handle = vpp_handle;
- vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & dmp);
+ vl_msg_api_send_shmem (wrk->vl_input_queue, (u8 *) & dmp);
}
/* VPP combines bind and listen as one operation. VCL manages the separation
@@ -486,7 +490,7 @@ vppcom_send_bind_sock (vcl_session_t * session)
memset (bmp, 0, sizeof (*bmp));
bmp->_vl_msg_id = ntohs (VL_API_BIND_SOCK);
- bmp->client_index = vcm->my_client_index;
+ bmp->client_index = wrk->my_client_index;
bmp->context = session->session_index;
bmp->wrk_index = wrk->vpp_wrk_index;
bmp->is_ip4 = session->transport.is_ip4;
@@ -494,7 +498,7 @@ vppcom_send_bind_sock (vcl_session_t * session)
bmp->port = session->transport.lcl_port;
bmp->proto = session->session_type;
clib_memcpy_fast (bmp->options, session->options, sizeof (bmp->options));
- vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & bmp);
+ vl_msg_api_send_shmem (wrk->vl_input_queue, (u8 *) & bmp);
}
void
@@ -507,15 +511,16 @@ vppcom_send_unbind_sock (u64 vpp_handle)
memset (ump, 0, sizeof (*ump));
ump->_vl_msg_id = ntohs (VL_API_UNBIND_SOCK);
- ump->client_index = vcm->my_client_index;
+ ump->client_index = wrk->my_client_index;
ump->wrk_index = wrk->vpp_wrk_index;
ump->handle = vpp_handle;
- vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & ump);
+ vl_msg_api_send_shmem (wrk->vl_input_queue, (u8 *) & ump);
}
void
vppcom_send_accept_session_reply (u64 handle, u32 context, int retval)
{
+ vcl_worker_t *wrk = vcl_worker_get_current ();
vl_api_accept_session_reply_t *rmp;
rmp = vl_msg_api_alloc (sizeof (*rmp));
@@ -524,7 +529,7 @@ vppcom_send_accept_session_reply (u64 handle, u32 context, int retval)
rmp->retval = htonl (retval);
rmp->context = context;
rmp->handle = handle;
- vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & rmp);
+ vl_msg_api_send_shmem (wrk->vl_input_queue, (u8 *) & rmp);
}
u32
@@ -549,6 +554,7 @@ vppcom_init_error_string_table (void)
int
vppcom_connect_to_vpp (char *app_name)
{
+ vcl_worker_t *wrk = vcl_worker_get_current ();
api_main_t *am = &api_main;
vppcom_cfg_t *vcl_cfg = &vcm->cfg;
@@ -584,9 +590,9 @@ vppcom_connect_to_vpp (char *app_name)
}
- vcm->vl_input_queue = am->shmem_hdr->vl_input_queue;
- vcm->my_client_index = (u32) am->my_client_index;
- vcm->app_state = STATE_APP_CONN_VPP;
+ wrk->vl_input_queue = am->shmem_hdr->vl_input_queue;
+ wrk->my_client_index = (u32) am->my_client_index;
+ wrk->wrk_state = STATE_APP_CONN_VPP;
VDBG (0, "app (%s) is connected to VPP!", app_name);
vcl_evt (VCL_EVT_INIT, vcm);
diff --git a/src/vcl/vcl_cfg.c b/src/vcl/vcl_cfg.c
index 402bb91315f..8baae82942d 100644
--- a/src/vcl/vcl_cfg.c
+++ b/src/vcl/vcl_cfg.c
@@ -23,7 +23,6 @@ static vppcom_main_t _vppcom_main = {
.debug = VPPCOM_DEBUG_INIT,
.is_init = 0,
.app_index = ~0,
- .my_client_index = ~0
};
vppcom_main_t *vcm = &_vppcom_main;
diff --git a/src/vcl/vcl_debug.h b/src/vcl/vcl_debug.h
index 48ff21af1de..191d4004eba 100644
--- a/src/vcl/vcl_debug.h
+++ b/src/vcl/vcl_debug.h
@@ -23,15 +23,18 @@
#define VDBG(_lvl, _fmt, _args...) \
if (VCL_DBG_ON && vcm->debug > _lvl) \
- clib_warning ("vcl<%d:%d>: " _fmt, vcm->current_pid, \
+ clib_warning ("vcl<%d:%d>: " _fmt, \
+ vcm->workers[__vcl_worker_index].current_pid, \
__vcl_worker_index, ##_args)
#define VWRN(_fmt, _args...) \
-clib_warning ("vcl<%d:%d>: " _fmt, vcm->current_pid, \
- __vcl_worker_index, ##_args)
+ clib_warning ("vcl<%d:%d>: " _fmt, \
+ vcm->workers[__vcl_worker_index].current_pid, \
+ __vcl_worker_index, ##_args)
#define VERR(_fmt, _args...) \
- clib_warning ("vcl<%d:%d>: ERROR " _fmt, vcm->current_pid, \
+ clib_warning ("vcl<%d:%d>: ERROR " _fmt, \
+ vcm->workers[__vcl_worker_index].current_pid, \
__vcl_worker_index, ##_args)
#define foreach_vcl_dbg_evt \
diff --git a/src/vcl/vcl_private.c b/src/vcl/vcl_private.c
index d159a49a89c..86dccfe1cc9 100644
--- a/src/vcl/vcl_private.c
+++ b/src/vcl/vcl_private.c
@@ -220,12 +220,12 @@ vcl_worker_free (vcl_worker_t * wrk)
pool_put (vcm->workers, wrk);
}
-static void
-vcl_worker_cleanup (void *arg)
+void
+vcl_worker_cleanup (void)
{
vcl_worker_t *wrk = vcl_worker_get_current ();
- VDBG (0, "cleaning up worker %u", wrk->wrk_index);
+ clib_spinlock_lock (&vcm->workers_lock);
vcl_send_app_worker_add_del (0 /* is_add */ );
close (wrk->mqs_epfd);
hash_free (wrk->session_index_by_vpp_handles);
@@ -235,6 +235,14 @@ vcl_worker_cleanup (void *arg)
vec_free (wrk->mq_msg_vector);
vcl_set_worker_index (~0);
vcl_worker_free (wrk);
+ clib_spinlock_unlock (&vcm->workers_lock);
+ VDBG (0, "cleaned up worker %u", wrk->wrk_index);
+}
+
+static void
+vcl_worker_cleanup_cb (void *arg)
+{
+ vcl_worker_cleanup ();
}
vcl_worker_t *
@@ -255,6 +263,8 @@ vcl_worker_alloc_and_init ()
clib_spinlock_lock (&vcm->workers_lock);
wrk = vcl_worker_alloc ();
vcl_set_worker_index (wrk->wrk_index);
+ wrk->thread_id = pthread_self ();
+ wrk->current_pid = getpid ();
wrk->mqs_epfd = -1;
if (vcm->cfg.use_mq_eventfd)
@@ -263,7 +273,7 @@ vcl_worker_alloc_and_init ()
if (wrk->mqs_epfd < 0)
{
clib_unix_warning ("epoll_create() returned");
- return 0;
+ goto done;
}
}
@@ -276,32 +286,160 @@ vcl_worker_alloc_and_init ()
vec_reset_length (wrk->mq_msg_vector);
vec_validate (wrk->unhandled_evts_vector, 128);
vec_reset_length (wrk->unhandled_evts_vector);
+ clib_spinlock_unlock (&vcm->workers_lock);
- if (wrk->wrk_index == 0)
- {
- clib_spinlock_unlock (&vcm->workers_lock);
- return wrk;
- }
+done:
+ return wrk;
+}
+
+int
+vcl_worker_register_with_vpp (void)
+{
+ vcl_worker_t *wrk = vcl_worker_get_current ();
+
+ clib_spinlock_lock (&vcm->workers_lock);
vcm->app_state = STATE_APP_ADDING_WORKER;
vcl_send_app_worker_add_del (1 /* is_add */ );
if (vcl_wait_for_app_state_change (STATE_APP_READY))
{
clib_warning ("failed to add worker to vpp");
- return 0;
+ return -1;
}
- if (pthread_key_create (&vcl_worker_stop_key, vcl_worker_cleanup))
+ if (pthread_key_create (&vcl_worker_stop_key, vcl_worker_cleanup_cb))
clib_warning ("failed to add pthread cleanup function");
if (pthread_setspecific (vcl_worker_stop_key, &wrk->thread_id))
clib_warning ("failed to setup key value");
- wrk->thread_id = pthread_self ();
clib_spinlock_unlock (&vcm->workers_lock);
VDBG (0, "added worker %u", wrk->wrk_index);
+ return 0;
+}
- return wrk;
+int
+vcl_worker_set_bapi (void)
+{
+ vcl_worker_t *wrk = vcl_worker_get_current ();
+ int i;
+
+ /* Find the first worker with the same pid */
+ for (i = 0; i < vec_len (vcm->workers); i++)
+ {
+ if (i == wrk->wrk_index)
+ continue;
+ if (vcm->workers[i].current_pid == wrk->current_pid)
+ {
+ wrk->vl_input_queue = vcm->workers[i].vl_input_queue;
+ wrk->my_client_index = vcm->workers[i].my_client_index;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+vcl_shared_session_t *
+vcl_shared_session_alloc (void)
+{
+ vcl_shared_session_t *ss;
+ pool_get (vcm->shared_sessions, ss);
+ memset (ss, 0, sizeof (*ss));
+ ss->ss_index = ss - vcm->shared_sessions;
+ return ss;
+}
+
+vcl_shared_session_t *
+vcl_shared_session_get (u32 ss_index)
+{
+ if (pool_is_free_index (vcm->shared_sessions, ss_index))
+ return 0;
+ return pool_elt_at_index (vcm->shared_sessions, ss_index);
+}
+
+void
+vcl_shared_session_free (vcl_shared_session_t * ss)
+{
+ pool_put (vcm->shared_sessions, ss);
+}
+
+void
+vcl_worker_share_session (vcl_worker_t * parent, vcl_worker_t * wrk,
+ vcl_session_t * new_s)
+{
+ vcl_shared_session_t *ss;
+ vcl_session_t *s;
+
+ s = vcl_session_get (parent, new_s->session_index);
+ if (s->shared_index == ~0)
+ {
+ ss = vcl_shared_session_alloc ();
+ vec_add1 (ss->workers, parent->wrk_index);
+ s->shared_index = ss->ss_index;
+ }
+ else
+ {
+ ss = vcl_shared_session_get (s->shared_index);
+ }
+ new_s->shared_index = ss->ss_index;
+ vec_add1 (ss->workers, wrk->wrk_index);
+}
+
+int
+vcl_worker_unshare_session (vcl_worker_t * wrk, vcl_session_t * s)
+{
+ vcl_shared_session_t *ss;
+ int i;
+
+ ss = vcl_shared_session_get (s->shared_index);
+ for (i = 0; i < vec_len (ss->workers); i++)
+ {
+ if (ss->workers[i] == wrk->wrk_index)
+ {
+ vec_del1 (ss->workers, i);
+ break;
+ }
+ }
+
+ if (vec_len (ss->workers) == 0)
+ {
+ vcl_shared_session_free (ss);
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+vcl_worker_share_sessions (u32 parent_wrk_index)
+{
+ vcl_worker_t *parent_wrk, *wrk;
+ vcl_session_t *new_s;
+
+ parent_wrk = vcl_worker_get (parent_wrk_index);
+ if (!parent_wrk->sessions)
+ return;
+
+ wrk = vcl_worker_get_current ();
+ wrk->sessions = pool_dup (parent_wrk->sessions);
+ wrk->session_index_by_vpp_handles =
+ hash_dup (parent_wrk->session_index_by_vpp_handles);
+
+ /* *INDENT-OFF* */
+ pool_foreach (new_s, wrk->sessions, ({
+ vcl_worker_share_session (parent_wrk, wrk, new_s);
+ }));
+ /* *INDENT-ON* */
+}
+
+int
+vcl_session_get_refcnt (vcl_session_t * s)
+{
+ vcl_shared_session_t *ss;
+ ss = vcl_shared_session_get (s->shared_index);
+ if (ss)
+ return vec_len (ss->workers);
+ return 0;
}
/*
diff --git a/src/vcl/vcl_private.h b/src/vcl/vcl_private.h
index 0204bd5493e..0420322d3f4 100644
--- a/src/vcl/vcl_private.h
+++ b/src/vcl/vcl_private.h
@@ -136,6 +136,12 @@ do { \
#define VCL_SESS_ATTR_TEST(ATTR, VAL) \
((ATTR) & (1 << (VAL)) ? 1 : 0)
+typedef struct vcl_shared_session_
+{
+ u32 ss_index;
+ u32 *workers;
+} vcl_shared_session_t;
+
typedef struct
{
CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
@@ -161,6 +167,7 @@ typedef struct
svm_msg_q_t *our_evt_q;
u64 options[16];
vcl_session_msg_t *accept_evts_fifo;
+ u32 shared_index;
#if VCL_ELOG
elog_track_t elog_track;
#endif
@@ -225,6 +232,15 @@ typedef struct vcl_worker_
/** Worker index in vpp*/
u32 vpp_wrk_index;
+ /** API client handle */
+ u32 my_client_index;
+
+ /** State of the connection, shared between msg RX thread and main thread */
+ volatile app_state_t wrk_state;
+
+ /** VPP binary api input queue */
+ svm_queue_t *vl_input_queue;
+
/** Message queues epoll fd. Initialized only if using mqs with eventfds */
int mqs_epfd;
@@ -268,6 +284,9 @@ typedef struct vcl_worker_
/** Used also as a thread stop key buffer */
pthread_t thread_id;
+
+ /** Current pid, may be different from main_pid if forked child */
+ pid_t current_pid;
} vcl_worker_t;
typedef struct vppcom_main_t_
@@ -279,18 +298,9 @@ typedef struct vppcom_main_t_
/** Main process pid */
pid_t main_pid;
- /** Current pid, may be different from main_pid if forked child */
- pid_t current_pid;
-
/** App's index in vpp. It's used by vpp to identify the app */
u32 app_index;
- /** API client handle */
- u32 my_client_index;
-
- /** VPP binary api input queue */
- svm_queue_t *vl_input_queue;
-
/** State of the connection, shared between msg RX thread and main thread */
volatile app_state_t app_state;
@@ -302,12 +312,15 @@ typedef struct vppcom_main_t_
/** Flag indicating that a new segment is being mounted */
volatile u32 mounting_segment;
+ volatile u32 forking;
+
/** Workers */
vcl_worker_t *workers;
/** Lock to protect worker registrations */
clib_spinlock_t workers_lock;
+ vcl_shared_session_t *shared_sessions;
#ifdef VCL_ELOG
/* VPP Event-logger */
elog_main_t elog_main;
@@ -330,6 +343,7 @@ vcl_session_alloc (vcl_worker_t * wrk)
pool_get (wrk->sessions, s);
memset (s, 0, sizeof (*s));
s->session_index = s - wrk->sessions;
+ s->shared_index = ~0;
return s;
}
@@ -481,6 +495,12 @@ int vcl_mq_epoll_add_evfd (vcl_worker_t * wrk, svm_msg_q_t * mq);
int vcl_mq_epoll_del_evfd (vcl_worker_t * wrk, u32 mqc_index);
vcl_worker_t *vcl_worker_alloc_and_init (void);
+void vcl_worker_cleanup (void);
+int vcl_worker_register_with_vpp (void);
+int vcl_worker_set_bapi (void);
+void vcl_worker_share_sessions (u32 parent_wrk_index);
+int vcl_worker_unshare_session (vcl_worker_t * wrk, vcl_session_t * s);
+int vcl_session_get_refcnt (vcl_session_t * s);
static inline vcl_worker_t *
vcl_worker_get (u32 wrk_index)
diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c
index 589d57c3872..195e6cbc602 100644
--- a/src/vcl/vppcom.c
+++ b/src/vcl/vppcom.c
@@ -423,7 +423,7 @@ vcl_session_reset_handler (vcl_worker_t * wrk,
session->session_state = STATE_CLOSE_ON_EMPTY;
VDBG (0, "reset handle 0x%llx, sid %u ", reset_msg->handle, sid);
vcl_send_session_reset_reply (vcl_session_vpp_evt_q (wrk, session),
- vcm->my_client_index, reset_msg->handle, 0);
+ wrk->my_client_index, reset_msg->handle, 0);
return sid;
}
@@ -673,7 +673,7 @@ vppcom_session_disconnect (u32 session_handle)
if (state & STATE_CLOSE_ON_EMPTY)
{
vpp_evt_q = vcl_session_vpp_evt_q (wrk, session);
- vcl_send_session_disconnected_reply (vpp_evt_q, vcm->my_client_index,
+ vcl_send_session_disconnected_reply (vpp_evt_q, wrk->my_client_index,
vpp_handle, 0);
VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: sending disconnect "
"REPLY...", getpid (), vpp_handle, session_handle);
@@ -691,12 +691,14 @@ vppcom_session_disconnect (u32 session_handle)
static void
vcl_cleanup_bapi (void)
{
+ socket_client_main_t *scm = &socket_client_main;
api_main_t *am = &api_main;
am->my_client_index = ~0;
am->my_registration = 0;
am->vl_input_queue = 0;
am->msg_index_by_name_and_crc = 0;
+ scm->socket_fd = 0;
vl_client_api_unmap ();
}
@@ -705,14 +707,22 @@ void
vcl_app_fork_child_handler (void)
{
u8 *child_name;
- int rv;
-
- vcm->current_pid = getpid ();
- vcl_set_worker_index (0);
+ int rv, parent_wrk;
VDBG (0, "initializing forked child");
- child_name = format (0, "%v-child-%u%c", vcm->app_name, getpid (), 0);
+ /*
+ * Allocate worker
+ */
+ parent_wrk = vcl_get_worker_index ();
+ vcl_set_worker_index (~0);
+ if (!vcl_worker_alloc_and_init ())
+ VERR ("couldn't allocate new worker");
+
+ /*
+ * Attach to binary api
+ */
+ child_name = format (0, "%v-child-%u%c", vcm->app_name, getpid (), 0);
vcl_cleanup_bapi ();
vppcom_api_hookup ();
vcm->app_state = STATE_APP_START;
@@ -724,14 +734,23 @@ vcl_app_fork_child_handler (void)
return;
}
- vcm->app_state = STATE_APP_ADDING_WORKER;
- vcl_send_app_worker_add_del (1 /* is_add */ );
- if (vcl_wait_for_app_state_change (STATE_APP_READY))
- {
- VERR ("failed to add worker to vpp");
- return;
- }
+ /*
+ * Register worker with vpp and share sessions
+ */
+ vcl_worker_register_with_vpp ();
+ vcl_worker_share_sessions (parent_wrk);
+
VDBG (0, "forked child main worker initialized");
+ vcm->forking = 0;
+}
+
+void
+vcl_app_fork_parent_handler (void)
+{
+ vcm->forking = 1;
+
+ while (vcm->forking)
+ ;
}
/*
@@ -743,55 +762,58 @@ vppcom_app_create (char *app_name)
vppcom_cfg_t *vcl_cfg = &vcm->cfg;
int rv;
- if (!vcm->is_init)
+ if (vcm->is_init)
{
- vcm->is_init = 1;
- vppcom_cfg (&vcm->cfg);
- vcl_cfg = &vcm->cfg;
-
- vcm->main_cpu = pthread_self ();
- vcm->main_pid = vcm->current_pid = getpid ();
- vcm->app_name = format (0, "%s", app_name);
- vppcom_init_error_string_table ();
- svm_fifo_segment_main_init (vcl_cfg->segment_baseva,
- 20 /* timeout in secs */ );
- pool_init_fixed (vcm->workers, vcl_cfg->max_workers);
- clib_spinlock_init (&vcm->workers_lock);
- vcl_worker_alloc_and_init ();
- pthread_atfork (NULL, NULL, vcl_app_fork_child_handler);
+ clib_warning ("already initialized");
+ return -1;
}
- if (vcm->my_client_index == ~0)
- {
- /* API hookup and connect to VPP */
- vppcom_api_hookup ();
- vcl_elog_init (vcm);
- vcm->app_state = STATE_APP_START;
- rv = vppcom_connect_to_vpp (app_name);
- if (rv)
- {
- VERR ("couldn't connect to VPP!");
- return rv;
- }
- VDBG (0, "sending session enable");
- rv = vppcom_app_session_enable ();
- if (rv)
- {
- VERR ("vppcom_app_session_enable() failed!");
- return rv;
- }
+ vcm->is_init = 1;
+ vppcom_cfg (&vcm->cfg);
+ vcl_cfg = &vcm->cfg;
- VDBG (0, "sending app attach");
- rv = vppcom_app_attach ();
- if (rv)
- {
- VERR ("vppcom_app_attach() failed!");
- return rv;
- }
+ vcm->main_cpu = pthread_self ();
+ vcm->main_pid = getpid ();
+ vcm->app_name = format (0, "%s", app_name);
+ vppcom_init_error_string_table ();
+ svm_fifo_segment_main_init (vcl_cfg->segment_baseva,
+ 20 /* timeout in secs */ );
+ pool_alloc (vcm->workers, vcl_cfg->max_workers);
+ clib_spinlock_init (&vcm->workers_lock);
+ pthread_atfork (NULL, vcl_app_fork_parent_handler,
+ vcl_app_fork_child_handler);
- VDBG (0, "app_name '%s', my_client_index %d (0x%x)",
- app_name, vcm->my_client_index, vcm->my_client_index);
+ /* Allocate default worker */
+ vcl_worker_alloc_and_init ();
+
+ /* API hookup and connect to VPP */
+ vppcom_api_hookup ();
+ vcl_elog_init (vcm);
+ vcm->app_state = STATE_APP_START;
+ rv = vppcom_connect_to_vpp (app_name);
+ if (rv)
+ {
+ VERR ("couldn't connect to VPP!");
+ return rv;
}
+ VDBG (0, "sending session enable");
+ rv = vppcom_app_session_enable ();
+ if (rv)
+ {
+ VERR ("vppcom_app_session_enable() failed!");
+ return rv;
+ }
+
+ VDBG (0, "sending app attach");
+ rv = vppcom_app_attach ();
+ if (rv)
+ {
+ VERR ("vppcom_app_attach() failed!");
+ return rv;
+ }
+
+ VDBG (0, "app_name '%s', my_client_index %d (0x%x)", app_name,
+ vcm->workers[0].my_client_index, vcm->workers[0].my_client_index);
return VPPCOM_OK;
}
@@ -802,27 +824,27 @@ vppcom_app_destroy (void)
int rv;
f64 orig_app_timeout;
- if (vcm->my_client_index == ~0)
- return;
-
- VDBG (0, "detaching from VPP, my_client_index %d (0x%x)",
- vcm->my_client_index, vcm->my_client_index);
vcl_evt (VCL_EVT_DETACH, vcm);
- vppcom_app_send_detach ();
- orig_app_timeout = vcm->cfg.app_timeout;
- vcm->cfg.app_timeout = 2.0;
- rv = vcl_wait_for_app_state_change (STATE_APP_ENABLED);
- vcm->cfg.app_timeout = orig_app_timeout;
- if (PREDICT_FALSE (rv))
- VDBG (0, "application detach timed out! returning %d (%s)",
- rv, vppcom_retval_str (rv));
+ if (vec_len (vcm->workers) == 1)
+ {
+ vppcom_app_send_detach ();
+ orig_app_timeout = vcm->cfg.app_timeout;
+ vcm->cfg.app_timeout = 2.0;
+ rv = vcl_wait_for_app_state_change (STATE_APP_ENABLED);
+ vcm->cfg.app_timeout = orig_app_timeout;
+ if (PREDICT_FALSE (rv))
+ VDBG (0, "application detach timed out! returning %d (%s)", rv,
+ vppcom_retval_str (rv));
+ }
+ else
+ {
+ vcl_worker_cleanup ();
+ }
vcl_elog_stop (vcm);
vl_client_disconnect_from_vlib ();
vec_free (vcm->app_name);
- vcm->my_client_index = ~0;
- vcm->app_state = STATE_APP_START;
}
int
@@ -853,8 +875,8 @@ int
vppcom_session_close (uint32_t session_handle)
{
vcl_worker_t *wrk = vcl_worker_get_current ();
+ u8 is_vep, do_disconnect = 1;
vcl_session_t *session = 0;
- u8 is_vep, is_vep_session;
session_state_t state;
u32 next_sh, vep_sh;
int rv = VPPCOM_OK;
@@ -864,24 +886,17 @@ vppcom_session_close (uint32_t session_handle)
if (!session)
return VPPCOM_EBADFD;
+ if (session->shared_index != ~0)
+ do_disconnect = vcl_worker_unshare_session (wrk, session);
+
is_vep = session->is_vep;
- is_vep_session = session->is_vep_session;
next_sh = session->vep.next_sh;
vep_sh = session->vep.vep_sh;
state = session->session_state;
vpp_handle = session->vpp_handle;
- if (VPPCOM_DEBUG > 0)
- {
- if (is_vep)
- clib_warning ("VCL<%d>: vep_idx %u / sid %u: "
- "closing epoll session...",
- getpid (), session_handle, session_handle);
- else
- clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %d: "
- "closing session...",
- getpid (), vpp_handle, session_handle);
- }
+ VDBG (0, "Closing session handle %u vpp handle %u", session_handle,
+ vpp_handle);
if (is_vep)
{
@@ -889,34 +904,34 @@ vppcom_session_close (uint32_t session_handle)
{
rv = vppcom_epoll_ctl (session_handle, EPOLL_CTL_DEL, next_sh, 0);
if (PREDICT_FALSE (rv < 0))
- VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL "
- "vep_idx %u failed! rv %d (%s)",
- getpid (), vpp_handle, next_sh, vep_sh,
- rv, vppcom_retval_str (rv));
+ VDBG (0, "vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL vep_idx %u"
+ " failed! rv %d (%s)", vpp_handle, next_sh, vep_sh, rv,
+ vppcom_retval_str (rv));
next_sh = session->vep.next_sh;
}
}
else
{
- if (is_vep_session)
+ if (session->is_vep_session)
{
rv = vppcom_epoll_ctl (vep_sh, EPOLL_CTL_DEL, session_handle, 0);
if (rv < 0)
- VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL "
- "vep_idx %u failed! rv %d (%s)",
- getpid (), vpp_handle, session_handle,
- vep_sh, rv, vppcom_retval_str (rv));
+ VDBG (0, "vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL vep_idx %u "
+ "failed! rv %d (%s)", vpp_handle, session_handle, vep_sh,
+ rv, vppcom_retval_str (rv));
}
+ if (!do_disconnect)
+ goto cleanup;
+
if (state & STATE_LISTEN)
{
rv = vppcom_session_unbind (session_handle);
if (PREDICT_FALSE (rv < 0))
- VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: listener unbind "
- "failed! rv %d (%s)",
- getpid (), vpp_handle, session_handle,
- rv, vppcom_retval_str (rv));
+ VDBG (0, "vpp handle 0x%llx, sid %u: listener unbind failed! "
+ "rv %d (%s)", vpp_handle, session_handle, rv,
+ vppcom_retval_str (rv));
}
else if (state & STATE_OPEN)
{
@@ -929,6 +944,8 @@ vppcom_session_close (uint32_t session_handle)
}
}
+cleanup:
+
if (vcl_session_is_ct (session))
{
vcl_cut_through_registration_t *ctr;
@@ -952,15 +969,8 @@ vppcom_session_close (uint32_t session_handle)
}
vcl_session_free (wrk, session);
- if (VPPCOM_DEBUG > 0)
- {
- if (is_vep)
- clib_warning ("VCL<%d>: vep_idx %u / sid %u: epoll session removed.",
- getpid (), session_handle, session_handle);
- else
- clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: session removed.",
- getpid (), vpp_handle, session_handle);
- }
+ VDBG (0, "session handle %u vpp handle %u removed", session_handle,
+ vpp_handle);
vcl_evt (VCL_EVT_CLOSE, session, rv);
@@ -1986,9 +1996,9 @@ vppcom_select (unsigned long n_bits, unsigned long *read_map,
clib_bitmap_foreach (sid, wrk->wr_bitmap, ({
if (!(session = vcl_session_get (wrk, sid)))
{
- VDBG (0, "VCL<%d>: session %d specified in write_map is closed.",
- getpid (), sid);
- return VPPCOM_EBADFD;
+ if (except_map && sid < minbits)
+ clib_bitmap_set_no_check (except_map, sid, 1);
+ continue;
}
rv = svm_fifo_is_full (session->tx_fifo);
@@ -2006,9 +2016,9 @@ check_rd:
clib_bitmap_foreach (sid, wrk->rd_bitmap, ({
if (!(session = vcl_session_get (wrk, sid)))
{
- VDBG (0, "VCL<%d>: session %d specified in write_map is closed.",
- getpid (), sid);
- return VPPCOM_EBADFD;
+ if (except_map && sid < minbits)
+ clib_bitmap_set_no_check (except_map, sid, 1);
+ continue;
}
rv = vppcom_session_read_ready (session);
@@ -3150,6 +3160,10 @@ vppcom_session_attr (uint32_t session_handle, uint32_t op,
rv = VPPCOM_EINVAL;
break;
+ case VPPCOM_ATTR_GET_REFCNT:
+ rv = vcl_session_get_refcnt (session);
+ break;
+
default:
rv = VPPCOM_EINVAL;
break;
@@ -3355,15 +3369,22 @@ vppcom_session_index (uint32_t session_handle)
int
vppcom_session_handle (uint32_t session_index)
{
- return vcl_get_worker_index () << 24 | session_index;
+ return (vcl_get_worker_index () << 24) | session_index;
}
int
vppcom_worker_register (void)
{
- if (vcl_worker_alloc_and_init ())
- return VPPCOM_OK;
- return VPPCOM_EEXIST;
+ if (!vcl_worker_alloc_and_init ())
+ return VPPCOM_EEXIST;
+
+ if (vcl_worker_set_bapi ())
+ return VPPCOM_EEXIST;
+
+ if (vcl_worker_register_with_vpp ())
+ return VPPCOM_EEXIST;
+
+ return VPPCOM_OK;
}
int
diff --git a/src/vcl/vppcom.h b/src/vcl/vppcom.h
index 0c0b7ce45fd..30ab7c4a56a 100644
--- a/src/vcl/vppcom.h
+++ b/src/vcl/vppcom.h
@@ -137,6 +137,7 @@ typedef enum
VPPCOM_ATTR_SET_TCP_KEEPINTVL,
VPPCOM_ATTR_GET_TCP_USER_MSS,
VPPCOM_ATTR_SET_TCP_USER_MSS,
+ VPPCOM_ATTR_GET_REFCNT,
} vppcom_attr_op_t;
typedef struct _vcl_poll