vcl/ldp: fix poll
[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 (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 (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 (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 (ldp->rd_bitmap, ldp->sid_rd_bitmap,
968                              vec_len (ldp->rd_bitmap) *
969                              sizeof (clib_bitmap_t));
970               if (writefds)
971                 clib_memcpy (ldp->wr_bitmap, ldp->sid_wr_bitmap,
972                              vec_len (ldp->wr_bitmap) *
973                              sizeof (clib_bitmap_t));
974               if (exceptfds)
975                 clib_memcpy (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 (readfds, ldp->libc_rd_bitmap,
1053                          vec_len (ldp->rd_bitmap) * sizeof (clib_bitmap_t));
1054           if (writefds)
1055             clib_memcpy (writefds, ldp->libc_wr_bitmap,
1056                          vec_len (ldp->wr_bitmap) * sizeof (clib_bitmap_t));
1057           if (exceptfds)
1058             clib_memcpy (exceptfds, ldp->libc_ex_bitmap,
1059                          vec_len (ldp->ex_bitmap) * sizeof (clib_bitmap_t));
1060           tspec.tv_sec = tspec.tv_nsec = 0;
1061           rv = libc_pselect (libc_bits,
1062                              readfds ? readfds : NULL,
1063                              writefds ? writefds : NULL,
1064                              exceptfds ? exceptfds : NULL, &tspec, sigmask);
1065           if (rv != 0)
1066             goto done;
1067         }
1068     }
1069   while ((time_out == -1) || (clib_time_now (&ldp->clib_time) < time_out));
1070   rv = 0;
1071
1072 done:
1073   /* TBD: set timeout to amount of time left */
1074   vec_reset_length (ldp->rd_bitmap);
1075   vec_reset_length (ldp->sid_rd_bitmap);
1076   vec_reset_length (ldp->libc_rd_bitmap);
1077   vec_reset_length (ldp->wr_bitmap);
1078   vec_reset_length (ldp->sid_wr_bitmap);
1079   vec_reset_length (ldp->libc_wr_bitmap);
1080   vec_reset_length (ldp->ex_bitmap);
1081   vec_reset_length (ldp->sid_ex_bitmap);
1082   vec_reset_length (ldp->libc_ex_bitmap);
1083
1084   if (LDP_DEBUG > 3)
1085     {
1086       if (rv < 0)
1087         {
1088           int errno_val = errno;
1089           perror (func_str);
1090           clib_warning ("LDP<%d>: ERROR: %s() failed! "
1091                         "rv %d, errno = %d", getpid (),
1092                         func_str, rv, errno_val);
1093           errno = errno_val;
1094         }
1095       else
1096         clib_warning ("LDP<%d>: returning %d (0x%x)", getpid (), rv, rv);
1097     }
1098   return rv;
1099 }
1100
1101 int
1102 select (int nfds, fd_set * __restrict readfds,
1103         fd_set * __restrict writefds,
1104         fd_set * __restrict exceptfds, struct timeval *__restrict timeout)
1105 {
1106   struct timespec tspec;
1107
1108   if (timeout)
1109     {
1110       tspec.tv_sec = timeout->tv_sec;
1111       tspec.tv_nsec = timeout->tv_usec * 1000;
1112     }
1113   return ldp_pselect (nfds, readfds, writefds, exceptfds,
1114                       timeout ? &tspec : NULL, NULL);
1115 }
1116
1117 #ifdef __USE_XOPEN2K
1118 int
1119 pselect (int nfds, fd_set * __restrict readfds,
1120          fd_set * __restrict writefds,
1121          fd_set * __restrict exceptfds,
1122          const struct timespec *__restrict timeout,
1123          const __sigset_t * __restrict sigmask)
1124 {
1125   return ldp_pselect (nfds, readfds, writefds, exceptfds, timeout, 0);
1126 }
1127 #endif
1128
1129 int
1130 socket (int domain, int type, int protocol)
1131 {
1132   const char *func_str;
1133   int rv;
1134   u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0;
1135   int sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
1136
1137   if ((errno = -ldp_init ()))
1138     return -1;
1139
1140   if (((domain == AF_INET) || (domain == AF_INET6)) &&
1141       ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
1142     {
1143       int sid;
1144       u8 proto = ((sock_type == SOCK_DGRAM) ?
1145                   VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP);
1146
1147       func_str = "vppcom_session_create";
1148
1149       LDBG (0, "LDP<%d>: : calling %s(): proto %u (%s), is_nonblocking %u",
1150             getpid (), func_str, proto, vppcom_proto_str (proto),
1151             is_nonblocking);
1152
1153       sid = vppcom_session_create (proto, is_nonblocking);
1154       if (sid < 0)
1155         {
1156           errno = -sid;
1157           rv = -1;
1158         }
1159       else
1160         {
1161           func_str = "ldp_fd_from_sid";
1162           rv = ldp_fd_from_sid (sid);
1163           if (rv < 0)
1164             {
1165               (void) vppcom_session_close (sid);
1166               errno = -rv;
1167               rv = -1;
1168             }
1169         }
1170     }
1171   else
1172     {
1173       func_str = "libc_socket";
1174
1175       LDBG (0, "LDP<%d>: : calling %s()", getpid (), func_str);
1176
1177       rv = libc_socket (domain, type, protocol);
1178     }
1179
1180   if (LDP_DEBUG > 0)
1181     {
1182       if (rv < 0)
1183         {
1184           int errno_val = errno;
1185           perror (func_str);
1186           clib_warning ("LDP<%d>: ERROR: %s() failed! "
1187                         "rv %d, errno = %d",
1188                         getpid (), func_str, rv, errno_val);
1189           errno = errno_val;
1190         }
1191       else
1192         clib_warning ("LDP<%d>: : returning fd %d (0x%x)", getpid (), rv, rv);
1193     }
1194   return rv;
1195 }
1196
1197 /*
1198  * Create two new sockets, of type TYPE in domain DOMAIN and using
1199  * protocol PROTOCOL, which are connected to each other, and put file
1200  * descriptors for them in FDS[0] and FDS[1].  If PROTOCOL is zero,
1201  * one will be chosen automatically.
1202  * Returns 0 on success, -1 for errors.
1203  * */
1204 int
1205 socketpair (int domain, int type, int protocol, int fds[2])
1206 {
1207   const char *func_str;
1208   int rv;
1209   int sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
1210
1211   if ((errno = -ldp_init ()))
1212     return -1;
1213
1214   if (((domain == AF_INET) || (domain == AF_INET6)) &&
1215       ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
1216     {
1217       func_str = __func__;
1218
1219       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1220       errno = ENOSYS;
1221       rv = -1;
1222     }
1223   else
1224     {
1225       func_str = "libc_socket";
1226
1227       if (LDP_DEBUG > 1)
1228         clib_warning ("LDP<%d>: : calling %s()", getpid (), func_str);
1229
1230       rv = libc_socket (domain, type, protocol);
1231     }
1232
1233   if (LDP_DEBUG > 1)
1234     {
1235       if (rv < 0)
1236         {
1237           int errno_val = errno;
1238           perror (func_str);
1239           clib_warning ("LDP<%d>: ERROR: %s() failed! "
1240                         "rv %d, errno = %d",
1241                         getpid (), func_str, rv, errno_val);
1242           errno = errno_val;
1243         }
1244       else
1245         clib_warning ("LDP<%d>: : returning fd %d (0x%x)", getpid (), rv, rv);
1246     }
1247   return rv;
1248 }
1249
1250 int
1251 bind (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
1252 {
1253   int rv;
1254   const char *func_str;
1255   u32 sid = ldp_sid_from_fd (fd);
1256
1257   if ((errno = -ldp_init ()))
1258     return -1;
1259
1260   if (sid != INVALID_SESSION_ID)
1261     {
1262       vppcom_endpt_t ep;
1263
1264       func_str = "vppcom_session_bind";
1265
1266       switch (addr->sa_family)
1267         {
1268         case AF_INET:
1269           if (len != sizeof (struct sockaddr_in))
1270             {
1271               clib_warning
1272                 ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): Invalid "
1273                  "AF_INET addr len %u!", getpid (), fd, fd, sid, sid, len);
1274               errno = EINVAL;
1275               rv = -1;
1276               goto done;
1277             }
1278           ep.is_ip4 = VPPCOM_IS_IP4;
1279           ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1280           ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1281           break;
1282
1283         case AF_INET6:
1284           if (len != sizeof (struct sockaddr_in6))
1285             {
1286               clib_warning
1287                 ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): Invalid "
1288                  "AF_INET6 addr len %u!", getpid (), fd, fd, sid, sid, len);
1289               errno = EINVAL;
1290               rv = -1;
1291               goto done;
1292             }
1293           ep.is_ip4 = VPPCOM_IS_IP6;
1294           ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1295           ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1296           break;
1297
1298         default:
1299           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): "
1300                         "Unsupported address family %u!",
1301                         getpid (), fd, fd, sid, sid, addr->sa_family);
1302           errno = EAFNOSUPPORT;
1303           rv = -1;
1304           goto done;
1305         }
1306       if (LDP_DEBUG > 0)
1307         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1308                       "addr %p, len %u",
1309                       getpid (), fd, fd, func_str, sid, sid, addr, len);
1310
1311       rv = vppcom_session_bind (sid, &ep);
1312       if (rv != VPPCOM_OK)
1313         {
1314           errno = -rv;
1315           rv = -1;
1316         }
1317     }
1318   else
1319     {
1320       func_str = "libc_bind";
1321
1322       if (LDP_DEBUG > 0)
1323         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1324                       "addr %p, len %u",
1325                       getpid (), fd, fd, func_str, addr, len);
1326
1327       rv = libc_bind (fd, addr, len);
1328     }
1329
1330 done:
1331   if (LDP_DEBUG > 0)
1332     {
1333       if (rv < 0)
1334         {
1335           int errno_val = errno;
1336           perror (func_str);
1337           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1338                         "rv %d, errno = %d", getpid (), fd, fd,
1339                         func_str, rv, errno_val);
1340           errno = errno_val;
1341         }
1342       else
1343         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1344                       getpid (), fd, fd, rv, rv);
1345     }
1346   return rv;
1347 }
1348
1349 static inline int
1350 ldp_copy_ep_to_sockaddr (__SOCKADDR_ARG addr, socklen_t * __restrict len,
1351                          vppcom_endpt_t * ep)
1352 {
1353   int rv = 0;
1354   int sa_len, copy_len;
1355
1356   if ((errno = -ldp_init ()))
1357     return -1;
1358
1359   if (addr && len && ep)
1360     {
1361       addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
1362       switch (addr->sa_family)
1363         {
1364         case AF_INET:
1365           ((struct sockaddr_in *) addr)->sin_port = ep->port;
1366           if (*len > sizeof (struct sockaddr_in))
1367             *len = sizeof (struct sockaddr_in);
1368           sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
1369           copy_len = *len - sa_len;
1370           if (copy_len > 0)
1371             memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
1372                     copy_len);
1373           break;
1374
1375         case AF_INET6:
1376           ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
1377           if (*len > sizeof (struct sockaddr_in6))
1378             *len = sizeof (struct sockaddr_in6);
1379           sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
1380           copy_len = *len - sa_len;
1381           if (copy_len > 0)
1382             memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
1383                     __in6_u.__u6_addr8, ep->ip, copy_len);
1384           break;
1385
1386         default:
1387           /* Not possible */
1388           rv = -EAFNOSUPPORT;
1389           break;
1390         }
1391     }
1392   return rv;
1393 }
1394
1395 int
1396 getsockname (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
1397 {
1398   int rv;
1399   const char *func_str;
1400   u32 sid = ldp_sid_from_fd (fd);
1401
1402   if ((errno = -ldp_init ()))
1403     return -1;
1404
1405   if (sid != INVALID_SESSION_ID)
1406     {
1407       vppcom_endpt_t ep;
1408       u8 addr_buf[sizeof (struct in6_addr)];
1409       u32 size = sizeof (ep);
1410
1411       ep.ip = addr_buf;
1412       func_str = "vppcom_session_attr[GET_LCL_ADDR]";
1413
1414       if (LDP_DEBUG > 2)
1415         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1416                       "addr %p, len %u",
1417                       getpid (), fd, fd, func_str, sid, sid, addr, len);
1418
1419       rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
1420       if (rv != VPPCOM_OK)
1421         {
1422           errno = -rv;
1423           rv = -1;
1424         }
1425       else
1426         {
1427           rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
1428           if (rv != VPPCOM_OK)
1429             {
1430               errno = -rv;
1431               rv = -1;
1432             }
1433         }
1434     }
1435   else
1436     {
1437       func_str = "libc_getsockname";
1438
1439       if (LDP_DEBUG > 2)
1440         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1441                       "addr %p, len %u",
1442                       getpid (), fd, fd, func_str, addr, len);
1443
1444       rv = libc_getsockname (fd, addr, len);
1445     }
1446
1447   if (LDP_DEBUG > 2)
1448     {
1449       if (rv < 0)
1450         {
1451           int errno_val = errno;
1452           perror (func_str);
1453           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1454                         "rv %d, errno = %d", getpid (), fd, fd,
1455                         func_str, rv, errno_val);
1456           errno = errno_val;
1457         }
1458       else
1459         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1460                       getpid (), fd, fd, rv, rv);
1461     }
1462   return rv;
1463 }
1464
1465 int
1466 connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
1467 {
1468   int rv;
1469   const char *func_str = __func__;
1470   u32 sid = ldp_sid_from_fd (fd);
1471
1472   if ((errno = -ldp_init ()))
1473     return -1;
1474
1475   if (!addr)
1476     {
1477       clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): NULL addr, len %u",
1478                     getpid (), fd, fd, len);
1479       errno = EINVAL;
1480       rv = -1;
1481       goto done;
1482     }
1483
1484   if (sid != INVALID_SESSION_ID)
1485     {
1486       vppcom_endpt_t ep;
1487
1488       func_str = "vppcom_session_connect";
1489
1490       switch (addr->sa_family)
1491         {
1492         case AF_INET:
1493           if (len != sizeof (struct sockaddr_in))
1494             {
1495               clib_warning
1496                 ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): Invalid "
1497                  "AF_INET addr len %u!", getpid (), fd, fd, sid, sid, len);
1498               errno = EINVAL;
1499               rv = -1;
1500               goto done;
1501             }
1502           ep.is_ip4 = VPPCOM_IS_IP4;
1503           ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1504           ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1505           break;
1506
1507         case AF_INET6:
1508           if (len != sizeof (struct sockaddr_in6))
1509             {
1510               clib_warning
1511                 ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): Invalid "
1512                  "AF_INET6 addr len %u!", getpid (), fd, fd, sid, sid, len);
1513               errno = EINVAL;
1514               rv = -1;
1515               goto done;
1516             }
1517           ep.is_ip4 = VPPCOM_IS_IP6;
1518           ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1519           ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1520           break;
1521
1522         default:
1523           clib_warning ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): "
1524                         "Unsupported address family %u!",
1525                         getpid (), fd, fd, sid, sid, addr->sa_family);
1526           errno = EAFNOSUPPORT;
1527           rv = -1;
1528           goto done;
1529         }
1530       if (LDP_DEBUG > 0)
1531         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x) "
1532                       "addr %p len %u",
1533                       getpid (), fd, fd, func_str, sid, sid, addr, len);
1534
1535       rv = vppcom_session_connect (sid, &ep);
1536       if (rv != VPPCOM_OK)
1537         {
1538           errno = -rv;
1539           rv = -1;
1540         }
1541     }
1542   else
1543     {
1544       func_str = "libc_connect";
1545
1546       if (LDP_DEBUG > 0)
1547         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1548                       "addr %p, len %u",
1549                       getpid (), fd, fd, func_str, addr, len);
1550
1551       rv = libc_connect (fd, addr, len);
1552     }
1553
1554 done:
1555   if (LDP_DEBUG > 0)
1556     {
1557       if (rv < 0)
1558         {
1559           int errno_val = errno;
1560           perror (func_str);
1561           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1562                         "rv %d, errno = %d", getpid (), fd, fd,
1563                         func_str, rv, errno_val);
1564           errno = errno_val;
1565         }
1566       else
1567         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1568                       getpid (), fd, fd, rv, rv);
1569     }
1570   return rv;
1571 }
1572
1573 int
1574 getpeername (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
1575 {
1576   int rv;
1577   const char *func_str;
1578   u32 sid = ldp_sid_from_fd (fd);
1579
1580   if ((errno = -ldp_init ()))
1581     return -1;
1582
1583   if (sid != INVALID_SESSION_ID)
1584     {
1585       vppcom_endpt_t ep;
1586       u8 addr_buf[sizeof (struct in6_addr)];
1587       u32 size = sizeof (ep);
1588
1589       ep.ip = addr_buf;
1590       func_str = "vppcom_session_attr[GET_PEER_ADDR]";
1591
1592       if (LDP_DEBUG > 2)
1593         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1594                       "addr %p, len %u",
1595                       getpid (), fd, fd, func_str, sid, sid, addr, len);
1596
1597       rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size);
1598       if (rv != VPPCOM_OK)
1599         {
1600           errno = -rv;
1601           rv = -1;
1602         }
1603       else
1604         {
1605           rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
1606           if (rv != VPPCOM_OK)
1607             {
1608               errno = -rv;
1609               rv = -1;
1610             }
1611         }
1612     }
1613   else
1614     {
1615       func_str = "libc_getpeername";
1616
1617       if (LDP_DEBUG > 2)
1618         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1619                       "addr %p, len %u",
1620                       getpid (), fd, fd, func_str, addr, len);
1621
1622       rv = libc_getpeername (fd, addr, len);
1623     }
1624
1625   if (LDP_DEBUG > 2)
1626     {
1627       if (rv < 0)
1628         {
1629           int errno_val = errno;
1630           perror (func_str);
1631           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1632                         "rv %d, errno = %d", getpid (), fd, fd,
1633                         func_str, rv, errno_val);
1634           errno = errno_val;
1635         }
1636       else
1637         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1638                       getpid (), fd, fd, rv, rv);
1639     }
1640   return rv;
1641 }
1642
1643 ssize_t
1644 send (int fd, const void *buf, size_t n, int flags)
1645 {
1646   ssize_t size;
1647   const char *func_str;
1648   u32 sid = ldp_sid_from_fd (fd);
1649
1650   if ((errno = -ldp_init ()))
1651     return -1;
1652
1653   if (sid != INVALID_SESSION_ID)
1654     {
1655
1656       func_str = "vppcom_session_sendto";
1657
1658       if (LDP_DEBUG > 2)
1659         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1660                       "buf %p, n %u, flags 0x%x",
1661                       getpid (), fd, fd, func_str, sid, sid, buf, n, flags);
1662
1663       size = vppcom_session_sendto (sid, (void *) buf, n, flags, NULL);
1664       if (size < VPPCOM_OK)
1665         {
1666           errno = -size;
1667           size = -1;
1668         }
1669     }
1670   else
1671     {
1672       func_str = "libc_send";
1673
1674       if (LDP_DEBUG > 2)
1675         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1676                       "buf %p, n %u, flags 0x%x",
1677                       getpid (), fd, fd, func_str, buf, n, flags);
1678
1679       size = libc_send (fd, buf, n, flags);
1680     }
1681
1682   if (LDP_DEBUG > 2)
1683     {
1684       if (size < 0)
1685         {
1686           int errno_val = errno;
1687           perror (func_str);
1688           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1689                         "rv %d, errno = %d", getpid (), fd, fd,
1690                         func_str, size, errno_val);
1691           errno = errno_val;
1692         }
1693       else
1694         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1695                       getpid (), fd, fd, size, size);
1696     }
1697   return size;
1698 }
1699
1700 ssize_t
1701 sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
1702 {
1703   ssize_t size = 0;
1704   const char *func_str;
1705   u32 sid = ldp_sid_from_fd (out_fd);
1706
1707   if ((errno = -ldp_init ()))
1708     return -1;
1709
1710   if (sid != INVALID_SESSION_ID)
1711     {
1712       int rv;
1713       ssize_t results = 0;
1714       size_t n_bytes_left = len;
1715       size_t bytes_to_read;
1716       int nbytes;
1717       int errno_val;
1718       u8 eagain = 0;
1719       u32 flags, flags_len = sizeof (flags);
1720
1721       func_str = "vppcom_session_attr[GET_FLAGS]";
1722       rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_FLAGS, &flags,
1723                                 &flags_len);
1724       if (PREDICT_FALSE (rv != VPPCOM_OK))
1725         {
1726           clib_warning ("LDP<%d>: ERROR: out fd %d (0x%x): %s(): "
1727                         "sid %u (0x%x), returned %d (%s)!", getpid (),
1728                         out_fd, out_fd, func_str, sid, sid, rv,
1729                         vppcom_retval_str (rv));
1730
1731           vec_reset_length (ldp->io_buffer);
1732           errno = -rv;
1733           size = -1;
1734           goto done;
1735         }
1736
1737       if (offset)
1738         {
1739           off_t off = lseek (in_fd, *offset, SEEK_SET);
1740           if (PREDICT_FALSE (off == -1))
1741             {
1742               func_str = "lseek";
1743               errno_val = errno;
1744               clib_warning ("LDP<%d>: ERROR: out fd %d (0x%x): %s(): "
1745                             "SEEK_SET failed: in_fd %d, offset %p, "
1746                             "*offset %ld, rv %ld, errno %d", getpid (),
1747                             out_fd, out_fd, in_fd, offset, *offset, off,
1748                             errno_val);
1749               errno = errno_val;
1750               size = -1;
1751               goto done;
1752             }
1753
1754           ASSERT (off == *offset);
1755         }
1756
1757       do
1758         {
1759           func_str = "vppcom_session_attr[GET_NWRITE]";
1760           size = vppcom_session_attr (sid, VPPCOM_ATTR_GET_NWRITE, 0, 0);
1761           if (size < 0)
1762             {
1763               clib_warning
1764                 ("LDP<%d>: ERROR: fd %d (0x%x): %s(): sid %u (0x%x), "
1765                  "returned %d (%s)!", getpid (), out_fd, out_fd, func_str,
1766                  sid, sid, size, vppcom_retval_str (size));
1767               vec_reset_length (ldp->io_buffer);
1768               errno = -size;
1769               size = -1;
1770               goto done;
1771             }
1772
1773           bytes_to_read = size;
1774           if (LDP_DEBUG > 2)
1775             clib_warning
1776               ("LDP<%d>: fd %d (0x%x): called %s(): sid %u (0x%x), "
1777                "results %ld, n_bytes_left %lu, bytes_to_read %lu", getpid (),
1778                out_fd, out_fd, func_str, sid, sid, results, n_bytes_left,
1779                bytes_to_read);
1780
1781           if (bytes_to_read == 0)
1782             {
1783               if (flags & O_NONBLOCK)
1784                 {
1785                   if (!results)
1786                     {
1787                       if (LDP_DEBUG > 2)
1788                         clib_warning ("LDP<%d>: fd %d (0x%x): sid %u (0x%x): "
1789                                       "EAGAIN",
1790                                       getpid (), out_fd, out_fd, sid, sid);
1791                       eagain = 1;
1792                     }
1793                   goto update_offset;
1794                 }
1795               else
1796                 continue;
1797             }
1798           bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
1799           vec_validate (ldp->io_buffer, bytes_to_read);
1800           nbytes = libc_read (in_fd, ldp->io_buffer, bytes_to_read);
1801           if (nbytes < 0)
1802             {
1803               func_str = "libc_read";
1804               errno_val = errno;
1805               clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): in_fd (%d), "
1806                             "io_buffer %p, bytes_to_read %lu, rv %d, "
1807                             "errno %d", getpid (), out_fd, out_fd, func_str,
1808                             in_fd, ldp->io_buffer, bytes_to_read, nbytes,
1809                             errno_val);
1810               errno = errno_val;
1811
1812               if (results == 0)
1813                 {
1814                   vec_reset_length (ldp->io_buffer);
1815                   size = -1;
1816                   goto done;
1817                 }
1818               goto update_offset;
1819             }
1820           func_str = "vppcom_session_write";
1821           if (LDP_DEBUG > 2)
1822             clib_warning
1823               ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1824                "buf %p, nbytes %u: results %d, n_bytes_left %d", getpid (),
1825                out_fd, out_fd, func_str, sid, sid, ldp->io_buffer, nbytes,
1826                results, n_bytes_left);
1827
1828           size = vppcom_session_write (sid, ldp->io_buffer, nbytes);
1829           if (size < 0)
1830             {
1831               if (size == VPPCOM_EAGAIN)
1832                 {
1833                   if (flags & O_NONBLOCK)
1834                     {
1835                       if (!results)
1836                         {
1837                           if (LDP_DEBUG > 2)
1838                             clib_warning
1839                               ("LDP<%d>: fd %d (0x%x): sid %u (0x%x): "
1840                                "EAGAIN", getpid (), out_fd, out_fd, sid, sid);
1841                           eagain = 1;
1842                         }
1843                       goto update_offset;
1844                     }
1845                   else
1846                     continue;
1847                 }
1848               else
1849                 {
1850                   clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s():"
1851                                 "sid %u, io_buffer %p, nbytes %u "
1852                                 "returned %d (%s)",
1853                                 getpid (), out_fd, out_fd, func_str,
1854                                 sid, ldp->io_buffer, nbytes,
1855                                 size, vppcom_retval_str (size));
1856                 }
1857               if (results == 0)
1858                 {
1859                   vec_reset_length (ldp->io_buffer);
1860                   errno = -size;
1861                   size = -1;
1862                   goto done;
1863                 }
1864               goto update_offset;
1865             }
1866
1867           results += nbytes;
1868           ASSERT (n_bytes_left >= nbytes);
1869           n_bytes_left = n_bytes_left - nbytes;
1870         }
1871       while (n_bytes_left > 0);
1872
1873     update_offset:
1874       vec_reset_length (ldp->io_buffer);
1875       if (offset)
1876         {
1877           off_t off = lseek (in_fd, *offset, SEEK_SET);
1878           if (PREDICT_FALSE (off == -1))
1879             {
1880               func_str = "lseek";
1881               errno_val = errno;
1882               clib_warning ("LDP<%d>: ERROR: %s(): SEEK_SET failed: "
1883                             "in_fd %d, offset %p, *offset %ld, "
1884                             "rv %ld, errno %d", getpid (), in_fd,
1885                             offset, *offset, off, errno_val);
1886               errno = errno_val;
1887               size = -1;
1888               goto done;
1889             }
1890
1891           ASSERT (off == *offset);
1892           *offset += results + 1;
1893         }
1894       if (eagain)
1895         {
1896           errno = EAGAIN;
1897           size = -1;
1898         }
1899       else
1900         size = results;
1901     }
1902   else
1903     {
1904       func_str = "libc_send";
1905
1906       if (LDP_DEBUG > 2)
1907         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1908                       "in_fd %d, offset %p, len %u",
1909                       getpid (), out_fd, out_fd, func_str,
1910                       in_fd, offset, len);
1911
1912       size = libc_sendfile (out_fd, in_fd, offset, len);
1913     }
1914
1915 done:
1916   if (LDP_DEBUG > 2)
1917     {
1918       if (size < 0)
1919         {
1920           int errno_val = errno;
1921           perror (func_str);
1922           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1923                         "rv %d, errno = %d", getpid (), out_fd, out_fd,
1924                         func_str, size, errno_val);
1925           errno = errno_val;
1926         }
1927       else
1928         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1929                       getpid (), out_fd, out_fd, size, size);
1930     }
1931   return size;
1932 }
1933
1934 ssize_t
1935 sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len)
1936 {
1937   return sendfile (out_fd, in_fd, offset, len);
1938 }
1939
1940 ssize_t
1941 recv (int fd, void *buf, size_t n, int flags)
1942 {
1943   ssize_t size;
1944   const char *func_str;
1945   u32 sid = ldp_sid_from_fd (fd);
1946
1947   if ((errno = -ldp_init ()))
1948     return -1;
1949
1950   if (sid != INVALID_SESSION_ID)
1951     {
1952       func_str = "vppcom_session_recvfrom";
1953
1954       if (LDP_DEBUG > 2)
1955         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1956                       "sid %u (0x%x), buf %p, n %u, flags 0x%x", getpid (),
1957                       fd, fd, func_str, sid, sid, buf, n, flags);
1958
1959       size = vppcom_session_recvfrom (sid, buf, n, flags, NULL);
1960       if (size < 0)
1961         {
1962           errno = -size;
1963           size = -1;
1964         }
1965     }
1966   else
1967     {
1968       func_str = "libc_recv";
1969
1970       if (LDP_DEBUG > 2)
1971         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1972                       "buf %p, n %u, flags 0x%x", getpid (),
1973                       fd, fd, func_str, buf, n, flags);
1974
1975       size = libc_recv (fd, buf, n, flags);
1976     }
1977
1978   if (LDP_DEBUG > 2)
1979     {
1980       if (size < 0)
1981         {
1982           int errno_val = errno;
1983           perror (func_str);
1984           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1985                         "rv %d, errno = %d", getpid (), fd, fd,
1986                         func_str, size, errno_val);
1987           errno = errno_val;
1988         }
1989       else
1990         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1991                       getpid (), fd, fd, size, size);
1992     }
1993   return size;
1994 }
1995
1996 ssize_t
1997 sendto (int fd, const void *buf, size_t n, int flags,
1998         __CONST_SOCKADDR_ARG addr, socklen_t addr_len)
1999 {
2000   ssize_t size;
2001   const char *func_str = __func__;
2002   u32 sid = ldp_sid_from_fd (fd);
2003
2004   if ((errno = -ldp_init ()))
2005     return -1;
2006
2007   if (sid != INVALID_SESSION_ID)
2008     {
2009       vppcom_endpt_t *ep = 0;
2010       vppcom_endpt_t _ep;
2011
2012       if (addr)
2013         {
2014           ep = &_ep;
2015           switch (addr->sa_family)
2016             {
2017             case AF_INET:
2018               ep->is_ip4 = VPPCOM_IS_IP4;
2019               ep->ip =
2020                 (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr;
2021               ep->port =
2022                 (uint16_t) ((const struct sockaddr_in *) addr)->sin_port;
2023               break;
2024
2025             case AF_INET6:
2026               ep->is_ip4 = VPPCOM_IS_IP6;
2027               ep->ip =
2028                 (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
2029               ep->port =
2030                 (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port;
2031               break;
2032
2033             default:
2034               errno = EAFNOSUPPORT;
2035               size = -1;
2036               goto done;
2037             }
2038         }
2039
2040       func_str = "vppcom_session_sendto";
2041
2042       if (LDP_DEBUG > 2)
2043         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2044                       "sid %u (0x%x), buf %p, n %u, flags 0x%x, ep %p",
2045                       getpid (), fd, fd, func_str, sid, sid, buf, n,
2046                       flags, ep);
2047
2048       size = vppcom_session_sendto (sid, (void *) buf, n, flags, ep);
2049       if (size < 0)
2050         {
2051           errno = -size;
2052           size = -1;
2053         }
2054     }
2055   else
2056     {
2057       func_str = "libc_sendto";
2058
2059       if (LDP_DEBUG > 2)
2060         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2061                       "buf %p, n %u, flags 0x%x, addr %p, addr_len %d",
2062                       getpid (), fd, fd, func_str, buf, n, flags,
2063                       addr, addr_len);
2064
2065       size = libc_sendto (fd, buf, n, flags, addr, addr_len);
2066     }
2067
2068 done:
2069   if (LDP_DEBUG > 2)
2070     {
2071       if (size < 0)
2072         {
2073           int errno_val = errno;
2074           perror (func_str);
2075           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2076                         "rv %d, errno = %d", getpid (), fd, fd,
2077                         func_str, size, errno_val);
2078           errno = errno_val;
2079         }
2080       else
2081         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2082                       getpid (), fd, fd, size, size);
2083     }
2084   return size;
2085 }
2086
2087 ssize_t
2088 recvfrom (int fd, void *__restrict buf, size_t n, int flags,
2089           __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
2090 {
2091   ssize_t size;
2092   const char *func_str;
2093   u32 sid = ldp_sid_from_fd (fd);
2094
2095   if ((errno = -ldp_init ()))
2096     return -1;
2097
2098   if (sid != INVALID_SESSION_ID)
2099     {
2100       vppcom_endpt_t ep;
2101       u8 src_addr[sizeof (struct sockaddr_in6)];
2102
2103       func_str = "vppcom_session_recvfrom";
2104
2105       if (LDP_DEBUG > 2)
2106         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2107                       "sid %u (0x%x), buf %p, n %u, flags 0x%x, ep %p",
2108                       getpid (), fd, fd, func_str, sid, sid, buf, n,
2109                       flags, &ep);
2110       if (addr)
2111         {
2112           ep.ip = src_addr;
2113           size = vppcom_session_recvfrom (sid, buf, n, flags, &ep);
2114
2115           if (size > 0)
2116             size = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
2117         }
2118       else
2119         size = vppcom_session_recvfrom (sid, buf, n, flags, NULL);
2120
2121       if (size < 0)
2122         {
2123           errno = -size;
2124           size = -1;
2125         }
2126     }
2127   else
2128     {
2129       func_str = "libc_recvfrom";
2130
2131       if (LDP_DEBUG > 2)
2132         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2133                       "buf %p, n %u, flags 0x%x, addr %p, addr_len %d",
2134                       getpid (), fd, fd, func_str, buf, n, flags,
2135                       addr, addr_len);
2136
2137       size = libc_recvfrom (fd, buf, n, flags, addr, addr_len);
2138     }
2139
2140   if (LDP_DEBUG > 2)
2141     {
2142       if (size < 0)
2143         {
2144           int errno_val = errno;
2145           perror (func_str);
2146           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2147                         "rv %d, errno = %d", getpid (), fd, fd,
2148                         func_str, size, errno_val);
2149           errno = errno_val;
2150         }
2151       else
2152         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2153                       getpid (), fd, fd, size, size);
2154     }
2155   return size;
2156 }
2157
2158 ssize_t
2159 sendmsg (int fd, const struct msghdr * message, int flags)
2160 {
2161   ssize_t size;
2162   const char *func_str;
2163   u32 sid = ldp_sid_from_fd (fd);
2164
2165   if ((errno = -ldp_init ()))
2166     return -1;
2167
2168   if (sid != INVALID_SESSION_ID)
2169     {
2170       func_str = __func__;
2171
2172       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2173       errno = ENOSYS;
2174       size = -1;
2175     }
2176   else
2177     {
2178       func_str = "libc_sendmsg";
2179
2180       if (LDP_DEBUG > 2)
2181         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2182                       "message %p, flags 0x%x",
2183                       getpid (), fd, fd, func_str, message, flags);
2184
2185       size = libc_sendmsg (fd, message, flags);
2186     }
2187
2188   if (LDP_DEBUG > 2)
2189     {
2190       if (size < 0)
2191         {
2192           int errno_val = errno;
2193           perror (func_str);
2194           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2195                         "rv %d, errno = %d", getpid (), fd, fd,
2196                         func_str, size, errno_val);
2197           errno = errno_val;
2198         }
2199       else
2200         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2201                       getpid (), fd, fd, size, size);
2202     }
2203   return size;
2204 }
2205
2206 #ifdef USE_GNU
2207 int
2208 sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
2209 {
2210   ssize_t size;
2211   const char *func_str;
2212   u32 sid = ldp_sid_from_fd (fd);
2213
2214   if ((errno = -ldp_init ()))
2215     return -1;
2216
2217   if (sid != INVALID_SESSION_ID)
2218     {
2219       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2220       errno = ENOSYS;
2221       size = -1;
2222     }
2223   else
2224     {
2225       func_str = "libc_sendmmsg";
2226
2227       if (LDP_DEBUG > 2)
2228         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2229                       "vmessages %p, vlen %u, flags 0x%x",
2230                       getpid (), fd, fd, func_str, vmessages, vlen, flags);
2231
2232       size = libc_sendmmsg (fd, vmessages, vlen, flags);
2233     }
2234
2235   if (LDP_DEBUG > 2)
2236     {
2237       if (size < 0)
2238         {
2239           int errno_val = errno;
2240           perror (func_str);
2241           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2242                         "rv %d, errno = %d", getpid (), fd, fd,
2243                         func_str, size, errno_val);
2244           errno = errno_val;
2245         }
2246       else
2247         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2248                       getpid (), fd, fd, size, size);
2249     }
2250   return size;
2251 }
2252 #endif
2253
2254 ssize_t
2255 recvmsg (int fd, struct msghdr * message, int flags)
2256 {
2257   ssize_t size;
2258   const char *func_str;
2259   u32 sid = ldp_sid_from_fd (fd);
2260
2261   if ((errno = -ldp_init ()))
2262     return -1;
2263
2264   if (sid != INVALID_SESSION_ID)
2265     {
2266       func_str = __func__;
2267
2268       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2269       errno = ENOSYS;
2270       size = -1;
2271     }
2272   else
2273     {
2274       func_str = "libc_recvmsg";
2275
2276       if (LDP_DEBUG > 2)
2277         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2278                       "message %p, flags 0x%x",
2279                       getpid (), fd, fd, func_str, message, flags);
2280
2281       size = libc_recvmsg (fd, message, flags);
2282     }
2283
2284   if (LDP_DEBUG > 2)
2285     {
2286       if (size < 0)
2287         {
2288           int errno_val = errno;
2289           perror (func_str);
2290           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2291                         "rv %d, errno = %d", getpid (), fd, fd,
2292                         func_str, size, errno_val);
2293           errno = errno_val;
2294         }
2295       else
2296         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2297                       getpid (), fd, fd, size, size);
2298     }
2299   return size;
2300 }
2301
2302 #ifdef USE_GNU
2303 int
2304 recvmmsg (int fd, struct mmsghdr *vmessages,
2305           unsigned int vlen, int flags, struct timespec *tmo)
2306 {
2307   ssize_t size;
2308   const char *func_str;
2309   u32 sid = ldp_sid_from_fd (fd);
2310
2311   if ((errno = -ldp_init ()))
2312     return -1;
2313
2314   if (sid != INVALID_SESSION_ID)
2315     {
2316       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2317       errno = ENOSYS;
2318       size = -1;
2319     }
2320   else
2321     {
2322       func_str = "libc_recvmmsg";
2323
2324       if (LDP_DEBUG > 2)
2325         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2326                       "vmessages %p, vlen %u, flags 0x%x, tmo %p",
2327                       getpid (), fd, fd, func_str, vmessages, vlen,
2328                       flags, tmo);
2329
2330       size = libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
2331     }
2332
2333   if (LDP_DEBUG > 2)
2334     {
2335       if (size < 0)
2336         {
2337           int errno_val = errno;
2338           perror (func_str);
2339           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2340                         "rv %d, errno = %d", getpid (), fd, fd,
2341                         func_str, size, errno_val);
2342           errno = errno_val;
2343         }
2344       else
2345         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2346                       getpid (), fd, fd, size, size);
2347     }
2348   return size;
2349 }
2350 #endif
2351
2352 int
2353 getsockopt (int fd, int level, int optname,
2354             void *__restrict optval, socklen_t * __restrict optlen)
2355 {
2356   int rv;
2357   const char *func_str = __func__;
2358   u32 sid = ldp_sid_from_fd (fd);
2359   u32 buflen = optlen ? (u32) * optlen : 0;
2360
2361   if ((errno = -ldp_init ()))
2362     return -1;
2363
2364   if (sid != INVALID_SESSION_ID)
2365     {
2366       rv = -EOPNOTSUPP;
2367
2368       switch (level)
2369         {
2370         case SOL_TCP:
2371           switch (optname)
2372             {
2373             case TCP_NODELAY:
2374               func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_NODELAY]";
2375               if (LDP_DEBUG > 1)
2376                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2377                               "sid %u (0x%x)",
2378                               getpid (), fd, fd, func_str, sid, sid);
2379               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_NODELAY,
2380                                         optval, optlen);
2381               break;
2382             case TCP_MAXSEG:
2383               func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_USER_MSS]";
2384               if (LDP_DEBUG > 1)
2385                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2386                               "sid %u (0x%x)",
2387                               getpid (), fd, fd, func_str, sid, sid);
2388               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_USER_MSS,
2389                                         optval, optlen);
2390               break;
2391             case TCP_KEEPIDLE:
2392               func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_KEEPIDLE]";
2393               if (LDP_DEBUG > 1)
2394                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2395                               "sid %u (0x%x)",
2396                               getpid (), fd, fd, func_str, sid, sid);
2397               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
2398                                         optval, optlen);
2399               break;
2400             case TCP_KEEPINTVL:
2401               func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_KEEPINTVL]";
2402               if (LDP_DEBUG > 1)
2403                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2404                               "sid %u (0x%x), SOL_TCP",
2405                               getpid (), fd, fd, func_str, sid, sid);
2406               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
2407                                         optval, optlen);
2408               break;
2409             case TCP_INFO:
2410               if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
2411                 {
2412                   if (LDP_DEBUG > 1)
2413                     clib_warning ("LDP<%d>: fd %d (0x%x): sid %u (0x%x), "
2414                                   "SOL_TCP, TCP_INFO, optval %p, "
2415                                   "optlen %d: #LDP-NOP#",
2416                                   getpid (), fd, fd, sid, sid,
2417                                   optval, *optlen);
2418                   memset (optval, 0, *optlen);
2419                   rv = VPPCOM_OK;
2420                 }
2421               else
2422                 rv = -EFAULT;
2423               break;
2424             default:
2425               if (LDP_DEBUG > 1)
2426                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2427                               "sid %u (0x%x), SOL_TCP, "
2428                               "optname %d unsupported!",
2429                               getpid (), fd, fd, func_str, sid, sid, optname);
2430               break;
2431             }
2432           break;
2433         case SOL_IPV6:
2434           switch (optname)
2435             {
2436             case IPV6_V6ONLY:
2437               func_str = "vppcom_session_attr[SOL_IPV6,GET_V6ONLY]";
2438               if (LDP_DEBUG > 1)
2439                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2440                               "sid %u (0x%x)",
2441                               getpid (), fd, fd, func_str, sid, sid);
2442               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_V6ONLY,
2443                                         optval, optlen);
2444               break;
2445             default:
2446               if (LDP_DEBUG > 1)
2447                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2448                               "sid %u (0x%x), SOL_IPV6, "
2449                               "optname %d unsupported!",
2450                               getpid (), fd, fd, func_str, sid, sid, optname);
2451               break;
2452             }
2453           break;
2454         case SOL_SOCKET:
2455           switch (optname)
2456             {
2457             case SO_ACCEPTCONN:
2458               func_str = "vppcom_session_attr[SOL_SOCKET,GET_ACCEPTCONN]";
2459               if (LDP_DEBUG > 1)
2460                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2461                               "sid %u (0x%x)",
2462                               getpid (), fd, fd, func_str, sid, sid);
2463               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LISTEN,
2464                                         optval, optlen);
2465               break;
2466             case SO_KEEPALIVE:
2467               func_str = "vppcom_session_attr[SOL_SOCKET,GET_KEEPALIVE]";
2468               if (LDP_DEBUG > 1)
2469                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2470                               "sid %u (0x%x)",
2471                               getpid (), fd, fd, func_str, sid, sid);
2472               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_KEEPALIVE,
2473                                         optval, optlen);
2474               break;
2475             case SO_PROTOCOL:
2476               func_str = "vppcom_session_attr[SOL_SOCKET,GET_PROTOCOL]";
2477               if (LDP_DEBUG > 1)
2478                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2479                               "sid %u (0x%x)",
2480                               getpid (), fd, fd, func_str, sid, sid);
2481               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PROTOCOL,
2482                                         optval, optlen);
2483               *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
2484               break;
2485             case SO_SNDBUF:
2486               func_str = "vppcom_session_attr[SOL_SOCKET,GET_TX_FIFO_LEN]";
2487               if (LDP_DEBUG > 1)
2488                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2489                               "sid %u (0x%x), optlen %d",
2490                               getpid (), fd, fd, func_str, sid, sid, buflen);
2491               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TX_FIFO_LEN,
2492                                         optval, optlen);
2493               break;
2494             case SO_RCVBUF:
2495               func_str = "vppcom_session_attr[SOL_SOCKET,GET_RX_FIFO_LEN]";
2496               if (LDP_DEBUG > 1)
2497                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2498                               "sid %u (0x%x), optlen %d",
2499                               getpid (), fd, fd, func_str, sid, sid, buflen);
2500               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_RX_FIFO_LEN,
2501                                         optval, optlen);
2502               break;
2503             case SO_REUSEADDR:
2504               func_str = "vppcom_session_attr[SOL_SOCKET,GET_REUSEADDR]";
2505               if (LDP_DEBUG > 1)
2506                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2507                               "sid %u (0x%x)",
2508                               getpid (), fd, fd, func_str, sid, sid);
2509               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_REUSEADDR,
2510                                         optval, optlen);
2511               break;
2512             case SO_BROADCAST:
2513               func_str = "vppcom_session_attr[SOL_SOCKET,GET_BROADCAST]";
2514               if (LDP_DEBUG > 1)
2515                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2516                               "sid %u (0x%x)",
2517                               getpid (), fd, fd, func_str, sid, sid);
2518               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_BROADCAST,
2519                                         optval, optlen);
2520               break;
2521             case SO_ERROR:
2522               func_str = "vppcom_session_attr[SOL_SOCKET,GET_ERROR]";
2523               if (LDP_DEBUG > 1)
2524                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2525                               "sid %u (0x%x)",
2526                               getpid (), fd, fd, func_str, sid, sid);
2527               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_ERROR,
2528                                         optval, optlen);
2529               break;
2530             default:
2531               if (LDP_DEBUG > 1)
2532                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2533                               "sid %u (0x%x), SOL_SOCKET, "
2534                               "optname %d unsupported!",
2535                               getpid (), fd, fd, func_str, sid, sid, optname);
2536               break;
2537             }
2538           break;
2539         default:
2540           break;
2541         }
2542
2543       if (rv != VPPCOM_OK)
2544         {
2545           errno = -rv;
2546           rv = -1;
2547         }
2548     }
2549   else
2550     {
2551       func_str = "libc_getsockopt";
2552
2553       if (LDP_DEBUG > 1)
2554         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): level %d, "
2555                       "optname %d, optval %p, optlen %d",
2556                       getpid (), fd, fd, func_str, level, optname,
2557                       optval, optlen);
2558
2559       rv = libc_getsockopt (fd, level, optname, optval, optlen);
2560     }
2561
2562   if (LDP_DEBUG > 1)
2563     {
2564       if (rv < 0)
2565         {
2566           int errno_val = errno;
2567           perror (func_str);
2568           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2569                         "rv %d, errno = %d", getpid (), fd, fd,
2570                         func_str, rv, errno_val);
2571           errno = errno_val;
2572         }
2573       else
2574         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2575                       getpid (), fd, fd, rv, rv);
2576     }
2577   return rv;
2578 }
2579
2580 int
2581 setsockopt (int fd, int level, int optname,
2582             const void *optval, socklen_t optlen)
2583 {
2584   int rv;
2585   const char *func_str = __func__;
2586   u32 sid = ldp_sid_from_fd (fd);
2587
2588   if ((errno = -ldp_init ()))
2589     return -1;
2590
2591   if (sid != INVALID_SESSION_ID)
2592     {
2593       rv = -EOPNOTSUPP;
2594
2595       switch (level)
2596         {
2597         case SOL_TCP:
2598           switch (optname)
2599             {
2600             case TCP_NODELAY:
2601               func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_NODELAY]";
2602               if (LDP_DEBUG > 1)
2603                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2604                               "sid %u (0x%x)",
2605                               getpid (), fd, fd, func_str, sid, sid);
2606               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_NODELAY,
2607                                         (void *) optval, &optlen);
2608               break;
2609             case TCP_MAXSEG:
2610               func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_USER_MSS]";
2611               if (LDP_DEBUG > 1)
2612                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2613                               "sid %u (0x%x)",
2614                               getpid (), fd, fd, func_str, sid, sid);
2615               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_USER_MSS,
2616                                         (void *) optval, &optlen);
2617               break;
2618             case TCP_KEEPIDLE:
2619               func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_KEEPIDLE]";
2620               if (LDP_DEBUG > 1)
2621                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2622                               "sid %u (0x%x)",
2623                               getpid (), fd, fd, func_str, sid, sid);
2624               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
2625                                         (void *) optval, &optlen);
2626               break;
2627             case TCP_KEEPINTVL:
2628               func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_KEEPINTVL]";
2629               if (LDP_DEBUG > 1)
2630                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2631                               "sid %u (0x%x), SOL_TCP",
2632                               getpid (), fd, fd, func_str, sid, sid);
2633               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
2634                                         (void *) optval, &optlen);
2635               break;
2636             default:
2637               if (LDP_DEBUG > 1)
2638                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2639                               "sid %u (0x%x), SOL_TCP, "
2640                               "optname %d unsupported!",
2641                               getpid (), fd, fd, func_str, sid, sid, optname);
2642               break;
2643             }
2644           break;
2645         case SOL_IPV6:
2646           switch (optname)
2647             {
2648             case IPV6_V6ONLY:
2649               func_str = "vppcom_session_attr[SOL_IPV6,SET_V6ONLY]";
2650               if (LDP_DEBUG > 1)
2651                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2652                               "sid %u (0x%x)",
2653                               getpid (), fd, fd, func_str, sid, sid);
2654               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_V6ONLY,
2655                                         (void *) optval, &optlen);
2656               break;
2657             default:
2658               if (LDP_DEBUG > 1)
2659                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2660                               "sid %u (0x%x), SOL_IPV6, "
2661                               "optname %d unsupported!",
2662                               getpid (), fd, fd, func_str, sid, sid, optname);
2663               break;
2664             }
2665           break;
2666         case SOL_SOCKET:
2667           switch (optname)
2668             {
2669             case SO_KEEPALIVE:
2670               func_str = "vppcom_session_attr[SOL_SOCKET,SET_KEEPALIVE]";
2671               if (LDP_DEBUG > 1)
2672                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2673                               "sid %u (0x%x)",
2674                               getpid (), fd, fd, func_str, sid, sid);
2675               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_KEEPALIVE,
2676                                         (void *) optval, &optlen);
2677               break;
2678             case SO_REUSEADDR:
2679               func_str = "vppcom_session_attr[SOL_SOCKET,SET_REUSEADDR]";
2680               if (LDP_DEBUG > 1)
2681                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2682                               "sid %u (0x%x)",
2683                               getpid (), fd, fd, func_str, sid, sid);
2684               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_REUSEADDR,
2685                                         (void *) optval, &optlen);
2686               break;
2687             case SO_BROADCAST:
2688               func_str = "vppcom_session_attr[SOL_SOCKET,SET_BROADCAST]";
2689               if (LDP_DEBUG > 1)
2690                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2691                               "sid %u (0x%x)",
2692                               getpid (), fd, fd, func_str, sid, sid);
2693               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_BROADCAST,
2694                                         (void *) optval, &optlen);
2695               break;
2696             default:
2697               if (LDP_DEBUG > 1)
2698                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2699                               "sid %u (0x%x), SOL_SOCKET, "
2700                               "optname %d unsupported!",
2701                               getpid (), fd, fd, func_str, sid, sid, optname);
2702               break;
2703             }
2704           break;
2705         default:
2706           break;
2707         }
2708
2709       if (rv != VPPCOM_OK)
2710         {
2711           errno = -rv;
2712           rv = -1;
2713         }
2714     }
2715   else
2716     {
2717       func_str = "libc_setsockopt";
2718
2719       if (LDP_DEBUG > 1)
2720         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): level %d, "
2721                       "optname %d, optval %p, optlen %d",
2722                       getpid (), fd, fd, func_str, level, optname,
2723                       optval, optlen);
2724
2725       rv = libc_setsockopt (fd, level, optname, optval, optlen);
2726     }
2727
2728   if (LDP_DEBUG > 1)
2729     {
2730       if (rv < 0)
2731         {
2732           int errno_val = errno;
2733           perror (func_str);
2734           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2735                         "rv %d, errno = %d", getpid (), fd, fd,
2736                         func_str, rv, errno_val);
2737           errno = errno_val;
2738         }
2739       else
2740         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2741                       getpid (), fd, fd, rv, rv);
2742     }
2743   return rv;
2744 }
2745
2746 int
2747 listen (int fd, int n)
2748 {
2749   int rv;
2750   const char *func_str;
2751   u32 sid = ldp_sid_from_fd (fd);
2752
2753   if ((errno = -ldp_init ()))
2754     return -1;
2755
2756   if (sid != INVALID_SESSION_ID)
2757     {
2758       func_str = "vppcom_session_listen";
2759
2760       LDBG (0, "LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), n %d",
2761             getpid (), fd, fd, func_str, sid, sid, n);
2762
2763       rv = vppcom_session_listen (sid, n);
2764       if (rv != VPPCOM_OK)
2765         {
2766           errno = -rv;
2767           rv = -1;
2768         }
2769     }
2770   else
2771     {
2772       func_str = "libc_listen";
2773
2774       LDBG (0, "LDP<%d>: fd %d (0x%x): calling %s(): n %d", getpid (), fd,
2775             fd, func_str, n);
2776
2777       rv = libc_listen (fd, n);
2778     }
2779
2780   if (LDP_DEBUG > 0)
2781     {
2782       if (rv < 0)
2783         {
2784           int errno_val = errno;
2785           perror (func_str);
2786           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2787                         "rv %d, errno = %d", getpid (), fd, fd,
2788                         func_str, rv, errno_val);
2789           errno = errno_val;
2790         }
2791       else
2792         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2793                       getpid (), fd, fd, rv, rv);
2794     }
2795   return rv;
2796 }
2797
2798 static inline int
2799 ldp_accept4 (int listen_fd, __SOCKADDR_ARG addr,
2800              socklen_t * __restrict addr_len, int flags)
2801 {
2802   int rv;
2803   const char *func_str;
2804   u32 listen_sid = ldp_sid_from_fd (listen_fd);
2805   int accept_sid;
2806
2807   if ((errno = -ldp_init ()))
2808     return -1;
2809
2810   if (listen_sid != INVALID_SESSION_ID)
2811     {
2812       vppcom_endpt_t ep;
2813       u8 src_addr[sizeof (struct sockaddr_in6)];
2814       memset (&ep, 0, sizeof (ep));
2815       ep.ip = src_addr;
2816
2817       func_str = "vppcom_session_accept";
2818
2819       if (LDP_DEBUG > 0)
2820         clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): "
2821                       "listen sid %u (0x%x), ep %p, flags 0x%x",
2822                       getpid (), listen_fd, listen_fd, func_str,
2823                       listen_sid, listen_sid, ep, flags);
2824
2825       accept_sid = vppcom_session_accept (listen_sid, &ep, flags);
2826       if (accept_sid < 0)
2827         {
2828           errno = -accept_sid;
2829           rv = -1;
2830         }
2831       else
2832         {
2833           rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
2834           if (rv != VPPCOM_OK)
2835             {
2836               (void) vppcom_session_close ((u32) accept_sid);
2837               errno = -rv;
2838               rv = -1;
2839             }
2840           else
2841             {
2842               func_str = "ldp_fd_from_sid";
2843               if (LDP_DEBUG > 0)
2844                 clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): "
2845                               "accept sid %u (0x%x), ep %p, flags 0x%x",
2846                               getpid (), listen_fd, listen_fd,
2847                               func_str, accept_sid, accept_sid, ep, flags);
2848               rv = ldp_fd_from_sid ((u32) accept_sid);
2849               if (rv < 0)
2850                 {
2851                   (void) vppcom_session_close ((u32) accept_sid);
2852                   errno = -rv;
2853                   rv = -1;
2854                 }
2855             }
2856         }
2857     }
2858   else
2859     {
2860       func_str = "libc_accept4";
2861
2862       if (LDP_DEBUG > 0)
2863         clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): "
2864                       "addr %p, addr_len %p, flags 0x%x",
2865                       getpid (), listen_fd, listen_fd, func_str,
2866                       addr, addr_len, flags);
2867
2868       rv = libc_accept4 (listen_fd, addr, addr_len, flags);
2869     }
2870
2871   if (LDP_DEBUG > 0)
2872     {
2873       if (rv < 0)
2874         {
2875           int errno_val = errno;
2876           perror (func_str);
2877           clib_warning ("LDP<%d>: ERROR: listen fd %d (0x%x): %s() failed! "
2878                         "rv %d, errno = %d", getpid (), listen_fd,
2879                         listen_fd, func_str, rv, errno_val);
2880           errno = errno_val;
2881         }
2882       else
2883         clib_warning ("LDP<%d>: listen fd %d (0x%x): returning %d (0x%x)",
2884                       getpid (), listen_fd, listen_fd, rv, rv);
2885     }
2886   return rv;
2887 }
2888
2889 int
2890 accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
2891          int flags)
2892 {
2893   return ldp_accept4 (fd, addr, addr_len, flags);
2894 }
2895
2896 int
2897 accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
2898 {
2899   return ldp_accept4 (fd, addr, addr_len, 0);
2900 }
2901
2902 int
2903 shutdown (int fd, int how)
2904 {
2905   int rv;
2906   const char *func_str;
2907   u32 sid = ldp_sid_from_fd (fd);
2908
2909   if ((errno = -ldp_init ()))
2910     return -1;
2911
2912   if (sid != INVALID_SESSION_ID)
2913     {
2914       func_str = "vppcom_session_close[TODO]";
2915       rv = close (fd);
2916     }
2917   else
2918     {
2919       func_str = "libc_shutdown";
2920
2921       if (LDP_DEBUG > 1)
2922         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): how %d",
2923                       getpid (), fd, fd, func_str, how);
2924
2925       rv = libc_shutdown (fd, how);
2926     }
2927
2928   if (LDP_DEBUG > 1)
2929     {
2930       if (rv < 0)
2931         {
2932           int errno_val = errno;
2933           perror (func_str);
2934           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2935                         "rv %d, errno = %d", getpid (), fd, fd,
2936                         func_str, rv, errno_val);
2937           errno = errno_val;
2938         }
2939       else
2940         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2941                       getpid (), fd, fd, rv, rv);
2942     }
2943   return rv;
2944 }
2945
2946 int
2947 epoll_create1 (int flags)
2948 {
2949   const char *func_str;
2950   int rv;
2951
2952   if ((errno = -ldp_init ()))
2953     return -1;
2954
2955   if (ldp->vcl_needs_real_epoll)
2956     {
2957       rv = libc_epoll_create1 (flags);
2958       ldp->vcl_needs_real_epoll = 0;
2959       ldp->vcl_mq_epfd = rv;
2960       LDBG (0, "LDP<%d>: created vcl epfd %u", getpid (), rv);
2961       return rv;
2962     }
2963   func_str = "vppcom_epoll_create";
2964
2965   LDBG (1, "LDP<%d>: calling %s()", getpid (), func_str);
2966
2967   rv = vppcom_epoll_create ();
2968
2969   if (PREDICT_FALSE (rv < 0))
2970     {
2971       errno = -rv;
2972       rv = -1;
2973     }
2974   else
2975     rv = ldp_fd_from_sid ((u32) rv);
2976
2977   if (LDP_DEBUG > 1)
2978     {
2979       if (rv < 0)
2980         {
2981           int errno_val = errno;
2982           perror (func_str);
2983           clib_warning ("LDP<%d>: ERROR: %s() failed! "
2984                         "rv %d, errno = %d",
2985                         getpid (), func_str, rv, errno_val);
2986           errno = errno_val;
2987         }
2988       else
2989         clib_warning ("LDP<%d>: returning epfd %d (0x%x)", getpid (), rv, rv);
2990     }
2991   return rv;
2992 }
2993
2994 int
2995 epoll_create (int size)
2996 {
2997   return epoll_create1 (0);
2998 }
2999
3000 int
3001 epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
3002 {
3003   u32 vep_idx = ldp_sid_from_fd (epfd), sid;
3004   const char *func_str;
3005   int rv;
3006
3007   if ((errno = -ldp_init ()))
3008     return -1;
3009
3010   if (PREDICT_FALSE (vep_idx == INVALID_SESSION_ID))
3011     {
3012       /* The LDP epoll_create1 always creates VCL epfd's.
3013        * The app should never have a kernel base epoll fd unless it
3014        * was acquired outside of the LD_PRELOAD process context.
3015        * In any case, if we get one, punt it to libc_epoll_ctl.
3016        */
3017       func_str = "libc_epoll_ctl";
3018
3019       LDBG (1, "LDP<%d>: epfd %d (0x%x): calling %s(): op %d, fd %d (0x%x),"
3020             " event %p", getpid (), epfd, epfd, func_str, op, fd, fd, event);
3021
3022       rv = libc_epoll_ctl (epfd, op, fd, event);
3023       goto done;
3024     }
3025
3026   sid = ldp_sid_from_fd (fd);
3027
3028   LDBG (0, "LDP<%d>: epfd %d (0x%x), vep_idx %d (0x%x), sid %d (0x%x)",
3029         getpid (), epfd, epfd, vep_idx, vep_idx, sid, sid);
3030
3031   if (sid != INVALID_SESSION_ID)
3032     {
3033       func_str = "vppcom_epoll_ctl";
3034
3035       LDBG (1, "LDP<%d>: epfd %d (0x%x): calling %s(): vep_idx %d (0x%x),"
3036             " op %d, sid %u (0x%x), event %p", getpid (), epfd, epfd,
3037             func_str, vep_idx, vep_idx, sid, sid, event);
3038
3039       rv = vppcom_epoll_ctl (vep_idx, op, sid, event);
3040       if (rv != VPPCOM_OK)
3041         {
3042           errno = -rv;
3043           rv = -1;
3044         }
3045     }
3046   else
3047     {
3048       int libc_epfd;
3049       u32 size = sizeof (epfd);
3050
3051       func_str = "vppcom_session_attr[GET_LIBC_EPFD]";
3052       libc_epfd = vppcom_session_attr (vep_idx, VPPCOM_ATTR_GET_LIBC_EPFD, 0,
3053                                        0);
3054       LDBG (1, "LDP<%d>: epfd %d (0x%x), vep_idx %d (0x%x): %s() "
3055             "returned libc_epfd %d (0x%x)", getpid (), epfd, epfd,
3056             vep_idx, vep_idx, func_str, libc_epfd, libc_epfd);
3057
3058       if (!libc_epfd)
3059         {
3060           func_str = "libc_epoll_create1";
3061
3062           LDBG (1, "LDP<%d>: epfd %d (0x%x), vep_idx %d (0x%x): "
3063                 "calling %s(): EPOLL_CLOEXEC", getpid (), epfd, epfd,
3064                 vep_idx, vep_idx, func_str);
3065
3066           libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
3067           if (libc_epfd < 0)
3068             {
3069               rv = libc_epfd;
3070               goto done;
3071             }
3072
3073           func_str = "vppcom_session_attr[SET_LIBC_EPFD]";
3074           LDBG (1, "LDP<%d>: epfd %d (0x%x): calling %s(): vep_idx %d (0x%x),"
3075                 " VPPCOM_ATTR_SET_LIBC_EPFD, libc_epfd %d (0x%x), size %d",
3076                 getpid (), epfd, epfd, func_str, vep_idx, vep_idx, libc_epfd,
3077                 libc_epfd, size);
3078
3079           rv = vppcom_session_attr (vep_idx, VPPCOM_ATTR_SET_LIBC_EPFD,
3080                                     &libc_epfd, &size);
3081           if (rv < 0)
3082             {
3083               errno = -rv;
3084               rv = -1;
3085               goto done;
3086             }
3087         }
3088       else if (PREDICT_FALSE (libc_epfd < 0))
3089         {
3090           errno = -epfd;
3091           rv = -1;
3092           goto done;
3093         }
3094
3095       func_str = "libc_epoll_ctl";
3096
3097       LDBG (1, "LDP<%d>: epfd %d (0x%x): calling %s(): libc_epfd %d (0x%x), "
3098             "op %d, fd %d (0x%x), event %p", getpid (), epfd, epfd, func_str,
3099             libc_epfd, libc_epfd, op, fd, fd, event);
3100
3101       rv = libc_epoll_ctl (libc_epfd, op, fd, event);
3102     }
3103
3104 done:
3105   if (LDP_DEBUG > 1)
3106     {
3107       if (rv < 0)
3108         {
3109           int errno_val = errno;
3110           perror (func_str);
3111           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
3112                         "rv %d, errno = %d", getpid (), fd, fd,
3113                         func_str, rv, errno_val);
3114           errno = errno_val;
3115         }
3116       else
3117         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
3118                       getpid (), fd, fd, rv, rv);
3119     }
3120   return rv;
3121 }
3122
3123 static inline int
3124 ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
3125                  int timeout, const sigset_t * sigmask)
3126 {
3127   double time_to_wait = (double) 0, time_out, now = 0;
3128   u32 vep_idx = ldp_sid_from_fd (epfd);
3129   int libc_epfd, rv = 0;
3130   const char *func_str;
3131
3132   if ((errno = -ldp_init ()))
3133     return -1;
3134
3135   if (PREDICT_FALSE (!events || (timeout < -1)))
3136     {
3137       errno = EFAULT;
3138       return -1;
3139     }
3140
3141   if (epfd == ldp->vcl_mq_epfd)
3142     return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
3143
3144   if (PREDICT_FALSE (vep_idx == INVALID_SESSION_ID))
3145     {
3146       clib_warning ("LDP<%d>: ERROR: epfd %d (0x%x): bad vep_idx %d (0x%x)!",
3147                     getpid (), epfd, epfd, vep_idx, vep_idx);
3148       errno = EBADFD;
3149       return -1;
3150     }
3151
3152   time_to_wait = ((timeout >= 0) ? (double) timeout : 0);
3153   time_out = clib_time_now (&ldp->clib_time) + time_to_wait;
3154
3155   func_str = "vppcom_session_attr[GET_LIBC_EPFD]";
3156   libc_epfd = vppcom_session_attr (vep_idx, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
3157   if (PREDICT_FALSE (libc_epfd < 0))
3158     {
3159       errno = -libc_epfd;
3160       rv = -1;
3161       goto done;
3162     }
3163
3164   LDBG (2, "LDP<%d>: epfd %d (0x%x): vep_idx %d (0x%x), libc_epfd %d (0x%x), "
3165         "events %p, maxevents %d, timeout %d, sigmask %p: time_to_wait %.02f",
3166         getpid (), epfd, epfd, vep_idx, vep_idx, libc_epfd, libc_epfd, events,
3167         maxevents, timeout, sigmask, time_to_wait, time_out);
3168   do
3169     {
3170       if (!ldp->epoll_wait_vcl)
3171         {
3172           func_str = "vppcom_epoll_wait";
3173
3174           LDBG (3, "LDP<%d>: epfd %d (0x%x): calling %s(): vep_idx %d (0x%x),"
3175                 " events %p, maxevents %d", getpid (), epfd, epfd, func_str,
3176                 vep_idx, vep_idx, events, maxevents);
3177
3178           rv = vppcom_epoll_wait (vep_idx, events, maxevents, 0);
3179           if (rv > 0)
3180             {
3181               ldp->epoll_wait_vcl = 1;
3182               goto done;
3183             }
3184           else if (rv < 0)
3185             {
3186               errno = -rv;
3187               rv = -1;
3188               goto done;
3189             }
3190         }
3191       else
3192         ldp->epoll_wait_vcl = 0;
3193
3194       if (libc_epfd > 0)
3195         {
3196           func_str = "libc_epoll_pwait";
3197
3198           LDBG (3, "LDP<%d>: epfd %d (0x%x): calling %s(): libc_epfd %d "
3199                 "(0x%x), events %p, maxevents %d, sigmask %p", getpid (),
3200                 epfd, epfd, func_str, libc_epfd, libc_epfd, events,
3201                 maxevents, sigmask);
3202
3203           rv = libc_epoll_pwait (libc_epfd, events, maxevents, 1, sigmask);
3204           if (rv != 0)
3205             goto done;
3206         }
3207
3208       if (timeout != -1)
3209         now = clib_time_now (&ldp->clib_time);
3210     }
3211   while (now < time_out);
3212
3213 done:
3214   if (LDP_DEBUG > 3)
3215     {
3216       if (libc_epfd > 0)
3217         epfd = libc_epfd;
3218       if (rv < 0)
3219         {
3220           int errno_val = errno;
3221           perror (func_str);
3222           clib_warning ("LDP<%d>: ERROR: epfd %d (0x%x): %s() failed! "
3223                         "rv %d, errno = %d", getpid (), epfd, epfd,
3224                         func_str, rv, errno_val);
3225           errno = errno_val;
3226         }
3227       else
3228         clib_warning ("LDP<%d>: epfd %d (0x%x): returning %d (0x%x)",
3229                       getpid (), epfd, epfd, rv, rv);
3230     }
3231   return rv;
3232 }
3233
3234 int
3235 epoll_pwait (int epfd, struct epoll_event *events,
3236              int maxevents, int timeout, const sigset_t * sigmask)
3237 {
3238   return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
3239 }
3240
3241 int
3242 epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
3243 {
3244   return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL);
3245 }
3246
3247 int
3248 poll (struct pollfd *fds, nfds_t nfds, int timeout)
3249 {
3250   const char *func_str = __func__;
3251   int rv, i, n_revents = 0;
3252   u32 sid;
3253   vcl_poll_t *vp;
3254   double wait_for_time;
3255
3256   LDBG (3, "LDP<%d>: fds %p, nfds %d, timeout %d", getpid (), fds, nfds,
3257         timeout);
3258
3259   if (timeout >= 0)
3260     wait_for_time = (f64) timeout / 1000;
3261   else
3262     wait_for_time = -1;
3263
3264   for (i = 0; i < nfds; i++)
3265     {
3266       if (fds[i].fd < 0)
3267         continue;
3268
3269       LDBG (3, "LDP<%d>: fds[%d] fd %d (0x%0x) events = 0x%x revents = 0x%x",
3270             getpid (), i, fds[i].fd, fds[i].fd, fds[i].events,
3271             fds[i].revents);
3272
3273       sid = ldp_sid_from_fd (fds[i].fd);
3274       if (sid != INVALID_SESSION_ID)
3275         {
3276           fds[i].fd = -fds[i].fd;
3277           vec_add2 (ldp->vcl_poll, vp, 1);
3278           vp->fds_ndx = i;
3279           vp->sid = sid;
3280           vp->events = fds[i].events;
3281 #ifdef __USE_XOPEN2K
3282           if (fds[i].events & POLLRDNORM)
3283             vp->events |= POLLIN;
3284           if (fds[i].events & POLLWRNORM)
3285             vp->events |= POLLOUT;
3286 #endif
3287           vp->revents = fds[i].revents;
3288         }
3289       else
3290         {
3291           vec_add1 (ldp->libc_poll, fds[i]);
3292           vec_add1 (ldp->libc_poll_idxs, i);
3293         }
3294     }
3295
3296   do
3297     {
3298       if (vec_len (ldp->vcl_poll))
3299         {
3300           func_str = "vppcom_poll";
3301
3302           LDBG (3, "LDP<%d>: calling %s(): vcl_poll %p, n_sids %u (0x%x): "
3303                 "n_libc_fds %u", getpid (), func_str, ldp->vcl_poll,
3304                 vec_len (ldp->vcl_poll), vec_len (ldp->vcl_poll),
3305                 vec_len (ldp->libc_poll));
3306
3307           rv = vppcom_poll (ldp->vcl_poll, vec_len (ldp->vcl_poll), 0);
3308           if (rv < 0)
3309             {
3310               errno = -rv;
3311               rv = -1;
3312               goto done;
3313             }
3314           else
3315             n_revents += rv;
3316         }
3317
3318       if (vec_len (ldp->libc_poll))
3319         {
3320           func_str = "libc_poll";
3321
3322           LDBG (3, "LDP<%d>: calling %s(): fds %p, nfds %u: n_sids %u",
3323                 getpid (), fds, nfds, vec_len (ldp->vcl_poll));
3324
3325           rv = libc_poll (ldp->libc_poll, vec_len (ldp->libc_poll), 0);
3326           if (rv < 0)
3327             goto done;
3328           else
3329             n_revents += rv;
3330         }
3331
3332       if (n_revents)
3333         {
3334           rv = n_revents;
3335           goto done;
3336         }
3337     }
3338   while ((wait_for_time == -1) ||
3339          (clib_time_now (&ldp->clib_time) < wait_for_time));
3340   rv = 0;
3341
3342 done:
3343   vec_foreach (vp, ldp->vcl_poll)
3344   {
3345     fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
3346     fds[vp->fds_ndx].revents = vp->revents;
3347 #ifdef __USE_XOPEN2K
3348     if ((fds[vp->fds_ndx].revents & POLLIN) &&
3349         (fds[vp->fds_ndx].events & POLLRDNORM))
3350       fds[vp->fds_ndx].revents |= POLLRDNORM;
3351     if ((fds[vp->fds_ndx].revents & POLLOUT) &&
3352         (fds[vp->fds_ndx].events & POLLWRNORM))
3353       fds[vp->fds_ndx].revents |= POLLWRNORM;
3354 #endif
3355   }
3356   vec_reset_length (ldp->vcl_poll);
3357
3358   for (i = 0; i < vec_len (ldp->libc_poll); i++)
3359     {
3360       fds[ldp->libc_poll_idxs[i]].revents = ldp->libc_poll[i].revents;
3361     }
3362   vec_reset_length (ldp->libc_poll_idxs);
3363   vec_reset_length (ldp->libc_poll);
3364
3365   if (LDP_DEBUG > 3)
3366     {
3367       if (rv < 0)
3368         {
3369           int errno_val = errno;
3370           perror (func_str);
3371           clib_warning ("LDP<%d>: ERROR: %s() failed! "
3372                         "rv %d, errno = %d", getpid (),
3373                         func_str, rv, errno_val);
3374           errno = errno_val;
3375         }
3376       else
3377         {
3378           clib_warning ("LDP<%d>: returning %d (0x%x): n_sids %u, "
3379                         "n_libc_fds %d", getpid (), rv, rv,
3380                         vec_len (ldp->vcl_poll), vec_len (ldp->libc_poll));
3381
3382           for (i = 0; i < nfds; i++)
3383             {
3384               if (fds[i].fd >= 0)
3385                 {
3386                   if (LDP_DEBUG > 3)
3387                     clib_warning ("LDP<%d>: fds[%d].fd %d (0x%0x), "
3388                                   ".events = 0x%x, .revents = 0x%x",
3389                                   getpid (), i, fds[i].fd, fds[i].fd,
3390                                   fds[i].events, fds[i].revents);
3391                 }
3392             }
3393         }
3394     }
3395
3396   return rv;
3397 }
3398
3399 #ifdef USE_GNU
3400 int
3401 ppoll (struct pollfd *fds, nfds_t nfds,
3402        const struct timespec *timeout, const sigset_t * sigmask)
3403 {
3404   if ((errno = -ldp_init ()))
3405     return -1;
3406
3407   clib_warning ("LDP<%d>: LDP-TBD", getpid ());
3408   errno = ENOSYS;
3409
3410
3411   return -1;
3412 }
3413 #endif
3414
3415 void CONSTRUCTOR_ATTRIBUTE ldp_constructor (void);
3416
3417 void DESTRUCTOR_ATTRIBUTE ldp_destructor (void);
3418
3419 /*
3420  * This function is called when the library is loaded
3421  */
3422 void
3423 ldp_constructor (void)
3424 {
3425   swrap_constructor ();
3426   if (ldp_init () != 0)
3427     fprintf (stderr, "\nLDP<%d>: ERROR: ldp_constructor: failed!\n",
3428              getpid ());
3429   else if (LDP_DEBUG > 0)
3430     clib_warning ("LDP<%d>: LDP constructor: done!\n", getpid ());
3431 }
3432
3433 /*
3434  * This function is called when the library is unloaded
3435  */
3436 void
3437 ldp_destructor (void)
3438 {
3439   swrap_destructor ();
3440   if (ldp->init)
3441     {
3442       vppcom_app_destroy ();
3443       ldp->init = 0;
3444     }
3445
3446   /* Don't use clib_warning() here because that calls writev()
3447    * which will call ldp_init().
3448    */
3449   if (LDP_DEBUG > 0)
3450     printf ("%s:%d: LDP<%d>: LDP destructor: done!\n",
3451             __func__, __LINE__, getpid ());
3452 }
3453
3454
3455 /*
3456  * fd.io coding-style-patch-verification: ON
3457  *
3458  * Local Variables:
3459  * eval: (c-set-style "gnu")
3460  * End:
3461  */