diff options
Diffstat (limited to 'src/vcl/vcl_locked.c')
-rw-r--r-- | src/vcl/vcl_locked.c | 63 |
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 |