vcl: inject epoll functions into vcl from ldp 62/43062/12
authorFlorin Coras <[email protected]>
Mon, 2 Jun 2025 04:12:36 +0000 (00:12 -0400)
committerDave Barach <[email protected]>
Mon, 9 Jun 2025 23:10:25 +0000 (23:10 +0000)
Instead of trying to detect in ldp if vcl is asking for real epoll, have
vcl use libc epoll directly. This is obtained either at startup or by
means of ldp/vls.

Type: improvement

Change-Id: Ia77d49aef33be7618aeeb1a1d6a618d7ef4bcc6c
Signed-off-by: Florin Coras <[email protected]>
src/vcl/ldp.c
src/vcl/vcl_locked.c
src/vcl/vcl_locked.h
src/vcl/vcl_private.c
src/vcl/vcl_private.h
src/vcl/vcl_sapi.c
src/vcl/vppcom.c

index d9f45b2..b4978bf 100644 (file)
@@ -122,9 +122,6 @@ typedef struct
   u32 vlsh_bit_mask;
   u32 debug;
 
-  /** vcl needs next epoll_create to go to libc_epoll */
-  u8 vcl_needs_real_epoll;
-
   /**
    * crypto state used only for testing
    */
@@ -288,11 +285,11 @@ ldp_init (void)
 
   ldp_init_cfg ();
   ldp->init = 1;
