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