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