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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <sys/resource.h>
23 #include <netinet/tcp.h>
25 #include <vcl/ldp_socket_wrapper.h>
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>
36 #define HAVE_CONSTRUCTOR_ATTRIBUTE
37 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
38 #define CONSTRUCTOR_ATTRIBUTE \
39 __attribute__ ((constructor))
41 #define CONSTRUCTOR_ATTRIBUTE
42 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
44 #define HAVE_DESTRUCTOR_ATTRIBUTE
45 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
46 #define DESTRUCTOR_ATTRIBUTE \
47 __attribute__ ((destructor))
49 #define DESTRUCTOR_ATTRIBUTE
52 #define LDP_MAX_NWORKERS 32
54 #define LDP_F_SHUT_RD (1 << 0)
55 #define LDP_F_SHUT_WR (1 << 1)
57 typedef struct ldp_fd_entry_
67 typedef struct ldp_worker_ctx_
70 clib_time_t clib_time;
75 clib_bitmap_t *rd_bitmap;
76 clib_bitmap_t *wr_bitmap;
77 clib_bitmap_t *ex_bitmap;
78 clib_bitmap_t *sid_rd_bitmap;
79 clib_bitmap_t *sid_wr_bitmap;
80 clib_bitmap_t *sid_ex_bitmap;
81 clib_bitmap_t *libc_rd_bitmap;
82 clib_bitmap_t *libc_wr_bitmap;
83 clib_bitmap_t *libc_ex_bitmap;
90 struct pollfd *libc_poll;
103 ldp_worker_ctx_t *workers;
105 char app_name[LDP_APP_NAME_MAX];
109 ldp_fd_entry_t *fd_pool;
110 clib_rwlock_t fd_table_lock;
111 uword *session_index_to_fd_table;
113 /** vcl needs next epoll_create to go to libc_epoll */
114 u8 vcl_needs_real_epoll;
117 #define LDP_DEBUG ldp->debug
119 #define LDBG(_lvl, _fmt, _args...) \
120 if (ldp->debug > _lvl) \
121 clib_warning ("ldp<%d>: " _fmt, getpid(), ##_args)
123 static ldp_main_t ldp_main = {
124 .sh_bit_val = (1 << LDP_SID_BIT_MIN),
125 .sid_bit_mask = (1 << LDP_SID_BIT_MIN) - 1,
126 .debug = LDP_DEBUG_INIT,
129 static ldp_main_t *ldp = &ldp_main;
131 static inline ldp_worker_ctx_t *
132 ldp_worker_get_current (void)
134 return (ldp->workers + vppcom_worker_index ());
138 * RETURN: 0 on success or -1 on error.
141 ldp_set_app_name (char *app_name)
143 int rv = snprintf (ldp->app_name, LDP_APP_NAME_MAX,
144 "ldp-%d-%s", getpid (), app_name);
146 if (rv >= LDP_APP_NAME_MAX)
147 app_name[LDP_APP_NAME_MAX - 1] = 0;
153 if (ldp->app_name[0] == '\0')
154 ldp_set_app_name ("app");
156 return ldp->app_name;
159 static inline vcl_session_handle_t
160 ldp_fd_entry_sh (ldp_fd_entry_t * fde)
162 return vppcom_session_handle (fde->session_index);
166 ldp_fd_alloc (vcl_session_handle_t sh)
170 clib_rwlock_writer_lock (&ldp->fd_table_lock);
171 if (pool_elts (ldp->fd_pool) >= (1ULL << 32) - ldp->sh_bit_val)
173 clib_rwlock_writer_unlock (&ldp->fd_table_lock);
176 pool_get (ldp->fd_pool, fde);
177 fde->session_index = vppcom_session_index (sh);
178 fde->worker_index = vppcom_session_worker (sh);
179 fde->fd_index = fde - ldp->fd_pool;
180 fde->fd = fde->fd_index + ldp->sh_bit_val;
181 hash_set (ldp->session_index_to_fd_table, fde->session_index, fde->fd);
182 clib_spinlock_init (&fde->lock);
183 clib_rwlock_writer_unlock (&ldp->fd_table_lock);
187 static ldp_fd_entry_t *
188 ldp_fd_entry_get (u32 fd_index)
190 if (pool_is_free_index (ldp->fd_pool, fd_index))
192 return pool_elt_at_index (ldp->fd_pool, fd_index);
195 static ldp_fd_entry_t *
196 ldp_fd_entry_lock (u32 fd_index)
199 clib_rwlock_reader_lock (&ldp->fd_table_lock);
200 if (pool_is_free_index (ldp->fd_pool, fd_index))
202 clib_rwlock_reader_unlock (&ldp->fd_table_lock);
206 fe = pool_elt_at_index (ldp->fd_pool, fd_index);
207 clib_spinlock_lock (&fe->lock);
212 ldp_fd_entry_unlock (ldp_fd_entry_t * fde)
214 clib_spinlock_unlock (&fde->lock);
215 clib_rwlock_reader_unlock (&ldp->fd_table_lock);
219 ldp_fd_from_sh (vcl_session_handle_t sh)
224 clib_rwlock_reader_lock (&ldp->fd_table_lock);
225 fdp = hash_get (ldp->session_index_to_fd_table, vppcom_session_index (sh));
226 fd = fdp ? *fdp : -EMFILE;
227 clib_rwlock_reader_unlock (&ldp->fd_table_lock);
233 ldp_fd_is_sh (int fd)
235 return fd >= ldp->sh_bit_val;
239 ldp_sh_from_fd (int fd)
241 u32 fd_index, session_index;
244 if (!ldp_fd_is_sh (fd))
245 return INVALID_SESSION_ID;
247 fd_index = fd - ldp->sh_bit_val;
248 fde = ldp_fd_entry_lock (fd_index);
251 LDBG (0, "unknown fd %d", fd);
252 return INVALID_SESSION_ID;
254 session_index = fde->session_index;
255 ldp_fd_entry_unlock (fde);
257 return vppcom_session_handle (session_index);
260 static ldp_fd_entry_t *
261 ldp_fd_entry_lock_w_fd (int fd)
265 if (!ldp_fd_is_sh (fd))
268 fd_index = fd - ldp->sh_bit_val;
269 return ldp_fd_entry_lock (fd_index);
273 ldp_fd_free_w_sh (vcl_session_handle_t sh)
279 fd = ldp_fd_from_sh (sh);
283 fd_index = fd - ldp->sh_bit_val;
284 clib_rwlock_writer_lock (&ldp->fd_table_lock);
285 fde = ldp_fd_entry_get (fd_index);
287 hash_unset (ldp->session_index_to_fd_table, fde->session_index);
288 clib_spinlock_free (&fde->lock);
289 pool_put (ldp->fd_pool, fde);
290 clib_rwlock_writer_unlock (&ldp->fd_table_lock);
296 ldp_worker_ctx_t *ldpw;
299 if (PREDICT_TRUE (ldp->init))
303 ldp->vcl_needs_real_epoll = 1;
304 rv = vppcom_app_create (ldp_get_app_name ());
307 ldp->vcl_needs_real_epoll = 0;
308 if (rv == VPPCOM_EEXIST)
310 LDBG (2, "\nERROR: ldp_init: vppcom_app_create()"
311 " failed! rv = %d (%s)\n", rv, vppcom_retval_str (rv));
315 ldp->vcl_needs_real_epoll = 0;
316 pool_alloc (ldp->workers, LDP_MAX_NWORKERS);
317 ldpw = ldp_worker_get_current ();
319 char *env_var_str = getenv (LDP_ENV_DEBUG);
323 if (sscanf (env_var_str, "%u", &tmp) != 1)
324 clib_warning ("LDP<%d>: WARNING: Invalid LDP debug level specified in"
325 " the env var " LDP_ENV_DEBUG " (%s)!", getpid (),
330 LDBG (0, "configured LDP debug level (%u) from env var "
331 LDP_ENV_DEBUG "!", ldp->debug);
335 env_var_str = getenv (LDP_ENV_APP_NAME);
338 ldp_set_app_name (env_var_str);
339 LDBG (0, "configured LDP app name (%s) from the env var "
340 LDP_ENV_APP_NAME "!", ldp->app_name);
343 env_var_str = getenv (LDP_ENV_SID_BIT);
347 if (sscanf (env_var_str, "%u", &sb) != 1)
349 clib_warning ("LDP<%d>: WARNING: Invalid LDP sid bit specified in"
350 " the env var " LDP_ENV_SID_BIT " (%s)! sid bit "
351 "value %d (0x%x)", getpid (), env_var_str,
352 ldp->sh_bit_val, ldp->sh_bit_val);
354 else if (sb < LDP_SID_BIT_MIN)
356 ldp->sh_bit_val = (1 << LDP_SID_BIT_MIN);
357 ldp->sid_bit_mask = ldp->sh_bit_val - 1;
359 clib_warning ("LDP<%d>: WARNING: LDP sid bit (%u) specified in the"
360 " env var " LDP_ENV_SID_BIT " (%s) is too small. "
361 "Using LDP_SID_BIT_MIN (%d)! sid bit value %d (0x%x)",
362 getpid (), sb, env_var_str, LDP_SID_BIT_MIN,
363 ldp->sh_bit_val, ldp->sh_bit_val);
365 else if (sb > LDP_SID_BIT_MAX)
367 ldp->sh_bit_val = (1 << LDP_SID_BIT_MAX);
368 ldp->sid_bit_mask = ldp->sh_bit_val - 1;
370 clib_warning ("LDP<%d>: WARNING: LDP sid bit (%u) specified in the"
371 " env var " LDP_ENV_SID_BIT " (%s) is too big. Using"
372 " LDP_SID_BIT_MAX (%d)! sid bit value %d (0x%x)",
373 getpid (), sb, env_var_str, LDP_SID_BIT_MAX,
374 ldp->sh_bit_val, ldp->sh_bit_val);
378 ldp->sh_bit_val = (1 << sb);
379 ldp->sid_bit_mask = ldp->sh_bit_val - 1;
381 LDBG (0, "configured LDP sid bit (%u) from "
382 LDP_ENV_SID_BIT "! sid bit value %d (0x%x)", sb,
383 ldp->sh_bit_val, ldp->sh_bit_val);
387 clib_time_init (&ldpw->clib_time);
388 clib_rwlock_init (&ldp->fd_table_lock);
389 LDBG (0, "LDP initialization: done!");
397 int rv, refcnt, epfd;
401 if ((errno = -ldp_init ()))
404 fde = ldp_fd_entry_lock_w_fd (fd);
407 sh = ldp_fd_entry_sh (fde);
408 epfd = vppcom_session_attr (sh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
411 LDBG (0, "fd %d (0x%x): calling libc_close: epfd %u (0x%x)",
414 rv = libc_close (epfd);
417 u32 size = sizeof (epfd);
420 (void) vppcom_session_attr (sh, VPPCOM_ATTR_SET_LIBC_EPFD,
424 else if (PREDICT_FALSE (epfd < 0))
428 ldp_fd_entry_unlock (fde);
432 LDBG (0, "fd %d (0x%x): calling vppcom_session_close: sid %u (0x%x)",
435 refcnt = vppcom_session_attr (sh, VPPCOM_ATTR_GET_REFCNT, 0, 0);
436 rv = vppcom_session_close (sh);
443 ldp_fd_entry_unlock (fde);
445 ldp_fd_free_w_sh (sh);
449 LDBG (0, "fd %d (0x%x): calling libc_close", fd, fd);
450 rv = libc_close (fd);
455 LDBG (1, "fd %d (0x%x): returning %d (0x%x)", fd, fd, rv, rv);
460 read (int fd, void *buf, size_t nbytes)
462 vcl_session_handle_t sh;
466 if ((errno = -ldp_init ()))
469 fde = ldp_fd_entry_lock_w_fd (fd);
472 sh = ldp_fd_entry_sh (fde);
473 LDBG (2, "fd %d (0x%x): calling vppcom_session_read(): sid %u (0x%x),"
474 " buf %p, nbytes %u", fd, fd, sh, sh, buf, nbytes);
476 size = vppcom_session_read (sh, buf, nbytes);
482 ldp_fd_entry_unlock (fde);
486 LDBG (2, "fd %d (0x%x): calling libc_read(): buf %p, nbytes %u",
487 fd, fd, buf, nbytes);
489 size = libc_read (fd, buf, nbytes);
492 LDBG (2, "fd %d (0x%x): returning %d (0x%x)", fd, fd, size, size);
497 readv (int fd, const struct iovec * iov, int iovcnt)
500 u32 sid = ldp_sh_from_fd (fd);
501 int rv = 0, i, total = 0;
503 if ((errno = -ldp_init ()))
506 if (sid != INVALID_SESSION_ID)
510 for (i = 0; i < iovcnt; ++i)
512 LDBG (2, "fd %d (0x%x): calling vppcom_session_read() [%d]:"
513 " sid %u (0x%x), iov %p, iovcnt %d, total %d", fd, fd, i,
514 sid, sid, iov, iovcnt, total);
516 rv = vppcom_session_read (sid, iov[i].iov_base, iov[i].iov_len);
522 if (rv < iov[i].iov_len)
524 LDBG (2, "fd %d (0x%x): rv (%d) < iov[%d].iov_len (%d)",
525 fd, fd, rv, i, iov[i].iov_len);
531 while ((rv >= 0) && (total == 0));
543 LDBG (2, "fd %d (0x%x): calling libc_readv(): iov %p, iovcnt %d", fd,
546 size = libc_readv (fd, iov, iovcnt);
550 LDBG (2, "fd %d (0x%x): returning %d (0x%x)", fd, fd, size, size);
555 write (int fd, const void *buf, size_t nbytes)
557 vcl_session_handle_t sh;
561 if ((errno = -ldp_init ()))
564 fde = ldp_fd_entry_lock_w_fd (fd);
567 sh = ldp_fd_entry_sh (fde);
568 LDBG (2, "fd %d (0x%x): calling vppcom_session_write(): sid %u (0x%x), "
569 "buf %p, nbytes %u", fd, fd, sh, sh, buf, nbytes);
571 size = vppcom_session_write_msg (sh, (void *) buf, nbytes);
577 ldp_fd_entry_unlock (fde);
581 LDBG (2, "fd %d (0x%x): calling libc_write(): buf %p, nbytes %u",
582 fd, fd, buf, nbytes);
584 size = libc_write (fd, buf, nbytes);
587 LDBG (2, "fd %d (0x%x): returning %d (0x%x)", fd, fd, size, size);
592 writev (int fd, const struct iovec * iov, int iovcnt)
594 ssize_t size = 0, total = 0;
595 u32 sid = ldp_sh_from_fd (fd);
599 * Use [f]printf() instead of clib_warning() to prevent recursion SIGSEGV.
602 if ((errno = -ldp_init ()))
605 if (sid != INVALID_SESSION_ID)
609 for (i = 0; i < iovcnt; ++i)
611 rv = vppcom_session_write_msg (sid, iov[i].iov_base,
618 if (rv < iov[i].iov_len)
623 while ((rv >= 0) && (total == 0));
635 size = libc_writev (fd, iov, iovcnt);
642 fcntl (int fd, int cmd, ...)
644 const char *func_str = __func__;
647 u32 sid = ldp_sh_from_fd (fd);
649 if ((errno = -ldp_init ()))
653 if (sid != INVALID_SESSION_ID)
655 int flags = va_arg (ap, int);
658 size = sizeof (flags);
663 func_str = "vppcom_session_attr[SET_FLAGS]";
664 LDBG (2, "fd %d (0x%x): calling %s(): sid %u (0x%x) "
665 "flags %d (0x%x), size %d", fd, fd, func_str, sid,
666 sid, flags, flags, size);
668 rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_FLAGS, &flags,
673 func_str = "vppcom_session_attr[GET_FLAGS]";
674 LDBG (2, "fd %d (0x%x): calling %s(): sid %u (0x%x), "
675 "flags %d (0x%x), size %d", fd, fd, func_str, sid,
676 sid, flags, flags, size);
678 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_FLAGS, &flags,
682 LDBG (2, "fd %d (0x%x), cmd %d (F_GETFL): %s() "
683 "returned flags %d (0x%x)", fd, fd, cmd,
684 func_str, flags, flags);
689 /* TODO handle this */
690 LDBG (0, "F_SETFD ignored flags %u", flags);
705 func_str = "libc_vfcntl";
707 LDBG (2, "fd %d (0x%x): calling %s(): cmd %d", fd, fd, func_str, cmd);
709 rv = libc_vfcntl (fd, cmd, ap);
718 int errno_val = errno;
720 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
721 "rv %d, errno = %d", getpid (), fd, fd,
722 func_str, rv, errno_val);
726 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
727 getpid (), fd, fd, rv, rv);
733 ioctl (int fd, unsigned long int cmd, ...)
735 const char *func_str;
738 u32 sid = ldp_sh_from_fd (fd);
740 if ((errno = -ldp_init ()))
744 if (sid != INVALID_SESSION_ID)
746 func_str = "vppcom_session_attr[GET_NREAD]";
753 ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x)",
754 getpid (), fd, fd, func_str, sid, sid);
756 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_NREAD, 0, 0);
761 u32 flags = va_arg (ap, int) ? O_NONBLOCK : 0;
762 u32 size = sizeof (flags);
764 /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than
765 * non-blocking, the flags should be read here and merged
769 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
770 "sid %u (0x%x), flags %d (0x%x), size %d",
771 getpid (), fd, fd, func_str, sid, sid,
774 rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_FLAGS, &flags,
791 func_str = "libc_vioctl";
794 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): cmd %d",
795 getpid (), fd, fd, func_str, cmd);
797 rv = libc_vioctl (fd, cmd, ap);
804 int errno_val = errno;
806 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
807 "rv %d, errno = %d", getpid (), fd, fd,
808 func_str, rv, errno_val);
812 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
813 getpid (), fd, fd, rv, rv);
820 ldp_pselect (int nfds, fd_set * __restrict readfds,
821 fd_set * __restrict writefds,
822 fd_set * __restrict exceptfds,
823 const struct timespec *__restrict timeout,
824 const __sigset_t * __restrict sigmask)
826 uword sid_bits, sid_bits_set, libc_bits, libc_bits_set;
827 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
828 u32 minbits = clib_max (nfds, BITS (uword)), sid;
829 char *func_str = "##";
841 time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ?
842 (f64) 0 : (f64) timeout->tv_sec +
843 (f64) timeout->tv_nsec / (f64) 1000000000;
845 /* select as fine grained sleep */
848 LDBG (3, "sleeping for %.02f seconds", time_out);
850 time_out += clib_time_now (&ldpw->clib_time);
851 while (clib_time_now (&ldpw->clib_time) < time_out)
865 if (nfds <= ldp->sh_bit_val)
867 func_str = "libc_pselect";
869 LDBG (3, "calling %s(): nfds %d, readfds %p, writefds %p, "
870 "exceptfds %p, timeout %p, sigmask %p", func_str, nfds,
871 readfds, writefds, exceptfds, timeout, sigmask);
873 rv = libc_pselect (nfds, readfds, writefds, exceptfds,
878 if (PREDICT_FALSE (ldp->sh_bit_val > FD_SETSIZE / 2))
880 clib_warning ("LDP<%d>: ERROR: LDP sid bit value %d (0x%x) > "
881 "FD_SETSIZE/2 %d (0x%x)!", getpid (),
882 ldp->sh_bit_val, ldp->sh_bit_val,
883 FD_SETSIZE / 2, FD_SETSIZE / 2);
888 sid_bits = libc_bits = 0;
889 u32 n_bytes = nfds / 8 + ((nfds % 8) ? 1 : 0);
892 clib_bitmap_validate (ldpw->sid_rd_bitmap, minbits);
893 clib_bitmap_validate (ldpw->libc_rd_bitmap, minbits);
894 clib_bitmap_validate (ldpw->rd_bitmap, minbits);
895 clib_memcpy_fast (ldpw->rd_bitmap, readfds, n_bytes);
896 memset (readfds, 0, n_bytes);
899 clib_bitmap_foreach (fd, ldpw->rd_bitmap, ({
902 sid = ldp_sh_from_fd (fd);
903 LDBG (3, "readfds: fd %d (0x%x), sid %u (0x%x)", fd, fd, sid, sid);
904 if (sid == INVALID_SESSION_ID)
905 clib_bitmap_set_no_check (ldpw->libc_rd_bitmap, fd, 1);
907 clib_bitmap_set_no_check (ldpw->sid_rd_bitmap,
908 vppcom_session_index (sid), 1);
912 sid_bits_set = clib_bitmap_last_set (ldpw->sid_rd_bitmap) + 1;
913 sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits;
915 libc_bits_set = clib_bitmap_last_set (ldpw->libc_rd_bitmap) + 1;
916 libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits;
918 LDBG (3, "readfds: sid_bits_set %d, sid_bits %d, "
919 "libc_bits_set %d, libc_bits %d", sid_bits_set,
920 sid_bits, libc_bits_set, libc_bits);
924 clib_bitmap_validate (ldpw->sid_wr_bitmap, minbits);
925 clib_bitmap_validate (ldpw->libc_wr_bitmap, minbits);
926 clib_bitmap_validate (ldpw->wr_bitmap, minbits);
927 clib_memcpy_fast (ldpw->wr_bitmap, writefds, n_bytes);
928 memset (writefds, 0, n_bytes);
931 clib_bitmap_foreach (fd, ldpw->wr_bitmap, ({
934 sid = ldp_sh_from_fd (fd);
935 LDBG (3, "writefds: fd %d (0x%x), sid %u (0x%x)", fd, fd, sid, sid);
936 if (sid == INVALID_SESSION_ID)
937 clib_bitmap_set_no_check (ldpw->libc_wr_bitmap, fd, 1);
939 clib_bitmap_set_no_check (ldpw->sid_wr_bitmap,
940 vppcom_session_index (sid), 1);
944 sid_bits_set = clib_bitmap_last_set (ldpw->sid_wr_bitmap) + 1;
945 sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits;
947 libc_bits_set = clib_bitmap_last_set (ldpw->libc_wr_bitmap) + 1;
948 libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits;
950 LDBG (3, "writefds: sid_bits_set %d, sid_bits %d, "
951 "libc_bits_set %d, libc_bits %d",
952 sid_bits_set, sid_bits, libc_bits_set, libc_bits);
956 clib_bitmap_validate (ldpw->sid_ex_bitmap, minbits);
957 clib_bitmap_validate (ldpw->libc_ex_bitmap, minbits);
958 clib_bitmap_validate (ldpw->ex_bitmap, minbits);
959 clib_memcpy_fast (ldpw->ex_bitmap, exceptfds, n_bytes);
960 memset (exceptfds, 0, n_bytes);
963 clib_bitmap_foreach (fd, ldpw->ex_bitmap, ({
966 sid = ldp_sh_from_fd (fd);
967 LDBG (3, "exceptfds: fd %d (0x%x), sid %u (0x%x)", fd, fd, sid, sid);
968 if (sid == INVALID_SESSION_ID)
969 clib_bitmap_set_no_check (ldpw->libc_ex_bitmap, fd, 1);
971 clib_bitmap_set_no_check (ldpw->sid_ex_bitmap,
972 vppcom_session_index (sid), 1);
976 sid_bits_set = clib_bitmap_last_set (ldpw->sid_ex_bitmap) + 1;
977 sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits;
979 libc_bits_set = clib_bitmap_last_set (ldpw->libc_ex_bitmap) + 1;
980 libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits;
982 LDBG (3, "exceptfds: sid_bits_set %d, sid_bits %d, "
983 "libc_bits_set %d, libc_bits %d",
984 sid_bits_set, sid_bits, libc_bits_set, libc_bits);
987 if (PREDICT_FALSE (!sid_bits && !libc_bits))
998 if (!ldpw->select_vcl)
1000 func_str = "vppcom_select";
1003 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->sid_rd_bitmap,
1004 vec_len (ldpw->rd_bitmap) *
1005 sizeof (clib_bitmap_t));
1007 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->sid_wr_bitmap,
1008 vec_len (ldpw->wr_bitmap) *
1009 sizeof (clib_bitmap_t));
1011 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->sid_ex_bitmap,
1012 vec_len (ldpw->ex_bitmap) *
1013 sizeof (clib_bitmap_t));
1015 rv = vppcom_select (sid_bits,
1016 readfds ? (unsigned long *) ldpw->rd_bitmap
1018 writefds ? (unsigned long *) ldpw->wr_bitmap
1020 exceptfds ? (unsigned long *)
1021 ldpw->ex_bitmap : NULL, 0);
1032 clib_bitmap_foreach (sid, ldpw->rd_bitmap,
1034 fd = ldp_fd_from_sh (vppcom_session_handle (sid));
1035 if (PREDICT_FALSE (fd < 0))
1041 FD_SET (fd, readfds);
1048 clib_bitmap_foreach (sid, ldpw->wr_bitmap,
1050 fd = ldp_fd_from_sh (vppcom_session_handle (sid));
1051 if (PREDICT_FALSE (fd < 0))
1057 FD_SET (fd, writefds);
1064 clib_bitmap_foreach (sid, ldpw->ex_bitmap,
1066 fd = ldp_fd_from_sh (vppcom_session_handle (sid));
1067 if (PREDICT_FALSE (fd < 0))
1073 FD_SET (fd, exceptfds);
1077 ldpw->select_vcl = 1;
1082 ldpw->select_vcl = 0;
1086 struct timespec tspec;
1088 func_str = "libc_pselect";
1091 clib_memcpy_fast (readfds, ldpw->libc_rd_bitmap,
1092 vec_len (ldpw->rd_bitmap) *
1093 sizeof (clib_bitmap_t));
1095 clib_memcpy_fast (writefds, ldpw->libc_wr_bitmap,
1096 vec_len (ldpw->wr_bitmap) *
1097 sizeof (clib_bitmap_t));
1099 clib_memcpy_fast (exceptfds, ldpw->libc_ex_bitmap,
1100 vec_len (ldpw->ex_bitmap) *
1101 sizeof (clib_bitmap_t));
1102 tspec.tv_sec = tspec.tv_nsec = 0;
1103 rv = libc_pselect (libc_bits,
1104 readfds ? readfds : NULL,
1105 writefds ? writefds : NULL,
1106 exceptfds ? exceptfds : NULL, &tspec, sigmask);
1111 while ((time_out == -1) || (clib_time_now (&ldpw->clib_time) < time_out));
1115 /* TBD: set timeout to amount of time left */
1116 clib_bitmap_zero (ldpw->rd_bitmap);
1117 clib_bitmap_zero (ldpw->sid_rd_bitmap);
1118 clib_bitmap_zero (ldpw->libc_rd_bitmap);
1119 clib_bitmap_zero (ldpw->wr_bitmap);
1120 clib_bitmap_zero (ldpw->sid_wr_bitmap);
1121 clib_bitmap_zero (ldpw->libc_wr_bitmap);
1122 clib_bitmap_zero (ldpw->ex_bitmap);
1123 clib_bitmap_zero (ldpw->sid_ex_bitmap);
1124 clib_bitmap_zero (ldpw->libc_ex_bitmap);
1130 int errno_val = errno;
1132 clib_warning ("LDP<%d>: ERROR: %s() failed! "
1133 "rv %d, errno = %d", getpid (),
1134 func_str, rv, errno_val);
1138 clib_warning ("LDP<%d>: returning %d (0x%x)", getpid (), rv, rv);
1144 select (int nfds, fd_set * __restrict readfds,
1145 fd_set * __restrict writefds,
1146 fd_set * __restrict exceptfds, struct timeval *__restrict timeout)
1148 struct timespec tspec;
1152 tspec.tv_sec = timeout->tv_sec;
1153 tspec.tv_nsec = timeout->tv_usec * 1000;
1155 return ldp_pselect (nfds, readfds, writefds, exceptfds,
1156 timeout ? &tspec : NULL, NULL);
1159 #ifdef __USE_XOPEN2K
1161 pselect (int nfds, fd_set * __restrict readfds,
1162 fd_set * __restrict writefds,
1163 fd_set * __restrict exceptfds,
1164 const struct timespec *__restrict timeout,
1165 const __sigset_t * __restrict sigmask)
1167 return ldp_pselect (nfds, readfds, writefds, exceptfds, timeout, 0);
1172 socket (int domain, int type, int protocol)
1174 const char *func_str;
1176 u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0;
1177 int sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
1179 if ((errno = -ldp_init ()))
1182 if (((domain == AF_INET) || (domain == AF_INET6)) &&
1183 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
1186 u8 proto = ((sock_type == SOCK_DGRAM) ?
1187 VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP);
1189 func_str = "vppcom_session_create";
1191 LDBG (0, "calling %s(): proto %u (%s), is_nonblocking %u",
1192 func_str, proto, vppcom_proto_str (proto), is_nonblocking);
1194 sid = vppcom_session_create (proto, is_nonblocking);
1202 func_str = "ldp_fd_from_sid";
1203 rv = ldp_fd_alloc (sid);
1206 (void) vppcom_session_close (sid);
1214 func_str = "libc_socket";
1216 LDBG (0, "calling %s()", func_str);
1218 rv = libc_socket (domain, type, protocol);
1225 int errno_val = errno;
1227 clib_warning ("LDP<%d>: ERROR: %s() failed! "
1228 "rv %d, errno = %d",
1229 getpid (), func_str, rv, errno_val);
1233 clib_warning ("returning fd %d (0x%x)", getpid (), rv, rv);
1239 * Create two new sockets, of type TYPE in domain DOMAIN and using
1240 * protocol PROTOCOL, which are connected to each other, and put file
1241 * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero,
1242 * one will be chosen automatically.
1243 * Returns 0 on success, -1 for errors.
1246 socketpair (int domain, int type, int protocol, int fds[2])
1248 const char *func_str;
1250 int sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
1252 if ((errno = -ldp_init ()))
1255 if (((domain == AF_INET) || (domain == AF_INET6)) &&
1256 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
1258 func_str = __func__;
1260 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1266 func_str = "libc_socket";
1268 LDBG (1, "calling %s()", func_str);
1270 rv = libc_socketpair (domain, type, protocol, fds);
1277 int errno_val = errno;
1279 clib_warning ("LDP<%d>: ERROR: %s() failed! "
1280 "rv %d, errno = %d",
1281 getpid (), func_str, rv, errno_val);
1285 clib_warning ("LDP<%d>: : returning fd %d (0x%x)", getpid (), rv, rv);
1291 bind (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
1294 u32 sid = ldp_sh_from_fd (fd);
1296 if ((errno = -ldp_init ()))
1299 if (sid != INVALID_SESSION_ID)
1303 switch (addr->sa_family)
1306 if (len != sizeof (struct sockaddr_in))
1309 ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): Invalid "
1310 "AF_INET addr len %u!", getpid (), fd, fd, sid, sid, len);
1315 ep.is_ip4 = VPPCOM_IS_IP4;
1316 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1317 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1321 if (len != sizeof (struct sockaddr_in6))
1324 ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): Invalid "
1325 "AF_INET6 addr len %u!", getpid (), fd, fd, sid, sid, len);
1330 ep.is_ip4 = VPPCOM_IS_IP6;
1331 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1332 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1336 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): "
1337 "Unsupported address family %u!",
1338 getpid (), fd, fd, sid, sid, addr->sa_family);
1339 errno = EAFNOSUPPORT;
1343 LDBG (0, "fd %d (0x%x): calling vppcom_session_bind(): "
1344 "sid %u (0x%x), addr %p, len %u", fd, fd, sid, sid, addr, len);
1346 rv = vppcom_session_bind (sid, &ep);
1347 if (rv != VPPCOM_OK)
1355 LDBG (0, "fd %d (0x%x): calling libc_bind(): addr %p, len %u",
1358 rv = libc_bind (fd, addr, len);
1362 LDBG (1, "fd %d (0x%x): returning %d", fd, fd, rv);
1368 ldp_copy_ep_to_sockaddr (__SOCKADDR_ARG addr, socklen_t * __restrict len,
1369 vppcom_endpt_t * ep)
1372 int sa_len, copy_len;
1374 if ((errno = -ldp_init ()))
1377 if (addr && len && ep)
1379 addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
1380 switch (addr->sa_family)
1383 ((struct sockaddr_in *) addr)->sin_port = ep->port;
1384 if (*len > sizeof (struct sockaddr_in))
1385 *len = sizeof (struct sockaddr_in);
1386 sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
1387 copy_len = *len - sa_len;
1389 memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
1394 ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
1395 if (*len > sizeof (struct sockaddr_in6))
1396 *len = sizeof (struct sockaddr_in6);
1397 sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
1398 copy_len = *len - sa_len;
1400 memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
1401 __in6_u.__u6_addr8, ep->ip, copy_len);
1414 getsockname (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
1417 const char *func_str;
1418 u32 sid = ldp_sh_from_fd (fd);
1420 if ((errno = -ldp_init ()))
1423 if (sid != INVALID_SESSION_ID)
1426 u8 addr_buf[sizeof (struct in6_addr)];
1427 u32 size = sizeof (ep);
1430 func_str = "vppcom_session_attr[GET_LCL_ADDR]";
1433 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1435 getpid (), fd, fd, func_str, sid, sid, addr, len);
1437 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
1438 if (rv != VPPCOM_OK)
1445 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
1446 if (rv != VPPCOM_OK)
1455 func_str = "libc_getsockname";
1458 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1460 getpid (), fd, fd, func_str, addr, len);
1462 rv = libc_getsockname (fd, addr, len);
1469 int errno_val = errno;
1471 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1472 "rv %d, errno = %d", getpid (), fd, fd,
1473 func_str, rv, errno_val);
1477 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1478 getpid (), fd, fd, rv, rv);
1484 connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
1487 u32 sid = ldp_sh_from_fd (fd);
1489 if ((errno = -ldp_init ()))
1494 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): NULL addr, len %u",
1495 getpid (), fd, fd, len);
1501 if (sid != INVALID_SESSION_ID)
1505 switch (addr->sa_family)
1508 if (len != sizeof (struct sockaddr_in))
1511 ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): Invalid "
1512 "AF_INET addr len %u!", getpid (), fd, fd, sid, sid, len);
1517 ep.is_ip4 = VPPCOM_IS_IP4;
1518 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1519 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1523 if (len != sizeof (struct sockaddr_in6))
1526 ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): Invalid "
1527 "AF_INET6 addr len %u!", getpid (), fd, fd, sid, sid, len);
1532 ep.is_ip4 = VPPCOM_IS_IP6;
1533 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1534 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1538 clib_warning ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): "
1539 "Unsupported address family %u!",
1540 getpid (), fd, fd, sid, sid, addr->sa_family);
1541 errno = EAFNOSUPPORT;
1545 LDBG (0, "fd %d (0x%x): calling vppcom_session_connect(): sid %u (0x%x)"
1546 " addr %p len %u", fd, fd, sid, sid, addr, len);
1548 rv = vppcom_session_connect (sid, &ep);
1549 if (rv != VPPCOM_OK)
1557 LDBG (0, "fd %d (0x%x): calling libc_connect(): addr %p, len %u",
1560 rv = libc_connect (fd, addr, len);
1564 LDBG (1, "fd %d (0x%x): returning %d (0x%x)", fd, fd, rv, rv);
1569 getpeername (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
1572 const char *func_str;
1573 u32 sid = ldp_sh_from_fd (fd);
1575 if ((errno = -ldp_init ()))
1578 if (sid != INVALID_SESSION_ID)
1581 u8 addr_buf[sizeof (struct in6_addr)];
1582 u32 size = sizeof (ep);
1585 func_str = "vppcom_session_attr[GET_PEER_ADDR]";
1588 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1590 getpid (), fd, fd, func_str, sid, sid, addr, len);
1592 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size);
1593 if (rv != VPPCOM_OK)
1600 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
1601 if (rv != VPPCOM_OK)
1610 func_str = "libc_getpeername";
1613 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1615 getpid (), fd, fd, func_str, addr, len);
1617 rv = libc_getpeername (fd, addr, len);
1624 int errno_val = errno;
1626 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1627 "rv %d, errno = %d", getpid (), fd, fd,
1628 func_str, rv, errno_val);
1632 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1633 getpid (), fd, fd, rv, rv);
1639 send (int fd, const void *buf, size_t n, int flags)
1642 const char *func_str;
1643 u32 sid = ldp_sh_from_fd (fd);
1645 if ((errno = -ldp_init ()))
1648 if (sid != INVALID_SESSION_ID)
1651 func_str = "vppcom_session_sendto";
1654 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1655 "buf %p, n %u, flags 0x%x",
1656 getpid (), fd, fd, func_str, sid, sid, buf, n, flags);
1658 size = vppcom_session_sendto (sid, (void *) buf, n, flags, NULL);
1659 if (size < VPPCOM_OK)
1667 func_str = "libc_send";
1670 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1671 "buf %p, n %u, flags 0x%x",
1672 getpid (), fd, fd, func_str, buf, n, flags);
1674 size = libc_send (fd, buf, n, flags);
1681 int errno_val = errno;
1683 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1684 "rv %d, errno = %d", getpid (), fd, fd,
1685 func_str, size, errno_val);
1689 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1690 getpid (), fd, fd, size, size);
1696 sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
1698 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
1700 const char *func_str;
1701 u32 sid = ldp_sh_from_fd (out_fd);
1703 if ((errno = -ldp_init ()))
1706 if (sid != INVALID_SESSION_ID)
1709 ssize_t results = 0;
1710 size_t n_bytes_left = len;
1711 size_t bytes_to_read;
1715 u32 flags, flags_len = sizeof (flags);
1717 func_str = "vppcom_session_attr[GET_FLAGS]";
1718 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_FLAGS, &flags,
1720 if (PREDICT_FALSE (rv != VPPCOM_OK))
1722 clib_warning ("LDP<%d>: ERROR: out fd %d (0x%x): %s(): "
1723 "sid %u (0x%x), returned %d (%s)!", getpid (),
1724 out_fd, out_fd, func_str, sid, sid, rv,
1725 vppcom_retval_str (rv));
1727 vec_reset_length (ldpw->io_buffer);
1735 off_t off = lseek (in_fd, *offset, SEEK_SET);
1736 if (PREDICT_FALSE (off == -1))
1740 clib_warning ("LDP<%d>: ERROR: out fd %d (0x%x): %s(): "
1741 "SEEK_SET failed: in_fd %d, offset %p, "
1742 "*offset %ld, rv %ld, errno %d", getpid (),
1743 out_fd, out_fd, in_fd, offset, *offset, off,
1750 ASSERT (off == *offset);
1755 func_str = "vppcom_session_attr[GET_NWRITE]";
1756 size = vppcom_session_attr (sid, VPPCOM_ATTR_GET_NWRITE, 0, 0);
1760 ("LDP<%d>: ERROR: fd %d (0x%x): %s(): sid %u (0x%x), "
1761 "returned %d (%s)!", getpid (), out_fd, out_fd, func_str,
1762 sid, sid, size, vppcom_retval_str (size));
1763 vec_reset_length (ldpw->io_buffer);
1769 bytes_to_read = size;
1772 ("LDP<%d>: fd %d (0x%x): called %s(): sid %u (0x%x), "
1773 "results %ld, n_bytes_left %lu, bytes_to_read %lu", getpid (),
1774 out_fd, out_fd, func_str, sid, sid, results, n_bytes_left,
1777 if (bytes_to_read == 0)
1779 if (flags & O_NONBLOCK)
1784 clib_warning ("LDP<%d>: fd %d (0x%x): sid %u (0x%x): "
1786 getpid (), out_fd, out_fd, sid, sid);
1794 bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
1795 vec_validate (ldpw->io_buffer, bytes_to_read);
1796 nbytes = libc_read (in_fd, ldpw->io_buffer, bytes_to_read);
1799 func_str = "libc_read";
1801 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): in_fd (%d), "
1802 "io_buffer %p, bytes_to_read %lu, rv %d, "
1803 "errno %d", getpid (), out_fd, out_fd, func_str,
1804 in_fd, ldpw->io_buffer, bytes_to_read, nbytes,
1810 vec_reset_length (ldpw->io_buffer);
1816 func_str = "vppcom_session_write";
1819 ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1820 "buf %p, nbytes %u: results %d, n_bytes_left %d", getpid (),
1821 out_fd, out_fd, func_str, sid, sid, ldpw->io_buffer, nbytes,
1822 results, n_bytes_left);
1824 size = vppcom_session_write (sid, ldpw->io_buffer, nbytes);
1827 if (size == VPPCOM_EAGAIN)
1829 if (flags & O_NONBLOCK)
1835 ("LDP<%d>: fd %d (0x%x): sid %u (0x%x): "
1836 "EAGAIN", getpid (), out_fd, out_fd, sid, sid);
1846 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s():"
1847 "sid %u, io_buffer %p, nbytes %u "
1849 getpid (), out_fd, out_fd, func_str,
1850 sid, ldpw->io_buffer, nbytes,
1851 size, vppcom_retval_str (size));
1855 vec_reset_length (ldpw->io_buffer);
1864 ASSERT (n_bytes_left >= nbytes);
1865 n_bytes_left = n_bytes_left - nbytes;
1867 while (n_bytes_left > 0);
1870 vec_reset_length (ldpw->io_buffer);
1873 off_t off = lseek (in_fd, *offset, SEEK_SET);
1874 if (PREDICT_FALSE (off == -1))
1878 clib_warning ("LDP<%d>: ERROR: %s(): SEEK_SET failed: "
1879 "in_fd %d, offset %p, *offset %ld, "
1880 "rv %ld, errno %d", getpid (), in_fd,
1881 offset, *offset, off, errno_val);
1887 ASSERT (off == *offset);
1888 *offset += results + 1;
1900 func_str = "libc_send";
1903 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1904 "in_fd %d, offset %p, len %u",
1905 getpid (), out_fd, out_fd, func_str,
1906 in_fd, offset, len);
1908 size = libc_sendfile (out_fd, in_fd, offset, len);
1916 int errno_val = errno;
1918 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1919 "rv %d, errno = %d", getpid (), out_fd, out_fd,
1920 func_str, size, errno_val);
1924 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1925 getpid (), out_fd, out_fd, size, size);
1931 sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len)
1933 return sendfile (out_fd, in_fd, offset, len);
1937 recv (int fd, void *buf, size_t n, int flags)
1942 if ((errno = -ldp_init ()))
1945 sid = ldp_sh_from_fd (fd);
1946 if (sid != INVALID_SESSION_ID)
1948 LDBG (2, "fd %d (0x%x): calling vcl recvfrom: sid %u (0x%x), buf %p,"
1949 " n %u, flags 0x%x", fd, fd, sid, sid, buf, n, flags);
1951 size = vppcom_session_recvfrom (sid, buf, n, flags, NULL);
1957 LDBG (2, "fd %d (0x%x): calling libc_recvfrom(): buf %p, n %u, "
1958 "flags 0x%x", fd, fd, buf, n, flags);
1960 size = libc_recv (fd, buf, n, flags);
1967 sendto (int fd, const void *buf, size_t n, int flags,
1968 __CONST_SOCKADDR_ARG addr, socklen_t addr_len)
1971 const char *func_str = __func__;
1972 u32 sid = ldp_sh_from_fd (fd);
1974 if ((errno = -ldp_init ()))
1977 if (sid != INVALID_SESSION_ID)
1979 vppcom_endpt_t *ep = 0;
1985 switch (addr->sa_family)
1988 ep->is_ip4 = VPPCOM_IS_IP4;
1990 (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr;
1992 (uint16_t) ((const struct sockaddr_in *) addr)->sin_port;
1996 ep->is_ip4 = VPPCOM_IS_IP6;
1998 (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
2000 (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port;
2004 errno = EAFNOSUPPORT;
2010 func_str = "vppcom_session_sendto";
2013 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2014 "sid %u (0x%x), buf %p, n %u, flags 0x%x, ep %p",
2015 getpid (), fd, fd, func_str, sid, sid, buf, n,
2018 size = vppcom_session_sendto (sid, (void *) buf, n, flags, ep);
2027 func_str = "libc_sendto";
2030 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2031 "buf %p, n %u, flags 0x%x, addr %p, addr_len %d",
2032 getpid (), fd, fd, func_str, buf, n, flags,
2035 size = libc_sendto (fd, buf, n, flags, addr, addr_len);
2043 int errno_val = errno;
2045 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2046 "rv %d, errno = %d", getpid (), fd, fd,
2047 func_str, size, errno_val);
2051 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2052 getpid (), fd, fd, size, size);
2058 recvfrom (int fd, void *__restrict buf, size_t n, int flags,
2059 __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
2062 const char *func_str;
2063 u32 sid = ldp_sh_from_fd (fd);
2065 if ((errno = -ldp_init ()))
2068 if (sid != INVALID_SESSION_ID)
2071 u8 src_addr[sizeof (struct sockaddr_in6)];
2073 func_str = "vppcom_session_recvfrom";
2076 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2077 "sid %u (0x%x), buf %p, n %u, flags 0x%x, ep %p",
2078 getpid (), fd, fd, func_str, sid, sid, buf, n,
2083 size = vppcom_session_recvfrom (sid, buf, n, flags, &ep);
2086 size = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
2089 size = vppcom_session_recvfrom (sid, buf, n, flags, NULL);
2099 func_str = "libc_recvfrom";
2102 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2103 "buf %p, n %u, flags 0x%x, addr %p, addr_len %d",
2104 getpid (), fd, fd, func_str, buf, n, flags,
2107 size = libc_recvfrom (fd, buf, n, flags, addr, addr_len);
2114 int errno_val = errno;
2116 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2117 "rv %d, errno = %d", getpid (), fd, fd,
2118 func_str, size, errno_val);
2122 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2123 getpid (), fd, fd, size, size);
2129 sendmsg (int fd, const struct msghdr * message, int flags)
2132 const char *func_str;
2133 u32 sid = ldp_sh_from_fd (fd);
2135 if ((errno = -ldp_init ()))
2138 if (sid != INVALID_SESSION_ID)
2140 func_str = __func__;
2142 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2148 func_str = "libc_sendmsg";
2151 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2152 "message %p, flags 0x%x",
2153 getpid (), fd, fd, func_str, message, flags);
2155 size = libc_sendmsg (fd, message, flags);
2162 int errno_val = errno;
2164 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2165 "rv %d, errno = %d", getpid (), fd, fd,
2166 func_str, size, errno_val);
2170 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2171 getpid (), fd, fd, size, size);
2178 sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
2181 const char *func_str;
2182 u32 sid = ldp_sh_from_fd (fd);
2184 if ((errno = -ldp_init ()))
2187 if (sid != INVALID_SESSION_ID)
2189 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2195 func_str = "libc_sendmmsg";
2198 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2199 "vmessages %p, vlen %u, flags 0x%x",
2200 getpid (), fd, fd, func_str, vmessages, vlen, flags);
2202 size = libc_sendmmsg (fd, vmessages, vlen, flags);
2209 int errno_val = errno;
2211 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2212 "rv %d, errno = %d", getpid (), fd, fd,
2213 func_str, size, errno_val);
2217 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2218 getpid (), fd, fd, size, size);
2225 recvmsg (int fd, struct msghdr * message, int flags)
2228 const char *func_str;
2229 u32 sid = ldp_sh_from_fd (fd);
2231 if ((errno = -ldp_init ()))
2234 if (sid != INVALID_SESSION_ID)
2236 func_str = __func__;
2238 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2244 func_str = "libc_recvmsg";
2247 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2248 "message %p, flags 0x%x",
2249 getpid (), fd, fd, func_str, message, flags);
2251 size = libc_recvmsg (fd, message, flags);
2258 int errno_val = errno;
2260 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2261 "rv %d, errno = %d", getpid (), fd, fd,
2262 func_str, size, errno_val);
2266 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2267 getpid (), fd, fd, size, size);
2274 recvmmsg (int fd, struct mmsghdr *vmessages,
2275 unsigned int vlen, int flags, struct timespec *tmo)
2278 const char *func_str;
2279 u32 sid = ldp_sh_from_fd (fd);
2281 if ((errno = -ldp_init ()))
2284 if (sid != INVALID_SESSION_ID)
2286 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2292 func_str = "libc_recvmmsg";
2295 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2296 "vmessages %p, vlen %u, flags 0x%x, tmo %p",
2297 getpid (), fd, fd, func_str, vmessages, vlen,
2300 size = libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
2307 int errno_val = errno;
2309 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2310 "rv %d, errno = %d", getpid (), fd, fd,
2311 func_str, size, errno_val);
2315 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2316 getpid (), fd, fd, size, size);
2323 getsockopt (int fd, int level, int optname,
2324 void *__restrict optval, socklen_t * __restrict optlen)
2327 const char *func_str = __func__;
2328 u32 sid = ldp_sh_from_fd (fd);
2329 u32 buflen = optlen ? (u32) * optlen : 0;
2331 if ((errno = -ldp_init ()))
2334 if (sid != INVALID_SESSION_ID)
2344 func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_NODELAY]";
2346 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2348 getpid (), fd, fd, func_str, sid, sid);
2349 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_NODELAY,
2353 func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_USER_MSS]";
2355 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2357 getpid (), fd, fd, func_str, sid, sid);
2358 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_USER_MSS,
2362 func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_KEEPIDLE]";
2364 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2366 getpid (), fd, fd, func_str, sid, sid);
2367 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
2371 func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_KEEPINTVL]";
2373 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2374 "sid %u (0x%x), SOL_TCP",
2375 getpid (), fd, fd, func_str, sid, sid);
2376 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
2380 if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
2383 clib_warning ("LDP<%d>: fd %d (0x%x): sid %u (0x%x), "
2384 "SOL_TCP, TCP_INFO, optval %p, "
2385 "optlen %d: #LDP-NOP#",
2386 getpid (), fd, fd, sid, sid,
2388 memset (optval, 0, *optlen);
2396 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2397 "sid %u (0x%x), SOL_TCP, "
2398 "optname %d unsupported!",
2399 getpid (), fd, fd, func_str, sid, sid, optname);
2407 func_str = "vppcom_session_attr[SOL_IPV6,GET_V6ONLY]";
2409 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2411 getpid (), fd, fd, func_str, sid, sid);
2412 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_V6ONLY,
2417 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2418 "sid %u (0x%x), SOL_IPV6, "
2419 "optname %d unsupported!",
2420 getpid (), fd, fd, func_str, sid, sid, optname);
2428 func_str = "vppcom_session_attr[SOL_SOCKET,GET_ACCEPTCONN]";
2430 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2432 getpid (), fd, fd, func_str, sid, sid);
2433 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LISTEN,
2437 func_str = "vppcom_session_attr[SOL_SOCKET,GET_KEEPALIVE]";
2439 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2441 getpid (), fd, fd, func_str, sid, sid);
2442 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_KEEPALIVE,
2446 func_str = "vppcom_session_attr[SOL_SOCKET,GET_PROTOCOL]";
2448 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2450 getpid (), fd, fd, func_str, sid, sid);
2451 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PROTOCOL,
2453 *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
2456 func_str = "vppcom_session_attr[SOL_SOCKET,GET_TX_FIFO_LEN]";
2458 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2459 "sid %u (0x%x), optlen %d",
2460 getpid (), fd, fd, func_str, sid, sid, buflen);
2461 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TX_FIFO_LEN,
2465 func_str = "vppcom_session_attr[SOL_SOCKET,GET_RX_FIFO_LEN]";
2467 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2468 "sid %u (0x%x), optlen %d",
2469 getpid (), fd, fd, func_str, sid, sid, buflen);
2470 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_RX_FIFO_LEN,
2474 func_str = "vppcom_session_attr[SOL_SOCKET,GET_REUSEADDR]";
2476 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2478 getpid (), fd, fd, func_str, sid, sid);
2479 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_REUSEADDR,
2483 func_str = "vppcom_session_attr[SOL_SOCKET,GET_BROADCAST]";
2485 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2487 getpid (), fd, fd, func_str, sid, sid);
2488 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_BROADCAST,
2492 func_str = "vppcom_session_attr[SOL_SOCKET,GET_ERROR]";
2494 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2496 getpid (), fd, fd, func_str, sid, sid);
2497 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_ERROR,
2502 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2503 "sid %u (0x%x), SOL_SOCKET, "
2504 "optname %d unsupported!",
2505 getpid (), fd, fd, func_str, sid, sid, optname);
2513 if (rv != VPPCOM_OK)
2521 func_str = "libc_getsockopt";
2524 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): level %d, "
2525 "optname %d, optval %p, optlen %d",
2526 getpid (), fd, fd, func_str, level, optname,
2529 rv = libc_getsockopt (fd, level, optname, optval, optlen);
2536 int errno_val = errno;
2538 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2539 "rv %d, errno = %d", getpid (), fd, fd,
2540 func_str, rv, errno_val);
2544 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2545 getpid (), fd, fd, rv, rv);
2551 setsockopt (int fd, int level, int optname,
2552 const void *optval, socklen_t optlen)
2555 const char *func_str = __func__;
2556 u32 sid = ldp_sh_from_fd (fd);
2558 if ((errno = -ldp_init ()))
2561 if (sid != INVALID_SESSION_ID)
2571 func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_NODELAY]";
2573 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2575 getpid (), fd, fd, func_str, sid, sid);
2576 rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_NODELAY,
2577 (void *) optval, &optlen);
2580 func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_USER_MSS]";
2582 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2584 getpid (), fd, fd, func_str, sid, sid);
2585 rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_USER_MSS,
2586 (void *) optval, &optlen);
2589 func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_KEEPIDLE]";
2591 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2593 getpid (), fd, fd, func_str, sid, sid);
2594 rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
2595 (void *) optval, &optlen);
2598 func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_KEEPINTVL]";
2600 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2601 "sid %u (0x%x), SOL_TCP",
2602 getpid (), fd, fd, func_str, sid, sid);
2603 rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
2604 (void *) optval, &optlen);
2608 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2609 "sid %u (0x%x), SOL_TCP, "
2610 "optname %d unsupported!",
2611 getpid (), fd, fd, func_str, sid, sid, optname);
2619 func_str = "vppcom_session_attr[SOL_IPV6,SET_V6ONLY]";
2621 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2623 getpid (), fd, fd, func_str, sid, sid);
2624 rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_V6ONLY,
2625 (void *) optval, &optlen);
2629 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2630 "sid %u (0x%x), SOL_IPV6, "
2631 "optname %d unsupported!",
2632 getpid (), fd, fd, func_str, sid, sid, optname);
2640 func_str = "vppcom_session_attr[SOL_SOCKET,SET_KEEPALIVE]";
2642 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2644 getpid (), fd, fd, func_str, sid, sid);
2645 rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_KEEPALIVE,
2646 (void *) optval, &optlen);
2649 func_str = "vppcom_session_attr[SOL_SOCKET,SET_REUSEADDR]";
2651 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2653 getpid (), fd, fd, func_str, sid, sid);
2654 rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_REUSEADDR,
2655 (void *) optval, &optlen);
2658 func_str = "vppcom_session_attr[SOL_SOCKET,SET_BROADCAST]";
2660 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2662 getpid (), fd, fd, func_str, sid, sid);
2663 rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_BROADCAST,
2664 (void *) optval, &optlen);
2668 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2669 "sid %u (0x%x), SOL_SOCKET, "
2670 "optname %d unsupported!",
2671 getpid (), fd, fd, func_str, sid, sid, optname);
2679 if (rv != VPPCOM_OK)
2687 func_str = "libc_setsockopt";
2690 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): level %d, "
2691 "optname %d, optval %p, optlen %d",
2692 getpid (), fd, fd, func_str, level, optname,
2695 rv = libc_setsockopt (fd, level, optname, optval, optlen);
2702 int errno_val = errno;
2704 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2705 "rv %d, errno = %d", getpid (), fd, fd,
2706 func_str, rv, errno_val);
2710 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2711 getpid (), fd, fd, rv, rv);
2717 listen (int fd, int n)
2720 u32 sid = ldp_sh_from_fd (fd);
2722 if ((errno = -ldp_init ()))
2725 if (sid != INVALID_SESSION_ID)
2727 LDBG (0, "fd %d (0x%x): calling vppcom_session_listen():"
2728 " sid %u (0x%x), n %d", fd, fd, sid, sid, n);
2730 rv = vppcom_session_listen (sid, n);
2731 if (rv != VPPCOM_OK)
2739 LDBG (0, "fd %d (0x%x): calling libc_listen(): n %d", fd, fd, n);
2741 rv = libc_listen (fd, n);
2744 LDBG (1, "fd %d (0x%x): returning %d (0x%x)", fd, fd, rv, rv);
2749 ldp_accept4 (int listen_fd, __SOCKADDR_ARG addr,
2750 socklen_t * __restrict addr_len, int flags)
2756 if ((errno = -ldp_init ()))
2759 listen_sh = ldp_sh_from_fd (listen_fd);
2760 if (listen_sh != INVALID_SESSION_ID)
2763 u8 src_addr[sizeof (struct sockaddr_in6)];
2764 memset (&ep, 0, sizeof (ep));
2767 LDBG (0, "listen fd %d (0x%x): calling vppcom_session_accept:"
2768 " listen sid %u (0x%x), ep %p, flags 0x%x", listen_fd,
2769 listen_fd, listen_sh, listen_sh, ep, flags);
2771 accept_sh = vppcom_session_accept (listen_sh, &ep, flags);
2779 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
2780 if (rv != VPPCOM_OK)
2782 (void) vppcom_session_close ((u32) accept_sh);
2788 rv = ldp_fd_alloc ((u32) accept_sh);
2791 (void) vppcom_session_close ((u32) accept_sh);
2800 LDBG (0, "listen fd %d (0x%x): calling libc_accept4(): "
2801 "addr %p, addr_len %p, flags 0x%x", listen_fd,
2802 listen_fd, addr, addr_len, flags);
2804 rv = libc_accept4 (listen_fd, addr, addr_len, flags);
2807 LDBG (1, "listen fd %d (0x%x): returning %d (0x%x)", listen_fd, listen_fd,
2814 accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
2817 return ldp_accept4 (fd, addr, addr_len, flags);
2821 accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
2823 return ldp_accept4 (fd, addr, addr_len, 0);
2827 shutdown (int fd, int how)
2831 if ((errno = -ldp_init ()))
2834 if (ldp_fd_is_sh (fd))
2836 u32 fd_index = fd - ldp->sh_bit_val;
2837 ldp_fd_entry_t *fde;
2839 fde = ldp_fd_entry_lock (fd_index);
2847 fde->flags |= LDP_F_SHUT_RD;
2848 else if (how == SHUT_WR)
2849 fde->flags |= LDP_F_SHUT_WR;
2850 else if (how == SHUT_RDWR)
2851 fde->flags |= (LDP_F_SHUT_RD | LDP_F_SHUT_WR);
2853 if ((fde->flags & LDP_F_SHUT_RD) && (fde->flags & LDP_F_SHUT_WR))
2856 ldp_fd_entry_unlock (fde);
2857 LDBG (0, "fd %d (0x%x): calling vcl shutdown: how %d", fd, fd, how);
2861 LDBG (1, "fd %d (0x%x): calling libc_shutdown: how %d", fd, fd, how);
2862 rv = libc_shutdown (fd, how);
2869 epoll_create1 (int flags)
2871 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
2872 const char *func_str;
2875 if ((errno = -ldp_init ()))
2878 if (ldp->vcl_needs_real_epoll)
2880 rv = libc_epoll_create1 (flags);
2881 ldp->vcl_needs_real_epoll = 0;
2882 ldpw->vcl_mq_epfd = rv;
2883 LDBG (0, "created vcl epfd %u", rv);
2886 func_str = "vppcom_epoll_create";
2888 LDBG (1, "calling %s()", func_str);
2890 rv = vppcom_epoll_create ();
2892 if (PREDICT_FALSE (rv < 0))
2898 rv = ldp_fd_alloc ((u32) rv);
2904 int errno_val = errno;
2906 clib_warning ("LDP<%d>: ERROR: %s() failed! "
2907 "rv %d, errno = %d",
2908 getpid (), func_str, rv, errno_val);
2912 clib_warning ("LDP<%d>: returning epfd %d (0x%x)", getpid (), rv, rv);
2918 epoll_create (int size)
2920 return epoll_create1 (0);
2924 epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
2926 u32 vep_idx = ldp_sh_from_fd (epfd), sid;
2927 const char *func_str;
2930 if ((errno = -ldp_init ()))
2933 if (PREDICT_FALSE (vep_idx == INVALID_SESSION_ID))
2935 /* The LDP epoll_create1 always creates VCL epfd's.
2936 * The app should never have a kernel base epoll fd unless it
2937 * was acquired outside of the LD_PRELOAD process context.
2938 * In any case, if we get one, punt it to libc_epoll_ctl.
2940 func_str = "libc_epoll_ctl";
2942 LDBG (1, "epfd %d (0x%x): calling %s(): op %d, fd %d (0x%x),"
2943 " event %p", epfd, epfd, func_str, op, fd, fd, event);
2945 rv = libc_epoll_ctl (epfd, op, fd, event);
2949 sid = ldp_sh_from_fd (fd);
2951 LDBG (0, "epfd %d (0x%x), vep_idx %d (0x%x), sid %d (0x%x)",
2952 epfd, epfd, vep_idx, vep_idx, sid, sid);
2954 if (sid != INVALID_SESSION_ID)
2956 func_str = "vppcom_epoll_ctl";
2958 LDBG (1, "epfd %d (0x%x): calling %s(): vep_idx %d (0x%x),"
2959 " op %d, sid %u (0x%x), event %p", epfd, epfd,
2960 func_str, vep_idx, vep_idx, sid, sid, event);
2962 rv = vppcom_epoll_ctl (vep_idx, op, sid, event);
2963 if (rv != VPPCOM_OK)
2972 u32 size = sizeof (epfd);
2974 func_str = "vppcom_session_attr[GET_LIBC_EPFD]";
2975 libc_epfd = vppcom_session_attr (vep_idx, VPPCOM_ATTR_GET_LIBC_EPFD, 0,
2977 LDBG (1, "epfd %d (0x%x), vep_idx %d (0x%x): %s() "
2978 "returned libc_epfd %d (0x%x)", epfd, epfd,
2979 vep_idx, vep_idx, func_str, libc_epfd, libc_epfd);
2983 func_str = "libc_epoll_create1";
2985 LDBG (1, "epfd %d (0x%x), vep_idx %d (0x%x): "
2986 "calling %s(): EPOLL_CLOEXEC", epfd, epfd,
2987 vep_idx, vep_idx, func_str);
2989 libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
2996 func_str = "vppcom_session_attr[SET_LIBC_EPFD]";
2997 LDBG (1, "epfd %d (0x%x): calling %s(): vep_idx %d (0x%x),"
2998 " VPPCOM_ATTR_SET_LIBC_EPFD, libc_epfd %d (0x%x), size %d",
2999 epfd, epfd, func_str, vep_idx, vep_idx, libc_epfd,
3002 rv = vppcom_session_attr (vep_idx, VPPCOM_ATTR_SET_LIBC_EPFD,
3011 else if (PREDICT_FALSE (libc_epfd < 0))
3018 func_str = "libc_epoll_ctl";
3020 LDBG (1, "epfd %d (0x%x): calling %s(): libc_epfd %d (0x%x), "
3021 "op %d, fd %d (0x%x), event %p", epfd, epfd, func_str,
3022 libc_epfd, libc_epfd, op, fd, fd, event);
3024 rv = libc_epoll_ctl (libc_epfd, op, fd, event);
3032 int errno_val = errno;
3034 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
3035 "rv %d, errno = %d", getpid (), fd, fd,
3036 func_str, rv, errno_val);
3040 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
3041 getpid (), fd, fd, rv, rv);
3047 ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
3048 int timeout, const sigset_t * sigmask)
3050 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
3051 double time_to_wait = (double) 0, time_out, now = 0;
3052 u32 vep_idx = ldp_sh_from_fd (epfd);
3053 int libc_epfd, rv = 0;
3055 if ((errno = -ldp_init ()))
3058 if (PREDICT_FALSE (!events || (timeout < -1)))
3064 if (epfd == ldpw->vcl_mq_epfd)
3065 return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
3067 if (PREDICT_FALSE (vep_idx == INVALID_SESSION_ID))
3069 LDBG (0, "epfd %d (0x%x): bad vep_idx %d (0x%x)!", epfd, epfd, vep_idx,
3075 time_to_wait = ((timeout >= 0) ? (double) timeout / 1000 : 0);
3076 time_out = clib_time_now (&ldpw->clib_time) + time_to_wait;
3078 libc_epfd = vppcom_session_attr (vep_idx, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
3079 if (PREDICT_FALSE (libc_epfd < 0))
3086 LDBG (2, "epfd %d (0x%x): vep_idx %d (0x%x), libc_epfd %d (0x%x), "
3087 "events %p, maxevents %d, timeout %d, sigmask %p: time_to_wait %.02f",
3088 epfd, epfd, vep_idx, vep_idx, libc_epfd, libc_epfd, events,
3089 maxevents, timeout, sigmask, time_to_wait, time_out);
3092 if (!ldpw->epoll_wait_vcl)
3094 LDBG (3, "epfd %d (0x%x): calling vcl_epoll_wait: vep_idx %d (0x%x)"
3095 " events %p, maxevents %d", epfd, epfd, vep_idx, vep_idx,
3098 rv = vppcom_epoll_wait (vep_idx, events, maxevents, 0);
3101 ldpw->epoll_wait_vcl = 1;
3112 ldpw->epoll_wait_vcl = 0;
3116 LDBG (3, "epfd %d (0x%x): calling libc_epoll_wait: libc_epfd %d "
3117 "(0x%x), events %p, maxevents %d, sigmask %p", epfd, epfd,
3118 libc_epfd, libc_epfd, events, maxevents, sigmask);
3120 rv = libc_epoll_pwait (libc_epfd, events, maxevents, 0, sigmask);
3126 now = clib_time_now (&ldpw->clib_time);
3128 while (now < time_out);
3135 epoll_pwait (int epfd, struct epoll_event *events,
3136 int maxevents, int timeout, const sigset_t * sigmask)
3138 return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
3142 epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
3144 return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL);
3148 poll (struct pollfd *fds, nfds_t nfds, int timeout)
3150 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
3151 const char *func_str = __func__;
3152 int rv, i, n_revents = 0;
3155 double wait_for_time;
3157 LDBG (3, "fds %p, nfds %d, timeout %d", fds, nfds, timeout);
3160 wait_for_time = (f64) timeout / 1000;
3164 for (i = 0; i < nfds; i++)
3169 LDBG (3, "fds[%d] fd %d (0x%0x) events = 0x%x revents = 0x%x",
3170 i, fds[i].fd, fds[i].fd, fds[i].events, fds[i].revents);
3172 sid = ldp_sh_from_fd (fds[i].fd);
3173 if (sid != INVALID_SESSION_ID)
3175 fds[i].fd = -fds[i].fd;
3176 vec_add2 (ldpw->vcl_poll, vp, 1);
3179 vp->events = fds[i].events;
3180 #ifdef __USE_XOPEN2K
3181 if (fds[i].events & POLLRDNORM)
3182 vp->events |= POLLIN;
3183 if (fds[i].events & POLLWRNORM)
3184 vp->events |= POLLOUT;
3186 vp->revents = fds[i].revents;
3190 vec_add1 (ldpw->libc_poll, fds[i]);
3191 vec_add1 (ldpw->libc_poll_idxs, i);
3197 if (vec_len (ldpw->vcl_poll))
3199 func_str = "vppcom_poll";
3201 LDBG (3, "calling %s(): vcl_poll %p, n_sids %u (0x%x): "
3202 "n_libc_fds %u", func_str, ldpw->vcl_poll,
3203 vec_len (ldpw->vcl_poll), vec_len (ldpw->vcl_poll),
3204 vec_len (ldpw->libc_poll));
3206 rv = vppcom_poll (ldpw->vcl_poll, vec_len (ldpw->vcl_poll), 0);
3217 if (vec_len (ldpw->libc_poll))
3219 func_str = "libc_poll";
3221 LDBG (3, "calling %s(): fds %p, nfds %u: n_sids %u",
3222 fds, nfds, vec_len (ldpw->vcl_poll));
3224 rv = libc_poll (ldpw->libc_poll, vec_len (ldpw->libc_poll), 0);
3237 while ((wait_for_time == -1) ||
3238 (clib_time_now (&ldpw->clib_time) < wait_for_time));
3242 vec_foreach (vp, ldpw->vcl_poll)
3244 fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
3245 fds[vp->fds_ndx].revents = vp->revents;
3246 #ifdef __USE_XOPEN2K
3247 if ((fds[vp->fds_ndx].revents & POLLIN) &&
3248 (fds[vp->fds_ndx].events & POLLRDNORM))
3249 fds[vp->fds_ndx].revents |= POLLRDNORM;
3250 if ((fds[vp->fds_ndx].revents & POLLOUT) &&
3251 (fds[vp->fds_ndx].events & POLLWRNORM))
3252 fds[vp->fds_ndx].revents |= POLLWRNORM;
3255 vec_reset_length (ldpw->vcl_poll);
3257 for (i = 0; i < vec_len (ldpw->libc_poll); i++)
3259 fds[ldpw->libc_poll_idxs[i]].revents = ldpw->libc_poll[i].revents;
3261 vec_reset_length (ldpw->libc_poll_idxs);
3262 vec_reset_length (ldpw->libc_poll);
3268 int errno_val = errno;
3270 clib_warning ("LDP<%d>: ERROR: %s() failed! "
3271 "rv %d, errno = %d", getpid (),
3272 func_str, rv, errno_val);
3277 clib_warning ("LDP<%d>: returning %d (0x%x): n_sids %u, "
3278 "n_libc_fds %d", getpid (), rv, rv,
3279 vec_len (ldpw->vcl_poll), vec_len (ldpw->libc_poll));
3281 for (i = 0; i < nfds; i++)
3286 clib_warning ("LDP<%d>: fds[%d].fd %d (0x%0x), "
3287 ".events = 0x%x, .revents = 0x%x",
3288 getpid (), i, fds[i].fd, fds[i].fd,
3289 fds[i].events, fds[i].revents);
3300 ppoll (struct pollfd *fds, nfds_t nfds,
3301 const struct timespec *timeout, const sigset_t * sigmask)
3303 if ((errno = -ldp_init ()))
3306 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
3314 void CONSTRUCTOR_ATTRIBUTE ldp_constructor (void);
3316 void DESTRUCTOR_ATTRIBUTE ldp_destructor (void);
3319 * This function is called when the library is loaded
3322 ldp_constructor (void)
3324 swrap_constructor ();
3325 if (ldp_init () != 0)
3326 fprintf (stderr, "\nLDP<%d>: ERROR: ldp_constructor: failed!\n",
3328 else if (LDP_DEBUG > 0)
3329 clib_warning ("LDP<%d>: LDP constructor: done!\n", getpid ());
3333 * This function is called when the library is unloaded
3336 ldp_destructor (void)
3338 swrap_destructor ();
3342 /* Don't use clib_warning() here because that calls writev()
3343 * which will call ldp_init().
3346 printf ("%s:%d: LDP<%d>: LDP destructor: done!\n",
3347 __func__, __LINE__, getpid ());
3352 * fd.io coding-style-patch-verification: ON
3355 * eval: (c-set-style "gnu")