ldp: avoid calling write in destructors
[vpp.git] / src / vcl / ldp.c
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <unistd.h>
16 #include <stdio.h>
17 #include <signal.h>
18 #include <dlfcn.h>
19 #include <pthread.h>
20 #include <time.h>
21 #include <stdarg.h>
22 #include <sys/resource.h>
23 #include <netinet/tcp.h>
24
25 #include <vcl/ldp_socket_wrapper.h>
26 #include <vcl/ldp.h>
27 #include <sys/time.h>
28
29 #include <vcl/vppcom.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_fd_entry_
55 {
56   u32 session_index;
57   u32 fd;
58   u32 fd_index;
59 } ldp_fd_entry_t;
60
61 typedef struct ldp_worker_ctx_
62 {
63   u8 *io_buffer;
64   clib_time_t clib_time;
65
66   /*
67    * Select state
68    */
69   clib_bitmap_t *rd_bitmap;
70   clib_bitmap_t *wr_bitmap;
71   clib_bitmap_t *ex_bitmap;
72   clib_bitmap_t *sid_rd_bitmap;
73   clib_bitmap_t *sid_wr_bitmap;
74   clib_bitmap_t *sid_ex_bitmap;
75   clib_bitmap_t *libc_rd_bitmap;
76   clib_bitmap_t *libc_wr_bitmap;
77   clib_bitmap_t *libc_ex_bitmap;
78   u8 select_vcl;
79
80   /*
81    * Poll state
82    */
83   vcl_poll_t *vcl_poll;
84   struct pollfd *libc_poll;
85   u16 *libc_poll_idxs;
86
87   /*
88    * Epoll state
89    */
90   u8 epoll_wait_vcl;
91   int vcl_mq_epfd;
92
93 } ldp_worker_ctx_t;
94
95 typedef struct
96 {
97   ldp_worker_ctx_t *workers;
98   int init;
99   char app_name[LDP_APP_NAME_MAX];
100   u32 sid_bit_val;
101   u32 sid_bit_mask;
102   u32 debug;
103   ldp_fd_entry_t *fd_pool;
104   clib_rwlock_t fd_table_lock;
105   uword *session_index_to_fd_table;
106
107   /** vcl needs next epoll_create to go to libc_epoll */
108   u8 vcl_needs_real_epoll;
109 } ldp_main_t;
110
111 #define LDP_DEBUG ldp->debug
112
113 #define LDBG(_lvl, _fmt, _args...)                                      \
114   if (ldp->debug > _lvl)                                                \
115     clib_warning (_fmt, ##_args)
116
117 static ldp_main_t ldp_main = {
118   .sid_bit_val = (1 << LDP_SID_BIT_MIN),
119   .sid_bit_mask = (1 << LDP_SID_BIT_MIN) - 1,
120   .debug = LDP_DEBUG_INIT,
121 };
122
123 static ldp_main_t *ldp = &ldp_main;
124
125 static inline ldp_worker_ctx_t *
126 ldp_worker_get_current (void)
127 {
128   return (ldp->workers + vppcom_worker_index ());
129 }
130
131 /*
132  * RETURN:  0 on success or -1 on error.
133  * */
134 static inline void
135 ldp_set_app_name (char *app_name)
136 {
137   int rv = snprintf (ldp->app_name, LDP_APP_NAME_MAX,
138                      "ldp-%d-%s", getpid (), app_name);
139
140   if (rv >= LDP_APP_NAME_MAX)
141     app_name[LDP_APP_NAME_MAX - 1] = 0;
142 }
143
144 static inline char *
145 ldp_get_app_name ()
146 {
147   if (ldp->app_name[0] == '\0')
148     ldp_set_app_name ("app");
149
150   return ldp->app_name;
151 }
152
153 static int
154 ldp_fd_alloc (u32 sid)
155 {
156   ldp_fd_entry_t *fde;
157
158   clib_rwlock_writer_lock (&ldp->fd_table_lock);
159   if (pool_elts (ldp->fd_pool) >= (1ULL << 32) - ldp->sid_bit_val)
160     {
161       clib_rwlock_writer_unlock (&ldp->fd_table_lock);
162       return -1;
163     }
164   pool_get (ldp->fd_pool, fde);
165   fde->session_index = vppcom_session_index (sid);
166   fde->fd_index = fde - ldp->fd_pool;
167   fde->fd = fde->fd_index + ldp->sid_bit_val;
168   hash_set (ldp->session_index_to_fd_table, fde->session_index, fde->fd);
169   clib_rwlock_writer_unlock (&ldp->fd_table_lock);
170   return fde->fd;
171 }
172
173 static ldp_fd_entry_t *
174 ldp_fd_entry_get_w_lock (u32 fd_index)
175 {
176   clib_rwlock_reader_lock (&ldp->fd_table_lock);
177   if (pool_is_free_index (ldp->fd_pool, fd_index))
178     return 0;
179
180   return pool_elt_at_index (ldp->fd_pool, fd_index);
181 }
182
183 static inline int
184 ldp_fd_from_sid (u32 sid)
185 {
186   uword *fdp;
187   int fd;
188
189   clib_rwlock_reader_lock (&ldp->fd_table_lock);
190   fdp = hash_get (ldp->session_index_to_fd_table, vppcom_session_index (sid));
191   fd = fdp ? *fdp : -EMFILE;
192   clib_rwlock_reader_unlock (&ldp->fd_table_lock);
193
194   return fd;
195 }
196
197 static inline int
198 ldp_fd_is_sid (int fd)
199 {
200   return fd >= ldp->sid_bit_val;
201 }
202
203 static inline u32
204 ldp_sid_from_fd (int fd)
205 {
206   u32 fd_index, session_index;
207   ldp_fd_entry_t *fde;
208
209   if (!ldp_fd_is_sid (fd))
210     return INVALID_SESSION_ID;
211
212   fd_index = fd - ldp->sid_bit_val;
213   fde = ldp_fd_entry_get_w_lock (fd_index);
214   if (!fde)
215     {
216       LDBG (0, "unknown fd %d", fd);
217       clib_rwlock_reader_unlock (&ldp->fd_table_lock);
218       return INVALID_SESSION_ID;
219     }
220   session_index = fde->session_index;
221   clib_rwlock_reader_unlock (&ldp->fd_table_lock);
222
223   return vppcom_session_handle (session_index);
224 }
225
226 static void
227 ldp_fd_free_w_sid (u32 sid)
228 {
229   ldp_fd_entry_t *fde;
230   u32 fd_index;
231   int fd;
232
233   fd = ldp_fd_from_sid (sid);
234   if (!fd)
235     return;
236
237   fd_index = fd - ldp->sid_bit_val;
238   fde = ldp_fd_entry_get_w_lock (fd_index);
239   if (fde)
240     {
241       hash_unset (ldp->session_index_to_fd_table, fde->session_index);
242       pool_put (ldp->fd_pool, fde);
243     }
244   clib_rwlock_writer_unlock (&ldp->fd_table_lock);
245 }
246
247 static inline int
248 ldp_init (void)
249 {
250   ldp_worker_ctx_t *ldpw;
251   int rv;
252
253   if (PREDICT_TRUE (ldp->init))
254     return 0;
255
256   ldp->init = 1;
257   ldp->vcl_needs_real_epoll = 1;
258   rv = vppcom_app_create (ldp_get_app_name ());
259   if (rv != VPPCOM_OK)
260     {
261       ldp->vcl_needs_real_epoll = 0;
262       if (rv == VPPCOM_EEXIST)
263         return 0;
264       LDBG (2, "\nLDP<%d>: ERROR: ldp_init: vppcom_app_create()"
265             " failed!  rv = %d (%s)\n",
266             getpid (), rv, vppcom_retval_str (rv));
267       ldp->init = 0;
268       return rv;
269     }
270   ldp->vcl_needs_real_epoll = 0;
271   pool_alloc (ldp->workers, LDP_MAX_NWORKERS);
272   ldpw = ldp_worker_get_current ();
273
274   char *env_var_str = getenv (LDP_ENV_DEBUG);
275   if (env_var_str)
276     {
277       u32 tmp;
278       if (sscanf (env_var_str, "%u", &tmp) != 1)
279         clib_warning ("LDP<%d>: WARNING: Invalid LDP debug level specified in"
280                       " the env var " LDP_ENV_DEBUG " (%s)!", getpid (),
281                       env_var_str);
282       else
283         {
284           ldp->debug = tmp;
285           LDBG (0, "LDP<%d>: configured LDP debug level (%u) from env var "
286                 LDP_ENV_DEBUG "!", getpid (), ldp->debug);
287         }
288     }
289
290   env_var_str = getenv (LDP_ENV_APP_NAME);
291   if (env_var_str)
292     {
293       ldp_set_app_name (env_var_str);
294       LDBG (0, "LDP<%d>: configured LDP app name (%s) from the env var "
295             LDP_ENV_APP_NAME "!", getpid (), ldp->app_name);
296     }
297
298   env_var_str = getenv (LDP_ENV_SID_BIT);
299   if (env_var_str)
300     {
301       u32 sb;
302       if (sscanf (env_var_str, "%u", &sb) != 1)
303         {
304           clib_warning ("LDP<%d>: WARNING: Invalid LDP sid bit specified in"
305                         " the env var " LDP_ENV_SID_BIT " (%s)! sid bit "
306                         "value %d (0x%x)", getpid (), env_var_str,
307                         ldp->sid_bit_val, ldp->sid_bit_val);
308         }
309       else if (sb < LDP_SID_BIT_MIN)
310         {
311           ldp->sid_bit_val = (1 << LDP_SID_BIT_MIN);
312           ldp->sid_bit_mask = ldp->sid_bit_val - 1;
313
314           clib_warning ("LDP<%d>: WARNING: LDP sid bit (%u) specified in the"
315                         " env var " LDP_ENV_SID_BIT " (%s) is too small. "
316                         "Using LDP_SID_BIT_MIN (%d)! sid bit value %d (0x%x)",
317                         getpid (), sb, env_var_str, LDP_SID_BIT_MIN,
318                         ldp->sid_bit_val, ldp->sid_bit_val);
319         }
320       else if (sb > LDP_SID_BIT_MAX)
321         {
322           ldp->sid_bit_val = (1 << LDP_SID_BIT_MAX);
323           ldp->sid_bit_mask = ldp->sid_bit_val - 1;
324
325           clib_warning ("LDP<%d>: WARNING: LDP sid bit (%u) specified in the"
326                         " env var " LDP_ENV_SID_BIT " (%s) is too big. Using"
327                         " LDP_SID_BIT_MAX (%d)! sid bit value %d (0x%x)",
328                         getpid (), sb, env_var_str, LDP_SID_BIT_MAX,
329                         ldp->sid_bit_val, ldp->sid_bit_val);
330         }
331       else
332         {
333           ldp->sid_bit_val = (1 << sb);
334           ldp->sid_bit_mask = ldp->sid_bit_val - 1;
335
336           LDBG (0, "LDP<%d>: configured LDP sid bit (%u) from "
337                 LDP_ENV_SID_BIT "!  sid bit value %d (0x%x)", getpid (), sb,
338                 ldp->sid_bit_val, ldp->sid_bit_val);
339         }
340     }
341
342   clib_time_init (&ldpw->clib_time);
343   clib_rwlock_init (&ldp->fd_table_lock);
344   LDBG (0, "LDP<%d>: LDP initialization: done!", getpid ());
345
346   return 0;
347 }
348
349 int
350 close (int fd)
351 {
352   int rv, refcnt;
353   const char *func_str;
354   u32 sid = ldp_sid_from_fd (fd);
355
356   if ((errno = -ldp_init ()))
357     return -1;
358
359   if (sid != INVALID_SESSION_ID)
360     {
361       int epfd;
362
363       func_str = "vppcom_session_attr[GET_LIBC_EPFD]";
364       epfd = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
365       if (epfd > 0)
366         {
367           func_str = "libc_close";
368
369           LDBG (0, "LDP<%d>: fd %d (0x%x): calling %s(): epfd %u (0x%x)",
370                 getpid (), fd, fd, func_str, epfd, epfd);
371
372           rv = libc_close (epfd);
373           if (rv < 0)
374             {
375               u32 size = sizeof (epfd);
376               epfd = 0;
377
378               (void) vppcom_session_attr (sid, VPPCOM_ATTR_SET_LIBC_EPFD,
379                                           &epfd, &size);
380             }
381         }
382       else if (PREDICT_FALSE (epfd < 0))
383         {
384           errno = -epfd;
385           rv = -1;
386           goto done;
387         }
388
389       func_str = "vppcom_session_close";
390
391       LDBG (0, "LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x)",
392             getpid (), fd, fd, func_str, sid, sid);
393
394       refcnt = vppcom_session_attr (sid, VPPCOM_ATTR_GET_REFCNT, 0, 0);
395       rv = vppcom_session_close (sid);
396       if (rv != VPPCOM_OK)
397         {
398           errno = -rv;
399           rv = -1;
400         }
401       if (refcnt == 1)
402         ldp_fd_free_w_sid (sid);
403     }
404   else
405     {
406       func_str = "libc_close";
407
408       LDBG (0, "LDP<%d>: fd %d (0x%x): calling %s()", getpid (), fd, fd,
409             func_str);
410
411       rv = libc_close (fd);
412     }
413
414 done:
415   if (LDP_DEBUG > 0)
416     {
417       if (rv < 0)
418         {
419           int errno_val = errno;
420           perror (func_str);
421           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
422                         "rv %d, errno = %d", getpid (), fd, fd,
423                         func_str, rv, errno_val);
424           errno = errno_val;
425         }
426       else
427         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
428                       getpid (), fd, fd, rv, rv);
429     }
430   return rv;
431 }
432
433 ssize_t
434 read (int fd, void *buf, size_t nbytes)
435 {
436   ssize_t size;
437   const char *func_str;
438   u32 sid = ldp_sid_from_fd (fd);
439
440   if ((errno = -ldp_init ()))
441     return -1;
442
443   if (sid != INVALID_SESSION_ID)
444     {
445       func_str = "vppcom_session_read";
446
447       if (LDP_DEBUG > 2)
448         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
449                       "sid %u (0x%x), buf %p, nbytes %u", getpid (),
450                       fd, fd, func_str, sid, sid, buf, nbytes);
451
452       size = vppcom_session_read (sid, buf, nbytes);
453       if (size < 0)
454         {
455           errno = -size;
456           size = -1;
457         }
458     }
459   else
460     {
461       func_str = "libc_read";
462
463       if (LDP_DEBUG > 2)
464         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
465                       "buf %p, nbytes %u", getpid (),
466                       fd, fd, func_str, buf, nbytes);
467
468       size = libc_read (fd, buf, nbytes);
469     }
470
471   if (LDP_DEBUG > 2)
472     {
473       if (size < 0)
474         {
475           int errno_val = errno;
476           perror (func_str);
477           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
478                         "rv %d, errno = %d", getpid (), fd, fd,
479                         func_str, size, errno_val);
480           errno = errno_val;
481         }
482       else
483         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
484                       getpid (), fd, fd, size, size);
485     }
486   return size;
487 }
488
489 ssize_t
490 readv (int fd, const struct iovec * iov, int iovcnt)
491 {
492   const char *func_str;
493   ssize_t size = 0;
494   u32 sid = ldp_sid_from_fd (fd);
495   int rv = 0, i, total = 0;
496
497   if ((errno = -ldp_init ()))
498     return -1;
499
500   if (sid != INVALID_SESSION_ID)
501     {
502       func_str = "vppcom_session_read";
503       do
504         {
505           for (i = 0; i < iovcnt; ++i)
506             {
507               if (LDP_DEBUG > 2)
508                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s() [%d]: "
509                               "sid %u (0x%x), iov %p, iovcnt %d, total %d",
510                               getpid (), fd, fd, func_str, i, sid, sid,
511                               iov, iovcnt, total);
512
513               rv = vppcom_session_read (sid, iov[i].iov_base, iov[i].iov_len);
514               if (rv < 0)
515                 break;
516               else
517                 {
518                   total += rv;
519                   if (rv < iov[i].iov_len)
520                     {
521                       if (LDP_DEBUG > 2)
522                         clib_warning ("LDP<%d>: fd %d (0x%x): "
523                                       "rv (%d) < iov[%d].iov_len (%d)",
524                                       getpid (), fd, fd, rv, i,
525                                       iov[i].iov_len);
526                       break;
527                     }
528                 }
529             }
530         }
531       while ((rv >= 0) && (total == 0));
532
533       if (rv < 0)
534         {
535           errno = -rv;
536           size = -1;
537         }
538       else
539         size = total;
540     }
541   else
542     {
543       func_str = "libc_readv";
544
545       if (LDP_DEBUG > 2)
546         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
547                       "iov %p, iovcnt %d", getpid (), fd, fd, iov, iovcnt);
548
549       size = libc_readv (fd, iov, iovcnt);
550     }
551
552   if (LDP_DEBUG > 2)
553     {
554       if (size < 0)
555         {
556           int errno_val = errno;
557           perror (func_str);
558           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
559                         "rv %d, errno = %d", getpid (), fd, fd,
560                         func_str, size, errno_val);
561           errno = errno_val;
562         }
563       else
564         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
565                       getpid (), fd, fd, size, size);
566     }
567   return size;
568 }
569
570 ssize_t
571 write (int fd, const void *buf, size_t nbytes)
572 {
573   const char *func_str;
574   ssize_t size = 0;
575   u32 sid = ldp_sid_from_fd (fd);
576
577   if ((errno = -ldp_init ()))
578     return -1;
579
580   if (sid != INVALID_SESSION_ID)
581     {
582       func_str = "vppcom_session_write";
583
584       if (LDP_DEBUG > 2)
585         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
586                       "sid %u (0x%x), buf %p, nbytes %u", getpid (),
587                       fd, fd, func_str, sid, sid, buf, nbytes);
588
589       size = vppcom_session_write (sid, (void *) buf, nbytes);
590       if (size < 0)
591         {
592           errno = -size;
593           size = -1;
594         }
595     }
596   else
597     {
598       func_str = "libc_write";
599
600       if (LDP_DEBUG > 2)
601         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
602                       "buf %p, nbytes %u", getpid (),
603                       fd, fd, func_str, buf, nbytes);
604
605       size = libc_write (fd, buf, nbytes);
606     }
607
608   if (LDP_DEBUG > 2)
609     {
610       if (size < 0)
611         {
612           int errno_val = errno;
613           perror (func_str);
614           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
615                         "rv %d, errno = %d", getpid (), fd, fd,
616                         func_str, size, errno_val);
617           errno = errno_val;
618         }
619       else
620         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
621                       getpid (), fd, fd, size, size);
622     }
623   return size;
624 }
625
626 ssize_t
627 writev (int fd, const struct iovec * iov, int iovcnt)
628 {
629   const char *func_str;
630   ssize_t size = 0, total = 0;
631   u32 sid = ldp_sid_from_fd (fd);
632   int i, rv = 0;
633
634   /*
635    * Use [f]printf() instead of clib_warning() to prevent recursion SIGSEGV.
636    */
637
638   if ((errno = -ldp_init ()))
639     return -1;
640
641   if (sid != INVALID_SESSION_ID)
642     {
643       func_str = "vppcom_session_write";
644       do
645         {
646           for (i = 0; i < iovcnt; ++i)
647             {
648               if (LDP_DEBUG > 4)
649                 printf ("%s:%d: LDP<%d>: fd %d (0x%x): calling %s() [%d]: "
650                         "sid %u (0x%x), buf %p, nbytes %ld, total %ld",
651                         __func__, __LINE__, getpid (), fd, fd, func_str,
652                         i, sid, sid, iov[i].iov_base, iov[i].iov_len, total);
653
654               rv = vppcom_session_write (sid, iov[i].iov_base,
655                                          iov[i].iov_len);
656               if (rv < 0)
657                 break;
658               else
659                 {
660                   total += rv;
661                   if (rv < iov[i].iov_len)
662                     {
663                       if (LDP_DEBUG > 4)
664                         printf ("%s:%d: LDP<%d>: fd %d (0x%x): "
665                                 "rv (%d) < iov[%d].iov_len (%ld)",
666                                 __func__, __LINE__, getpid (), fd, fd,
667                                 rv, i, iov[i].iov_len);
668                       break;
669                     }
670                 }
671             }
672         }
673       while ((rv >= 0) && (total == 0));
674
675       if (rv < 0)
676         {
677           errno = -rv;
678           size = -1;
679         }
680       else
681         size = total;
682     }
683   else
684     {
685       func_str = "libc_writev";
686
687       if (LDP_DEBUG > 4)
688         printf ("%s:%d: LDP<%d>: fd %d (0x%x): calling %s(): "
689                 "iov %p, iovcnt %d\n", __func__, __LINE__, getpid (),
690                 fd, fd, func_str, iov, iovcnt);
691
692       size = libc_writev (fd, iov, iovcnt);
693     }
694
695   if (LDP_DEBUG > 4)
696     {
697       if (size < 0)
698         {
699           int errno_val = errno;
700           perror (func_str);
701           fprintf (stderr,
702                    "%s:%d: LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
703                    "rv %ld, errno = %d\n", __func__, __LINE__, getpid (), fd,
704                    fd, func_str, size, errno_val);
705           errno = errno_val;
706         }
707       else
708         printf ("%s:%d: LDP<%d>: fd %d (0x%x): returning %ld\n",
709                 __func__, __LINE__, getpid (), fd, fd, size);
710     }
711   return size;
712 }
713
714 int
715 fcntl (int fd, int cmd, ...)
716 {
717   const char *func_str = __func__;
718   int rv = 0;
719   va_list ap;
720   u32 sid = ldp_sid_from_fd (fd);
721
722   if ((errno = -ldp_init ()))
723     return -1;
724
725   va_start (ap, cmd);
726   if (sid != INVALID_SESSION_ID)
727     {
728       int flags = va_arg (ap, int);
729       u32 size;
730
731       size = sizeof (flags);
732       rv = -EOPNOTSUPP;
733       switch (cmd)
734         {
735         case F_SETFL:
736           func_str = "vppcom_session_attr[SET_FLAGS]";
737           LDBG (2, "LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x) "
738                 "flags %d (0x%x), size %d", getpid (), fd, fd, func_str, sid,
739                 sid, flags, flags, size);
740
741           rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_FLAGS, &flags,
742                                     &size);
743           break;
744
745         case F_GETFL:
746           func_str = "vppcom_session_attr[GET_FLAGS]";
747           LDBG (2, "LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
748                 "flags %d (0x%x), size %d", getpid (), fd, fd, func_str, sid,
749                 sid, flags, flags, size);
750
751           rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_FLAGS, &flags,
752                                     &size);
753           if (rv == VPPCOM_OK)
754             {
755               LDBG (2, "LDP<%d>: fd %d (0x%x), cmd %d (F_GETFL): %s() "
756                     "returned flags %d (0x%x)", getpid (), fd, fd, cmd,
757                     func_str, flags, flags);
758               rv = flags;
759             }
760           break;
761         case F_SETFD:
762           /* TODO handle this */
763           LDBG (0, "F_SETFD ignored flags %u", flags);
764           rv = 0;
765           break;
766         default:
767           rv = -EOPNOTSUPP;
768           break;
769         }
770       if (rv < 0)
771         {
772           errno = -rv;
773           rv = -1;
774         }
775     }
776   else
777     {
778       func_str = "libc_vfcntl";
779
780       if (LDP_DEBUG > 2)
781         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): cmd %d",
782                       getpid (), fd, fd, func_str, cmd);
783
784       rv = libc_vfcntl (fd, cmd, ap);
785     }
786
787   va_end (ap);
788
789   if (LDP_DEBUG > 2)
790     {
791       if (rv < 0)
792         {
793           int errno_val = errno;
794           perror (func_str);
795           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
796                         "rv %d, errno = %d", getpid (), fd, fd,
797                         func_str, rv, errno_val);
798           errno = errno_val;
799         }
800       else
801         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
802                       getpid (), fd, fd, rv, rv);
803     }
804   return rv;
805 }
806
807 int
808 ioctl (int fd, unsigned long int cmd, ...)
809 {
810   const char *func_str;
811   int rv;
812   va_list ap;
813   u32 sid = ldp_sid_from_fd (fd);
814
815   if ((errno = -ldp_init ()))
816     return -1;
817
818   va_start (ap, cmd);
819   if (sid != INVALID_SESSION_ID)
820     {
821       func_str = "vppcom_session_attr[GET_NREAD]";
822
823       switch (cmd)
824         {
825         case FIONREAD:
826           if (LDP_DEBUG > 2)
827             clib_warning
828               ("LDP<%d>: fd %d (0x%x): calling  %s(): sid %u (0x%x)",
829                getpid (), fd, fd, func_str, sid, sid);
830
831           rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_NREAD, 0, 0);
832           break;
833
834         case FIONBIO:
835           {
836             u32 flags = va_arg (ap, int) ? O_NONBLOCK : 0;
837             u32 size = sizeof (flags);
838
839             /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than
840              *      non-blocking, the flags should be read here and merged
841              *      with O_NONBLOCK.
842              */
843             if (LDP_DEBUG > 2)
844               clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
845                             "sid %u (0x%x), flags %d (0x%x), size %d",
846                             getpid (), fd, fd, func_str, sid, sid,
847                             flags, flags, size);
848
849             rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_FLAGS, &flags,
850                                       &size);
851           }
852           break;
853
854         default:
855           rv = -EOPNOTSUPP;
856           break;
857         }
858       if (rv < 0)
859         {
860           errno = -rv;
861           rv = -1;
862         }
863     }
864   else
865     {
866       func_str = "libc_vioctl";
867
868       if (LDP_DEBUG > 2)
869         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): cmd %d",
870                       getpid (), fd, fd, func_str, cmd);
871
872       rv = libc_vioctl (fd, cmd, ap);
873     }
874
875   if (LDP_DEBUG > 2)
876     {
877       if (rv < 0)
878         {
879           int errno_val = errno;
880           perror (func_str);
881           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
882                         "rv %d, errno = %d", getpid (), fd, fd,
883                         func_str, rv, errno_val);
884           errno = errno_val;
885         }
886       else
887         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
888                       getpid (), fd, fd, rv, rv);
889     }
890   va_end (ap);
891   return rv;
892 }
893
894 int
895 ldp_pselect (int nfds, fd_set * __restrict readfds,
896              fd_set * __restrict writefds,
897              fd_set * __restrict exceptfds,
898              const struct timespec *__restrict timeout,
899              const __sigset_t * __restrict sigmask)
900 {
901   uword sid_bits, sid_bits_set, libc_bits, libc_bits_set;
902   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
903   u32 minbits = clib_max (nfds, BITS (uword)), sid;
904   char *func_str = "##";
905   f64 time_out;
906   int rv, fd;
907
908   if (nfds < 0)
909     {
910       errno = EINVAL;
911       return -1;
912     }
913
914   if (timeout)
915     {
916       time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ?
917         (f64) 0 : (f64) timeout->tv_sec +
918         (f64) timeout->tv_nsec / (f64) 1000000000;
919
920       /* select as fine grained sleep */
921       if (!nfds)
922         {
923           LDBG (3, "LDP<%d>: sleeping for %.02f seconds", getpid (),
924                 time_out);
925
926           time_out += clib_time_now (&ldpw->clib_time);
927           while (clib_time_now (&ldpw->clib_time) < time_out)
928             ;
929           return 0;
930         }
931     }
932   else if (!nfds)
933     {
934       errno = EINVAL;
935       return -1;
936     }
937   else
938     time_out = -1;
939
940
941   if (nfds <= ldp->sid_bit_val)
942     {
943       func_str = "libc_pselect";
944
945       LDBG (3, "LDP<%d>: calling %s(): nfds %d, readfds %p, writefds %p, "
946             "exceptfds %p, timeout %p, sigmask %p", getpid (), func_str, nfds,
947             readfds, writefds, exceptfds, timeout, sigmask);
948
949       rv = libc_pselect (nfds, readfds, writefds, exceptfds,
950                          timeout, sigmask);
951       goto done;
952     }
953
954   if (PREDICT_FALSE (ldp->sid_bit_val > FD_SETSIZE / 2))
955     {
956       clib_warning ("LDP<%d>: ERROR: LDP sid bit value %d (0x%x) > "
957                     "FD_SETSIZE/2 %d (0x%x)!", getpid (),
958                     ldp->sid_bit_val, ldp->sid_bit_val,
959                     FD_SETSIZE / 2, FD_SETSIZE / 2);
960       errno = EOVERFLOW;
961       return -1;
962     }
963
964   sid_bits = libc_bits = 0;
965   u32 n_bytes = nfds / 8 + ((nfds % 8) ? 1 : 0);
966   if (readfds)
967     {
968       clib_bitmap_validate (ldpw->sid_rd_bitmap, minbits);
969       clib_bitmap_validate (ldpw->libc_rd_bitmap, minbits);
970       clib_bitmap_validate (ldpw->rd_bitmap, minbits);
971       clib_memcpy_fast (ldpw->rd_bitmap, readfds, n_bytes);
972       memset (readfds, 0, n_bytes);
973
974       /* *INDENT-OFF* */
975       clib_bitmap_foreach (fd, ldpw->rd_bitmap, ({
976         if (fd > nfds)
977           break;
978         sid = ldp_sid_from_fd (fd);
979         LDBG (3, "LDP<%d>: readfds: fd %d (0x%x), sid %u (0x%x)",
980               getpid (), fd, fd, sid, sid);
981         if (sid == INVALID_SESSION_ID)
982           clib_bitmap_set_no_check (ldpw->libc_rd_bitmap, fd, 1);
983         else
984           clib_bitmap_set_no_check (ldpw->sid_rd_bitmap,
985                                     vppcom_session_index (sid), 1);
986       }));
987       /* *INDENT-ON* */
988
989       sid_bits_set = clib_bitmap_last_set (ldpw->sid_rd_bitmap) + 1;
990       sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits;
991
992       libc_bits_set = clib_bitmap_last_set (ldpw->libc_rd_bitmap) + 1;
993       libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits;
994
995       LDBG (3, "LDP<%d>: readfds: sid_bits_set %d, sid_bits %d, "
996             "libc_bits_set %d, libc_bits %d", getpid (), sid_bits_set,
997             sid_bits, libc_bits_set, libc_bits);
998     }
999   if (writefds)
1000     {
1001       clib_bitmap_validate (ldpw->sid_wr_bitmap, minbits);
1002       clib_bitmap_validate (ldpw->libc_wr_bitmap, minbits);
1003       clib_bitmap_validate (ldpw->wr_bitmap, minbits);
1004       clib_memcpy_fast (ldpw->wr_bitmap, writefds, n_bytes);
1005       memset (writefds, 0, n_bytes);
1006
1007       /* *INDENT-OFF* */
1008       clib_bitmap_foreach (fd, ldpw->wr_bitmap, ({
1009         if (fd > nfds)
1010           break;
1011         sid = ldp_sid_from_fd (fd);
1012         LDBG (3, "LDP<%d>: writefds: fd %d (0x%x), sid %u (0x%x)",
1013                         getpid (), fd, fd, sid, sid);
1014         if (sid == INVALID_SESSION_ID)
1015           clib_bitmap_set_no_check (ldpw->libc_wr_bitmap, fd, 1);
1016         else
1017           clib_bitmap_set_no_check (ldpw->sid_wr_bitmap,
1018                                     vppcom_session_index (sid), 1);
1019       }));
1020       /* *INDENT-ON* */
1021
1022       sid_bits_set = clib_bitmap_last_set (ldpw->sid_wr_bitmap) + 1;
1023       sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits;
1024
1025       libc_bits_set = clib_bitmap_last_set (ldpw->libc_wr_bitmap) + 1;
1026       libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits;
1027
1028       LDBG (3, "LDP<%d>: writefds: sid_bits_set %d, sid_bits %d, "
1029             "libc_bits_set %d, libc_bits %d", getpid (),
1030             sid_bits_set, sid_bits, libc_bits_set, libc_bits);
1031     }
1032   if (exceptfds)
1033     {
1034       clib_bitmap_validate (ldpw->sid_ex_bitmap, minbits);
1035       clib_bitmap_validate (ldpw->libc_ex_bitmap, minbits);
1036       clib_bitmap_validate (ldpw->ex_bitmap, minbits);
1037       clib_memcpy_fast (ldpw->ex_bitmap, exceptfds, n_bytes);
1038       memset (exceptfds, 0, n_bytes);
1039
1040       /* *INDENT-OFF* */
1041       clib_bitmap_foreach (fd, ldpw->ex_bitmap, ({
1042         if (fd > nfds)
1043           break;
1044         sid = ldp_sid_from_fd (fd);
1045         LDBG (3, "LDP<%d>: exceptfds: fd %d (0x%x), sid %u (0x%x)",
1046                         getpid (), fd, fd, sid, sid);
1047         if (sid == INVALID_SESSION_ID)
1048           clib_bitmap_set_no_check (ldpw->libc_ex_bitmap, fd, 1);
1049         else
1050           clib_bitmap_set_no_check (ldpw->sid_ex_bitmap,
1051                                     vppcom_session_index (sid), 1);
1052       }));
1053       /* *INDENT-ON* */
1054
1055       sid_bits_set = clib_bitmap_last_set (ldpw->sid_ex_bitmap) + 1;
1056       sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits;
1057
1058       libc_bits_set = clib_bitmap_last_set (ldpw->libc_ex_bitmap) + 1;
1059       libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits;
1060
1061       LDBG (3, "LDP<%d>: exceptfds: sid_bits_set %d, sid_bits %d, "
1062             "libc_bits_set %d, libc_bits %d", getpid (),
1063             sid_bits_set, sid_bits, libc_bits_set, libc_bits);
1064     }
1065
1066   if (PREDICT_FALSE (!sid_bits && !libc_bits))
1067     {
1068       errno = EINVAL;
1069       rv = -1;
1070       goto done;
1071     }
1072
1073   do
1074     {
1075       if (sid_bits)
1076         {
1077           if (!ldpw->select_vcl)
1078             {
1079               func_str = "vppcom_select";
1080
1081               if (readfds)
1082                 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->sid_rd_bitmap,
1083                                   vec_len (ldpw->rd_bitmap) *
1084                                   sizeof (clib_bitmap_t));
1085               if (writefds)
1086                 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->sid_wr_bitmap,
1087                                   vec_len (ldpw->wr_bitmap) *
1088                                   sizeof (clib_bitmap_t));
1089               if (exceptfds)
1090                 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->sid_ex_bitmap,
1091                                   vec_len (ldpw->ex_bitmap) *
1092                                   sizeof (clib_bitmap_t));
1093
1094               rv = vppcom_select (sid_bits,
1095                                   readfds ? ldpw->rd_bitmap : NULL,
1096                                   writefds ? ldpw->wr_bitmap : NULL,
1097                                   exceptfds ? ldpw->ex_bitmap : NULL, 0);
1098               if (rv < 0)
1099                 {
1100                   errno = -rv;
1101                   rv = -1;
1102                 }
1103               else if (rv > 0)
1104                 {
1105                   if (readfds)
1106                     {
1107                       /* *INDENT-OFF* */
1108                       clib_bitmap_foreach (sid, ldpw->rd_bitmap,
1109                         ({
1110                           fd = ldp_fd_from_sid (vppcom_session_handle (sid));
1111                           if (PREDICT_FALSE (fd < 0))
1112                             {
1113                               errno = EBADFD;
1114                               rv = -1;
1115                               goto done;
1116                             }
1117                           FD_SET (fd, readfds);
1118                         }));
1119                       /* *INDENT-ON* */
1120                     }
1121                   if (writefds)
1122                     {
1123                       /* *INDENT-OFF* */
1124                       clib_bitmap_foreach (sid, ldpw->wr_bitmap,
1125                         ({
1126                           fd = ldp_fd_from_sid (vppcom_session_handle (sid));
1127                           if (PREDICT_FALSE (fd < 0))
1128                             {
1129                               errno = EBADFD;
1130                               rv = -1;
1131                               goto done;
1132                             }
1133                           FD_SET (fd, writefds);
1134                         }));
1135                       /* *INDENT-ON* */
1136                     }
1137                   if (exceptfds)
1138                     {
1139                       /* *INDENT-OFF* */
1140                       clib_bitmap_foreach (sid, ldpw->ex_bitmap,
1141                         ({
1142                           fd = ldp_fd_from_sid (vppcom_session_handle (sid));
1143                           if (PREDICT_FALSE (fd < 0))
1144                             {
1145                               errno = EBADFD;
1146                               rv = -1;
1147                               goto done;
1148                             }
1149                           FD_SET (fd, exceptfds);
1150                         }));
1151                       /* *INDENT-ON* */
1152                     }
1153                   ldpw->select_vcl = 1;
1154                   goto done;
1155                 }
1156             }
1157           else
1158             ldpw->select_vcl = 0;
1159         }
1160       if (libc_bits)
1161         {
1162           struct timespec tspec;
1163
1164           func_str = "libc_pselect";
1165
1166           if (readfds)
1167             clib_memcpy_fast (readfds, ldpw->libc_rd_bitmap,
1168                               vec_len (ldpw->rd_bitmap) *
1169                               sizeof (clib_bitmap_t));
1170           if (writefds)
1171             clib_memcpy_fast (writefds, ldpw->libc_wr_bitmap,
1172                               vec_len (ldpw->wr_bitmap) *
1173                               sizeof (clib_bitmap_t));
1174           if (exceptfds)
1175             clib_memcpy_fast (exceptfds, ldpw->libc_ex_bitmap,
1176                               vec_len (ldpw->ex_bitmap) *
1177                               sizeof (clib_bitmap_t));
1178           tspec.tv_sec = tspec.tv_nsec = 0;
1179           rv = libc_pselect (libc_bits,
1180                              readfds ? readfds : NULL,
1181                              writefds ? writefds : NULL,
1182                              exceptfds ? exceptfds : NULL, &tspec, sigmask);
1183           if (rv != 0)
1184             goto done;
1185         }
1186     }
1187   while ((time_out == -1) || (clib_time_now (&ldpw->clib_time) < time_out));
1188   rv = 0;
1189
1190 done:
1191   /* TBD: set timeout to amount of time left */
1192   clib_bitmap_zero (ldpw->rd_bitmap);
1193   clib_bitmap_zero (ldpw->sid_rd_bitmap);
1194   clib_bitmap_zero (ldpw->libc_rd_bitmap);
1195   clib_bitmap_zero (ldpw->wr_bitmap);
1196   clib_bitmap_zero (ldpw->sid_wr_bitmap);
1197   clib_bitmap_zero (ldpw->libc_wr_bitmap);
1198   clib_bitmap_zero (ldpw->ex_bitmap);
1199   clib_bitmap_zero (ldpw->sid_ex_bitmap);
1200   clib_bitmap_zero (ldpw->libc_ex_bitmap);
1201
1202   if (LDP_DEBUG > 3)
1203     {
1204       if (rv < 0)
1205         {
1206           int errno_val = errno;
1207           perror (func_str);
1208           clib_warning ("LDP<%d>: ERROR: %s() failed! "
1209                         "rv %d, errno = %d", getpid (),
1210                         func_str, rv, errno_val);
1211           errno = errno_val;
1212         }
1213       else
1214         clib_warning ("LDP<%d>: returning %d (0x%x)", getpid (), rv, rv);
1215     }
1216   return rv;
1217 }
1218
1219 int
1220 select (int nfds, fd_set * __restrict readfds,
1221         fd_set * __restrict writefds,
1222         fd_set * __restrict exceptfds, struct timeval *__restrict timeout)
1223 {
1224   struct timespec tspec;
1225
1226   if (timeout)
1227     {
1228       tspec.tv_sec = timeout->tv_sec;
1229       tspec.tv_nsec = timeout->tv_usec * 1000;
1230     }
1231   return ldp_pselect (nfds, readfds, writefds, exceptfds,
1232                       timeout ? &tspec : NULL, NULL);
1233 }
1234
1235 #ifdef __USE_XOPEN2K
1236 int
1237 pselect (int nfds, fd_set * __restrict readfds,
1238          fd_set * __restrict writefds,
1239          fd_set * __restrict exceptfds,
1240          const struct timespec *__restrict timeout,
1241          const __sigset_t * __restrict sigmask)
1242 {
1243   return ldp_pselect (nfds, readfds, writefds, exceptfds, timeout, 0);
1244 }
1245 #endif
1246
1247 int
1248 socket (int domain, int type, int protocol)
1249 {
1250   const char *func_str;
1251   int rv;
1252   u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0;
1253   int sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
1254
1255   if ((errno = -ldp_init ()))
1256     return -1;
1257
1258   if (((domain == AF_INET) || (domain == AF_INET6)) &&
1259       ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
1260     {
1261       int sid;
1262       u8 proto = ((sock_type == SOCK_DGRAM) ?
1263                   VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP);
1264
1265       func_str = "vppcom_session_create";
1266
1267       LDBG (0, "LDP<%d>: : calling %s(): proto %u (%s), is_nonblocking %u",
1268             getpid (), func_str, proto, vppcom_proto_str (proto),
1269             is_nonblocking);
1270
1271       sid = vppcom_session_create (proto, is_nonblocking);
1272       if (sid < 0)
1273         {
1274           errno = -sid;
1275           rv = -1;
1276         }
1277       else
1278         {
1279           func_str = "ldp_fd_from_sid";
1280           rv = ldp_fd_alloc (sid);
1281           if (rv < 0)
1282             {
1283               (void) vppcom_session_close (sid);
1284               errno = -rv;
1285               rv = -1;
1286             }
1287         }
1288     }
1289   else
1290     {
1291       func_str = "libc_socket";
1292
1293       LDBG (0, "LDP<%d>: : calling %s()", getpid (), func_str);
1294
1295       rv = libc_socket (domain, type, protocol);
1296     }
1297
1298   if (LDP_DEBUG > 0)
1299     {
1300       if (rv < 0)
1301         {
1302           int errno_val = errno;
1303           perror (func_str);
1304           clib_warning ("LDP<%d>: ERROR: %s() failed! "
1305                         "rv %d, errno = %d",
1306                         getpid (), func_str, rv, errno_val);
1307           errno = errno_val;
1308         }
1309       else
1310         clib_warning ("LDP<%d>: : returning fd %d (0x%x)", getpid (), rv, rv);
1311     }
1312   return rv;
1313 }
1314
1315 /*
1316  * Create two new sockets, of type TYPE in domain DOMAIN and using
1317  * protocol PROTOCOL, which are connected to each other, and put file
1318  * descriptors for them in FDS[0] and FDS[1].  If PROTOCOL is zero,
1319  * one will be chosen automatically.
1320  * Returns 0 on success, -1 for errors.
1321  * */
1322 int
1323 socketpair (int domain, int type, int protocol, int fds[2])
1324 {
1325   const char *func_str;
1326   int rv;
1327   int sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
1328
1329   if ((errno = -ldp_init ()))
1330     return -1;
1331
1332   if (((domain == AF_INET) || (domain == AF_INET6)) &&
1333       ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
1334     {
1335       func_str = __func__;
1336
1337       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1338       errno = ENOSYS;
1339       rv = -1;
1340     }
1341   else
1342     {
1343       func_str = "libc_socket";
1344
1345       LDBG (1, "LDP<%d>: : calling %s()", getpid (), func_str);
1346
1347       rv = libc_socketpair (domain, type, protocol, fds);
1348     }
1349
1350   if (LDP_DEBUG > 1)
1351     {
1352       if (rv < 0)
1353         {
1354           int errno_val = errno;
1355           perror (func_str);
1356           clib_warning ("LDP<%d>: ERROR: %s() failed! "
1357                         "rv %d, errno = %d",
1358                         getpid (), func_str, rv, errno_val);
1359           errno = errno_val;
1360         }
1361       else
1362         clib_warning ("LDP<%d>: : returning fd %d (0x%x)", getpid (), rv, rv);
1363     }
1364   return rv;
1365 }
1366
1367 int
1368 bind (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
1369 {
1370   int rv;
1371   const char *func_str;
1372   u32 sid = ldp_sid_from_fd (fd);
1373
1374   if ((errno = -ldp_init ()))
1375     return -1;
1376
1377   if (sid != INVALID_SESSION_ID)
1378     {
1379       vppcom_endpt_t ep;
1380
1381       func_str = "vppcom_session_bind";
1382
1383       switch (addr->sa_family)
1384         {
1385         case AF_INET:
1386           if (len != sizeof (struct sockaddr_in))
1387             {
1388               clib_warning
1389                 ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): Invalid "
1390                  "AF_INET addr len %u!", getpid (), fd, fd, sid, sid, len);
1391               errno = EINVAL;
1392               rv = -1;
1393               goto done;
1394             }
1395           ep.is_ip4 = VPPCOM_IS_IP4;
1396           ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1397           ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1398           break;
1399
1400         case AF_INET6:
1401           if (len != sizeof (struct sockaddr_in6))
1402             {
1403               clib_warning
1404                 ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): Invalid "
1405                  "AF_INET6 addr len %u!", getpid (), fd, fd, sid, sid, len);
1406               errno = EINVAL;
1407               rv = -1;
1408               goto done;
1409             }
1410           ep.is_ip4 = VPPCOM_IS_IP6;
1411           ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1412           ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1413           break;
1414
1415         default:
1416           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): "
1417                         "Unsupported address family %u!",
1418                         getpid (), fd, fd, sid, sid, addr->sa_family);
1419           errno = EAFNOSUPPORT;
1420           rv = -1;
1421           goto done;
1422         }
1423       if (LDP_DEBUG > 0)
1424         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1425                       "addr %p, len %u",
1426                       getpid (), fd, fd, func_str, sid, sid, addr, len);
1427
1428       rv = vppcom_session_bind (sid, &ep);
1429       if (rv != VPPCOM_OK)
1430         {
1431           errno = -rv;
1432           rv = -1;
1433         }
1434     }
1435   else
1436     {
1437       func_str = "libc_bind";
1438
1439       if (LDP_DEBUG > 0)
1440         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1441                       "addr %p, len %u",
1442                       getpid (), fd, fd, func_str, addr, len);
1443
1444       rv = libc_bind (fd, addr, len);
1445     }
1446
1447 done:
1448   if (LDP_DEBUG > 0)
1449     {
1450       if (rv < 0)
1451         {
1452           int errno_val = errno;
1453           perror (func_str);
1454           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1455                         "rv %d, errno = %d", getpid (), fd, fd,
1456                         func_str, rv, errno_val);
1457           errno = errno_val;
1458         }
1459       else
1460         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1461                       getpid (), fd, fd, rv, rv);
1462     }
1463   return rv;
1464 }
1465
1466 static inline int
1467 ldp_copy_ep_to_sockaddr (__SOCKADDR_ARG addr, socklen_t * __restrict len,
1468                          vppcom_endpt_t * ep)
1469 {
1470   int rv = 0;
1471   int sa_len, copy_len;
1472
1473   if ((errno = -ldp_init ()))
1474     return -1;
1475
1476   if (addr && len && ep)
1477     {
1478       addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
1479       switch (addr->sa_family)
1480         {
1481         case AF_INET:
1482           ((struct sockaddr_in *) addr)->sin_port = ep->port;
1483           if (*len > sizeof (struct sockaddr_in))
1484             *len = sizeof (struct sockaddr_in);
1485           sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
1486           copy_len = *len - sa_len;
1487           if (copy_len > 0)
1488             memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
1489                     copy_len);
1490           break;
1491
1492         case AF_INET6:
1493           ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
1494           if (*len > sizeof (struct sockaddr_in6))
1495             *len = sizeof (struct sockaddr_in6);
1496           sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
1497           copy_len = *len - sa_len;
1498           if (copy_len > 0)
1499             memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
1500                     __in6_u.__u6_addr8, ep->ip, copy_len);
1501           break;
1502
1503         default:
1504           /* Not possible */
1505           rv = -EAFNOSUPPORT;
1506           break;
1507         }
1508     }
1509   return rv;
1510 }
1511
1512 int
1513 getsockname (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
1514 {
1515   int rv;
1516   const char *func_str;
1517   u32 sid = ldp_sid_from_fd (fd);
1518
1519   if ((errno = -ldp_init ()))
1520     return -1;
1521
1522   if (sid != INVALID_SESSION_ID)
1523     {
1524       vppcom_endpt_t ep;
1525       u8 addr_buf[sizeof (struct in6_addr)];
1526       u32 size = sizeof (ep);
1527
1528       ep.ip = addr_buf;
1529       func_str = "vppcom_session_attr[GET_LCL_ADDR]";
1530
1531       if (LDP_DEBUG > 2)
1532         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1533                       "addr %p, len %u",
1534                       getpid (), fd, fd, func_str, sid, sid, addr, len);
1535
1536       rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
1537       if (rv != VPPCOM_OK)
1538         {
1539           errno = -rv;
1540           rv = -1;
1541         }
1542       else
1543         {
1544           rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
1545           if (rv != VPPCOM_OK)
1546             {
1547               errno = -rv;
1548               rv = -1;
1549             }
1550         }
1551     }
1552   else
1553     {
1554       func_str = "libc_getsockname";
1555
1556       if (LDP_DEBUG > 2)
1557         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1558                       "addr %p, len %u",
1559                       getpid (), fd, fd, func_str, addr, len);
1560
1561       rv = libc_getsockname (fd, addr, len);
1562     }
1563
1564   if (LDP_DEBUG > 2)
1565     {
1566       if (rv < 0)
1567         {
1568           int errno_val = errno;
1569           perror (func_str);
1570           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1571                         "rv %d, errno = %d", getpid (), fd, fd,
1572                         func_str, rv, errno_val);
1573           errno = errno_val;
1574         }
1575       else
1576         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1577                       getpid (), fd, fd, rv, rv);
1578     }
1579   return rv;
1580 }
1581
1582 int
1583 connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
1584 {
1585   int rv;
1586   const char *func_str = __func__;
1587   u32 sid = ldp_sid_from_fd (fd);
1588
1589   if ((errno = -ldp_init ()))
1590     return -1;
1591
1592   if (!addr)
1593     {
1594       clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): NULL addr, len %u",
1595                     getpid (), fd, fd, len);
1596       errno = EINVAL;
1597       rv = -1;
1598       goto done;
1599     }
1600
1601   if (sid != INVALID_SESSION_ID)
1602     {
1603       vppcom_endpt_t ep;
1604
1605       func_str = "vppcom_session_connect";
1606
1607       switch (addr->sa_family)
1608         {
1609         case AF_INET:
1610           if (len != sizeof (struct sockaddr_in))
1611             {
1612               clib_warning
1613                 ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): Invalid "
1614                  "AF_INET addr len %u!", getpid (), fd, fd, sid, sid, len);
1615               errno = EINVAL;
1616               rv = -1;
1617               goto done;
1618             }
1619           ep.is_ip4 = VPPCOM_IS_IP4;
1620           ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1621           ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1622           break;
1623
1624         case AF_INET6:
1625           if (len != sizeof (struct sockaddr_in6))
1626             {
1627               clib_warning
1628                 ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): Invalid "
1629                  "AF_INET6 addr len %u!", getpid (), fd, fd, sid, sid, len);
1630               errno = EINVAL;
1631               rv = -1;
1632               goto done;
1633             }
1634           ep.is_ip4 = VPPCOM_IS_IP6;
1635           ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1636           ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1637           break;
1638
1639         default:
1640           clib_warning ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): "
1641                         "Unsupported address family %u!",
1642                         getpid (), fd, fd, sid, sid, addr->sa_family);
1643           errno = EAFNOSUPPORT;
1644           rv = -1;
1645           goto done;
1646         }
1647       if (LDP_DEBUG > 0)
1648         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x) "
1649                       "addr %p len %u",
1650                       getpid (), fd, fd, func_str, sid, sid, addr, len);
1651
1652       rv = vppcom_session_connect (sid, &ep);
1653       if (rv != VPPCOM_OK)
1654         {
1655           errno = -rv;
1656           rv = -1;
1657         }
1658     }
1659   else
1660     {
1661       func_str = "libc_connect";
1662
1663       if (LDP_DEBUG > 0)
1664         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1665                       "addr %p, len %u",
1666                       getpid (), fd, fd, func_str, addr, len);
1667
1668       rv = libc_connect (fd, addr, len);
1669     }
1670
1671 done:
1672   if (LDP_DEBUG > 0)
1673     {
1674       if (rv < 0)
1675         {
1676           int errno_val = errno;
1677           perror (func_str);
1678           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1679                         "rv %d, errno = %d", getpid (), fd, fd,
1680                         func_str, rv, errno_val);
1681           errno = errno_val;
1682         }
1683       else
1684         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1685                       getpid (), fd, fd, rv, rv);
1686     }
1687   return rv;
1688 }
1689
1690 int
1691 getpeername (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
1692 {
1693   int rv;
1694   const char *func_str;
1695   u32 sid = ldp_sid_from_fd (fd);
1696
1697   if ((errno = -ldp_init ()))
1698     return -1;
1699
1700   if (sid != INVALID_SESSION_ID)
1701     {
1702       vppcom_endpt_t ep;
1703       u8 addr_buf[sizeof (struct in6_addr)];
1704       u32 size = sizeof (ep);
1705
1706       ep.ip = addr_buf;
1707       func_str = "vppcom_session_attr[GET_PEER_ADDR]";
1708
1709       if (LDP_DEBUG > 2)
1710         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1711                       "addr %p, len %u",
1712                       getpid (), fd, fd, func_str, sid, sid, addr, len);
1713
1714       rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size);
1715       if (rv != VPPCOM_OK)
1716         {
1717           errno = -rv;
1718           rv = -1;
1719         }
1720       else
1721         {
1722           rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
1723           if (rv != VPPCOM_OK)
1724             {
1725               errno = -rv;
1726               rv = -1;
1727             }
1728         }
1729     }
1730   else
1731     {
1732       func_str = "libc_getpeername";
1733
1734       if (LDP_DEBUG > 2)
1735         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1736                       "addr %p, len %u",
1737                       getpid (), fd, fd, func_str, addr, len);
1738
1739       rv = libc_getpeername (fd, addr, len);
1740     }
1741
1742   if (LDP_DEBUG > 2)
1743     {
1744       if (rv < 0)
1745         {
1746           int errno_val = errno;
1747           perror (func_str);
1748           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1749                         "rv %d, errno = %d", getpid (), fd, fd,
1750                         func_str, rv, errno_val);
1751           errno = errno_val;
1752         }
1753       else
1754         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1755                       getpid (), fd, fd, rv, rv);
1756     }
1757   return rv;
1758 }
1759
1760 ssize_t
1761 send (int fd, const void *buf, size_t n, int flags)
1762 {
1763   ssize_t size;
1764   const char *func_str;
1765   u32 sid = ldp_sid_from_fd (fd);
1766
1767   if ((errno = -ldp_init ()))
1768     return -1;
1769
1770   if (sid != INVALID_SESSION_ID)
1771     {
1772
1773       func_str = "vppcom_session_sendto";
1774
1775       if (LDP_DEBUG > 2)
1776         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1777                       "buf %p, n %u, flags 0x%x",
1778                       getpid (), fd, fd, func_str, sid, sid, buf, n, flags);
1779
1780       size = vppcom_session_sendto (sid, (void *) buf, n, flags, NULL);
1781       if (size < VPPCOM_OK)
1782         {
1783           errno = -size;
1784           size = -1;
1785         }
1786     }
1787   else
1788     {
1789       func_str = "libc_send";
1790
1791       if (LDP_DEBUG > 2)
1792         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1793                       "buf %p, n %u, flags 0x%x",
1794                       getpid (), fd, fd, func_str, buf, n, flags);
1795
1796       size = libc_send (fd, buf, n, flags);
1797     }
1798
1799   if (LDP_DEBUG > 2)
1800     {
1801       if (size < 0)
1802         {
1803           int errno_val = errno;
1804           perror (func_str);
1805           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1806                         "rv %d, errno = %d", getpid (), fd, fd,
1807                         func_str, size, errno_val);
1808           errno = errno_val;
1809         }
1810       else
1811         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1812                       getpid (), fd, fd, size, size);
1813     }
1814   return size;
1815 }
1816
1817 ssize_t
1818 sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
1819 {
1820   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
1821   ssize_t size = 0;
1822   const char *func_str;
1823   u32 sid = ldp_sid_from_fd (out_fd);
1824
1825   if ((errno = -ldp_init ()))
1826     return -1;
1827
1828   if (sid != INVALID_SESSION_ID)
1829     {
1830       int rv;
1831       ssize_t results = 0;
1832       size_t n_bytes_left = len;
1833       size_t bytes_to_read;
1834       int nbytes;
1835       int errno_val;
1836       u8 eagain = 0;
1837       u32 flags, flags_len = sizeof (flags);
1838
1839       func_str = "vppcom_session_attr[GET_FLAGS]";
1840       rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_FLAGS, &flags,
1841                                 &flags_len);
1842       if (PREDICT_FALSE (rv != VPPCOM_OK))
1843         {
1844           clib_warning ("LDP<%d>: ERROR: out fd %d (0x%x): %s(): "
1845                         "sid %u (0x%x), returned %d (%s)!", getpid (),
1846                         out_fd, out_fd, func_str, sid, sid, rv,
1847                         vppcom_retval_str (rv));
1848
1849           vec_reset_length (ldpw->io_buffer);
1850           errno = -rv;
1851           size = -1;
1852           goto done;
1853         }
1854
1855       if (offset)
1856         {
1857           off_t off = lseek (in_fd, *offset, SEEK_SET);
1858           if (PREDICT_FALSE (off == -1))
1859             {
1860               func_str = "lseek";
1861               errno_val = errno;
1862               clib_warning ("LDP<%d>: ERROR: out fd %d (0x%x): %s(): "
1863                             "SEEK_SET failed: in_fd %d, offset %p, "
1864                             "*offset %ld, rv %ld, errno %d", getpid (),
1865                             out_fd, out_fd, in_fd, offset, *offset, off,
1866                             errno_val);
1867               errno = errno_val;
1868               size = -1;
1869               goto done;
1870             }
1871
1872           ASSERT (off == *offset);
1873         }
1874
1875       do
1876         {
1877           func_str = "vppcom_session_attr[GET_NWRITE]";
1878           size = vppcom_session_attr (sid, VPPCOM_ATTR_GET_NWRITE, 0, 0);
1879           if (size < 0)
1880             {
1881               clib_warning
1882                 ("LDP<%d>: ERROR: fd %d (0x%x): %s(): sid %u (0x%x), "
1883                  "returned %d (%s)!", getpid (), out_fd, out_fd, func_str,
1884                  sid, sid, size, vppcom_retval_str (size));
1885               vec_reset_length (ldpw->io_buffer);
1886               errno = -size;
1887               size = -1;
1888               goto done;
1889             }
1890
1891           bytes_to_read = size;
1892           if (LDP_DEBUG > 2)
1893             clib_warning
1894               ("LDP<%d>: fd %d (0x%x): called %s(): sid %u (0x%x), "
1895                "results %ld, n_bytes_left %lu, bytes_to_read %lu", getpid (),
1896                out_fd, out_fd, func_str, sid, sid, results, n_bytes_left,
1897                bytes_to_read);
1898
1899           if (bytes_to_read == 0)
1900             {
1901               if (flags & O_NONBLOCK)
1902                 {
1903                   if (!results)
1904                     {
1905                       if (LDP_DEBUG > 2)
1906                         clib_warning ("LDP<%d>: fd %d (0x%x): sid %u (0x%x): "
1907                                       "EAGAIN",
1908                                       getpid (), out_fd, out_fd, sid, sid);
1909                       eagain = 1;
1910                     }
1911                   goto update_offset;
1912                 }
1913               else
1914                 continue;
1915             }
1916           bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
1917           vec_validate (ldpw->io_buffer, bytes_to_read);
1918           nbytes = libc_read (in_fd, ldpw->io_buffer, bytes_to_read);
1919           if (nbytes < 0)
1920             {
1921               func_str = "libc_read";
1922               errno_val = errno;
1923               clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): in_fd (%d), "
1924                             "io_buffer %p, bytes_to_read %lu, rv %d, "
1925                             "errno %d", getpid (), out_fd, out_fd, func_str,
1926                             in_fd, ldpw->io_buffer, bytes_to_read, nbytes,
1927                             errno_val);
1928               errno = errno_val;
1929
1930               if (results == 0)
1931                 {
1932                   vec_reset_length (ldpw->io_buffer);
1933                   size = -1;
1934                   goto done;
1935                 }
1936               goto update_offset;
1937             }
1938           func_str = "vppcom_session_write";
1939           if (LDP_DEBUG > 2)
1940             clib_warning
1941               ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1942                "buf %p, nbytes %u: results %d, n_bytes_left %d", getpid (),
1943                out_fd, out_fd, func_str, sid, sid, ldpw->io_buffer, nbytes,
1944                results, n_bytes_left);
1945
1946           size = vppcom_session_write (sid, ldpw->io_buffer, nbytes);
1947           if (size < 0)
1948             {
1949               if (size == VPPCOM_EAGAIN)
1950                 {
1951                   if (flags & O_NONBLOCK)
1952                     {
1953                       if (!results)
1954                         {
1955                           if (LDP_DEBUG > 2)
1956                             clib_warning
1957                               ("LDP<%d>: fd %d (0x%x): sid %u (0x%x): "
1958                                "EAGAIN", getpid (), out_fd, out_fd, sid, sid);
1959                           eagain = 1;
1960                         }
1961                       goto update_offset;
1962                     }
1963                   else
1964                     continue;
1965                 }
1966               else
1967                 {
1968                   clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s():"
1969                                 "sid %u, io_buffer %p, nbytes %u "
1970                                 "returned %d (%s)",
1971                                 getpid (), out_fd, out_fd, func_str,
1972                                 sid, ldpw->io_buffer, nbytes,
1973                                 size, vppcom_retval_str (size));
1974                 }
1975               if (results == 0)
1976                 {
1977                   vec_reset_length (ldpw->io_buffer);
1978                   errno = -size;
1979                   size = -1;
1980                   goto done;
1981                 }
1982               goto update_offset;
1983             }
1984
1985           results += nbytes;
1986           ASSERT (n_bytes_left >= nbytes);
1987           n_bytes_left = n_bytes_left - nbytes;
1988         }
1989       while (n_bytes_left > 0);
1990
1991     update_offset:
1992       vec_reset_length (ldpw->io_buffer);
1993       if (offset)
1994         {
1995           off_t off = lseek (in_fd, *offset, SEEK_SET);
1996           if (PREDICT_FALSE (off == -1))
1997             {
1998               func_str = "lseek";
1999               errno_val = errno;
2000               clib_warning ("LDP<%d>: ERROR: %s(): SEEK_SET failed: "
2001                             "in_fd %d, offset %p, *offset %ld, "
2002                             "rv %ld, errno %d", getpid (), in_fd,
2003                             offset, *offset, off, errno_val);
2004               errno = errno_val;
2005               size = -1;
2006               goto done;
2007             }
2008
2009           ASSERT (off == *offset);
2010           *offset += results + 1;
2011         }
2012       if (eagain)
2013         {
2014           errno = EAGAIN;
2015           size = -1;
2016         }
2017       else
2018         size = results;
2019     }
2020   else
2021     {
2022       func_str = "libc_send";
2023
2024       if (LDP_DEBUG > 2)
2025         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2026                       "in_fd %d, offset %p, len %u",
2027                       getpid (), out_fd, out_fd, func_str,
2028                       in_fd, offset, len);
2029
2030       size = libc_sendfile (out_fd, in_fd, offset, len);
2031     }
2032
2033 done:
2034   if (LDP_DEBUG > 2)
2035     {
2036       if (size < 0)
2037         {
2038           int errno_val = errno;
2039           perror (func_str);
2040           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2041                         "rv %d, errno = %d", getpid (), out_fd, out_fd,
2042                         func_str, size, errno_val);
2043           errno = errno_val;
2044         }
2045       else
2046         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2047                       getpid (), out_fd, out_fd, size, size);
2048     }
2049   return size;
2050 }
2051
2052 ssize_t
2053 sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len)
2054 {
2055   return sendfile (out_fd, in_fd, offset, len);
2056 }
2057
2058 ssize_t
2059 recv (int fd, void *buf, size_t n, int flags)
2060 {
2061   ssize_t size;
2062   const char *func_str;
2063   u32 sid = ldp_sid_from_fd (fd);
2064
2065   if ((errno = -ldp_init ()))
2066     return -1;
2067
2068   if (sid != INVALID_SESSION_ID)
2069     {
2070       func_str = "vppcom_session_recvfrom";
2071
2072       if (LDP_DEBUG > 2)
2073         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2074                       "sid %u (0x%x), buf %p, n %u, flags 0x%x", getpid (),
2075                       fd, fd, func_str, sid, sid, buf, n, flags);
2076
2077       size = vppcom_session_recvfrom (sid, buf, n, flags, NULL);
2078       if (size < 0)
2079         {
2080           errno = -size;
2081           size = -1;
2082         }
2083     }
2084   else
2085     {
2086       func_str = "libc_recv";
2087
2088       if (LDP_DEBUG > 2)
2089         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2090                       "buf %p, n %u, flags 0x%x", getpid (),
2091                       fd, fd, func_str, buf, n, flags);
2092
2093       size = libc_recv (fd, buf, n, flags);
2094     }
2095
2096   if (LDP_DEBUG > 2)
2097     {
2098       if (size < 0)
2099         {
2100           int errno_val = errno;
2101           perror (func_str);
2102           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2103                         "rv %d, errno = %d", getpid (), fd, fd,
2104                         func_str, size, errno_val);
2105           errno = errno_val;
2106         }
2107       else
2108         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2109                       getpid (), fd, fd, size, size);
2110     }
2111   return size;
2112 }
2113
2114 ssize_t
2115 sendto (int fd, const void *buf, size_t n, int flags,
2116         __CONST_SOCKADDR_ARG addr, socklen_t addr_len)
2117 {
2118   ssize_t size;
2119   const char *func_str = __func__;
2120   u32 sid = ldp_sid_from_fd (fd);
2121
2122   if ((errno = -ldp_init ()))
2123     return -1;
2124
2125   if (sid != INVALID_SESSION_ID)
2126     {
2127       vppcom_endpt_t *ep = 0;
2128       vppcom_endpt_t _ep;
2129
2130       if (addr)
2131         {
2132           ep = &_ep;
2133           switch (addr->sa_family)
2134             {
2135             case AF_INET:
2136               ep->is_ip4 = VPPCOM_IS_IP4;
2137               ep->ip =
2138                 (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr;
2139               ep->port =
2140                 (uint16_t) ((const struct sockaddr_in *) addr)->sin_port;
2141               break;
2142
2143             case AF_INET6:
2144               ep->is_ip4 = VPPCOM_IS_IP6;
2145               ep->ip =
2146                 (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
2147               ep->port =
2148                 (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port;
2149               break;
2150
2151             default:
2152               errno = EAFNOSUPPORT;
2153               size = -1;
2154               goto done;
2155             }
2156         }
2157
2158       func_str = "vppcom_session_sendto";
2159
2160       if (LDP_DEBUG > 2)
2161         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2162                       "sid %u (0x%x), buf %p, n %u, flags 0x%x, ep %p",
2163                       getpid (), fd, fd, func_str, sid, sid, buf, n,
2164                       flags, ep);
2165
2166       size = vppcom_session_sendto (sid, (void *) buf, n, flags, ep);
2167       if (size < 0)
2168         {
2169           errno = -size;
2170           size = -1;
2171         }
2172     }
2173   else
2174     {
2175       func_str = "libc_sendto";
2176
2177       if (LDP_DEBUG > 2)
2178         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2179                       "buf %p, n %u, flags 0x%x, addr %p, addr_len %d",
2180                       getpid (), fd, fd, func_str, buf, n, flags,
2181                       addr, addr_len);
2182
2183       size = libc_sendto (fd, buf, n, flags, addr, addr_len);
2184     }
2185
2186 done:
2187   if (LDP_DEBUG > 2)
2188     {
2189       if (size < 0)
2190         {
2191           int errno_val = errno;
2192           perror (func_str);
2193           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2194                         "rv %d, errno = %d", getpid (), fd, fd,
2195                         func_str, size, errno_val);
2196           errno = errno_val;
2197         }
2198       else
2199         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2200                       getpid (), fd, fd, size, size);
2201     }
2202   return size;
2203 }
2204
2205 ssize_t
2206 recvfrom (int fd, void *__restrict buf, size_t n, int flags,
2207           __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
2208 {
2209   ssize_t size;
2210   const char *func_str;
2211   u32 sid = ldp_sid_from_fd (fd);
2212
2213   if ((errno = -ldp_init ()))
2214     return -1;
2215
2216   if (sid != INVALID_SESSION_ID)
2217     {
2218       vppcom_endpt_t ep;
2219       u8 src_addr[sizeof (struct sockaddr_in6)];
2220
2221       func_str = "vppcom_session_recvfrom";
2222
2223       if (LDP_DEBUG > 2)
2224         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2225                       "sid %u (0x%x), buf %p, n %u, flags 0x%x, ep %p",
2226                       getpid (), fd, fd, func_str, sid, sid, buf, n,
2227                       flags, &ep);
2228       if (addr)
2229         {
2230           ep.ip = src_addr;
2231           size = vppcom_session_recvfrom (sid, buf, n, flags, &ep);
2232
2233           if (size > 0)
2234             size = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
2235         }
2236       else
2237         size = vppcom_session_recvfrom (sid, buf, n, flags, NULL);
2238
2239       if (size < 0)
2240         {
2241           errno = -size;
2242           size = -1;
2243         }
2244     }
2245   else
2246     {
2247       func_str = "libc_recvfrom";
2248
2249       if (LDP_DEBUG > 2)
2250         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2251                       "buf %p, n %u, flags 0x%x, addr %p, addr_len %d",
2252                       getpid (), fd, fd, func_str, buf, n, flags,
2253                       addr, addr_len);
2254
2255       size = libc_recvfrom (fd, buf, n, flags, addr, addr_len);
2256     }
2257
2258   if (LDP_DEBUG > 2)
2259     {
2260       if (size < 0)
2261         {
2262           int errno_val = errno;
2263           perror (func_str);
2264           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2265                         "rv %d, errno = %d", getpid (), fd, fd,
2266                         func_str, size, errno_val);
2267           errno = errno_val;
2268         }
2269       else
2270         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2271                       getpid (), fd, fd, size, size);
2272     }
2273   return size;
2274 }
2275
2276 ssize_t
2277 sendmsg (int fd, const struct msghdr * message, int flags)
2278 {
2279   ssize_t size;
2280   const char *func_str;
2281   u32 sid = ldp_sid_from_fd (fd);
2282
2283   if ((errno = -ldp_init ()))
2284     return -1;
2285
2286   if (sid != INVALID_SESSION_ID)
2287     {
2288       func_str = __func__;
2289
2290       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2291       errno = ENOSYS;
2292       size = -1;
2293     }
2294   else
2295     {
2296       func_str = "libc_sendmsg";
2297
2298       if (LDP_DEBUG > 2)
2299         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2300                       "message %p, flags 0x%x",
2301                       getpid (), fd, fd, func_str, message, flags);
2302
2303       size = libc_sendmsg (fd, message, flags);
2304     }
2305
2306   if (LDP_DEBUG > 2)
2307     {
2308       if (size < 0)
2309         {
2310           int errno_val = errno;
2311           perror (func_str);
2312           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2313                         "rv %d, errno = %d", getpid (), fd, fd,
2314                         func_str, size, errno_val);
2315           errno = errno_val;
2316         }
2317       else
2318         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2319                       getpid (), fd, fd, size, size);
2320     }
2321   return size;
2322 }
2323
2324 #ifdef USE_GNU
2325 int
2326 sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
2327 {
2328   ssize_t size;
2329   const char *func_str;
2330   u32 sid = ldp_sid_from_fd (fd);
2331
2332   if ((errno = -ldp_init ()))
2333     return -1;
2334
2335   if (sid != INVALID_SESSION_ID)
2336     {
2337       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2338       errno = ENOSYS;
2339       size = -1;
2340     }
2341   else
2342     {
2343       func_str = "libc_sendmmsg";
2344
2345       if (LDP_DEBUG > 2)
2346         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2347                       "vmessages %p, vlen %u, flags 0x%x",
2348                       getpid (), fd, fd, func_str, vmessages, vlen, flags);
2349
2350       size = libc_sendmmsg (fd, vmessages, vlen, flags);
2351     }
2352
2353   if (LDP_DEBUG > 2)
2354     {
2355       if (size < 0)
2356         {
2357           int errno_val = errno;
2358           perror (func_str);
2359           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2360                         "rv %d, errno = %d", getpid (), fd, fd,
2361                         func_str, size, errno_val);
2362           errno = errno_val;
2363         }
2364       else
2365         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2366                       getpid (), fd, fd, size, size);
2367     }
2368   return size;
2369 }
2370 #endif
2371
2372 ssize_t
2373 recvmsg (int fd, struct msghdr * message, int flags)
2374 {
2375   ssize_t size;
2376   const char *func_str;
2377   u32 sid = ldp_sid_from_fd (fd);
2378
2379   if ((errno = -ldp_init ()))
2380     return -1;
2381
2382   if (sid != INVALID_SESSION_ID)
2383     {
2384       func_str = __func__;
2385
2386       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2387       errno = ENOSYS;
2388       size = -1;
2389     }
2390   else
2391     {
2392       func_str = "libc_recvmsg";
2393
2394       if (LDP_DEBUG > 2)
2395         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2396                       "message %p, flags 0x%x",
2397                       getpid (), fd, fd, func_str, message, flags);
2398
2399       size = libc_recvmsg (fd, message, flags);
2400     }
2401
2402   if (LDP_DEBUG > 2)
2403     {
2404       if (size < 0)
2405         {
2406           int errno_val = errno;
2407           perror (func_str);
2408           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2409                         "rv %d, errno = %d", getpid (), fd, fd,
2410                         func_str, size, errno_val);
2411           errno = errno_val;
2412         }
2413       else
2414         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2415                       getpid (), fd, fd, size, size);
2416     }
2417   return size;
2418 }
2419
2420 #ifdef USE_GNU
2421 int
2422 recvmmsg (int fd, struct mmsghdr *vmessages,
2423           unsigned int vlen, int flags, struct timespec *tmo)
2424 {
2425   ssize_t size;
2426   const char *func_str;
2427   u32 sid = ldp_sid_from_fd (fd);
2428
2429   if ((errno = -ldp_init ()))
2430     return -1;
2431
2432   if (sid != INVALID_SESSION_ID)
2433     {
2434       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2435       errno = ENOSYS;
2436       size = -1;
2437     }
2438   else
2439     {
2440       func_str = "libc_recvmmsg";
2441
2442       if (LDP_DEBUG > 2)
2443         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2444                       "vmessages %p, vlen %u, flags 0x%x, tmo %p",
2445                       getpid (), fd, fd, func_str, vmessages, vlen,
2446                       flags, tmo);
2447
2448       size = libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
2449     }
2450
2451   if (LDP_DEBUG > 2)
2452     {
2453       if (size < 0)
2454         {
2455           int errno_val = errno;
2456           perror (func_str);
2457           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2458                         "rv %d, errno = %d", getpid (), fd, fd,
2459                         func_str, size, errno_val);
2460           errno = errno_val;
2461         }
2462       else
2463         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2464                       getpid (), fd, fd, size, size);
2465     }
2466   return size;
2467 }
2468 #endif
2469
2470 int
2471 getsockopt (int fd, int level, int optname,
2472             void *__restrict optval, socklen_t * __restrict optlen)
2473 {
2474   int rv;
2475   const char *func_str = __func__;
2476   u32 sid = ldp_sid_from_fd (fd);
2477   u32 buflen = optlen ? (u32) * optlen : 0;
2478
2479   if ((errno = -ldp_init ()))
2480     return -1;
2481
2482   if (sid != INVALID_SESSION_ID)
2483     {
2484       rv = -EOPNOTSUPP;
2485
2486       switch (level)
2487         {
2488         case SOL_TCP:
2489           switch (optname)
2490             {
2491             case TCP_NODELAY:
2492               func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_NODELAY]";
2493               if (LDP_DEBUG > 1)
2494                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2495                               "sid %u (0x%x)",
2496                               getpid (), fd, fd, func_str, sid, sid);
2497               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_NODELAY,
2498                                         optval, optlen);
2499               break;
2500             case TCP_MAXSEG:
2501               func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_USER_MSS]";
2502               if (LDP_DEBUG > 1)
2503                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2504                               "sid %u (0x%x)",
2505                               getpid (), fd, fd, func_str, sid, sid);
2506               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_USER_MSS,
2507                                         optval, optlen);
2508               break;
2509             case TCP_KEEPIDLE:
2510               func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_KEEPIDLE]";
2511               if (LDP_DEBUG > 1)
2512                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2513                               "sid %u (0x%x)",
2514                               getpid (), fd, fd, func_str, sid, sid);
2515               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
2516                                         optval, optlen);
2517               break;
2518             case TCP_KEEPINTVL:
2519               func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_KEEPINTVL]";
2520               if (LDP_DEBUG > 1)
2521                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2522                               "sid %u (0x%x), SOL_TCP",
2523                               getpid (), fd, fd, func_str, sid, sid);
2524               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
2525                                         optval, optlen);
2526               break;
2527             case TCP_INFO:
2528               if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
2529                 {
2530                   if (LDP_DEBUG > 1)
2531                     clib_warning ("LDP<%d>: fd %d (0x%x): sid %u (0x%x), "
2532                                   "SOL_TCP, TCP_INFO, optval %p, "
2533                                   "optlen %d: #LDP-NOP#",
2534                                   getpid (), fd, fd, sid, sid,
2535                                   optval, *optlen);
2536                   memset (optval, 0, *optlen);
2537                   rv = VPPCOM_OK;
2538                 }
2539               else
2540                 rv = -EFAULT;
2541               break;
2542             default:
2543               if (LDP_DEBUG > 1)
2544                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2545                               "sid %u (0x%x), SOL_TCP, "
2546                               "optname %d unsupported!",
2547                               getpid (), fd, fd, func_str, sid, sid, optname);
2548               break;
2549             }
2550           break;
2551         case SOL_IPV6:
2552           switch (optname)
2553             {
2554             case IPV6_V6ONLY:
2555               func_str = "vppcom_session_attr[SOL_IPV6,GET_V6ONLY]";
2556               if (LDP_DEBUG > 1)
2557                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2558                               "sid %u (0x%x)",
2559                               getpid (), fd, fd, func_str, sid, sid);
2560               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_V6ONLY,
2561                                         optval, optlen);
2562               break;
2563             default:
2564               if (LDP_DEBUG > 1)
2565                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2566                               "sid %u (0x%x), SOL_IPV6, "
2567                               "optname %d unsupported!",
2568                               getpid (), fd, fd, func_str, sid, sid, optname);
2569               break;
2570             }
2571           break;
2572         case SOL_SOCKET:
2573           switch (optname)
2574             {
2575             case SO_ACCEPTCONN:
2576               func_str = "vppcom_session_attr[SOL_SOCKET,GET_ACCEPTCONN]";
2577               if (LDP_DEBUG > 1)
2578                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2579                               "sid %u (0x%x)",
2580                               getpid (), fd, fd, func_str, sid, sid);
2581               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LISTEN,
2582                                         optval, optlen);
2583               break;
2584             case SO_KEEPALIVE:
2585               func_str = "vppcom_session_attr[SOL_SOCKET,GET_KEEPALIVE]";
2586               if (LDP_DEBUG > 1)
2587                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2588                               "sid %u (0x%x)",
2589                               getpid (), fd, fd, func_str, sid, sid);
2590               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_KEEPALIVE,
2591                                         optval, optlen);
2592               break;
2593             case SO_PROTOCOL:
2594               func_str = "vppcom_session_attr[SOL_SOCKET,GET_PROTOCOL]";
2595               if (LDP_DEBUG > 1)
2596                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2597                               "sid %u (0x%x)",
2598                               getpid (), fd, fd, func_str, sid, sid);
2599               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PROTOCOL,
2600                                         optval, optlen);
2601               *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
2602               break;
2603             case SO_SNDBUF:
2604               func_str = "vppcom_session_attr[SOL_SOCKET,GET_TX_FIFO_LEN]";
2605               if (LDP_DEBUG > 1)
2606                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2607                               "sid %u (0x%x), optlen %d",
2608                               getpid (), fd, fd, func_str, sid, sid, buflen);
2609               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TX_FIFO_LEN,
2610                                         optval, optlen);
2611               break;
2612             case SO_RCVBUF:
2613               func_str = "vppcom_session_attr[SOL_SOCKET,GET_RX_FIFO_LEN]";
2614               if (LDP_DEBUG > 1)
2615                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2616                               "sid %u (0x%x), optlen %d",
2617                               getpid (), fd, fd, func_str, sid, sid, buflen);
2618               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_RX_FIFO_LEN,
2619                                         optval, optlen);
2620               break;
2621             case SO_REUSEADDR:
2622               func_str = "vppcom_session_attr[SOL_SOCKET,GET_REUSEADDR]";
2623               if (LDP_DEBUG > 1)
2624                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2625                               "sid %u (0x%x)",
2626                               getpid (), fd, fd, func_str, sid, sid);
2627               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_REUSEADDR,
2628                                         optval, optlen);
2629               break;
2630             case SO_BROADCAST:
2631               func_str = "vppcom_session_attr[SOL_SOCKET,GET_BROADCAST]";
2632               if (LDP_DEBUG > 1)
2633                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2634                               "sid %u (0x%x)",
2635                               getpid (), fd, fd, func_str, sid, sid);
2636               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_BROADCAST,
2637                                         optval, optlen);
2638               break;
2639             case SO_ERROR:
2640               func_str = "vppcom_session_attr[SOL_SOCKET,GET_ERROR]";
2641               if (LDP_DEBUG > 1)
2642                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2643                               "sid %u (0x%x)",
2644                               getpid (), fd, fd, func_str, sid, sid);
2645               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_ERROR,
2646                                         optval, optlen);
2647               break;
2648             default:
2649               if (LDP_DEBUG > 1)
2650                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2651                               "sid %u (0x%x), SOL_SOCKET, "
2652                               "optname %d unsupported!",
2653                               getpid (), fd, fd, func_str, sid, sid, optname);
2654               break;
2655             }
2656           break;
2657         default:
2658           break;
2659         }
2660
2661       if (rv != VPPCOM_OK)
2662         {
2663           errno = -rv;
2664           rv = -1;
2665         }
2666     }
2667   else
2668     {
2669       func_str = "libc_getsockopt";
2670
2671       if (LDP_DEBUG > 1)
2672         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): level %d, "
2673                       "optname %d, optval %p, optlen %d",
2674                       getpid (), fd, fd, func_str, level, optname,
2675                       optval, optlen);
2676
2677       rv = libc_getsockopt (fd, level, optname, optval, optlen);
2678     }
2679
2680   if (LDP_DEBUG > 1)
2681     {
2682       if (rv < 0)
2683         {
2684           int errno_val = errno;
2685           perror (func_str);
2686           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2687                         "rv %d, errno = %d", getpid (), fd, fd,
2688                         func_str, rv, errno_val);
2689           errno = errno_val;
2690         }
2691       else
2692         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2693                       getpid (), fd, fd, rv, rv);
2694     }
2695   return rv;
2696 }
2697
2698 int
2699 setsockopt (int fd, int level, int optname,
2700             const void *optval, socklen_t optlen)
2701 {
2702   int rv;
2703   const char *func_str = __func__;
2704   u32 sid = ldp_sid_from_fd (fd);
2705
2706   if ((errno = -ldp_init ()))
2707     return -1;
2708
2709   if (sid != INVALID_SESSION_ID)
2710     {
2711       rv = -EOPNOTSUPP;
2712
2713       switch (level)
2714         {
2715         case SOL_TCP:
2716           switch (optname)
2717             {
2718             case TCP_NODELAY:
2719               func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_NODELAY]";
2720               if (LDP_DEBUG > 1)
2721                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2722                               "sid %u (0x%x)",
2723                               getpid (), fd, fd, func_str, sid, sid);
2724               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_NODELAY,
2725                                         (void *) optval, &optlen);
2726               break;
2727             case TCP_MAXSEG:
2728               func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_USER_MSS]";
2729               if (LDP_DEBUG > 1)
2730                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2731                               "sid %u (0x%x)",
2732                               getpid (), fd, fd, func_str, sid, sid);
2733               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_USER_MSS,
2734                                         (void *) optval, &optlen);
2735               break;
2736             case TCP_KEEPIDLE:
2737               func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_KEEPIDLE]";
2738               if (LDP_DEBUG > 1)
2739                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2740                               "sid %u (0x%x)",
2741                               getpid (), fd, fd, func_str, sid, sid);
2742               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
2743                                         (void *) optval, &optlen);
2744               break;
2745             case TCP_KEEPINTVL:
2746               func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_KEEPINTVL]";
2747               if (LDP_DEBUG > 1)
2748                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2749                               "sid %u (0x%x), SOL_TCP",
2750                               getpid (), fd, fd, func_str, sid, sid);
2751               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
2752                                         (void *) optval, &optlen);
2753               break;
2754             default:
2755               if (LDP_DEBUG > 1)
2756                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2757                               "sid %u (0x%x), SOL_TCP, "
2758                               "optname %d unsupported!",
2759                               getpid (), fd, fd, func_str, sid, sid, optname);
2760               break;
2761             }
2762           break;
2763         case SOL_IPV6:
2764           switch (optname)
2765             {
2766             case IPV6_V6ONLY:
2767               func_str = "vppcom_session_attr[SOL_IPV6,SET_V6ONLY]";
2768               if (LDP_DEBUG > 1)
2769                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2770                               "sid %u (0x%x)",
2771                               getpid (), fd, fd, func_str, sid, sid);
2772               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_V6ONLY,
2773                                         (void *) optval, &optlen);
2774               break;
2775             default:
2776               if (LDP_DEBUG > 1)
2777                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2778                               "sid %u (0x%x), SOL_IPV6, "
2779                               "optname %d unsupported!",
2780                               getpid (), fd, fd, func_str, sid, sid, optname);
2781               break;
2782             }
2783           break;
2784         case SOL_SOCKET:
2785           switch (optname)
2786             {
2787             case SO_KEEPALIVE:
2788               func_str = "vppcom_session_attr[SOL_SOCKET,SET_KEEPALIVE]";
2789               if (LDP_DEBUG > 1)
2790                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2791                               "sid %u (0x%x)",
2792                               getpid (), fd, fd, func_str, sid, sid);
2793               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_KEEPALIVE,
2794                                         (void *) optval, &optlen);
2795               break;
2796             case SO_REUSEADDR:
2797               func_str = "vppcom_session_attr[SOL_SOCKET,SET_REUSEADDR]";
2798               if (LDP_DEBUG > 1)
2799                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2800                               "sid %u (0x%x)",
2801                               getpid (), fd, fd, func_str, sid, sid);
2802               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_REUSEADDR,
2803                                         (void *) optval, &optlen);
2804               break;
2805             case SO_BROADCAST:
2806               func_str = "vppcom_session_attr[SOL_SOCKET,SET_BROADCAST]";
2807               if (LDP_DEBUG > 1)
2808                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2809                               "sid %u (0x%x)",
2810                               getpid (), fd, fd, func_str, sid, sid);
2811               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_BROADCAST,
2812                                         (void *) optval, &optlen);
2813               break;
2814             default:
2815               if (LDP_DEBUG > 1)
2816                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2817                               "sid %u (0x%x), SOL_SOCKET, "
2818                               "optname %d unsupported!",
2819                               getpid (), fd, fd, func_str, sid, sid, optname);
2820               break;
2821             }
2822           break;
2823         default:
2824           break;
2825         }
2826
2827       if (rv != VPPCOM_OK)
2828         {
2829           errno = -rv;
2830           rv = -1;
2831         }
2832     }
2833   else
2834     {
2835       func_str = "libc_setsockopt";
2836
2837       if (LDP_DEBUG > 1)
2838         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): level %d, "
2839                       "optname %d, optval %p, optlen %d",
2840                       getpid (), fd, fd, func_str, level, optname,
2841                       optval, optlen);
2842
2843       rv = libc_setsockopt (fd, level, optname, optval, optlen);
2844     }
2845
2846   if (LDP_DEBUG > 1)
2847     {
2848       if (rv < 0)
2849         {
2850           int errno_val = errno;
2851           perror (func_str);
2852           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2853                         "rv %d, errno = %d", getpid (), fd, fd,
2854                         func_str, rv, errno_val);
2855           errno = errno_val;
2856         }
2857       else
2858         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2859                       getpid (), fd, fd, rv, rv);
2860     }
2861   return rv;
2862 }
2863
2864 int
2865 listen (int fd, int n)
2866 {
2867   int rv;
2868   const char *func_str;
2869   u32 sid = ldp_sid_from_fd (fd);
2870
2871   if ((errno = -ldp_init ()))
2872     return -1;
2873
2874   if (sid != INVALID_SESSION_ID)
2875     {
2876       func_str = "vppcom_session_listen";
2877
2878       LDBG (0, "LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), n %d",
2879             getpid (), fd, fd, func_str, sid, sid, n);
2880
2881       rv = vppcom_session_listen (sid, n);
2882       if (rv != VPPCOM_OK)
2883         {
2884           errno = -rv;
2885           rv = -1;
2886         }
2887     }
2888   else
2889     {
2890       func_str = "libc_listen";
2891
2892       LDBG (0, "LDP<%d>: fd %d (0x%x): calling %s(): n %d", getpid (), fd,
2893             fd, func_str, n);
2894
2895       rv = libc_listen (fd, n);
2896     }
2897
2898   if (LDP_DEBUG > 0)
2899     {
2900       if (rv < 0)
2901         {
2902           int errno_val = errno;
2903           perror (func_str);
2904           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2905                         "rv %d, errno = %d", getpid (), fd, fd,
2906                         func_str, rv, errno_val);
2907           errno = errno_val;
2908         }
2909       else
2910         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2911                       getpid (), fd, fd, rv, rv);
2912     }
2913   return rv;
2914 }
2915
2916 static inline int
2917 ldp_accept4 (int listen_fd, __SOCKADDR_ARG addr,
2918              socklen_t * __restrict addr_len, int flags)
2919 {
2920   int rv;
2921   const char *func_str;
2922   u32 listen_sid = ldp_sid_from_fd (listen_fd);
2923   int accept_sid;
2924
2925   if ((errno = -ldp_init ()))
2926     return -1;
2927
2928   if (listen_sid != INVALID_SESSION_ID)
2929     {
2930       vppcom_endpt_t ep;
2931       u8 src_addr[sizeof (struct sockaddr_in6)];
2932       memset (&ep, 0, sizeof (ep));
2933       ep.ip = src_addr;
2934
2935       func_str = "vppcom_session_accept";
2936
2937       if (LDP_DEBUG > 0)
2938         clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): "
2939                       "listen sid %u (0x%x), ep %p, flags 0x%x",
2940                       getpid (), listen_fd, listen_fd, func_str,
2941                       listen_sid, listen_sid, ep, flags);
2942
2943       accept_sid = vppcom_session_accept (listen_sid, &ep, flags);
2944       if (accept_sid < 0)
2945         {
2946           errno = -accept_sid;
2947           rv = -1;
2948         }
2949       else
2950         {
2951           rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
2952           if (rv != VPPCOM_OK)
2953             {
2954               (void) vppcom_session_close ((u32) accept_sid);
2955               errno = -rv;
2956               rv = -1;
2957             }
2958           else
2959             {
2960               func_str = "ldp_fd_from_sid";
2961               if (LDP_DEBUG > 0)
2962                 clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): "
2963                               "accept sid %u (0x%x), ep %p, flags 0x%x",
2964                               getpid (), listen_fd, listen_fd,
2965                               func_str, accept_sid, accept_sid, ep, flags);
2966               rv = ldp_fd_alloc ((u32) accept_sid);
2967               if (rv < 0)
2968                 {
2969                   (void) vppcom_session_close ((u32) accept_sid);
2970                   errno = -rv;
2971                   rv = -1;
2972                 }
2973             }
2974         }
2975     }
2976   else
2977     {
2978       func_str = "libc_accept4";
2979
2980       if (LDP_DEBUG > 0)
2981         clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): "
2982                       "addr %p, addr_len %p, flags 0x%x",
2983                       getpid (), listen_fd, listen_fd, func_str,
2984                       addr, addr_len, flags);
2985
2986       rv = libc_accept4 (listen_fd, addr, addr_len, flags);
2987     }
2988
2989   if (LDP_DEBUG > 0)
2990     {
2991       if (rv < 0)
2992         {
2993           int errno_val = errno;
2994           perror (func_str);
2995           clib_warning ("LDP<%d>: ERROR: listen fd %d (0x%x): %s() failed! "
2996                         "rv %d, errno = %d", getpid (), listen_fd,
2997                         listen_fd, func_str, rv, errno_val);
2998           errno = errno_val;
2999         }
3000       else
3001         clib_warning ("LDP<%d>: listen fd %d (0x%x): returning %d (0x%x)",
3002                       getpid (), listen_fd, listen_fd, rv, rv);
3003     }
3004   return rv;
3005 }
3006
3007 int
3008 accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
3009          int flags)
3010 {
3011   return ldp_accept4 (fd, addr, addr_len, flags);
3012 }
3013
3014 int
3015 accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
3016 {
3017   return ldp_accept4 (fd, addr, addr_len, 0);
3018 }
3019
3020 int
3021 shutdown (int fd, int how)
3022 {
3023   int rv;
3024   const char *func_str;
3025   u32 sid = ldp_sid_from_fd (fd);
3026
3027   if ((errno = -ldp_init ()))
3028     return -1;
3029
3030   if (sid != INVALID_SESSION_ID)
3031     {
3032       func_str = "vppcom_session_close[TODO]";
3033       rv = close (fd);
3034     }
3035   else
3036     {
3037       func_str = "libc_shutdown";
3038
3039       if (LDP_DEBUG > 1)
3040         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): how %d",
3041                       getpid (), fd, fd, func_str, how);
3042
3043       rv = libc_shutdown (fd, how);
3044     }
3045
3046   if (LDP_DEBUG > 1)
3047     {
3048       if (rv < 0)
3049         {
3050           int errno_val = errno;
3051           perror (func_str);
3052           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
3053                         "rv %d, errno = %d", getpid (), fd, fd,
3054                         func_str, rv, errno_val);
3055           errno = errno_val;
3056         }
3057       else
3058         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
3059                       getpid (), fd, fd, rv, rv);
3060     }
3061   return rv;
3062 }
3063
3064 int
3065 epoll_create1 (int flags)
3066 {
3067   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
3068   const char *func_str;
3069   int rv;
3070
3071   if ((errno = -ldp_init ()))
3072     return -1;
3073
3074   if (ldp->vcl_needs_real_epoll)
3075     {
3076       rv = libc_epoll_create1 (flags);
3077       ldp->vcl_needs_real_epoll = 0;
3078       ldpw->vcl_mq_epfd = rv;
3079       LDBG (0, "LDP<%d>: created vcl epfd %u", getpid (), rv);
3080       return rv;
3081     }
3082   func_str = "vppcom_epoll_create";
3083
3084   LDBG (1, "LDP<%d>: calling %s()", getpid (), func_str);
3085
3086   rv = vppcom_epoll_create ();
3087
3088   if (PREDICT_FALSE (rv < 0))
3089     {
3090       errno = -rv;
3091       rv = -1;
3092     }
3093   else
3094     rv = ldp_fd_alloc ((u32) rv);
3095
3096   if (LDP_DEBUG > 1)
3097     {
3098       if (rv < 0)
3099         {
3100           int errno_val = errno;
3101           perror (func_str);
3102           clib_warning ("LDP<%d>: ERROR: %s() failed! "
3103                         "rv %d, errno = %d",
3104                         getpid (), func_str, rv, errno_val);
3105           errno = errno_val;
3106         }
3107       else
3108         clib_warning ("LDP<%d>: returning epfd %d (0x%x)", getpid (), rv, rv);
3109     }
3110   return rv;
3111 }
3112
3113 int
3114 epoll_create (int size)
3115 {
3116   return epoll_create1 (0);
3117 }
3118
3119 int
3120 epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
3121 {
3122   u32 vep_idx = ldp_sid_from_fd (epfd), sid;
3123   const char *func_str;
3124   int rv;
3125
3126   if ((errno = -ldp_init ()))
3127     return -1;
3128
3129   if (PREDICT_FALSE (vep_idx == INVALID_SESSION_ID))
3130     {
3131       /* The LDP epoll_create1 always creates VCL epfd's.
3132        * The app should never have a kernel base epoll fd unless it
3133        * was acquired outside of the LD_PRELOAD process context.
3134        * In any case, if we get one, punt it to libc_epoll_ctl.
3135        */
3136       func_str = "libc_epoll_ctl";
3137
3138       LDBG (1, "LDP<%d>: epfd %d (0x%x): calling %s(): op %d, fd %d (0x%x),"
3139             " event %p", getpid (), epfd, epfd, func_str, op, fd, fd, event);
3140
3141       rv = libc_epoll_ctl (epfd, op, fd, event);
3142       goto done;
3143     }
3144
3145   sid = ldp_sid_from_fd (fd);
3146
3147   LDBG (0, "LDP<%d>: epfd %d (0x%x), vep_idx %d (0x%x), sid %d (0x%x)",
3148         getpid (), epfd, epfd, vep_idx, vep_idx, sid, sid);
3149
3150   if (sid != INVALID_SESSION_ID)
3151     {
3152       func_str = "vppcom_epoll_ctl";
3153
3154       LDBG (1, "LDP<%d>: epfd %d (0x%x): calling %s(): vep_idx %d (0x%x),"
3155             " op %d, sid %u (0x%x), event %p", getpid (), epfd, epfd,
3156             func_str, vep_idx, vep_idx, sid, sid, event);
3157
3158       rv = vppcom_epoll_ctl (vep_idx, op, sid, event);
3159       if (rv != VPPCOM_OK)
3160         {
3161           errno = -rv;
3162           rv = -1;
3163         }
3164     }
3165   else
3166     {
3167       int libc_epfd;
3168       u32 size = sizeof (epfd);
3169
3170       func_str = "vppcom_session_attr[GET_LIBC_EPFD]";
3171       libc_epfd = vppcom_session_attr (vep_idx, VPPCOM_ATTR_GET_LIBC_EPFD, 0,
3172                                        0);
3173       LDBG (1, "LDP<%d>: epfd %d (0x%x), vep_idx %d (0x%x): %s() "
3174             "returned libc_epfd %d (0x%x)", getpid (), epfd, epfd,
3175             vep_idx, vep_idx, func_str, libc_epfd, libc_epfd);
3176
3177       if (!libc_epfd)
3178         {
3179           func_str = "libc_epoll_create1";
3180
3181           LDBG (1, "LDP<%d>: epfd %d (0x%x), vep_idx %d (0x%x): "
3182                 "calling %s(): EPOLL_CLOEXEC", getpid (), epfd, epfd,
3183                 vep_idx, vep_idx, func_str);
3184
3185           libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
3186           if (libc_epfd < 0)
3187             {
3188               rv = libc_epfd;
3189               goto done;
3190             }
3191
3192           func_str = "vppcom_session_attr[SET_LIBC_EPFD]";
3193           LDBG (1, "LDP<%d>: epfd %d (0x%x): calling %s(): vep_idx %d (0x%x),"
3194                 " VPPCOM_ATTR_SET_LIBC_EPFD, libc_epfd %d (0x%x), size %d",
3195                 getpid (), epfd, epfd, func_str, vep_idx, vep_idx, libc_epfd,
3196                 libc_epfd, size);
3197
3198           rv = vppcom_session_attr (vep_idx, VPPCOM_ATTR_SET_LIBC_EPFD,
3199                                     &libc_epfd, &size);
3200           if (rv < 0)
3201             {
3202               errno = -rv;
3203               rv = -1;
3204               goto done;
3205             }
3206         }
3207       else if (PREDICT_FALSE (libc_epfd < 0))
3208         {
3209           errno = -epfd;
3210           rv = -1;
3211           goto done;
3212         }
3213
3214       func_str = "libc_epoll_ctl";
3215
3216       LDBG (1, "LDP<%d>: epfd %d (0x%x): calling %s(): libc_epfd %d (0x%x), "
3217             "op %d, fd %d (0x%x), event %p", getpid (), epfd, epfd, func_str,
3218             libc_epfd, libc_epfd, op, fd, fd, event);
3219
3220       rv = libc_epoll_ctl (libc_epfd, op, fd, event);
3221     }
3222
3223 done:
3224   if (LDP_DEBUG > 1)
3225     {
3226       if (rv < 0)
3227         {
3228           int errno_val = errno;
3229           perror (func_str);
3230           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
3231                         "rv %d, errno = %d", getpid (), fd, fd,
3232                         func_str, rv, errno_val);
3233           errno = errno_val;
3234         }
3235       else
3236         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
3237                       getpid (), fd, fd, rv, rv);
3238     }
3239   return rv;
3240 }
3241
3242 static inline int
3243 ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
3244                  int timeout, const sigset_t * sigmask)
3245 {
3246   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
3247   double time_to_wait = (double) 0, time_out, now = 0;
3248   u32 vep_idx = ldp_sid_from_fd (epfd);
3249   int libc_epfd, rv = 0;
3250   const char *func_str;
3251
3252   if ((errno = -ldp_init ()))
3253     return -1;
3254
3255   if (PREDICT_FALSE (!events || (timeout < -1)))
3256     {
3257       errno = EFAULT;
3258       return -1;
3259     }
3260
3261   if (epfd == ldpw->vcl_mq_epfd)
3262     return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
3263
3264   if (PREDICT_FALSE (vep_idx == INVALID_SESSION_ID))
3265     {
3266       clib_warning ("LDP<%d>: ERROR: epfd %d (0x%x): bad vep_idx %d (0x%x)!",
3267                     getpid (), epfd, epfd, vep_idx, vep_idx);
3268       errno = EBADFD;
3269       return -1;
3270     }
3271
3272   time_to_wait = ((timeout >= 0) ? (double) timeout : 0);
3273   time_out = clib_time_now (&ldpw->clib_time) + time_to_wait;
3274
3275   func_str = "vppcom_session_attr[GET_LIBC_EPFD]";
3276   libc_epfd = vppcom_session_attr (vep_idx, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
3277   if (PREDICT_FALSE (libc_epfd < 0))
3278     {
3279       errno = -libc_epfd;
3280       rv = -1;
3281       goto done;
3282     }
3283
3284   LDBG (2, "LDP<%d>: epfd %d (0x%x): vep_idx %d (0x%x), libc_epfd %d (0x%x), "
3285         "events %p, maxevents %d, timeout %d, sigmask %p: time_to_wait %.02f",
3286         getpid (), epfd, epfd, vep_idx, vep_idx, libc_epfd, libc_epfd, events,
3287         maxevents, timeout, sigmask, time_to_wait, time_out);
3288   do
3289     {
3290       if (!ldpw->epoll_wait_vcl)
3291         {
3292           func_str = "vppcom_epoll_wait";
3293
3294           LDBG (3, "LDP<%d>: epfd %d (0x%x): calling %s(): vep_idx %d (0x%x),"
3295                 " events %p, maxevents %d", getpid (), epfd, epfd, func_str,
3296                 vep_idx, vep_idx, events, maxevents);
3297
3298           rv = vppcom_epoll_wait (vep_idx, events, maxevents, 0);
3299           if (rv > 0)
3300             {
3301               ldpw->epoll_wait_vcl = 1;
3302               goto done;
3303             }
3304           else if (rv < 0)
3305             {
3306               errno = -rv;
3307               rv = -1;
3308               goto done;
3309             }
3310         }
3311       else
3312         ldpw->epoll_wait_vcl = 0;
3313
3314       if (libc_epfd > 0)
3315         {
3316           func_str = "libc_epoll_pwait";
3317
3318           LDBG (3, "LDP<%d>: epfd %d (0x%x): calling %s(): libc_epfd %d "
3319                 "(0x%x), events %p, maxevents %d, sigmask %p", getpid (),
3320                 epfd, epfd, func_str, libc_epfd, libc_epfd, events,
3321                 maxevents, sigmask);
3322
3323           rv = libc_epoll_pwait (libc_epfd, events, maxevents, 1, sigmask);
3324           if (rv != 0)
3325             goto done;
3326         }
3327
3328       if (timeout != -1)
3329         now = clib_time_now (&ldpw->clib_time);
3330     }
3331   while (now < time_out);
3332
3333 done:
3334   if (LDP_DEBUG > 3)
3335     {
3336       if (libc_epfd > 0)
3337         epfd = libc_epfd;
3338       if (rv < 0)
3339         {
3340           int errno_val = errno;
3341           perror (func_str);
3342           clib_warning ("LDP<%d>: ERROR: epfd %d (0x%x): %s() failed! "
3343                         "rv %d, errno = %d", getpid (), epfd, epfd,
3344                         func_str, rv, errno_val);
3345           errno = errno_val;
3346         }
3347       else
3348         clib_warning ("LDP<%d>: epfd %d (0x%x): returning %d (0x%x)",
3349                       getpid (), epfd, epfd, rv, rv);
3350     }
3351   return rv;
3352 }
3353
3354 int
3355 epoll_pwait (int epfd, struct epoll_event *events,
3356              int maxevents, int timeout, const sigset_t * sigmask)
3357 {
3358   return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
3359 }
3360
3361 int
3362 epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
3363 {
3364   return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL);
3365 }
3366
3367 int
3368 poll (struct pollfd *fds, nfds_t nfds, int timeout)
3369 {
3370   ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
3371   const char *func_str = __func__;
3372   int rv, i, n_revents = 0;
3373   u32 sid;
3374   vcl_poll_t *vp;
3375   double wait_for_time;
3376
3377   LDBG (3, "LDP<%d>: fds %p, nfds %d, timeout %d", getpid (), fds, nfds,
3378         timeout);
3379
3380   if (timeout >= 0)
3381     wait_for_time = (f64) timeout / 1000;
3382   else
3383     wait_for_time = -1;
3384
3385   for (i = 0; i < nfds; i++)
3386     {
3387       if (fds[i].fd < 0)
3388         continue;
3389
3390       LDBG (3, "LDP<%d>: fds[%d] fd %d (0x%0x) events = 0x%x revents = 0x%x",
3391             getpid (), i, fds[i].fd, fds[i].fd, fds[i].events,
3392             fds[i].revents);
3393
3394       sid = ldp_sid_from_fd (fds[i].fd);
3395       if (sid != INVALID_SESSION_ID)
3396         {
3397           fds[i].fd = -fds[i].fd;
3398           vec_add2 (ldpw->vcl_poll, vp, 1);
3399           vp->fds_ndx = i;
3400           vp->sid = sid;
3401           vp->events = fds[i].events;
3402 #ifdef __USE_XOPEN2K
3403           if (fds[i].events & POLLRDNORM)
3404             vp->events |= POLLIN;
3405           if (fds[i].events & POLLWRNORM)
3406             vp->events |= POLLOUT;
3407 #endif
3408           vp->revents = fds[i].revents;
3409         }
3410       else
3411         {
3412           vec_add1 (ldpw->libc_poll, fds[i]);
3413           vec_add1 (ldpw->libc_poll_idxs, i);
3414         }
3415     }
3416
3417   do
3418     {
3419       if (vec_len (ldpw->vcl_poll))
3420         {
3421           func_str = "vppcom_poll";
3422
3423           LDBG (3, "LDP<%d>: calling %s(): vcl_poll %p, n_sids %u (0x%x): "
3424                 "n_libc_fds %u", getpid (), func_str, ldpw->vcl_poll,
3425                 vec_len (ldpw->vcl_poll), vec_len (ldpw->vcl_poll),
3426                 vec_len (ldpw->libc_poll));
3427
3428           rv = vppcom_poll (ldpw->vcl_poll, vec_len (ldpw->vcl_poll), 0);
3429           if (rv < 0)
3430             {
3431               errno = -rv;
3432               rv = -1;
3433               goto done;
3434             }
3435           else
3436             n_revents += rv;
3437         }
3438
3439       if (vec_len (ldpw->libc_poll))
3440         {
3441           func_str = "libc_poll";
3442
3443           LDBG (3, "LDP<%d>: calling %s(): fds %p, nfds %u: n_sids %u",
3444                 getpid (), fds, nfds, vec_len (ldpw->vcl_poll));
3445
3446           rv = libc_poll (ldpw->libc_poll, vec_len (ldpw->libc_poll), 0);
3447           if (rv < 0)
3448             goto done;
3449           else
3450             n_revents += rv;
3451         }
3452
3453       if (n_revents)
3454         {
3455           rv = n_revents;
3456           goto done;
3457         }
3458     }
3459   while ((wait_for_time == -1) ||
3460          (clib_time_now (&ldpw->clib_time) < wait_for_time));
3461   rv = 0;
3462
3463 done:
3464   vec_foreach (vp, ldpw->vcl_poll)
3465   {
3466     fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
3467     fds[vp->fds_ndx].revents = vp->revents;
3468 #ifdef __USE_XOPEN2K
3469     if ((fds[vp->fds_ndx].revents & POLLIN) &&
3470         (fds[vp->fds_ndx].events & POLLRDNORM))
3471       fds[vp->fds_ndx].revents |= POLLRDNORM;
3472     if ((fds[vp->fds_ndx].revents & POLLOUT) &&
3473         (fds[vp->fds_ndx].events & POLLWRNORM))
3474       fds[vp->fds_ndx].revents |= POLLWRNORM;
3475 #endif
3476   }
3477   vec_reset_length (ldpw->vcl_poll);
3478
3479   for (i = 0; i < vec_len (ldpw->libc_poll); i++)
3480     {
3481       fds[ldpw->libc_poll_idxs[i]].revents = ldpw->libc_poll[i].revents;
3482     }
3483   vec_reset_length (ldpw->libc_poll_idxs);
3484   vec_reset_length (ldpw->libc_poll);
3485
3486   if (LDP_DEBUG > 3)
3487     {
3488       if (rv < 0)
3489         {
3490           int errno_val = errno;
3491           perror (func_str);
3492           clib_warning ("LDP<%d>: ERROR: %s() failed! "
3493                         "rv %d, errno = %d", getpid (),
3494                         func_str, rv, errno_val);
3495           errno = errno_val;
3496         }
3497       else
3498         {
3499           clib_warning ("LDP<%d>: returning %d (0x%x): n_sids %u, "
3500                         "n_libc_fds %d", getpid (), rv, rv,
3501                         vec_len (ldpw->vcl_poll), vec_len (ldpw->libc_poll));
3502
3503           for (i = 0; i < nfds; i++)
3504             {
3505               if (fds[i].fd >= 0)
3506                 {
3507                   if (LDP_DEBUG > 3)
3508                     clib_warning ("LDP<%d>: fds[%d].fd %d (0x%0x), "
3509                                   ".events = 0x%x, .revents = 0x%x",
3510                                   getpid (), i, fds[i].fd, fds[i].fd,
3511                                   fds[i].events, fds[i].revents);
3512                 }
3513             }
3514         }
3515     }
3516
3517   return rv;
3518 }
3519
3520 #ifdef USE_GNU
3521 int
3522 ppoll (struct pollfd *fds, nfds_t nfds,
3523        const struct timespec *timeout, const sigset_t * sigmask)
3524 {
3525   if ((errno = -ldp_init ()))
3526     return -1;
3527
3528   clib_warning ("LDP<%d>: LDP-TBD", getpid ());
3529   errno = ENOSYS;
3530
3531
3532   return -1;
3533 }
3534 #endif
3535
3536 void CONSTRUCTOR_ATTRIBUTE ldp_constructor (void);
3537
3538 void DESTRUCTOR_ATTRIBUTE ldp_destructor (void);
3539
3540 /*
3541  * This function is called when the library is loaded
3542  */
3543 void
3544 ldp_constructor (void)
3545 {
3546   swrap_constructor ();
3547   if (ldp_init () != 0)
3548     fprintf (stderr, "\nLDP<%d>: ERROR: ldp_constructor: failed!\n",
3549              getpid ());
3550   else if (LDP_DEBUG > 0)
3551     clib_warning ("LDP<%d>: LDP constructor: done!\n", getpid ());
3552 }
3553
3554 /*
3555  * This function is called when the library is unloaded
3556  */
3557 void
3558 ldp_destructor (void)
3559 {
3560   swrap_destructor ();
3561   if (ldp->init)
3562     ldp->init = 0;
3563
3564   /* Don't use clib_warning() here because that calls writev()
3565    * which will call ldp_init().
3566    */
3567   if (LDP_DEBUG > 0)
3568     printf ("%s:%d: LDP<%d>: LDP destructor: done!\n",
3569             __func__, __LINE__, getpid ());
3570 }
3571
3572
3573 /*
3574  * fd.io coding-style-patch-verification: ON
3575  *
3576  * Local Variables:
3577  * eval: (c-set-style "gnu")
3578  * End:
3579  */