aboutsummaryrefslogtreecommitdiffstats
path: root/src/vcl/vcl_locked.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vcl/vcl_locked.c')
-rw-r--r--src/vcl/vcl_locked.c63
1 files changed, 45 insertions, 18 deletions
diff --git a/src/vcl/vcl_locked.c b/src/vcl/vcl_locked.c
index 6027fd19c15..69dd15b0ef4 100644
--- a/src/vcl/vcl_locked.c
+++ b/src/vcl/vcl_locked.c
@@ -619,7 +619,8 @@ vls_listener_wrk_set (vcl_locked_session_t * vls, u32 wrk_index, u8 is_active)
vls_shd = vls_shared_data_get (vls->shared_data_index);
clib_spinlock_lock (&vls_shd->lock);
- clib_bitmap_set (vls_shd->listeners, wrk_index, is_active);
+ vls_shd->listeners =
+ clib_bitmap_set (vls_shd->listeners, wrk_index, is_active);
clib_spinlock_unlock (&vls_shd->lock);
vls_shared_data_pool_runlock ();
@@ -669,8 +670,19 @@ vls_listener_wrk_is_active (vcl_locked_session_t * vls, u32 wrk_index)
static void
vls_listener_wrk_start_listen (vcl_locked_session_t * vls, u32 wrk_index)
{
- vppcom_session_listen (vls_to_sh (vls), ~0);
- vls_listener_wrk_set (vls, wrk_index, 1 /* is_active */ );
+ vcl_worker_t *wrk;
+ vcl_session_t *ls;
+
+ wrk = vcl_worker_get (wrk_index);
+ ls = vcl_session_get (wrk, vls->session_index);
+
+ /* Listen request already sent */
+ if (ls->flags & VCL_SESSION_F_PENDING_LISTEN)
+ return;
+
+ vcl_send_session_listen (wrk, ls);
+
+ vls_listener_wrk_set (vls, wrk_index, 1 /* is_active */);
}
static void
@@ -835,13 +847,14 @@ vls_share_session (vls_worker_t * vls_wrk, vcl_locked_session_t * vls)
vls_shared_data_pool_runlock ();
- if (s->rx_fifo)
+ if (s->session_state == VCL_STATE_LISTEN)
{
- vcl_session_share_fifos (s, s->rx_fifo, s->tx_fifo);
+ s->session_state = VCL_STATE_LISTEN_NO_MQ;
+ s->rx_fifo = s->tx_fifo = 0;
}
- else if (s->session_state == VCL_STATE_LISTEN)
+ else if (s->rx_fifo)
{
- s->session_state = VCL_STATE_LISTEN_NO_MQ;
+ vcl_session_share_fifos (s, s->rx_fifo, s->tx_fifo);
}
}
@@ -850,7 +863,6 @@ vls_share_sessions (vls_worker_t * vls_parent_wrk, vls_worker_t * vls_wrk)
{
vcl_locked_session_t *vls, *parent_vls;
- /* *INDENT-OFF* */
pool_foreach (vls, vls_wrk->vls_pool) {
/* Initialize sharing on parent session */
if (vls->shared_data_index == ~0)
@@ -861,7 +873,6 @@ vls_share_sessions (vls_worker_t * vls_parent_wrk, vls_worker_t * vls_wrk)
}
vls_share_session (vls_wrk, vls);
}
- /* *INDENT-ON* */
}
static void
@@ -1300,7 +1311,13 @@ vls_mp_checks (vcl_locked_session_t * vls, int is_add)
vls_listener_wrk_set (vls, vls->vcl_wrk_index, 1 /* is_active */);
break;
}
- vls_listener_wrk_stop_listen (vls, vls->vcl_wrk_index);
+ /* Although removal from epoll means listener no longer accepts new
+ * sessions, the accept queue built by vpp cannot be drained by stopping
+ * the listener. Morover, some applications, e.g., nginx, might
+ * constantly remove and add listeners to their epfds. Removing
+ * listeners in such situations causes a lot of churn in vpp as segments
+ * and segment managers need to be recreated. */
+ /* vls_listener_wrk_stop_listen (vls, vls->vcl_wrk_index); */
break;
case VCL_STATE_LISTEN_NO_MQ:
if (!is_add)
@@ -1380,13 +1397,11 @@ vls_mt_session_cleanup (vcl_locked_session_t * vls)
current_vcl_wrk = vcl_get_worker_index ();
- /* *INDENT-OFF* */
hash_foreach (wrk_index, session_index, vls->vcl_wrk_index_to_session_index,
({
if (current_vcl_wrk != wrk_index)
vls_send_session_cleanup_rpc (wrk, wrk_index, session_index);
}));
- /* *INDENT-ON* */
hash_free (vls->vcl_wrk_index_to_session_index);
}
@@ -1480,17 +1495,33 @@ vls_epoll_ctl (vls_handle_t ep_vlsh, int op, vls_handle_t vlsh,
vls_mt_detect ();
vls_mt_pool_rlock ();
+
ep_vls = vls_get_and_lock (ep_vlsh);
+ if (PREDICT_FALSE (!ep_vls))
+ {
+ vls_mt_pool_runlock ();
+ return VPPCOM_EBADFD;
+ }
if (vls_mt_session_should_migrate (ep_vls))
{
ep_vls = vls_mt_session_migrate (ep_vls);
if (PREDICT_FALSE (!ep_vls))
- return VPPCOM_EBADFD;
+ {
+ vls_mt_pool_runlock ();
+ return VPPCOM_EBADFD;
+ }
}
- ep_sh = vls_to_sh (ep_vls);
vls = vls_get_and_lock (vlsh);
+ if (PREDICT_FALSE (!vls))
+ {
+ vls_unlock (ep_vls);
+ vls_mt_pool_runlock ();
+ return VPPCOM_EBADFD;
+ }
+
+ ep_sh = vls_to_sh (ep_vls);
sh = vls_to_sh (vls);
vls_epoll_ctl_mp_checks (vls, op);
@@ -1545,7 +1576,6 @@ vls_select_mp_checks (vcl_si_set * read_map)
vlsl->select_mp_check = 1;
wrk = vcl_worker_get_current ();
- /* *INDENT-OFF* */
clib_bitmap_foreach (si, read_map) {
s = vcl_session_get (wrk, si);
if (s->session_state == VCL_STATE_LISTEN)
@@ -1554,7 +1584,6 @@ vls_select_mp_checks (vcl_si_set * read_map)
vls_mp_checks (vls, 1 /* is_add */);
}
}
- /* *INDENT-ON* */
}
int
@@ -1587,13 +1616,11 @@ vls_unshare_vcl_worker_sessions (vcl_worker_t * wrk)
current_wrk = vcl_get_worker_index ();
is_current = current_wrk == wrk->wrk_index;
- /* *INDENT-OFF* */
pool_foreach (s, wrk->sessions) {
vls = vls_get (vls_si_wi_to_vlsh (s->session_index, wrk->wrk_index));
if (vls && (is_current || vls_is_shared_by_wrk (vls, current_wrk)))
vls_unshare_session (vls, wrk);
}
- /* *INDENT-ON* */
}
static void