aboutsummaryrefslogtreecommitdiffstats
path: root/src/vcl/vcom.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vcl/vcom.c')
-rw-r--r--src/vcl/vcom.c5266
1 files changed, 2693 insertions, 2573 deletions
diff --git a/src/vcl/vcom.c b/src/vcl/vcom.c
index 4f8435f41bf..7c163112ba1 100644
--- a/src/vcl/vcom.c
+++ b/src/vcl/vcom.c
@@ -20,21 +20,15 @@
#include <time.h>
#include <stdarg.h>
#include <sys/resource.h>
+#include <netinet/tcp.h>
#include <vcl/vcom_socket_wrapper.h>
#include <vcl/vcom.h>
#include <sys/time.h>
#include <vcl/vppcom.h>
-#include <vcl/vcom_socket.h>
-
-/* GCC have printf type attribute check. */
-#ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
-#define PRINTF_ATTRIBUTE(a,b) \
- __attribute__ ((__format__ (__printf__, a, b)))
-#else
-#define PRINTF_ATTRIBUTE(a,b)
-#endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
+#include <vppinfra/time.h>
+#include <vppinfra/bitmap.h>
#define HAVE_CONSTRUCTOR_ATTRIBUTE
#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
@@ -52,3230 +46,3351 @@
#define DESTRUCTOR_ATTRIBUTE
#endif
-#define HAVE_ADDRESS_SANITIZER_ATTRIBUTE
-#ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
-#define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE \
- __attribute__((no_sanitize_address))
-#else
-#define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
-#endif
-
-#define VCOM_SOCKET_FD_MAX 0x10000
-
-static char vcom_app_name[MAX_VCOM_APP_NAME];
+typedef struct
+{
+ int init;
+ char app_name[VCOM_APP_NAME_MAX];
+ u32 sid_bit_val;
+ u32 sid_bit_mask;
+ u32 debug;
+ u8 *io_buffer;
+ clib_time_t clib_time;
+ clib_bitmap_t *rd_bitmap;
+ clib_bitmap_t *wr_bitmap;
+ clib_bitmap_t *ex_bitmap;
+ clib_bitmap_t *sid_rd_bitmap;
+ clib_bitmap_t *sid_wr_bitmap;
+ clib_bitmap_t *sid_ex_bitmap;
+ clib_bitmap_t *libc_rd_bitmap;
+ clib_bitmap_t *libc_wr_bitmap;
+ clib_bitmap_t *libc_ex_bitmap;
+ vcl_poll_t *vcl_poll;
+ u8 select_vcl;
+ u8 epoll_wait_vcl;
+} vcom_main_t;
+#define VCOM_DEBUG vcom->debug
+
+static vcom_main_t vcom_main = {
+ .sid_bit_val = (1 << VCOM_SID_BIT_MIN),
+ .sid_bit_mask = (1 << VCOM_SID_BIT_MIN) - 1,
+ .debug = VCOM_DEBUG_INIT,
+};
+
+static vcom_main_t *vcom = &vcom_main;
/*
* RETURN: 0 on success or -1 on error.
* */
-int
-vcom_set_app_name (char *__app_name)
+static inline void
+vcom_set_app_name (char *app_name)
{
- return snprintf (vcom_app_name, MAX_VCOM_APP_NAME, "vcom-%s-%d",
- __app_name, getpid ()) < 0 ? -1 : 0;
+ int rv = snprintf (vcom->app_name, VCOM_APP_NAME_MAX,
+ "vcom-%d-%s", getpid (), app_name);
+
+ if (rv >= VCOM_APP_NAME_MAX)
+ app_name[VCOM_APP_NAME_MAX - 1] = 0;
}
-static char *
+static inline char *
vcom_get_app_name ()
{
- if (vcom_app_name[0] == '\0')
- {
- snprintf (vcom_app_name, MAX_VCOM_APP_NAME, "vcom-app-%d", getpid ());
- }
- return vcom_app_name;
-}
+ if (vcom->app_name[0] == '\0')
+ vcom_set_app_name ("app");
-/*
- * 1 if init, 0 otherwise
- */
-static int is_vcom_init;
-
-/*
- * TBD: Make it thread safe
- */
+ return vcom->app_name;
+}
-/*
- * constructor function called before main is called
- * RETURN: 0 on success -1 on failure
- * */
static inline int
-vcom_init (void)
+vcom_fd_from_sid (u32 sid)
{
- pid_t pid = getpid ();
- int rv;
-
- if (!is_vcom_init)
- {
- rv = vppcom_app_create (vcom_get_app_name ());
- if (rv)
- {
- printf ("\n[%d] vcom_init...failed!\n", pid);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] vcom_init: vppcom_app_create failed!\n", pid);
- return rv;
- }
- if (vcom_socket_main_init () != 0)
- {
- printf ("\n[%d] vcom_init...failed!\n", pid);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] vcom_init: vcom_socket_main_init failed!\n", pid);
- return -1;
- }
-
- is_vcom_init = 1;
- printf ("\n[%d] vcom_init...done!\n", pid);
- }
- return 0;
+ if (PREDICT_FALSE (sid >= vcom->sid_bit_val))
+ return -EMFILE;
+ else
+ return (sid | vcom->sid_bit_val);
}
-static inline void
-vcom_destroy (void)
+static inline int
+vcom_fd_is_sid (int fd)
{
- pid_t pid = getpid ();
-
- if (is_vcom_init)
- {
- vcom_socket_main_destroy ();
- vppcom_app_destroy ();
- is_vcom_init = 0;
- fprintf (stderr, "\n[%d] vcom_destroy...done!\n", pid);
- }
+ return ((u32) fd & vcom->sid_bit_val) ? 1 : 0;
}
-static inline int
-is_vcom_socket_fd (int fd)
+static inline u32
+vcom_sid_from_fd (int fd)
{
- return vcom_socket_is_vcom_fd (fd);
+ return (vcom_fd_is_sid (fd) ? ((u32) fd & vcom->sid_bit_mask) :
+ INVALID_SESSION_ID);
}
static inline int
-is_vcom_epfd (int epfd)
+vcom_init (void)
{
- return vcom_socket_is_vcom_epfd (epfd);
-}
+ int rv = 0;
+ if (PREDICT_FALSE (!vcom->init))
+ {
+ vcom->init = 1;
+ rv = vppcom_app_create (vcom_get_app_name ());
+ if (rv == VPPCOM_OK)
+ {
+ char *env_var_str = getenv (VCOM_ENV_DEBUG);
+ if (env_var_str)
+ {
+ u32 tmp;
+ if (sscanf (env_var_str, "%u", &tmp) != 1)
+ clib_warning ("LDP<%d>: WARNING: Invalid VCOM debug level "
+ "specified in the env var " VCOM_ENV_DEBUG
+ " (%s)!", getpid (), env_var_str);
+ else
+ {
+ vcom->debug = tmp;
+ clib_warning ("LDP<%d>: configured VCOM debug level (%u) "
+ "from the env var " VCOM_ENV_DEBUG "!",
+ getpid (), vcom->debug);
+ }
+ }
-/*
- *
- * Generic glibc fd api
- *
- */
+ env_var_str = getenv (VCOM_ENV_APP_NAME);
+ if (env_var_str)
+ {
+ vcom_set_app_name (env_var_str);
+ clib_warning ("LDP<%d>: configured VCOM app name (%s) "
+ "from the env var " VCOM_ENV_APP_NAME "!",
+ getpid (), vcom->app_name);
+ }
-/* Close the file descriptor FD.
+ env_var_str = getenv (VCOM_ENV_SID_BIT);
+ if (env_var_str)
+ {
+ u32 sb;
+ if (sscanf (env_var_str, "%u", &sb) != 1)
+ {
+ clib_warning ("LDP<%d>: WARNING: Invalid VCOM sid bit "
+ "specified in the env var "
+ VCOM_ENV_SID_BIT " (%s)!"
+ "sid bit value %d (0x%x)",
+ getpid (), env_var_str,
+ vcom->sid_bit_val, vcom->sid_bit_val);
+ }
+ else if (sb < VCOM_SID_BIT_MIN)
+ {
+ vcom->sid_bit_val = (1 << VCOM_SID_BIT_MIN);
+ vcom->sid_bit_mask = vcom->sid_bit_val - 1;
+
+ clib_warning ("LDP<%d>: WARNING: VCOM sid bit (%u) "
+ "specified in the env var "
+ VCOM_ENV_SID_BIT " (%s) is too small. "
+ "Using VCOM_SID_BIT_MIN (%d)! "
+ "sid bit value %d (0x%x)",
+ getpid (), sb, env_var_str, VCOM_SID_BIT_MIN,
+ vcom->sid_bit_val, vcom->sid_bit_val);
+ }
+ else if (sb > VCOM_SID_BIT_MAX)
+ {
+ vcom->sid_bit_val = (1 << VCOM_SID_BIT_MAX);
+ vcom->sid_bit_mask = vcom->sid_bit_val - 1;
+
+ clib_warning ("LDP<%d>: WARNING: VCOM sid bit (%u) "
+ "specified in the env var "
+ VCOM_ENV_SID_BIT " (%s) is too big. "
+ "Using VCOM_SID_BIT_MAX (%d)! "
+ "sid bit value %d (0x%x)",
+ getpid (), sb, env_var_str, VCOM_SID_BIT_MAX,
+ vcom->sid_bit_val, vcom->sid_bit_val);
+ }
+ else
+ {
+ vcom->sid_bit_val = (1 << sb);
+ vcom->sid_bit_mask = vcom->sid_bit_val - 1;
- This function is a cancellation point and therefore
- not marked with __THROW. */
-/*
- * PRE: is_vcom_socket_fd(__fd) == 1
- * RETURN: 0 on success and -1 for errors.
- * */
-int
-vcom_close (int __fd)
-{
- if (vcom_init () != 0)
- {
- return -1;
- }
+ clib_warning ("LDP<%d>: configured VCOM sid bit (%u) "
+ "from " VCOM_ENV_SID_BIT
+ "! sid bit value %d (0x%x)", getpid (),
+ sb, vcom->sid_bit_val, vcom->sid_bit_val);
+ }
+ }
- if (vcom_socket_close (__fd) != 0)
- {
- return -1;
+ clib_time_init (&vcom->clib_time);
+ clib_warning ("LDP<%d>: VCOM initialization: done!", getpid ());
+ }
+ else
+ {
+ fprintf (stderr, "\nLDP<%d>: ERROR: vcom_init: vppcom_app_create()"
+ " failed! rv = %d (%s)\n",
+ getpid (), rv, vppcom_retval_str (rv));
+ vcom->init = 0;
+ }
}
-
- return 0;
+ return rv;
}
-/*
- * RETURN: 0 on success, or -1 on error
- */
int
-close (int __fd)
+close (int fd)
{
int rv;
- pid_t pid = getpid ();
+ const char *func_str;
+ u32 sid = vcom_sid_from_fd (fd);
+
+ if ((errno = -vcom_init ()))
+ return -1;
- if (is_vcom_socket_fd (__fd) || is_vcom_epfd (__fd))
+ if (sid != INVALID_SESSION_ID)
{
+ int epfd;
+
+ func_str = "vppcom_session_attr[GET_LIBC_EPFD]";
+ epfd = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
+ if (epfd > 0)
+ {
+ func_str = "libc_close";
+
+ if (VCOM_DEBUG > 0)
+ clib_warning
+ ("LDP<%d>: fd %d (0x%x): calling %s(): epfd %u (0x%x)",
+ getpid (), fd, fd, func_str, epfd, epfd);
+
+ rv = libc_close (epfd);
+ if (rv < 0)
+ {
+ u32 size = sizeof (epfd);
+ epfd = 0;
+
+ (void) vppcom_session_attr (sid, VPPCOM_ATTR_SET_LIBC_EPFD,
+ &epfd, &size);
+ }
+ }
+ else if (PREDICT_FALSE (epfd < 0))
+ {
+ errno = -epfd;
+ rv = -1;
+ goto done;
+ }
+
+ func_str = "vppcom_session_close";
+
if (VCOM_DEBUG > 0)
- fprintf (stderr, "[%d] close: fd %d\n", pid, __fd);
- rv = vcom_close (__fd);
- if (VCOM_DEBUG > 0)
- fprintf (stderr, "[%d] close: vcom_close() returned %d\n", pid, rv);
- if (rv != 0)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x)",
+ getpid (), fd, fd, func_str, sid, sid);
+
+ rv = vppcom_session_close (sid);
+ if (rv != VPPCOM_OK)
{
errno = -rv;
- return -1;
+ rv = -1;
}
- return 0;
}
- return libc_close (__fd);
-}
+ else
+ {
+ func_str = "libc_close";
-/* Read NBYTES into BUF from FD. Return the
- number read, -1 for errors or 0 for EOF.
+ if (VCOM_DEBUG > 0)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s()",
+ getpid (), fd, fd, func_str);
- This function is a cancellation point and therefore
- not marked with __THROW. */
-ssize_t
-vcom_read (int __fd, void *__buf, size_t __nbytes)
-{
- if (vcom_init () != 0)
- {
- return -1;
+ rv = libc_close (fd);
}
- return vcom_socket_read (__fd, __buf, __nbytes);
+done:
+ if (VCOM_DEBUG > 0)
+ {
+ if (rv < 0)
+ {
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, rv, errno_val);
+ errno = errno_val;
+ }
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, rv, rv);
+ }
+ return rv;
}
ssize_t
-read (int __fd, void *__buf, size_t __nbytes)
+read (int fd, void *buf, size_t nbytes)
{
- ssize_t size = 0;
- pid_t pid = getpid ();
- pthread_t tid = pthread_self ();
+ ssize_t size;
+ const char *func_str;
+ u32 sid = vcom_sid_from_fd (fd);
+
+ if ((errno = -vcom_init ()))
+ return -1;
- if (is_vcom_socket_fd (__fd))
+ if (sid != INVALID_SESSION_ID)
{
+ func_str = "vppcom_session_read";
+
if (VCOM_DEBUG > 2)
- fprintf (stderr,
- "[%d][%lu (0x%lx)] read:1 "
- "'%04d'='%04d', '%p', '%04d'\n",
- pid, (unsigned long) tid, (unsigned long) tid,
- (int) size, __fd, __buf, (int) __nbytes);
- size = vcom_read (__fd, __buf, __nbytes);
- if (VCOM_DEBUG > 2)
- fprintf (stderr,
- "[%d][%lu (0x%lx)] read:2 "
- "'%04d'='%04d', '%p', '%04d'\n",
- pid, (unsigned long) tid, (unsigned long) tid,
- (int) size, __fd, __buf, (int) __nbytes);
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x), buf %p, nbytes %u", getpid (),
+ fd, fd, func_str, sid, sid, buf, nbytes);
+
+ size = vppcom_session_read (sid, buf, nbytes);
if (size < 0)
{
errno = -size;
- return -1;
+ size = -1;
}
- return size;
}
- return libc_read (__fd, __buf, __nbytes);
-}
-
-ssize_t
-vcom_readv (int __fd, const struct iovec * __iov, int __iovcnt)
-{
- if (vcom_init () != 0)
+ else
{
- return -1;
+ func_str = "libc_read";
+
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "buf %p, nbytes %u", getpid (),
+ fd, fd, func_str, buf, nbytes);
+
+ size = libc_read (fd, buf, nbytes);
}
- return vcom_socket_readv (__fd, __iov, __iovcnt);
+ if (VCOM_DEBUG > 2)
+ {
+ if (size < 0)
+ {
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, size, errno_val);
+ errno = errno_val;
+ }
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, size, size);
+ }
+ return size;
}
ssize_t
-readv (int __fd, const struct iovec * __iov, int __iovcnt)
+readv (int fd, const struct iovec * iov, int iovcnt)
{
+ const char *func_str;
ssize_t size = 0;
+ u32 sid = vcom_sid_from_fd (fd);
+ int rv, i, total = 0;
+
+ if ((errno = -vcom_init ()))
+ return -1;
- if (is_vcom_socket_fd (__fd))
+ if (sid != INVALID_SESSION_ID)
{
- size = vcom_readv (__fd, __iov, __iovcnt);
- if (size < 0)
+ func_str = "vppcom_session_read";
+ do
{
- errno = -size;
- return -1;
+ for (i = 0; i < iovcnt; ++i)
+ {
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s() [%d]: "
+ "sid %u (0x%x), iov %p, iovcnt %d, total %d",
+ getpid (), fd, fd, func_str, i, sid, sid,
+ iov, iovcnt, total);
+
+ rv = vppcom_session_read (sid, iov[i].iov_base, iov[i].iov_len);
+ if (rv < 0)
+ break;
+ else
+ {
+ total += rv;
+ if (rv < iov[i].iov_len)
+ {
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): "
+ "rv (%d) < iov[%d].iov_len (%d)",
+ getpid (), fd, fd, rv, i,
+ iov[i].iov_len);
+ break;
+ }
+ }
+ }
+ }
+ while ((rv >= 0) && (total == 0));
+
+ if (rv < 0)
+ {
+ errno = -rv;
+ size = -1;
}
- return size;
+ else
+ size = total;
}
else
- return libc_readv (__fd, __iov, __iovcnt);
-}
+ {
+ func_str = "libc_readv";
-/* Write N bytes of BUF to FD. Return the number written, or -1.
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "iov %p, iovcnt %d", getpid (), fd, fd, iov, iovcnt);
- This function is a cancellation point and therefore
- not marked with __THROW. */
-ssize_t
-vcom_write (int __fd, const void *__buf, size_t __n)
-{
- if (vcom_init () != 0)
- {
- return -1;
+ size = libc_readv (fd, iov, iovcnt);
}
- return vcom_socket_write (__fd, (void *) __buf, __n);
+ if (VCOM_DEBUG > 2)
+ {
+ if (size < 0)
+ {
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, size, errno_val);
+ errno = errno_val;
+ }
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, size, size);
+ }
+ return size;
}
ssize_t
-write (int __fd, const void *__buf, size_t __n)
+write (int fd, const void *buf, size_t nbytes)
{
+ const char *func_str;
ssize_t size = 0;
- pid_t pid = getpid ();
- pthread_t tid = pthread_self ();
+ u32 sid = vcom_sid_from_fd (fd);
+
+ if ((errno = -vcom_init ()))
+ return -1;
- if (is_vcom_socket_fd (__fd))
+ if (sid != INVALID_SESSION_ID)
{
+ func_str = "vppcom_session_write";
+
if (VCOM_DEBUG > 2)
- fprintf (stderr,
- "[%d][%lu (0x%lx)] write:1 "
- "'%04d'='%04d', '%p', '%04d'\n",
- pid, (unsigned long) tid, (unsigned long) tid,
- (int) size, __fd, __buf, (int) __n);
- size = vcom_write (__fd, __buf, __n);
- if (VCOM_DEBUG > 2)
- fprintf (stderr,
- "[%d][%lu (0x%lx)] write:2 "
- "'%04d'='%04d', '%p', '%04d'\n",
- pid, (unsigned long) tid, (unsigned long) tid,
- (int) size, __fd, __buf, (int) __n);
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x), buf %p, nbytes %u", getpid (),
+ fd, fd, func_str, sid, sid, buf, nbytes);
+
+ size = vppcom_session_write (sid, (void *) buf, nbytes);
if (size < 0)
{
errno = -size;
- return -1;
+ size = -1;
}
- return size;
}
- return libc_write (__fd, __buf, __n);
-}
-
-ssize_t
-vcom_writev (int __fd, const struct iovec * __iov, int __iovcnt)
-{
- if (vcom_init () != 0)
+ else
{
- return -1;
- }
+ func_str = "libc_write";
- return vcom_socket_writev (__fd, __iov, __iovcnt);
-}
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "buf %p, nbytes %u", getpid (),
+ fd, fd, func_str, buf, nbytes);
-ssize_t
-writev (int __fd, const struct iovec * __iov, int __iovcnt)
-{
- ssize_t size = 0;
+ size = libc_write (fd, buf, nbytes);
+ }
- if (is_vcom_socket_fd (__fd))
+ if (VCOM_DEBUG > 2)
{
- size = vcom_writev (__fd, __iov, __iovcnt);
if (size < 0)
{
- errno = -size;
- return -1;
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, size, errno_val);
+ errno = errno_val;
}
- return size;
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, size, size);
}
- else
- return libc_writev (__fd, __iov, __iovcnt);
+ return size;
}
-/* Do the file control operation described by CMD on FD.
- The remaining arguments are interpreted depending on CMD.
-
- This function is a cancellation point and therefore
- not marked with __THROW. */
-int
-vcom_fcntl_va (int __fd, int __cmd, va_list __ap)
+ssize_t
+writev (int fd, const struct iovec * iov, int iovcnt)
{
- if (vcom_init () != 0)
+ const char *func_str;
+ ssize_t size = 0, total = 0;
+ u32 sid = vcom_sid_from_fd (fd);
+ int rv, i;
+
+ /*
+ * Use [f]printf() instead of clib_warning() to prevent recursion SIGSEGV.
+ */
+
+ if ((errno = -vcom_init ()))
+ return -1;
+
+ if (sid != INVALID_SESSION_ID)
{
- return -1;
+ func_str = "vppcom_session_write";
+ do
+ {
+ for (i = 0; i < iovcnt; ++i)
+ {
+ if (VCOM_DEBUG > 4)
+ printf ("%s:%d: LDP<%d>: fd %d (0x%x): calling %s() [%d]: "
+ "sid %u (0x%x), buf %p, nbytes %ld, total %ld",
+ __func__, __LINE__, getpid (), fd, fd, func_str,
+ i, sid, sid, iov[i].iov_base, iov[i].iov_len, total);
+
+ rv = vppcom_session_write (sid, iov[i].iov_base,
+ iov[i].iov_len);
+ if (rv < 0)
+ break;
+ else
+ {
+ total += rv;
+ if (rv < iov[i].iov_len)
+ {
+ if (VCOM_DEBUG > 4)
+ printf ("%s:%d: LDP<%d>: fd %d (0x%x): "
+ "rv (%d) < iov[%d].iov_len (%ld)",
+ __func__, __LINE__, getpid (), fd, fd,
+ rv, i, iov[i].iov_len);
+ break;
+ }
+ }
+ }
+ }
+ while ((rv >= 0) && (total == 0));
+
+ if (rv < 0)
+ {
+ errno = -rv;
+ size = -1;
+ }
+ else
+ size = total;
}
+ else
+ {
+ func_str = "libc_writev";
- return vcom_socket_fcntl_va (__fd, __cmd, __ap);
-}
+ if (VCOM_DEBUG > 4)
+ printf ("%s:%d: LDP<%d>: fd %d (0x%x): calling %s(): "
+ "iov %p, iovcnt %d\n", __func__, __LINE__, getpid (),
+ fd, fd, func_str, iov, iovcnt);
-int
-vcom_fcntl (int __fd, int __cmd, ...)
-{
- int rv = -1;
- va_list ap;
+ size = libc_writev (fd, iov, iovcnt);
+ }
- if (is_vcom_socket_fd (__fd))
+ if (VCOM_DEBUG > 4)
{
- va_start (ap, __cmd);
- rv = vcom_fcntl_va (__fd, __cmd, ap);
- va_end (ap);
+ if (size < 0)
+ {
+ int errno_val = errno;
+ perror (func_str);
+ fprintf (stderr,
+ "%s:%d: LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %ld, errno = %d\n", __func__, __LINE__, getpid (), fd,
+ fd, func_str, size, errno_val);
+ errno = errno_val;
+ }
+ else
+ printf ("%s:%d: LDP<%d>: fd %d (0x%x): returning %ld\n",
+ __func__, __LINE__, getpid (), fd, fd, size);
}
- return rv;
+ return size;
}
int
-fcntl (int __fd, int __cmd, ...)
+fcntl (int fd, int cmd, ...)
{
- int rv;
+ const char *func_str = __func__;
+ int rv = 0;
va_list ap;
- pid_t pid = getpid ();
+ u32 sid = vcom_sid_from_fd (fd);
+
+ if ((errno = -vcom_init ()))
+ return -1;
- va_start (ap, __cmd);
- if (is_vcom_socket_fd (__fd))
+ va_start (ap, cmd);
+ if (sid != INVALID_SESSION_ID)
{
- rv = vcom_fcntl_va (__fd, __cmd, ap);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] fcntl: "
- "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __cmd);
+ int flags = va_arg (ap, int);
+ u32 size;
+
+ size = sizeof (flags);
+ rv = -EOPNOTSUPP;
+ switch (cmd)
+ {
+ case F_SETFL:
+ func_str = "vppcom_session_attr[SET_FLAGS]";
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x) flags %d (0x%x), size %d",
+ getpid (), fd, fd, func_str, sid, sid,
+ flags, flags, size);
+
+ rv =
+ vppcom_session_attr (sid, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
+ break;
+
+ case F_GETFL:
+ func_str = "vppcom_session_attr[GET_FLAGS]";
+ if (VCOM_DEBUG > 2)
+ clib_warning
+ ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
+ "flags %d (0x%x), size %d", getpid (), fd, fd, func_str, sid,
+ sid, flags, flags, size);
+
+ rv =
+ vppcom_session_attr (sid, VPPCOM_ATTR_GET_FLAGS, &flags, &size);
+ if (rv == VPPCOM_OK)
+ {
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x), cmd %d (F_GETFL): "
+ "%s() returned flags %d (0x%x)",
+ getpid (), fd, fd, cmd, func_str, flags, flags);
+ rv = flags;
+ }
+ break;
+
+ default:
+ rv = -EOPNOTSUPP;
+ break;
+ }
if (rv < 0)
{
errno = -rv;
rv = -1;
}
- goto out;
}
- rv = libc_vfcntl (__fd, __cmd, ap);
+ else
+ {
+ func_str = "libc_vfcntl";
-out:
- va_end (ap);
- return rv;
-}
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): cmd %d",
+ getpid (), fd, fd, func_str, cmd);
-int
-vcom_ioctl_va (int __fd, unsigned long int __cmd, va_list __ap)
-{
- if (vcom_init () != 0)
- {
- return -1;
+ rv = libc_vfcntl (fd, cmd, ap);
}
- return vcom_socket_ioctl_va (__fd, __cmd, __ap);
-}
-
-int
-vcom_ioctl (int __fd, unsigned long int __cmd, ...)
-{
- int rv = -1;
- va_list ap;
+ va_end (ap);
- if (is_vcom_socket_fd (__fd))
+ if (VCOM_DEBUG > 2)
{
- va_start (ap, __cmd);
- rv = vcom_ioctl_va (__fd, __cmd, ap);
- va_end (ap);
+ if (rv < 0)
+ {
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, rv, errno_val);
+ errno = errno_val;
+ }
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, rv, rv);
}
return rv;
}
int
-ioctl (int __fd, unsigned long int __cmd, ...)
+ioctl (int fd, unsigned long int cmd, ...)
{
+ const char *func_str;
int rv;
va_list ap;
- pid_t pid = getpid ();
+ u32 sid = vcom_sid_from_fd (fd);
+
+ if ((errno = -vcom_init ()))
+ return -1;
- va_start (ap, __cmd);
- if (is_vcom_socket_fd (__fd))
+ va_start (ap, cmd);
+ if (sid != INVALID_SESSION_ID)
{
- rv = vcom_ioctl_va (__fd, __cmd, ap);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] ioctl: "
- "'%04d'='%04d', '%04ld'\n", pid, rv, __fd, __cmd);
+ func_str = "vppcom_session_attr[GET_NREAD]";
+
+ switch (cmd)
+ {
+ case FIONREAD:
+ if (VCOM_DEBUG > 2)
+ clib_warning
+ ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x)",
+ getpid (), fd, fd, func_str, sid, sid);
+
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_NREAD, 0, 0);
+ break;
+
+ case FIONBIO:
+ {
+ u32 flags = va_arg (ap, int) ? O_NONBLOCK : 0;
+ u32 size = sizeof (flags);
+
+ /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than
+ * non-blocking, the flags should be read here and merged
+ * with O_NONBLOCK.
+ */
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x), flags %d (0x%x), size %d",
+ getpid (), fd, fd, func_str, sid, sid,
+ flags, flags, size);
+
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_FLAGS, &flags,
+ &size);
+ }
+ break;
+
+ default:
+ rv = -EOPNOTSUPP;
+ break;
+ }
if (rv < 0)
{
errno = -rv;
rv = -1;
}
- goto out;
}
- rv = libc_vioctl (__fd, __cmd, ap);
-
-out:
- va_end (ap);
- return rv;
-}
-
-/*
- * Check the first NFDS descriptors each in READFDS (if not NULL) for
- * read readiness, in WRITEFDS (if not NULL) for write readiness,
- * and in EXCEPTFDS (if not NULL) for exceptional conditions.
- * If TIMEOUT is not NULL, time out after waiting the interval
- * specified therein. Returns the number of ready descriptors,
- * or -1 for errors.
- *
- * This function is a cancellation point and therefore not marked
- * with __THROW.
- * */
-
-/*
- * clear all vcom FDs from fd_sets __readfds, __writefds and
- * __exceptfds and update the new nfds
- *
- * new nfds is the highest-numbered file descriptor
- * in any of the three sets, plus 1
- *
- * Return the number of file descriptors contained in the
- * three descriptor sets. ie. the total number of the bits
- * that are set in __readfds, __writefds and __exceptfds
- */
-static inline int
-vcom_fd_clear (int __nfds,
- int *__new_nfds,
- fd_set * __restrict __readfds,
- fd_set * __restrict __writefds,
- fd_set * __restrict __exceptfds)
-{
- int fd;
- /* invalid max_fd is -1 */
- int max_fd = -1;
- int nfd = 0;
-
-
- /* clear all vcom fd from the sets */
- for (fd = 0; fd < __nfds; fd++)
+ else
{
+ func_str = "libc_vioctl";
- /* clear vcom fd from set */
- /*
- * F fd set
- */
-#define _(F) \
- if ((F) && FD_ISSET (fd, (F))) \
- { \
- if (is_vcom_socket_fd (fd)) \
- { \
- FD_CLR (fd, (F)); \
- } \
- }
-
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): cmd %d",
+ getpid (), fd, fd, func_str, cmd);
- _(__readfds);
- _(__writefds);
- _(__exceptfds);
-#undef _
+ rv = libc_vioctl (fd, cmd, ap);
}
- /*
- * compute nfd and __new_nfds
- */
- for (fd = 0; fd < __nfds; fd++)
+ if (VCOM_DEBUG > 2)
{
-
- /*
- * F fd set
- */
-#define _(F) \
- if ((F) && FD_ISSET (fd, (F))) \
- { \
- if (fd > max_fd) \
- { \
- max_fd = fd; \
- } \
- ++nfd; \
- }
-
-
- _(__readfds);
- _(__writefds);
- _(__exceptfds);
-#undef _
+ if (rv < 0)
+ {
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, rv, errno_val);
+ errno = errno_val;
+ }
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, rv, rv);
}
-
- *__new_nfds = max_fd != -1 ? max_fd + 1 : 0;
- return nfd;
+ va_end (ap);
+ return rv;
}
-/*
- * Return the number of file descriptors contained in the
- * three descriptor sets. ie. the total number of the bits
- * that are set in __readfds, __writefds and __exceptfds
- */
-static inline int
-vcom_fd_set (int __nfds,
- /* dest */
- int *__new_nfds,
- fd_set * __restrict __readfds,
- fd_set * __restrict __writefds, fd_set * __restrict __exceptfds,
- /* src */
- fd_set * __restrict __saved_readfds,
- fd_set * __restrict __saved_writefds,
- fd_set * __restrict __saved_exceptfds)
+int
+vcom_pselect (int nfds, fd_set * __restrict readfds,
+ fd_set * __restrict writefds,
+ fd_set * __restrict exceptfds,
+ const struct timespec *__restrict timeout,
+ const __sigset_t * __restrict sigmask)
{
+ int rv;
+ char *func_str = "##";
+ f64 time_out;
int fd;
- /* invalid max_fd is -1 */
- int max_fd = -1;
- int nfd = 0;
+ uword sid_bits, sid_bits_set, libc_bits, libc_bits_set;
+ u32 minbits = clib_max (nfds, BITS (uword));
+ u32 sid;
- for (fd = 0; fd < __nfds; fd++)
+ if (nfds < 0)
{
- /*
- * F fd set
- * S saved fd set
- */
-#define _(S,F) \
- if ((F) && (S) && FD_ISSET (fd, (S))) \
- { \
- if (is_vcom_socket_fd (fd)) \
- { \
- FD_SET (fd, (F)); \
- } \
- }
-
-
- _(__saved_readfds, __readfds);
- _(__saved_writefds, __writefds);
-#undef _
+ errno = EINVAL;
+ return -1;
}
-
- /*
- * compute nfd and __new_nfds
- */
- for (fd = 0; fd < __nfds; fd++)
+ if (nfds <= vcom->sid_bit_val)
{
+ func_str = "libc_pselect";
- /*
- * F fd set
- */
-#define _(F) \
- if ((F) && FD_ISSET (fd, (F))) \
- { \
- if (fd > max_fd) \
- { \
- max_fd = fd; \
- } \
- ++nfd; \
- }
+ if (VCOM_DEBUG > 3)
+ clib_warning
+ ("LDP<%d>: calling %s(): nfds %d, readfds %p, writefds %p, "
+ "exceptfds %p, timeout %p, sigmask %p", getpid (), func_str, nfds,
+ readfds, writefds, exceptfds, timeout, sigmask);
-
- _(__readfds);
- _(__writefds);
- _(__exceptfds);
-#undef _
+ rv = libc_pselect (nfds, readfds, writefds, exceptfds,
+ timeout, sigmask);
+ goto done;
}
- *__new_nfds = max_fd != -1 ? max_fd + 1 : 0;
- return nfd;
-}
-
-/*
- * split select sets(src) into
- * vcom sets(dest1) and libc sets(dest2)
- */
-static inline void
-vcom_fd_set_split (
- /* src, select sets */
- int nfds,
- fd_set * __restrict readfds,
- fd_set * __restrict writefds,
- fd_set * __restrict exceptfds,
- /* dest1, vcom sets */
- int *vcom_nfds,
- fd_set * __restrict vcom_readfds,
- fd_set * __restrict vcom_writefds,
- fd_set * __restrict vcom_exceptfds, int *vcom_nfd,
- /* dest2, libc sets */
- int *libc_nfds,
- fd_set * __restrict libc_readfds,
- fd_set * __restrict libc_writefds,
- fd_set * __restrict libc_exceptfds, int *libc_nfd)
-{
- int fd;
-
- /* vcom */
- /* invalid max_fd is -1 */
- int vcom_max_fd = -1;
- int vcom_nfd2 = 0;
-
- /* libc */
- /* invalid max_fd is -1 */
- int libc_max_fd = -1;
- int libc_nfd2 = 0;
-
-
- for (fd = 0; fd < nfds; fd++)
- {
- /*
- * S select fd set
- * V vcom fd set
- * L libc fd set
- */
-#define _(S,V,L) \
- if ((S) && FD_ISSET (fd, (S))) \
- { \
- if (is_vcom_socket_fd (fd)) \
- { \
- if ((V)) \
- { \
- FD_SET(fd, (V)); \
- if (fd > vcom_max_fd) \
- { \
- vcom_max_fd = fd; \
- } \
- ++vcom_nfd2; \
- } \
- } \
- else \
- { \
- if ((L)) \
- { \
- FD_SET(fd, (L)); \
- if (fd > libc_max_fd) \
- { \
- libc_max_fd = fd; \
- } \
- ++libc_nfd2; \
- } \
- } \
- }
-
-
- _(readfds, vcom_readfds, libc_readfds);
- _(writefds, vcom_writefds, libc_writefds);
- _(exceptfds, vcom_exceptfds, libc_exceptfds);
-#undef _
- }
-
- if (vcom_nfds)
- *vcom_nfds = vcom_max_fd != -1 ? vcom_max_fd + 1 : 0;
- if (vcom_nfd)
- *vcom_nfd = vcom_nfd2;
- if (libc_nfds)
- *libc_nfds = libc_max_fd != -1 ? libc_max_fd + 1 : 0;
- if (libc_nfd)
- *libc_nfd = libc_nfd2;
-}
-
-/*
- * merge vcom sets(src1) and libc sets(src2)
- * into select sets(dest)
- */
-static inline void
-vcom_fd_set_merge (
- /* dest, select sets */
- int *nfds,
- fd_set * __restrict readfds,
- fd_set * __restrict writefds,
- fd_set * __restrict exceptfds, int *nfd,
- /* src1, vcom sets */
- int vcom_nfds,
- fd_set * __restrict vcom_readfds,
- fd_set * __restrict vcom_writefds,
- fd_set * __restrict vcom_exceptfds, int vcom_nfd,
- /* src2, libc sets */
- int libc_nfds,
- fd_set * __restrict libc_readfds,
- fd_set * __restrict libc_writefds,
- fd_set * __restrict libc_exceptfds, int libc_nfd)
-{
- int fd;
- /* invalid max_fd is -1 */
- int max_fd = -1;
- int nfd2 = 0;
-
-
- /* FD_BIT_OR
- *
- * dest |= src at current bit index
- * update MAX and NFD of dest fd set
- *
- *
- * FS source fd set
- * FD dest fd set
- * BI bit index
- * MAX current max_fd of dest fd sets
- * NFD current nfd of dest fd sets
- * N nfds of source fd set
- */
-#define FD_BIT_OR(FD,FS,BI, \
- MAX,NFD) \
- if ((FS) && (FD) && FD_ISSET ((BI), (FS))) \
- { \
- FD_SET ((BI), (FD)); \
- if ((BI) > (MAX)) \
- { \
- (MAX) = (BI); \
- } \
- ++(NFD); \
+ if (PREDICT_FALSE (vcom->sid_bit_val > FD_SETSIZE / 2))
+ {
+ clib_warning ("LDP<%d>: ERROR: VCOM sid bit value %d (0x%x) > "
+ "FD_SETSIZE/2 %d (0x%x)!", getpid (),
+ vcom->sid_bit_val, vcom->sid_bit_val,
+ FD_SETSIZE / 2, FD_SETSIZE / 2);
+ errno = EOVERFLOW;
+ return -1;
}
+ if (timeout)
+ {
+ time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ?
+ (f64) 0 : (f64) timeout->tv_sec +
+ (f64) timeout->tv_nsec / (f64) 1000000000 +
+ (f64) (timeout->tv_nsec % 1000000000) / (f64) 1000000000;
- /* FD_RWE_SET_OR */
- /*
- * SR,SW,SE source RWE fd sets
- * DR,DW,DE dest RWE fd sets
- * BI bit index
- * NFDS nfds of source fd sets
- * MAX current max_fd of dest fd sets
- * NFD current nfd of dest fd sets
- */
-#define FD_RWE_SETS_OR(DR,DW,DE, \
- SR,SW,SE, \
- BI,NFDS, \
- MAX,NFD) \
- do \
- { \
- for ((BI) = 0; (BI) < (NFDS); (BI)++) \
- { \
- FD_BIT_OR((DR), (SR), (BI), (MAX), (NFD)); \
- FD_BIT_OR((DW), (SW), (BI), (MAX), (NFD)); \
- FD_BIT_OR((DE), (SE), (BI), (MAX), (NFD)); \
- } \
- } \
- while (0);
-
-
- /* source(vcom) to dest(select) rwe fd sets */
- FD_RWE_SETS_OR (readfds, writefds, exceptfds,
- vcom_readfds, vcom_writefds, vcom_exceptfds,
- fd, vcom_nfds, max_fd, nfd2);
-
- /* source(libc) to dest(select) rwe fd sets */
- FD_RWE_SETS_OR (readfds, writefds, exceptfds,
- libc_readfds, libc_writefds, libc_exceptfds,
- fd, libc_nfds, max_fd, nfd2);
-
-#undef FD_RWE_SETS_OR
-#undef FD_BIT_OR
-
- if (nfds)
- *nfds = max_fd != -1 ? max_fd + 1 : 0;
- if (nfd)
- *nfd = nfd2;
-}
-
-/*
- * RETURN 1 if fds is NULL or empty. 0 otherwise
- */
-static inline int
-fd_set_iszero (fd_set * __restrict fds)
-{
- int fd;
+ /* select as fine grained sleep */
+ if (!nfds)
+ {
+ if (VCOM_DEBUG > 3)
+ clib_warning ("LDP<%d>: sleeping for %f seconds",
+ getpid (), time_out);
- /* NULL fds */
- if (!fds)
- return 1;
+ time_out += clib_time_now (&vcom->clib_time);
+ while (clib_time_now (&vcom->clib_time) < time_out)
+ ;
+ return 0;
+ }
+ }
+ else if (!nfds)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ else
+ time_out = -1;
+
+ sid_bits = libc_bits = 0;
+ if (readfds)
+ {
+ clib_bitmap_validate (vcom->sid_rd_bitmap, minbits);
+ clib_bitmap_validate (vcom->libc_rd_bitmap, minbits);
+ clib_bitmap_validate (vcom->rd_bitmap, minbits);
+ clib_memcpy (vcom->rd_bitmap, readfds,
+ vec_len (vcom->rd_bitmap) * sizeof (clib_bitmap_t));
+ FD_ZERO (readfds);
+
+ /* *INDENT-OFF* */
+ clib_bitmap_foreach (fd, vcom->rd_bitmap,
+ ({
+ sid = vcom_sid_from_fd (fd);
+ if (VCOM_DEBUG > 3)
+ clib_warning ("LDP<%d>: readfds: fd %d (0x%x), sid %u (0x%x)",
+ getpid (), fd, fd, sid, sid);
+ if (sid == INVALID_SESSION_ID)
+ clib_bitmap_set_no_check (vcom->libc_rd_bitmap, fd, 1);
+ else
+ clib_bitmap_set_no_check (vcom->sid_rd_bitmap, sid, 1);
+ }));
+ /* *INDENT-ON* */
+
+ sid_bits_set = clib_bitmap_last_set (vcom->sid_rd_bitmap) + 1;
+ sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits;
+
+ libc_bits_set = clib_bitmap_last_set (vcom->libc_rd_bitmap) + 1;
+ libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits;
+
+ if (VCOM_DEBUG > 3)
+ clib_warning ("LDP<%d>: readfds: sid_bits_set %d, sid_bits %d, "
+ "libc_bits_set %d, libc_bits %d", getpid (),
+ sid_bits_set, sid_bits, libc_bits_set, libc_bits);
+ }
+ if (writefds)
+ {
+ clib_bitmap_validate (vcom->sid_wr_bitmap, minbits);
+ clib_bitmap_validate (vcom->libc_wr_bitmap, minbits);
+ clib_bitmap_validate (vcom->wr_bitmap, minbits);
+ clib_memcpy (vcom->wr_bitmap, writefds,
+ vec_len (vcom->wr_bitmap) * sizeof (clib_bitmap_t));
+ FD_ZERO (writefds);
+
+ /* *INDENT-OFF* */
+ clib_bitmap_foreach (fd, vcom->wr_bitmap,
+ ({
+ sid = vcom_sid_from_fd (fd);
+ if (VCOM_DEBUG > 3)
+ clib_warning ("LDP<%d>: writefds: fd %d (0x%x), sid %u (0x%x)",
+ getpid (), fd, fd, sid, sid);
+ if (sid == INVALID_SESSION_ID)
+ clib_bitmap_set_no_check (vcom->libc_wr_bitmap, fd, 1);
+ else
+ clib_bitmap_set_no_check (vcom->sid_wr_bitmap, sid, 1);
+ }));
+ /* *INDENT-ON* */
+
+ sid_bits_set = clib_bitmap_last_set (vcom->sid_wr_bitmap) + 1;
+ sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits;
+
+ libc_bits_set = clib_bitmap_last_set (vcom->libc_wr_bitmap) + 1;
+ libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits;
+
+ if (VCOM_DEBUG > 3)
+ clib_warning ("LDP<%d>: writefds: sid_bits_set %d, sid_bits %d, "
+ "libc_bits_set %d, libc_bits %d", getpid (),
+ sid_bits_set, sid_bits, libc_bits_set, libc_bits);
+ }
+ if (exceptfds)
+ {
+ clib_bitmap_validate (vcom->sid_ex_bitmap, minbits);
+ clib_bitmap_validate (vcom->libc_ex_bitmap, minbits);
+ clib_bitmap_validate (vcom->ex_bitmap, minbits);
+ clib_memcpy (vcom->ex_bitmap, exceptfds,
+ vec_len (vcom->ex_bitmap) * sizeof (clib_bitmap_t));
+ FD_ZERO (exceptfds);
+
+ /* *INDENT-OFF* */
+ clib_bitmap_foreach (fd, vcom->ex_bitmap,
+ ({
+ sid = vcom_sid_from_fd (fd);
+ if (VCOM_DEBUG > 3)
+ clib_warning ("LDP<%d>: exceptfds: fd %d (0x%x), sid %u (0x%x)",
+ getpid (), fd, fd, sid, sid);
+ if (sid == INVALID_SESSION_ID)
+ clib_bitmap_set_no_check (vcom->libc_ex_bitmap, fd, 1);
+ else
+ clib_bitmap_set_no_check (vcom->sid_ex_bitmap, sid, 1);
+ }));
+ /* *INDENT-ON* */
+
+ sid_bits_set = clib_bitmap_last_set (vcom->sid_ex_bitmap) + 1;
+ sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits;
+
+ libc_bits_set = clib_bitmap_last_set (vcom->libc_ex_bitmap) + 1;
+ libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits;
+
+ if (VCOM_DEBUG > 3)
+ clib_warning ("LDP<%d>: exceptfds: sid_bits_set %d, sid_bits %d, "
+ "libc_bits_set %d, libc_bits %d", getpid (),
+ sid_bits_set, sid_bits, libc_bits_set, libc_bits);
+ }
+
+ if (PREDICT_FALSE (!sid_bits && !libc_bits))
+ {
+ errno = EINVAL;
+ rv = -1;
+ goto done;
+ }
- for (fd = 0; fd < FD_SETSIZE; fd++)
+ do
{
- if (FD_ISSET (fd, fds))
+ if (sid_bits)
{
- /* non-empty fds */
- return 0;
+ if (!vcom->select_vcl)
+ {
+ func_str = "vppcom_select";
+
+ if (readfds)
+ clib_memcpy (vcom->rd_bitmap, vcom->sid_rd_bitmap,
+ vec_len (vcom->rd_bitmap) *
+ sizeof (clib_bitmap_t));
+ if (writefds)
+ clib_memcpy (vcom->wr_bitmap, vcom->sid_wr_bitmap,
+ vec_len (vcom->wr_bitmap) *
+ sizeof (clib_bitmap_t));
+ if (exceptfds)
+ clib_memcpy (vcom->ex_bitmap, vcom->sid_ex_bitmap,
+ vec_len (vcom->ex_bitmap) *
+ sizeof (clib_bitmap_t));
+
+ rv = vppcom_select (sid_bits,
+ readfds ? vcom->rd_bitmap : NULL,
+ writefds ? vcom->wr_bitmap : NULL,
+ exceptfds ? vcom->ex_bitmap : NULL, 0);
+ if (rv < 0)
+ {
+ errno = -rv;
+ rv = -1;
+ }
+ else if (rv > 0)
+ {
+ if (readfds)
+ {
+ /* *INDENT-OFF* */
+ clib_bitmap_foreach (sid, vcom->rd_bitmap,
+ ({
+ fd = vcom_fd_from_sid (sid);
+ if (PREDICT_FALSE (fd < 0))
+ {
+ errno = EBADFD;
+ rv = -1;
+ goto done;
+ }
+ FD_SET (fd, readfds);
+ }));
+ /* *INDENT-ON* */
+ }
+ if (writefds)
+ {
+ /* *INDENT-OFF* */
+ clib_bitmap_foreach (sid, vcom->wr_bitmap,
+ ({
+ fd = vcom_fd_from_sid (sid);
+ if (PREDICT_FALSE (fd < 0))
+ {
+ errno = EBADFD;
+ rv = -1;
+ goto done;
+ }
+ FD_SET (fd, writefds);
+ }));
+ /* *INDENT-ON* */
+ }
+ if (exceptfds)
+ {
+ /* *INDENT-OFF* */
+ clib_bitmap_foreach (sid, vcom->ex_bitmap,
+ ({
+ fd = vcom_fd_from_sid (sid);
+ if (PREDICT_FALSE (fd < 0))
+ {
+ errno = EBADFD;
+ rv = -1;
+ goto done;
+ }
+ FD_SET (fd, exceptfds);
+ }));
+ /* *INDENT-ON* */
+ }
+ vcom->select_vcl = 1;
+ goto done;
+ }
+ }
+ else
+ vcom->select_vcl = 0;
+ }
+ if (libc_bits)
+ {
+ struct timespec tspec;
+
+ func_str = "libc_pselect";
+
+ if (readfds)
+ clib_memcpy (readfds, vcom->libc_rd_bitmap,
+ vec_len (vcom->rd_bitmap) * sizeof (clib_bitmap_t));
+ if (writefds)
+ clib_memcpy (writefds, vcom->libc_wr_bitmap,
+ vec_len (vcom->wr_bitmap) * sizeof (clib_bitmap_t));
+ if (exceptfds)
+ clib_memcpy (exceptfds, vcom->libc_ex_bitmap,
+ vec_len (vcom->ex_bitmap) * sizeof (clib_bitmap_t));
+ tspec.tv_sec = tspec.tv_nsec = 0;
+ rv = libc_pselect (libc_bits,
+ readfds ? readfds : NULL,
+ writefds ? writefds : NULL,
+ exceptfds ? exceptfds : NULL, &tspec, sigmask);
+ if (rv != 0)
+ goto done;
}
}
- /* empty fds */
- return 1;
-}
-
-
-/*
- * ################
- * kernel time64.h
- * ################
- * */
-typedef long int s64;
-typedef unsigned long int u64;
-
-typedef long long int __s64;
-typedef unsigned long long int __u64;
-
-typedef __s64 time64_t;
-typedef __u64 timeu64_t;
-
-/* Parameters used to convert the timespec values: */
-#define MSEC_PER_SEC 1000L
-#define USEC_PER_MSEC 1000L
-#define NSEC_PER_USEC 1000L
-#define NSEC_PER_MSEC 1000000L
-#define USEC_PER_SEC 1000000L
-#define NSEC_PER_SEC 1000000000L
-#define FSEC_PER_SEC 1000000000000000LL
-
-
-/*
- * ################
- * kernel time.h
- * ################
- * */
-
-
-#define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
-
-#ifdef VCOM_USE_TIMESPEC_EQUAL
-static inline int
-timespec_equal (const struct timespec *a, const struct timespec *b)
-{
- return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
-}
-#endif
-
-/*
- * lhs < rhs: return <0
- * lhs == rhs: return 0
- * lhs > rhs: return >0
- */
-static inline int
-timespec_compare (const struct timespec *lhs, const struct timespec *rhs)
-{
- if (lhs->tv_sec < rhs->tv_sec)
- return -1;
- if (lhs->tv_sec > rhs->tv_sec)
- return 1;
- return lhs->tv_nsec - rhs->tv_nsec;
-}
-
-#ifdef VCOM_USE_TIMEVAL_COMPARE
-static inline int
-timeval_compare (const struct timeval *lhs, const struct timeval *rhs)
-{
- if (lhs->tv_sec < rhs->tv_sec)
- return -1;
- if (lhs->tv_sec > rhs->tv_sec)
- return 1;
- return lhs->tv_usec - rhs->tv_usec;
-}
-#endif
+ while ((time_out == -1) || (clib_time_now (&vcom->clib_time) < time_out));
+ rv = 0;
-extern void set_normalized_timespec (struct timespec *ts, time_t sec,
- s64 nsec);
+done:
+ /* TBD: set timeout to amount of time left */
+ vec_reset_length (vcom->rd_bitmap);
+ vec_reset_length (vcom->sid_rd_bitmap);
+ vec_reset_length (vcom->libc_rd_bitmap);
+ vec_reset_length (vcom->wr_bitmap);
+ vec_reset_length (vcom->sid_wr_bitmap);
+ vec_reset_length (vcom->libc_wr_bitmap);
+ vec_reset_length (vcom->ex_bitmap);
+ vec_reset_length (vcom->sid_ex_bitmap);
+ vec_reset_length (vcom->libc_ex_bitmap);
-static inline struct timespec
-timespec_add (struct timespec lhs, struct timespec rhs)
-{
- struct timespec ts_delta;
- set_normalized_timespec (&ts_delta, lhs.tv_sec + rhs.tv_sec,
- lhs.tv_nsec + rhs.tv_nsec);
- return ts_delta;
+ if (VCOM_DEBUG > 3)
+ {
+ if (rv < 0)
+ {
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: %s() failed! "
+ "rv %d, errno = %d", getpid (),
+ func_str, rv, errno_val);
+ errno = errno_val;
+ }
+ else
+ clib_warning ("LDP<%d>: returning %d (0x%x)", getpid (), rv, rv);
+ }
+ return rv;
}
-/*
- * sub = lhs - rhs, in normalized form
- */
-static inline struct timespec
-timespec_sub (struct timespec lhs, struct timespec rhs)
+int
+select (int nfds, fd_set * __restrict readfds,
+ fd_set * __restrict writefds,
+ fd_set * __restrict exceptfds, struct timeval *__restrict timeout)
{
- struct timespec ts_delta;
- set_normalized_timespec (&ts_delta, lhs.tv_sec - rhs.tv_sec,
- lhs.tv_nsec - rhs.tv_nsec);
- return ts_delta;
-}
+ struct timespec tspec;
-/*
- * ################
- * kernel time.c
- * ################
- * */
-
-
-/**
- * set_normalized_timespec - set timespec sec and nsec parts and normalize
- *
- * @ts: pointer to timespec variable to be set
- * @sec: seconds to set
- * @nsec: nanoseconds to set
- *
- * Set seconds and nanoseconds field of a timespec variable and
- * normalize to the timespec storage format
- *
- * Note: The tv_nsec part is always in the range of
- * 0 <= tv_nsec < NSEC_PER_SEC
- * For negative values only the tv_sec field is negative !
- */
-void
-set_normalized_timespec (struct timespec *ts, time_t sec, s64 nsec)
-{
- while (nsec >= NSEC_PER_SEC)
- {
- /*
- * The following asm() prevents the compiler from
- * optimising this loop into a modulo operation. See
- * also __iter_div_u64_rem() in include/linux/time.h
- */
- asm ("":"+rm" (nsec));
- nsec -= NSEC_PER_SEC;
- ++sec;
- }
- while (nsec < 0)
+ if (timeout)
{
- asm ("":"+rm" (nsec));
- nsec += NSEC_PER_SEC;
- --sec;
+ tspec.tv_sec = timeout->tv_sec;
+ tspec.tv_nsec = timeout->tv_usec * 1000;
}
- ts->tv_sec = sec;
- ts->tv_nsec = nsec;
+ return vcom_pselect (nfds, readfds, writefds, exceptfds,
+ timeout ? &tspec : NULL, NULL);
}
-#define vcom_timerisvalid(tvp) (!((tvp)->tv_sec < 0 || (tvp)->tv_usec < 0))
-
-/* Macros for converting between `struct timeval' and `struct timespec'. */
-#define VCOM_TIMEVAL_TO_TIMESPEC(tv, ts) { \
- (ts)->tv_sec = (tv)->tv_sec; \
- (ts)->tv_nsec = (tv)->tv_usec * 1000; \
-}
-#define VCOM_TIMESPEC_TO_TIMEVAL(tv, ts) { \
- (tv)->tv_sec = (ts)->tv_sec; \
- (tv)->tv_usec = (ts)->tv_nsec / 1000; \
-}
-
-static inline int
-vcom_select_impl (int vcom_nfds, fd_set * __restrict vcom_readfds,
- fd_set * __restrict vcom_writefds,
- fd_set * __restrict vcom_exceptfds,
- struct timeval *__restrict timeout)
+#ifdef __USE_XOPEN2K
+int
+pselect (int nfds, fd_set * __restrict readfds,
+ fd_set * __restrict writefds,
+ fd_set * __restrict exceptfds,
+ const struct timespec *__restrict timeout,
+ const __sigset_t * __restrict sigmask)
{
- return vcom_socket_select (vcom_nfds, vcom_readfds,
- vcom_writefds, vcom_exceptfds, timeout);
+ return vcom_pselect (nfds, readfds, writefds, exceptfds, timeout, 0);
}
+#endif
int
-vcom_select (int __nfds, fd_set * __restrict __readfds,
- fd_set * __restrict __writefds,
- fd_set * __restrict __exceptfds,
- struct timeval *__restrict __timeout)
+socket (int domain, int type, int protocol)
{
+ const char *func_str;
int rv;
- int rv2 = 0;
- pid_t pid = getpid ();
-
- int timedout = 0;
- /* block indefinitely */
- int no_timeout = 0;
- int first_clock_gettime_failed = 0;
- /* timeout value in units of timespec */
- struct timespec timeout_ts;
- struct timespec start_time, now, end_time;
-
- /* select sets attributes - after merge */
- int new_nfds = 0;
- int new_nfd = -1;
-
- /* vcom */
- int vcom_nfds = 0;
- fd_set vcom_readfds;
- fd_set vcom_writefds;
- fd_set vcom_exceptfds;
- int vcom_nfd = -1;
-
- /* libc */
- int libc_nfds = 0;
- fd_set libc_readfds;
- fd_set libc_writefds;
- fd_set libc_exceptfds;
- int libc_nfd = -1;
+ u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0;
+ int sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
- /* for polling */
- struct timeval tv = {.tv_sec = 0,.tv_usec = 0 };
+ if ((errno = -vcom_init ()))
+ return -1;
- /* validate __timeout */
- if (__timeout)
+ if (((domain == AF_INET) || (domain == AF_INET6)) &&
+ ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
{
- /* validate tv_sec */
- /* bogus */
- if (!vcom_timerisvalid (__timeout))
- {
- rv = -EINVAL;
- goto select_done;
- }
+ int sid;
+ u32 vrf = VPPCOM_VRF_DEFAULT;
+ u8 proto = ((sock_type == SOCK_DGRAM) ?
+ VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP);
- /* validate tv_usec */
- /* TBD: */
- /* init timeout_ts */
- VCOM_TIMEVAL_TO_TIMESPEC (__timeout, &timeout_ts);
- set_normalized_timespec (&timeout_ts,
- timeout_ts.tv_sec, timeout_ts.tv_nsec);
- }
+ func_str = "vppcom_session_create";
- rv = clock_gettime (CLOCK_MONOTONIC, &start_time);
- if (rv == -1)
- {
- rv = -errno;
- first_clock_gettime_failed = 1;
- goto select_done;
- }
+ if (VCOM_DEBUG > 0)
+ clib_warning ("LDP<%d>: : calling %s(): vrf %u, "
+ "proto %u (%s), is_nonblocking %u",
+ getpid (), func_str, vrf, proto,
+ vppcom_proto_str (proto), is_nonblocking);
- /* init end_time */
- if (__timeout)
- {
- if (timerisset (__timeout))
+ sid = vppcom_session_create (vrf, proto, is_nonblocking);
+ if (sid < 0)
{
- end_time = timespec_add (start_time, timeout_ts);
+ errno = -sid;
+ rv = -1;
}
else
{
- /*
- * if both fields of the timeout structure are zero,
- * then select returns immediately
- * */
- end_time = start_time;
+ func_str = "vcom_fd_from_sid";
+ rv = vcom_fd_from_sid (sid);
+ if (rv < 0)
+ {
+ (void) vppcom_session_close (sid);
+ errno = -rv;
+ rv = -1;
+ }
}
}
else
{
- /* block indefinitely */
- no_timeout = 1;
- }
+ func_str = "libc_socket";
+ if (VCOM_DEBUG > 0)
+ clib_warning ("LDP<%d>: : calling %s()", getpid (), func_str);
-
- if (vcom_init () != 0)
- {
- rv = -1;
- goto select_done;
- }
-
- /* validate __nfds */
- if (__nfds < 0 || __nfds > FD_SETSIZE)
- {
- rv = -EINVAL;
- goto select_done;
+ rv = libc_socket (domain, type, protocol);
}
-
- /*
- * usleep(3) emulation
- * */
-
- /* call libc_select() with a finite timeout and
- * no file descriptors or empty fd sets and
- * zero nfds */
- if (__nfds == 0 &&
- (!__readfds || fd_set_iszero (__readfds)) &&
- (!__writefds || fd_set_iszero (__writefds)) &&
- (!__exceptfds || fd_set_iszero (__exceptfds)))
+ if (VCOM_DEBUG > 0)
{
- if (__timeout)
+ if (rv < 0)
{
- rv = libc_select (__nfds,
- __readfds, __writefds, __exceptfds, __timeout);
- if (rv == -1)
- rv = -errno;
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: %s() failed! "
+ "rv %d, errno = %d",
+ getpid (), func_str, rv, errno_val);
+ errno = errno_val;
}
else
- {
- /* TBD: block indefinitely or return -EINVAL */
- rv = -EINVAL;
- }
- goto select_done;
+ clib_warning ("LDP<%d>: : returning fd %d (0x%x)", getpid (), rv, rv);
}
+ return rv;
+}
- /* init once before the polling loop */
+/*
+ * Create two new sockets, of type TYPE in domain DOMAIN and using
+ * protocol PROTOCOL, which are connected to each other, and put file
+ * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero,
+ * one will be chosen automatically.
+ * Returns 0 on success, -1 for errors.
+ * */
+int
+socketpair (int domain, int type, int protocol, int fds[2])
+{
+ const char *func_str;
+ int rv;
+ int sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
- /* zero vcom and libc fd sets */
- /*
- * S select fd set
- * V vcom fd set
- * L libc fd set
- */
-#define _(S,V,L) \
- if ((S)) \
- { \
- FD_ZERO ((V)); \
- FD_ZERO ((L)); \
- }
-
-
- _(__readfds, &vcom_readfds, &libc_readfds);
- _(__writefds, &vcom_writefds, &libc_writefds);
- _(__exceptfds, &vcom_exceptfds, &libc_exceptfds);
-#undef _
- new_nfds = 0;
- new_nfd = -1;
-
- vcom_nfds = 0;
- vcom_nfd = -1;
- libc_nfds = 0;
- libc_nfd = -1;
-
- vcom_fd_set_split (
- /* src, select sets */
- __nfds, __readfds, __writefds, __exceptfds,
- /* dest1, vcom sets */
- __readfds || __writefds || __exceptfds ?
- &vcom_nfds : NULL,
- __readfds ? &vcom_readfds : NULL,
- __writefds ? &vcom_writefds : NULL,
- __exceptfds ? &vcom_exceptfds : NULL,
- __readfds || __writefds || __exceptfds ?
- &vcom_nfd : NULL,
- /* dest2, libc sets */
- __readfds || __writefds || __exceptfds ?
- &libc_nfds : NULL,
- __readfds ? &libc_readfds : NULL,
- __writefds ? &libc_writefds : NULL,
- __exceptfds ? &libc_exceptfds : NULL,
- __readfds || __writefds || __exceptfds ?
- &libc_nfd : NULL);
+ if ((errno = -vcom_init ()))
+ return -1;
- /*
- * polling loop
- * */
- do
+ if (((domain == AF_INET) || (domain == AF_INET6)) &&
+ ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
{
- new_nfd = -1;
- vcom_nfd = -1;
- libc_nfd = -1;
-
- /*
- * if both fields of timeval structure are zero,
- * vcom_select_impl and libc_select returns immediately.
- * useful for polling and ensure fairness among
- * file descriptors watched.
- */
-
- /* for polling */
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- /* select on vcom fds */
- if (vcom_nfds)
- {
- vcom_nfd = vcom_select_impl (vcom_nfds,
- __readfds ? &vcom_readfds : NULL,
- __writefds ? &vcom_writefds : NULL,
- __exceptfds ? &vcom_exceptfds : NULL,
- &tv);
- if (VCOM_DEBUG > 2)
- fprintf (stderr,
- "[%d] select vcom: "
- "'%04d'='%04d'\n", pid, vcom_nfd, vcom_nfds);
-
- if (vcom_nfd < 0)
- {
- rv = vcom_nfd;
- goto select_done;
- }
- }
- /* select on libc fds */
- if (libc_nfds)
- {
- libc_nfd = libc_select (libc_nfds,
- __readfds ? &libc_readfds : NULL,
- __writefds ? &libc_writefds : NULL,
- __exceptfds ? &libc_exceptfds : NULL, &tv);
- if (VCOM_DEBUG > 2)
- fprintf (stderr,
- "[%d] select libc: "
- "'%04d'='%04d'\n", pid, libc_nfd, libc_nfds);
+ clib_warning ("LDP<%d>: LDP-TBD", getpid ());
+ errno = ENOSYS;
+ rv = -1;
+ }
+ else
+ {
+ func_str = "libc_socket";
- if (libc_nfd < 0)
- {
- /* tv becomes undefined */
- libc_nfd = errno;
- rv = libc_nfd;
- goto select_done;
- }
- }
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: : calling %s()", getpid (), func_str);
- /* check if any file descriptors changed status */
- if ((vcom_nfds && vcom_nfd > 0) || (libc_nfds && libc_nfd > 0))
- {
- /* zero the sets before merge and exit */
-
- /*
- * F fd set
- */
-#define _(F) \
- if ((F)) \
- { \
- FD_ZERO ((F)); \
- }
-
-
- _(__readfds);
- _(__writefds);
- _(__exceptfds);
-#undef _
- new_nfds = 0;
- new_nfd = -1;
-
- /*
- * on exit, sets are modified in place to indicate which
- * file descriptors actually changed status
- * */
- vcom_fd_set_merge (
- /* dest, select sets */
- &new_nfds,
- __readfds, __writefds, __exceptfds, &new_nfd,
- /* src1, vcom sets */
- vcom_nfds,
- __readfds ? &vcom_readfds : NULL,
- __writefds ? &vcom_writefds : NULL,
- __exceptfds ? &vcom_exceptfds : NULL, vcom_nfd,
- /* src2, libc sets */
- libc_nfds,
- __readfds ? &libc_readfds : NULL,
- __writefds ? &libc_writefds : NULL,
- __exceptfds ? &libc_exceptfds : NULL, libc_nfd);
- /*
- * return the number of file descriptors contained in the
- * three returned sets
- * */
- rv = 0;
- /*
- * for documentation
- *
- * if(vcom_nfd > 0)
- * rv += vcom_nfd;
- * if(libc_nfd > 0)
- * rv += libc_nfd;
- */
-
- rv = new_nfd == -1 ? 0 : new_nfd;
- goto select_done;
- }
-
- rv = clock_gettime (CLOCK_MONOTONIC, &now);
- if (rv == -1)
- {
- rv = -errno;
- goto select_done;
- }
- }
- while (no_timeout || timespec_compare (&now, &end_time) < 0);
-
- /* timeout expired before anything interesting happened */
- timedout = 1;
- rv = 0;
+ rv = libc_socket (domain, type, protocol);
+ }
-select_done:
- if (VCOM_DEBUG > 2)
- fprintf (stderr, "[%d] vselect1: " "'%04d'='%04d'\n", pid, rv, __nfds);
- /*
- * modify timeout parameter to reflect the amount of time not slept
- * */
- if (__timeout)
+ if (VCOM_DEBUG > 1)
{
- if (vcom_timerisvalid (__timeout))
+ if (rv < 0)
{
- /* timeout expired */
- if (timedout)
- {
- timerclear (__timeout);
- }
- else if (!first_clock_gettime_failed)
- {
- rv2 = clock_gettime (CLOCK_MONOTONIC, &now);
- if (rv2 == -1)
- {
- rv = -errno;
- }
- else
- {
- struct timespec ts_delta;
- ts_delta = timespec_sub (end_time, now);
- VCOM_TIMESPEC_TO_TIMEVAL (__timeout, &ts_delta);
- }
- }
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: %s() failed! "
+ "rv %d, errno = %d",
+ getpid (), func_str, rv, errno_val);
+ errno = errno_val;
}
+ else
+ clib_warning ("LDP<%d>: : returning fd %d (0x%x)", getpid (), rv, rv);
}
- if (VCOM_DEBUG > 2)
- fprintf (stderr, "[%d] vselect2: " "'%04d',='%04d'\n", pid, rv, __nfds);
-
return rv;
}
int
-vcom_select_internal (int __nfds, fd_set * __restrict __readfds,
- fd_set * __restrict __writefds,
- fd_set * __restrict __exceptfds,
- struct timeval *__restrict __timeout)
+bind (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
{
int rv;
- int new_nfds = 0;
- int nfd = 0;
- pid_t pid = getpid ();
+ const char *func_str;
+ u32 sid = vcom_sid_from_fd (fd);
- fd_set saved_readfds;
- fd_set saved_writefds;
- fd_set saved_exceptfds;
+ if ((errno = -vcom_init ()))
+ return -1;
- /* validate __nfds */
- if (__nfds < 0)
+ if (sid != INVALID_SESSION_ID)
{
- errno = EINVAL;
- return -1;
- }
+ vppcom_endpt_t ep;
- /* validate __timeout */
- if (__timeout)
- {
- /* validate tv_sec */
- /* bogus */
- if (__timeout->tv_sec < 0 || __timeout->tv_usec < 0)
- {
- errno = EINVAL;
- return -1;
- }
+ func_str = "vppcom_session_bind";
- /* validate tv_usec */
- /* TBD: */
- }
+ ep.vrf = VPPCOM_VRF_DEFAULT;
+ switch (addr->sa_family)
+ {
+ case AF_INET:
+ if (len != sizeof (struct sockaddr_in))
+ {
+ clib_warning
+ ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): Invalid "
+ "AF_INET addr len %u!", getpid (), fd, fd, sid, sid, len);
+ errno = EINVAL;
+ rv = -1;
+ goto done;
+ }
+ ep.is_ip4 = VPPCOM_IS_IP4;
+ ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
+ ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
+ break;
- /* init saved_x fds */
- if (__readfds)
- {
- saved_readfds = *__readfds;
- /*
- memcpy (&saved_readfds, __readfds, sizeof (*__readfds));
- */
- }
- else
- {
- FD_ZERO (&saved_readfds);
- }
+ case AF_INET6:
+ if (len != sizeof (struct sockaddr_in6))
+ {
+ clib_warning
+ ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): Invalid "
+ "AF_INET6 addr len %u!", getpid (), fd, fd, sid, sid, len);
+ errno = EINVAL;
+ rv = -1;
+ goto done;
+ }
+ ep.is_ip4 = VPPCOM_IS_IP6;
+ ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
+ ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
+ break;
- if (__writefds)
- {
- saved_writefds = *__writefds;
- /*
- memcpy (&saved_writefds, __writefds, sizeof (*__writefds));
- */
+ default:
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): "
+ "Unsupported address family %u!",
+ getpid (), fd, fd, sid, sid, addr->sa_family);
+ errno = EAFNOSUPPORT;
+ rv = -1;
+ goto done;
+ }
+ if (VCOM_DEBUG > 0)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
+ "addr %p, len %u",
+ getpid (), fd, fd, func_str, sid, sid, addr, len);
+ rv = vppcom_session_bind (sid, &ep);
+ if (rv != VPPCOM_OK)
+ {
+ errno = -rv;
+ rv = -1;
+ }
}
else
{
- FD_ZERO (&saved_writefds);
- }
+ func_str = "libc_bind";
- if (__exceptfds)
- {
- saved_exceptfds = *__exceptfds;
- /*
- memcpy (&saved_exceptfds, __exceptfds, sizeof (*__exceptfds));
- */
+ if (VCOM_DEBUG > 0)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "addr %p, len %u",
+ getpid (), fd, fd, func_str, addr, len);
+ rv = libc_bind (fd, addr, len);
}
- else
- {
- FD_ZERO (&saved_exceptfds);
- }
-
- /* clear vcom fds */
- nfd = vcom_fd_clear (__nfds, &new_nfds, __readfds, __writefds, __exceptfds);
-
- /* set to an invalid value */
- rv = -2;
- /* have kernel fds */
- if (new_nfds)
- rv = libc_select (new_nfds, __readfds,
- __writefds, __exceptfds, __timeout);
- if (new_nfds && rv == -1)
- {
- /* on error, the file descriptor sets are unmodified */
- if (__readfds)
- *__readfds = saved_readfds;
- if (__writefds)
- *__writefds = saved_writefds;
- if (__exceptfds)
- *__exceptfds = saved_exceptfds;
- return rv;
- }
- else if ((new_nfds && rv != -1) || (rv == -2))
+done:
+ if (VCOM_DEBUG > 0)
{
- /* restore vcom fds */
- nfd = vcom_fd_set (__nfds,
- &new_nfds,
- __readfds,
- __writefds,
- __exceptfds,
- &saved_readfds, &saved_writefds, &saved_exceptfds);
- rv = nfd;
+ if (rv < 0)
+ {
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, rv, errno_val);
+ errno = errno_val;
+ }
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, rv, rv);
}
-
- if (VCOM_DEBUG > 0)
- fprintf (stderr, "[%d] select: " "'%04d'='%04d'\n", pid, rv, __nfds);
return rv;
}
-int
-select (int __nfds, fd_set * __restrict __readfds,
- fd_set * __restrict __writefds,
- fd_set * __restrict __exceptfds, struct timeval *__restrict __timeout)
+static inline int
+vcom_copy_ep_to_sockaddr (__SOCKADDR_ARG addr, socklen_t * __restrict len,
+ vppcom_endpt_t * ep)
{
int rv = 0;
- pid_t pid = getpid ();
+ int sa_len, copy_len;
- if (VCOM_DEBUG > 2)
- fprintf (stderr, "[%d] select1: " "'%04d'='%04d'\n", pid, rv, __nfds);
- rv = vcom_select (__nfds, __readfds, __writefds, __exceptfds, __timeout);
- if (VCOM_DEBUG > 2)
- fprintf (stderr, "[%d] select2: " "'%04d'='%04d'\n", pid, rv, __nfds);
- if (rv < 0)
+ if ((errno = -vcom_init ()))
+ return -1;
+
+ if (addr && len && ep)
{
- errno = -rv;
- return -1;
+ addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
+ switch (addr->sa_family)
+ {
+ case AF_INET:
+ ((struct sockaddr_in *) addr)->sin_port = ep->port;
+ if (*len > sizeof (struct sockaddr_in))
+ *len = sizeof (struct sockaddr_in);
+ sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
+ copy_len = *len - sa_len;
+ if (copy_len > 0)
+ memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
+ copy_len);
+ break;
+
+ case AF_INET6:
+ ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
+ if (*len > sizeof (struct sockaddr_in6))
+ *len = sizeof (struct sockaddr_in6);
+ sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
+ copy_len = *len - sa_len;
+ if (copy_len > 0)
+ memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
+ __in6_u.__u6_addr8, ep->ip, copy_len);
+ break;
+
+ default:
+ /* Not possible */
+ rv = -EAFNOSUPPORT;
+ break;
+ }
}
return rv;
}
-#ifdef __USE_XOPEN2K
-/*
- * Same as above only that the TIMEOUT value is given with higher
- * resolution and a sigmask which is been set temporarily. This
- * version should be used.
- *
- * This function is a cancellation point and therefore not marked
- * with __THROW.
- * */
int
-vcom_pselect (int __nfds, fd_set * __restrict __readfds,
- fd_set * __restrict __writefds,
- fd_set * __restrict __exceptfds,
- const struct timespec *__restrict __timeout,
- const __sigset_t * __restrict __sigmask)
+getsockname (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
{
- int fd;
- int vcom_nfds = 0;
+ int rv;
+ const char *func_str;
+ u32 sid = vcom_sid_from_fd (fd);
+
+ if ((errno = -vcom_init ()))
+ return -1;
- for (fd = 0; fd < __nfds; fd++)
+ if (sid != INVALID_SESSION_ID)
{
- if (__readfds && FD_ISSET (fd, __readfds))
+ vppcom_endpt_t ep;
+ u8 addr_buf[sizeof (struct in6_addr)];
+ u32 size = sizeof (ep);
+
+ ep.ip = addr_buf;
+ func_str = "vppcom_session_attr[GET_LCL_ADDR]";
+
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
+ "addr %p, len %u",
+ getpid (), fd, fd, func_str, sid, sid, addr, len);
+
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
+ if (rv != VPPCOM_OK)
{
- if (is_vcom_socket_fd (fd))
- {
- vcom_nfds++;
- }
+ errno = -rv;
+ rv = -1;
}
-
- if (__writefds && FD_ISSET (fd, __writefds))
+ else
{
- if (is_vcom_socket_fd (fd))
+ rv = vcom_copy_ep_to_sockaddr (addr, len, &ep);
+ if (rv != VPPCOM_OK)
{
- vcom_nfds++;
+ errno = -rv;
+ rv = -1;
}
}
- if (__exceptfds && FD_ISSET (fd, __exceptfds))
+ }
+ else
+ {
+ func_str = "libc_getsockname";
+
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "addr %p, len %u",
+ getpid (), fd, fd, func_str, addr, len);
+
+ rv = libc_getsockname (fd, addr, len);
+ }
+
+ if (VCOM_DEBUG > 2)
+ {
+ if (rv < 0)
{
- if (is_vcom_socket_fd (fd))
- {
- FD_CLR (fd, __exceptfds);
- }
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, rv, errno_val);
+ errno = errno_val;
}
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, rv, rv);
}
- return vcom_nfds;
+ return rv;
}
int
-pselect (int __nfds, fd_set * __restrict __readfds,
- fd_set * __restrict __writefds,
- fd_set * __restrict __exceptfds,
- const struct timespec *__restrict __timeout,
- const __sigset_t * __restrict __sigmask)
+connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
{
int rv;
- int new_nfds = 0;
- int nfd = 0;
- pid_t pid = getpid ();
+ const char *func_str = __func__;
+ u32 sid = vcom_sid_from_fd (fd);
- fd_set saved_readfds;
- fd_set saved_writefds;
- fd_set saved_exceptfds;
+ if ((errno = -vcom_init ()))
+ return -1;
- /* validate __nfds */
- if (__nfds < 0)
+ if (!addr)
{
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): NULL addr, len %u",
+ getpid (), fd, fd, len);
errno = EINVAL;
- return -1;
+ rv = -1;
+ goto done;
}
- /* validate __timeout */
- if (__timeout)
+ if (sid != INVALID_SESSION_ID)
{
- /* validate tv_sec */
- /* bogus */
- if (__timeout->tv_sec < 0 || __timeout->tv_nsec < 0)
- {
- errno = EINVAL;
- return -1;
- }
-
- /* validate tv_usec */
- /* TBD: */
- }
+ vppcom_endpt_t ep;
- /* init saved fds */
- if (__readfds)
- {
- saved_readfds = *__readfds;
- /*
- memcpy (&saved_readfds, __readfds, sizeof (*__readfds));
- */
- }
- else
- {
- FD_ZERO (&saved_readfds);
- }
+ func_str = "vppcom_session_connect";
- if (__writefds)
- {
- saved_writefds = *__writefds;
- /*
- memcpy (&saved_writefds, __writefds, sizeof (*__writefds));
- */
+ ep.vrf = VPPCOM_VRF_DEFAULT;
+ switch (addr->sa_family)
+ {
+ case AF_INET:
+ if (len != sizeof (struct sockaddr_in))
+ {
+ clib_warning
+ ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): Invalid "
+ "AF_INET addr len %u!", getpid (), fd, fd, sid, sid, len);
+ errno = EINVAL;
+ rv = -1;
+ goto done;
+ }
+ ep.is_ip4 = VPPCOM_IS_IP4;
+ ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
+ ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
+ break;
- }
- else
- {
- FD_ZERO (&saved_writefds);
- }
+ case AF_INET6:
+ if (len != sizeof (struct sockaddr_in6))
+ {
+ clib_warning
+ ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): Invalid "
+ "AF_INET6 addr len %u!", getpid (), fd, fd, sid, sid, len);
+ errno = EINVAL;
+ rv = -1;
+ goto done;
+ }
+ ep.is_ip4 = VPPCOM_IS_IP6;
+ ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
+ ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
+ break;
- if (__exceptfds)
- {
- saved_exceptfds = *__exceptfds;
- /*
- memcpy (&saved_exceptfds, __exceptfds, sizeof (*__exceptfds));
- */
+ default:
+ clib_warning ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): "
+ "Unsupported address family %u!",
+ getpid (), fd, fd, sid, sid, addr->sa_family);
+ errno = EAFNOSUPPORT;
+ rv = -1;
+ goto done;
+ }
+ if (VCOM_DEBUG > 0)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x) "
+ "addr %p len %u",
+ getpid (), fd, fd, func_str, sid, sid, addr, len);
+ rv = vppcom_session_connect (sid, &ep);
+ if (rv != VPPCOM_OK)
+ {
+ errno = -rv;
+ rv = -1;
+ }
}
else
{
- FD_ZERO (&saved_exceptfds);
- }
-
- /* clear vcom fds */
- nfd = vcom_fd_clear (__nfds, &new_nfds, __readfds, __writefds, __exceptfds);
+ func_str = "libc_connect";
- /* set to an invalid value */
- rv = -2;
- if (new_nfds)
- rv = libc_pselect (new_nfds,
- __readfds,
- __writefds, __exceptfds, __timeout, __sigmask);
+ if (VCOM_DEBUG > 0)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "addr %p, len %u",
+ getpid (), fd, fd, func_str, addr, len);
- if (new_nfds && rv == -1)
- {
- /* on error, the file descriptor sets are unmodified */
- if (__readfds)
- *__readfds = saved_readfds;
- if (__writefds)
- *__writefds = saved_writefds;
- if (__exceptfds)
- *__exceptfds = saved_exceptfds;
- return rv;
+ rv = libc_connect (fd, addr, len);
}
- else if ((new_nfds && rv != -1) || (rv == -2))
+
+done:
+ if (VCOM_DEBUG > 0)
{
- /* restore vcom fds */
- nfd = vcom_fd_set (__nfds,
- &new_nfds,
- __readfds,
- __writefds,
- __exceptfds,
- &saved_readfds, &saved_writefds, &saved_exceptfds);
- rv = nfd;
+ if (rv < 0)
+ {
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, rv, errno_val);
+ errno = errno_val;
+ }
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, rv, rv);
}
-
- if (VCOM_DEBUG > 2)
- fprintf (stderr, "[%d] pselect: " "'%04d'='%04d'\n", pid, rv, __nfds);
return rv;
}
-#endif
-
-/*
- *
- * Socket specific glibc api
- *
- */
-
-/* Create a new socket of type TYPE in domain DOMAIN, using
- * protocol PROTOCOL. If PROTOCOL is zero, one is chosen
- * automatically. Returns a file descriptor for the new socket,
- * or -1 for errors.
- * RETURN: a valid file descriptor for the new socket,
- * or -1 for errors.
- * */
int
-vcom_socket (int __domain, int __type, int __protocol)
+getpeername (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
{
- if (vcom_init () != 0)
- {
- return -1;
- }
+ int rv;
+ const char *func_str;
+ u32 sid = vcom_sid_from_fd (fd);
- return vcom_socket_socket (__domain, __type, __protocol);
-}
+ if ((errno = -vcom_init ()))
+ return -1;
-int
-socket (int __domain, int __type, int __protocol)
-{
- int rv;
- pid_t pid = getpid ();
- pthread_t tid = pthread_self ();
+ clib_warning ("LDP<%d>: fd %d (0x%x) ", getpid (), fd, fd);
- /* handle domains implemented by vpp */
- switch (__domain)
+ if (sid != INVALID_SESSION_ID)
{
- case AF_INET:
- case AF_INET6:
- /* handle types implemented by vpp */
- switch (__type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
+ vppcom_endpt_t ep;
+ u8 addr_buf[sizeof (struct in6_addr)];
+ u32 size = sizeof (ep);
+
+ ep.ip = addr_buf;
+ func_str = "vppcom_session_attr[GET_PEER_ADDR]";
+
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
+ "addr %p, len %u",
+ getpid (), fd, fd, func_str, sid, sid, addr, len);
+
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size);
+ if (rv != VPPCOM_OK)
{
- case SOCK_STREAM:
- case SOCK_DGRAM:
- if (VCOM_DEBUG > 0)
- vcom_socket_main_show ();
- rv = vcom_socket (__domain, __type, __protocol);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d][%lu (0x%lx)] socket: "
- "'%04d'= D='%04d', T='%04d', P='%04d'\n",
- pid, (unsigned long) tid, (unsigned long) tid,
- rv, __domain, __type, __protocol);
- if (VCOM_DEBUG > 0)
- vcom_socket_main_show ();
- if (rv < 0)
+ errno = -rv;
+ rv = -1;
+ }
+ else
+ {
+ rv = vcom_copy_ep_to_sockaddr (addr, len, &ep);
+ if (rv != VPPCOM_OK)
{
errno = -rv;
- return -1;
+ rv = -1;
}
- return rv;
- break;
-
- default:
- goto CALL_GLIBC_SOCKET_API;
- break;
}
-
- break;
-
- default:
- goto CALL_GLIBC_SOCKET_API;
- break;
}
-
-CALL_GLIBC_SOCKET_API:
- return libc_socket (__domain, __type, __protocol);
-}
-
-/*
- * Create two new sockets, of type TYPE in domain DOMAIN and using
- * protocol PROTOCOL, which are connected to each other, and put file
- * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero,
- * one will be chosen automatically.
- * Returns 0 on success, -1 for errors.
- * */
-int
-vcom_socketpair (int __domain, int __type, int __protocol, int __fds[2])
-{
- if (vcom_init () != 0)
+ else
{
- return -1;
- }
+ func_str = "libc_getpeername";
- return vcom_socket_socketpair (__domain, __type, __protocol, __fds);
-}
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "addr %p, len %u",
+ getpid (), fd, fd, func_str, addr, len);
-int
-socketpair (int __domain, int __type, int __protocol, int __fds[2])
-{
- int rv;
- pid_t pid = getpid ();
+ rv = libc_getpeername (fd, addr, len);
+ }
- /* handle domains implemented by vpp */
- switch (__domain)
+ if (VCOM_DEBUG > 2)
{
- case AF_INET:
- case AF_INET6:
- /* handle types implemented by vpp */
- switch (__type)
+ if (rv < 0)
{
- case SOCK_STREAM:
- case SOCK_DGRAM:
- rv = vcom_socketpair (__domain, __type, __protocol, __fds);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] socketpair: "
- "'%04d'= D='%04d', T='%04d', P='%04d'\n",
- pid, rv, __domain, __type, __protocol);
- if (rv < 0)
- {
- errno = -rv;
- return -1;
- }
- return 0;
- break;
-
- default:
- goto CALL_GLIBC_SOCKET_API;
- break;
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, rv, errno_val);
+ errno = errno_val;
}
-
- break;
-
- default:
- goto CALL_GLIBC_SOCKET_API;
- break;
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, rv, rv);
}
-
-CALL_GLIBC_SOCKET_API:
- return libc_socketpair (__domain, __type, __protocol, __fds);
+ return rv;
}
-/*
- * Give the socket FD the local address ADDR
- * (which is LEN bytes long).
- * */
-int
-vcom_bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
+ssize_t
+send (int fd, const void *buf, size_t n, int flags)
{
- int rv;
+ ssize_t size;
+ const char *func_str;
+ u32 sid = vcom_sid_from_fd (fd);
- if (vcom_init () != 0)
- {
- return -1;
- }
+ if ((errno = -vcom_init ()))
+ return -1;
- /* validate __len */
- switch (__addr->sa_family)
+ if (sid != INVALID_SESSION_ID)
{
- case AF_INET:
- if (__len != sizeof (struct sockaddr_in))
- return -EINVAL;
- break;
- case AF_INET6:
- if (__len != sizeof (struct sockaddr_in6))
- return -EINVAL;
- break;
- default:
- return -1;
- break;
- }
+ func_str = "vppcom_session_sendto";
- /* handle domains implemented by vpp */
- switch (__addr->sa_family)
- {
- case AF_INET:
- case AF_INET6:
- rv = vcom_socket_bind (__fd, __addr, __len);
- return rv;
- break;
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
+ "buf %p, n %u, flags 0x%x",
+ getpid (), fd, fd, func_str, sid, sid, buf, n, flags);
- default:
- return -1;
- break;
+ size = vppcom_session_sendto (sid, (void *) buf, n, flags, NULL);
+ if (size != VPPCOM_OK)
+ {
+ errno = -size;
+ size = -1;
+ }
}
+ else
+ {
+ func_str = "libc_send";
- return -1;
-}
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "buf %p, n %u, flags 0x%x",
+ getpid (), fd, fd, func_str, buf, n, flags);
-int
-bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
-{
- int rv;
- pid_t pid = getpid ();
+ size = libc_send (fd, buf, n, flags);
+ }
- if (is_vcom_socket_fd (__fd))
+ if (VCOM_DEBUG > 2)
{
-
- rv = vcom_bind (__fd, __addr, __len);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] bind: "
- "'%04d'='%04d', '%p', '%04d'\n",
- pid, rv, __fd, __addr, __len);
- if (rv != 0)
+ if (size < 0)
{
- errno = -rv;
- return -1;
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, size, errno_val);
+ errno = errno_val;
}
- return 0;
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, size, size);
}
- return libc_bind (__fd, __addr, __len);
+ return size;
}
-/*
- * Put the local address of FD into *ADDR and its length in *LEN.
- * */
-int
-vcom_getsockname (int __fd, __SOCKADDR_ARG __addr,
- socklen_t * __restrict __len)
+ssize_t
+sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
{
- if (vcom_init () != 0)
- {
- return -1;
- }
-
- return vcom_socket_getsockname (__fd, __addr, __len);
-}
+ ssize_t size = 0;
+ const char *func_str;
+ u32 sid = vcom_sid_from_fd (out_fd);
-int
-getsockname (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __len)
-{
- int rv;
- pid_t pid = getpid ();
+ if ((errno = -vcom_init ()))
+ return -1;
- if (is_vcom_socket_fd (__fd))
- {
- rv = vcom_getsockname (__fd, __addr, __len);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] getsockname: "
- "'%04d'='%04d', '%p', '%p'\n", pid, rv, __fd, __addr, __len);
- if (rv != 0)
+ if (sid != INVALID_SESSION_ID)
+ {
+ int rv;
+ ssize_t results = 0;
+ size_t n_bytes_left = len;
+ size_t bytes_to_read;
+ int nbytes;
+ int errno_val;
+ u8 eagain = 0;
+ u32 flags, flags_len = sizeof (flags);
+
+ func_str = "vppcom_session_attr[GET_FLAGS]";
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_FLAGS, &flags,
+ &flags_len);
+ if (PREDICT_FALSE (rv != VPPCOM_OK))
{
+ clib_warning ("LDP<%d>: ERROR: out fd %d (0x%x): %s(): "
+ "sid %u (0x%x), returned %d (%s)!", getpid (),
+ out_fd, out_fd, func_str, sid, sid, rv,
+ vppcom_retval_str (rv));
+
+ vec_reset_length (vcom->io_buffer);
errno = -rv;
- return -1;
+ size = -1;
+ goto done;
}
- return 0;
- }
- return libc_getsockname (__fd, __addr, __len);
-}
-
-/*
- * Open a connection on socket FD to peer at ADDR
- * (which LEN bytes long). For connectionless socket types, just set
- * the default address to send to and the only address from which to
- * accept transmissions. Return 0 on success, -1 for errors.
- * This function is a cancellation point and therefore not marked
- * with __THROW.
- * */
-int
-vcom_connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
-{
- int rv;
- rv = vcom_init ();
- if (rv)
- {
- return rv;
- }
+ if (offset)
+ {
+ off_t off = lseek (in_fd, *offset, SEEK_SET);
+ if (PREDICT_FALSE (off == -1))
+ {
+ func_str = "lseek";
+ errno_val = errno;
+ clib_warning ("LDP<%d>: ERROR: out fd %d (0x%x): %s(): "
+ "SEEK_SET failed: in_fd %d, offset %p, "
+ "*offset %ld, rv %ld, errno %d", getpid (),
+ out_fd, out_fd, in_fd, offset, *offset, off,
+ errno_val);
+ errno = errno_val;
+ size = -1;
+ goto done;
+ }
- /* validate __len */
- switch (__addr->sa_family)
- {
- case AF_INET:
- if (__len != INET_ADDRSTRLEN)
- return -EINVAL;
- break;
- case AF_INET6:
- if (__len != INET6_ADDRSTRLEN)
- return -EINVAL;
- break;
+ ASSERT (off == *offset);
+ }
- default:
- return -EAFNOSUPPORT;
- break;
- }
+ do
+ {
+ func_str = "vppcom_session_attr[GET_NWRITE]";
+ size = vppcom_session_attr (sid, VPPCOM_ATTR_GET_NWRITE, 0, 0);
+ if (size < 0)
+ {
+ clib_warning
+ ("LDP<%d>: ERROR: fd %d (0x%x): %s(): sid %u (0x%x), "
+ "returned %d (%s)!", getpid (), out_fd, out_fd, func_str,
+ sid, sid, size, vppcom_retval_str (size));
+ vec_reset_length (vcom->io_buffer);
+ errno = -size;
+ size = -1;
+ goto done;
+ }
- /* handle domains implemented by vpp */
- switch (__addr->sa_family)
- {
- case AF_INET:
- case AF_INET6:
- rv = vcom_socket_connect (__fd, __addr, __len);
- break;
+ bytes_to_read = size;
+ if (VCOM_DEBUG > 2)
+ clib_warning
+ ("LDP<%d>: fd %d (0x%x): called %s(): sid %u (0x%x), "
+ "results %ld, n_bytes_left %lu, bytes_to_read %lu", getpid (),
+ out_fd, out_fd, func_str, sid, sid, results, n_bytes_left,
+ bytes_to_read);
- default:
- return -EPFNOSUPPORT;
- break;
- }
+ if (bytes_to_read == 0)
+ {
+ if (flags & O_NONBLOCK)
+ {
+ if (!results)
+ {
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): sid %u (0x%x): "
+ "EAGAIN",
+ getpid (), out_fd, out_fd, sid, sid);
+ eagain = 1;
+ }
+ goto update_offset;
+ }
+ else
+ continue;
+ }
+ bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
+ vec_validate (vcom->io_buffer, bytes_to_read);
+ nbytes = libc_read (in_fd, vcom->io_buffer, bytes_to_read);
+ if (nbytes < 0)
+ {
+ func_str = "libc_read";
+ errno_val = errno;
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): in_fd (%d), "
+ "io_buffer %p, bytes_to_read %lu, rv %d, "
+ "errno %d", getpid (), out_fd, out_fd, func_str,
+ in_fd, vcom->io_buffer, bytes_to_read, nbytes,
+ errno_val);
+ errno = errno_val;
+
+ if (results == 0)
+ {
+ vec_reset_length (vcom->io_buffer);
+ size = -1;
+ goto done;
+ }
+ goto update_offset;
+ }
+ func_str = "vppcom_session_write";
+ if (VCOM_DEBUG > 2)
+ clib_warning
+ ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
+ "buf %p, nbytes %u: results %d, n_bytes_left %d", getpid (),
+ out_fd, out_fd, func_str, sid, sid, vcom->io_buffer, nbytes,
+ results, n_bytes_left);
+
+ size = vppcom_session_write (sid, vcom->io_buffer, nbytes);
+ if (size < 0)
+ {
+ if (size == VPPCOM_EAGAIN)
+ {
+ if (flags & O_NONBLOCK)
+ {
+ if (!results)
+ {
+ if (VCOM_DEBUG > 2)
+ clib_warning
+ ("LDP<%d>: fd %d (0x%x): sid %u (0x%x): "
+ "EAGAIN", getpid (), out_fd, out_fd, sid, sid);
+ eagain = 1;
+ }
+ goto update_offset;
+ }
+ else
+ continue;
+ }
+ else
+ {
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s():"
+ "sid %u, io_buffer %p, nbytes %u "
+ "returned %d (%s)",
+ getpid (), out_fd, out_fd, func_str,
+ sid, vcom->io_buffer, nbytes,
+ size, vppcom_retval_str (size));
+ }
+ if (results == 0)
+ {
+ vec_reset_length (vcom->io_buffer);
+ errno = -size;
+ size = -1;
+ goto done;
+ }
+ goto update_offset;
+ }
- return rv;
-}
+ results += nbytes;
+ ASSERT (n_bytes_left >= nbytes);
+ n_bytes_left = n_bytes_left - nbytes;
+ }
+ while (n_bytes_left > 0);
-int
-connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
-{
- int rv;
- pid_t pid = getpid ();
+ update_offset:
+ vec_reset_length (vcom->io_buffer);
+ if (offset)
+ {
+ off_t off = lseek (in_fd, *offset, SEEK_SET);
+ if (PREDICT_FALSE (off == -1))
+ {
+ func_str = "lseek";
+ errno_val = errno;
+ clib_warning ("LDP<%d>: ERROR: %s(): SEEK_SET failed: "
+ "in_fd %d, offset %p, *offset %ld, "
+ "rv %ld, errno %d", getpid (), in_fd,
+ offset, *offset, off, errno_val);
+ errno = errno_val;
+ size = -1;
+ goto done;
+ }
- if (is_vcom_socket_fd (__fd))
- {
- rv = vcom_connect (__fd, __addr, __len);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] connect: "
- "'%04d'='%04d', '%p', '%04d'\n",
- pid, rv, __fd, __addr, __len);
- if (rv)
+ ASSERT (off == *offset);
+ *offset += results + 1;
+ }
+ if (eagain)
{
- errno = -rv;
- return -1;
+ errno = EAGAIN;
+ size = -1;
}
- return 0;
+ else
+ size = results;
}
-
- return libc_connect (__fd, __addr, __len);
-}
-
-/*
- * Put the address of the peer connected to socket FD into *ADDR
- * (which is *LEN bytes long), and its actual length into *LEN.
- * */
-int
-vcom_getpeername (int __fd, __SOCKADDR_ARG __addr,
- socklen_t * __restrict __len)
-{
- if (vcom_init () != 0)
+ else
{
- return -1;
- }
+ func_str = "libc_send";
- return vcom_socket_getpeername (__fd, __addr, __len);
-}
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "in_fd %d, offset %p, len %u",
+ getpid (), out_fd, out_fd, func_str,
+ in_fd, offset, len);
-int
-getpeername (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __len)
-{
- int rv;
- pid_t pid = getpid ();
+ size = libc_sendfile (out_fd, in_fd, offset, len);
+ }
- if (is_vcom_socket_fd (__fd))
+done:
+ if (VCOM_DEBUG > 2)
{
- rv = vcom_getpeername (__fd, __addr, __len);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] getpeername: "
- "'%04d'='%04d', '%p', '%p'\n", pid, rv, __fd, __addr, __len);
- if (rv != 0)
+ if (size < 0)
{
- errno = -rv;
- return -1;
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), out_fd, out_fd,
+ func_str, size, errno_val);
+ errno = errno_val;
}
- return 0;
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), out_fd, out_fd, size, size);
}
- return libc_getpeername (__fd, __addr, __len);
+ return size;
}
-/*
- * Send N bytes of BUF to socket FD. Returns the number sent or -1.
- * This function is a cancellation point and therefore not marked
- * with __THROW.
- * */
ssize_t
-vcom_send (int __fd, const void *__buf, size_t __n, int __flags)
+sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len)
{
-
- if (vcom_init () != 0)
- {
- return -1;
- }
-
- return vcom_socket_send (__fd, (void *) __buf, (int) __n, __flags);
+ return sendfile (out_fd, in_fd, offset, len);
}
ssize_t
-send (int __fd, const void *__buf, size_t __n, int __flags)
+recv (int fd, void *buf, size_t n, int flags)
{
ssize_t size;
- pid_t pid = getpid ();
+ const char *func_str;
+ u32 sid = vcom_sid_from_fd (fd);
+
+ if ((errno = -vcom_init ()))
+ return -1;
- if (is_vcom_socket_fd (__fd))
+ if (sid != INVALID_SESSION_ID)
{
- size = vcom_send (__fd, __buf, __n, __flags);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] send: "
- "'%04d'='%04d', '%p', '%04d', '%04x'\n",
- pid, (int) size, __fd, __buf, (int) __n, __flags);
+ func_str = "vppcom_session_recvfrom";
+
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x), buf %p, n %u, flags 0x%x", getpid (),
+ fd, fd, func_str, sid, sid, buf, n, flags);
+
+ size = vppcom_session_recvfrom (sid, buf, n, flags, NULL);
if (size < 0)
{
errno = -size;
- return -1;
+ size = -1;
}
- return size;
}
- return libc_send (__fd, __buf, __n, __flags);
-}
+ else
+ {
+ func_str = "libc_recv";
-ssize_t
-sendfile (int __out_fd, int __in_fd, off_t * __offset, size_t __len)
-{
- ssize_t size;
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "buf %p, n %u, flags 0x%x", getpid (),
+ fd, fd, func_str, buf, n, flags);
- if (VCOM_DEBUG > 2)
- clib_warning ("[%d] __out_fd %d, __in_fd %d, __offset %p, __len %ld",
- getpid (), __out_fd, __in_fd, __offset, __len);
+ size = libc_recv (fd, buf, n, flags);
+ }
- if (is_vcom_socket_fd (__out_fd))
+ if (VCOM_DEBUG > 2)
{
- /* TBD: refactor this check to be part of is_vcom_socket_fd() */
- if (vcom_init () != 0)
- return -1;
-
- size = vcom_socket_sendfile (__out_fd, __in_fd, __offset, __len);
- if (VCOM_DEBUG > 2)
- clib_warning ("[%d] vcom_socket_sendfile (out_fd %d, in_fd %d, "
- "offset %p (%ld), len %lu) returned %ld",
- getpid (), __out_fd, __in_fd, __offset,
- __offset ? *__offset : -1, __len, size);
if (size < 0)
{
- errno = -size;
- return -1;
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, size, errno_val);
+ errno = errno_val;
}
- return size;
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, size, size);
}
- if (VCOM_DEBUG > 2)
- clib_warning ("[%d] calling libc_sendfile!", getpid ());
- return libc_sendfile (__out_fd, __in_fd, __offset, __len);
+ return size;
}
ssize_t
-sendfile64 (int __out_fd, int __in_fd, off_t * __offset, size_t __len)
+sendto (int fd, const void *buf, size_t n, int flags,
+ __CONST_SOCKADDR_ARG addr, socklen_t addr_len)
{
- return sendfile (__out_fd, __in_fd, __offset, __len);
-}
+ ssize_t size;
+ const char *func_str = __func__;
+ u32 sid = vcom_sid_from_fd (fd);
+ if ((errno = -vcom_init ()))
+ return -1;
-/*
- * Read N bytes into BUF from socket FD.
- * Returns the number read or -1 for errors.
- * This function is a cancellation point and therefore not marked
- * with __THROW.
- * */
-ssize_t
-vcom_recv (int __fd, void *__buf, size_t __n, int __flags)
-{
- if (vcom_init () != 0)
+ if (sid != INVALID_SESSION_ID)
{
- return -1;
- }
+ vppcom_endpt_t *ep = 0;
+ vppcom_endpt_t _ep;
- return vcom_socket_recv (__fd, __buf, __n, __flags);
-}
+ if (addr)
+ {
+ ep = &_ep;
+ ep->vrf = VPPCOM_VRF_DEFAULT;
+ switch (addr->sa_family)
+ {
+ case AF_INET:
+ ep->is_ip4 = VPPCOM_IS_IP4;
+ ep->ip =
+ (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr;
+ ep->port =
+ (uint16_t) ((const struct sockaddr_in *) addr)->sin_port;
+ break;
+
+ case AF_INET6:
+ ep->is_ip4 = VPPCOM_IS_IP6;
+ ep->ip =
+ (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
+ ep->port =
+ (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port;
+ break;
+
+ default:
+ errno = EAFNOSUPPORT;
+ size = -1;
+ goto done;
+ }
+ }
-ssize_t
-recv (int __fd, void *__buf, size_t __n, int __flags)
-{
- ssize_t size;
- pid_t pid = getpid ();
+ func_str = "vppcom_session_sendto";
- if (is_vcom_socket_fd (__fd))
- {
- size = vcom_recv (__fd, __buf, __n, __flags);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] recv: "
- "'%04d'='%04d', '%p', '%04d', '%04x'\n",
- pid, (int) size, __fd, __buf, (int) __n, __flags);
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x), buf %p, n %u, flags 0x%x, ep %p",
+ getpid (), fd, fd, func_str, sid, sid, buf, n,
+ flags, ep);
+
+ size = vppcom_session_sendto (sid, (void *) buf, n, flags, ep);
if (size < 0)
{
errno = -size;
- return -1;
+ size = -1;
}
- return size;
}
- return libc_recv (__fd, __buf, __n, __flags);
-}
-
-/*
- * Send N bytes of BUF on socket FD to peer at address ADDR (which is
- * ADDR_LEN bytes long). Returns the number sent, or -1 for errors.
- * This function is a cancellation point and therefore not marked
- * with __THROW.
- * */
-ssize_t
-vcom_sendto (int __fd, const void *__buf, size_t __n, int __flags,
- __CONST_SOCKADDR_ARG __addr, socklen_t __addr_len)
-{
- if (vcom_init () != 0)
+ else
{
- return -1;
+ func_str = "libc_sendto";
+
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "buf %p, n %u, flags 0x%x, addr %p, addr_len %d",
+ getpid (), fd, fd, func_str, buf, n, flags,
+ addr, addr_len);
+
+ size = libc_sendto (fd, buf, n, flags, addr, addr_len);
}
- return vcom_socket_sendto (__fd, __buf, __n, __flags, __addr, __addr_len);
+done:
+ if (VCOM_DEBUG > 2)
+ {
+ if (size < 0)
+ {
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, size, errno_val);
+ errno = errno_val;
+ }
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, size, size);
+ }
+ return size;
}
ssize_t
-sendto (int __fd, const void *__buf, size_t __n, int __flags,
- __CONST_SOCKADDR_ARG __addr, socklen_t __addr_len)
+recvfrom (int fd, void *__restrict buf, size_t n, int flags,
+ __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
{
ssize_t size;
- pid_t pid = getpid ();
+ const char *func_str;
+ u32 sid = vcom_sid_from_fd (fd);
- if (is_vcom_socket_fd (__fd))
+ if ((errno = -vcom_init ()))
+ return -1;
+
+ if (sid != INVALID_SESSION_ID)
{
- size = vcom_sendto (__fd, __buf, __n, __flags, __addr, __addr_len);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] sendto: "
- "'%04d'='%04d', '%p', '%04d', '%04x', "
- "'%p', '%04d'\n",
- pid, (int) size, __fd, __buf, (int) __n, __flags,
- __addr, __addr_len);
+ vppcom_endpt_t ep;
+ u8 src_addr[sizeof (struct sockaddr_in6)];
+
+ func_str = "vppcom_session_recvfrom";
+
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x), buf %p, n %u, flags 0x%x, ep %p",
+ getpid (), fd, fd, func_str, sid, sid, buf, n,
+ flags, &ep);
+ if (addr)
+ {
+ ep.ip = src_addr;
+ size = vppcom_session_recvfrom (sid, buf, n, flags, &ep);
+
+ if (size > 0)
+ size = vcom_copy_ep_to_sockaddr (addr, addr_len, &ep);
+ }
+ else
+ size = vppcom_session_recvfrom (sid, buf, n, flags, NULL);
+
if (size < 0)
{
errno = -size;
- return -1;
+ size = -1;
}
- return size;
}
- return libc_sendto (__fd, __buf, __n, __flags, __addr, __addr_len);
-}
-
-/*
- * Read N bytes into BUF through socket FD.
- * If ADDR is not NULL, fill in *ADDR_LEN bytes of it with the
- * address of the sender, and store the actual size of the address
- * in *ADDR_LEN.
- * Returns the number of bytes read or -1 for errors.
- * This function is a cancellation point and therefore not marked
- * with __THROW.
- * */
-ssize_t
-vcom_recvfrom (int __fd, void *__restrict __buf, size_t __n,
- int __flags,
- __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len)
-{
- if (vcom_init () != 0)
+ else
{
- return -1;
- }
+ func_str = "libc_recvfrom";
- return vcom_socket_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len);
-}
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "buf %p, n %u, flags 0x%x, addr %p, addr_len %d",
+ getpid (), fd, fd, func_str, buf, n, flags,
+ addr, addr_len);
-ssize_t
-recvfrom (int __fd, void *__restrict __buf, size_t __n,
- int __flags,
- __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len)
-{
- ssize_t size;
- pid_t pid = getpid ();
+ size = libc_recvfrom (fd, buf, n, flags, addr, addr_len);
+ }
- if (is_vcom_socket_fd (__fd))
+ if (VCOM_DEBUG > 2)
{
- size = vcom_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] recvfrom: "
- "'%04d'='%04d', '%p', '%04d', '%04x', "
- "'%p', '%p'\n",
- pid, (int) size, __fd, __buf, (int) __n, __flags,
- __addr, __addr_len);
if (size < 0)
{
- errno = -size;
- return -1;
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, size, errno_val);
+ errno = errno_val;
}
- return size;
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, size, size);
}
- return libc_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len);
+ return size;
}
-/*
- * Send a message described MESSAGE on socket FD.
- * Returns the number of bytes sent, or -1 for errors.
- * This function is a cancellation point and therefore not marked
- * with __THROW.
- * */
ssize_t
-vcom_sendmsg (int __fd, const struct msghdr * __message, int __flags)
+sendmsg (int fd, const struct msghdr * message, int flags)
{
- if (vcom_init () != 0)
+ ssize_t size;
+ const char *func_str;
+ u32 sid = vcom_sid_from_fd (fd);
+
+ if ((errno = -vcom_init ()))
+ return -1;
+
+ if (sid != INVALID_SESSION_ID)
{
- return -1;
+ clib_warning ("LDP<%d>: LDP-TBD", getpid ());
+ errno = ENOSYS;
+ size = -1;
}
+ else
+ {
+ func_str = "libc_sendmsg";
- return vcom_socket_sendmsg (__fd, __message, __flags);
-}
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "message %p, flags 0x%x",
+ getpid (), fd, fd, func_str, message, flags);
-ssize_t
-sendmsg (int __fd, const struct msghdr * __message, int __flags)
-{
- ssize_t size;
- pid_t pid = getpid ();
+ size = libc_sendmsg (fd, message, flags);
+ }
- if (is_vcom_socket_fd (__fd))
+ if (VCOM_DEBUG > 2)
{
- size = vcom_sendmsg (__fd, __message, __flags);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] sendmsg: "
- "'%04d'='%04d', '%p', '%04x'\n",
- pid, (int) size, __fd, __message, __flags);
if (size < 0)
{
- errno = -size;
- return -1;
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, size, errno_val);
+ errno = errno_val;
}
- return size;
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, size, size);
}
- return libc_sendmsg (__fd, __message, __flags);
+ return size;
}
-#ifdef __USE_GNU
-/*
- * Send a VLEN messages as described by VMESSAGES to socket FD.
- * Returns the number of datagrams successfully written
- * or -1 for errors.
- * This function is a cancellation point and therefore not marked
- * with __THROW.
- * */
+#ifdef USE_GNU
int
-vcom_sendmmsg (int __fd, struct mmsghdr *__vmessages,
- unsigned int __vlen, int __flags)
+sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
{
- if (vcom_init () != 0)
+ ssize_t size;
+ const char *func_str;
+ u32 sid = vcom_sid_from_fd (fd);
+
+ if ((errno = -vcom_init ()))
+ return -1;
+
+ if (sid != INVALID_SESSION_ID)
{
- return -1;
+ clib_warning ("LDP<%d>: LDP-TBD", getpid ());
+ errno = ENOSYS;
+ size = -1;
}
+ else
+ {
+ func_str = "libc_sendmmsg";
- return vcom_socket_sendmmsg (__fd, __message, __vlen, __flags);
-}
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "vmessages %p, vlen %u, flags 0x%x",
+ getpid (), fd, fd, func_str, vmessages, vlen, flags);
-int
-sendmmsg (int __fd, struct mmsghdr *__vmessages,
- unsigned int __vlen, int __flags)
-{
- ssize_t size;
- pid_t pid = getpid ();
+ size = libc_sendmmsg (fd, vmessages, vlen, flags);
+ }
- if (is_vcom_socket_fd (__fd))
+ if (VCOM_DEBUG > 2)
{
- size = vcom_sendmmsg (__fd, __message, __vlen, __flags);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] sendmmsg: "
- "'%04d'='%04d', '%p', '%04d', '%04x'\n",
- pid, (int) size, __fd, __vmessages, __vlen, __flags);
if (size < 0)
{
- errno = -size;
- return -1;
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, size, errno_val);
+ errno = errno_val;
}
- return size;
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, size, size);
}
- return libc_sendmmsg (__fd, __message, __vlen, __flags);
+ return size;
}
-
#endif
-/*
- * Receive a message as described by MESSAGE from socket FD.
- * Returns the number of bytes read or -1 for errors.
- * This function is a cancellation point and therefore not marked
- * with __THROW.
- * */
ssize_t
-vcom_recvmsg (int __fd, struct msghdr * __message, int __flags)
+recvmsg (int fd, struct msghdr * message, int flags)
{
- if (vcom_init () != 0)
+ ssize_t size;
+ const char *func_str;
+ u32 sid = vcom_sid_from_fd (fd);
+
+ if ((errno = -vcom_init ()))
+ return -1;
+
+ if (sid != INVALID_SESSION_ID)
{
- return -1;
+ clib_warning ("LDP<%d>: LDP-TBD", getpid ());
+ errno = ENOSYS;
+ size = -1;
}
+ else
+ {
+ func_str = "libc_recvmsg";
- return vcom_socket_recvmsg (__fd, __message, __flags);
-}
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "message %p, flags 0x%x",
+ getpid (), fd, fd, func_str, message, flags);
-ssize_t
-recvmsg (int __fd, struct msghdr * __message, int __flags)
-{
- ssize_t size;
- pid_t pid = getpid ();
+ size = libc_recvmsg (fd, message, flags);
+ }
- if (is_vcom_socket_fd (__fd))
+ if (VCOM_DEBUG > 2)
{
- size = vcom_recvmsg (__fd, __message, __flags);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] recvmsg: "
- "'%04d'='%04d', '%p', '%04x'\n",
- pid, (int) size, __fd, __message, __flags);
if (size < 0)
{
- errno = -size;
- return -1;
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, size, errno_val);
+ errno = errno_val;
}
- return size;
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, size, size);
}
- return libc_recvmsg (__fd, __message, __flags);
+ return size;
}
-#ifdef __USE_GNU
-/*
- * Receive up to VLEN messages as described by VMESSAGES from socket FD.
- * Returns the number of messages received or -1 for errors.
- * This function is a cancellation point and therefore not marked
- * with __THROW.
- * */
+#ifdef USE_GNU
int
-vcom_recvmmsg (int __fd, struct mmsghdr *__vmessages,
- unsigned int __vlen, int __flags, struct timespec *__tmo)
+recvmmsg (int fd, struct mmsghdr *vmessages,
+ unsigned int vlen, int flags, struct timespec *tmo)
{
- if (vcom_init () != 0)
+ ssize_t size;
+ const char *func_str;
+ u32 sid = vcom_sid_from_fd (fd);
+
+ if ((errno = -vcom_init ()))
+ return -1;
+
+ if (sid != INVALID_SESSION_ID)
{
- return -1;
+ clib_warning ("LDP<%d>: LDP-TBD", getpid ());
+ errno = ENOSYS;
+ size = -1;
}
+ else
+ {
+ func_str = "libc_recvmmsg";
- return vcom_socket_recvmmsg (__fd, __message, __vlen, __flags, __tmo);
-}
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "vmessages %p, vlen %u, flags 0x%x, tmo %p",
+ getpid (), fd, fd, func_str, vmessages, vlen,
+ flags, tmo);
-int
-recvmmsg (int __fd, struct mmsghdr *__vmessages,
- unsigned int __vlen, int __flags, struct timespec *__tmo)
-{
- ssize_t size;
- pid_t pid = getpid ();
+ size = libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
+ }
- if (is_vcom_socket_fd (__fd))
+ if (VCOM_DEBUG > 2)
{
- size = vcom_recvmmsg (__fd, __message, __vlen, __flags, __tmo);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] recvmmsg: "
- "'%04d'='%04d', '%p', "
- "'%04d', '%04x', '%p'\n",
- pid, (int) size, __fd, __vmessages, __vlen, __flags, __tmo);
if (size < 0)
{
- errno = -size;
- return -1;
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, size, errno_val);
+ errno = errno_val;
}
- return size;
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, size, size);
}
- return libc_recvmmsg (__fd, __message, __vlen, __flags, __tmo);
+ return size;
}
-
#endif
-/*
- * Put the current value for socket FD's option OPTNAME
- * at protocol level LEVEL into OPTVAL (which is *OPTLEN bytes long),
- * and set *OPTLEN to the value's actual length.
- * Returns 0 on success, -1 for errors.
- * */
int
-vcom_getsockopt (int __fd, int __level, int __optname,
- void *__restrict __optval, socklen_t * __restrict __optlen)
-{
- if (vcom_init () != 0)
- {
- return -1;
- }
-
- return vcom_socket_getsockopt (__fd, __level, __optname,
- __optval, __optlen);
-}
-
-int
-getsockopt (int __fd, int __level, int __optname,
- void *__restrict __optval, socklen_t * __restrict __optlen)
+getsockopt (int fd, int level, int optname,
+ void *__restrict optval, socklen_t * __restrict optlen)
{
int rv;
- pid_t pid = getpid ();
+ const char *func_str = __func__;
+ u32 sid = vcom_sid_from_fd (fd);
+ u32 buflen = (u32) * optlen;
+
+ if ((errno = -vcom_init ()))
+ return -1;
- if (is_vcom_socket_fd (__fd))
+ if (sid != INVALID_SESSION_ID)
{
- rv = vcom_getsockopt (__fd, __level, __optname, __optval, __optlen);
- if (VCOM_DEBUG > 2)
- fprintf (stderr,
- "[%d] getsockopt: "
- "'%04d'='%04d', '%04d', '%04d', "
- "'%p', '%p'\n",
- pid, rv, __fd, __level, __optname, __optval, __optlen);
- if (rv != 0)
+ rv = -EOPNOTSUPP;
+
+ switch (level)
+ {
+ case SOL_TCP:
+ switch (optname)
+ {
+ case TCP_NODELAY:
+ func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_NODELAY]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x)",
+ getpid (), fd, fd, func_str, sid, sid);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_NODELAY,
+ optval, optlen);
+ break;
+ case TCP_MAXSEG:
+ func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_USER_MSS]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x)",
+ getpid (), fd, fd, func_str, sid, sid);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_USER_MSS,
+ optval, optlen);
+ break;
+ case TCP_KEEPIDLE:
+ func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_KEEPIDLE]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x)",
+ getpid (), fd, fd, func_str, sid, sid);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
+ optval, optlen);
+ break;
+ case TCP_KEEPINTVL:
+ func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_KEEPINTVL]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x), SOL_TCP",
+ getpid (), fd, fd, func_str, sid, sid);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
+ optval, optlen);
+ break;
+ case TCP_INFO:
+ if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
+ {
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): sid %u (0x%x), "
+ "SOL_TCP, TCP_INFO, optval %p, "
+ "optlen %d: #LDP-NOP#",
+ getpid (), fd, fd, sid, sid,
+ optval, *optlen);
+ memset (optval, 0, *optlen);
+ rv = VPPCOM_OK;
+ }
+ else
+ rv = -EFAULT;
+ break;
+ default:
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
+ "sid %u (0x%x), SOL_TCP, "
+ "optname %d unsupported!",
+ getpid (), fd, fd, func_str, sid, sid, optname);
+ break;
+ }
+ break;
+ case SOL_IPV6:
+ switch (optname)
+ {
+ case IPV6_V6ONLY:
+ func_str = "vppcom_session_attr[SOL_IPV6,GET_V6ONLY]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x)",
+ getpid (), fd, fd, func_str, sid, sid);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_V6ONLY,
+ optval, optlen);
+ break;
+ default:
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
+ "sid %u (0x%x), SOL_IPV6, "
+ "optname %d unsupported!",
+ getpid (), fd, fd, func_str, sid, sid, optname);
+ break;
+ }
+ break;
+ case SOL_SOCKET:
+ switch (optname)
+ {
+ case SO_ACCEPTCONN:
+ func_str = "vppcom_session_attr[SOL_SOCKET,GET_ACCEPTCONN]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x)",
+ getpid (), fd, fd, func_str, sid, sid);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LISTEN,
+ optval, optlen);
+ break;
+ case SO_KEEPALIVE:
+ func_str = "vppcom_session_attr[SOL_SOCKET,GET_KEEPALIVE]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x)",
+ getpid (), fd, fd, func_str, sid, sid);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_KEEPALIVE,
+ optval, optlen);
+ break;
+ case SO_PROTOCOL:
+ func_str = "vppcom_session_attr[SOL_SOCKET,GET_PROTOCOL]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x)",
+ getpid (), fd, fd, func_str, sid, sid);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PROTOCOL,
+ optval, optlen);
+ *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
+ break;
+ case SO_SNDBUF:
+ func_str = "vppcom_session_attr[SOL_SOCKET,GET_TX_FIFO_LEN]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x), optlen %d",
+ getpid (), fd, fd, func_str, sid, sid, buflen);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TX_FIFO_LEN,
+ optval, optlen);
+ break;
+ case SO_RCVBUF:
+ func_str = "vppcom_session_attr[SOL_SOCKET,GET_RX_FIFO_LEN]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x), optlen %d",
+ getpid (), fd, fd, func_str, sid, sid, *optlen);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_RX_FIFO_LEN,
+ optval, optlen);
+ break;
+ case SO_REUSEADDR:
+ func_str = "vppcom_session_attr[SOL_SOCKET,GET_REUSEADDR]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x)",
+ getpid (), fd, fd, func_str, sid, sid);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_REUSEADDR,
+ optval, optlen);
+ break;
+ case SO_BROADCAST:
+ func_str = "vppcom_session_attr[SOL_SOCKET,GET_BROADCAST]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x)",
+ getpid (), fd, fd, func_str, sid, sid);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_BROADCAST,
+ optval, optlen);
+ break;
+ case SO_ERROR:
+ func_str = "vppcom_session_attr[SOL_SOCKET,GET_ERROR]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x)",
+ getpid (), fd, fd, func_str, sid, sid);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_ERROR,
+ optval, optlen);
+ break;
+ default:
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
+ "sid %u (0x%x), SOL_SOCKET, "
+ "optname %d unsupported!",
+ getpid (), fd, fd, func_str, sid, sid, optname);
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (rv != VPPCOM_OK)
{
errno = -rv;
- return -1;
+ rv = -1;
}
- return 0;
}
- return libc_getsockopt (__fd, __level, __optname, __optval, __optlen);
-}
-
-/*
- * Set socket FD's option OPTNAME at protocol level LEVEL
- * to *OPTVAL (which is OPTLEN bytes long).
- * Returns 0 on success, -1 for errors.
- * */
-int
-vcom_setsockopt (int __fd, int __level, int __optname,
- const void *__optval, socklen_t __optlen)
-{
- if (vcom_init () != 0)
+ else
{
- return -1;
- }
+ func_str = "libc_getsockopt";
- return vcom_socket_setsockopt (__fd, __level, __optname,
- __optval, __optlen);
-}
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): level %d, "
+ "optname %d, optval %p, optlen %d",
+ getpid (), fd, fd, func_str, level, optname,
+ optval, optlen);
-int
-setsockopt (int __fd, int __level, int __optname,
- const void *__optval, socklen_t __optlen)
-{
- int rv;
- pid_t pid = getpid ();
+ rv = libc_getsockopt (fd, level, optname, optval, optlen);
+ }
- if (is_vcom_socket_fd (__fd))
+ if (VCOM_DEBUG > 1)
{
- rv = vcom_setsockopt (__fd, __level, __optname, __optval, __optlen);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] setsockopt: "
- "'%04d'='%04d', '%04d', '%04d', "
- "'%p', '%04d'\n",
- pid, rv, __fd, __level, __optname, __optval, __optlen);
- if (rv != 0)
+ if (rv < 0)
{
- errno = -rv;
- return -1;
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, rv, errno_val);
+ errno = errno_val;
}
- return 0;
- }
- return libc_setsockopt (__fd, __level, __optname, __optval, __optlen);
-}
-
-/*
- * Prepare to accept connections on socket FD.
- * N connection requests will be queued before further
- * requests are refused.
- * Returns 0 on success, -1 for errors.
- * */
-int
-vcom_listen (int __fd, int __n)
-{
- if (vcom_init () != 0)
- {
- return -1;
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, rv, rv);
}
-
- return vcom_socket_listen (__fd, __n);
+ return rv;
}
int
-listen (int __fd, int __n)
+setsockopt (int fd, int level, int optname,
+ const void *optval, socklen_t optlen)
{
int rv;
- pid_t pid = getpid ();
+ const char *func_str = __func__;
+ u32 sid = vcom_sid_from_fd (fd);
+
+ if ((errno = -vcom_init ()))
+ return -1;
- if (is_vcom_socket_fd (__fd))
+ if (sid != INVALID_SESSION_ID)
{
- rv = vcom_listen (__fd, __n);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] listen: "
- "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __n);
- if (rv != 0)
+ rv = -EOPNOTSUPP;
+
+ switch (level)
+ {
+ case SOL_TCP:
+ switch (optname)
+ {
+ case TCP_NODELAY:
+ func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_NODELAY]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x)",
+ getpid (), fd, fd, func_str, sid, sid);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_NODELAY,
+ (void *) optval, &optlen);
+ break;
+ case TCP_MAXSEG:
+ func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_USER_MSS]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x)",
+ getpid (), fd, fd, func_str, sid, sid);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_USER_MSS,
+ (void *) optval, &optlen);
+ break;
+ case TCP_KEEPIDLE:
+ func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_KEEPIDLE]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x)",
+ getpid (), fd, fd, func_str, sid, sid);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
+ (void *) optval, &optlen);
+ break;
+ case TCP_KEEPINTVL:
+ func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_KEEPINTVL]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x), SOL_TCP",
+ getpid (), fd, fd, func_str, sid, sid);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
+ (void *) optval, &optlen);
+ break;
+ default:
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
+ "sid %u (0x%x), SOL_TCP, "
+ "optname %d unsupported!",
+ getpid (), fd, fd, func_str, sid, sid, optname);
+ break;
+ }
+ break;
+ case SOL_IPV6:
+ switch (optname)
+ {
+ case IPV6_V6ONLY:
+ func_str = "vppcom_session_attr[SOL_IPV6,SET_V6ONLY]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x)",
+ getpid (), fd, fd, func_str, sid, sid);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_V6ONLY,
+ (void *) optval, &optlen);
+ break;
+ default:
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
+ "sid %u (0x%x), SOL_IPV6, "
+ "optname %d unsupported!",
+ getpid (), fd, fd, func_str, sid, sid, optname);
+ break;
+ }
+ break;
+ case SOL_SOCKET:
+ switch (optname)
+ {
+ case SO_KEEPALIVE:
+ func_str = "vppcom_session_attr[SOL_SOCKET,SET_KEEPALIVE]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x)",
+ getpid (), fd, fd, func_str, sid, sid);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_KEEPALIVE,
+ (void *) optval, &optlen);
+ break;
+ case SO_REUSEADDR:
+ func_str = "vppcom_session_attr[SOL_SOCKET,SET_REUSEADDR]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x)",
+ getpid (), fd, fd, func_str, sid, sid);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_REUSEADDR,
+ (void *) optval, &optlen);
+ break;
+ case SO_BROADCAST:
+ func_str = "vppcom_session_attr[SOL_SOCKET,SET_BROADCAST]";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
+ "sid %u (0x%x)",
+ getpid (), fd, fd, func_str, sid, sid);
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_BROADCAST,
+ (void *) optval, &optlen);
+ break;
+ default:
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
+ "sid %u (0x%x), SOL_SOCKET, "
+ "optname %d unsupported!",
+ getpid (), fd, fd, func_str, sid, sid, optname);
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (rv != VPPCOM_OK)
{
errno = -rv;
- return -1;
+ rv = -1;
}
- return 0;
}
- return libc_listen (__fd, __n);
-}
+ else
+ {
+ func_str = "libc_setsockopt";
-/*
- * Await a connection on socket FD.
- * When a connection arrives, open a new socket to communicate
- * with it, set *ADDR (which is *ADDR_LEN bytes long) to the address
- * of the connecting peer and *ADDR_LEN to the address's actual
- * length, and return the new socket's descriptor, or -1 for errors.
- * This function is a cancellation point and therefore not marked
- * with __THROW.
- * */
-int
-vcom_accept (int __fd, __SOCKADDR_ARG __addr,
- socklen_t * __restrict __addr_len)
-{
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): level %d, "
+ "optname %d, optval %p, optlen %d",
+ getpid (), fd, fd, func_str, level, optname,
+ optval, optlen);
- if (vcom_init () != 0)
- {
- return -1;
+ rv = libc_setsockopt (fd, level, optname, optval, optlen);
}
- return vcom_socket_accept (__fd, __addr, __addr_len);
-}
-int
-accept (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len)
-{
- int rv = -1;
- pid_t pid = getpid ();
- pthread_t tid = pthread_self ();
-
- if (is_vcom_socket_fd (__fd))
+ if (VCOM_DEBUG > 1)
{
- if (VCOM_DEBUG > 0)
- vcom_socket_main_show ();
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d][%lu (0x%lx)] accept1: "
- "'%04d'='%04d', '%p', '%p'\n",
- pid, (unsigned long) tid, (unsigned long) tid,
- rv, __fd, __addr, __addr_len);
- rv = vcom_accept (__fd, __addr, __addr_len);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d][%lu (0x%lx)] accept2: "
- "'%04d'='%04d', '%p', '%p'\n",
- pid, (unsigned long) tid, (unsigned long) tid,
- rv, __fd, __addr, __addr_len);
- if (VCOM_DEBUG > 0)
- vcom_socket_main_show ();
if (rv < 0)
{
- errno = -rv;
- return -1;
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, rv, errno_val);
+ errno = errno_val;
}
- return rv;
- }
- return libc_accept (__fd, __addr, __addr_len);
-}
-
-/*
- * Similar to 'accept' but takes an additional parameter to specify
- * flags.
- * This function is a cancellation point and therefore not marked
- * with __THROW.
- * */
-int
-vcom_accept4 (int __fd, __SOCKADDR_ARG __addr,
- socklen_t * __restrict __addr_len, int __flags)
-{
-
- if (vcom_init () != 0)
- {
- return -1;
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, rv, rv);
}
-
- return vcom_socket_accept4 (__fd, __addr, __addr_len, __flags);
+ return rv;
}
int
-accept4 (int __fd, __SOCKADDR_ARG __addr,
- socklen_t * __restrict __addr_len, int __flags)
+listen (int fd, int n)
{
- int rv = 0;
- pid_t pid = getpid ();
+ int rv;
+ const char *func_str;
+ u32 sid = vcom_sid_from_fd (fd);
- fprintf (stderr,
- "[%d] accept4: in the beginning... "
- "'%04d'='%04d', '%p', '%p', '%04x'\n",
- pid, rv, __fd, __addr, __addr_len, __flags);
+ if ((errno = -vcom_init ()))
+ return -1;
- if (is_vcom_socket_fd (__fd))
+ if (sid != INVALID_SESSION_ID)
{
+ func_str = "vppcom_session_listen";
+
if (VCOM_DEBUG > 0)
- vcom_socket_main_show ();
- rv = vcom_accept4 (__fd, __addr, __addr_len, __flags);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] accept4: VCL "
- "'%04d'='%04d', '%p', '%p', '%04x'\n",
- pid, rv, __fd, __addr, __addr_len, __flags);
- if (VCOM_DEBUG > 0)
- vcom_socket_main_show ();
- if (rv < 0)
+ clib_warning
+ ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), n %d",
+ getpid (), fd, fd, func_str, sid, sid, n);
+
+ rv = vppcom_session_listen (sid, n);
+ if (rv != VPPCOM_OK)
{
errno = -rv;
- return -1;
+ rv = -1;
}
- return rv;
}
- fprintf (stderr,
- "[%d] accept4: libc "
- "'%04d'='%04d', '%p', '%p', '%04x'\n",
- pid, rv, __fd, __addr, __addr_len, __flags);
+ else
+ {
+ func_str = "libc_listen";
- return libc_accept4 (__fd, __addr, __addr_len, __flags);
-}
+ if (VCOM_DEBUG > 0)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): n %d",
+ getpid (), fd, fd, func_str, n);
-/*
- * Shut down all or part of the connection open on socket FD.
- * HOW determines what to shut down:
- * SHUT_RD = No more receptions;
- * SHUT_WR = No more transmissions;
- * SHUT_RDWR = No more receptions or transmissions.
- * Returns 0 on success, -1 for errors.
- * */
-int
-vcom_shutdown (int __fd, int __how)
-{
- if (vcom_init () != 0)
- {
- return -1;
+ rv = libc_listen (fd, n);
}
- return vcom_socket_shutdown (__fd, __how);
-}
-
-int
-shutdown (int __fd, int __how)
-{
- int rv;
- pid_t pid = getpid ();
- if (is_vcom_socket_fd (__fd))
+ if (VCOM_DEBUG > 0)
{
- rv = vcom_shutdown (__fd, __how);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] shutdown: "
- "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __how);
- if (rv != 0)
+ if (rv < 0)
{
- errno = -rv;
- return -1;
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, rv, errno_val);
+ errno = errno_val;
}
- return 0;
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, rv, rv);
}
- return libc_shutdown (__fd, __how);
+ return rv;
}
-int
-vcom_epoll_create (int __size)
+static inline int
+vcom_accept4 (int listen_fd, __SOCKADDR_ARG addr,
+ socklen_t * __restrict addr_len, int flags)
{
+ int rv;
+ const char *func_str;
+ u32 listen_sid = vcom_sid_from_fd (listen_fd);
+ int accept_sid;
- if (vcom_init () != 0)
- {
- return -1;
- }
+ if ((errno = -vcom_init ()))
+ return -1;
- if (__size <= 0)
+ if (listen_sid != INVALID_SESSION_ID)
{
- return -EINVAL;
- }
+ vppcom_endpt_t ep;
+ u8 src_addr[sizeof (struct sockaddr_in6)];
+ ep.ip = src_addr;
- /* __size argument is ignored "thereafter" */
- return vcom_epoll_create1 (0);
-}
+ func_str = "vppcom_session_accept";
-/*
- * __size argument is ignored, but must be greater than zero
- */
-int
-epoll_create (int __size)
-{
- int rv = 0;
- pid_t pid = getpid ();
+ if (VCOM_DEBUG > 0)
+ clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): "
+ "listen sid %u (0x%x), ep %p, flags 0x%x",
+ getpid (), listen_fd, listen_fd, func_str,
+ listen_sid, listen_sid, ep, flags);
- rv = vcom_epoll_create (__size);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] epoll_create: " "'%04d'='%04d'\n", pid, rv, __size);
- if (rv < 0)
- {
- errno = -rv;
- return -1;
+ accept_sid = vppcom_session_accept (listen_sid, &ep, flags);
+ if (accept_sid < 0)
+ {
+ errno = -accept_sid;
+ rv = -1;
+ }
+ else
+ {
+ rv = vcom_copy_ep_to_sockaddr (addr, addr_len, &ep);
+ if (rv != VPPCOM_OK)
+ {
+ (void) vppcom_session_close ((u32) accept_sid);
+ errno = -rv;
+ rv = -1;
+ }
+ else
+ {
+ func_str = "vcom_fd_from_sid";
+ if (VCOM_DEBUG > 0)
+ clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): "
+ "accept sid %u (0x%x), ep %p, flags 0x%x",
+ getpid (), listen_fd, listen_fd,
+ func_str, accept_sid, accept_sid, ep, flags);
+ rv = vcom_fd_from_sid ((u32) accept_sid);
+ if (rv < 0)
+ {
+ (void) vppcom_session_close ((u32) accept_sid);
+ errno = -rv;
+ rv = -1;
+ }
+ }
+ }
}
- return rv;
-}
-
-int
-vcom_epoll_create1 (int __flags)
-{
- if (vcom_init () != 0)
+ else
{
- return -1;
- }
+ func_str = "libc_accept4";
- if (__flags < 0)
- {
- return -EINVAL;
- }
- if (__flags & ~EPOLL_CLOEXEC)
- {
- return -EINVAL;
- }
- /* __flags can be either zero or EPOLL_CLOEXEC */
- /* implementation */
- return vcom_socket_epoll_create1 (__flags);
-}
+ if (VCOM_DEBUG > 0)
+ clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): "
+ "addr %p, addr_len %p, flags 0x%x",
+ getpid (), listen_fd, listen_fd, func_str,
+ addr, addr_len, flags);
-/*
- * __flags can be either zero or EPOLL_CLOEXEC
- * */
-int
-epoll_create1 (int __flags)
-{
- int rv = 0;
- pid_t pid = getpid ();
+ rv = libc_accept4 (listen_fd, addr, addr_len, flags);
+ }
- rv = vcom_epoll_create1 (__flags);
if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] epoll_create: " "'%04d'='%08x'\n", pid, rv, __flags);
- if (rv < 0)
{
- errno = -rv;
- return -1;
+ if (rv < 0)
+ {
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: listen fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), listen_fd,
+ listen_fd, func_str, rv, errno_val);
+ errno = errno_val;
+ }
+ else
+ clib_warning ("LDP<%d>: listen fd %d (0x%x): returning %d (0x%x)",
+ getpid (), listen_fd, listen_fd, rv, rv);
}
return rv;
}
-static inline int
-ep_op_has_event (int op)
+int
+accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
+ int flags)
{
- return op != EPOLL_CTL_DEL;
+ return vcom_accept4 (fd, addr, addr_len, flags);
}
int
-vcom_epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event)
+accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
{
- if (vcom_init () != 0)
- {
- return -1;
- }
-
- /*
- * the requested operation __op is not supported
- * by this interface */
- if (!((__op == EPOLL_CTL_ADD) ||
- (__op == EPOLL_CTL_MOD) || (__op == EPOLL_CTL_DEL)))
- {
- return -EINVAL;
- }
-
- /* op is ADD or MOD but event parameter is NULL */
- if ((ep_op_has_event (__op) && !__event))
- {
- return -EFAULT;
- }
-
- /* fd is same as epfd */
- /* do not permit adding an epoll file descriptor inside itself */
- if (__epfd == __fd)
- {
- return -EINVAL;
- }
-
- /* implementation */
- return vcom_socket_epoll_ctl (__epfd, __op, __fd, __event);
+ return vcom_accept4 (fd, addr, addr_len, 0);
}
-/*
- * implement the controller interface for epoll
- * that enables the insertion/removal/change of
- * file descriptors inside the interest set.
- */
int
-epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event)
+shutdown (int fd, int how)
{
int rv;
- pid_t pid = getpid ();
+ const char *func_str;
+ u32 sid = vcom_sid_from_fd (fd);
- rv = vcom_epoll_ctl (__epfd, __op, __fd, __event);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] epoll_ctl: "
- "'%04d'='%04d', '%04d', '%04d'\n", pid, rv, __epfd, __op, __fd);
- if (rv != 0)
+ if ((errno = -vcom_init ()))
+ return -1;
+
+ if (sid != INVALID_SESSION_ID)
{
- errno = -rv;
- return -1;
+ clib_warning ("LDP<%d>: LDP-TBD", getpid ());
+ errno = ENOSYS;
+ rv = -1;
}
- return 0;
-}
+ else
+ {
+ func_str = "libc_shutdown";
-int
-epoll_wait (int __epfd, struct epoll_event *__events,
- int __maxevents, int __timeout)
-{
- int rv;
- pid_t pid = getpid ();
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): how %d",
+ getpid (), fd, fd, func_str, how);
- if (__maxevents <= 0 || __maxevents > EP_MAX_EVENTS)
- {
- fprintf (stderr, "[%d] ERROR: epoll_wait() invalid maxevents %d\n",
- pid, __maxevents);
- errno = EINVAL;
- return -1;
+ rv = libc_shutdown (fd, how);
}
- rv =
- vcom_socket_epoll_pwait (__epfd, __events, __maxevents, __timeout, NULL);
- if (VCOM_DEBUG > 2)
- fprintf (stderr,
- "[%d] epoll_wait: "
- "'%04d'='%04d', '%p', "
- "'%04d', '%04d'\n",
- pid, rv, __epfd, __events, __maxevents, __timeout);
- if (rv < 0)
+ if (VCOM_DEBUG > 1)
{
- errno = -rv;
- return -1;
+ if (rv < 0)
+ {
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, rv, errno_val);
+ errno = errno_val;
+ }
+ else
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, rv, rv);
}
return rv;
}
-
int
-epoll_pwait (int __epfd, struct epoll_event *__events,
- int __maxevents, int __timeout, const __sigset_t * __ss)
+epoll_create1 (int flags)
{
+ const char *func_str;
int rv;
- pid_t pid = getpid ();
- if (__maxevents <= 0 || __maxevents > EP_MAX_EVENTS)
+ if ((errno = -vcom_init ()))
+ return -1;
+
+ func_str = "vppcom_epoll_create";
+
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: calling %s()", getpid (), func_str);
+
+ rv = vppcom_epoll_create ();
+
+ if (PREDICT_FALSE (rv < 0))
{
- errno = EINVAL;
- return -1;
+ errno = -rv;
+ rv = -1;
}
+ else
+ rv = vcom_fd_from_sid ((u32) rv);
- if (is_vcom_epfd (__epfd))
+ if (VCOM_DEBUG > 1)
{
- rv =
- vcom_socket_epoll_pwait (__epfd, __events, __maxevents, __timeout,
- __ss);
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] epoll_pwait: "
- "'%04d'='%04d', '%p', "
- "'%04d', '%04d', "
- "'%p'\n",
- pid, rv, __epfd, __events, __maxevents, __timeout, __ss);
if (rv < 0)
{
- errno = -rv;
- return -1;
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: %s() failed! "
+ "rv %d, errno = %d",
+ getpid (), func_str, rv, errno_val);
+ errno = errno_val;
}
- return rv;
- }
- else
- {
- errno = EINVAL;
- return -1;
+ else
+ clib_warning ("LDP<%d>: returning epfd %d (0x%x)", getpid (), rv, rv);
}
-
- return 0;
+ return rv;
}
-/* Poll the file descriptors described by the NFDS structures starting at
- FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
- an event to occur; if TIMEOUT is -1, block until an event occurs.
- Returns the number of file descriptors with events, zero if timed out,
- or -1 for errors.
-
- This function is a cancellation point and therefore not marked with
- __THROW. */
+int
+epoll_create (int size)
+{
+ return epoll_create1 (0);
+}
int
-vcom_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
+epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
{
- int rv = 0;
- pid_t pid = getpid ();
+ int rv;
+ const char *func_str;
+ u32 vep_idx = vcom_sid_from_fd (epfd);
- struct rlimit nofile_limit;
- struct pollfd vcom_fds[MAX_POLL_NFDS_DEFAULT];
- nfds_t fds_idx = 0;
+ if ((errno = -vcom_init ()))
+ return -1;
- /* actual set of file descriptors to be monitored */
- nfds_t libc_nfds = 0;
- nfds_t vcom_nfds = 0;
+ if (vep_idx != INVALID_SESSION_ID)
+ {
+ u32 sid = vcom_sid_from_fd (fd);
- /* ready file descriptors
- *
- * number of structures which have nonzero revents fields
- * in other words, descriptors with events or errors reported.
- * */
- /* after call to libc_poll () */
- int rlibc_nfds = 0;
- /* after call to vcom_socket_poll () */
- int rvcom_nfds = 0;
+ if (sid != INVALID_SESSION_ID)
+ {
+ func_str = "vppcom_epoll_create";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): "
+ "vep_idx %d (0x%x), op %d, sid %u (0x%x), event %p",
+ getpid (), epfd, epfd, func_str, vep_idx, vep_idx,
+ sid, sid, event);
- /* timeout value in units of timespec */
- struct timespec timeout_ts;
- struct timespec start_time, now, end_time;
+ rv = vppcom_epoll_ctl (vep_idx, op, sid, event);
+ if (rv != VPPCOM_OK)
+ {
+ errno = -rv;
+ rv = -1;
+ }
+ }
+ else
+ {
+ int epfd;
+ u32 size = sizeof (epfd);
+
+ func_str = "vppcom_session_attr[GET_LIBC_EPFD]";
+ epfd = vppcom_session_attr (vep_idx, VPPCOM_ATTR_GET_LIBC_EPFD,
+ 0, 0);
+ if (!epfd)
+ {
+ func_str = "libc_epoll_create1";
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: calling %s(): EPOLL_CLOEXEC",
+ getpid (), func_str);
+
+ epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
+ if (epfd < 0)
+ {
+ rv = epfd;
+ goto done;
+ }
+
+ func_str = "vppcom_session_attr[SET_LIBC_EPFD]";
+ rv = vppcom_session_attr (vep_idx, VPPCOM_ATTR_SET_LIBC_EPFD,
+ &epfd, &size);
+ if (rv < 0)
+ {
+ errno = -rv;
+ rv = -1;
+ goto done;
+ }
+ }
+ else if (PREDICT_FALSE (epfd < 0))
+ {
+ errno = -epfd;
+ rv = -1;
+ goto done;
+ }
- /* get start_time */
- rv = clock_gettime (CLOCK_MONOTONIC, &start_time);
- if (rv == -1)
+ rv = libc_epoll_ctl (epfd, op, fd, event);
+ }
+ }
+ else
{
- rv = -errno;
- goto poll_done;
+ func_str = "libc_epoll_ctl";
+
+ if (VCOM_DEBUG > 1)
+ clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): "
+ "op %d, fd %d (0x%x), event %p",
+ getpid (), epfd, epfd, func_str, op, fd, fd, event);
+
+ rv = libc_epoll_ctl (epfd, op, fd, event);
}
- /* set timeout_ts & end_time */
- if (__timeout >= 0)
+done:
+ if (VCOM_DEBUG > 1)
{
- /* set timeout_ts */
- timeout_ts.tv_sec = __timeout / MSEC_PER_SEC;
- timeout_ts.tv_nsec = (__timeout % MSEC_PER_SEC) * NSEC_PER_MSEC;
- set_normalized_timespec (&timeout_ts,
- timeout_ts.tv_sec, timeout_ts.tv_nsec);
- /* set end_time */
- if (__timeout)
+ if (rv < 0)
{
- end_time = timespec_add (start_time, timeout_ts);
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), fd, fd,
+ func_str, rv, errno_val);
+ errno = errno_val;
}
else
- {
- end_time = start_time;
- }
+ clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
+ getpid (), fd, fd, rv, rv);
}
+ return rv;
+}
- if (vcom_init () != 0)
- {
- rv = -1;
- goto poll_done;
- }
+static inline int
+vcom_epoll_pwait (int epfd, struct epoll_event *events,
+ int maxevents, int timeout, const sigset_t * sigmask)
+{
+ const char *func_str;
+ int rv;
+ double time_to_wait = (double) 0;
+ double time_out, now = 0;
+ u32 vep_idx = vcom_sid_from_fd (epfd);
+ int libc_epfd;
- /* validate __fds */
- if (!__fds)
- {
- rv = -EFAULT;
- goto poll_done;
- }
+ if ((errno = -vcom_init ()))
+ return -1;
- /* validate __nfds */
- /*TBD: call getrlimit once when vcl-ldpreload library is init */
- rv = getrlimit (RLIMIT_NOFILE, &nofile_limit);
- if (rv != 0)
+ if (PREDICT_FALSE (!events || (timeout < -1)))
{
- rv = -errno;
- goto poll_done;
- }
- if (__nfds >= nofile_limit.rlim_cur)
- {
- rv = -EINVAL;
- goto poll_done;
+ errno = EFAULT;
+ return -1;
}
- /*
- * for the POC, it's fair to assume that nfds is less than 1024
- * */
- if (__nfds >= MAX_POLL_NFDS_DEFAULT)
+ if (PREDICT_FALSE (vep_idx == INVALID_SESSION_ID))
{
- rv = -EINVAL;
- goto poll_done;
+ clib_warning ("LDP<%d>: ERROR: epfd %d (0x%x): bad vep_idx %d (0x%x)!",
+ getpid (), epfd, epfd, vep_idx, vep_idx);
+ errno = EBADFD;
+ return -1;
}
- /* set revents field (output parameter)
- * to zero
- * */
- for (fds_idx = 0; fds_idx < __nfds; fds_idx++)
+ time_to_wait = ((timeout >= 0) ? (double) timeout / (double) 1000 : 0);
+ time_out = clib_time_now (&vcom->clib_time) + time_to_wait;
+
+ func_str = "vppcom_session_attr[GET_LIBC_EPFD]";
+ libc_epfd = vppcom_session_attr (vep_idx, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
+ if (PREDICT_FALSE (libc_epfd < 0))
{
- __fds[fds_idx].revents = 0;
+ errno = -libc_epfd;
+ rv = -1;
+ goto done;
}
-#if 0
- /* set revents field (output parameter)
- * to zero for user ignored fds
- * */
- for (fds_idx = 0; fds_idx < __nfds; fds_idx++)
+ if (VCOM_DEBUG > 2)
+ clib_warning ("LDP<%d>: epfd %d (0x%x): vep_idx %d (0x%x), "
+ "libc_epfd %d (0x%x), events %p, maxevents %d, "
+ "timeout %d, sigmask %p", getpid (), epfd, epfd,
+ vep_idx, vep_idx, libc_epfd, libc_epfd, events,
+ maxevents, timeout, sigmask);
+ do
{
- /*
- * if negative fd, ignore events field
- * and set output parameter (revents field) to zero */
- if (__fds[fds_idx].fd < 0)
+ if (!vcom->epoll_wait_vcl)
{
- __fds[fds_idx].revents = 0;
- }
- }
-#endif
+ func_str = "vppcom_epoll_wait";
- /*
- * 00. prepare __fds and vcom_fds for polling
- * copy __fds to vcom_fds
- * 01. negate all except libc fds in __fds,
- * ignore user negated fds
- * 02. negate all except vcom_fds in vocm fds,
- * ignore user negated fds
- * ignore fd 0 by setting it to negative number
- * */
- memcpy (vcom_fds, __fds, sizeof (*__fds) * __nfds);
- libc_nfds = 0;
- vcom_nfds = 0;
- for (fds_idx = 0; fds_idx < __nfds; fds_idx++)
- {
- /* ignore negative fds */
- if (__fds[fds_idx].fd < 0)
- {
- continue;
- }
-
- /*
- * 00. ignore vcom fds in __fds
- * 01. ignore libc fds in vcom_fds,
- * ignore fd 0 by setting it to negative number.
- * as fd 0 cannot be ignored.
- */
- if (is_vcom_socket_fd (__fds[fds_idx].fd) ||
- is_vcom_epfd (__fds[fds_idx].fd))
- {
- __fds[fds_idx].fd = -__fds[fds_idx].fd;
- vcom_nfds++;
+ if (VCOM_DEBUG > 3)
+ clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): "
+ "vep_idx %d (0x%x), events %p, maxevents %d",
+ getpid (), epfd, epfd, func_str,
+ vep_idx, vep_idx, events, maxevents);
+
+ rv = vppcom_epoll_wait (vep_idx, events, maxevents, 0);
+ if (rv > 0)
+ {
+ vcom->epoll_wait_vcl = 1;
+ goto done;
+ }
+ else if (rv < 0)
+ {
+ errno = -rv;
+ rv = -1;
+ goto done;
+ }
}
else
+ vcom->epoll_wait_vcl = 0;
+
+ if (libc_epfd > 0)
{
- libc_nfds++;
- /* ignore fd 0 by setting it to negative number */
- if (!vcom_fds[fds_idx].fd)
- {
- vcom_fds[fds_idx].fd = -1;
- }
- vcom_fds[fds_idx].fd = -vcom_fds[fds_idx].fd;
+ func_str = "libc_epoll_pwait";
+
+ if (VCOM_DEBUG > 3)
+ clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): "
+ "libc_epfd %d (0x%x), events %p, "
+ "maxevents %d, sigmask %p",
+ getpid (), epfd, epfd, func_str,
+ libc_epfd, libc_epfd, events, maxevents, sigmask);
+
+ rv = libc_epoll_pwait (epfd, events, maxevents, 1, sigmask);
+ if (rv != 0)
+ goto done;
}
+
+ if (timeout != -1)
+ now = clib_time_now (&vcom->clib_time);
}
+ while (now < time_out);
- /*
- * polling loop
- *
- * poll on libc fds and vcom fds
- *
- * specifying a timeout of zero causes libc_poll() and
- * vcom_socket_poll() to return immediately, even if no
- * file descriptors are ready
- * */
- do
+done:
+ if (VCOM_DEBUG > 3)
{
- rlibc_nfds = 0;
- rvcom_nfds = 0;
+ if (rv < 0)
+ {
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: epfd %d (0x%x): %s() failed! "
+ "rv %d, errno = %d", getpid (), epfd, epfd,
+ func_str, rv, errno_val);
+ errno = errno_val;
+ }
+ else
+ clib_warning ("LDP<%d>: epfd %d (0x%x): returning %d (0x%x)",
+ getpid (), epfd, epfd, rv, rv);
+ }
+ return rv;
+}
+
+int
+epoll_pwait (int epfd, struct epoll_event *events,
+ int maxevents, int timeout, const sigset_t * sigmask)
+{
+ return vcom_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
+}
+
+int
+epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
+{
+ return vcom_epoll_pwait (epfd, events, maxevents, timeout, NULL);
+}
+
+int
+poll (struct pollfd *fds, nfds_t nfds, int timeout)
+{
+ const char *func_str = __func__;
+ int rv, i, n_libc_fds, n_revents;
+ u32 sid;
+ vcl_poll_t *vp;
+ double wait_for_time;
+
+ if (VCOM_DEBUG > 3)
+ clib_warning ("LDP<%d>: fds %p, nfds %d, timeout %d",
+ getpid (), fds, nfds, timeout);
- /*
- * timeout parameter for libc_poll () set to zero
- * to poll on libc fds
- * */
+ if (timeout >= 0)
+ wait_for_time = (f64) timeout / 1000;
+ else
+ wait_for_time = -1;
- /* poll on libc fds */
- if (libc_nfds)
+ n_libc_fds = 0;
+ for (i = 0; i < nfds; i++)
+ {
+ if (fds[i].fd >= 0)
{
- /*
- * a timeout of zero causes libc_poll()
- * to return immediately
- * */
- rlibc_nfds = libc_poll (__fds, __nfds, 0);
- if (VCOM_DEBUG > 2)
- fprintf (stderr,
- "[%d] poll libc: "
- "'%04d'='%08lu'\n", pid, rlibc_nfds, __nfds);
+ if (VCOM_DEBUG > 3)
+ clib_warning ("LDP<%d>: fds[%d].fd %d (0x%0x), .events = 0x%x, "
+ ".revents = 0x%x", getpid (), i, fds[i].fd,
+ fds[i].fd, fds[i].events, fds[i].revents);
- if (rlibc_nfds < 0)
+ sid = vcom_sid_from_fd (fds[i].fd);
+ if (sid != INVALID_SESSION_ID)
{
- rv = -errno;
- goto poll_done_update_nfds;
+ fds[i].fd = -fds[i].fd;
+ vec_add2 (vcom->vcl_poll, vp, 1);
+ vp->fds_ndx = i;
+ vp->sid = sid;
+ vp->events = fds[i].events;
+#ifdef __USE_XOPEN2K
+ if (fds[i].events & POLLRDNORM)
+ vp->events |= POLLIN;
+ if (fds[i].events & POLLWRNORM)
+ vp->events |= POLLOUT;
+#endif
+ vp->revents = &fds[i].revents;
}
+ else
+ n_libc_fds++;
}
+ }
- /*
- * timeout parameter for vcom_socket_poll () set to zero
- * to poll on vcom fds
- * */
-
- /* poll on vcom fds */
- if (vcom_nfds)
+ n_revents = 0;
+ do
+ {
+ if (vec_len (vcom->vcl_poll))
{
- /*
- * a timeout of zero causes vcom_socket_poll()
- * to return immediately
- * */
- rvcom_nfds = vcom_socket_poll (vcom_fds, __nfds, 0);
- if (VCOM_DEBUG > 2)
- fprintf (stderr,
- "[%d] poll vcom: "
- "'%04d'='%08lu'\n", pid, rvcom_nfds, __nfds);
- if (rvcom_nfds < 0)
+ func_str = "vppcom_poll";
+
+ if (VCOM_DEBUG > 3)
+ clib_warning ("LDP<%d>: calling %s(): "
+ "vcl_poll %p, n_sids %u (0x%x): "
+ "n_libc_fds %u",
+ getpid (), func_str, vcom->vcl_poll,
+ vec_len (vcom->vcl_poll), vec_len (vcom->vcl_poll),
+ n_libc_fds);
+
+ rv = vppcom_poll (vcom->vcl_poll, vec_len (vcom->vcl_poll), 0);
+ if (rv < 0)
{
- rv = rvcom_nfds;
- goto poll_done_update_nfds;
+ errno = -rv;
+ rv = -1;
+ goto done;
}
+ else
+ n_revents += rv;
}
- /* check if any file descriptors changed status */
- if ((libc_nfds && rlibc_nfds > 0) || (vcom_nfds && rvcom_nfds > 0))
+ if (n_libc_fds)
{
- /* something interesting happened */
- rv = rlibc_nfds + rvcom_nfds;
- goto poll_done_update_nfds;
+ func_str = "libc_poll";
+
+ if (VCOM_DEBUG > 3)
+ clib_warning ("LDP<%d>: calling %s(): fds %p, nfds %u: n_sids %u",
+ getpid (), fds, nfds, vec_len (vcom->vcl_poll));
+
+ rv = libc_poll (fds, nfds, 0);
+ if (rv < 0)
+ goto done;
+ else
+ n_revents += rv;
}
- rv = clock_gettime (CLOCK_MONOTONIC, &now);
- if (rv == -1)
+ if (n_revents)
{
- rv = -errno;
- goto poll_done_update_nfds;
+ rv = n_revents;
+ goto done;
}
}
-
- /* block indefinitely || timeout elapsed */
- while ((__timeout < 0) || timespec_compare (&now, &end_time) < 0);
-
- /* timeout expired before anything interesting happened */
+ while ((wait_for_time == -1) ||
+ (clib_time_now (&vcom->clib_time) < wait_for_time));
rv = 0;
-poll_done_update_nfds:
- for (fds_idx = 0; fds_idx < __nfds; fds_idx++)
+done:
+ vec_foreach (vp, vcom->vcl_poll)
+ {
+ fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
+#ifdef __USE_XOPEN2K
+ if ((fds[vp->fds_ndx].revents & POLLIN) &&
+ (fds[vp->fds_ndx].events & POLLRDNORM))
+ fds[vp->fds_ndx].revents |= POLLRDNORM;
+ if ((fds[vp->fds_ndx].revents & POLLOUT) &&
+ (fds[vp->fds_ndx].events & POLLWRNORM))
+ fds[vp->fds_ndx].revents |= POLLWRNORM;
+#endif
+ }
+ vec_reset_length (vcom->vcl_poll);
+
+ if (VCOM_DEBUG > 3)
{
- /* ignore negative fds in vcom_fds
- * 00. user negated fds
- * 01. libc fds
- * */
- if (vcom_fds[fds_idx].fd < 0)
+ if (rv < 0)
{
- continue;
+ int errno_val = errno;
+ perror (func_str);
+ clib_warning ("LDP<%d>: ERROR: %s() failed! "
+ "rv %d, errno = %d", getpid (),
+ func_str, rv, errno_val);
+ errno = errno_val;
}
-
- /* from here on handle positive vcom fds */
- /*
- * restore vcom fds to positive number in __fds
- * and update revents in __fds with the events
- * that actually occurred in vcom fds
- * */
- __fds[fds_idx].fd = -__fds[fds_idx].fd;
- if (rvcom_nfds)
+ else
{
- __fds[fds_idx].revents = vcom_fds[fds_idx].revents;
+ clib_warning ("LDP<%d>: returning %d (0x%x): n_sids %u, "
+ "n_libc_fds %d", getpid (), rv, rv,
+ vec_len (vcom->vcl_poll), n_libc_fds);
+
+ for (i = 0; i < nfds; i++)
+ {
+ if (fds[i].fd >= 0)
+ {
+ if (VCOM_DEBUG > 3)
+ clib_warning ("LDP<%d>: fds[%d].fd %d (0x%0x), "
+ ".events = 0x%x, .revents = 0x%x",
+ getpid (), i, fds[i].fd, fds[i].fd,
+ fds[i].events, fds[i].revents);
+ }
+ }
}
}
-poll_done:
- if (VCOM_DEBUG > 2)
- fprintf (stderr, "[%d] vpoll: " "'%04d'='%08lu'\n", pid, rv, __nfds);
return rv;
}
-/*
- * 00. The field __fds[i].fd contains a file descriptor for an
- * open file.
- * If this field is negative, then the corresponding
- * events field is ignored and the revents field returns zero.
- * The field __fds[i].events is an input parameter.
- * The field __fds[i].revents is an output parameter.
- * 01. Specifying a negative value in timeout
- * means an infinite timeout.
- * Specifying a timeout of zero causes poll() to return
- * immediately, even if no file descriptors are ready.
- *
- * NOTE: observed __nfds is less than 128 from kubecon strace files
- */
-
-
+#ifdef USE_GNU
int
-poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
+ppoll (struct pollfd *fds, nfds_t nfds,
+ const struct timespec *timeout, const sigset_t * sigmask)
{
- int rv = 0;
- pid_t pid = getpid ();
-
-
- if (VCOM_DEBUG > 2)
- fprintf (stderr, "[%d] poll1: " "'%04d'='%08lu, %d, 0x%x'\n",
- pid, rv, __nfds, __fds[0].fd, __fds[0].events);
- rv = vcom_poll (__fds, __nfds, __timeout);
- if (VCOM_DEBUG > 2)
- fprintf (stderr, "[%d] poll2: " "'%04d'='%08lu, %d, 0x%x'\n",
- pid, rv, __nfds, __fds[0].fd, __fds[0].revents);
- if (rv < 0)
- {
- errno = -rv;
- return -1;
- }
- return rv;
-}
-
-#ifdef __USE_GNU
-/* Like poll, but before waiting the threads signal mask is replaced
- with that specified in the fourth parameter. For better usability,
- the timeout value is specified using a TIMESPEC object.
-
- This function is a cancellation point and therefore not marked with
- __THROW. */
-int
-vcom_ppoll (struct pollfd *__fds, nfds_t __nfds,
- const struct timespec *__timeout, const __sigset_t * __ss)
-{
- if (vcom_init () != 0)
- {
- return -1;
- }
+ if ((errno = -vcom_init ()))
+ return -1;
- return -EOPNOTSUPP;
-}
+ clib_warning ("LDP<%d>: LDP-TBD", getpid ());
+ errno = ENOSYS;
-int
-ppoll (struct pollfd *__fds, nfds_t __nfds,
- const struct timespec *__timeout, const __sigset_t * __ss)
-{
- int rv = 0;
- errno = EOPNOTSUPP;
- rv = -1;
- return rv;
+ return -1;
}
#endif
@@ -3283,20 +3398,18 @@ void CONSTRUCTOR_ATTRIBUTE vcom_constructor (void);
void DESTRUCTOR_ATTRIBUTE vcom_destructor (void);
+/*
+ * This function is called when the library is loaded
+ */
void
vcom_constructor (void)
{
- pid_t pid = getpid ();
-
swrap_constructor ();
if (vcom_init () != 0)
- {
- printf ("\n[%d] vcom_constructor...failed!\n", pid);
- }
+ fprintf (stderr, "\nLDP<%d>: ERROR: vcom_constructor: failed!\n",
+ getpid ());
else
- {
- printf ("\n[%d] vcom_constructor...done!\n", pid);
- }
+ clib_warning ("LDP<%d>: VCOM constructor: done!\n", getpid ());
}
/*
@@ -3305,11 +3418,18 @@ vcom_constructor (void)
void
vcom_destructor (void)
{
- pid_t pid = getpid ();
-
- vcom_destroy ();
swrap_destructor ();
- printf ("\n[%d] vcom_destructor...done!\n", pid);
+ if (vcom->init)
+ {
+ vppcom_app_destroy ();
+ vcom->init = 0;
+ }
+
+ /* Don't use clib_warning() here because that calls writev()
+ * which will call vcom_init().
+ */
+ printf ("%s:%d: LDP<%d>: VCOM destructor: done!\n",
+ __func__, __LINE__, getpid ());
}