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