-  ldp->vcl_needs_real_epoll = 1;
+  vls_set_epoll_fns (
+    (vls_epoll_fns_t){ libc_epoll_create1, libc_epoll_ctl, libc_epoll_wait });
   rv = vls_app_create (ldp_get_app_name ());
   if (rv != VPPCOM_OK)
     {
-      ldp->vcl_needs_real_epoll = 0;
       if (rv == VPPCOM_EEXIST)
        return 0;
       LDBG (2,
@@ -302,7 +299,6 @@ ldp_init (void)
       ldp->init = 0;
       return rv;
     }
-  ldp->vcl_needs_real_epoll = 0;
 
   LDBG (0, "LDP initialization: done!");
 
@@ -2385,22 +2381,11 @@ shutdown (int fd, int how)
 int
 epoll_create1 (int flags)
 {
-  ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
   vls_handle_t vlsh;
   int rv;
 
   ldp_init_check ();
 
-  if (ldp->vcl_needs_real_epoll || vls_use_real_epoll ())
-    {
-      rv = libc_epoll_create1 (flags);
-      ldp->vcl_needs_real_epoll = 0;
-      /* Assume this is a request to create the mq epfd */
-      ldpw->vcl_mq_epfd = rv;
-      LDBG (0, "created vcl epfd %u", rv);
-      return rv;
-    }
-
   vlsh = vls_epoll_create ();
   if (PREDICT_FALSE (vlsh == VLS_INVALID_HANDLE))
     {
@@ -2527,10 +2512,6 @@ ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
   if (PREDICT_FALSE (vppcom_worker_index () == ~0))
     vls_register_vcl_worker ();
 
-  ldpw = ldp_worker_get_current ();
-  if (epfd == ldpw->vcl_mq_epfd)
-    return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
-
   ep_vlsh = ldp_fd_to_vlsh (epfd);
   if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
     {
@@ -2539,6 +2520,7 @@ ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
       return -1;
     }
 
+  ldpw = ldp_worker_get_current ();
   if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
     clib_time_init (&ldpw->clib_time);
   time_to_wait = ((timeout >= 0) ? (double) timeout / 1000 : 0);
@@ -2611,9 +2593,6 @@ ldp_epoll_pwait_eventfd (int epfd, struct epoll_event *events,
     vls_register_vcl_worker ();
 
   ldpw = ldp_worker_get_current ();
-  if (epfd == ldpw->vcl_mq_epfd)
-    return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
-
   ep_vlsh = ldp_fd_to_vlsh (epfd);
   if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
     {
@@ -2655,8 +2634,7 @@ ldp_epoll_pwait_eventfd (int epfd, struct epoll_event *events,
       ldpw->vcl_mq_epfd = vppcom_mq_epoll_fd ();
       e.events = EPOLLIN;
       e.data.fd = ldpw->vcl_mq_epfd;
-      if (libc_epoll_ctl (libc_epfd, EPOLL_CTL_ADD, ldpw->vcl_mq_epfd, &e) <
-         0)
+      if (libc_epoll_ctl (libc_epfd, EPOLL_CTL_ADD, ldpw->vcl_mq_epfd, &e) < 0)
        {
          LDBG (0, "epfd %d, add libc mq epoll fd %d to libc epoll fd %d",
                epfd, ldpw->vcl_mq_epfd, libc_epfd);
index aaf47c8..15b53a3 100644 (file)
@@ -2216,15 +2216,6 @@ vls_mt_wrk_supported (void)
   return vcm->cfg.mt_wrk_supported;
 }
 
-int
-vls_use_real_epoll (void)
-{
-  if (vcl_get_worker_index () == ~0)
-    return 0;
-
-  return vcl_worker_get_current ()->vcl_needs_real_epoll;
-}
-
 int
 vls_set_libc_epfd (vls_handle_t ep_vlsh, int libc_epfd)
 {
@@ -2271,6 +2262,14 @@ vls_get_libc_epfd (vls_handle_t ep_vlsh)
   return rv;
 }
 
+void
+vls_set_epoll_fns (vls_epoll_fns_t ep_fns)
+{
+  vcm->vcl_epoll_create1 = ep_fns.epoll_create1_fn;
+  vcm->vcl_epoll_ctl = ep_fns.epoll_ctl_fn;
+  vcm->vcl_epoll_wait = ep_fns.epoll_wait_fn;
+}
+
 void
 vls_register_vcl_worker (void)
 {
index 98a1c54..a55d182 100644 (file)
 #define VLS_WORKER_RPC_TIMEOUT 3 /* timeout to wait rpc response. */
 
 typedef int vls_handle_t;
+typedef struct vls_epoll_fns_
+{
+  int (*epoll_create1_fn) (int flags);
+  int (*epoll_ctl_fn) (int epfd, int op, int fd, struct epoll_event *event);
+  int (*epoll_wait_fn) (int epfd, struct epoll_event *events, int maxevents,
+                       int timeout);
+} vls_epoll_fns_t;
 
 vls_handle_t vls_create (uint8_t proto, uint8_t is_nonblocking);
 int vls_shutdown (vls_handle_t vlsh, int how);
@@ -57,9 +64,9 @@ vls_handle_t vls_session_index_to_vlsh (uint32_t session_index);
 int vls_app_create (char *app_name);
 unsigned char vls_use_eventfd (void);
 unsigned char vls_mt_wrk_supported (void);
-int vls_use_real_epoll (void);
 int vls_set_libc_epfd (vls_handle_t ep_vlsh, int libc_epfd);
 int vls_get_libc_epfd (vls_handle_t ep_vlsh);
+void vls_set_epoll_fns (vls_epoll_fns_t ep_fns);
 void vls_register_vcl_worker (void);
 
 #endif /* SRC_VCL_VCL_LOCKED_H_ */
index ea82c26..dcd827f 100644 (file)
@@ -48,7 +48,7 @@ vcl_mq_epoll_add_api_sock (vcl_worker_t *wrk)
   int rv;
 
   e.data.u32 = VCL_EP_SAPIFD_EVT;
-  rv = epoll_ctl (wrk->mqs_epfd, EPOLL_CTL_ADD, cs->fd, &e);
+  rv = vcm->vcl_epoll_ctl (wrk->mqs_epfd, EPOLL_CTL_ADD, cs->fd, &e);
   if (rv != EEXIST && rv < 0)
     return -1;
 
@@ -77,7 +77,7 @@ vcl_mq_epoll_add_evfd (vcl_worker_t * wrk, svm_msg_q_t * mq)
 
   e.events = EPOLLIN;
   e.data.u32 = mqc_index;
-  if (epoll_ctl (wrk->mqs_epfd, EPOLL_CTL_ADD, mq_fd, &e) < 0)
+  if (vcm->vcl_epoll_ctl (wrk->mqs_epfd, EPOLL_CTL_ADD, mq_fd, &e) < 0)
     {
       VDBG (0, "failed to add mq eventfd to mq epoll fd");
       return -1;
@@ -101,7 +101,7 @@ vcl_mq_epoll_del_evfd (vcl_worker_t * wrk, u32 mqc_index)
     return -1;
 
   mqc = vcl_mq_evt_conn_get (wrk, mqc_index);
-  if (epoll_ctl (wrk->mqs_epfd, EPOLL_CTL_DEL, mqc->mq_fd, 0) < 0)
+  if (vcm->vcl_epoll_ctl (wrk->mqs_epfd, EPOLL_CTL_DEL, mqc->mq_fd, 0) < 0)
     {
       VDBG (0, "failed to del mq eventfd to mq epoll fd");
       return -1;
@@ -187,8 +187,8 @@ vcl_worker_detached_start_signal_mq (vcl_worker_t *wrk)
   struct epoll_event evt = {};
   evt.events = EPOLLIN;
   evt.data.u32 = VCL_EP_PIPEFD_EVT;
-  if (epoll_ctl (wrk->mqs_epfd, EPOLL_CTL_ADD, wrk->detached_pipefds[0],
-                &evt) < 0)
+  if (vcm->vcl_epoll_ctl (wrk->mqs_epfd, EPOLL_CTL_ADD,
+                         wrk->detached_pipefds[0], &evt) < 0)
     {
       VDBG (0, "failed to add mq eventfd to mq epoll fd");
       exit (1);
@@ -211,8 +211,8 @@ vcl_worker_detached_signal_mq (vcl_worker_t *wrk)
 void
 vcl_worker_detached_stop_signal_mq (vcl_worker_t *wrk)
 {
-  if (epoll_ctl (wrk->mqs_epfd, EPOLL_CTL_DEL, wrk->detached_pipefds[0], 0) <
-      0)
+  if (vcm->vcl_epoll_ctl (wrk->mqs_epfd, EPOLL_CTL_DEL,
+                         wrk->detached_pipefds[0], 0) < 0)
     {
       VDBG (0, "failed to del mq eventfd to mq epoll fd");
       exit (1);
@@ -324,9 +324,7 @@ vcl_worker_alloc_and_init ()
   wrk->mqs_epfd = -1;
   if (vcm->cfg.use_mq_eventfd)
     {
-      wrk->vcl_needs_real_epoll = 1;
-      wrk->mqs_epfd = epoll_create (1);
-      wrk->vcl_needs_real_epoll = 0;
+      wrk->mqs_epfd = vcm->vcl_epoll_create1 (0);
       if (wrk->mqs_epfd < 0)
        {
          clib_unix_warning ("epoll_create() returned");
@@ -374,6 +372,17 @@ vcl_worker_ctrl_mq (vcl_worker_t * wrk)
   return wrk->ctrl_mq;
 }
 
+void
+vcl_init_epoll_fns ()
+{
+  if (!vcm->vcl_epoll_create1)
+    vcm->vcl_epoll_create1 = epoll_create1;
+  if (!vcm->vcl_epoll_ctl)
+    vcm->vcl_epoll_ctl = epoll_ctl;
+  if (!vcm->vcl_epoll_wait)
+    vcm->vcl_epoll_wait = epoll_wait;
+}
+
 int
 vcl_session_read_ready (vcl_session_t * s)
 {
index 609653f..a66dbf3 100644 (file)
@@ -320,8 +320,6 @@ typedef struct vcl_worker_
   int session_attr_op_rv;
   transport_endpt_attr_t session_attr_rv;
 
-  /** vcl needs next epoll_create to go to libc_epoll */
-  u8 vcl_needs_real_epoll;
   volatile int rpc_done;
 
   /* functions to be called pre/post wait if vcl managed by vls */
@@ -381,6 +379,14 @@ typedef struct vppcom_main_t_
 
   vcl_rpc_fn_t *wrk_rpc_fn;
 
+  /*
+   * Pointers to libc epoll fns to avoid loops when ldp is on
+   */
+  int (*vcl_epoll_create1) (int flags);
+  int (*vcl_epoll_ctl) (int epfd, int op, int fd, struct epoll_event *event);
+  int (*vcl_epoll_wait) (int epfd, struct epoll_event *events, int maxevents,
+                        int timeout);
+
   /*
    * Binary api context
    */
@@ -807,6 +813,9 @@ void vcl_worker_set_wait_mq_fns (vcl_worker_wait_mq_fn pre_wait,
 void vcl_worker_detached_start_signal_mq (vcl_worker_t *wrk);
 void vcl_worker_detached_signal_mq (vcl_worker_t *wrk);
 void vcl_worker_detached_stop_signal_mq (vcl_worker_t *wrk);
+
+void vcl_init_epoll_fns (void);
+
 /*
  * VCL Binary API
  */
index e3e2b6a..f23273a 100644 (file)
@@ -26,8 +26,6 @@ vcl_api_connect_app_socket (vcl_worker_t * wrk)
   cs->flags =
     CLIB_SOCKET_F_IS_CLIENT | CLIB_SOCKET_F_SEQPACKET | CLIB_SOCKET_F_BLOCKING;
 
-  wrk->vcl_needs_real_epoll = 1;
-
   if ((err = clib_socket_init (cs)))
     {
       /* don't report the error to avoid flood of error messages during
@@ -39,8 +37,6 @@ vcl_api_connect_app_socket (vcl_worker_t * wrk)
 
 done:
 
-  wrk->vcl_needs_real_epoll = 0;
-
   return rv;
 }
 
index 0671a37..62d2add 100644 (file)
@@ -1482,6 +1482,7 @@ vppcom_app_create (const char *app_name)
   vcm->main_cpu = pthread_self ();
   vcm->main_pid = getpid ();
   vcm->app_name = format (0, "%s", app_name);
+  vcl_init_epoll_fns ();
   fifo_segment_main_init (&vcm->segment_main, (uword) ~0,
                          20 /* timeout in secs */);
   pool_alloc (vcm->workers, vcl_cfg->max_workers);
@@ -2799,8 +2800,8 @@ vppcom_select_eventfd (vcl_worker_t * wrk, int n_bits,
 
   do
     {
-      n_mq_evts = epoll_wait (wrk->mqs_epfd, wrk->mq_events,
-                             vec_len (wrk->mq_events), time_to_wait);
+      n_mq_evts = vcm->vcl_epoll_wait (wrk->mqs_epfd, wrk->mq_events,
+                                      vec_len (wrk->mq_events), time_to_wait);
       if (n_mq_evts < 0)
        {
          if (errno == EINTR)
@@ -3599,8 +3600,8 @@ vppcom_epoll_wait_eventfd (vcl_worker_t *wrk, struct epoll_event *events,
 
   do
     {
-      n_mq_evts = epoll_wait (wrk->mqs_epfd, wrk->mq_events,
-                             vec_len (wrk->mq_events), timeout_ms);
+      n_mq_evts = vcm->vcl_epoll_wait (wrk->mqs_epfd, wrk->mq_events,
+                                      vec_len (wrk->mq_events), timeout_ms);
       if (n_mq_evts < 0)
        {
          if (errno == EINTR)