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