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