build: archive make install-ext-deps build logs in ci
[vpp.git] / src / vcl / vcl_locked.c
index 6027fd1..93ece00 100644 (file)
@@ -374,6 +374,12 @@ vls_worker_get_current (void)
   return pool_elt_at_index (vlsm->workers, vls_get_worker_index ());
 }
 
+static inline u8
+vls_n_workers (void)
+{
+  return pool_elts (vlsm->workers);
+}
+
 static void
 vls_worker_alloc (void)
 {
@@ -619,7 +625,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 +676,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 +853,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 +869,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 +879,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
@@ -1287,7 +1304,7 @@ vls_mp_checks (vcl_locked_session_t * vls, int is_add)
   vcl_session_t *s;
   u32 owner_wrk;
 
-  if (vls_mt_wrk_supported ())
+  if (vls_mt_wrk_supported () && vls_n_workers () <= 1)
     return;
 
   ASSERT (wrk->wrk_index == vls->vcl_wrk_index);
@@ -1300,7 +1317,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 +1403,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 +1501,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 +1582,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 +1590,6 @@ vls_select_mp_checks (vcl_si_set * read_map)
        vls_mp_checks (vls, 1 /* is_add */);
       }
   }
-  /* *INDENT-ON* */
 }
 
 int
@@ -1587,13 +1622,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