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