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