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