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