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