LCOV - code coverage report
Current view: top level - vcl - ldp.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 510 1314 38.8 %
Date: 2023-07-05 22:20:52 Functions: 18 28 64.3 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016-2019 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : 
      16             : #ifdef HAVE_GNU_SOURCE
      17             : #define _GNU_SOURCE
      18             : #endif
      19             : 
      20             : #include <unistd.h>
      21             : #include <stdio.h>
      22             : #include <signal.h>
      23             : #include <dlfcn.h>
      24             : #include <pthread.h>
      25             : #include <time.h>
      26             : #include <stdarg.h>
      27             : #include <sys/resource.h>
      28             : #include <netinet/tcp.h>
      29             : #include <netinet/udp.h>
      30             : 
      31             : #include <vcl/ldp_socket_wrapper.h>
      32             : #include <vcl/ldp.h>
      33             : #include <sys/time.h>
      34             : 
      35             : #include <vcl/vcl_locked.h>
      36             : #include <vppinfra/time.h>
      37             : #include <vppinfra/bitmap.h>
      38             : #include <vppinfra/lock.h>
      39             : #include <vppinfra/pool.h>
      40             : #include <vppinfra/hash.h>
      41             : 
      42             : #define HAVE_CONSTRUCTOR_ATTRIBUTE
      43             : #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
      44             : #define CONSTRUCTOR_ATTRIBUTE                       \
      45             :     __attribute__ ((constructor))
      46             : #else
      47             : #define CONSTRUCTOR_ATTRIBUTE
      48             : #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
      49             : 
      50             : #define HAVE_DESTRUCTOR_ATTRIBUTE
      51             : #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
      52             : #define DESTRUCTOR_ATTRIBUTE                        \
      53             :     __attribute__ ((destructor))
      54             : #else
      55             : #define DESTRUCTOR_ATTRIBUTE
      56             : #endif
      57             : 
      58             : #define LDP_MAX_NWORKERS 32
      59             : 
      60             : #ifdef HAVE_GNU_SOURCE
      61             : #define SOCKADDR_GET_SA(__addr) __addr.__sockaddr__;
      62             : #else
      63             : #define SOCKADDR_GET_SA(__addr) _addr;
      64             : #endif
      65             : 
      66             : #ifndef UDP_SEGMENT
      67             : #define UDP_SEGMENT 103
      68             : #endif
      69             : 
      70             : typedef struct ldp_worker_ctx_
      71             : {
      72             :   u8 *io_buffer;
      73             :   clib_time_t clib_time;
      74             : 
      75             :   /*
      76             :    * Select state
      77             :    */
      78             :   clib_bitmap_t *rd_bitmap;
      79             :   clib_bitmap_t *wr_bitmap;
      80             :   clib_bitmap_t *ex_bitmap;
      81             :   clib_bitmap_t *si_rd_bitmap;
      82             :   clib_bitmap_t *si_wr_bitmap;
      83             :   clib_bitmap_t *si_ex_bitmap;
      84             :   clib_bitmap_t *libc_rd_bitmap;
      85             :   clib_bitmap_t *libc_wr_bitmap;
      86             :   clib_bitmap_t *libc_ex_bitmap;
      87             : 
      88             :   /*
      89             :    * Poll state
      90             :    */
      91             :   vcl_poll_t *vcl_poll;
      92             :   struct pollfd *libc_poll;
      93             :   u16 *libc_poll_idxs;
      94             : 
      95             :   /*
      96             :    * Epoll state
      97             :    */
      98             :   u8 epoll_wait_vcl;
      99             :   u8 mq_epfd_added;
     100             :   int vcl_mq_epfd;
     101             : 
     102             : } ldp_worker_ctx_t;
     103             : 
     104             : /* clib_bitmap_t, fd_mask and vcl_si_set are used interchangeably. Make sure
     105             :  * they are the same size */
     106             : STATIC_ASSERT (sizeof (clib_bitmap_t) == sizeof (fd_mask),
     107             :                "ldp bitmap size mismatch");
     108             : STATIC_ASSERT (sizeof (vcl_si_set) == sizeof (fd_mask),
     109             :                "ldp bitmap size mismatch");
     110             : 
     111             : typedef struct
     112             : {
     113             :   ldp_worker_ctx_t *workers;
     114             :   int init;
     115             :   char app_name[LDP_APP_NAME_MAX];
     116             :   u32 vlsh_bit_val;
     117             :   u32 vlsh_bit_mask;
     118             :   u32 debug;
     119             : 
     120             :   /** vcl needs next epoll_create to go to libc_epoll */
     121             :   u8 vcl_needs_real_epoll;
     122             : 
     123             :   /**
     124             :    * crypto state used only for testing
     125             :    */
     126             :   u8 transparent_tls;
     127             :   u32 ckpair_index;
     128             : } ldp_main_t;
     129             : 
     130             : #define LDP_DEBUG ldp->debug
     131             : 
     132             : #define LDBG(_lvl, _fmt, _args...)                                      \
     133             :   if (ldp->debug > _lvl)                                          \
     134             :     {                                                                   \
     135             :       int errno_saved = errno;                                          \
     136             :       fprintf (stderr, "ldp<%d>: " _fmt "\n", getpid(), ##_args);     \
     137             :       errno = errno_saved;                                              \
     138             :     }
     139             : 
     140             : static ldp_main_t ldp_main = {
     141             :   .vlsh_bit_val = (1 << LDP_SID_BIT_MIN),
     142             :   .vlsh_bit_mask = (1 << LDP_SID_BIT_MIN) - 1,
     143             :   .debug = LDP_DEBUG_INIT,
     144             :   .transparent_tls = 0,
     145             :   .ckpair_index = ~0,
     146             : };
     147             : 
     148             : static ldp_main_t *ldp = &ldp_main;
     149             : 
     150             : static inline ldp_worker_ctx_t *
     151      441984 : ldp_worker_get_current (void)
     152             : {
     153      441984 :   return (ldp->workers + vppcom_worker_index ());
     154             : }
     155             : 
     156             : /*
     157             :  * RETURN:  0 on success or -1 on error.
     158             :  * */
     159             : static inline void
     160          13 : ldp_set_app_name (char *app_name)
     161             : {
     162          13 :   snprintf (ldp->app_name, LDP_APP_NAME_MAX, "%s-ldp-%d", app_name, getpid ());
     163          13 : }
     164             : 
     165             : static inline char *
     166          13 : ldp_get_app_name ()
     167             : {
     168          13 :   if (ldp->app_name[0] == '\0')
     169          13 :     ldp_set_app_name (program_invocation_short_name);
     170             : 
     171          13 :   return ldp->app_name;
     172             : }
     173             : 
     174             : static inline int
     175      442791 : ldp_vlsh_to_fd (vls_handle_t vlsh)
     176             : {
     177      442791 :   return (vlsh + ldp->vlsh_bit_val);
     178             : }
     179             : 
     180             : static inline vls_handle_t
     181     2933860 : ldp_fd_to_vlsh (int fd)
     182             : {
     183     2933860 :   if (fd < ldp->vlsh_bit_val)
     184      131767 :     return VLS_INVALID_HANDLE;
     185             : 
     186     2802100 :   return (fd - ldp->vlsh_bit_val);
     187             : }
     188             : 
     189             : static void
     190          13 : ldp_alloc_workers (void)
     191             : {
     192          13 :   if (ldp->workers)
     193           0 :     return;
     194          13 :   pool_alloc (ldp->workers, LDP_MAX_NWORKERS);
     195             : }
     196             : 
     197             : static void
     198          13 : ldp_init_cfg (void)
     199             : {
     200          13 :   char *env_var_str = getenv (LDP_ENV_DEBUG);
     201          13 :   if (env_var_str)
     202             :     {
     203             :       u32 tmp;
     204           0 :       if (sscanf (env_var_str, "%u", &tmp) != 1)
     205           0 :         clib_warning ("LDP<%d>: WARNING: Invalid LDP debug level specified in"
     206             :                       " the env var " LDP_ENV_DEBUG " (%s)!", getpid (),
     207             :                       env_var_str);
     208             :       else
     209             :         {
     210           0 :           ldp->debug = tmp;
     211           0 :           LDBG (0, "configured LDP debug level (%u) from env var "
     212             :                 LDP_ENV_DEBUG "!", ldp->debug);
     213             :         }
     214             :     }
     215             : 
     216          13 :   env_var_str = getenv (LDP_ENV_APP_NAME);
     217          13 :   if (env_var_str)
     218             :     {
     219           0 :       ldp_set_app_name (env_var_str);
     220           0 :       LDBG (0, "configured LDP app name (%s) from the env var "
     221             :             LDP_ENV_APP_NAME "!", ldp->app_name);
     222             :     }
     223             : 
     224          13 :   env_var_str = getenv (LDP_ENV_SID_BIT);
     225          13 :   if (env_var_str)
     226             :     {
     227             :       u32 sb;
     228           0 :       if (sscanf (env_var_str, "%u", &sb) != 1)
     229             :         {
     230           0 :           LDBG (0, "WARNING: Invalid LDP sid bit specified in the env var "
     231             :                 LDP_ENV_SID_BIT " (%s)! sid bit value %d (0x%x)", env_var_str,
     232             :                 ldp->vlsh_bit_val, ldp->vlsh_bit_val);
     233             :         }
     234           0 :       else if (sb < LDP_SID_BIT_MIN)
     235             :         {
     236           0 :           ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MIN);
     237           0 :           ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
     238             : 
     239           0 :           LDBG (0, "WARNING: LDP sid bit (%u) specified in the env var "
     240             :                 LDP_ENV_SID_BIT " (%s) is too small. Using LDP_SID_BIT_MIN"
     241             :                 " (%d)! sid bit value %d (0x%x)", sb, env_var_str,
     242             :                 LDP_SID_BIT_MIN, ldp->vlsh_bit_val, ldp->vlsh_bit_val);
     243             :         }
     244           0 :       else if (sb > LDP_SID_BIT_MAX)
     245             :         {
     246           0 :           ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MAX);
     247           0 :           ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
     248             : 
     249           0 :           LDBG (0, "WARNING: LDP sid bit (%u) specified in the env var "
     250             :                 LDP_ENV_SID_BIT " (%s) is too big. Using LDP_SID_BIT_MAX"
     251             :                 " (%d)! sid bit value %d (0x%x)", sb, env_var_str,
     252             :                 LDP_SID_BIT_MAX, ldp->vlsh_bit_val, ldp->vlsh_bit_val);
     253             :         }
     254             :       else
     255             :         {
     256           0 :           ldp->vlsh_bit_val = (1 << sb);
     257           0 :           ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
     258             : 
     259           0 :           LDBG (0, "configured LDP sid bit (%u) from "
     260             :                 LDP_ENV_SID_BIT "!  sid bit value %d (0x%x)", sb,
     261             :                 ldp->vlsh_bit_val, ldp->vlsh_bit_val);
     262             :         }
     263             : 
     264             :       /* Make sure there are enough bits in the fd set for vcl sessions */
     265           0 :       if (ldp->vlsh_bit_val > FD_SETSIZE / 2)
     266             :         {
     267             :           /* Only valid for select/pselect, so just WARNING and not exit */
     268           0 :           LDBG (0,
     269             :                 "WARNING: LDP vlsh bit value %d > FD_SETSIZE/2 %d, "
     270             :                 "select/pselect not supported now!",
     271             :                 ldp->vlsh_bit_val, FD_SETSIZE / 2);
     272             :         }
     273             :     }
     274          13 :   env_var_str = getenv (LDP_ENV_TLS_TRANS);
     275          13 :   if (env_var_str)
     276             :     {
     277           0 :       ldp->transparent_tls = 1;
     278             :     }
     279          13 : }
     280             : 
     281             : static int
     282          13 : ldp_init (void)
     283             : {
     284             :   ldp_worker_ctx_t *ldpw;
     285             :   int rv;
     286             : 
     287          13 :   ASSERT (!ldp->init);
     288             : 
     289          13 :   ldp_init_cfg ();
     290          13 :   ldp->init = 1;
     291          13 :   ldp->vcl_needs_real_epoll = 1;
     292          13 :   rv = vls_app_create (ldp_get_app_name ());
     293          13 :   if (rv != VPPCOM_OK)
     294             :     {
     295           0 :       ldp->vcl_needs_real_epoll = 0;
     296           0 :       if (rv == VPPCOM_EEXIST)
     297           0 :         return 0;
     298           0 :       LDBG (2,
     299             :             "\nERROR: ldp_init: vppcom_app_create()"
     300             :             " failed!  rv = %d (%s)\n",
     301             :             rv, vppcom_retval_str (rv));
     302           0 :       ldp->init = 0;
     303           0 :       return rv;
     304             :     }
     305          13 :   ldp->vcl_needs_real_epoll = 0;
     306          13 :   ldp_alloc_workers ();
     307          13 :   ldpw = ldp_worker_get_current ();
     308             : 
     309          13 :   pool_foreach (ldpw, ldp->workers)  {
     310           0 :     clib_memset (&ldpw->clib_time, 0, sizeof (ldpw->clib_time));
     311             :   }
     312             : 
     313          13 :   LDBG (0, "LDP initialization: done!");
     314             : 
     315          13 :   return 0;
     316             : }
     317             : 
     318             : #define ldp_init_check()                                                      \
     319             :   if (PREDICT_FALSE (!ldp->init))                                             \
     320             :     {                                                                         \
     321             :       if ((errno = -ldp_init ()))                                             \
     322             :         return -1;                                                            \
     323             :     }
     324             : 
     325             : int
     326             : close (int fd)
     327             : {
     328             :   vls_handle_t vlsh;
     329             :   int rv, epfd;
     330             : 
     331          61 :   ldp_init_check ();
     332             : 
     333          61 :   vlsh = ldp_fd_to_vlsh (fd);
     334          61 :   if (vlsh != VLS_INVALID_HANDLE)
     335             :     {
     336          35 :       epfd = vls_attr (vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
     337          35 :       if (epfd > 0)
     338             :         {
     339           0 :           ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
     340           0 :           u32 size = sizeof (epfd);
     341             : 
     342           0 :           LDBG (0, "fd %d: calling libc_close: epfd %u", fd, epfd);
     343             : 
     344           0 :           libc_close (epfd);
     345           0 :           ldpw->mq_epfd_added = 0;
     346             : 
     347           0 :           epfd = 0;
     348           0 :           (void) vls_attr (vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &epfd, &size);
     349             :         }
     350          35 :       else if (PREDICT_FALSE (epfd < 0))
     351             :         {
     352           0 :           errno = -epfd;
     353           0 :           rv = -1;
     354           0 :           goto done;
     355             :         }
     356             : 
     357          35 :       LDBG (0, "fd %d: calling vls_close: vlsh %u", fd, vlsh);
     358             : 
     359          35 :       rv = vls_close (vlsh);
     360          35 :       if (rv != VPPCOM_OK)
     361             :         {
     362           0 :           errno = -rv;
     363           0 :           rv = -1;
     364             :         }
     365             :     }
     366             :   else
     367             :     {
     368          26 :       LDBG (0, "fd %d: calling libc_close", fd);
     369          26 :       rv = libc_close (fd);
     370             :     }
     371             : 
     372          61 : done:
     373          61 :   return rv;
     374             : }
     375             : 
     376             : ssize_t
     377             : read (int fd, void *buf, size_t nbytes)
     378             : {
     379             :   vls_handle_t vlsh;
     380             :   ssize_t size;
     381             : 
     382      806745 :   ldp_init_check ();
     383             : 
     384      806745 :   vlsh = ldp_fd_to_vlsh (fd);
     385      806745 :   if (vlsh != VLS_INVALID_HANDLE)
     386             :     {
     387      708264 :       size = vls_read (vlsh, buf, nbytes);
     388      708264 :       if (size < 0)
     389             :         {
     390      261179 :           errno = -size;
     391      261179 :           size = -1;
     392             :         }
     393             :     }
     394             :   else
     395             :     {
     396       98481 :       size = libc_read (fd, buf, nbytes);
     397             :     }
     398             : 
     399      806745 :   return size;
     400             : }
     401             : 
     402             : ssize_t
     403             : readv (int fd, const struct iovec * iov, int iovcnt)
     404             : {
     405           0 :   int rv = 0, i, total = 0;
     406             :   vls_handle_t vlsh;
     407           0 :   ssize_t size = 0;
     408             : 
     409           0 :   ldp_init_check ();
     410             : 
     411           0 :   vlsh = ldp_fd_to_vlsh (fd);
     412           0 :   if (vlsh != VLS_INVALID_HANDLE)
     413             :     {
     414           0 :       for (i = 0; i < iovcnt; ++i)
     415             :         {
     416           0 :           rv = vls_read (vlsh, iov[i].iov_base, iov[i].iov_len);
     417           0 :           if (rv <= 0)
     418           0 :             break;
     419             :           else
     420             :             {
     421           0 :               total += rv;
     422           0 :               if (rv < iov[i].iov_len)
     423           0 :                 break;
     424             :             }
     425             :         }
     426           0 :       if (rv < 0 && total == 0)
     427             :         {
     428           0 :           errno = -rv;
     429           0 :           size = -1;
     430             :         }
     431             :       else
     432           0 :         size = total;
     433             :     }
     434             :   else
     435             :     {
     436           0 :       size = libc_readv (fd, iov, iovcnt);
     437             :     }
     438             : 
     439           0 :   return size;
     440             : }
     441             : 
     442             : ssize_t
     443             : write (int fd, const void *buf, size_t nbytes)
     444             : {
     445             :   vls_handle_t vlsh;
     446      829173 :   ssize_t size = 0;
     447             : 
     448      829173 :   ldp_init_check ();
     449             : 
     450      829173 :   vlsh = ldp_fd_to_vlsh (fd);
     451      829173 :   if (vlsh != VLS_INVALID_HANDLE)
     452             :     {
     453      829129 :       size = vls_write_msg (vlsh, (void *) buf, nbytes);
     454      829129 :       if (size < 0)
     455             :         {
     456      681386 :           errno = -size;
     457      681386 :           size = -1;
     458             :         }
     459             :     }
     460             :   else
     461             :     {
     462          44 :       size = libc_write (fd, buf, nbytes);
     463             :     }
     464             : 
     465      829173 :   return size;
     466             : }
     467             : 
     468             : ssize_t
     469             : writev (int fd, const struct iovec * iov, int iovcnt)
     470             : {
     471         219 :   ssize_t size = 0, total = 0;
     472             :   vls_handle_t vlsh;
     473         219 :   int i, rv = 0;
     474             : 
     475         219 :   ldp_init_check ();
     476             : 
     477         219 :   vlsh = ldp_fd_to_vlsh (fd);
     478         219 :   if (vlsh != VLS_INVALID_HANDLE)
     479             :     {
     480           0 :       for (i = 0; i < iovcnt; ++i)
     481             :         {
     482           0 :           rv = vls_write_msg (vlsh, iov[i].iov_base, iov[i].iov_len);
     483           0 :           if (rv < 0)
     484           0 :             break;
     485             :           else
     486             :             {
     487           0 :               total += rv;
     488           0 :               if (rv < iov[i].iov_len)
     489           0 :                 break;
     490             :             }
     491             :         }
     492             : 
     493           0 :       if (rv < 0 && total == 0)
     494             :         {
     495           0 :           errno = -rv;
     496           0 :           size = -1;
     497             :         }
     498             :       else
     499           0 :         size = total;
     500             :     }
     501             :   else
     502             :     {
     503         219 :       size = libc_writev (fd, iov, iovcnt);
     504             :     }
     505             : 
     506         219 :   return size;
     507             : }
     508             : 
     509             : static int
     510          64 : fcntl_internal (int fd, int cmd, va_list ap)
     511             : {
     512             :   vls_handle_t vlsh;
     513          64 :   int rv = 0;
     514             : 
     515          64 :   vlsh = ldp_fd_to_vlsh (fd);
     516          64 :   LDBG (0, "fd %u vlsh %d, cmd %u", fd, vlsh, cmd);
     517          64 :   if (vlsh != VLS_INVALID_HANDLE)
     518             :     {
     519          37 :       int flags = va_arg (ap, int);
     520             :       u32 size;
     521             : 
     522          37 :       size = sizeof (flags);
     523          37 :       rv = -EOPNOTSUPP;
     524          37 :       switch (cmd)
     525             :         {
     526          23 :         case F_SETFL:
     527          23 :           rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
     528          23 :           break;
     529             : 
     530          14 :         case F_GETFL:
     531          14 :           rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &size);
     532          14 :           if (rv == VPPCOM_OK)
     533          14 :             rv = flags;
     534          14 :           break;
     535           0 :         case F_SETFD:
     536             :           /* TODO handle this */
     537           0 :           LDBG (0, "F_SETFD ignored flags %u", flags);
     538           0 :           rv = 0;
     539           0 :           break;
     540           0 :         default:
     541           0 :           rv = -EOPNOTSUPP;
     542           0 :           break;
     543             :         }
     544          37 :       if (rv < 0)
     545             :         {
     546           0 :           errno = -rv;
     547           0 :           rv = -1;
     548             :         }
     549             :     }
     550             :   else
     551             :     {
     552             : #ifdef HAVE_FCNTL64
     553          27 :       rv = libc_vfcntl64 (fd, cmd, ap);
     554             : #else
     555             :       rv = libc_vfcntl (fd, cmd, ap);
     556             : #endif
     557             :     }
     558             : 
     559          64 :   return rv;
     560             : }
     561             : 
     562             : int
     563             : fcntl (int fd, int cmd, ...)
     564             : {
     565             :   va_list ap;
     566             :   int rv;
     567             : 
     568          64 :   ldp_init_check ();
     569             : 
     570          64 :   va_start (ap, cmd);
     571          64 :   rv = fcntl_internal (fd, cmd, ap);
     572          64 :   va_end (ap);
     573             : 
     574          64 :   return rv;
     575             : }
     576             : 
     577             : int
     578             : fcntl64 (int fd, int cmd, ...)
     579             : {
     580             :   va_list ap;
     581             :   int rv;
     582             : 
     583           0 :   ldp_init_check ();
     584             : 
     585           0 :   va_start (ap, cmd);
     586           0 :   rv = fcntl_internal (fd, cmd, ap);
     587           0 :   va_end (ap);
     588           0 :   return rv;
     589             : }
     590             : 
     591             : int
     592             : ioctl (int fd, unsigned long int cmd, ...)
     593             : {
     594             :   vls_handle_t vlsh;
     595             :   va_list ap;
     596             :   int rv;
     597             : 
     598         242 :   ldp_init_check ();
     599             : 
     600         242 :   va_start (ap, cmd);
     601             : 
     602         242 :   vlsh = ldp_fd_to_vlsh (fd);
     603         242 :   if (vlsh != VLS_INVALID_HANDLE)
     604             :     {
     605         242 :       switch (cmd)
     606             :         {
     607         242 :         case FIONREAD:
     608         242 :           rv = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
     609         242 :           break;
     610             : 
     611           0 :         case FIONBIO:
     612             :           {
     613           0 :             u32 flags = *(va_arg (ap, int *)) ? O_NONBLOCK : 0;
     614           0 :             u32 size = sizeof (flags);
     615             : 
     616             :             /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than
     617             :              *      non-blocking, the flags should be read here and merged
     618             :              *      with O_NONBLOCK.
     619             :              */
     620           0 :             rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
     621             :           }
     622           0 :           break;
     623             : 
     624           0 :         default:
     625           0 :           rv = -EOPNOTSUPP;
     626           0 :           break;
     627             :         }
     628         242 :       if (rv < 0)
     629             :         {
     630           0 :           errno = -rv;
     631           0 :           rv = -1;
     632             :         }
     633             :     }
     634             :   else
     635             :     {
     636           0 :       rv = libc_vioctl (fd, cmd, ap);
     637             :     }
     638             : 
     639         242 :   va_end (ap);
     640         242 :   return rv;
     641             : }
     642             : 
     643             : always_inline void
     644      882432 : ldp_select_init_maps (fd_set * __restrict original,
     645             :                       clib_bitmap_t ** resultb, clib_bitmap_t ** libcb,
     646             :                       clib_bitmap_t ** vclb, int nfds, u32 minbits,
     647             :                       u32 n_bytes, uword * si_bits, uword * libc_bits)
     648             : {
     649             :   uword si_bits_set, libc_bits_set;
     650             :   vls_handle_t vlsh;
     651             :   int fd;
     652             : 
     653      882432 :   clib_bitmap_validate (*vclb, minbits);
     654      882432 :   clib_bitmap_validate (*libcb, minbits);
     655      882432 :   clib_bitmap_validate (*resultb, minbits);
     656      882432 :   clib_memcpy_fast (*resultb, original, n_bytes);
     657      882432 :   memset (original, 0, n_bytes);
     658             : 
     659             :   /* *INDENT-OFF* */
     660     2146370 :   clib_bitmap_foreach (fd, *resultb)  {
     661     1263940 :     if (fd > nfds)
     662           0 :       break;
     663     1263940 :     vlsh = ldp_fd_to_vlsh (fd);
     664     1263940 :     if (vlsh == VLS_INVALID_HANDLE)
     665           0 :       clib_bitmap_set_no_check (*libcb, fd, 1);
     666             :     else
     667     1263940 :       *vclb = clib_bitmap_set (*vclb, vlsh_to_session_index (vlsh), 1);
     668             :   }
     669             :   /* *INDENT-ON* */
     670             : 
     671      882432 :   si_bits_set = clib_bitmap_last_set (*vclb) + 1;
     672      882432 :   *si_bits = (si_bits_set > *si_bits) ? si_bits_set : *si_bits;
     673      882432 :   clib_bitmap_validate (*resultb, *si_bits);
     674             : 
     675      882432 :   libc_bits_set = clib_bitmap_last_set (*libcb) + 1;
     676      882432 :   *libc_bits = (libc_bits_set > *libc_bits) ? libc_bits_set : *libc_bits;
     677      882432 : }
     678             : 
     679             : always_inline int
     680     1315050 : ldp_select_vcl_map_to_libc (clib_bitmap_t * vclb, fd_set * __restrict libcb)
     681             : {
     682             :   vls_handle_t vlsh;
     683             :   uword si;
     684             :   int fd;
     685             : 
     686     1315050 :   if (!libcb)
     687      439351 :     return 0;
     688             : 
     689             :   /* *INDENT-OFF* */
     690     1318450 :   clib_bitmap_foreach (si, vclb)  {
     691      442744 :     vlsh = vls_session_index_to_vlsh (si);
     692      442744 :     ASSERT (vlsh != VLS_INVALID_HANDLE);
     693      442744 :     fd = ldp_vlsh_to_fd (vlsh);
     694      442744 :     if (PREDICT_FALSE (fd < 0))
     695             :       {
     696           0 :         errno = EBADFD;
     697           0 :         return -1;
     698             :       }
     699      442744 :     FD_SET (fd, libcb);
     700             :   }
     701             :   /* *INDENT-ON* */
     702             : 
     703      875702 :   return 0;
     704             : }
     705             : 
     706             : always_inline void
     707           0 : ldp_select_libc_map_merge (clib_bitmap_t * result, fd_set * __restrict libcb)
     708             : {
     709             :   uword fd;
     710             : 
     711           0 :   if (!libcb)
     712           0 :     return;
     713             : 
     714             :   /* *INDENT-OFF* */
     715           0 :   clib_bitmap_foreach (fd, result)
     716           0 :     FD_SET ((int)fd, libcb);
     717             :   /* *INDENT-ON* */
     718             : }
     719             : 
     720             : int
     721      441719 : ldp_pselect (int nfds, fd_set * __restrict readfds,
     722             :              fd_set * __restrict writefds,
     723             :              fd_set * __restrict exceptfds,
     724             :              const struct timespec *__restrict timeout,
     725             :              const __sigset_t * __restrict sigmask)
     726             : {
     727      441719 :   u32 minbits = clib_max (nfds, BITS (uword)), n_bytes;
     728      441719 :   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
     729      441719 :   struct timespec libc_tspec = { 0 };
     730      441719 :   f64 time_out, vcl_timeout = 0;
     731             :   uword si_bits, libc_bits;
     732      441719 :   int rv, bits_set = 0;
     733             : 
     734      441719 :   if (nfds < 0)
     735             :     {
     736           0 :       errno = EINVAL;
     737           0 :       return -1;
     738             :     }
     739             : 
     740      441719 :   if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
     741          12 :     clib_time_init (&ldpw->clib_time);
     742             : 
     743      441719 :   if (timeout)
     744             :     {
     745      441569 :       time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ?
     746      883138 :         (f64) 0 : (f64) timeout->tv_sec + (f64) timeout->tv_nsec / (f64) 1e9;
     747             : 
     748      441569 :       time_out += clib_time_now (&ldpw->clib_time);
     749             : 
     750             :       /* select as fine grained sleep */
     751      441569 :       if (!nfds)
     752             :         {
     753           0 :           while (clib_time_now (&ldpw->clib_time) < time_out)
     754             :             ;
     755           0 :           return 0;
     756             :         }
     757             :     }
     758         150 :   else if (!nfds)
     759             :     {
     760           0 :       errno = EINVAL;
     761           0 :       return -1;
     762             :     }
     763             :   else
     764         150 :     time_out = -1;
     765             : 
     766      441719 :   if (nfds <= ldp->vlsh_bit_val)
     767             :     {
     768           0 :       rv = libc_pselect (nfds, readfds, writefds, exceptfds,
     769             :                          timeout, sigmask);
     770           0 :       goto done;
     771             :     }
     772             : 
     773      441719 :   si_bits = libc_bits = 0;
     774      441719 :   n_bytes = nfds / 8 + ((nfds % 8) ? 1 : 0);
     775             : 
     776      441719 :   if (readfds)
     777      440719 :     ldp_select_init_maps (readfds, &ldpw->rd_bitmap, &ldpw->libc_rd_bitmap,
     778             :                           &ldpw->si_rd_bitmap, nfds, minbits, n_bytes,
     779             :                           &si_bits, &libc_bits);
     780      441719 :   if (writefds)
     781      441713 :     ldp_select_init_maps (writefds, &ldpw->wr_bitmap,
     782             :                           &ldpw->libc_wr_bitmap, &ldpw->si_wr_bitmap, nfds,
     783             :                           minbits, n_bytes, &si_bits, &libc_bits);
     784      441719 :   if (exceptfds)
     785           0 :     ldp_select_init_maps (exceptfds, &ldpw->ex_bitmap,
     786             :                           &ldpw->libc_ex_bitmap, &ldpw->si_ex_bitmap, nfds,
     787             :                           minbits, n_bytes, &si_bits, &libc_bits);
     788             : 
     789      441719 :   if (PREDICT_FALSE (!si_bits && !libc_bits))
     790             :     {
     791           0 :       errno = EINVAL;
     792           0 :       rv = -1;
     793           0 :       goto done;
     794             :     }
     795             : 
     796      441719 :   if (!si_bits)
     797           0 :     libc_tspec = timeout ? *timeout : libc_tspec;
     798             : 
     799             :   do
     800             :     {
     801    26430600 :       if (si_bits)
     802             :         {
     803    26430600 :           if (readfds)
     804    26429600 :             clib_memcpy_fast (ldpw->rd_bitmap, ldpw->si_rd_bitmap,
     805    26429600 :                               vec_len (ldpw->si_rd_bitmap) *
     806             :                               sizeof (clib_bitmap_t));
     807    26430600 :           if (writefds)
     808    26430600 :             clib_memcpy_fast (ldpw->wr_bitmap, ldpw->si_wr_bitmap,
     809    26430600 :                               vec_len (ldpw->si_wr_bitmap) *
     810             :                               sizeof (clib_bitmap_t));
     811    26430600 :           if (exceptfds)
     812           0 :             clib_memcpy_fast (ldpw->ex_bitmap, ldpw->si_ex_bitmap,
     813           0 :                               vec_len (ldpw->si_ex_bitmap) *
     814             :                               sizeof (clib_bitmap_t));
     815             : 
     816    26430600 :           rv = vls_select (si_bits, readfds ? ldpw->rd_bitmap : NULL,
     817             :                            writefds ? ldpw->wr_bitmap : NULL,
     818             :                            exceptfds ? ldpw->ex_bitmap : NULL, vcl_timeout);
     819    26430600 :           if (rv < 0)
     820             :             {
     821           0 :               errno = -rv;
     822           0 :               rv = -1;
     823           0 :               goto done;
     824             :             }
     825    26430600 :           else if (rv > 0)
     826             :             {
     827      438351 :               if (ldp_select_vcl_map_to_libc (ldpw->rd_bitmap, readfds))
     828             :                 {
     829           0 :                   rv = -1;
     830           0 :                   goto done;
     831             :                 }
     832             : 
     833      438351 :               if (ldp_select_vcl_map_to_libc (ldpw->wr_bitmap, writefds))
     834             :                 {
     835           0 :                   rv = -1;
     836           0 :                   goto done;
     837             :                 }
     838             : 
     839      438351 :               if (ldp_select_vcl_map_to_libc (ldpw->ex_bitmap, exceptfds))
     840             :                 {
     841           0 :                   rv = -1;
     842           0 :                   goto done;
     843             :                 }
     844      438351 :               bits_set = rv;
     845             :             }
     846             :         }
     847    26430600 :       if (libc_bits)
     848             :         {
     849           0 :           if (readfds)
     850           0 :             clib_memcpy_fast (ldpw->rd_bitmap, ldpw->libc_rd_bitmap,
     851           0 :                               vec_len (ldpw->libc_rd_bitmap) *
     852             :                               sizeof (clib_bitmap_t));
     853           0 :           if (writefds)
     854           0 :             clib_memcpy_fast (ldpw->wr_bitmap, ldpw->libc_wr_bitmap,
     855           0 :                               vec_len (ldpw->libc_wr_bitmap) *
     856             :                               sizeof (clib_bitmap_t));
     857           0 :           if (exceptfds)
     858           0 :             clib_memcpy_fast (ldpw->ex_bitmap, ldpw->libc_ex_bitmap,
     859           0 :                               vec_len (ldpw->libc_ex_bitmap) *
     860             :                               sizeof (clib_bitmap_t));
     861             : 
     862           0 :           rv = libc_pselect (libc_bits,
     863             :                              readfds ? (fd_set *) ldpw->rd_bitmap : NULL,
     864             :                              writefds ? (fd_set *) ldpw->wr_bitmap : NULL,
     865             :                              exceptfds ? (fd_set *) ldpw->ex_bitmap : NULL,
     866             :                              &libc_tspec, sigmask);
     867           0 :           if (rv > 0)
     868             :             {
     869           0 :               ldp_select_libc_map_merge (ldpw->rd_bitmap, readfds);
     870           0 :               ldp_select_libc_map_merge (ldpw->wr_bitmap, writefds);
     871           0 :               ldp_select_libc_map_merge (ldpw->ex_bitmap, exceptfds);
     872           0 :               bits_set += rv;
     873             :             }
     874             :         }
     875             : 
     876    26430600 :       if (bits_set)
     877             :         {
     878      438351 :           rv = bits_set;
     879      438351 :           goto done;
     880             :         }
     881             :     }
     882    25992300 :   while ((time_out == -1) || (clib_time_now (&ldpw->clib_time) < time_out));
     883        3363 :   rv = 0;
     884             : 
     885      441714 : done:
     886             :   /* TBD: set timeout to amount of time left */
     887      441714 :   clib_bitmap_zero (ldpw->rd_bitmap);
     888      441714 :   clib_bitmap_zero (ldpw->si_rd_bitmap);
     889      441714 :   clib_bitmap_zero (ldpw->libc_rd_bitmap);
     890      441714 :   clib_bitmap_zero (ldpw->wr_bitmap);
     891      441714 :   clib_bitmap_zero (ldpw->si_wr_bitmap);
     892      441714 :   clib_bitmap_zero (ldpw->libc_wr_bitmap);
     893      441714 :   clib_bitmap_zero (ldpw->ex_bitmap);
     894      441714 :   clib_bitmap_zero (ldpw->si_ex_bitmap);
     895      441714 :   clib_bitmap_zero (ldpw->libc_ex_bitmap);
     896             : 
     897      441714 :   return rv;
     898             : }
     899             : 
     900             : int
     901             : select (int nfds, fd_set * __restrict readfds,
     902             :         fd_set * __restrict writefds,
     903             :         fd_set * __restrict exceptfds, struct timeval *__restrict timeout)
     904             : {
     905             :   struct timespec tspec;
     906             : 
     907      441719 :   if (timeout)
     908             :     {
     909      441569 :       tspec.tv_sec = timeout->tv_sec;
     910      441569 :       tspec.tv_nsec = timeout->tv_usec * 1000;
     911             :     }
     912      441719 :   return ldp_pselect (nfds, readfds, writefds, exceptfds,
     913             :                       timeout ? &tspec : NULL, NULL);
     914             : }
     915             : 
     916             : #ifdef __USE_XOPEN2K
     917             : int
     918             : pselect (int nfds, fd_set * __restrict readfds,
     919             :          fd_set * __restrict writefds,
     920             :          fd_set * __restrict exceptfds,
     921             :          const struct timespec *__restrict timeout,
     922             :          const __sigset_t * __restrict sigmask)
     923             : {
     924           0 :   return ldp_pselect (nfds, readfds, writefds, exceptfds, timeout, 0);
     925             : }
     926             : #endif
     927             : 
     928             : /* If transparent TLS mode is turned on, then ldp will load key and cert.
     929             :  */
     930             : static int
     931           0 : load_cert_key_pair (void)
     932             : {
     933           0 :   char *cert_str = getenv (LDP_ENV_TLS_CERT);
     934           0 :   char *key_str = getenv (LDP_ENV_TLS_KEY);
     935             :   char cert_buf[4096], key_buf[4096];
     936             :   int cert_size, key_size;
     937             :   vppcom_cert_key_pair_t crypto;
     938             :   int ckp_index;
     939             :   FILE *fp;
     940             : 
     941           0 :   if (!cert_str || !key_str)
     942             :     {
     943           0 :       LDBG (0, "ERROR: failed to read LDP environment %s\n",
     944             :             LDP_ENV_TLS_CERT);
     945           0 :       return -1;
     946             :     }
     947             : 
     948           0 :   fp = fopen (cert_str, "r");
     949           0 :   if (fp == NULL)
     950             :     {
     951           0 :       LDBG (0, "ERROR: failed to open cert file %s \n", cert_str);
     952           0 :       return -1;
     953             :     }
     954           0 :   cert_size = fread (cert_buf, sizeof (char), sizeof (cert_buf), fp);
     955           0 :   fclose (fp);
     956             : 
     957           0 :   fp = fopen (key_str, "r");
     958           0 :   if (fp == NULL)
     959             :     {
     960           0 :       LDBG (0, "ERROR: failed to open key file %s \n", key_str);
     961           0 :       return -1;
     962             :     }
     963           0 :   key_size = fread (key_buf, sizeof (char), sizeof (key_buf), fp);
     964           0 :   fclose (fp);
     965             : 
     966           0 :   crypto.cert = cert_buf;
     967           0 :   crypto.key = key_buf;
     968           0 :   crypto.cert_len = cert_size;
     969           0 :   crypto.key_len = key_size;
     970           0 :   ckp_index = vppcom_add_cert_key_pair (&crypto);
     971           0 :   if (ckp_index < 0)
     972             :     {
     973           0 :       LDBG (0, "ERROR: failed to add cert key pair\n");
     974           0 :       return -1;
     975             :     }
     976             : 
     977           0 :   ldp->ckpair_index = ckp_index;
     978             : 
     979           0 :   return 0;
     980             : }
     981             : 
     982             : static int
     983           0 : assign_cert_key_pair (vls_handle_t vlsh)
     984             : {
     985             :   uint32_t ckp_len;
     986             : 
     987           0 :   if (ldp->ckpair_index == ~0 && load_cert_key_pair () < 0)
     988           0 :     return -1;
     989             : 
     990           0 :   ckp_len = sizeof (ldp->ckpair_index);
     991           0 :   return vls_attr (vlsh, VPPCOM_ATTR_SET_CKPAIR, &ldp->ckpair_index, &ckp_len);
     992             : }
     993             : 
     994             : int
     995             : socket (int domain, int type, int protocol)
     996             : {
     997          49 :   int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
     998          49 :   u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0;
     999             :   vls_handle_t vlsh;
    1000             : 
    1001          49 :   ldp_init_check ();
    1002             : 
    1003          49 :   if (((domain == AF_INET) || (domain == AF_INET6)) &&
    1004           5 :       ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
    1005          35 :     {
    1006             :       u8 proto;
    1007          35 :       if (ldp->transparent_tls)
    1008             :         {
    1009           0 :           proto = VPPCOM_PROTO_TLS;
    1010             :         }
    1011             :       else
    1012          35 :         proto = ((sock_type == SOCK_DGRAM) ?
    1013          35 :                  VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP);
    1014             : 
    1015          35 :       LDBG (0, "calling vls_create: proto %u (%s), is_nonblocking %u",
    1016             :             proto, vppcom_proto_str (proto), is_nonblocking);
    1017             : 
    1018          35 :       vlsh = vls_create (proto, is_nonblocking);
    1019          35 :       if (vlsh < 0)
    1020             :         {
    1021           0 :           errno = -vlsh;
    1022           0 :           rv = -1;
    1023             :         }
    1024             :       else
    1025             :         {
    1026          35 :           if (ldp->transparent_tls)
    1027             :             {
    1028           0 :               if (assign_cert_key_pair (vlsh) < 0)
    1029           0 :                 return -1;
    1030             :             }
    1031          35 :           rv = ldp_vlsh_to_fd (vlsh);
    1032             :         }
    1033             :     }
    1034             :   else
    1035             :     {
    1036          14 :       LDBG (0, "calling libc_socket");
    1037          14 :       rv = libc_socket (domain, type, protocol);
    1038             :     }
    1039             : 
    1040          49 :   return rv;
    1041             : }
    1042             : 
    1043             : /*
    1044             :  * Create two new sockets, of type TYPE in domain DOMAIN and using
    1045             :  * protocol PROTOCOL, which are connected to each other, and put file
    1046             :  * descriptors for them in FDS[0] and FDS[1].  If PROTOCOL is zero,
    1047             :  * one will be chosen automatically.
    1048             :  * Returns 0 on success, -1 for errors.
    1049             :  * */
    1050             : int
    1051             : socketpair (int domain, int type, int protocol, int fds[2])
    1052             : {
    1053           0 :   int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
    1054             : 
    1055           0 :   ldp_init_check ();
    1056             : 
    1057           0 :   if (((domain == AF_INET) || (domain == AF_INET6)) &&
    1058           0 :       ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
    1059             :     {
    1060           0 :       LDBG (0, "LDP-TBD");
    1061           0 :       errno = ENOSYS;
    1062           0 :       rv = -1;
    1063             :     }
    1064             :   else
    1065             :     {
    1066           0 :       LDBG (1, "calling libc_socketpair");
    1067           0 :       rv = libc_socketpair (domain, type, protocol, fds);
    1068             :     }
    1069             : 
    1070           0 :   return rv;
    1071             : }
    1072             : 
    1073             : int
    1074             : bind (int fd, __CONST_SOCKADDR_ARG _addr, socklen_t len)
    1075             : {
    1076          17 :   const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
    1077             :   vls_handle_t vlsh;
    1078             :   int rv;
    1079             : 
    1080          17 :   ldp_init_check ();
    1081             : 
    1082          17 :   vlsh = ldp_fd_to_vlsh (fd);
    1083          17 :   if (vlsh != VLS_INVALID_HANDLE)
    1084             :     {
    1085             :       vppcom_endpt_t ep;
    1086             : 
    1087          16 :       switch (addr->sa_family)
    1088             :         {
    1089          14 :         case AF_INET:
    1090          14 :           if (len != sizeof (struct sockaddr_in))
    1091             :             {
    1092           0 :               LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET addr len %u!",
    1093             :                     fd, vlsh, len);
    1094           0 :               errno = EINVAL;
    1095           0 :               rv = -1;
    1096           0 :               goto done;
    1097             :             }
    1098          14 :           ep.is_ip4 = VPPCOM_IS_IP4;
    1099          14 :           ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
    1100          14 :           ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
    1101          14 :           break;
    1102             : 
    1103           2 :         case AF_INET6:
    1104           2 :           if (len != sizeof (struct sockaddr_in6))
    1105             :             {
    1106           0 :               LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET6 addr len %u!",
    1107             :                     fd, vlsh, len);
    1108           0 :               errno = EINVAL;
    1109           0 :               rv = -1;
    1110           0 :               goto done;
    1111             :             }
    1112           2 :           ep.is_ip4 = VPPCOM_IS_IP6;
    1113           2 :           ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
    1114           2 :           ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
    1115           2 :           break;
    1116             : 
    1117           0 :         default:
    1118           0 :           LDBG (0, "ERROR: fd %d: vlsh %u: Unsupported address family %u!",
    1119             :                 fd, vlsh, addr->sa_family);
    1120           0 :           errno = EAFNOSUPPORT;
    1121           0 :           rv = -1;
    1122           0 :           goto done;
    1123             :         }
    1124          16 :       LDBG (0, "fd %d: calling vls_bind: vlsh %u, addr %p, len %u", fd, vlsh,
    1125             :             addr, len);
    1126             : 
    1127          16 :       rv = vls_bind (vlsh, &ep);
    1128          16 :       if (rv != VPPCOM_OK)
    1129             :         {
    1130           0 :           errno = -rv;
    1131           0 :           rv = -1;
    1132             :         }
    1133             :     }
    1134             :   else
    1135             :     {
    1136           1 :       LDBG (0, "fd %d: calling libc_bind: addr %p, len %u", fd, addr, len);
    1137           1 :       rv = libc_bind (fd, addr, len);
    1138             :     }
    1139             : 
    1140          17 : done:
    1141          17 :   LDBG (1, "fd %d: returning %d", fd, rv);
    1142             : 
    1143          17 :   return rv;
    1144             : }
    1145             : 
    1146             : static inline int
    1147          59 : ldp_copy_ep_to_sockaddr (struct sockaddr *addr, socklen_t *__restrict len,
    1148             :                          vppcom_endpt_t *ep)
    1149             : {
    1150          59 :   int rv = 0, sa_len, copy_len;
    1151             : 
    1152          59 :   ldp_init_check ();
    1153             : 
    1154          59 :   if (addr && len && ep)
    1155             :     {
    1156          57 :       addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
    1157          57 :       switch (addr->sa_family)
    1158             :         {
    1159          47 :         case AF_INET:
    1160          47 :           ((struct sockaddr_in *) addr)->sin_port = ep->port;
    1161          47 :           if (*len > sizeof (struct sockaddr_in))
    1162          47 :             *len = sizeof (struct sockaddr_in);
    1163          47 :           sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
    1164          47 :           copy_len = *len - sa_len;
    1165          47 :           if (copy_len > 0)
    1166          47 :             memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
    1167             :                     copy_len);
    1168          47 :           break;
    1169             : 
    1170          10 :         case AF_INET6:
    1171          10 :           ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
    1172          10 :           if (*len > sizeof (struct sockaddr_in6))
    1173          10 :             *len = sizeof (struct sockaddr_in6);
    1174          10 :           sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
    1175          10 :           copy_len = *len - sa_len;
    1176          10 :           if (copy_len > 0)
    1177          10 :             memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
    1178          10 :                     __in6_u.__u6_addr8, ep->ip, copy_len);
    1179          10 :           break;
    1180             : 
    1181           0 :         default:
    1182             :           /* Not possible */
    1183           0 :           rv = -EAFNOSUPPORT;
    1184           0 :           break;
    1185             :         }
    1186           2 :     }
    1187          59 :   return rv;
    1188             : }
    1189             : 
    1190             : int
    1191             : getsockname (int fd, __SOCKADDR_ARG _addr, socklen_t *__restrict len)
    1192             : {
    1193          29 :   struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
    1194             :   vls_handle_t vlsh;
    1195             :   int rv;
    1196             : 
    1197          29 :   ldp_init_check ();
    1198             : 
    1199          29 :   vlsh = ldp_fd_to_vlsh (fd);
    1200          29 :   if (vlsh != VLS_INVALID_HANDLE)
    1201             :     {
    1202             :       vppcom_endpt_t ep;
    1203             :       u8 addr_buf[sizeof (struct in6_addr)];
    1204          29 :       u32 size = sizeof (ep);
    1205             : 
    1206          29 :       ep.ip = addr_buf;
    1207             : 
    1208          29 :       rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
    1209          29 :       if (rv != VPPCOM_OK)
    1210             :         {
    1211           0 :           errno = -rv;
    1212           0 :           rv = -1;
    1213             :         }
    1214             :       else
    1215             :         {
    1216          29 :           rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
    1217          29 :           if (rv != VPPCOM_OK)
    1218             :             {
    1219           0 :               errno = -rv;
    1220           0 :               rv = -1;
    1221             :             }
    1222             :         }
    1223             :     }
    1224             :   else
    1225             :     {
    1226           0 :       rv = libc_getsockname (fd, _addr, len);
    1227             :     }
    1228             : 
    1229          29 :   return rv;
    1230             : }
    1231             : 
    1232             : int
    1233             : connect (int fd, __CONST_SOCKADDR_ARG _addr, socklen_t len)
    1234             : {
    1235          34 :   const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
    1236             :   vls_handle_t vlsh;
    1237             :   int rv;
    1238             : 
    1239          34 :   ldp_init_check ();
    1240             : 
    1241          34 :   if (!addr)
    1242             :     {
    1243           0 :       LDBG (0, "ERROR: fd %d: NULL addr, len %u", fd, len);
    1244           0 :       errno = EINVAL;
    1245           0 :       rv = -1;
    1246           0 :       goto done;
    1247             :     }
    1248             : 
    1249          34 :   vlsh = ldp_fd_to_vlsh (fd);
    1250          34 :   if (vlsh != VLS_INVALID_HANDLE)
    1251             :     {
    1252             :       vppcom_endpt_t ep;
    1253             : 
    1254          21 :       switch (addr->sa_family)
    1255             :         {
    1256          19 :         case AF_INET:
    1257          19 :           if (len != sizeof (struct sockaddr_in))
    1258             :             {
    1259           0 :               LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET addr len %u!",
    1260             :                     fd, vlsh, len);
    1261           0 :               errno = EINVAL;
    1262           0 :               rv = -1;
    1263           0 :               goto done;
    1264             :             }
    1265          19 :           ep.is_ip4 = VPPCOM_IS_IP4;
    1266          19 :           ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
    1267          19 :           ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
    1268          19 :           break;
    1269             : 
    1270           2 :         case AF_INET6:
    1271           2 :           if (len != sizeof (struct sockaddr_in6))
    1272             :             {
    1273           0 :               LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET6 addr len %u!",
    1274             :                     fd, vlsh, len);
    1275           0 :               errno = EINVAL;
    1276           0 :               rv = -1;
    1277           0 :               goto done;
    1278             :             }
    1279           2 :           ep.is_ip4 = VPPCOM_IS_IP6;
    1280           2 :           ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
    1281           2 :           ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
    1282           2 :           break;
    1283             : 
    1284           0 :         default:
    1285           0 :           LDBG (0, "fd %d: ERROR vlsh %u: Unsupported address family %u!",
    1286             :                 fd, vlsh, addr->sa_family);
    1287           0 :           errno = EAFNOSUPPORT;
    1288           0 :           rv = -1;
    1289           0 :           goto done;
    1290             :         }
    1291          21 :       LDBG (0, "fd %d: calling vls_connect(): vlsh %u addr %p len %u", fd,
    1292             :             vlsh, addr, len);
    1293             : 
    1294          21 :       rv = vls_connect (vlsh, &ep);
    1295          21 :       if (rv != VPPCOM_OK)
    1296             :         {
    1297           0 :           errno = -rv;
    1298           0 :           rv = -1;
    1299             :         }
    1300             :     }
    1301             :   else
    1302             :     {
    1303          13 :       LDBG (0, "fd %d: calling libc_connect(): addr %p, len %u",
    1304             :             fd, addr, len);
    1305             : 
    1306          13 :       rv = libc_connect (fd, addr, len);
    1307             :     }
    1308             : 
    1309          34 : done:
    1310          34 :   LDBG (1, "fd %d: returning %d (0x%x)", fd, rv, rv);
    1311          34 :   return rv;
    1312             : }
    1313             : 
    1314             : int
    1315             : getpeername (int fd, __SOCKADDR_ARG _addr, socklen_t *__restrict len)
    1316             : {
    1317          17 :   struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
    1318             :   vls_handle_t vlsh;
    1319             :   int rv;
    1320             : 
    1321          17 :   ldp_init_check ();
    1322             : 
    1323          17 :   vlsh = ldp_fd_to_vlsh (fd);
    1324          17 :   if (vlsh != VLS_INVALID_HANDLE)
    1325             :     {
    1326             :       vppcom_endpt_t ep;
    1327             :       u8 addr_buf[sizeof (struct in6_addr)];
    1328          17 :       u32 size = sizeof (ep);
    1329             : 
    1330          17 :       ep.ip = addr_buf;
    1331          17 :       rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size);
    1332          17 :       if (rv != VPPCOM_OK)
    1333             :         {
    1334           0 :           errno = -rv;
    1335           0 :           rv = -1;
    1336             :         }
    1337             :       else
    1338             :         {
    1339          17 :           rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
    1340          17 :           if (rv != VPPCOM_OK)
    1341             :             {
    1342           0 :               errno = -rv;
    1343           0 :               rv = -1;
    1344             :             }
    1345             :         }
    1346             :     }
    1347             :   else
    1348             :     {
    1349           0 :       rv = libc_getpeername (fd, addr, len);
    1350             :     }
    1351             : 
    1352          17 :   return rv;
    1353             : }
    1354             : 
    1355             : ssize_t
    1356             : send (int fd, const void *buf, size_t n, int flags)
    1357             : {
    1358           0 :   vls_handle_t vlsh = ldp_fd_to_vlsh (fd);
    1359             :   ssize_t size;
    1360             : 
    1361           0 :   ldp_init_check ();
    1362             : 
    1363           0 :   if (vlsh != VLS_INVALID_HANDLE)
    1364             :     {
    1365           0 :       size = vls_sendto (vlsh, (void *) buf, n, flags, NULL);
    1366           0 :       if (size < VPPCOM_OK)
    1367             :         {
    1368           0 :           errno = -size;
    1369           0 :           size = -1;
    1370             :         }
    1371             :     }
    1372             :   else
    1373             :     {
    1374           0 :       size = libc_send (fd, buf, n, flags);
    1375             :     }
    1376             : 
    1377           0 :   return size;
    1378             : }
    1379             : 
    1380             : ssize_t
    1381           0 : sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
    1382             : {
    1383           0 :   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
    1384             :   vls_handle_t vlsh;
    1385           0 :   ssize_t size = 0;
    1386             : 
    1387           0 :   ldp_init_check ();
    1388             : 
    1389           0 :   vlsh = ldp_fd_to_vlsh (out_fd);
    1390           0 :   if (vlsh != VLS_INVALID_HANDLE)
    1391             :     {
    1392             :       int rv;
    1393           0 :       ssize_t results = 0;
    1394           0 :       size_t n_bytes_left = len;
    1395             :       size_t bytes_to_read;
    1396             :       int nbytes;
    1397           0 :       u8 eagain = 0;
    1398           0 :       u32 flags, flags_len = sizeof (flags);
    1399             : 
    1400           0 :       rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &flags_len);
    1401           0 :       if (PREDICT_FALSE (rv != VPPCOM_OK))
    1402             :         {
    1403           0 :           LDBG (0, "ERROR: out fd %d: vls_attr: vlsh %u, returned %d (%s)!",
    1404             :                 out_fd, vlsh, rv, vppcom_retval_str (rv));
    1405             : 
    1406           0 :           vec_reset_length (ldpw->io_buffer);
    1407           0 :           errno = -rv;
    1408           0 :           size = -1;
    1409           0 :           goto done;
    1410             :         }
    1411             : 
    1412           0 :       if (offset)
    1413             :         {
    1414           0 :           off_t off = lseek (in_fd, *offset, SEEK_SET);
    1415           0 :           if (PREDICT_FALSE (off == -1))
    1416             :             {
    1417           0 :               size = -1;
    1418           0 :               goto done;
    1419             :             }
    1420             : 
    1421           0 :           ASSERT (off == *offset);
    1422             :         }
    1423             : 
    1424             :       do
    1425             :         {
    1426           0 :           size = vls_attr (vlsh, VPPCOM_ATTR_GET_NWRITE, 0, 0);
    1427           0 :           if (size < 0)
    1428             :             {
    1429           0 :               LDBG (0, "ERROR: fd %d: vls_attr: vlsh %u returned %ld (%s)!",
    1430             :                     out_fd, vlsh, size, vppcom_retval_str (size));
    1431           0 :               vec_reset_length (ldpw->io_buffer);
    1432           0 :               errno = -size;
    1433           0 :               size = -1;
    1434           0 :               goto done;
    1435             :             }
    1436             : 
    1437           0 :           bytes_to_read = size;
    1438           0 :           if (bytes_to_read == 0)
    1439             :             {
    1440           0 :               if (flags & O_NONBLOCK)
    1441             :                 {
    1442           0 :                   if (!results)
    1443           0 :                     eagain = 1;
    1444           0 :                   goto update_offset;
    1445             :                 }
    1446             :               else
    1447           0 :                 continue;
    1448             :             }
    1449           0 :           bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
    1450           0 :           vec_validate (ldpw->io_buffer, bytes_to_read);
    1451           0 :           nbytes = libc_read (in_fd, ldpw->io_buffer, bytes_to_read);
    1452           0 :           if (nbytes < 0)
    1453             :             {
    1454           0 :               if (results == 0)
    1455             :                 {
    1456           0 :                   vec_reset_length (ldpw->io_buffer);
    1457           0 :                   size = -1;
    1458           0 :                   goto done;
    1459             :                 }
    1460           0 :               goto update_offset;
    1461             :             }
    1462             : 
    1463           0 :           size = vls_write (vlsh, ldpw->io_buffer, nbytes);
    1464           0 :           if (size < 0)
    1465             :             {
    1466           0 :               if (size == VPPCOM_EAGAIN)
    1467             :                 {
    1468           0 :                   if (flags & O_NONBLOCK)
    1469             :                     {
    1470           0 :                       if (!results)
    1471           0 :                         eagain = 1;
    1472           0 :                       goto update_offset;
    1473             :                     }
    1474             :                   else
    1475           0 :                     continue;
    1476             :                 }
    1477           0 :               if (results == 0)
    1478             :                 {
    1479           0 :                   vec_reset_length (ldpw->io_buffer);
    1480           0 :                   errno = -size;
    1481           0 :                   size = -1;
    1482           0 :                   goto done;
    1483             :                 }
    1484           0 :               goto update_offset;
    1485             :             }
    1486             : 
    1487           0 :           results += nbytes;
    1488           0 :           ASSERT (n_bytes_left >= nbytes);
    1489           0 :           n_bytes_left = n_bytes_left - nbytes;
    1490             :         }
    1491           0 :       while (n_bytes_left > 0);
    1492             : 
    1493           0 :     update_offset:
    1494           0 :       vec_reset_length (ldpw->io_buffer);
    1495           0 :       if (offset)
    1496             :         {
    1497           0 :           off_t off = lseek (in_fd, *offset, SEEK_SET);
    1498           0 :           if (PREDICT_FALSE (off == -1))
    1499             :             {
    1500           0 :               size = -1;
    1501           0 :               goto done;
    1502             :             }
    1503             : 
    1504           0 :           ASSERT (off == *offset);
    1505           0 :           *offset += results + 1;
    1506             :         }
    1507           0 :       if (eagain)
    1508             :         {
    1509           0 :           errno = EAGAIN;
    1510           0 :           size = -1;
    1511             :         }
    1512             :       else
    1513           0 :         size = results;
    1514             :     }
    1515             :   else
    1516             :     {
    1517           0 :       size = libc_sendfile (out_fd, in_fd, offset, len);
    1518             :     }
    1519             : 
    1520           0 : done:
    1521           0 :   return size;
    1522             : }
    1523             : 
    1524             : ssize_t
    1525           0 : sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len)
    1526             : {
    1527           0 :   return sendfile (out_fd, in_fd, offset, len);
    1528             : }
    1529             : 
    1530             : ssize_t
    1531             : recv (int fd, void *buf, size_t n, int flags)
    1532             : {
    1533             :   vls_handle_t vlsh;
    1534             :   ssize_t size;
    1535             : 
    1536           2 :   ldp_init_check ();
    1537             : 
    1538           2 :   vlsh = ldp_fd_to_vlsh (fd);
    1539           2 :   if (vlsh != VLS_INVALID_HANDLE)
    1540             :     {
    1541           2 :       size = vls_recvfrom (vlsh, buf, n, flags, NULL);
    1542           2 :       if (size < 0)
    1543             :         {
    1544           0 :           errno = -size;
    1545           0 :           size = -1;
    1546             :         }
    1547             :     }
    1548             :   else
    1549             :     {
    1550           0 :       size = libc_recv (fd, buf, n, flags);
    1551             :     }
    1552             : 
    1553           2 :   return size;
    1554             : }
    1555             : 
    1556             : ssize_t
    1557           0 : __recv_chk (int fd, void *buf, size_t n, size_t buflen, int flags)
    1558             : {
    1559           0 :   if (n > buflen)
    1560           0 :     return -1;
    1561             : 
    1562           0 :   return recv (fd, buf, n, flags);
    1563             : }
    1564             : 
    1565             : static inline int
    1566           0 : ldp_vls_sendo (vls_handle_t vlsh, const void *buf, size_t n,
    1567             :                vppcom_endpt_tlv_t *app_tlvs, int flags,
    1568             :                __CONST_SOCKADDR_ARG _addr, socklen_t addr_len)
    1569             : {
    1570           0 :   const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
    1571           0 :   vppcom_endpt_t *ep = 0;
    1572             :   vppcom_endpt_t _ep;
    1573             : 
    1574           0 :   _ep.app_tlvs = app_tlvs;
    1575             : 
    1576           0 :   if (addr)
    1577             :     {
    1578           0 :       ep = &_ep;
    1579           0 :       switch (addr->sa_family)
    1580             :         {
    1581           0 :         case AF_INET:
    1582           0 :           ep->is_ip4 = VPPCOM_IS_IP4;
    1583           0 :           ep->ip =
    1584           0 :             (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr;
    1585           0 :           ep->port = (uint16_t) ((const struct sockaddr_in *) addr)->sin_port;
    1586           0 :           break;
    1587             : 
    1588           0 :         case AF_INET6:
    1589           0 :           ep->is_ip4 = VPPCOM_IS_IP6;
    1590           0 :           ep->ip =
    1591           0 :             (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
    1592           0 :           ep->port =
    1593           0 :             (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port;
    1594           0 :           break;
    1595             : 
    1596           0 :         default:
    1597           0 :           return EAFNOSUPPORT;
    1598             :         }
    1599           0 :     }
    1600             : 
    1601           0 :   return vls_sendto (vlsh, (void *) buf, n, flags, ep);
    1602             : }
    1603             : 
    1604             : static int
    1605           2 : ldp_vls_recvfrom (vls_handle_t vlsh, void *__restrict buf, size_t n, int flags,
    1606             :                   __SOCKADDR_ARG _addr, socklen_t *__restrict addr_len)
    1607             : {
    1608             :   u8 src_addr[sizeof (struct sockaddr_in6)];
    1609           2 :   struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
    1610             :   vppcom_endpt_t ep;
    1611             :   ssize_t size;
    1612             :   int rv;
    1613             : 
    1614           2 :   if (addr)
    1615             :     {
    1616           2 :       ep.ip = src_addr;
    1617           2 :       size = vls_recvfrom (vlsh, buf, n, flags, &ep);
    1618             : 
    1619           2 :       if (size > 0)
    1620             :         {
    1621           2 :           rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
    1622           2 :           if (rv < 0)
    1623           0 :             size = rv;
    1624             :         }
    1625             :     }
    1626             :   else
    1627           0 :     size = vls_recvfrom (vlsh, buf, n, flags, NULL);
    1628             : 
    1629           2 :   return size;
    1630             : }
    1631             : 
    1632             : ssize_t
    1633             : sendto (int fd, const void *buf, size_t n, int flags,
    1634             :         __CONST_SOCKADDR_ARG _addr, socklen_t addr_len)
    1635             : {
    1636           0 :   const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
    1637             :   vls_handle_t vlsh;
    1638             :   ssize_t size;
    1639             : 
    1640           0 :   ldp_init_check ();
    1641             : 
    1642           0 :   vlsh = ldp_fd_to_vlsh (fd);
    1643           0 :   if (vlsh != VLS_INVALID_HANDLE)
    1644             :     {
    1645           0 :       size = ldp_vls_sendo (vlsh, buf, n, NULL, flags, addr, addr_len);
    1646           0 :       if (size < 0)
    1647             :         {
    1648           0 :           errno = -size;
    1649           0 :           size = -1;
    1650             :         }
    1651             :     }
    1652             :   else
    1653             :     {
    1654           0 :       size = libc_sendto (fd, buf, n, flags, addr, addr_len);
    1655             :     }
    1656             : 
    1657           0 :   return size;
    1658             : }
    1659             : 
    1660             : ssize_t
    1661             : recvfrom (int fd, void *__restrict buf, size_t n, int flags,
    1662             :           __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
    1663             : {
    1664             :   vls_handle_t vlsh;
    1665             :   ssize_t size;
    1666             : 
    1667           2 :   ldp_init_check ();
    1668             : 
    1669           2 :   vlsh = ldp_fd_to_vlsh (fd);
    1670           2 :   if (vlsh != VLS_INVALID_HANDLE)
    1671             :     {
    1672           2 :       size = ldp_vls_recvfrom (vlsh, buf, n, flags, addr, addr_len);
    1673           2 :       if (size < 0)
    1674             :         {
    1675           0 :           errno = -size;
    1676           0 :           size = -1;
    1677             :         }
    1678             :     }
    1679             :   else
    1680             :     {
    1681           0 :       size = libc_recvfrom (fd, buf, n, flags, addr, addr_len);
    1682             :     }
    1683             : 
    1684           2 :   return size;
    1685             : }
    1686             : 
    1687             : static int
    1688           0 : ldp_parse_cmsg (vls_handle_t vlsh, const struct msghdr *msg,
    1689             :                 vppcom_endpt_tlv_t **app_tlvs)
    1690             : {
    1691           0 :   uint8_t *ad, *at = (uint8_t *) *app_tlvs;
    1692             :   vppcom_endpt_tlv_t *adh;
    1693             :   struct in_pktinfo *pi;
    1694             :   struct cmsghdr *cmsg;
    1695             : 
    1696           0 :   cmsg = CMSG_FIRSTHDR (msg);
    1697             : 
    1698           0 :   while (cmsg != NULL)
    1699             :     {
    1700           0 :       switch (cmsg->cmsg_level)
    1701             :         {
    1702           0 :         case SOL_UDP:
    1703           0 :           switch (cmsg->cmsg_type)
    1704             :             {
    1705           0 :             case UDP_SEGMENT:
    1706           0 :               vec_add2 (at, adh, sizeof (*adh));
    1707           0 :               adh->data_type = VCL_UDP_SEGMENT;
    1708           0 :               adh->data_len = sizeof (uint16_t);
    1709           0 :               vec_add2 (at, ad, sizeof (uint16_t));
    1710           0 :               *(uint16_t *) ad = *(uint16_t *) CMSG_DATA (cmsg);
    1711           0 :               break;
    1712           0 :             default:
    1713           0 :               LDBG (1, "SOL_UDP cmsg_type %u not supported", cmsg->cmsg_type);
    1714           0 :               break;
    1715             :             }
    1716           0 :           break;
    1717           0 :         case SOL_IP:
    1718           0 :           switch (cmsg->cmsg_type)
    1719             :             {
    1720           0 :             case IP_PKTINFO:
    1721           0 :               vec_add2 (at, adh, sizeof (*adh));
    1722           0 :               adh->data_type = VCL_IP_PKTINFO;
    1723           0 :               adh->data_len = sizeof (struct in_addr);
    1724           0 :               vec_add2 (at, ad, sizeof (struct in_addr));
    1725           0 :               pi = (void *) CMSG_DATA (cmsg);
    1726           0 :               clib_memcpy_fast (ad, &pi->ipi_spec_dst,
    1727             :                                 sizeof (struct in_addr));
    1728           0 :               break;
    1729           0 :             default:
    1730           0 :               LDBG (1, "SOL_IP cmsg_type %u not supported", cmsg->cmsg_type);
    1731           0 :               break;
    1732             :             }
    1733           0 :           break;
    1734           0 :         default:
    1735           0 :           LDBG (1, "cmsg_level %u not supported", cmsg->cmsg_level);
    1736           0 :           break;
    1737             :         }
    1738           0 :       cmsg = CMSG_NXTHDR ((struct msghdr *) msg, cmsg);
    1739             :     }
    1740           0 :   *app_tlvs = (vppcom_endpt_tlv_t *) at;
    1741           0 :   return 0;
    1742             : }
    1743             : 
    1744             : static int
    1745           0 : ldp_make_cmsg (vls_handle_t vlsh, struct msghdr *msg)
    1746             : {
    1747           0 :   u32 optval, optlen = sizeof (optval);
    1748             :   struct cmsghdr *cmsg;
    1749             : 
    1750           0 :   cmsg = CMSG_FIRSTHDR (msg);
    1751             : 
    1752           0 :   if (!vls_attr (vlsh, VPPCOM_ATTR_GET_IP_PKTINFO, (void *) &optval, &optlen))
    1753           0 :     return 0;
    1754             : 
    1755           0 :   if (optval)
    1756             :     {
    1757             :       vppcom_endpt_t ep;
    1758             :       u8 addr_buf[sizeof (struct in_addr)];
    1759           0 :       u32 size = sizeof (ep);
    1760             : 
    1761           0 :       ep.ip = addr_buf;
    1762             : 
    1763           0 :       if (!vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size))
    1764             :         {
    1765           0 :           struct in_pktinfo pi = {};
    1766             : 
    1767           0 :           clib_memcpy (&pi.ipi_addr, ep.ip, sizeof (struct in_addr));
    1768           0 :           cmsg->cmsg_level = SOL_IP;
    1769           0 :           cmsg->cmsg_type = IP_PKTINFO;
    1770           0 :           cmsg->cmsg_len = CMSG_LEN (sizeof (pi));
    1771           0 :           clib_memcpy (CMSG_DATA (cmsg), &pi, sizeof (pi));
    1772             :         }
    1773             :     }
    1774             : 
    1775           0 :   return 0;
    1776             : }
    1777             : 
    1778             : ssize_t
    1779             : sendmsg (int fd, const struct msghdr * msg, int flags)
    1780             : {
    1781             :   vls_handle_t vlsh;
    1782             :   ssize_t size;
    1783             : 
    1784           2 :   ldp_init_check ();
    1785             : 
    1786           2 :   vlsh = ldp_fd_to_vlsh (fd);
    1787           2 :   if (vlsh != VLS_INVALID_HANDLE)
    1788             :     {
    1789           0 :       vppcom_endpt_tlv_t *app_tlvs = 0;
    1790           0 :       struct iovec *iov = msg->msg_iov;
    1791           0 :       ssize_t total = 0;
    1792           0 :       int i, rv = 0;
    1793             : 
    1794           0 :       ldp_parse_cmsg (vlsh, msg, &app_tlvs);
    1795             : 
    1796           0 :       for (i = 0; i < msg->msg_iovlen; ++i)
    1797             :         {
    1798           0 :           rv = ldp_vls_sendo (vlsh, iov[i].iov_base, iov[i].iov_len, app_tlvs,
    1799           0 :                               flags, msg->msg_name, msg->msg_namelen);
    1800           0 :           if (rv < 0)
    1801           0 :             break;
    1802             :           else
    1803             :             {
    1804           0 :               total += rv;
    1805           0 :               if (rv < iov[i].iov_len)
    1806           0 :                 break;
    1807             :             }
    1808             :         }
    1809             : 
    1810           0 :       vec_free (app_tlvs);
    1811             : 
    1812           0 :       if (rv < 0 && total == 0)
    1813             :         {
    1814           0 :           errno = -rv;
    1815           0 :           size = -1;
    1816             :         }
    1817             :       else
    1818           0 :         size = total;
    1819             :     }
    1820             :   else
    1821             :     {
    1822           2 :       size = libc_sendmsg (fd, msg, flags);
    1823             :     }
    1824             : 
    1825           2 :   return size;
    1826             : }
    1827             : 
    1828             : #ifdef _GNU_SOURCE
    1829             : int
    1830             : sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
    1831             : {
    1832             :   ssize_t size;
    1833             :   const char *func_str;
    1834           0 :   u32 sh = ldp_fd_to_vlsh (fd);
    1835             : 
    1836           0 :   ldp_init_check ();
    1837             : 
    1838           0 :   if (sh != VLS_INVALID_HANDLE)
    1839             :     {
    1840           0 :       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
    1841           0 :       errno = ENOSYS;
    1842           0 :       size = -1;
    1843             :     }
    1844             :   else
    1845             :     {
    1846           0 :       func_str = "libc_sendmmsg";
    1847             : 
    1848           0 :       if (LDP_DEBUG > 2)
    1849           0 :         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
    1850             :                       "vmessages %p, vlen %u, flags 0x%x",
    1851             :                       getpid (), fd, fd, func_str, vmessages, vlen, flags);
    1852             : 
    1853           0 :       size = libc_sendmmsg (fd, vmessages, vlen, flags);
    1854             :     }
    1855             : 
    1856           0 :   if (LDP_DEBUG > 2)
    1857             :     {
    1858           0 :       if (size < 0)
    1859             :         {
    1860           0 :           int errno_val = errno;
    1861           0 :           perror (func_str);
    1862           0 :           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
    1863             :                         "rv %d, errno = %d", getpid (), fd, fd,
    1864             :                         func_str, size, errno_val);
    1865           0 :           errno = errno_val;
    1866             :         }
    1867             :       else
    1868           0 :         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
    1869             :                       getpid (), fd, fd, size, size);
    1870             :     }
    1871           0 :   return size;
    1872             : }
    1873             : #endif
    1874             : 
    1875             : ssize_t
    1876             : recvmsg (int fd, struct msghdr * msg, int flags)
    1877             : {
    1878             :   vls_handle_t vlsh;
    1879             :   ssize_t size;
    1880             : 
    1881       32952 :   ldp_init_check ();
    1882             : 
    1883       32952 :   vlsh = ldp_fd_to_vlsh (fd);
    1884       32952 :   if (vlsh != VLS_INVALID_HANDLE)
    1885             :     {
    1886           0 :       struct iovec *iov = msg->msg_iov;
    1887           0 :       ssize_t max_deq, total = 0;
    1888             :       int i, rv;
    1889             : 
    1890           0 :       max_deq = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
    1891           0 :       if (!max_deq)
    1892           0 :         return 0;
    1893             : 
    1894           0 :       for (i = 0; i < msg->msg_iovlen; i++)
    1895             :         {
    1896           0 :           rv = ldp_vls_recvfrom (vlsh, iov[i].iov_base, iov[i].iov_len, flags,
    1897           0 :                                  (i == 0 ? msg->msg_name : NULL),
    1898             :                                  (i == 0 ? &msg->msg_namelen : NULL));
    1899           0 :           if (rv <= 0)
    1900           0 :             break;
    1901             :           else
    1902             :             {
    1903           0 :               total += rv;
    1904           0 :               if (rv < iov[i].iov_len)
    1905           0 :                 break;
    1906             :             }
    1907           0 :           if (total >= max_deq)
    1908           0 :             break;
    1909             :         }
    1910             : 
    1911           0 :       if (rv < 0 && total == 0)
    1912             :         {
    1913           0 :           errno = -rv;
    1914           0 :           size = -1;
    1915             :         }
    1916             :       else
    1917             :         {
    1918           0 :           if (msg->msg_controllen)
    1919           0 :             ldp_make_cmsg (vlsh, msg);
    1920           0 :           size = total;
    1921             :         }
    1922             :     }
    1923             :   else
    1924             :     {
    1925       32952 :       size = libc_recvmsg (fd, msg, flags);
    1926             :     }
    1927             : 
    1928       32952 :   return size;
    1929             : }
    1930             : 
    1931             : #ifdef _GNU_SOURCE
    1932             : int
    1933             : recvmmsg (int fd, struct mmsghdr *vmessages,
    1934             :           unsigned int vlen, int flags, struct timespec *tmo)
    1935             : {
    1936           0 :   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
    1937             :   u32 sh;
    1938             : 
    1939           0 :   ldp_init_check ();
    1940             : 
    1941           0 :   sh = ldp_fd_to_vlsh (fd);
    1942             : 
    1943           0 :   if (sh != VLS_INVALID_HANDLE)
    1944             :     {
    1945             :       struct mmsghdr *mh;
    1946           0 :       ssize_t rv = 0;
    1947           0 :       u32 nvecs = 0;
    1948             :       f64 time_out;
    1949             : 
    1950           0 :       if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
    1951           0 :         clib_time_init (&ldpw->clib_time);
    1952           0 :       if (tmo)
    1953             :         {
    1954           0 :           time_out = (f64) tmo->tv_sec + (f64) tmo->tv_nsec / (f64) 1e9;
    1955           0 :           time_out += clib_time_now (&ldpw->clib_time);
    1956             :         }
    1957             :       else
    1958             :         {
    1959           0 :           time_out = (f64) ~0;
    1960             :         }
    1961             : 
    1962           0 :       while (nvecs < vlen)
    1963             :         {
    1964           0 :           mh = &vmessages[nvecs];
    1965           0 :           rv = recvmsg (fd, &mh->msg_hdr, flags);
    1966           0 :           if (rv > 0)
    1967             :             {
    1968           0 :               mh->msg_len = rv;
    1969           0 :               nvecs += 1;
    1970           0 :               continue;
    1971             :             }
    1972             : 
    1973           0 :           if (!time_out || clib_time_now (&ldpw->clib_time) >= time_out)
    1974             :             break;
    1975             : 
    1976           0 :           usleep (1);
    1977             :         }
    1978             : 
    1979           0 :       return nvecs > 0 ? nvecs : rv;
    1980             :     }
    1981             :   else
    1982             :     {
    1983           0 :       return libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
    1984             :     }
    1985             : }
    1986             : #endif
    1987             : 
    1988             : int
    1989             : getsockopt (int fd, int level, int optname,
    1990             :             void *__restrict optval, socklen_t * __restrict optlen)
    1991             : {
    1992             :   vls_handle_t vlsh;
    1993             :   int rv;
    1994             : 
    1995          57 :   ldp_init_check ();
    1996             : 
    1997          57 :   vlsh = ldp_fd_to_vlsh (fd);
    1998          57 :   if (vlsh != VLS_INVALID_HANDLE)
    1999             :     {
    2000          57 :       rv = -EOPNOTSUPP;
    2001             : 
    2002          57 :       switch (level)
    2003             :         {
    2004          33 :         case SOL_TCP:
    2005             :           switch (optname)
    2006             :             {
    2007           0 :             case TCP_NODELAY:
    2008           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_NODELAY,
    2009             :                              optval, optlen);
    2010           0 :               break;
    2011           5 :             case TCP_MAXSEG:
    2012           5 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_USER_MSS,
    2013             :                              optval, optlen);
    2014           5 :               break;
    2015           0 :             case TCP_KEEPIDLE:
    2016           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
    2017             :                              optval, optlen);
    2018           0 :               break;
    2019           0 :             case TCP_KEEPINTVL:
    2020           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
    2021             :                              optval, optlen);
    2022           0 :               break;
    2023          20 :             case TCP_INFO:
    2024          20 :               if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
    2025             :                 {
    2026          20 :                   LDBG (1, "fd %d: vlsh %u SOL_TCP, TCP_INFO, optval %p, "
    2027             :                         "optlen %d: #LDP-NOP#", fd, vlsh, optval, *optlen);
    2028          20 :                   memset (optval, 0, *optlen);
    2029          20 :                   rv = VPPCOM_OK;
    2030             :                 }
    2031             :               else
    2032           0 :                 rv = -EFAULT;
    2033          20 :               break;
    2034           8 :             case TCP_CONGESTION:
    2035           8 :               *optlen = strlen ("cubic");
    2036           8 :               strncpy (optval, "cubic", *optlen + 1);
    2037           8 :               rv = 0;
    2038           8 :               break;
    2039           0 :             default:
    2040           0 :               LDBG (0, "ERROR: fd %d: getsockopt SOL_TCP: sid %u, "
    2041             :                     "optname %d unsupported!", fd, vlsh, optname);
    2042           0 :               break;
    2043             :             }
    2044          33 :           break;
    2045           0 :         case SOL_IPV6:
    2046             :           switch (optname)
    2047             :             {
    2048           0 :             case IPV6_V6ONLY:
    2049           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_V6ONLY, optval, optlen);
    2050           0 :               break;
    2051           0 :             default:
    2052           0 :               LDBG (0, "ERROR: fd %d: getsockopt SOL_IPV6: vlsh %u "
    2053             :                     "optname %d unsupported!", fd, vlsh, optname);
    2054           0 :               break;
    2055             :             }
    2056           0 :           break;
    2057          24 :         case SOL_SOCKET:
    2058             :           switch (optname)
    2059             :             {
    2060           0 :             case SO_ACCEPTCONN:
    2061           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LISTEN, optval, optlen);
    2062           0 :               break;
    2063           0 :             case SO_KEEPALIVE:
    2064           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_KEEPALIVE, optval, optlen);
    2065           0 :               break;
    2066           0 :             case SO_PROTOCOL:
    2067           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PROTOCOL, optval, optlen);
    2068           0 :               *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
    2069           0 :               break;
    2070          12 :             case SO_SNDBUF:
    2071          12 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TX_FIFO_LEN,
    2072             :                              optval, optlen);
    2073          12 :               break;
    2074          12 :             case SO_RCVBUF:
    2075          12 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_RX_FIFO_LEN,
    2076             :                              optval, optlen);
    2077          12 :               break;
    2078           0 :             case SO_REUSEADDR:
    2079           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEADDR, optval, optlen);
    2080           0 :               break;
    2081           0 :             case SO_REUSEPORT:
    2082           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEPORT, optval, optlen);
    2083           0 :               break;
    2084           0 :             case SO_BROADCAST:
    2085           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_BROADCAST, optval, optlen);
    2086           0 :               break;
    2087           0 :             case SO_DOMAIN:
    2088           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_DOMAIN, optval, optlen);
    2089           0 :               break;
    2090           0 :             case SO_ERROR:
    2091           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_ERROR, optval, optlen);
    2092           0 :               break;
    2093           0 :             case SO_BINDTODEVICE:
    2094           0 :               rv = 0;
    2095           0 :               break;
    2096           0 :             default:
    2097           0 :               LDBG (0, "ERROR: fd %d: getsockopt SOL_SOCKET: vlsh %u "
    2098             :                     "optname %d unsupported!", fd, vlsh, optname);
    2099           0 :               break;
    2100             :             }
    2101          24 :           break;
    2102           0 :         default:
    2103           0 :           break;
    2104             :         }
    2105             : 
    2106          57 :       if (rv != VPPCOM_OK)
    2107             :         {
    2108           2 :           errno = -rv;
    2109           2 :           rv = -1;
    2110             :         }
    2111             :     }
    2112             :   else
    2113             :     {
    2114           0 :       rv = libc_getsockopt (fd, level, optname, optval, optlen);
    2115             :     }
    2116             : 
    2117          57 :   return rv;
    2118             : }
    2119             : 
    2120             : int
    2121             : setsockopt (int fd, int level, int optname,
    2122             :             const void *optval, socklen_t optlen)
    2123             : {
    2124             :   vls_handle_t vlsh;
    2125             :   int rv;
    2126             : 
    2127          21 :   ldp_init_check ();
    2128             : 
    2129          21 :   vlsh = ldp_fd_to_vlsh (fd);
    2130          21 :   if (vlsh != VLS_INVALID_HANDLE)
    2131             :     {
    2132          21 :       rv = -EOPNOTSUPP;
    2133             : 
    2134          21 :       switch (level)
    2135             :         {
    2136           2 :         case SOL_TCP:
    2137             :           switch (optname)
    2138             :             {
    2139           0 :             case TCP_NODELAY:
    2140           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_NODELAY,
    2141             :                              (void *) optval, &optlen);
    2142           0 :               break;
    2143           2 :             case TCP_MAXSEG:
    2144           2 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_USER_MSS,
    2145             :                              (void *) optval, &optlen);
    2146           2 :               break;
    2147           0 :             case TCP_KEEPIDLE:
    2148           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
    2149             :                              (void *) optval, &optlen);
    2150           0 :               break;
    2151           0 :             case TCP_KEEPINTVL:
    2152           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
    2153             :                              (void *) optval, &optlen);
    2154           0 :               break;
    2155           0 :             case TCP_CONGESTION:
    2156             :             case TCP_CORK:
    2157             :               /* Ignore */
    2158           0 :               rv = 0;
    2159           0 :               break;
    2160           0 :             default:
    2161           0 :               LDBG (0, "ERROR: fd %d: setsockopt() SOL_TCP: vlsh %u"
    2162             :                     "optname %d unsupported!", fd, vlsh, optname);
    2163           0 :               break;
    2164             :             }
    2165           2 :           break;
    2166           2 :         case SOL_IPV6:
    2167             :           switch (optname)
    2168             :             {
    2169           2 :             case IPV6_V6ONLY:
    2170           2 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_V6ONLY,
    2171             :                              (void *) optval, &optlen);
    2172           2 :               break;
    2173           0 :             default:
    2174           0 :               LDBG (0, "ERROR: fd %d: setsockopt SOL_IPV6: vlsh %u"
    2175             :                     "optname %d unsupported!", fd, vlsh, optname);
    2176           0 :               break;
    2177             :             }
    2178           2 :           break;
    2179          17 :         case SOL_SOCKET:
    2180             :           switch (optname)
    2181             :             {
    2182           0 :             case SO_KEEPALIVE:
    2183           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_KEEPALIVE,
    2184             :                              (void *) optval, &optlen);
    2185           0 :               break;
    2186          15 :             case SO_REUSEADDR:
    2187          15 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEADDR,
    2188             :                              (void *) optval, &optlen);
    2189          15 :               break;
    2190           0 :             case SO_REUSEPORT:
    2191           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEPORT, (void *) optval,
    2192             :                              &optlen);
    2193           0 :               break;
    2194           0 :             case SO_BROADCAST:
    2195           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_BROADCAST,
    2196             :                              (void *) optval, &optlen);
    2197           0 :               break;
    2198           0 :             case SO_LINGER:
    2199           0 :               rv = 0;
    2200           0 :               break;
    2201           2 :             default:
    2202           2 :               LDBG (0, "ERROR: fd %d: setsockopt SOL_SOCKET: vlsh %u "
    2203             :                     "optname %d unsupported!", fd, vlsh, optname);
    2204           2 :               break;
    2205             :             }
    2206          17 :           break;
    2207           0 :         case SOL_IP:
    2208             :           switch (optname)
    2209             :             {
    2210           0 :             case IP_PKTINFO:
    2211           0 :               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_IP_PKTINFO, (void *) optval,
    2212             :                              &optlen);
    2213           0 :               break;
    2214           0 :             default:
    2215           0 :               LDBG (0,
    2216             :                     "ERROR: fd %d: setsockopt SOL_IP: vlsh %u optname %d"
    2217             :                     "unsupported!",
    2218             :                     fd, vlsh, optname);
    2219           0 :               break;
    2220             :             }
    2221           0 :           break;
    2222           0 :         default:
    2223           0 :           break;
    2224             :         }
    2225             : 
    2226          21 :       if (rv != VPPCOM_OK)
    2227             :         {
    2228           2 :           errno = -rv;
    2229           2 :           rv = -1;
    2230             :         }
    2231             :     }
    2232             :   else
    2233             :     {
    2234           0 :       rv = libc_setsockopt (fd, level, optname, optval, optlen);
    2235             :     }
    2236             : 
    2237          21 :   return rv;
    2238             : }
    2239             : 
    2240             : int
    2241             : listen (int fd, int n)
    2242             : {
    2243             :   vls_handle_t vlsh;
    2244             :   int rv;
    2245             : 
    2246          14 :   ldp_init_check ();
    2247             : 
    2248          14 :   vlsh = ldp_fd_to_vlsh (fd);
    2249          14 :   if (vlsh != VLS_INVALID_HANDLE)
    2250             :     {
    2251          13 :       LDBG (0, "fd %d: calling vls_listen: vlsh %u, n %d", fd, vlsh, n);
    2252             : 
    2253          13 :       rv = vls_listen (vlsh, n);
    2254          13 :       if (rv != VPPCOM_OK)
    2255             :         {
    2256           0 :           errno = -rv;
    2257           0 :           rv = -1;
    2258             :         }
    2259             :     }
    2260             :   else
    2261             :     {
    2262           1 :       LDBG (0, "fd %d: calling libc_listen(): n %d", fd, n);
    2263           1 :       rv = libc_listen (fd, n);
    2264             :     }
    2265             : 
    2266          14 :   LDBG (1, "fd %d: returning %d", fd, rv);
    2267          14 :   return rv;
    2268             : }
    2269             : 
    2270             : static inline int
    2271          11 : ldp_accept4 (int listen_fd, __SOCKADDR_ARG _addr,
    2272             :              socklen_t *__restrict addr_len, int flags)
    2273             : {
    2274          11 :   struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
    2275             :   vls_handle_t listen_vlsh, accept_vlsh;
    2276             :   int rv;
    2277             : 
    2278          11 :   ldp_init_check ();
    2279             : 
    2280          11 :   listen_vlsh = ldp_fd_to_vlsh (listen_fd);
    2281          11 :   if (listen_vlsh != VLS_INVALID_HANDLE)
    2282             :     {
    2283             :       vppcom_endpt_t ep;
    2284             :       u8 src_addr[sizeof (struct sockaddr_in6)];
    2285          11 :       memset (&ep, 0, sizeof (ep));
    2286          11 :       ep.ip = src_addr;
    2287             : 
    2288          11 :       LDBG (0, "listen fd %d: calling vppcom_session_accept: listen sid %u,"
    2289             :             " ep %p, flags 0x%x", listen_fd, listen_vlsh, &ep, flags);
    2290             : 
    2291          11 :       accept_vlsh = vls_accept (listen_vlsh, &ep, flags);
    2292          11 :       if (accept_vlsh < 0)
    2293             :         {
    2294           0 :           errno = -accept_vlsh;
    2295           0 :           rv = -1;
    2296             :         }
    2297             :       else
    2298             :         {
    2299          11 :           rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
    2300          11 :           if (rv != VPPCOM_OK)
    2301             :             {
    2302           0 :               (void) vls_close (accept_vlsh);
    2303           0 :               errno = -rv;
    2304           0 :               rv = -1;
    2305             :             }
    2306             :           else
    2307             :             {
    2308          11 :               rv = ldp_vlsh_to_fd (accept_vlsh);
    2309             :             }
    2310             :         }
    2311             :     }
    2312             :   else
    2313             :     {
    2314           0 :       LDBG (0, "listen fd %d: calling libc_accept4(): addr %p, addr_len %p,"
    2315             :             " flags 0x%x", listen_fd, addr, addr_len, flags);
    2316             : 
    2317           0 :       rv = libc_accept4 (listen_fd, addr, addr_len, flags);
    2318             :     }
    2319             : 
    2320          11 :   LDBG (1, "listen fd %d: accept returning %d", listen_fd, rv);
    2321             : 
    2322          11 :   return rv;
    2323             : }
    2324             : 
    2325             : int
    2326             : accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
    2327             :          int flags)
    2328             : {
    2329           0 :   return ldp_accept4 (fd, addr, addr_len, flags);
    2330             : }
    2331             : 
    2332             : int
    2333             : accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
    2334             : {
    2335          11 :   return ldp_accept4 (fd, addr, addr_len, 0);
    2336             : }
    2337             : 
    2338             : int
    2339             : shutdown (int fd, int how)
    2340             : {
    2341             :   vls_handle_t vlsh;
    2342           0 :   int rv = 0;
    2343             : 
    2344           0 :   ldp_init_check ();
    2345             : 
    2346           0 :   vlsh = ldp_fd_to_vlsh (fd);
    2347           0 :   if (vlsh != VLS_INVALID_HANDLE)
    2348             :     {
    2349           0 :       LDBG (0, "called shutdown: fd %u vlsh %u how %d", fd, vlsh, how);
    2350           0 :       rv = vls_shutdown (vlsh, how);
    2351             :     }
    2352             :   else
    2353             :     {
    2354           0 :       LDBG (0, "fd %d: calling libc_shutdown: how %d", fd, how);
    2355           0 :       rv = libc_shutdown (fd, how);
    2356             :     }
    2357             : 
    2358           0 :   return rv;
    2359             : }
    2360             : 
    2361             : int
    2362             : epoll_create1 (int flags)
    2363             : {
    2364           1 :   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
    2365             :   vls_handle_t vlsh;
    2366             :   int rv;
    2367             : 
    2368           1 :   ldp_init_check ();
    2369             : 
    2370           1 :   if (ldp->vcl_needs_real_epoll || vls_use_real_epoll ())
    2371             :     {
    2372             :       /* Make sure workers have been allocated */
    2373           0 :       if (!ldp->workers)
    2374             :         {
    2375           0 :           ldp_alloc_workers ();
    2376           0 :           ldpw = ldp_worker_get_current ();
    2377             :         }
    2378           0 :       rv = libc_epoll_create1 (flags);
    2379           0 :       ldp->vcl_needs_real_epoll = 0;
    2380           0 :       ldpw->vcl_mq_epfd = rv;
    2381           0 :       LDBG (0, "created vcl epfd %u", rv);
    2382           0 :       return rv;
    2383             :     }
    2384             : 
    2385           1 :   vlsh = vls_epoll_create ();
    2386           1 :   if (PREDICT_FALSE (vlsh == VLS_INVALID_HANDLE))
    2387             :     {
    2388           0 :       errno = -vlsh;
    2389           0 :       rv = -1;
    2390             :     }
    2391             :   else
    2392             :     {
    2393           1 :       rv = ldp_vlsh_to_fd (vlsh);
    2394             :     }
    2395           1 :   LDBG (0, "epoll_create epfd %u vlsh %u", rv, vlsh);
    2396           1 :   return rv;
    2397             : }
    2398             : 
    2399             : int
    2400             : epoll_create (int size)
    2401             : {
    2402           1 :   return epoll_create1 (0);
    2403             : }
    2404             : 
    2405             : int
    2406             : epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
    2407             : {
    2408             :   vls_handle_t vep_vlsh, vlsh;
    2409             :   int rv;
    2410             : 
    2411           4 :   ldp_init_check ();
    2412             : 
    2413           4 :   vep_vlsh = ldp_fd_to_vlsh (epfd);
    2414           4 :   if (PREDICT_FALSE (vep_vlsh == VLS_INVALID_HANDLE))
    2415             :     {
    2416             :       /* The LDP epoll_create1 always creates VCL epfd's.
    2417             :        * The app should never have a kernel base epoll fd unless it
    2418             :        * was acquired outside of the LD_PRELOAD process context.
    2419             :        * In any case, if we get one, punt it to libc_epoll_ctl.
    2420             :        */
    2421           0 :       LDBG (1,
    2422             :             "epfd %d: calling libc_epoll_ctl: op %d, fd %d"
    2423             :             " events 0x%x",
    2424             :             epfd, op, fd, event ? event->events : 0);
    2425             : 
    2426           0 :       rv = libc_epoll_ctl (epfd, op, fd, event);
    2427           0 :       goto done;
    2428             :     }
    2429             : 
    2430           4 :   vlsh = ldp_fd_to_vlsh (fd);
    2431             : 
    2432           4 :   LDBG (0, "epfd %d ep_vlsh %d, fd %u vlsh %d, op %u", epfd, vep_vlsh, fd,
    2433             :         vlsh, op);
    2434             : 
    2435           4 :   if (vlsh != VLS_INVALID_HANDLE)
    2436             :     {
    2437           3 :       LDBG (1,
    2438             :             "epfd %d: calling vls_epoll_ctl: ep_vlsh %d op %d, vlsh %u,"
    2439             :             " events 0x%x",
    2440             :             epfd, vep_vlsh, op, vlsh, event ? event->events : 0);
    2441             : 
    2442           3 :       rv = vls_epoll_ctl (vep_vlsh, op, vlsh, event);
    2443           3 :       if (rv != VPPCOM_OK)
    2444             :         {
    2445           0 :           errno = -rv;
    2446           0 :           rv = -1;
    2447             :         }
    2448             :     }
    2449             :   else
    2450             :     {
    2451             :       int libc_epfd;
    2452           1 :       u32 size = sizeof (epfd);
    2453             : 
    2454           1 :       libc_epfd = vls_attr (vep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
    2455           1 :       if (!libc_epfd)
    2456             :         {
    2457           1 :           LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
    2458             :                 "EPOLL_CLOEXEC", epfd, vep_vlsh);
    2459             : 
    2460           1 :           libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
    2461           1 :           if (libc_epfd < 0)
    2462             :             {
    2463           0 :               rv = libc_epfd;
    2464           0 :               goto done;
    2465             :             }
    2466             : 
    2467           1 :           rv = vls_attr (vep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd,
    2468             :                          &size);
    2469           1 :           if (rv < 0)
    2470             :             {
    2471           0 :               errno = -rv;
    2472           0 :               rv = -1;
    2473           0 :               goto done;
    2474             :             }
    2475             :         }
    2476           0 :       else if (PREDICT_FALSE (libc_epfd < 0))
    2477             :         {
    2478           0 :           errno = -epfd;
    2479           0 :           rv = -1;
    2480           0 :           goto done;
    2481             :         }
    2482             : 
    2483           1 :       LDBG (1, "epfd %d: calling libc_epoll_ctl: libc_epfd %d, op %d, fd %d,"
    2484             :             " event %p", epfd, libc_epfd, op, fd, event);
    2485             : 
    2486           1 :       rv = libc_epoll_ctl (libc_epfd, op, fd, event);
    2487             :     }
    2488             : 
    2489           4 : done:
    2490           4 :   return rv;
    2491             : }
    2492             : 
    2493             : static inline int
    2494         251 : ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
    2495             :                  int timeout, const sigset_t * sigmask)
    2496             : {
    2497             :   ldp_worker_ctx_t *ldpw;
    2498         251 :   double time_to_wait = (double) 0, max_time;
    2499         251 :   int libc_epfd, rv = 0;
    2500             :   vls_handle_t ep_vlsh;
    2501             : 
    2502         251 :   ldp_init_check ();
    2503             : 
    2504         251 :   if (PREDICT_FALSE (!events || (timeout < -1)))
    2505             :     {
    2506           0 :       errno = EFAULT;
    2507           0 :       return -1;
    2508             :     }
    2509             : 
    2510         251 :   if (PREDICT_FALSE (vppcom_worker_index () == ~0))
    2511           0 :     vls_register_vcl_worker ();
    2512             : 
    2513         251 :   ldpw = ldp_worker_get_current ();
    2514         251 :   if (epfd == ldpw->vcl_mq_epfd)
    2515           0 :     return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
    2516             : 
    2517         251 :   ep_vlsh = ldp_fd_to_vlsh (epfd);
    2518         251 :   if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
    2519             :     {
    2520           0 :       LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
    2521           0 :       errno = EBADFD;
    2522           0 :       return -1;
    2523             :     }
    2524             : 
    2525         251 :   if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
    2526           1 :     clib_time_init (&ldpw->clib_time);
    2527         251 :   time_to_wait = ((timeout >= 0) ? (double) timeout / 1000 : 0);
    2528         251 :   max_time = clib_time_now (&ldpw->clib_time) + time_to_wait;
    2529             : 
    2530         251 :   libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
    2531         251 :   if (PREDICT_FALSE (libc_epfd < 0))
    2532             :     {
    2533           0 :       errno = -libc_epfd;
    2534           0 :       rv = -1;
    2535           0 :       goto done;
    2536             :     }
    2537             : 
    2538         251 :   LDBG (2, "epfd %d: vep_idx %d, libc_epfd %d, events %p, maxevents %d, "
    2539             :         "timeout %d, sigmask %p: time_to_wait %.02f", epfd, ep_vlsh,
    2540             :         libc_epfd, events, maxevents, timeout, sigmask, time_to_wait);
    2541             :   do
    2542             :     {
    2543     1169850 :       if (!ldpw->epoll_wait_vcl)
    2544             :         {
    2545     1169600 :           rv = vls_epoll_wait (ep_vlsh, events, maxevents, 0);
    2546     1169600 :           if (rv > 0)
    2547             :             {
    2548         251 :               ldpw->epoll_wait_vcl = 1;
    2549         251 :               goto done;
    2550             :             }
    2551     1169350 :           else if (rv < 0)
    2552             :             {
    2553           0 :               errno = -rv;
    2554           0 :               rv = -1;
    2555           0 :               goto done;
    2556             :             }
    2557             :         }
    2558             :       else
    2559         250 :         ldpw->epoll_wait_vcl = 0;
    2560             : 
    2561     1169600 :       if (libc_epfd > 0)
    2562             :         {
    2563         117 :           rv = libc_epoll_pwait (libc_epfd, events, maxevents, 0, sigmask);
    2564         117 :           if (rv != 0)
    2565           0 :             goto done;
    2566             :         }
    2567             :     }
    2568     1169600 :   while ((timeout == -1) || (clib_time_now (&ldpw->clib_time) < max_time));
    2569             : 
    2570           0 : done:
    2571         251 :   return rv;
    2572             : }
    2573             : 
    2574             : static inline int
    2575           0 : ldp_epoll_pwait_eventfd (int epfd, struct epoll_event *events,
    2576             :                          int maxevents, int timeout, const sigset_t * sigmask)
    2577             : {
    2578           0 :   int libc_epfd, rv = 0, num_ev, libc_num_ev, vcl_wups = 0;
    2579             :   struct epoll_event *libc_evts;
    2580             :   ldp_worker_ctx_t *ldpw;
    2581             :   vls_handle_t ep_vlsh;
    2582             : 
    2583           0 :   ldp_init_check ();
    2584             : 
    2585           0 :   if (PREDICT_FALSE (!events || (timeout < -1)))
    2586             :     {
    2587           0 :       errno = EFAULT;
    2588           0 :       return -1;
    2589             :     }
    2590             : 
    2591             :   /* Make sure the vcl worker is valid. Could be that epoll fd was created on
    2592             :    * one thread but it is now used on another */
    2593           0 :   if (PREDICT_FALSE (vppcom_worker_index () == ~0))
    2594           0 :     vls_register_vcl_worker ();
    2595             : 
    2596           0 :   ldpw = ldp_worker_get_current ();
    2597           0 :   if (epfd == ldpw->vcl_mq_epfd)
    2598           0 :     return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
    2599             : 
    2600           0 :   ep_vlsh = ldp_fd_to_vlsh (epfd);
    2601           0 :   if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
    2602             :     {
    2603           0 :       LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
    2604           0 :       errno = EBADFD;
    2605           0 :       return -1;
    2606             :     }
    2607             : 
    2608           0 :   libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
    2609           0 :   if (PREDICT_FALSE (!libc_epfd))
    2610             :     {
    2611           0 :       u32 size = sizeof (epfd);
    2612             : 
    2613           0 :       LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
    2614             :             "EPOLL_CLOEXEC", epfd, ep_vlsh);
    2615           0 :       libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
    2616           0 :       if (libc_epfd < 0)
    2617             :         {
    2618           0 :           rv = libc_epfd;
    2619           0 :           goto done;
    2620             :         }
    2621             : 
    2622           0 :       rv = vls_attr (ep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd, &size);
    2623           0 :       if (rv < 0)
    2624             :         {
    2625           0 :           errno = -rv;
    2626           0 :           rv = -1;
    2627           0 :           goto done;
    2628             :         }
    2629             :     }
    2630           0 :   if (PREDICT_FALSE (libc_epfd <= 0))
    2631             :     {
    2632           0 :       errno = -libc_epfd;
    2633           0 :       rv = -1;
    2634           0 :       goto done;
    2635             :     }
    2636             : 
    2637           0 :   if (PREDICT_FALSE (!ldpw->mq_epfd_added))
    2638             :     {
    2639           0 :       struct epoll_event e = { 0 };
    2640           0 :       e.events = EPOLLIN;
    2641           0 :       e.data.fd = ldpw->vcl_mq_epfd;
    2642           0 :       if (libc_epoll_ctl (libc_epfd, EPOLL_CTL_ADD, ldpw->vcl_mq_epfd, &e) <
    2643             :           0)
    2644             :         {
    2645           0 :           LDBG (0, "epfd %d, add libc mq epoll fd %d to libc epoll fd %d",
    2646             :                 epfd, ldpw->vcl_mq_epfd, libc_epfd);
    2647           0 :           rv = -1;
    2648           0 :           goto done;
    2649             :         }
    2650           0 :       ldpw->mq_epfd_added = 1;
    2651             :     }
    2652             : 
    2653             :   /* Request to only drain unhandled to prevent libc_epoll_wait starved */
    2654           0 :   rv = vls_epoll_wait (ep_vlsh, events, maxevents, -2);
    2655           0 :   if (rv > 0)
    2656             :     {
    2657           0 :       timeout = 0;
    2658           0 :       if (rv >= maxevents)
    2659           0 :         goto done;
    2660             :     }
    2661           0 :   else if (PREDICT_FALSE (rv < 0))
    2662             :     {
    2663           0 :       errno = -rv;
    2664           0 :       rv = -1;
    2665           0 :       goto done;
    2666             :     }
    2667             : 
    2668           0 : epoll_again:
    2669             : 
    2670           0 :   libc_evts = &events[rv];
    2671             :   libc_num_ev =
    2672           0 :     libc_epoll_pwait (libc_epfd, libc_evts, maxevents - rv, timeout, sigmask);
    2673           0 :   if (libc_num_ev <= 0)
    2674             :     {
    2675           0 :       rv = rv >= 0 ? rv : -1;
    2676           0 :       goto done;
    2677             :     }
    2678             : 
    2679           0 :   for (int i = 0; i < libc_num_ev; i++)
    2680             :     {
    2681           0 :       if (libc_evts[i].data.fd == ldpw->vcl_mq_epfd)
    2682             :         {
    2683             :           /* We should remove mq epoll fd from events. */
    2684           0 :           libc_num_ev--;
    2685           0 :           if (i != libc_num_ev)
    2686             :             {
    2687           0 :               libc_evts[i].events = libc_evts[libc_num_ev].events;
    2688           0 :               libc_evts[i].data.u64 = libc_evts[libc_num_ev].data.u64;
    2689             :             }
    2690           0 :           num_ev = vls_epoll_wait (ep_vlsh, &libc_evts[libc_num_ev],
    2691             :                                    maxevents - libc_num_ev, 0);
    2692           0 :           if (PREDICT_TRUE (num_ev > 0))
    2693           0 :             rv += num_ev;
    2694             :           /* Woken up by vcl but no events generated. Accept it once */
    2695           0 :           if (rv == 0 && libc_num_ev == 0 && timeout && vcl_wups++ < 1)
    2696           0 :             goto epoll_again;
    2697           0 :           break;
    2698             :         }
    2699             :     }
    2700             : 
    2701           0 :   rv += libc_num_ev;
    2702             : 
    2703           0 : done:
    2704           0 :   return rv;
    2705             : }
    2706             : 
    2707             : int
    2708             : epoll_pwait (int epfd, struct epoll_event *events,
    2709             :              int maxevents, int timeout, const sigset_t * sigmask)
    2710             : {
    2711           0 :   if (vls_use_eventfd ())
    2712           0 :     return ldp_epoll_pwait_eventfd (epfd, events, maxevents, timeout,
    2713             :                                     sigmask);
    2714             :   else
    2715           0 :     return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
    2716             : }
    2717             : 
    2718             : int
    2719             : epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
    2720             : {
    2721         251 :   if (vls_use_eventfd ())
    2722           0 :     return ldp_epoll_pwait_eventfd (epfd, events, maxevents, timeout, NULL);
    2723             :   else
    2724         251 :     return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL);
    2725             : }
    2726             : 
    2727             : int
    2728             : poll (struct pollfd *fds, nfds_t nfds, int timeout)
    2729             : {
    2730           0 :   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
    2731           0 :   int rv, i, n_revents = 0;
    2732             :   vls_handle_t vlsh;
    2733             :   vcl_poll_t *vp;
    2734             :   double max_time;
    2735             : 
    2736           0 :   LDBG (3, "fds %p, nfds %ld, timeout %d", fds, nfds, timeout);
    2737             : 
    2738           0 :   if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
    2739           0 :     clib_time_init (&ldpw->clib_time);
    2740             : 
    2741           0 :   max_time = (timeout >= 0) ? (f64) timeout / 1000 : 0;
    2742           0 :   max_time += clib_time_now (&ldpw->clib_time);
    2743             : 
    2744           0 :   for (i = 0; i < nfds; i++)
    2745             :     {
    2746           0 :       if (fds[i].fd < 0)
    2747           0 :         continue;
    2748             : 
    2749           0 :       vlsh = ldp_fd_to_vlsh (fds[i].fd);
    2750           0 :       if (vlsh != VLS_INVALID_HANDLE)
    2751             :         {
    2752           0 :           fds[i].fd = -fds[i].fd;
    2753           0 :           vec_add2 (ldpw->vcl_poll, vp, 1);
    2754           0 :           vp->fds_ndx = i;
    2755           0 :           vp->sh = vlsh_to_sh (vlsh);
    2756           0 :           vp->events = fds[i].events;
    2757             : #ifdef __USE_XOPEN2K
    2758           0 :           if (fds[i].events & POLLRDNORM)
    2759           0 :             vp->events |= POLLIN;
    2760           0 :           if (fds[i].events & POLLWRNORM)
    2761           0 :             vp->events |= POLLOUT;
    2762             : #endif
    2763           0 :           vp->revents = fds[i].revents;
    2764             :         }
    2765             :       else
    2766             :         {
    2767           0 :           vec_add1 (ldpw->libc_poll, fds[i]);
    2768           0 :           vec_add1 (ldpw->libc_poll_idxs, i);
    2769             :         }
    2770             :     }
    2771             : 
    2772             :   do
    2773             :     {
    2774           0 :       if (vec_len (ldpw->vcl_poll))
    2775             :         {
    2776           0 :           rv = vppcom_poll (ldpw->vcl_poll, vec_len (ldpw->vcl_poll), 0);
    2777           0 :           if (rv < 0)
    2778             :             {
    2779           0 :               errno = -rv;
    2780           0 :               rv = -1;
    2781           0 :               goto done;
    2782             :             }
    2783             :           else
    2784           0 :             n_revents += rv;
    2785             :         }
    2786             : 
    2787           0 :       if (vec_len (ldpw->libc_poll))
    2788             :         {
    2789           0 :           rv = libc_poll (ldpw->libc_poll, vec_len (ldpw->libc_poll), 0);
    2790           0 :           if (rv < 0)
    2791           0 :             goto done;
    2792             :           else
    2793           0 :             n_revents += rv;
    2794             :         }
    2795             : 
    2796           0 :       if (n_revents)
    2797             :         {
    2798           0 :           rv = n_revents;
    2799           0 :           goto done;
    2800             :         }
    2801             :     }
    2802           0 :   while ((timeout < 0) || (clib_time_now (&ldpw->clib_time) < max_time));
    2803           0 :   rv = 0;
    2804             : 
    2805           0 : done:
    2806           0 :   vec_foreach (vp, ldpw->vcl_poll)
    2807             :   {
    2808           0 :     fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
    2809           0 :     fds[vp->fds_ndx].revents = vp->revents;
    2810             : #ifdef __USE_XOPEN2K
    2811           0 :     if ((fds[vp->fds_ndx].revents & POLLIN) &&
    2812           0 :         (fds[vp->fds_ndx].events & POLLRDNORM))
    2813           0 :       fds[vp->fds_ndx].revents |= POLLRDNORM;
    2814           0 :     if ((fds[vp->fds_ndx].revents & POLLOUT) &&
    2815           0 :         (fds[vp->fds_ndx].events & POLLWRNORM))
    2816           0 :       fds[vp->fds_ndx].revents |= POLLWRNORM;
    2817             : #endif
    2818             :   }
    2819           0 :   vec_reset_length (ldpw->vcl_poll);
    2820             : 
    2821           0 :   for (i = 0; i < vec_len (ldpw->libc_poll); i++)
    2822             :     {
    2823           0 :       fds[ldpw->libc_poll_idxs[i]].revents = ldpw->libc_poll[i].revents;
    2824             :     }
    2825           0 :   vec_reset_length (ldpw->libc_poll_idxs);
    2826           0 :   vec_reset_length (ldpw->libc_poll);
    2827             : 
    2828           0 :   return rv;
    2829             : }
    2830             : 
    2831             : #ifdef _GNU_SOURCE
    2832             : int
    2833             : ppoll (struct pollfd *fds, nfds_t nfds,
    2834             :        const struct timespec *timeout, const sigset_t * sigmask)
    2835             : {
    2836           0 :   ldp_init_check ();
    2837             : 
    2838           0 :   clib_warning ("LDP<%d>: LDP-TBD", getpid ());
    2839           0 :   errno = ENOSYS;
    2840             : 
    2841             : 
    2842           0 :   return -1;
    2843             : }
    2844             : #endif
    2845             : 
    2846             : void CONSTRUCTOR_ATTRIBUTE ldp_constructor (void);
    2847             : 
    2848             : void DESTRUCTOR_ATTRIBUTE ldp_destructor (void);
    2849             : 
    2850             : /*
    2851             :  * This function is called when the library is loaded
    2852             :  */
    2853             : void
    2854          13 : ldp_constructor (void)
    2855             : {
    2856          13 :   swrap_constructor ();
    2857          13 :   if (ldp_init () != 0)
    2858             :     {
    2859           0 :       fprintf (stderr, "\nLDP<%d>: ERROR: ldp_constructor: failed!\n",
    2860             :                getpid ());
    2861           0 :       _exit (1);
    2862             :     }
    2863          13 :   else if (LDP_DEBUG > 0)
    2864          13 :     clib_warning ("LDP<%d>: LDP constructor: done!\n", getpid ());
    2865          13 : }
    2866             : 
    2867             : /*
    2868             :  * This function is called when the library is unloaded
    2869             :  */
    2870             : void
    2871          13 : ldp_destructor (void)
    2872             : {
    2873             :   /*
    2874             :      swrap_destructor ();
    2875             :      if (ldp->init)
    2876             :      ldp->init = 0;
    2877             :    */
    2878             : 
    2879             :   /* Don't use clib_warning() here because that calls writev()
    2880             :    * which will call ldp_init().
    2881             :    */
    2882          13 :   if (LDP_DEBUG > 0)
    2883          13 :     fprintf (stderr, "%s:%d: LDP<%d>: LDP destructor: done!\n",
    2884             :              __func__, __LINE__, getpid ());
    2885          13 : }
    2886             : 
    2887             : 
    2888             : /*
    2889             :  * fd.io coding-style-patch-verification: ON
    2890             :  *
    2891             :  * Local Variables:
    2892             :  * eval: (c-set-style "gnu")
    2893             :  * End:
    2894             :  */

Generated by: LCOV version 1.14