vcl/ldp: add locked sessions shim layer
[vpp.git] / src / vcl / ldp.c
1 /*
2  * Copyright (c) 2016 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 #include <unistd.h>
16 #include <stdio.h>
17 #include <signal.h>
18 #include <dlfcn.h>
19 #include <pthread.h>
20 #include <time.h>
21 #include <stdarg.h>
22 #include <sys/resource.h>
23 #include <netinet/tcp.h>
24
25 #include <vcl/ldp_socket_wrapper.h>
26 #include <vcl/ldp.h>
27 #include <sys/time.h>
28
29 #include <vcl/vcl_locked.h>
30 #include <vppinfra/time.h>
31 #include <vppinfra/bitmap.h>
32 #include <vppinfra/lock.h>
33 #include <vppinfra/pool.h>
34 #include <vppinfra/hash.h>
35
36 #define HAVE_CONSTRUCTOR_ATTRIBUTE
37 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
38 #define CONSTRUCTOR_ATTRIBUTE                       \
39     __attribute__ ((constructor))
40 #else
41 #define CONSTRUCTOR_ATTRIBUTE
42 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
43
44 #define HAVE_DESTRUCTOR_ATTRIBUTE
45 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
46 #define DESTRUCTOR_ATTRIBUTE                        \
47     __attribute__ ((destructor))
48 #else
49 #define DESTRUCTOR_ATTRIBUTE
50 #endif
51
52 #define LDP_MAX_NWORKERS 32
53
54 typedef struct ldp_worker_ctx_
55 {
56   u8 *io_buffer;
57   clib_time_t clib_time;
58
59   /*
60    * Select state
61    */
62   clib_bitmap_t *rd_bitmap;
63   clib_bitmap_t *wr_bitmap;
64   clib_bitmap_t *ex_bitmap;
65   clib_bitmap_t *sid_rd_bitmap;
66   clib_bitmap_t *sid_wr_bitmap;
67   clib_bitmap_t *sid_ex_bitmap;
68   clib_bitmap_t *libc_rd_bitmap;
69   clib_bitmap_t *libc_wr_bitmap;
70   clib_bitmap_t *libc_ex_bitmap;
71   u8 select_vcl;
72
73   /*
74    * Poll state
75    */
76   vcl_poll_t *vcl_poll;
77   struct pollfd *libc_poll;
78   u16 *libc_poll_idxs;
79
80   /*
81    * Epoll state
82    */
83   u8 epoll_wait_vcl;
84   int vcl_mq_epfd;
85
86 } ldp_worker_ctx_t;
87
88 typedef struct
89 {
90   ldp_worker_ctx_t *workers;
91   int init;
92   char app_name[LDP_APP_NAME_MAX];
93   u32 vlsh_bit_val;
94   u32 vlsh_bit_mask;
95   u32 debug;
96
97   /** vcl needs next epoll_create to go to libc_epoll */
98   u8 vcl_needs_real_epoll;
99 } ldp_main_t;
100
101 #define LDP_DEBUG ldp->debug
102
103 #define LDBG(_lvl, _fmt, _args...)                                      \
104   if (ldp->debug > _lvl)                                                \
105     clib_warning ("ldp<%d>: " _fmt, getpid(), ##_args)
106
107 static ldp_main_t ldp_main = {
108   .vlsh_bit_val = (1 << LDP_SID_BIT_MIN),
109   .vlsh_bit_mask = (1 << LDP_SID_BIT_MIN) - 1,
110   .debug = LDP_DEBUG_INIT,
111 };
112
113 static ldp_main_t *ldp = &ldp_main;
114
115 static inline ldp_worker_ctx_t *
116 ldp_worker_get_current (void)
117 {
118   return (ldp->workers + vppcom_worker_index ());
119 }
120
121 /*
122  * RETURN:  0 on success or -1 on error.
123  * */
124 static inline void
125 ldp_set_app_name (char *app_name)
126 {
127   int rv = snprintf (ldp->app_name, LDP_APP_NAME_MAX,
128                      "ldp-%d-%s", getpid (), app_name);
129
130   if (rv >= LDP_APP_NAME_MAX)
131     app_name[LDP_APP_NAME_MAX - 1] = 0;
132 }
133
134 static inline char *
135 ldp_get_app_name ()
136 {
137   if (ldp->app_name[0] == '\0')
138     ldp_set_app_name ("app");
139
140   return ldp->app_name;
141 }
142
143 static inline int
144 ldp_vlsh_to_fd (vls_handle_t vlsh)
145 {
146   return (vlsh + ldp->vlsh_bit_val);
147 }
148
149 static inline vls_handle_t
150 ldp_fd_to_vlsh (int fd)
151 {
152   if (fd < ldp->vlsh_bit_val)
153     return VLS_INVALID_HANDLE;
154
155   return (fd - ldp->vlsh_bit_val);
156 }
157
158 static inline int
159 ldp_init (void)
160 {
161   ldp_worker_ctx_t *ldpw;
162   int rv;
163
164   if (PREDICT_TRUE (ldp->init))
165     return 0;
166
167   ldp->init = 1;
168   ldp->vcl_needs_real_epoll = 1;
169   rv = vls_app_create (ldp_get_app_name ());
170   if (rv != VPPCOM_OK)
171     {
172       ldp->vcl_needs_real_epoll = 0;
173       if (rv == VPPCOM_EEXIST)
174         return 0;
175       LDBG (2, "\nERROR: ldp_init: vppcom_app_create()"
176             " failed!  rv = %d (%s)\n", rv, vppcom_retval_str (rv));
177       ldp->init = 0;
178       return rv;
179     }
180   ldp->vcl_needs_real_epoll = 0;
181   pool_alloc (ldp->workers, LDP_MAX_NWORKERS);
182   ldpw = ldp_worker_get_current ();
183
184   char *env_var_str = getenv (LDP_ENV_DEBUG);
185   if (env_var_str)
186     {
187       u32 tmp;
188       if (sscanf (env_var_str, "%u", &tmp) != 1)
189         clib_warning ("LDP<%d>: WARNING: Invalid LDP debug level specified in"
190                       " the env var " LDP_ENV_DEBUG " (%s)!", getpid (),
191                       env_var_str);
192       else
193         {
194           ldp->debug = tmp;
195           LDBG (0, "configured LDP debug level (%u) from env var "
196                 LDP_ENV_DEBUG "!", ldp->debug);
197         }
198     }
199
200   env_var_str = getenv (LDP_ENV_APP_NAME);
201   if (env_var_str)
202     {
203       ldp_set_app_name (env_var_str);
204       LDBG (0, "configured LDP app name (%s) from the env var "
205             LDP_ENV_APP_NAME "!", ldp->app_name);
206     }
207
208   env_var_str = getenv (LDP_ENV_SID_BIT);
209   if (env_var_str)
210     {
211       u32 sb;
212       if (sscanf (env_var_str, "%u", &sb) != 1)
213         {
214           clib_warning ("LDP<%d>: WARNING: Invalid LDP sid bit specified in"
215                         " the env var " LDP_ENV_SID_BIT " (%s)! sid bit "
216                         "value %d (0x%x)", getpid (), env_var_str,
217                         ldp->vlsh_bit_val, ldp->vlsh_bit_val);
218         }
219       else if (sb < LDP_SID_BIT_MIN)
220         {
221           ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MIN);
222           ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
223
224           clib_warning ("LDP<%d>: WARNING: LDP sid bit (%u) specified in the"
225                         " env var " LDP_ENV_SID_BIT " (%s) is too small. "
226                         "Using LDP_SID_BIT_MIN (%d)! sid bit value %d (0x%x)",
227                         getpid (), sb, env_var_str, LDP_SID_BIT_MIN,
228                         ldp->vlsh_bit_val, ldp->vlsh_bit_val);
229         }
230       else if (sb > LDP_SID_BIT_MAX)
231         {
232           ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MAX);
233           ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
234
235           clib_warning ("LDP<%d>: WARNING: LDP sid bit (%u) specified in the"
236                         " env var " LDP_ENV_SID_BIT " (%s) is too big. Using"
237                         " LDP_SID_BIT_MAX (%d)! sid bit value %d (0x%x)",
238                         getpid (), sb, env_var_str, LDP_SID_BIT_MAX,
239                         ldp->vlsh_bit_val, ldp->vlsh_bit_val);
240         }
241       else
242         {
243           ldp->vlsh_bit_val = (1 << sb);
244           ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
245
246           LDBG (0, "configured LDP sid bit (%u) from "
247                 LDP_ENV_SID_BIT "!  sid bit value %d (0x%x)", sb,
248                 ldp->vlsh_bit_val, ldp->vlsh_bit_val);
249         }
250     }
251
252   clib_time_init (&ldpw->clib_time);
253   LDBG (0, "LDP initialization: done!");
254
255   return 0;
256 }
257
258 int
259 close (int fd)
260 {
261   vls_handle_t vlsh;
262   int rv, epfd;
263
264   if ((errno = -ldp_init ()))
265     return -1;
266
267   vlsh = ldp_fd_to_vlsh (fd);
268   if (vlsh != VLS_INVALID_HANDLE)
269     {
270       epfd = vls_attr (vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
271       if (epfd > 0)
272         {
273           LDBG (0, "fd %d: calling libc_close: epfd %u", fd, epfd);
274
275           rv = libc_close (epfd);
276           if (rv < 0)
277             {
278               u32 size = sizeof (epfd);
279               epfd = 0;
280
281               (void) vls_attr (vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &epfd, &size);
282             }
283         }
284       else if (PREDICT_FALSE (epfd < 0))
285         {
286           errno = -epfd;
287           rv = -1;
288           goto done;
289         }
290
291       LDBG (0, "fd %d: calling vls_close: vlsh %u", fd, vlsh);
292
293       rv = vls_close (vlsh);
294       if (rv != VPPCOM_OK)
295         {
296           errno = -rv;
297           rv = -1;
298         }
299     }
300   else
301     {
302       LDBG (0, "fd %d: calling libc_close", fd);
303       rv = libc_close (fd);
304     }
305
306 done:
307   return rv;
308 }
309
310 ssize_t
311 read (int fd, void *buf, size_t nbytes)
312 {
313   vls_handle_t vlsh;
314   ssize_t size;
315
316   if ((errno = -ldp_init ()))
317     return -1;
318
319   vlsh = ldp_fd_to_vlsh (fd);
320   if (vlsh != VLS_INVALID_HANDLE)
321     {
322       size = vls_read (vlsh, buf, nbytes);
323       if (size < 0)
324         {
325           errno = -size;
326           size = -1;
327         }
328     }
329   else
330     {
331       size = libc_read (fd, buf, nbytes);
332     }
333
334   return size;
335 }
336
337 ssize_t
338 readv (int fd, const struct iovec * iov, int iovcnt)
339 {
340   int rv = 0, i, total = 0;
341   vls_handle_t vlsh;
342   ssize_t size = 0;
343
344   if ((errno = -ldp_init ()))
345     return -1;
346
347   vlsh = ldp_fd_to_vlsh (fd);
348   if (vlsh != VLS_INVALID_HANDLE)
349     {
350       do
351         {
352           for (i = 0; i < iovcnt; ++i)
353             {
354               rv = vls_read (vlsh, iov[i].iov_base, iov[i].iov_len);
355               if (rv < 0)
356                 break;
357               else
358                 {
359                   total += rv;
360                   if (rv < iov[i].iov_len)
361                     break;
362                 }
363             }
364         }
365       while ((rv >= 0) && (total == 0));
366
367       if (rv < 0)
368         {
369           errno = -rv;
370           size = -1;
371         }
372       else
373         size = total;
374     }
375   else
376     {
377       size = libc_readv (fd, iov, iovcnt);
378     }
379
380   return size;
381 }
382
383 ssize_t
384 write (int fd, const void *buf, size_t nbytes)
385 {
386   vls_handle_t vlsh;
387   ssize_t size = 0;
388
389   if ((errno = -ldp_init ()))
390     return -1;
391
392   vlsh = ldp_fd_to_vlsh (fd);
393   if (vlsh != VLS_INVALID_HANDLE)
394     {
395       size = vls_write_msg (vlsh, (void *) buf, nbytes);
396       if (size < 0)
397         {
398           errno = -size;
399           size = -1;
400         }
401     }
402   else
403     {
404       size = libc_write (fd, buf, nbytes);
405     }
406
407   return size;
408 }
409
410 ssize_t
411 writev (int fd, const struct iovec * iov, int iovcnt)
412 {
413   ssize_t size = 0, total = 0;
414   vls_handle_t vlsh;
415   int i, rv = 0;
416
417   if ((errno = -ldp_init ()))
418     return -1;
419
420   vlsh = ldp_fd_to_vlsh (fd);
421   if (vlsh != VLS_INVALID_HANDLE)
422     {
423       do
424         {
425           for (i = 0; i < iovcnt; ++i)
426             {
427               rv = vls_write_msg (vlsh, iov[i].iov_base, iov[i].iov_len);
428               if (rv < 0)
429                 break;
430               else
431                 {
432                   total += rv;
433                   if (rv < iov[i].iov_len)
434                     break;
435                 }
436             }
437         }
438       while ((rv >= 0) && (total == 0));
439
440       if (rv < 0)
441         {
442           errno = -rv;
443           size = -1;
444         }
445       else
446         size = total;
447     }
448   else
449     {
450       size = libc_writev (fd, iov, iovcnt);
451     }
452
453   return size;
454 }
455
456 int
457 fcntl (int fd, int cmd, ...)
458 {
459   vls_handle_t vlsh;
460   int rv = 0;
461   va_list ap;
462
463   if ((errno = -ldp_init ()))
464     return -1;
465
466   va_start (ap, cmd);
467
468   vlsh = ldp_fd_to_vlsh (fd);
469   LDBG (0, "fd %u vlsh %d, cmd %u", fd, vlsh, cmd);
470   if (vlsh != VLS_INVALID_HANDLE)
471     {
472       int flags = va_arg (ap, int);
473       u32 size;
474
475       size = sizeof (flags);
476       rv = -EOPNOTSUPP;
477       switch (cmd)
478         {
479         case F_SETFL:
480           rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
481           break;
482
483         case F_GETFL:
484           rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &size);
485           if (rv == VPPCOM_OK)
486             rv = flags;
487           break;
488         case F_SETFD:
489           /* TODO handle this */
490           LDBG (0, "F_SETFD ignored flags %u", flags);
491           rv = 0;
492           break;
493         default:
494           rv = -EOPNOTSUPP;
495           break;
496         }
497       if (rv < 0)
498         {
499           errno = -rv;
500           rv = -1;
501         }
502     }
503   else
504     {
505       rv = libc_vfcntl (fd, cmd, ap);
506     }
507
508   va_end (ap);
509
510   return rv;
511 }
512
513 int
514 ioctl (int fd, unsigned long int cmd, ...)
515 {
516   vls_handle_t vlsh;
517   va_list ap;
518   int rv;
519
520   if ((errno = -ldp_init ()))
521     return -1;
522
523   va_start (ap, cmd);
524
525   vlsh = ldp_fd_to_vlsh (fd);
526   if (vlsh != VLS_INVALID_HANDLE)
527     {
528       switch (cmd)
529         {
530         case FIONREAD:
531           rv = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
532           break;
533
534         case FIONBIO:
535           {
536             u32 flags = va_arg (ap, int) ? O_NONBLOCK : 0;
537             u32 size = sizeof (flags);
538
539             /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than
540              *      non-blocking, the flags should be read here and merged
541              *      with O_NONBLOCK.
542              */
543             rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
544           }
545           break;
546
547         default:
548           rv = -EOPNOTSUPP;
549           break;
550         }
551       if (rv < 0)
552         {
553           errno = -rv;
554           rv = -1;
555         }
556     }
557   else
558     {
559       rv = libc_vioctl (fd, cmd, ap);
560     }
561
562   va_end (ap);
563   return rv;
564 }
565
566 int
567 ldp_pselect (int nfds, fd_set * __restrict readfds,
568              fd_set * __restrict writefds,
569              fd_set * __restrict exceptfds,
570              const struct timespec *__restrict timeout,
571              const __sigset_t * __restrict sigmask)
572 {
573   uword sid_bits, sid_bits_set, libc_bits, libc_bits_set;
574   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
575   u32 minbits = clib_max (nfds, BITS (uword)), si;
576   vls_handle_t vlsh;
577   f64 time_out;
578   int rv, fd;
579
580   if (nfds < 0)
581     {
582       errno = EINVAL;
583       return -1;
584     }
585
586   if (timeout)
587     {
588       time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ?
589         (f64) 0 : (f64) timeout->tv_sec + (f64) timeout->tv_nsec / (f64) 1e9;
590
591       /* select as fine grained sleep */
592       if (!nfds)
593         {
594           time_out += clib_time_now (&ldpw->clib_time);
595           while (clib_time_now (&ldpw->clib_time) < time_out)
596             ;
597           return 0;
598         }
599     }
600   else if (!nfds)
601     {
602       errno = EINVAL;
603       return -1;
604     }
605   else
606     time_out = -1;
607
608
609   if (nfds <= ldp->vlsh_bit_val)
610     {
611       rv = libc_pselect (nfds, readfds, writefds, exceptfds,
612                          timeout, sigmask);
613       goto done;
614     }
615
616   if (PREDICT_FALSE (ldp->vlsh_bit_val > FD_SETSIZE / 2))
617     {
618       LDBG (0, "ERROR: LDP sid bit value %d > FD_SETSIZE/2 %d!",
619             ldp->vlsh_bit_val, FD_SETSIZE / 2);
620       errno = EOVERFLOW;
621       return -1;
622     }
623
624   sid_bits = libc_bits = 0;
625   u32 n_bytes = nfds / 8 + ((nfds % 8) ? 1 : 0);
626
627   if (readfds)
628     {
629       clib_bitmap_validate (ldpw->sid_rd_bitmap, minbits);
630       clib_bitmap_validate (ldpw->libc_rd_bitmap, minbits);
631       clib_bitmap_validate (ldpw->rd_bitmap, minbits);
632       clib_memcpy_fast (ldpw->rd_bitmap, readfds, n_bytes);
633       memset (readfds, 0, n_bytes);
634
635       /* *INDENT-OFF* */
636       clib_bitmap_foreach (fd, ldpw->rd_bitmap, ({
637         if (fd > nfds)
638           break;
639         vlsh = ldp_fd_to_vlsh (fd);
640         if (vlsh == VLS_INVALID_HANDLE)
641           clib_bitmap_set_no_check (ldpw->libc_rd_bitmap, fd, 1);
642         else
643           clib_bitmap_set_no_check (ldpw->sid_rd_bitmap,
644                                     vlsh_to_session_index (vlsh), 1);
645       }));
646       /* *INDENT-ON* */
647
648       sid_bits_set = clib_bitmap_last_set (ldpw->sid_rd_bitmap) + 1;
649       sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits;
650
651       libc_bits_set = clib_bitmap_last_set (ldpw->libc_rd_bitmap) + 1;
652       libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits;
653     }
654   if (writefds)
655     {
656       clib_bitmap_validate (ldpw->sid_wr_bitmap, minbits);
657       clib_bitmap_validate (ldpw->libc_wr_bitmap, minbits);
658       clib_bitmap_validate (ldpw->wr_bitmap, minbits);
659       clib_memcpy_fast (ldpw->wr_bitmap, writefds, n_bytes);
660       memset (writefds, 0, n_bytes);
661
662       /* *INDENT-OFF* */
663       clib_bitmap_foreach (fd, ldpw->wr_bitmap, ({
664         if (fd > nfds)
665           break;
666         vlsh = ldp_fd_to_vlsh (fd);
667         if (vlsh == VLS_INVALID_HANDLE)
668           clib_bitmap_set_no_check (ldpw->libc_wr_bitmap, fd, 1);
669         else
670           clib_bitmap_set_no_check (ldpw->sid_wr_bitmap,
671                                     vlsh_to_session_index (vlsh), 1);
672       }));
673       /* *INDENT-ON* */
674
675       sid_bits_set = clib_bitmap_last_set (ldpw->sid_wr_bitmap) + 1;
676       sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits;
677
678       libc_bits_set = clib_bitmap_last_set (ldpw->libc_wr_bitmap) + 1;
679       libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits;
680
681     }
682   if (exceptfds)
683     {
684       clib_bitmap_validate (ldpw->sid_ex_bitmap, minbits);
685       clib_bitmap_validate (ldpw->libc_ex_bitmap, minbits);
686       clib_bitmap_validate (ldpw->ex_bitmap, minbits);
687       clib_memcpy_fast (ldpw->ex_bitmap, exceptfds, n_bytes);
688       memset (exceptfds, 0, n_bytes);
689
690       /* *INDENT-OFF* */
691       clib_bitmap_foreach (fd, ldpw->ex_bitmap, ({
692         if (fd > nfds)
693           break;
694         vlsh = ldp_fd_to_vlsh (fd);
695         if (vlsh == VLS_INVALID_HANDLE)
696           clib_bitmap_set_no_check (ldpw->libc_ex_bitmap, fd, 1);
697         else
698           clib_bitmap_set_no_check (ldpw->sid_ex_bitmap,
699                                     vlsh_to_session_index (vlsh), 1);
700       }));
701       /* *INDENT-ON* */
702
703       sid_bits_set = clib_bitmap_last_set (ldpw->sid_ex_bitmap) + 1;
704       sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits;
705
706       libc_bits_set = clib_bitmap_last_set (ldpw->libc_ex_bitmap) + 1;
707       libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits;
708     }
709
710   if (PREDICT_FALSE (!sid_bits && !libc_bits))
711     {
712       errno = EINVAL;
713       rv = -1;
714       goto done;
715     }
716
717   do
718     {
719       if (sid_bits)
720         {
721           if (!ldpw->select_vcl)
722             {
723               if (readfds)
724                 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->sid_rd_bitmap,
725                                   vec_len (ldpw->rd_bitmap) *
726                                   sizeof (clib_bitmap_t));
727               if (writefds)
728                 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->sid_wr_bitmap,
729                                   vec_len (ldpw->wr_bitmap) *
730                                   sizeof (clib_bitmap_t));
731               if (exceptfds)
732                 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->sid_ex_bitmap,
733                                   vec_len (ldpw->ex_bitmap) *
734                                   sizeof (clib_bitmap_t));
735
736               rv = vppcom_select (sid_bits,
737                                   readfds ? (unsigned long *) ldpw->rd_bitmap
738                                   : NULL,
739                                   writefds ? (unsigned long *) ldpw->wr_bitmap
740                                   : NULL,
741                                   exceptfds ? (unsigned long *)
742                                   ldpw->ex_bitmap : NULL, 0);
743               if (rv < 0)
744                 {
745                   errno = -rv;
746                   rv = -1;
747                 }
748               else if (rv > 0)
749                 {
750                   if (readfds)
751                     {
752                       /* *INDENT-OFF* */
753                       clib_bitmap_foreach (si, ldpw->rd_bitmap, ({
754                         vlsh = vls_session_index_to_vlsh (si);
755                         fd = ldp_vlsh_to_fd (vlsh);
756                         if (PREDICT_FALSE (fd < 0))
757                           {
758                             errno = EBADFD;
759                             rv = -1;
760                             goto done;
761                           }
762                         FD_SET (fd, readfds);
763                       }));
764                       /* *INDENT-ON* */
765                     }
766                   if (writefds)
767                     {
768                       /* *INDENT-OFF* */
769                       clib_bitmap_foreach (si, ldpw->wr_bitmap, ({
770                         vlsh = vls_session_index_to_vlsh (si);
771                         fd = ldp_vlsh_to_fd (vlsh);
772                         if (PREDICT_FALSE (fd < 0))
773                           {
774                             errno = EBADFD;
775                             rv = -1;
776                             goto done;
777                           }
778                         FD_SET (fd, writefds);
779                       }));
780                       /* *INDENT-ON* */
781                     }
782                   if (exceptfds)
783                     {
784                       /* *INDENT-OFF* */
785                       clib_bitmap_foreach (si, ldpw->ex_bitmap, ({
786                         vlsh = vls_session_index_to_vlsh (si);
787                         fd = ldp_vlsh_to_fd (vlsh);
788                         if (PREDICT_FALSE (fd < 0))
789                           {
790                             errno = EBADFD;
791                             rv = -1;
792                             goto done;
793                           }
794                         FD_SET (fd, exceptfds);
795                       }));
796                       /* *INDENT-ON* */
797                     }
798                   ldpw->select_vcl = 1;
799                   goto done;
800                 }
801             }
802           else
803             ldpw->select_vcl = 0;
804         }
805       if (libc_bits)
806         {
807           struct timespec tspec;
808
809           if (readfds)
810             clib_memcpy_fast (readfds, ldpw->libc_rd_bitmap,
811                               vec_len (ldpw->rd_bitmap) *
812                               sizeof (clib_bitmap_t));
813           if (writefds)
814             clib_memcpy_fast (writefds, ldpw->libc_wr_bitmap,
815                               vec_len (ldpw->wr_bitmap) *
816                               sizeof (clib_bitmap_t));
817           if (exceptfds)
818             clib_memcpy_fast (exceptfds, ldpw->libc_ex_bitmap,
819                               vec_len (ldpw->ex_bitmap) *
820                               sizeof (clib_bitmap_t));
821           tspec.tv_sec = tspec.tv_nsec = 0;
822           rv = libc_pselect (libc_bits,
823                              readfds ? readfds : NULL,
824                              writefds ? writefds : NULL,
825                              exceptfds ? exceptfds : NULL, &tspec, sigmask);
826           if (rv != 0)
827             goto done;
828         }
829     }
830   while ((time_out == -1) || (clib_time_now (&ldpw->clib_time) < time_out));
831   rv = 0;
832
833 done:
834   /* TBD: set timeout to amount of time left */
835   clib_bitmap_zero (ldpw->rd_bitmap);
836   clib_bitmap_zero (ldpw->sid_rd_bitmap);
837   clib_bitmap_zero (ldpw->libc_rd_bitmap);
838   clib_bitmap_zero (ldpw->wr_bitmap);
839   clib_bitmap_zero (ldpw->sid_wr_bitmap);
840   clib_bitmap_zero (ldpw->libc_wr_bitmap);
841   clib_bitmap_zero (ldpw->ex_bitmap);
842   clib_bitmap_zero (ldpw->sid_ex_bitmap);
843   clib_bitmap_zero (ldpw->libc_ex_bitmap);
844
845   return rv;
846 }
847
848 int
849 select (int nfds, fd_set * __restrict readfds,
850         fd_set * __restrict writefds,
851         fd_set * __restrict exceptfds, struct timeval *__restrict timeout)
852 {
853   struct timespec tspec;
854
855   if (timeout)
856     {
857       tspec.tv_sec = timeout->tv_sec;
858       tspec.tv_nsec = timeout->tv_usec * 1000;
859     }
860   return ldp_pselect (nfds, readfds, writefds, exceptfds,
861                       timeout ? &tspec : NULL, NULL);
862 }
863
864 #ifdef __USE_XOPEN2K
865 int
866 pselect (int nfds, fd_set * __restrict readfds,
867          fd_set * __restrict writefds,
868          fd_set * __restrict exceptfds,
869          const struct timespec *__restrict timeout,
870          const __sigset_t * __restrict sigmask)
871 {
872   return ldp_pselect (nfds, readfds, writefds, exceptfds, timeout, 0);
873 }
874 #endif
875
876 int
877 socket (int domain, int type, int protocol)
878 {
879   int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
880   u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0;
881   vls_handle_t vlsh;
882
883   if ((errno = -ldp_init ()))
884     return -1;
885
886   if (((domain == AF_INET) || (domain == AF_INET6)) &&
887       ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
888     {
889       u8 proto = ((sock_type == SOCK_DGRAM) ?
890                   VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP);
891
892       LDBG (0, "calling vls_create: proto %u (%s), is_nonblocking %u",
893             proto, vppcom_proto_str (proto), is_nonblocking);
894
895       vlsh = vls_create (proto, is_nonblocking);
896       if (vlsh < 0)
897         {
898           errno = -vlsh;
899           rv = -1;
900         }
901       else
902         {
903           rv = ldp_vlsh_to_fd (vlsh);
904         }
905     }
906   else
907     {
908       LDBG (0, "calling libc_socket");
909       rv = libc_socket (domain, type, protocol);
910     }
911
912   return rv;
913 }
914
915 /*
916  * Create two new sockets, of type TYPE in domain DOMAIN and using
917  * protocol PROTOCOL, which are connected to each other, and put file
918  * descriptors for them in FDS[0] and FDS[1].  If PROTOCOL is zero,
919  * one will be chosen automatically.
920  * Returns 0 on success, -1 for errors.
921  * */
922 int
923 socketpair (int domain, int type, int protocol, int fds[2])
924 {
925   int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
926
927   if ((errno = -ldp_init ()))
928     return -1;
929
930   if (((domain == AF_INET) || (domain == AF_INET6)) &&
931       ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
932     {
933       LDBG (0, "LDP-TBD");
934       errno = ENOSYS;
935       rv = -1;
936     }
937   else
938     {
939       LDBG (1, "calling libc_socketpair");
940       rv = libc_socketpair (domain, type, protocol, fds);
941     }
942
943   return rv;
944 }
945
946 int
947 bind (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
948 {
949   vls_handle_t vlsh;
950   int rv;
951
952   if ((errno = -ldp_init ()))
953     return -1;
954
955   vlsh = ldp_fd_to_vlsh (fd);
956   if (vlsh != VLS_INVALID_HANDLE)
957     {
958       vppcom_endpt_t ep;
959
960       switch (addr->sa_family)
961         {
962         case AF_INET:
963           if (len != sizeof (struct sockaddr_in))
964             {
965               LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET addr len %u!",
966                     fd, vlsh, len);
967               errno = EINVAL;
968               rv = -1;
969               goto done;
970             }
971           ep.is_ip4 = VPPCOM_IS_IP4;
972           ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
973           ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
974           break;
975
976         case AF_INET6:
977           if (len != sizeof (struct sockaddr_in6))
978             {
979               LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET6 addr len %u!",
980                     fd, vlsh, len);
981               errno = EINVAL;
982               rv = -1;
983               goto done;
984             }
985           ep.is_ip4 = VPPCOM_IS_IP6;
986           ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
987           ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
988           break;
989
990         default:
991           LDBG (0, "ERROR: fd %d: vlsh %u: Unsupported address family %u!",
992                 fd, vlsh, addr->sa_family);
993           errno = EAFNOSUPPORT;
994           rv = -1;
995           goto done;
996         }
997       LDBG (0, "fd %d: calling vls_bind: vlsh %u, addr %p, len %u", fd, vlsh,
998             addr, len);
999
1000       rv = vls_bind (vlsh, &ep);
1001       if (rv != VPPCOM_OK)
1002         {
1003           errno = -rv;
1004           rv = -1;
1005         }
1006     }
1007   else
1008     {
1009       LDBG (0, "fd %d: calling libc_bind: addr %p, len %u", fd, addr, len);
1010       rv = libc_bind (fd, addr, len);
1011     }
1012
1013 done:
1014   LDBG (1, "fd %d: returning %d", fd, rv);
1015
1016   return rv;
1017 }
1018
1019 static inline int
1020 ldp_copy_ep_to_sockaddr (__SOCKADDR_ARG addr, socklen_t * __restrict len,
1021                          vppcom_endpt_t * ep)
1022 {
1023   int rv = 0;
1024   int sa_len, copy_len;
1025
1026   if ((errno = -ldp_init ()))
1027     return -1;
1028
1029   if (addr && len && ep)
1030     {
1031       addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
1032       switch (addr->sa_family)
1033         {
1034         case AF_INET:
1035           ((struct sockaddr_in *) addr)->sin_port = ep->port;
1036           if (*len > sizeof (struct sockaddr_in))
1037             *len = sizeof (struct sockaddr_in);
1038           sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
1039           copy_len = *len - sa_len;
1040           if (copy_len > 0)
1041             memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
1042                     copy_len);
1043           break;
1044
1045         case AF_INET6:
1046           ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
1047           if (*len > sizeof (struct sockaddr_in6))
1048             *len = sizeof (struct sockaddr_in6);
1049           sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
1050           copy_len = *len - sa_len;
1051           if (copy_len > 0)
1052             memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
1053                     __in6_u.__u6_addr8, ep->ip, copy_len);
1054           break;
1055
1056         default:
1057           /* Not possible */
1058           rv = -EAFNOSUPPORT;
1059           break;
1060         }
1061     }
1062   return rv;
1063 }
1064
1065 int
1066 getsockname (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
1067 {
1068   vls_handle_t vlsh;
1069   int rv;
1070
1071   if ((errno = -ldp_init ()))
1072     return -1;
1073
1074   vlsh = ldp_fd_to_vlsh (fd);
1075   if (vlsh != VLS_INVALID_HANDLE)
1076     {
1077       vppcom_endpt_t ep;
1078       u8 addr_buf[sizeof (struct in6_addr)];
1079       u32 size = sizeof (ep);
1080
1081       ep.ip = addr_buf;
1082
1083       rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
1084       if (rv != VPPCOM_OK)
1085         {
1086           errno = -rv;
1087           rv = -1;
1088         }
1089       else
1090         {
1091           rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
1092           if (rv != VPPCOM_OK)
1093             {
1094               errno = -rv;
1095               rv = -1;
1096             }
1097         }
1098     }
1099   else
1100     {
1101       rv = libc_getsockname (fd, addr, len);
1102     }
1103
1104   return rv;
1105 }
1106
1107 int
1108 connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
1109 {
1110   vls_handle_t vlsh;
1111   int rv;
1112
1113   if ((errno = -ldp_init ()))
1114     return -1;
1115
1116   if (!addr)
1117     {
1118       LDBG (0, "ERROR: fd %d: NULL addr, len %u", fd, len);
1119       errno = EINVAL;
1120       rv = -1;
1121       goto done;
1122     }
1123
1124   vlsh = ldp_fd_to_vlsh (fd);
1125   if (vlsh != VLS_INVALID_HANDLE)
1126     {
1127       vppcom_endpt_t ep;
1128
1129       switch (addr->sa_family)
1130         {
1131         case AF_INET:
1132           if (len != sizeof (struct sockaddr_in))
1133             {
1134               LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET addr len %u!",
1135                     fd, vlsh, len);
1136               errno = EINVAL;
1137               rv = -1;
1138               goto done;
1139             }
1140           ep.is_ip4 = VPPCOM_IS_IP4;
1141           ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1142           ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1143           break;
1144
1145         case AF_INET6:
1146           if (len != sizeof (struct sockaddr_in6))
1147             {
1148               LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET6 addr len %u!",
1149                     fd, vlsh, len);
1150               errno = EINVAL;
1151               rv = -1;
1152               goto done;
1153             }
1154           ep.is_ip4 = VPPCOM_IS_IP6;
1155           ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1156           ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1157           break;
1158
1159         default:
1160           LDBG (0, "fd %d: ERROR vlsh %u: Unsupported address family %u!",
1161                 fd, vlsh, addr->sa_family);
1162           errno = EAFNOSUPPORT;
1163           rv = -1;
1164           goto done;
1165         }
1166       LDBG (0, "fd %d: calling vls_connect(): vlsh %u addr %p len %u", fd,
1167             vlsh, addr, len);
1168
1169       rv = vls_connect (vlsh, &ep);
1170       if (rv != VPPCOM_OK)
1171         {
1172           errno = -rv;
1173           rv = -1;
1174         }
1175     }
1176   else
1177     {
1178       LDBG (0, "fd %d: calling libc_connect(): addr %p, len %u",
1179             fd, addr, len);
1180
1181       rv = libc_connect (fd, addr, len);
1182     }
1183
1184 done:
1185   LDBG (1, "fd %d: returning %d (0x%x)", fd, rv, rv);
1186   return rv;
1187 }
1188
1189 int
1190 getpeername (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
1191 {
1192   vls_handle_t vlsh;
1193   int rv;
1194
1195   if ((errno = -ldp_init ()))
1196     return -1;
1197
1198   vlsh = ldp_fd_to_vlsh (fd);
1199   if (vlsh != VLS_INVALID_HANDLE)
1200     {
1201       vppcom_endpt_t ep;
1202       u8 addr_buf[sizeof (struct in6_addr)];
1203       u32 size = sizeof (ep);
1204
1205       ep.ip = addr_buf;
1206       rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size);
1207       if (rv != VPPCOM_OK)
1208         {
1209           errno = -rv;
1210           rv = -1;
1211         }
1212       else
1213         {
1214           rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
1215           if (rv != VPPCOM_OK)
1216             {
1217               errno = -rv;
1218               rv = -1;
1219             }
1220         }
1221     }
1222   else
1223     {
1224       rv = libc_getpeername (fd, addr, len);
1225     }
1226
1227   return rv;
1228 }
1229
1230 ssize_t
1231 send (int fd, const void *buf, size_t n, int flags)
1232 {
1233   vls_handle_t vlsh = ldp_fd_to_vlsh (fd);
1234   ssize_t size;
1235
1236   if ((errno = -ldp_init ()))
1237     return -1;
1238
1239   if (vlsh != VLS_INVALID_HANDLE)
1240     {
1241       size = vls_sendto (vlsh, (void *) buf, n, flags, NULL);
1242       if (size < VPPCOM_OK)
1243         {
1244           errno = -size;
1245           size = -1;
1246         }
1247     }
1248   else
1249     {
1250       size = libc_send (fd, buf, n, flags);
1251     }
1252
1253   return size;
1254 }
1255
1256 ssize_t
1257 sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
1258 {
1259   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
1260   vls_handle_t vlsh;
1261   ssize_t size = 0;
1262
1263   if ((errno = -ldp_init ()))
1264     return -1;
1265
1266   vlsh = ldp_fd_to_vlsh (out_fd);
1267   if (vlsh != VLS_INVALID_HANDLE)
1268     {
1269       int rv;
1270       ssize_t results = 0;
1271       size_t n_bytes_left = len;
1272       size_t bytes_to_read;
1273       int nbytes;
1274       u8 eagain = 0;
1275       u32 flags, flags_len = sizeof (flags);
1276
1277       rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &flags_len);
1278       if (PREDICT_FALSE (rv != VPPCOM_OK))
1279         {
1280           LDBG (0, "ERROR: out fd %d: vls_attr: vlsh %u, returned %d (%s)!",
1281                 out_fd, vlsh, rv, vppcom_retval_str (rv));
1282
1283           vec_reset_length (ldpw->io_buffer);
1284           errno = -rv;
1285           size = -1;
1286           goto done;
1287         }
1288
1289       if (offset)
1290         {
1291           off_t off = lseek (in_fd, *offset, SEEK_SET);
1292           if (PREDICT_FALSE (off == -1))
1293             {
1294               size = -1;
1295               goto done;
1296             }
1297
1298           ASSERT (off == *offset);
1299         }
1300
1301       do
1302         {
1303           size = vls_attr (vlsh, VPPCOM_ATTR_GET_NWRITE, 0, 0);
1304           if (size < 0)
1305             {
1306               LDBG (0, "ERROR: fd %d: vls_attr: vlsh %u returned %d (%s)!",
1307                     out_fd, vlsh, size, vppcom_retval_str (size));
1308               vec_reset_length (ldpw->io_buffer);
1309               errno = -size;
1310               size = -1;
1311               goto done;
1312             }
1313
1314           bytes_to_read = size;
1315           if (bytes_to_read == 0)
1316             {
1317               if (flags & O_NONBLOCK)
1318                 {
1319                   if (!results)
1320                     eagain = 1;
1321                   goto update_offset;
1322                 }
1323               else
1324                 continue;
1325             }
1326           bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
1327           vec_validate (ldpw->io_buffer, bytes_to_read);
1328           nbytes = libc_read (in_fd, ldpw->io_buffer, bytes_to_read);
1329           if (nbytes < 0)
1330             {
1331               if (results == 0)
1332                 {
1333                   vec_reset_length (ldpw->io_buffer);
1334                   size = -1;
1335                   goto done;
1336                 }
1337               goto update_offset;
1338             }
1339
1340           size = vls_write (vlsh, ldpw->io_buffer, nbytes);
1341           if (size < 0)
1342             {
1343               if (size == VPPCOM_EAGAIN)
1344                 {
1345                   if (flags & O_NONBLOCK)
1346                     {
1347                       if (!results)
1348                         eagain = 1;
1349                       goto update_offset;
1350                     }
1351                   else
1352                     continue;
1353                 }
1354               if (results == 0)
1355                 {
1356                   vec_reset_length (ldpw->io_buffer);
1357                   errno = -size;
1358                   size = -1;
1359                   goto done;
1360                 }
1361               goto update_offset;
1362             }
1363
1364           results += nbytes;
1365           ASSERT (n_bytes_left >= nbytes);
1366           n_bytes_left = n_bytes_left - nbytes;
1367         }
1368       while (n_bytes_left > 0);
1369
1370     update_offset:
1371       vec_reset_length (ldpw->io_buffer);
1372       if (offset)
1373         {
1374           off_t off = lseek (in_fd, *offset, SEEK_SET);
1375           if (PREDICT_FALSE (off == -1))
1376             {
1377               size = -1;
1378               goto done;
1379             }
1380
1381           ASSERT (off == *offset);
1382           *offset += results + 1;
1383         }
1384       if (eagain)
1385         {
1386           errno = EAGAIN;
1387           size = -1;
1388         }
1389       else
1390         size = results;
1391     }
1392   else
1393     {
1394       size = libc_sendfile (out_fd, in_fd, offset, len);
1395     }
1396
1397 done:
1398   return size;
1399 }
1400
1401 ssize_t
1402 sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len)
1403 {
1404   return sendfile (out_fd, in_fd, offset, len);
1405 }
1406
1407 ssize_t
1408 recv (int fd, void *buf, size_t n, int flags)
1409 {
1410   vls_handle_t vlsh;
1411   ssize_t size;
1412
1413   if ((errno = -ldp_init ()))
1414     return -1;
1415
1416   vlsh = ldp_fd_to_vlsh (fd);
1417   if (vlsh != VLS_INVALID_HANDLE)
1418     {
1419       size = vls_recvfrom (vlsh, buf, n, flags, NULL);
1420       if (size < 0)
1421         errno = -size;
1422     }
1423   else
1424     {
1425       size = libc_recv (fd, buf, n, flags);
1426     }
1427
1428   return size;
1429 }
1430
1431 ssize_t
1432 sendto (int fd, const void *buf, size_t n, int flags,
1433         __CONST_SOCKADDR_ARG addr, socklen_t addr_len)
1434 {
1435   vls_handle_t vlsh;
1436   ssize_t size;
1437
1438   if ((errno = -ldp_init ()))
1439     return -1;
1440
1441   vlsh = ldp_fd_to_vlsh (fd);
1442   if (vlsh != INVALID_SESSION_ID)
1443     {
1444       vppcom_endpt_t *ep = 0;
1445       vppcom_endpt_t _ep;
1446
1447       if (addr)
1448         {
1449           ep = &_ep;
1450           switch (addr->sa_family)
1451             {
1452             case AF_INET:
1453               ep->is_ip4 = VPPCOM_IS_IP4;
1454               ep->ip =
1455                 (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr;
1456               ep->port =
1457                 (uint16_t) ((const struct sockaddr_in *) addr)->sin_port;
1458               break;
1459
1460             case AF_INET6:
1461               ep->is_ip4 = VPPCOM_IS_IP6;
1462               ep->ip =
1463                 (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1464               ep->port =
1465                 (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port;
1466               break;
1467
1468             default:
1469               errno = EAFNOSUPPORT;
1470               size = -1;
1471               goto done;
1472             }
1473         }
1474
1475       size = vls_sendto (vlsh, (void *) buf, n, flags, ep);
1476       if (size < 0)
1477         {
1478           errno = -size;
1479           size = -1;
1480         }
1481     }
1482   else
1483     {
1484       size = libc_sendto (fd, buf, n, flags, addr, addr_len);
1485     }
1486
1487 done:
1488   return size;
1489 }
1490
1491 ssize_t
1492 recvfrom (int fd, void *__restrict buf, size_t n, int flags,
1493           __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
1494 {
1495   vls_handle_t sid;
1496   ssize_t size;
1497
1498   if ((errno = -ldp_init ()))
1499     return -1;
1500
1501   sid = ldp_fd_to_vlsh (fd);
1502   if (sid != VLS_INVALID_HANDLE)
1503     {
1504       vppcom_endpt_t ep;
1505       u8 src_addr[sizeof (struct sockaddr_in6)];
1506
1507       if (addr)
1508         {
1509           ep.ip = src_addr;
1510           size = vls_recvfrom (sid, buf, n, flags, &ep);
1511
1512           if (size > 0)
1513             size = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
1514         }
1515       else
1516         size = vls_recvfrom (sid, buf, n, flags, NULL);
1517
1518       if (size < 0)
1519         {
1520           errno = -size;
1521           size = -1;
1522         }
1523     }
1524   else
1525     {
1526       size = libc_recvfrom (fd, buf, n, flags, addr, addr_len);
1527     }
1528
1529   return size;
1530 }
1531
1532 ssize_t
1533 sendmsg (int fd, const struct msghdr * message, int flags)
1534 {
1535   vls_handle_t vlsh;
1536   ssize_t size;
1537
1538   if ((errno = -ldp_init ()))
1539     return -1;
1540
1541   vlsh = ldp_fd_to_vlsh (fd);
1542   if (vlsh != VLS_INVALID_HANDLE)
1543     {
1544       LDBG (0, "LDP-TBD");
1545       errno = ENOSYS;
1546       size = -1;
1547     }
1548   else
1549     {
1550       size = libc_sendmsg (fd, message, flags);
1551     }
1552
1553   return size;
1554 }
1555
1556 #ifdef USE_GNU
1557 int
1558 sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
1559 {
1560   ssize_t size;
1561   const char *func_str;
1562   u32 sh = ldp_fd_to_vlsh (fd);
1563
1564   if ((errno = -ldp_init ()))
1565     return -1;
1566
1567   if (sh != INVALID_SESSION_ID)
1568     {
1569       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1570       errno = ENOSYS;
1571       size = -1;
1572     }
1573   else
1574     {
1575       func_str = "libc_sendmmsg";
1576
1577       if (LDP_DEBUG > 2)
1578         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1579                       "vmessages %p, vlen %u, flags 0x%x",
1580                       getpid (), fd, fd, func_str, vmessages, vlen, flags);
1581
1582       size = libc_sendmmsg (fd, vmessages, vlen, flags);
1583     }
1584
1585   if (LDP_DEBUG > 2)
1586     {
1587       if (size < 0)
1588         {
1589           int errno_val = errno;
1590           perror (func_str);
1591           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1592                         "rv %d, errno = %d", getpid (), fd, fd,
1593                         func_str, size, errno_val);
1594           errno = errno_val;
1595         }
1596       else
1597         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1598                       getpid (), fd, fd, size, size);
1599     }
1600   return size;
1601 }
1602 #endif
1603
1604 ssize_t
1605 recvmsg (int fd, struct msghdr * message, int flags)
1606 {
1607   vls_handle_t vlsh;
1608   ssize_t size;
1609
1610   if ((errno = -ldp_init ()))
1611     return -1;
1612
1613   vlsh = ldp_fd_to_vlsh (fd);
1614   if (vlsh != VLS_INVALID_HANDLE)
1615     {
1616       LDBG (0, "LDP-TBD");
1617       errno = ENOSYS;
1618       size = -1;
1619     }
1620   else
1621     {
1622       size = libc_recvmsg (fd, message, flags);
1623     }
1624
1625   return size;
1626 }
1627
1628 #ifdef USE_GNU
1629 int
1630 recvmmsg (int fd, struct mmsghdr *vmessages,
1631           unsigned int vlen, int flags, struct timespec *tmo)
1632 {
1633   ssize_t size;
1634   const char *func_str;
1635   u32 sh = ldp_fd_to_vlsh (fd);
1636
1637   if ((errno = -ldp_init ()))
1638     return -1;
1639
1640   if (sh != INVALID_SESSION_ID)
1641     {
1642       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1643       errno = ENOSYS;
1644       size = -1;
1645     }
1646   else
1647     {
1648       func_str = "libc_recvmmsg";
1649
1650       if (LDP_DEBUG > 2)
1651         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1652                       "vmessages %p, vlen %u, flags 0x%x, tmo %p",
1653                       getpid (), fd, fd, func_str, vmessages, vlen,
1654                       flags, tmo);
1655
1656       size = libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
1657     }
1658
1659   if (LDP_DEBUG > 2)
1660     {
1661       if (size < 0)
1662         {
1663           int errno_val = errno;
1664           perror (func_str);
1665           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1666                         "rv %d, errno = %d", getpid (), fd, fd,
1667                         func_str, size, errno_val);
1668           errno = errno_val;
1669         }
1670       else
1671         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1672                       getpid (), fd, fd, size, size);
1673     }
1674   return size;
1675 }
1676 #endif
1677
1678 int
1679 getsockopt (int fd, int level, int optname,
1680             void *__restrict optval, socklen_t * __restrict optlen)
1681 {
1682   vls_handle_t vlsh;
1683   int rv;
1684
1685   if ((errno = -ldp_init ()))
1686     return -1;
1687
1688   vlsh = ldp_fd_to_vlsh (fd);
1689   if (vlsh != VLS_INVALID_HANDLE)
1690     {
1691       rv = -EOPNOTSUPP;
1692
1693       switch (level)
1694         {
1695         case SOL_TCP:
1696           switch (optname)
1697             {
1698             case TCP_NODELAY:
1699               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_NODELAY,
1700                              optval, optlen);
1701               break;
1702             case TCP_MAXSEG:
1703               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_USER_MSS,
1704                              optval, optlen);
1705               break;
1706             case TCP_KEEPIDLE:
1707               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
1708                              optval, optlen);
1709               break;
1710             case TCP_KEEPINTVL:
1711               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
1712                              optval, optlen);
1713               break;
1714             case TCP_INFO:
1715               if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
1716                 {
1717                   LDBG (1, "fd %d: vlsh %u SOL_TCP, TCP_INFO, optval %p, "
1718                         "optlen %d: #LDP-NOP#", fd, vlsh, optval, *optlen);
1719                   memset (optval, 0, *optlen);
1720                   rv = VPPCOM_OK;
1721                 }
1722               else
1723                 rv = -EFAULT;
1724               break;
1725             default:
1726               LDBG (0, "ERROR: fd %d: getsockopt SOL_TCP: sid %u, "
1727                     "optname %d unsupported!", fd, vlsh, optname);
1728               break;
1729             }
1730           break;
1731         case SOL_IPV6:
1732           switch (optname)
1733             {
1734             case IPV6_V6ONLY:
1735               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_V6ONLY, optval, optlen);
1736               break;
1737             default:
1738               LDBG (0, "ERROR: fd %d: getsockopt SOL_IPV6: vlsh %u "
1739                     "optname %d unsupported!", fd, vlsh, optname);
1740               break;
1741             }
1742           break;
1743         case SOL_SOCKET:
1744           switch (optname)
1745             {
1746             case SO_ACCEPTCONN:
1747               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LISTEN, optval, optlen);
1748               break;
1749             case SO_KEEPALIVE:
1750               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_KEEPALIVE, optval, optlen);
1751               break;
1752             case SO_PROTOCOL:
1753               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PROTOCOL, optval, optlen);
1754               *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
1755               break;
1756             case SO_SNDBUF:
1757               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TX_FIFO_LEN,
1758                              optval, optlen);
1759               break;
1760             case SO_RCVBUF:
1761               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_RX_FIFO_LEN,
1762                              optval, optlen);
1763               break;
1764             case SO_REUSEADDR:
1765               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEADDR, optval, optlen);
1766               break;
1767             case SO_BROADCAST:
1768               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_BROADCAST, optval, optlen);
1769               break;
1770             case SO_ERROR:
1771               rv = vls_attr (vlsh, VPPCOM_ATTR_GET_ERROR, optval, optlen);
1772               break;
1773             default:
1774               LDBG (0, "ERROR: fd %d: getsockopt SOL_SOCKET: vlsh %u "
1775                     "optname %d unsupported!", fd, vlsh, optname);
1776               break;
1777             }
1778           break;
1779         default:
1780           break;
1781         }
1782
1783       if (rv != VPPCOM_OK)
1784         {
1785           errno = -rv;
1786           rv = -1;
1787         }
1788     }
1789   else
1790     {
1791       rv = libc_getsockopt (fd, level, optname, optval, optlen);
1792     }
1793
1794   return rv;
1795 }
1796
1797 int
1798 setsockopt (int fd, int level, int optname,
1799             const void *optval, socklen_t optlen)
1800 {
1801   vls_handle_t vlsh;
1802   int rv;
1803
1804   if ((errno = -ldp_init ()))
1805     return -1;
1806
1807   vlsh = ldp_fd_to_vlsh (fd);
1808   if (vlsh != VLS_INVALID_HANDLE)
1809     {
1810       rv = -EOPNOTSUPP;
1811
1812       switch (level)
1813         {
1814         case SOL_TCP:
1815           switch (optname)
1816             {
1817             case TCP_NODELAY:
1818               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_NODELAY,
1819                              (void *) optval, &optlen);
1820               break;
1821             case TCP_MAXSEG:
1822               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_USER_MSS,
1823                              (void *) optval, &optlen);
1824               break;
1825             case TCP_KEEPIDLE:
1826               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
1827                              (void *) optval, &optlen);
1828               break;
1829             case TCP_KEEPINTVL:
1830               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
1831                              (void *) optval, &optlen);
1832               break;
1833             default:
1834               LDBG (0, "ERROR: fd %d: setsockopt() SOL_TCP: vlsh %u"
1835                     "optname %d unsupported!", fd, vlsh, optname);
1836               break;
1837             }
1838           break;
1839         case SOL_IPV6:
1840           switch (optname)
1841             {
1842             case IPV6_V6ONLY:
1843               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_V6ONLY,
1844                              (void *) optval, &optlen);
1845               break;
1846             default:
1847               LDBG (0, "ERROR: fd %d: setsockopt SOL_IPV6: vlsh %u"
1848                     "optname %d unsupported!", fd, vlsh, optname);
1849               break;
1850             }
1851           break;
1852         case SOL_SOCKET:
1853           switch (optname)
1854             {
1855             case SO_KEEPALIVE:
1856               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_KEEPALIVE,
1857                              (void *) optval, &optlen);
1858               break;
1859             case SO_REUSEADDR:
1860               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEADDR,
1861                              (void *) optval, &optlen);
1862               break;
1863             case SO_BROADCAST:
1864               rv = vls_attr (vlsh, VPPCOM_ATTR_SET_BROADCAST,
1865                              (void *) optval, &optlen);
1866               break;
1867             default:
1868               LDBG (0, "ERROR: fd %d: setsockopt SOL_SOCKET: vlsh %u "
1869                     "optname %d unsupported!", fd, vlsh, optname);
1870               break;
1871             }
1872           break;
1873         default:
1874           break;
1875         }
1876
1877       if (rv != VPPCOM_OK)
1878         {
1879           errno = -rv;
1880           rv = -1;
1881         }
1882     }
1883   else
1884     {
1885       rv = libc_setsockopt (fd, level, optname, optval, optlen);
1886     }
1887
1888   return rv;
1889 }
1890
1891 int
1892 listen (int fd, int n)
1893 {
1894   vls_handle_t vlsh;
1895   int rv;
1896
1897   if ((errno = -ldp_init ()))
1898     return -1;
1899
1900   vlsh = ldp_fd_to_vlsh (fd);
1901   if (vlsh != VLS_INVALID_HANDLE)
1902     {
1903       LDBG (0, "fd %d: calling vls_listen: vlsh %u, n %d", fd, vlsh, n);
1904
1905       rv = vls_listen (vlsh, n);
1906       if (rv != VPPCOM_OK)
1907         {
1908           errno = -rv;
1909           rv = -1;
1910         }
1911     }
1912   else
1913     {
1914       LDBG (0, "fd %d: calling libc_listen(): n %d", fd, n);
1915       rv = libc_listen (fd, n);
1916     }
1917
1918   LDBG (1, "fd %d: returning %d", fd, rv);
1919   return rv;
1920 }
1921
1922 static inline int
1923 ldp_accept4 (int listen_fd, __SOCKADDR_ARG addr,
1924              socklen_t * __restrict addr_len, int flags)
1925 {
1926   vls_handle_t listen_vlsh, accept_vlsh;
1927   int rv;
1928
1929   if ((errno = -ldp_init ()))
1930     return -1;
1931
1932   listen_vlsh = ldp_fd_to_vlsh (listen_fd);
1933   if (listen_vlsh != VLS_INVALID_HANDLE)
1934     {
1935       vppcom_endpt_t ep;
1936       u8 src_addr[sizeof (struct sockaddr_in6)];
1937       memset (&ep, 0, sizeof (ep));
1938       ep.ip = src_addr;
1939
1940       LDBG (0, "listen fd %d: calling vppcom_session_accept: listen sid %u,"
1941             " ep %p, flags 0x%x", listen_fd, listen_vlsh, ep, flags);
1942
1943       accept_vlsh = vls_accept (listen_vlsh, &ep, flags);
1944       if (accept_vlsh < 0)
1945         {
1946           errno = -accept_vlsh;
1947           rv = -1;
1948         }
1949       else
1950         {
1951           rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
1952           if (rv != VPPCOM_OK)
1953             {
1954               (void) vls_close (accept_vlsh);
1955               errno = -rv;
1956               rv = -1;
1957             }
1958           else
1959             {
1960               rv = ldp_vlsh_to_fd (accept_vlsh);
1961             }
1962         }
1963     }
1964   else
1965     {
1966       LDBG (0, "listen fd %d: calling libc_accept4(): addr %p, addr_len %p,"
1967             " flags 0x%x", listen_fd, addr, addr_len, flags);
1968
1969       rv = libc_accept4 (listen_fd, addr, addr_len, flags);
1970     }
1971
1972   LDBG (1, "listen fd %d: accept returning %d", listen_fd, rv);
1973
1974   return rv;
1975 }
1976
1977 int
1978 accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
1979          int flags)
1980 {
1981   return ldp_accept4 (fd, addr, addr_len, flags);
1982 }
1983
1984 int
1985 accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
1986 {
1987   return ldp_accept4 (fd, addr, addr_len, 0);
1988 }
1989
1990 int
1991 shutdown (int fd, int how)
1992 {
1993   vls_handle_t vlsh;
1994   int rv = 0, flags;
1995   u32 flags_len = sizeof (flags);
1996
1997   if ((errno = -ldp_init ()))
1998     return -1;
1999
2000   vlsh = ldp_fd_to_vlsh (fd);
2001   if (vlsh != VLS_INVALID_HANDLE)
2002     {
2003       LDBG (0, "called shutdown: fd %u vlsh %u how %d", fd, vlsh, how);
2004
2005       if (vls_attr (vlsh, VPPCOM_ATTR_SET_SHUT, &how, &flags_len))
2006         {
2007           close (fd);
2008           return -1;
2009         }
2010
2011       if (vls_attr (vlsh, VPPCOM_ATTR_GET_SHUT, &flags, &flags_len))
2012         {
2013           close (fd);
2014           return -1;
2015         }
2016
2017       if (flags == SHUT_RDWR)
2018         rv = close (fd);
2019     }
2020   else
2021     {
2022       LDBG (0, "fd %d: calling libc_shutdown: how %d", fd, how);
2023       rv = libc_shutdown (fd, how);
2024     }
2025
2026   return rv;
2027 }
2028
2029 int
2030 epoll_create1 (int flags)
2031 {
2032   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
2033   vls_handle_t vlsh;
2034   int rv;
2035
2036   if ((errno = -ldp_init ()))
2037     return -1;
2038
2039   if (ldp->vcl_needs_real_epoll)
2040     {
2041       rv = libc_epoll_create1 (flags);
2042       ldp->vcl_needs_real_epoll = 0;
2043       ldpw->vcl_mq_epfd = rv;
2044       LDBG (0, "created vcl epfd %u", rv);
2045       return rv;
2046     }
2047
2048   vlsh = vls_epoll_create ();
2049   if (PREDICT_FALSE (vlsh == VLS_INVALID_HANDLE))
2050     {
2051       errno = -vlsh;
2052       rv = -1;
2053     }
2054   else
2055     {
2056       rv = ldp_vlsh_to_fd (vlsh);
2057     }
2058   LDBG (0, "epoll_create epfd %u vlsh %u", rv, vlsh);
2059   return rv;
2060 }
2061
2062 int
2063 epoll_create (int size)
2064 {
2065   return epoll_create1 (0);
2066 }
2067
2068 int
2069 epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
2070 {
2071   vls_handle_t vep_vlsh, vlsh;
2072   int rv;
2073
2074   if ((errno = -ldp_init ()))
2075     return -1;
2076
2077   vep_vlsh = ldp_fd_to_vlsh (epfd);
2078   if (PREDICT_FALSE (vep_vlsh == VLS_INVALID_HANDLE))
2079     {
2080       /* The LDP epoll_create1 always creates VCL epfd's.
2081        * The app should never have a kernel base epoll fd unless it
2082        * was acquired outside of the LD_PRELOAD process context.
2083        * In any case, if we get one, punt it to libc_epoll_ctl.
2084        */
2085       LDBG (1, "epfd %d: calling libc_epoll_ctl: op %d, fd %d"
2086             " event %p", epfd, op, fd, event);
2087
2088       rv = libc_epoll_ctl (epfd, op, fd, event);
2089       goto done;
2090     }
2091
2092   vlsh = ldp_fd_to_vlsh (fd);
2093
2094   LDBG (0, "epfd %d ep_vlsh %d, fd %u vlsh %d, op %u", epfd, vep_vlsh, fd,
2095         vlsh, op);
2096
2097   if (vlsh != VLS_INVALID_HANDLE)
2098     {
2099       LDBG (1, "epfd %d: calling vls_epoll_ctl: ep_vlsh %d op %d, vlsh %u,"
2100             " event %p", epfd, vep_vlsh, vlsh, event);
2101
2102       rv = vls_epoll_ctl (vep_vlsh, op, vlsh, event);
2103       if (rv != VPPCOM_OK)
2104         {
2105           errno = -rv;
2106           rv = -1;
2107         }
2108     }
2109   else
2110     {
2111       int libc_epfd;
2112       u32 size = sizeof (epfd);
2113
2114       libc_epfd = vls_attr (vep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
2115       if (!libc_epfd)
2116         {
2117           LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
2118                 "EPOLL_CLOEXEC", epfd, vep_vlsh);
2119
2120           libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
2121           if (libc_epfd < 0)
2122             {
2123               rv = libc_epfd;
2124               goto done;
2125             }
2126
2127           rv = vls_attr (vep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd,
2128                          &size);
2129           if (rv < 0)
2130             {
2131               errno = -rv;
2132               rv = -1;
2133               goto done;
2134             }
2135         }
2136       else if (PREDICT_FALSE (libc_epfd < 0))
2137         {
2138           errno = -epfd;
2139           rv = -1;
2140           goto done;
2141         }
2142
2143       LDBG (1, "epfd %d: calling libc_epoll_ctl: libc_epfd %d, op %d, fd %d,"
2144             " event %p", epfd, libc_epfd, op, fd, event);
2145
2146       rv = libc_epoll_ctl (libc_epfd, op, fd, event);
2147     }
2148
2149 done:
2150   return rv;
2151 }
2152
2153 static inline int
2154 ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
2155                  int timeout, const sigset_t * sigmask)
2156 {
2157   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
2158   double time_to_wait = (double) 0, time_out, now = 0;
2159   int libc_epfd, rv = 0;
2160   vls_handle_t ep_vlsh;
2161
2162   if ((errno = -ldp_init ()))
2163     return -1;
2164
2165   if (PREDICT_FALSE (!events || (timeout < -1)))
2166     {
2167       errno = EFAULT;
2168       return -1;
2169     }
2170
2171   if (epfd == ldpw->vcl_mq_epfd)
2172     return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
2173
2174   ep_vlsh = ldp_fd_to_vlsh (epfd);
2175   if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
2176     {
2177       LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
2178       errno = EBADFD;
2179       return -1;
2180     }
2181
2182   time_to_wait = ((timeout >= 0) ? (double) timeout / 1000 : 0);
2183   time_out = clib_time_now (&ldpw->clib_time) + time_to_wait;
2184
2185   libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
2186   if (PREDICT_FALSE (libc_epfd < 0))
2187     {
2188       errno = -libc_epfd;
2189       rv = -1;
2190       goto done;
2191     }
2192
2193   LDBG (2, "epfd %d: vep_idx %d, libc_epfd %d, events %p, maxevents %d, "
2194         "timeout %d, sigmask %p: time_to_wait %.02f", epfd, ep_vlsh,
2195         libc_epfd, events, maxevents, timeout, sigmask, time_to_wait,
2196         time_out);
2197   do
2198     {
2199       if (!ldpw->epoll_wait_vcl)
2200         {
2201           rv = vls_epoll_wait (ep_vlsh, events, maxevents, 0);
2202           if (rv > 0)
2203             {
2204               ldpw->epoll_wait_vcl = 1;
2205               goto done;
2206             }
2207           else if (rv < 0)
2208             {
2209               errno = -rv;
2210               rv = -1;
2211               goto done;
2212             }
2213         }
2214       else
2215         ldpw->epoll_wait_vcl = 0;
2216
2217       if (libc_epfd > 0)
2218         {
2219           rv = libc_epoll_pwait (libc_epfd, events, maxevents, 0, sigmask);
2220           if (rv != 0)
2221             goto done;
2222         }
2223
2224       if (timeout != -1)
2225         now = clib_time_now (&ldpw->clib_time);
2226     }
2227   while (now < time_out);
2228
2229 done:
2230   return rv;
2231 }
2232
2233 int
2234 epoll_pwait (int epfd, struct epoll_event *events,
2235              int maxevents, int timeout, const sigset_t * sigmask)
2236 {
2237   return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
2238 }
2239
2240 int
2241 epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
2242 {
2243   return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL);
2244 }
2245
2246 int
2247 poll (struct pollfd *fds, nfds_t nfds, int timeout)
2248 {
2249   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
2250   int rv, i, n_revents = 0;
2251   vls_handle_t vlsh;
2252   vcl_poll_t *vp;
2253   double wait_for_time;
2254
2255   LDBG (3, "fds %p, nfds %d, timeout %d", fds, nfds, timeout);
2256
2257   if (timeout >= 0)
2258     wait_for_time = (f64) timeout / 1000;
2259   else
2260     wait_for_time = -1;
2261
2262   for (i = 0; i < nfds; i++)
2263     {
2264       if (fds[i].fd < 0)
2265         continue;
2266
2267       vlsh = ldp_fd_to_vlsh (fds[i].fd);
2268       if (vlsh != VLS_INVALID_HANDLE)
2269         {
2270           fds[i].fd = -fds[i].fd;
2271           vec_add2 (ldpw->vcl_poll, vp, 1);
2272           vp->fds_ndx = i;
2273           vp->sh = vlsh_to_sh (vlsh);
2274           vp->events = fds[i].events;
2275 #ifdef __USE_XOPEN2K
2276           if (fds[i].events & POLLRDNORM)
2277             vp->events |= POLLIN;
2278           if (fds[i].events & POLLWRNORM)
2279             vp->events |= POLLOUT;
2280 #endif
2281           vp->revents = fds[i].revents;
2282         }
2283       else
2284         {
2285           vec_add1 (ldpw->libc_poll, fds[i]);
2286           vec_add1 (ldpw->libc_poll_idxs, i);
2287         }
2288     }
2289
2290   do
2291     {
2292       if (vec_len (ldpw->vcl_poll))
2293         {
2294           rv = vppcom_poll (ldpw->vcl_poll, vec_len (ldpw->vcl_poll), 0);
2295           if (rv < 0)
2296             {
2297               errno = -rv;
2298               rv = -1;
2299               goto done;
2300             }
2301           else
2302             n_revents += rv;
2303         }
2304
2305       if (vec_len (ldpw->libc_poll))
2306         {
2307           rv = libc_poll (ldpw->libc_poll, vec_len (ldpw->libc_poll), 0);
2308           if (rv < 0)
2309             goto done;
2310           else
2311             n_revents += rv;
2312         }
2313
2314       if (n_revents)
2315         {
2316           rv = n_revents;
2317           goto done;
2318         }
2319     }
2320   while ((wait_for_time == -1) ||
2321          (clib_time_now (&ldpw->clib_time) < wait_for_time));
2322   rv = 0;
2323
2324 done:
2325   vec_foreach (vp, ldpw->vcl_poll)
2326   {
2327     fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
2328     fds[vp->fds_ndx].revents = vp->revents;
2329 #ifdef __USE_XOPEN2K
2330     if ((fds[vp->fds_ndx].revents & POLLIN) &&
2331         (fds[vp->fds_ndx].events & POLLRDNORM))
2332       fds[vp->fds_ndx].revents |= POLLRDNORM;
2333     if ((fds[vp->fds_ndx].revents & POLLOUT) &&
2334         (fds[vp->fds_ndx].events & POLLWRNORM))
2335       fds[vp->fds_ndx].revents |= POLLWRNORM;
2336 #endif
2337   }
2338   vec_reset_length (ldpw->vcl_poll);
2339
2340   for (i = 0; i < vec_len (ldpw->libc_poll); i++)
2341     {
2342       fds[ldpw->libc_poll_idxs[i]].revents = ldpw->libc_poll[i].revents;
2343     }
2344   vec_reset_length (ldpw->libc_poll_idxs);
2345   vec_reset_length (ldpw->libc_poll);
2346
2347   return rv;
2348 }
2349
2350 #ifdef USE_GNU
2351 int
2352 ppoll (struct pollfd *fds, nfds_t nfds,
2353        const struct timespec *timeout, const sigset_t * sigmask)
2354 {
2355   if ((errno = -ldp_init ()))
2356     return -1;
2357
2358   clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2359   errno = ENOSYS;
2360
2361
2362   return -1;
2363 }
2364 #endif
2365
2366 void CONSTRUCTOR_ATTRIBUTE ldp_constructor (void);
2367
2368 void DESTRUCTOR_ATTRIBUTE ldp_destructor (void);
2369
2370 /*
2371  * This function is called when the library is loaded
2372  */
2373 void
2374 ldp_constructor (void)
2375 {
2376   swrap_constructor ();
2377   if (ldp_init () != 0)
2378     fprintf (stderr, "\nLDP<%d>: ERROR: ldp_constructor: failed!\n",
2379              getpid ());
2380   else if (LDP_DEBUG > 0)
2381     clib_warning ("LDP<%d>: LDP constructor: done!\n", getpid ());
2382 }
2383
2384 /*
2385  * This function is called when the library is unloaded
2386  */
2387 void
2388 ldp_destructor (void)
2389 {
2390   swrap_destructor ();
2391   if (ldp->init)
2392     ldp->init = 0;
2393
2394   /* Don't use clib_warning() here because that calls writev()
2395    * which will call ldp_init().
2396    */
2397   if (LDP_DEBUG > 0)
2398     printf ("%s:%d: LDP<%d>: LDP destructor: done!\n",
2399             __func__, __LINE__, getpid ());
2400 }
2401
2402
2403 /*
2404  * fd.io coding-style-patch-verification: ON
2405  *
2406  * Local Variables:
2407  * eval: (c-set-style "gnu")
2408  * End:
2409  */