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