summaryrefslogtreecommitdiffstats
path: root/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.c')
-rw-r--r--extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.c3447
1 files changed, 0 insertions, 3447 deletions
diff --git a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.c b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.c
deleted file mode 100644
index 7b5f6c84f83..00000000000
--- a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.c
+++ /dev/null
@@ -1,3447 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/uio.h>
-#include <limits.h>
-#define __need_IOV_MAX
-#include <bits/stdio_lim.h>
-#include <netinet/tcp.h>
-
-#include <vppinfra/types.h>
-#include <vppinfra/hash.h>
-#include <vppinfra/pool.h>
-
-#include <libvcl-ldpreload/vcom_socket.h>
-#include <libvcl-ldpreload/vcom_socket_wrapper.h>
-#include <libvcl-ldpreload/vcom.h>
-
-#include <uri/vppcom.h>
-
-
-/*
- * VCOM_SOCKET Private definitions and functions.
- */
-
-typedef struct vcom_socket_main_t_
-{
- u8 init;
-
- /* vcom_socket pool */
- vcom_socket_t *vsockets;
-
- /* Hash table for socketidx to fd mapping */
- uword *sockidx_by_fd;
-
- /* vcom_epoll pool */
- vcom_epoll_t *vepolls;
-
- /* Hash table for epollidx to epfd mapping */
- uword *epollidx_by_epfd;
-
-
- /* common epitem poll for all epfd */
- /* TBD: epitem poll per epfd */
- /* vcom_epitem pool */
- vcom_epitem_t *vepitems;
-
- /* Hash table for epitemidx to epfdfd mapping */
- uword *epitemidx_by_epfdfd;
-
- /* Hash table - key:epfd, value:vec of epitemidx */
- uword *epitemidxs_by_epfd;
- /* Hash table - key:fd, value:vec of epitemidx */
- uword *epitemidxs_by_fd;
-
-} vcom_socket_main_t;
-
-vcom_socket_main_t vcom_socket_main;
-
-
-static int
-vcom_socket_open_socket (int domain, int type, int protocol)
-{
- int rv = -1;
-
- /* handle domains implemented by vpp */
- switch (domain)
- {
- case AF_INET:
- case AF_INET6:
- /* get socket type and
- * handle the socket types supported by vpp */
- switch (type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
- {
- case SOCK_STREAM:
- case SOCK_DGRAM:
- /* the type argument serves a second purpose,
- * in addition to specifying a socket type,
- * it may include the bitwise OR of any of
- * SOCK_NONBLOCK and SOCK_CLOEXEC, to modify
- * the behavior of socket. */
- rv = libc_socket (domain, type, protocol);
- if (rv == -1)
- rv = -errno;
- break;
-
- default:
- break;
- }
-
- break;
-
- default:
- break;
- }
-
- return rv;
-}
-
-static int
-vcom_socket_open_epoll (int flags)
-{
- int rv = -1;
-
- if (flags < 0)
- {
- return -EINVAL;
- }
- if (flags && (flags & ~EPOLL_CLOEXEC))
- {
- return -EINVAL;
- }
-
- /* flags can be either zero or EPOLL_CLOEXEC */
- rv = libc_epoll_create1 (flags);
- if (rv == -1)
- rv = -errno;
-
- return rv;
-}
-
-static int
-vcom_socket_close_socket (int fd)
-{
- int rv;
-
- rv = libc_close (fd);
- if (rv == -1)
- rv = -errno;
-
- return rv;
-}
-
-static int
-vcom_socket_close_epoll (int epfd)
-{
- int rv;
-
- rv = libc_close (epfd);
- if (rv == -1)
- rv = -errno;
-
- return rv;
-}
-
-/*
- * Public API functions
- */
-
-
-int
-vcom_socket_is_vcom_fd (int fd)
-{
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- p = hash_get (vsm->sockidx_by_fd, fd);
-
- if (p)
- {
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
- return 1;
- }
- return 0;
-}
-
-int
-vcom_socket_is_vcom_epfd (int epfd)
-{
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_epoll_t *vepoll;
-
- p = hash_get (vsm->epollidx_by_epfd, epfd);
-
- if (p)
- {
- vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
- if (vepoll && vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
- return 1;
- }
- return 0;
-}
-
-static inline int
-vcom_socket_get_sid (int fd)
-{
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- p = hash_get (vsm->sockidx_by_fd, fd);
-
- if (p)
- {
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
- return vsock->sid;
- }
- return INVALID_SESSION_ID;
-}
-
-static inline int
-vcom_socket_get_vep_idx (int epfd)
-{
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_epoll_t *vepoll;
-
- p = hash_get (vsm->epollidx_by_epfd, epfd);
-
- if (p)
- {
- vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
- if (vepoll && vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
- return vepoll->vep_idx;
- }
- return INVALID_VEP_IDX;
-}
-
-static inline int
-vcom_socket_get_sid_and_vsock (int fd, vcom_socket_t ** vsockp)
-{
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- p = hash_get (vsm->sockidx_by_fd, fd);
-
- if (p)
- {
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
- {
- *vsockp = vsock;
- return vsock->sid;
- }
- }
- return INVALID_SESSION_ID;
-}
-
-static inline int
-vcom_socket_get_vep_idx_and_vepoll (int epfd, vcom_epoll_t ** vepollp)
-{
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_epoll_t *vepoll;
-
- p = hash_get (vsm->epollidx_by_epfd, epfd);
-
- if (p)
- {
- vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
- if (vepoll && vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
- {
- *vepollp = vepoll;
- return vepoll->vep_idx;
- }
- }
- return INVALID_VEP_IDX;
-}
-
-
-static int
-vcom_socket_close_vepoll (int epfd)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_epoll_t *vepoll;
-
- p = hash_get (vsm->epollidx_by_epfd, epfd);
- if (!p)
- return -EBADF;
-
- vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
- if (!vepoll)
- return -EBADF;
-
- if (vepoll->type != EPOLL_TYPE_VPPCOM_BOUND)
- return -EINVAL;
-
- if (vepoll->count)
- {
- if (!vepoll->close)
- {
- vepoll->close = 1;
- return 0;
- }
- else
- {
- return -EBADF;
- }
- }
-
- /* count is zero */
- rv = vppcom_session_close (vepoll->vep_idx);
- rv = vcom_socket_close_epoll (vepoll->epfd);
-
- vepoll_init (vepoll);
- hash_unset (vsm->epollidx_by_epfd, epfd);
- pool_put (vsm->vepolls, vepoll);
-
- return rv;
-}
-
-static int
-vcom_socket_close_vsock (int fd)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- vcom_epitem_t *vepitem;
-
- i32 *vepitemidxs = 0;
- i32 *vepitemidxs_var = 0;
-
- p = hash_get (vsm->sockidx_by_fd, fd);
- if (!p)
- return -EBADF;
-
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (!vsock)
- return -ENOTSOCK;
-
- if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
- return -EINVAL;
-
- rv = vppcom_session_close (vsock->sid);
- rv = vcom_socket_close_socket (vsock->fd);
-
- vsocket_init (vsock);
- hash_unset (vsm->sockidx_by_fd, fd);
- pool_put (vsm->vsockets, vsock);
-
- /*
- * NOTE:
- * Before calling close(), user should remove
- * this fd from the epoll-set of all epoll instances,
- * otherwise resource(epitems) leaks ensues.
- */
-
- /*
- * 00. close all epoll instances that are marked as "close"
- * of which this fd is the "last" remaining member.
- * 01. epitems associated with this fd are intentionally
- * not removed, see NOTE: above.
- * */
-
- /* does this fd participate in epoll */
- p = hash_get (vsm->epitemidxs_by_fd, fd);
- if (p)
- {
- vepitemidxs = *(i32 **) p;
- vec_foreach (vepitemidxs_var, vepitemidxs)
- {
- vepitem = pool_elt_at_index (vsm->vepitems, vepitemidxs_var[0]);
- if (vepitem && vepitem->fd == fd &&
- vepitem->type == FD_TYPE_VCOM_SOCKET)
- {
- i32 vep_idx;
- vcom_epoll_t *vepoll;
- if ((vep_idx =
- vcom_socket_get_vep_idx_and_vepoll (vepitem->epfd,
- &vepoll)) !=
- INVALID_VEP_IDX)
- {
- if (vepoll->close)
- {
- if (vepoll->count == 1)
- {
- /*
- * force count to zero and
- * close this epoll instance
- * */
- vepoll->count = 0;
- vcom_socket_close_vepoll (vepoll->epfd);
- }
- else
- {
- vepoll->count -= 1;
- }
- }
- }
- }
-
- }
- }
-
- return rv;
-}
-
-int
-vcom_socket_close (int __fd)
-{
- int rv;
-
- if (vcom_socket_is_vcom_fd (__fd))
- {
- rv = vcom_socket_close_vsock (__fd);
- }
- else if (vcom_socket_is_vcom_epfd (__fd))
- {
- rv = vcom_socket_close_vepoll (__fd);
- }
- else
- {
- rv = -EBADF;
- }
-
- return rv;
-}
-
-ssize_t
-vcom_socket_read (int __fd, void *__buf, size_t __nbytes)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
- if (!p)
- return -EBADF;
-
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (!vsock)
- return -ENOTSOCK;
-
- if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
- return -EINVAL;
-
- if (!__buf || __nbytes < 0)
- {
- return -EINVAL;
- }
-
- rv = vcom_fcntl (__fd, F_GETFL, 0);
- if (rv < 0)
- {
- return rv;
-
- }
-
- /* is blocking */
- if (!(rv & O_NONBLOCK))
- {
- do
- {
- rv = vppcom_session_read (vsock->sid, __buf, __nbytes);
- }
- while (rv == -EAGAIN || rv == -EWOULDBLOCK);
- return rv;
- }
- /* The file descriptor refers to a socket and has been
- * marked nonblocking(O_NONBLOCK) and the read would
- * block.
- * */
- /* is non blocking */
- rv = vppcom_session_read (vsock->sid, __buf, __nbytes);
- return rv;
-}
-
-ssize_t
-vcom_socket_readv (int __fd, const struct iovec * __iov, int __iovcnt)
-{
- int rv;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
- ssize_t total = 0, len = 0;
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
- if (!p)
- return -EBADF;
-
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (!vsock)
- return -ENOTSOCK;
-
- if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
- return -EINVAL;
-
- if (__iov == 0 || __iovcnt == 0 || __iovcnt > IOV_MAX)
- return -EINVAL;
-
- /* Sanity check */
- for (int i = 0; i < __iovcnt; ++i)
- {
- if (SSIZE_MAX - len < __iov[i].iov_len)
- return -EINVAL;
- len += __iov[i].iov_len;
- }
-
- rv = vcom_fcntl (__fd, F_GETFL, 0);
- if (rv < 0)
- {
- return rv;
- }
-
- /* is blocking */
- if (!(rv & O_NONBLOCK))
- {
- do
- {
- for (int i = 0; i < __iovcnt; ++i)
- {
- rv = vppcom_session_read (vsock->sid, __iov[i].iov_base,
- __iov[i].iov_len);
- if (rv < 0)
- break;
- else
- {
- total += rv;
- if (rv < __iov[i].iov_len)
- /* Read less than buffer provided, no point to continue */
- break;
- }
- }
- }
- while ((rv == -EAGAIN || rv == -EWOULDBLOCK) && total == 0);
- return total;
- }
-
- /* is non blocking */
- for (int i = 0; i < __iovcnt; ++i)
- {
- rv = vppcom_session_read (vsock->sid, __iov[i].iov_base,
- __iov[i].iov_len);
- if (rv < 0)
- {
- if (total > 0)
- break;
- else
- {
- errno = rv;
- return rv;
- }
- }
- else
- {
- total += rv;
- if (rv < __iov[i].iov_len)
- /* Read less than buffer provided, no point to continue */
- break;
- }
- }
- return total;
-}
-
-ssize_t
-vcom_socket_write (int __fd, const void *__buf, size_t __n)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
- if (!p)
- return -EBADF;
-
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (!vsock)
- return -ENOTSOCK;
-
- if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
- return -EINVAL;
-
- if (!__buf || __n < 0)
- {
- return -EINVAL;
- }
-
- rv = vppcom_session_write (vsock->sid, (void *) __buf, __n);
- return rv;
-}
-
-ssize_t
-vcom_socket_writev (int __fd, const struct iovec * __iov, int __iovcnt)
-{
- int rv = -1;
- ssize_t total = 0;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
- if (!p)
- return -EBADF;
-
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (!vsock)
- return -ENOTSOCK;
-
- if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
- return -EINVAL;
-
- if (__iov == 0 || __iovcnt == 0 || __iovcnt > IOV_MAX)
- return -EINVAL;
-
- for (int i = 0; i < __iovcnt; ++i)
- {
- rv = vppcom_session_write (vsock->sid, __iov[i].iov_base,
- __iov[i].iov_len);
- if (rv < 0)
- {
- if (total > 0)
- break;
- else
- return rv;
- }
- else
- total += rv;
- }
- return total;
-}
-
-/*
- * RETURN: 0 - invalid cmd
- * 1 - cmd not handled by vcom and vppcom
- * 2 - cmd handled by vcom socket resource
- * 3 - cmd handled by vppcom
- * */
-/* TBD: incomplete list of cmd */
-static int
-vcom_socket_check_fcntl_cmd (int __cmd)
-{
- switch (__cmd)
- {
- /*cmd not handled by vcom and vppcom */
- /* Fallthrough */
- case F_DUPFD:
- case F_DUPFD_CLOEXEC:
- return 1;
-
- /* cmd handled by vcom socket resource */
- /* Fallthrough */
- case F_GETFD:
- case F_SETFD:
- case F_GETLK:
- case F_SETLK:
- case F_SETLKW:
- case F_GETOWN:
- case F_SETOWN:
- return 2;
-
- /* cmd handled by vcom and vppcom */
- case F_SETFL:
- case F_GETFL:
- return 3;
-
- /* cmd not handled by vcom and vppcom */
- default:
- return 1;
- }
- return 0;
-}
-
-static inline int
-vcom_session_fcntl_va (int __sid, int __cmd, va_list __ap)
-{
- int flags = va_arg (__ap, int);
- int rv = -EOPNOTSUPP;
- uint32_t size;
-
- size = sizeof (flags);
- if (__cmd == F_SETFL)
- {
- rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
- }
- else if (__cmd == F_GETFL)
- {
- rv = vppcom_session_attr (__sid, VPPCOM_ATTR_GET_FLAGS, &flags, &size);
- if (rv == VPPCOM_OK)
- rv = flags;
- }
-
- return rv;
-}
-
-int
-vcom_socket_fcntl_va (int __fd, int __cmd, va_list __ap)
-{
- int rv = -EBADF;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
- if (!p)
- return -EBADF;
-
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (!vsock)
- return -ENOTSOCK;
-
- if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
- return -EINVAL;
-
- switch (vcom_socket_check_fcntl_cmd (__cmd))
- {
- /* invalid cmd */
- case 0:
- rv = -EBADF;
- break;
- /*cmd not handled by vcom and vppcom */
- case 1:
- rv = libc_vfcntl (vsock->fd, __cmd, __ap);
- break;
- /* cmd handled by vcom socket resource */
- case 2:
- rv = libc_vfcntl (vsock->fd, __cmd, __ap);
- break;
- /* cmd handled by vppcom */
- case 3:
- rv = vcom_session_fcntl_va (vsock->sid, __cmd, __ap);
- break;
-
- default:
- rv = -EINVAL;
- break;
- }
-
- return rv;
-}
-
-/*
- * RETURN: 0 - invalid cmd
- * 1 - cmd not handled by vcom and vppcom
- * 2 - cmd handled by vcom socket resource
- * 3 - cmd handled by vppcom
- */
-static int
-vcom_socket_check_ioctl_cmd (unsigned long int __cmd)
-{
- int rc;
-
- switch (__cmd)
- {
- /* cmd handled by vppcom */
- case FIONREAD:
- rc = 3;
- break;
-
- /* cmd not handled by vcom and vppcom */
- default:
- rc = 1;
- break;
- }
- return rc;
-}
-
-static inline int
-vcom_session_ioctl_va (int __sid, int __cmd, va_list __ap)
-{
- int rv;
-
- if (__cmd == FIONREAD)
- rv = vppcom_session_attr (__sid, VPPCOM_ATTR_GET_NREAD, 0, 0);
- else
- rv = -EOPNOTSUPP;
- return rv;
-}
-
-int
-vcom_socket_ioctl_va (int __fd, unsigned long int __cmd, va_list __ap)
-{
- int rv = -EBADF;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
- if (!p)
- return -EBADF;
-
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (!vsock)
- return -ENOTSOCK;
-
- if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
- return -EINVAL;
-
- switch (vcom_socket_check_ioctl_cmd (__cmd))
- {
- /* Not supported cmd */
- case 0:
- rv = -EOPNOTSUPP;
- break;
-
- /* cmd not handled by vcom and vppcom */
- case 1:
- rv = libc_vioctl (vsock->fd, __cmd, __ap);
- break;
-
- /* cmd handled by vcom socket resource */
- case 2:
- rv = libc_vioctl (vsock->fd, __cmd, __ap);
- break;
-
- /* cmd handled by vppcom */
- case 3:
- rv = vcom_session_ioctl_va (vsock->sid, __cmd, __ap);
- break;
-
- default:
- rv = -EINVAL;
- break;
- }
-
- return rv;
-}
-
-static inline int
-vcom_socket_fds_2_sid_fds (
- /* dest */
- int *vcom_nsid_fds,
- fd_set * __restrict vcom_rd_sid_fds,
- fd_set * __restrict vcom_wr_sid_fds,
- fd_set * __restrict vcom_ex_sid_fds,
- /* src */
- int vcom_nfds,
- fd_set * __restrict vcom_readfds,
- fd_set * __restrict vcom_writefds,
- fd_set * __restrict vcom_exceptfds)
-{
- int rv = 0;
- int fd;
- int sid;
- /* invalid max_sid is -1 */
- int max_sid = -1;
- int nsid = 0;
-
- /*
- * set sid in sid sets corresponding to fd's in fd sets
- * compute nsid and vcom_nsid_fds from sid sets
- */
-
- for (fd = 0; fd < vcom_nfds; fd++)
- {
- /*
- * F fd set, src
- * S sid set, dest
- */
-#define _(S,F) \
- if ((F) && (S) && FD_ISSET (fd, (F))) \
- { \
- sid = vcom_socket_get_sid (fd); \
- if (sid != INVALID_SESSION_ID) \
- { \
- FD_SET (sid, (S)); \
- if (sid > max_sid) \
- { \
- max_sid = sid; \
- } \
- ++nsid; \
- } \
- else \
- { \
- rv = -EBADFD; \
- goto done; \
- } \
- }
-
-
- _(vcom_rd_sid_fds, vcom_readfds);
- _(vcom_wr_sid_fds, vcom_writefds);
- _(vcom_ex_sid_fds, vcom_exceptfds);
-#undef _
- }
-
- *vcom_nsid_fds = max_sid != -1 ? max_sid + 1 : 0;
- rv = nsid;
-
-done:
- return rv;
-}
-
-/*
- * PRE: 00. sid sets were derived from fd sets
- * 01. sid sets were updated with sids that actually changed
- * status
- * 02. fd sets still has watched fds
- *
- * This function will modify in place fd sets to indicate which fd's
- * actually changed status(inferred from sid sets)
- */
-static inline int
-vcom_socket_sid_fds_2_fds (
- /* dest */
- int *new_vcom_nfds,
- int vcom_nfds,
- fd_set * __restrict vcom_readfds,
- fd_set * __restrict vcom_writefds,
- fd_set * __restrict vcom_exceptfds,
- /* src */
- int vcom_nsid_fds,
- fd_set * __restrict vcom_rd_sid_fds,
- fd_set * __restrict vcom_wr_sid_fds,
- fd_set * __restrict vcom_ex_sid_fds)
-{
- int rv = 0;
- int fd;
- int sid;
- /* invalid max_fd is -1 */
- int max_fd = -1;
- int nfd = 0;
-
-
- /*
- * modify in place fd sets to indicate which fd's
- * actually changed status(inferred from sid sets)
- */
- for (fd = 0; fd < vcom_nfds; fd++)
- {
- /*
- * F fd set, dest
- * S sid set, src
- */
-#define _(S,F) \
- if ((F) && (S) && FD_ISSET (fd, (F))) \
- { \
- sid = vcom_socket_get_sid (fd); \
- if (sid != INVALID_SESSION_ID) \
- { \
- if (!FD_ISSET (sid, (S))) \
- { \
- FD_CLR(fd, (F)); \
- } \
- } \
- else \
- { \
- rv = -EBADFD; \
- goto done; \
- } \
- }
-
-
- _(vcom_rd_sid_fds, vcom_readfds);
- _(vcom_wr_sid_fds, vcom_writefds);
- _(vcom_ex_sid_fds, vcom_exceptfds);
-#undef _
- }
-
- /*
- * compute nfd and new_vcom_nfds from fd sets
- */
- for (fd = 0; fd < vcom_nfds; fd++)
- {
-
-#define _(F) \
- if ((F) && FD_ISSET (fd, (F))) \
- { \
- if (fd > max_fd) \
- { \
- max_fd = fd; \
- } \
- ++nfd; \
- }
-
-
- _(vcom_readfds);
- _(vcom_writefds);
- _(vcom_exceptfds);
-#undef _
-
- }
-
- *new_vcom_nfds = max_fd != -1 ? max_fd + 1 : 0;
- rv = nfd;
-
-done:
- return rv;
-}
-
-/*
- * PRE:
- * vom_socket_select is always called with
- * timeout->tv_sec and timeout->tv_usec set to zero.
- * hence vppcom_select return immediately.
- */
-/*
- * TBD: do{body;} while(timeout conditional); timeout loop
- */
-int
-vcom_socket_select (int vcom_nfds, fd_set * __restrict vcom_readfds,
- fd_set * __restrict vcom_writefds,
- fd_set * __restrict vcom_exceptfds,
- struct timeval *__restrict timeout)
-{
- static unsigned long vcom_nsid_fds = 0;
- int vcom_nsid = 0;
- int rv = -EBADF;
- pid_t pid = getpid ();
-
- int new_vcom_nfds = 0;
- int new_vcom_nfd = 0;
-
- /* vcom sid fds */
- fd_set vcom_rd_sid_fds;
- fd_set vcom_wr_sid_fds;
- fd_set vcom_ex_sid_fds;
-
- /* in seconds eg. 3.123456789 seconds */
- double time_to_wait = (double) 0;
-
- /* validate inputs */
- if (vcom_nfds < 0)
- {
- return -EINVAL;
- }
-
- /* convert timeval timeout to double time_to_wait */
- if (timeout)
- {
- if (timeout->tv_sec == 0 && timeout->tv_usec == 0)
- {
- /* polling: vppcom_select returns immediately */
- time_to_wait = (double) 0;
- }
- else
- {
- /*TBD: use timeval api */
- time_to_wait = (double) timeout->tv_sec +
- (double) timeout->tv_usec / (double) 1000000 +
- (double) (timeout->tv_usec % 1000000) / (double) 1000000;
- }
- }
- else
- {
- /*
- * no timeout: vppcom_select can block indefinitely
- * waiting for a file descriptor to become ready
- * */
- /* set to a phantom value */
- time_to_wait = ~0;
- }
-
- /* zero the sid_sets */
- /*
- * F fd set
- * S sid set
- */
-#define _(S,F) \
- if ((F)) \
- { \
- FD_ZERO ((S)); \
- }
-
-
- _(&vcom_rd_sid_fds, vcom_readfds);
- _(&vcom_wr_sid_fds, vcom_writefds);
- _(&vcom_ex_sid_fds, vcom_exceptfds);
-#undef _
-
- if (vcom_nfds == 0)
- {
- if (time_to_wait > 0)
- {
- if (VCOM_DEBUG > 0)
- fprintf (stderr,
- "[%d] vcom_socket_select called to "
- "emulate delay_ns()!\n", pid);
- rv = vppcom_select (0, NULL, NULL, NULL, time_to_wait);
- }
- else
- {
- fprintf (stderr, "[%d] vcom_socket_select called vcom_nfds = 0 "
- "and invalid time_to_wait (%f)!\n", pid, time_to_wait);
- }
- return 0;
- }
-
- /* populate read, write and except sid_sets */
- vcom_nsid = vcom_socket_fds_2_sid_fds (
- /* dest */
- vcom_readfds || vcom_writefds
- || vcom_exceptfds ? (int *)
- &vcom_nsid_fds : NULL,
- vcom_readfds ? &vcom_rd_sid_fds :
- NULL,
- vcom_writefds ? &vcom_wr_sid_fds :
- NULL,
- vcom_exceptfds ? &vcom_ex_sid_fds :
- NULL,
- /* src */
- vcom_nfds,
- vcom_readfds,
- vcom_writefds, vcom_exceptfds);
- if (vcom_nsid < 0)
- {
- return vcom_nsid;
- }
- if (vcom_nsid_fds < 0)
- {
- return -EINVAL;
- }
-
- rv = vppcom_select (vcom_nsid_fds,
- vcom_readfds ? (unsigned long *) &vcom_rd_sid_fds :
- NULL,
- vcom_writefds ? (unsigned long *) &vcom_wr_sid_fds :
- NULL,
- vcom_exceptfds ? (unsigned long *) &vcom_ex_sid_fds :
- NULL, time_to_wait);
- if (VCOM_DEBUG > 2)
- fprintf (stderr, "[%d] called vppcom_select(): "
- "'%04d'='%04d'\n", pid, rv, (int) vcom_nsid_fds);
-
- /* check if any file descriptors changed status */
- if (rv > 0)
- {
- /*
- * on exit, sets are modified in place to indicate which
- * file descriptors actually changed status
- * */
-
- /*
- * comply with pre-condition
- * do not clear vcom fd sets befor calling
- * vcom_socket_sid_fds_2_fds
- */
- new_vcom_nfd = vcom_socket_sid_fds_2_fds (
- /* dest */
- &new_vcom_nfds,
- vcom_nfds,
- vcom_readfds,
- vcom_writefds,
- vcom_exceptfds,
- /* src */
- vcom_nsid_fds,
- vcom_readfds ?
- &vcom_rd_sid_fds : NULL,
- vcom_writefds ?
- &vcom_wr_sid_fds : NULL,
- vcom_exceptfds ?
- &vcom_ex_sid_fds : NULL);
- if (new_vcom_nfd < 0)
- {
- return new_vcom_nfd;
- }
- if (new_vcom_nfds < 0)
- {
- return -EINVAL;
- }
- rv = new_vcom_nfd;
- }
- return rv;
-}
-
-
-int
-vcom_socket_socket (int __domain, int __type, int __protocol)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- vcom_socket_t *vsock;
-
- i32 fd;
- i32 sid;
- i32 sockidx;
- u8 is_nonblocking = __type & SOCK_NONBLOCK ? 1 : 0;
- int type = __type & ~(SOCK_NONBLOCK | SOCK_CLOEXEC);
-
- fd = vcom_socket_open_socket (__domain, __type, __protocol);
- if (fd < 0)
- {
- rv = fd;
- goto out;
- }
-
- sid = vppcom_session_create (VPPCOM_VRF_DEFAULT,
- (type == SOCK_DGRAM) ?
- VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP,
- is_nonblocking);
- if (sid < 0)
- {
- rv = sid;
- goto out_close_socket;
- }
-
- pool_get (vsm->vsockets, vsock);
- vsocket_init (vsock);
-
- sockidx = vsock - vsm->vsockets;
- hash_set (vsm->sockidx_by_fd, fd, sockidx);
-
- vsocket_set (vsock, fd, sid, SOCKET_TYPE_VPPCOM_BOUND);
- return fd;
-
-out_close_socket:
- vcom_socket_close_socket (fd);
-out:
- return rv;
-}
-
-int
-vcom_socket_socketpair (int __domain, int __type, int __protocol,
- int __fds[2])
-{
-/* TBD: */
- return 0;
-}
-
-int
-vcom_socket_bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- vppcom_endpt_t ep;
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
- if (!p)
- return -EBADF;
-
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (!vsock)
- return -ENOTSOCK;
-
- if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
- return -EINVAL;
-
- if (!__addr)
- {
- return -EINVAL;
- }
-
- ep.vrf = VPPCOM_VRF_DEFAULT;
- switch (__addr->sa_family)
- {
- case AF_INET:
- if (__len != sizeof (struct sockaddr_in))
- {
- return -EINVAL;
- }
- 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;
-
- case AF_INET6:
- if (__len != sizeof (struct sockaddr_in6))
- {
- return -EINVAL;
- }
- 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;
-
- default:
- return -1;
- break;
- }
-
- rv = vppcom_session_bind (vsock->sid, &ep);
- return rv;
-}
-
-static inline int
-vcom_session_getsockname (int sid, vppcom_endpt_t * ep)
-{
- int rv;
- uint32_t size = sizeof (*ep);
-
- rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LCL_ADDR, ep, &size);
- return rv;
-}
-
-int
-vcom_socket_getsockname (int __fd, __SOCKADDR_ARG __addr,
- socklen_t * __restrict __len)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
- if (!p)
- return -EBADF;
-
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (!vsock)
- return -ENOTSOCK;
-
- if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
- return -EINVAL;
-
- if (!__addr || !__len)
- return -EFAULT;
-
- if (*__len < 0)
- {
- return -EINVAL;
- }
-
- vppcom_endpt_t ep;
- ep.ip = (u8 *) & ((const struct sockaddr_in *) __addr)->sin_addr;
- rv = vcom_session_getsockname (vsock->sid, &ep);
- if (rv == 0)
- {
- if (ep.vrf == VPPCOM_VRF_DEFAULT)
- {
- __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;
- *__len = sizeof (struct sockaddr_in);
- break;
-
- case AF_INET6:
- ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port;
- *__len = sizeof (struct sockaddr_in6);
- break;
-
- default:
- break;
- }
- }
- }
-
- return rv;
-}
-
-int
-vcom_socket_connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- vppcom_endpt_t ep;
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
- if (p)
- {
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
-
- 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:
- return -1;
- break;
- }
-
- rv = vppcom_session_connect (vsock->sid, &ep);
- }
- return rv;
-}
-
-static inline int
-vcom_session_getpeername (int sid, vppcom_endpt_t * ep)
-{
- int rv;
- uint32_t size = sizeof (*ep);
-
- rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PEER_ADDR, ep, &size);
- return rv;
-}
-
-int
-vcom_socket_getpeername (int __fd, __SOCKADDR_ARG __addr,
- socklen_t * __restrict __len)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
- if (!p)
- return -EBADF;
-
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (!vsock)
- return -ENOTSOCK;
-
- if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
- return -EINVAL;
-
- if (!__addr || !__len)
- return -EFAULT;
-
- if (*__len < 0)
- {
- return -EINVAL;
- }
-
- vppcom_endpt_t ep;
- ep.ip = (u8 *) & ((const struct sockaddr_in *) __addr)->sin_addr;
- rv = vcom_session_getpeername (vsock->sid, &ep);
- if (rv == 0)
- {
- if (ep.vrf == VPPCOM_VRF_DEFAULT)
- {
- __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;
- *__len = sizeof (struct sockaddr_in);
- break;
-
- case AF_INET6:
- ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port;
- *__len = sizeof (struct sockaddr_in6);
- break;
-
- default:
- break;
- }
- }
- }
-
- return rv;
-}
-
-ssize_t
-vcom_socket_send (int __fd, const void *__buf, size_t __n, int __flags)
-{
- return vcom_socket_sendto (__fd, __buf, __n, __flags, NULL, 0);
-}
-
-ssize_t
-vcom_socket_recv (int __fd, void *__buf, size_t __n, int __flags)
-{
- int rv = -1;
- rv = vcom_socket_recvfrom (__fd, __buf, __n, __flags, NULL, 0);
- return rv;
-}
-
-/*
- * RETURN 1 if __fd is (SOCK_STREAM, SOCK_SEQPACKET),
- * 0 otherwise
- * */
-int
-vcom_socket_is_connection_mode_socket (int __fd)
-{
- int rv = -1;
- /* TBD define new vppcom api */
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- int type;
- socklen_t optlen;
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
-
- if (p)
- {
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
- {
- optlen = sizeof (type);
- rv = libc_getsockopt (__fd, SOL_SOCKET, SO_TYPE, &type, &optlen);
- if (rv != 0)
- {
- return 0;
- }
- /* get socket type */
- switch (type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
- {
- case SOCK_STREAM:
- case SOCK_SEQPACKET:
- return 1;
- break;
-
- default:
- return 0;
- break;
- }
- }
- }
- return 0;
-}
-
-static inline ssize_t
-vcom_session_sendto (int __sid, void *__buf, size_t __n,
- int __flags, __CONST_SOCKADDR_ARG __addr,
- socklen_t __addr_len)
-{
- int rv = -1;
- /* TBD add new vpp api */
- /* TBD add flags parameter */
- rv = vppcom_session_write (__sid, (void *) __buf, (int) __n);
- return rv;
-}
-
-ssize_t
-vcom_socket_sendto (int __fd, const void *__buf, size_t __n,
- int __flags, __CONST_SOCKADDR_ARG __addr,
- socklen_t __addr_len)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
- if (!p)
- return -EBADF;
-
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (!vsock)
- return -ENOTSOCK;
-
- if ((vsock->type != SOCKET_TYPE_VPPCOM_BOUND) || !__buf || __n < 0)
- {
- return -EINVAL;
- }
-
- if (vcom_socket_is_connection_mode_socket (__fd))
- {
- /* ignore __addr and _addr_len */
- /* and EISCONN may be returned when they are not NULL and 0 */
- if ((__addr != NULL) || (__addr_len != 0))
- {
- return -EISCONN;
- }
- }
- else
- {
- if (!__addr || __addr_len < 0)
- {
- return -EDESTADDRREQ;
- }
- /* not a vppcom supported address family */
- if ((__addr->sa_family != AF_INET) || (__addr->sa_family != AF_INET6))
- {
- return -EINVAL;
- }
- }
-
- rv = vcom_session_sendto (vsock->sid, (void *) __buf, (int) __n,
- __flags, __addr, __addr_len);
- return rv;
-}
-
-static inline ssize_t
-vcom_session_recvfrom (int __sid, void *__restrict __buf, size_t __n,
- int __flags, __SOCKADDR_ARG __addr,
- socklen_t * __restrict __addr_len)
-{
- int rv = -1;
-
- /* TBD add flags parameter */
- rv = vppcom_session_read (__sid, __buf, __n);
- return rv;
-}
-
-ssize_t
-vcom_socket_recvfrom (int __fd, void *__restrict __buf, size_t __n,
- int __flags, __SOCKADDR_ARG __addr,
- socklen_t * __restrict __addr_len)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
- if (!p)
- return -EBADF;
-
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (!vsock)
- return -ENOTSOCK;
-
- if ((vsock->type != SOCKET_TYPE_VPPCOM_BOUND) ||
- !__buf || __n < 0 || !__addr || !__addr_len || (__addr_len < 0))
- {
- return -EINVAL;
- }
-
- rv = vcom_session_recvfrom (vsock->sid, __buf, __n,
- __flags, __addr, __addr_len);
- return rv;
-}
-
-/* TBD: move it to vppcom */
-static inline ssize_t
-vcom_session_sendmsg (int __sid, const struct msghdr *__message, int __flags)
-{
- int rv = -1;
- /* rv = vppcom_session_write (__sid, (void *) __message->__buf,
- (int)__n); */
- return rv;
-}
-
-ssize_t
-vcom_socket_sendmsg (int __fd, const struct msghdr * __message, int __flags)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
- if (!p)
- return -EBADF;
-
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (!vsock)
- return -ENOTSOCK;
-
- if (vcom_socket_is_connection_mode_socket (__fd))
- {
- /* ignore __addr and _addr_len */
- /* and EISCONN may be returned when they are not NULL and 0 */
- if ((__message->msg_name != NULL) || (__message->msg_namelen != 0))
- {
- return -EISCONN;
- }
- }
- else
- {
- /* TBD: validate __message->msg_name and __message->msg_namelen
- * and return -EINVAL on validation error
- * */
- ;
- }
-
- rv = vcom_session_sendmsg (vsock->sid, __message, __flags);
-
- return rv;
-}
-
-#ifdef __USE_GNU
-int
-vcom_socket_sendmmsg (int __fd, struct mmsghdr *__vmessages,
- unsigned int __vlen, int __flags)
-{
-
- /* TBD: define a new vppcom api */
- return 0;
-}
-#endif
-
-/* TBD: move it to vppcom */
-static inline ssize_t
-vcom_session_recvmsg (int __sid, struct msghdr *__message, int __flags)
-{
- int rv = -1;
- /* rv = vppcom_session_read (__sid, (void *) __message->__buf,
- (int)__n); */
- rv = -EOPNOTSUPP;
- return rv;
-}
-
-ssize_t
-vcom_socket_recvmsg (int __fd, struct msghdr * __message, int __flags)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
- if (!p)
- return -EBADF;
-
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (!vsock)
- return -ENOTSOCK;
-
- if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
- return -EINVAL;
-
- if (!__message)
- {
- return -EINVAL;
- }
-
- /* validate __flags */
-
- rv = vcom_session_recvmsg (vsock->sid, __message, __flags);
- return rv;
-}
-
-#ifdef __USE_GNU
-int
-vcom_socket_recvmmsg (int __fd, struct mmsghdr *__vmessages,
- unsigned int __vlen, int __flags,
- struct timespec *__tmo)
-{
- /* TBD: define a new vppcom api */
- return 0;
-}
-#endif
-
-/* TBD: move it to vppcom */
-static inline int
-vcom_session_get_sockopt (int __sid, int __level, int __optname,
- void *__restrict __optval,
- socklen_t * __restrict __optlen)
-{
- /* 1. for socket level options that are NOT socket attributes
- * and that has corresponding vpp options get from vppcom */
- return 0;
-}
-
-int
-vcom_socket_getsockopt (int __fd, int __level, int __optname,
- void *__restrict __optval,
- socklen_t * __restrict __optlen)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
- if (!p)
- return -EBADF;
-
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (!vsock)
- return -ENOTSOCK;
-
- if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
- return -EINVAL;
-
- if (!__optval && !__optlen)
- return -EFAULT;
-
- if (*__optlen < 0)
- {
- return -EINVAL;
- }
-
- switch (__level)
- {
- /* handle options at socket level */
- case SOL_SOCKET:
- switch (__optname)
- {
-/*
- * 1. for socket level options that are socket attributes,
- * get from libc_getsockopt.
- * 2. for socket level options that are NOT socket
- * attributes and that has corresponding vpp options
- * get from vppcom.
- * 3. for socket level options unimplemented
- * return -ENOPROTOOPT */
- case SO_DEBUG:
- case SO_DONTROUTE:
- case SO_BROADCAST:
- case SO_SNDBUF:
- case SO_RCVBUF:
- case SO_REUSEADDR:
- case SO_REUSEPORT:
- case SO_KEEPALIVE:
- case SO_TYPE:
- case SO_PROTOCOL:
- case SO_DOMAIN:
- case SO_ERROR:
- case SO_OOBINLINE:
- case SO_NO_CHECK:
- case SO_PRIORITY:
- case SO_LINGER:
- case SO_BSDCOMPAT:
- case SO_TIMESTAMP:
- case SO_TIMESTAMPNS:
- case SO_TIMESTAMPING:
- case SO_RCVTIMEO:
- case SO_SNDTIMEO:
- case SO_RCVLOWAT:
- case SO_SNDLOWAT:
- case SO_PASSCRED:
- case SO_PEERCRED:
- case SO_PEERNAME:
- case SO_ACCEPTCONN:
- case SO_PASSSEC:
- case SO_PEERSEC:
- case SO_MARK:
- case SO_RXQ_OVFL:
- case SO_WIFI_STATUS:
- case SO_PEEK_OFF:
- case SO_NOFCS:
- case SO_BINDTODEVICE:
- case SO_GET_FILTER:
- case SO_LOCK_FILTER:
- case SO_BPF_EXTENSIONS:
- case SO_SELECT_ERR_QUEUE:
-#ifdef CONFIG_NET_RX_BUSY_POLL
- case SO_BUSY_POLL:
-#endif
- case SO_MAX_PACING_RATE:
- case SO_INCOMING_CPU:
- rv = libc_getsockopt (__fd, __level, __optname, __optval, __optlen);
- if (rv != 0)
- {
- rv = -errno;
- return rv;
- }
- break;
-
- default:
- /* We implement the SO_SNDLOWAT etc to not be settable
- * (1003.1g 7).
- */
- return -ENOPROTOOPT;
- }
-
- break;
-
- default:
- /* 1. handle options that are NOT socket level options,
- * but have corresponding vpp otions. */
- rv = vcom_session_get_sockopt (vsock->sid, __level, __optname,
- __optval, __optlen);
- break;
- }
-
- return rv;
-}
-
-/* TBD: move it to vppcom */
-static inline int
-vcom_session_setsockopt (int __sid, int __level, int __optname,
- const void *__optval, socklen_t __optlen)
-{
- int rv = -EOPNOTSUPP;
-
- switch (__level)
- {
- case SOL_TCP:
- switch (__optname)
- {
- case TCP_KEEPIDLE:
- rv =
- vppcom_session_attr (__sid, VPPCOM_ATTR_SET_TCP_KEEPIDLE, 0, 0);
- break;
- case TCP_KEEPINTVL:
- rv =
- vppcom_session_attr (__sid, VPPCOM_ATTR_SET_TCP_KEEPINTVL, 0, 0);
- break;
- default:
- break;
- }
- break;
- case SOL_IPV6:
- switch (__optname)
- {
- case IPV6_V6ONLY:
- rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_V6ONLY, 0, 0);
- break;
- default:
- break;
- }
- break;
- case SOL_SOCKET:
- switch (__optname)
- {
- case SO_KEEPALIVE:
- rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_KEEPALIVE, 0, 0);
- break;
- case SO_REUSEADDR:
- rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_REUSEADDR, 0, 0);
- break;
- case SO_BROADCAST:
- rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_BROADCAST, 0, 0);
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
-
- return rv;
-}
-
-int
-vcom_socket_setsockopt (int __fd, int __level, int __optname,
- const void *__optval, socklen_t __optlen)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
- if (!p)
- return -EBADF;
-
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- if (!vsock)
- return -ENOTSOCK;
-
- if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
- return -EINVAL;
-
- /*
- * Options without arguments
- */
-
- if (__optname == SO_BINDTODEVICE)
- {
- rv = libc_setsockopt (__fd, __level, __optname, __optval, __optlen);
- if (rv != 0)
- {
- rv = -errno;
- }
- return rv;
- }
-
- if (!__optval)
- return -EFAULT;
-
- if ((__optlen < 0) || (__optlen < sizeof (int)))
- return -EINVAL;
-
- switch (__level)
- {
- case SOL_IPV6:
- switch (__optname)
- {
- case IPV6_V6ONLY:
- rv = vcom_session_setsockopt (vsock->sid, __level, __optname,
- __optval, __optlen);
- break;
- default:
- return -EOPNOTSUPP;
- }
- break;
- case SOL_TCP:
- switch (__optname)
- {
- case TCP_NODELAY:
- return 0;
- case TCP_KEEPIDLE:
- case TCP_KEEPINTVL:
- rv = vcom_session_setsockopt (vsock->sid, __level, __optname,
- __optval, __optlen);
- break;
- default:
- return -EOPNOTSUPP;
- }
- break;
- /* handle options at socket level */
- case SOL_SOCKET:
- switch (__optname)
- {
- case SO_REUSEADDR:
- case SO_BROADCAST:
- case SO_KEEPALIVE:
- rv = vcom_session_setsockopt (vsock->sid, __level, __optname,
- __optval, __optlen);
- break;
-
- /*
- * 1. for socket level options that are socket attributes,
- * set it from libc_getsockopt
- * 2. for socket level options that are NOT socket
- * attributes and that has corresponding vpp options
- * set it from vppcom
- * 3. for socket level options unimplemented
- * return -ENOPROTOOPT */
- case SO_DEBUG:
- case SO_DONTROUTE:
- case SO_SNDBUF:
- case SO_RCVBUF:
- case SO_REUSEPORT:
- case SO_TYPE:
- case SO_PROTOCOL:
- case SO_DOMAIN:
- case SO_ERROR:
- case SO_OOBINLINE:
- case SO_NO_CHECK:
- case SO_PRIORITY:
- case SO_LINGER:
- case SO_BSDCOMPAT:
- case SO_TIMESTAMP:
- case SO_TIMESTAMPNS:
- case SO_TIMESTAMPING:
- case SO_RCVTIMEO:
- case SO_SNDTIMEO:
- case SO_RCVLOWAT:
- case SO_SNDLOWAT:
- case SO_PASSCRED:
- case SO_PEERCRED:
- case SO_PEERNAME:
- case SO_ACCEPTCONN:
- case SO_PASSSEC:
- case SO_PEERSEC:
- case SO_MARK:
- case SO_RXQ_OVFL:
- case SO_WIFI_STATUS:
- case SO_PEEK_OFF:
- case SO_NOFCS:
- /*
- * SO_BINDTODEVICE already handled as
- * "Options without arguments" */
- /* case SO_BINDTODEVICE: */
- case SO_GET_FILTER:
- case SO_LOCK_FILTER:
- case SO_BPF_EXTENSIONS:
- case SO_SELECT_ERR_QUEUE:
-#ifdef CONFIG_NET_RX_BUSY_POLL
- case SO_BUSY_POLL:
-#endif
- case SO_MAX_PACING_RATE:
- case SO_INCOMING_CPU:
- rv = libc_setsockopt (__fd, __level, __optname, __optval, __optlen);
- if (rv != 0)
- {
- rv = -errno;
- return rv;
- }
- break;
-
- default:
- /* We implement the SO_SNDLOWAT etc to not be settable
- * (1003.1g 7).
- */
- return -ENOPROTOOPT;
- }
-
- break;
-
- default:
- return -ENOPROTOOPT;
- }
-
- return rv;
-}
-
-int
-vcom_socket_listen (int __fd, int __n)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
- if (p)
- {
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
-
- /* TBD vppcom to accept __n parameter */
- rv = vppcom_session_listen (vsock->sid, __n);
- }
-
- return rv;
-}
-
-static int
-vcom_socket_connected_socket (int __fd, int __sid,
- int *__domain,
- int *__type, int *__protocol, int flags)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- vcom_socket_t *vsock;
-
- i32 fd;
- i32 sockidx;
-
- socklen_t optlen;
-
- optlen = sizeof (*__domain);
- rv = libc_getsockopt (__fd, SOL_SOCKET, SO_DOMAIN, __domain, &optlen);
- if (rv != 0)
- {
- rv = -errno;
- goto out;
- }
-
- optlen = sizeof (*__type);
- rv = libc_getsockopt (__fd, SOL_SOCKET, SO_TYPE, __type, &optlen);
- if (rv != 0)
- {
- rv = -errno;
- goto out;
- }
-
- optlen = sizeof (*__protocol);
- rv = libc_getsockopt (__fd, SOL_SOCKET, SO_PROTOCOL, __protocol, &optlen);
- if (rv != 0)
- {
- rv = -errno;
- goto out;
- }
-
- fd = vcom_socket_open_socket (*__domain, *__type | flags, *__protocol);
- if (fd < 0)
- {
- rv = fd;
- goto out;
- }
-
- pool_get (vsm->vsockets, vsock);
- vsocket_init (vsock);
-
- sockidx = vsock - vsm->vsockets;
- hash_set (vsm->sockidx_by_fd, fd, sockidx);
-
- vsocket_set (vsock, fd, __sid, SOCKET_TYPE_VPPCOM_BOUND);
- return fd;
-
-out:
- return rv;
-}
-
-/* If flag is 0, then accept4() is the same as accept().
- * SOCK_NONBLOCK and SOCK_CLOEXEC can be bitwise ORed in flags
- */
-static int
-vcom_socket_accept_flags (int __fd, __SOCKADDR_ARG __addr,
- socklen_t * __restrict __addr_len, int flags)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- int fd;
- int sid;
- int domain;
- int type;
- int protocol;
-
- uint8_t addr8[sizeof (struct in6_addr)];
- vppcom_endpt_t ep;
-
- ep.ip = addr8;
-
- /* validate flags */
-
- /*
- * for documentation
- * switch (flags)
- * {
- * case 0:
- * case SOCK_NONBLOCK:
- * case SOCK_CLOEXEC:
- * case SOCK_NONBLOCK | SOCK_CLOEXEC:
- * break;
- *
- * default:
- * return -1;
- * }
- */
- /* flags can be 0 or can be bitwise OR
- * of any of SOCK_NONBLOCK and SOCK_CLOEXEC */
-
- if (!(!flags || (flags & (SOCK_NONBLOCK | SOCK_CLOEXEC))))
- {
- /* TBD: return proper error code */
- return -1;
- }
-
- /* TBD: return proper error code */
-
- if (!vcom_socket_is_connection_mode_socket (__fd))
- {
- return -EOPNOTSUPP;
- }
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
- if (p)
- {
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
-
-
- rv = vcom_fcntl (vsock->fd, F_GETFL, 0);
- if (rv < 0)
- {
- return rv;
- }
-
- /* is blocking */
- if (!(rv & O_NONBLOCK))
- {
- /* socket is not marked as nonblocking
- * and no pending connections are present
- * on the queue, accept () blocks the caller
- * until a connection is present.
- */
- rv = vppcom_session_accept (vsock->sid, &ep,
- -1.0 /* wait forever */ );
- }
- else
- {
- /* The file descriptor refers to a socket and has been
- * marked nonblocking(O_NONBLOCK) and the accept would
- * block.
- * */
- /* is non blocking */
- rv = vppcom_session_accept (vsock->sid, &ep, 0);
- /* If the socket is marked nonblocking and
- * no pending connections are present on the
- * queue, accept fails with the error
- * EAGAIN or EWOULDBLOCK
- */
- if (rv == VPPCOM_ETIMEDOUT)
- {
- rv = VPPCOM_EAGAIN;
- }
- }
- if (rv < 0)
- {
- return rv;
- }
-
- sid = rv;
-
- /* create a new connected socket resource and set flags
- * on the new file descriptor.
- * update vsockets and sockidx_by_fd table
- * */
- fd = vcom_socket_connected_socket (__fd, sid,
- &domain, &type, &protocol, flags);
- if (fd < 0)
- {
- return fd;
- }
-
- rv = fd;
-
- /* TBD populate __addr and __addr_len */
- /* TBD: The returned address is truncated if the buffer
- * provided is too small, in this case, __addr_len will
- * return a value greater than was supplied to the call.*/
- if (__addr)
- {
- if (ep.is_cut_thru)
- {
- /* TBD populate __addr and __addr_len */
- switch (domain)
- {
- case AF_INET:
- ((struct sockaddr_in *) __addr)->sin_family = AF_INET;
- ((struct sockaddr_in *) __addr)->sin_port = ep.port;
- memcpy (&((struct sockaddr_in *) __addr)->sin_addr,
- addr8, sizeof (struct in_addr));
- /* TBD: populate __addr_len */
- if (__addr_len)
- {
- *__addr_len = sizeof (struct sockaddr_in);
- }
- break;
-
- case AF_INET6:
- ((struct sockaddr_in6 *) __addr)->sin6_family = AF_INET6;
- ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port;
- memcpy (((struct sockaddr_in6 *) __addr)->sin6_addr.
- __in6_u.__u6_addr8, addr8,
- sizeof (struct in6_addr));
- /* TBD: populate __addr_len */
- if (__addr_len)
- {
- *__addr_len = sizeof (struct sockaddr_in6);
- }
- break;
-
- default:
- return -EAFNOSUPPORT;
- }
- }
- else
- {
- switch (ep.is_ip4)
- {
- case VPPCOM_IS_IP4:
- ((struct sockaddr_in *) __addr)->sin_family = AF_INET;
- ((struct sockaddr_in *) __addr)->sin_port = ep.port;
- memcpy (&((struct sockaddr_in *) __addr)->sin_addr,
- addr8, sizeof (struct in_addr));
- /* TBD: populate __addr_len */
- if (__addr_len)
- {
- *__addr_len = sizeof (struct sockaddr_in);
- }
- break;
-
- case VPPCOM_IS_IP6:
- ((struct sockaddr_in6 *) __addr)->sin6_family = AF_INET6;
- ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port;
- memcpy (((struct sockaddr_in6 *) __addr)->sin6_addr.
- __in6_u.__u6_addr8, addr8,
- sizeof (struct in6_addr));
- /* TBD: populate __addr_len */
- if (__addr_len)
- {
- *__addr_len = sizeof (struct sockaddr_in6);
- }
- break;
-
- default:
- return -EAFNOSUPPORT;
- }
- }
- }
- else
- {
- /* when __addr is NULL, nothing is filled in,
- * in this case, __addr_len is not used,
- * and should also be null
- * */
- if (__addr_len)
- {
- /* TBD: return proper error code */
- return -1;
- }
- }
- }
-
- return rv;
-}
-
-int
-vcom_socket_accept (int __fd, __SOCKADDR_ARG __addr,
- socklen_t * __restrict __addr_len)
-{
- /* set flags to 0 for accept() */
- return vcom_socket_accept_flags (__fd, __addr, __addr_len, 0);
-}
-
-#ifdef __USE_GNU
-int
-vcom_socket_accept4 (int __fd, __SOCKADDR_ARG __addr,
- socklen_t * __restrict __addr_len, int __flags)
-{
- /* SOCK_NONBLOCK and SOCK_CLOEXEC can be bitwise ORed in flags */
- return vcom_socket_accept_flags (__fd, __addr, __addr_len, __flags);
-}
-#endif
-
-/* TBD: move it to vppcom */
-static inline int
-vcom_session_shutdown (int __fd, int __how)
-{
- return 0;
-}
-
-int
-vcom_socket_shutdown (int __fd, int __how)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- uword *p;
- vcom_socket_t *vsock;
-
- p = hash_get (vsm->sockidx_by_fd, __fd);
- if (p)
- {
- vsock = pool_elt_at_index (vsm->vsockets, p[0]);
- switch (__how)
- {
- case SHUT_RD:
- case SHUT_WR:
- case SHUT_RDWR:
- rv = vcom_session_shutdown (vsock->sid, __how);
- return rv;
- break;
-
- default:
- return -EINVAL;
- break;
- }
- }
-
- return rv;
-}
-
-int
-vcom_socket_epoll_create1 (int __flags)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- vcom_epoll_t *vepoll;
-
- i32 epfd;
- i32 vep_idx;
- i32 epollidx;
-
- epfd = vcom_socket_open_epoll (__flags);
- if (epfd < 0)
- {
- rv = epfd;
- goto out;
- }
-
- vep_idx = vppcom_epoll_create ();
- if (vep_idx < 0)
- {
- rv = vep_idx;
- goto out_close_epoll;
- }
-
- pool_get (vsm->vepolls, vepoll);
- vepoll_init (vepoll);
-
- epollidx = vepoll - vsm->vepolls;
- hash_set (vsm->epollidx_by_epfd, epfd, epollidx);
-
- vepoll_set (vepoll, epfd, vep_idx, EPOLL_TYPE_VPPCOM_BOUND, __flags, 0, 0);
-
- return epfd;
-
-out_close_epoll:
- vcom_socket_close_epoll (epfd);
-out:
- return rv;
-}
-
-/*
- * PRE: vppcom_epoll_ctl() is successful
- * free_vepitem_on_del : 0 - no_pool_put, 1 - pool_put
- */
-int
-vcom_socket_ctl_vepitem (int __epfd, int __op, int __fd,
- struct epoll_event *__event,
- i32 vep_idx, vcom_epoll_t * vepoll,
- i32 vfd_id, void *vfd, vcom_fd_type_t type,
- int free_vepitem_on_del)
-{
- int rv = -1;
- vcom_socket_main_t *vsm = &vcom_socket_main;
- vcom_epitem_t *vepitem;
-
- vcom_epitem_key_t epfdfd = {.epfd = __epfd,.fd = __fd };
- uword *p;
- i32 vepitemidx;
-
- i32 *vepitemidxs = 0;
-
- struct epoll_event revent = {.events = 0,.data.fd = INVALID_FD };
-
- i32 vec_idx;
-
- /* perform control operations on the epoll instance */
- switch (__op)
- {
- case EPOLL_CTL_ADD:
- /*
- * supplied file descriptor is already
- * registered with this epoll instance
- * */
- /* vepitem exists */
- p = hash_get (vsm->epitemidx_by_epfdfd, epfdfd.key);
- if (p)
- {
- rv = -EEXIST;
- goto out;
- }
-
- /* add a new vepitem */
- pool_get (vsm->vepitems, vepitem);
- vepitem_init (vepitem);
-
- vepitemidx = vepitem - vsm->vepitems;
- hash_set (vsm->epitemidx_by_epfdfd, epfdfd.key, vepitemidx);
- vepitem_set (vepitem, __epfd, __fd, __fd, __fd, type, *__event, revent);
-
- /* update epitemidxs */
- /* by_epfd */
- p = hash_get (vsm->epitemidxs_by_epfd, __epfd);
- if (!p) /* not exist */
- {
- vepitemidxs = 0;
- vec_add1 (vepitemidxs, vepitemidx);
- hash_set (vsm->epitemidxs_by_epfd, __epfd, vepitemidxs);
- }
- else /* exists */
- {
- vepitemidxs = *(i32 **) p;
- vec_add1 (vepitemidxs, vepitemidx);
- hash_set3 (vsm->epitemidxs_by_epfd, __epfd, vepitemidxs, 0);
- }
- /* update epitemidxs */
- /* by_fd */
- p = hash_get (vsm->epitemidxs_by_fd, __fd);
- if (!p) /* not exist */
- {
- vepitemidxs = 0;
- vec_add1 (vepitemidxs, vepitemidx);
- hash_set (vsm->epitemidxs_by_fd, __fd, vepitemidxs);
- }
- else /* exists */
- {
- vepitemidxs = *(i32 **) p;
- vec_add1 (vepitemidxs, vepitemidx);
- hash_set3 (vsm->epitemidxs_by_fd, __fd, vepitemidxs, 0);
- }
-
- /* increment vepoll fd count by 1 */
- vepoll->count += 1;
-
- rv = 0;
- goto out;
- break;
-
- case EPOLL_CTL_MOD:
- /*
- * supplied file descriptor is not
- * registered with this epoll instance
- * */
- /* vepitem not exist */
- p = hash_get (vsm->epitemidx_by_epfdfd, epfdfd.key);
- if (!p)
- {
- rv = -ENOENT;
- goto out;
- }
- vepitem = pool_elt_at_index (vsm->vepitems, p[0]);
- if (vepitem)
- {
- vepitem->event = *__event;
- vepitem->revent = revent;
- }
-
- rv = 0;
- goto out;
- break;
-
- case EPOLL_CTL_DEL:
- /*
- * supplied file descriptor is not
- * registered with this epoll instance
- * */
- /* vepitem not exist */
- p = hash_get (vsm->epitemidx_by_epfdfd, epfdfd.key);
- if (!p)
- {
- rv = -ENOENT;
- goto out;
- }
- vepitemidx = *(i32 *) p;
- hash_unset (vsm->epitemidx_by_epfdfd, epfdfd.key);
-
- /* update epitemidxs */
- /* by_epfd */
- p = hash_get (vsm->epitemidxs_by_epfd, __epfd);
- if (!p) /* not exist */
- {
- rv = -ENOENT;
- goto out;
- }
- else /* exists */
- {
- vepitemidxs = *(i32 **) p;
- vec_idx = vec_search (vepitemidxs, vepitemidx);
- if (vec_idx != ~0)
- {
- vec_del1 (vepitemidxs, vec_idx);
- if (!vec_len (vepitemidxs))
- {
- vec_free (vepitemidxs);
- hash_unset (vsm->epitemidxs_by_epfd, __epfd);
- }
- }
- }
-
- /* update epitemidxs */
- /* by_fd */
- p = hash_get (vsm->epitemidxs_by_fd, __fd);
- if (!p) /* not exist */
- {
- rv = -ENOENT;
- goto out;
- }
- else /* exists */
- {
- vepitemidxs = *(i32 **) p;
- vec_idx = vec_search (vepitemidxs, vepitemidx);
- if (vec_idx != ~0)
- {
- vec_del1 (vepitemidxs, vec_idx);
- if (!vec_len (vepitemidxs))
- {
- vec_free (vepitemidxs);
- hash_unset (vsm->epitemidxs_by_fd, __fd);
- }
- }
- }
-
- /* pool put vepitem */
- vepitem = pool_elt_at_index (vsm->vepitems, vepitemidx);
- if (free_vepitem_on_del)
- {
- if (!vepitem)
- {
- rv = -ENOENT;
- goto out;
- }
- vepitem_init (vepitem);
- pool_put (vsm->vepitems, vepitem);
- }
- else
- {
- if (!vepitem)
- {
- vepitem_init (vepitem);
- }
- }
-
- /* decrement vepoll fd count by 1 */
- vepoll->count -= 1;
-
- rv = 0;
- goto out;
- break;
-
- default:
- rv = -EINVAL;
- goto out;
- break;
- }
-
-out:
- return rv;
-}
-
-/*
- * PRE: 00. null pointer check on __event
- * 01. all other parameters are validated
- */
-
-static int
-vcom_socket_epoll_ctl_internal (int __epfd, int __op, int __fd,
- struct epoll_event *__event,
- int free_vepitem_on_del)
-{
- int rv = -1;
-
- /* vcom_socket_main_t *vsm = &vcom_socket_main; */
- vcom_epoll_t *vepoll;
-
- /*__fd could could be vcom socket or vcom epoll or kernel fd */
- void *vfd;
- vcom_epoll_t *vfd_vepoll;
- vcom_socket_t *vfd_vsock;
-
- i32 vep_idx;
- i32 vfd_id;
-
- vcom_fd_type_t type = FD_TYPE_INVALID;
-
- /* validate __event */
-
- /* get vep_idx and vepoll */
- vep_idx = vcom_socket_get_vep_idx_and_vepoll (__epfd, &vepoll);
- if (vep_idx == INVALID_VEP_IDX)
- {
- return -EBADF;
- }
-
- /* get vcom fd type, vfd_id and vfd */
- vfd_id = vcom_socket_get_sid_and_vsock (__fd, &vfd_vsock);
- if (vfd_id != INVALID_SESSION_ID)
- {
- type = FD_TYPE_VCOM_SOCKET;
- vfd = vfd_vsock;
- }
- else if ((vfd_id = vcom_socket_get_vep_idx_and_vepoll (__fd, &vfd_vepoll))
- != INVALID_VEP_IDX)
- {
- type = FD_TYPE_EPOLL;
- vfd = vfd_vepoll;
- }
- else
- {
- /* FD_TYPE_KERNEL not supported by epoll instance */
- type = FD_TYPE_INVALID;
- return -EBADF;
- }
-
-
- /* vepoll and vsock are now valid */
- rv = vppcom_epoll_ctl (vep_idx, __op, vfd_id, __event);
- if (rv < 0)
- {
- return rv;
- }
-
- rv = vcom_socket_ctl_vepitem (__epfd, __op, __fd,
- __event,
- vep_idx, vepoll,
- vfd_id, vfd, type, free_vepitem_on_del);
- return rv;
-}
-
-int
-vcom_socket_epoll_ctl (int __epfd, int __op, int __fd,
- struct epoll_event *__event)
-{
- int rv = -1;
-
- rv = vcom_socket_epoll_ctl_internal (__epfd, __op, __fd, __event, 1);
- return rv;
-}
-
-static int
-vcom_socket_epoll_ctl1 (int __epfd, int __op, int __fd,
- struct epoll_event *__event)
-{
- int rv = -1;
-
- rv = vcom_socket_epoll_ctl_internal (__epfd, __op, __fd, __event, 0);
- return rv;
-}
-
-int
-vcom_socket_epoll_pwait (int __epfd, struct epoll_event *__events,
- int __maxevents, int __timeout,
- const __sigset_t * __ss)
-{
- int rv = -EBADF;
-
- /* in seconds eg. 3.123456789 seconds */
- double time_to_wait = (double) 0;
-
- i32 vep_idx;
-
- /* validate __event */
- if (!__events)
- {
- rv = -EFAULT;
- goto out;
- }
-
- /* validate __timeout */
- if (__timeout > 0)
- {
- time_to_wait = (double) __timeout / (double) 1000;
- }
- else if (__timeout == 0)
- {
- time_to_wait = (double) 0;
- }
- else if (__timeout == -1)
- {
- time_to_wait = ~0;
- }
- else
- {
- rv = -EBADF;
- goto out;
- }
-
- /* get vep_idx */
- vep_idx = vcom_socket_get_vep_idx (__epfd);
- if (vep_idx != INVALID_VEP_IDX)
- {
- rv = vppcom_epoll_wait (vep_idx, __events, __maxevents, time_to_wait);
- }
-out:
- return rv;
-}
-
-static inline void
-vcom_pollfds_2_selectfds (
- /* src */
- struct pollfd *__fds, nfds_t __nfds,
- /* dest */
- int vcom_nfds,
- fd_set * __restrict vcom_readfds,
- fd_set * __restrict vcom_writefds,
- fd_set * __restrict vcom_exceptfds)
-{
- nfds_t fds_idx = 0;
-
- for (fds_idx = 0; fds_idx < __nfds; fds_idx++)
- {
- /* ignore negative fds */
- if (__fds[fds_idx].fd < 0)
- {
- continue;
- }
-
- /* for POLLRDHUP, POLLERR, POLLHUP and POLLNVAL */
- FD_SET (__fds[fds_idx].fd, vcom_exceptfds);
-
- /* requested events */
- if (__fds[fds_idx].events)
- {
- if (__fds[fds_idx].events & POLLIN)
- {
- FD_SET (__fds[fds_idx].fd, vcom_readfds);
- }
- if (__fds[fds_idx].events & POLLPRI)
- {
- FD_SET (__fds[fds_idx].fd, vcom_readfds);
- }
- if (__fds[fds_idx].events & POLLOUT)
- {
- FD_SET (__fds[fds_idx].fd, vcom_writefds);
- }
-#if defined __USE_XOPEN || defined __USE_XOPEN2K8
- if (__fds[fds_idx].events & POLLRDNORM)
- {
- FD_SET (__fds[fds_idx].fd, vcom_readfds);
- }
- if (__fds[fds_idx].events & POLLRDBAND)
- {
- FD_SET (__fds[fds_idx].fd, vcom_readfds);
- }
- if (__fds[fds_idx].events & POLLWRNORM)
- {
- FD_SET (__fds[fds_idx].fd, vcom_writefds);
- }
- if (__fds[fds_idx].events & POLLWRBAND)
- {
- FD_SET (__fds[fds_idx].fd, vcom_writefds);
- }
-#endif
- }
- } /* for (fds_idx = 0; fds_idx < __nfds; fds_idx++) */
-}
-
-static inline void
-vcom_selectfds_2_pollfds (
- /* dest */
- struct pollfd *__fds, nfds_t __nfds, int *nfd,
- /* src */
- int vcom_nfds,
- fd_set * __restrict vcom_readfds,
- fd_set * __restrict vcom_writefds,
- fd_set * __restrict vcom_exceptfds)
-{
- nfds_t fds_idx = 0;
-
-
- for (fds_idx = 0; fds_idx < __nfds; fds_idx++)
- {
- /* ignore negative fds */
- if (__fds[fds_idx].fd < 0)
- {
- __fds[fds_idx].revents = 0;
- }
-
- /* for POLLRDHUP, POLLERR, POLLHUP and POLLNVAL */
- if (FD_ISSET (__fds[fds_idx].fd, vcom_exceptfds))
- {
- /*
- * TBD: for now any select exception
- * is flagged as POLLERR
- * */
- __fds[fds_idx].revents |= POLLERR;
- }
-
- /* requested events */
- if (__fds[fds_idx].events & POLLIN)
- {
- if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds))
- {
- __fds[fds_idx].revents |= POLLIN;
- }
- }
- if (__fds[fds_idx].events & POLLPRI)
- {
- if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds))
- {
- __fds[fds_idx].revents |= POLLIN;
- }
- }
- if (__fds[fds_idx].events & POLLOUT)
- {
- if (FD_ISSET (__fds[fds_idx].fd, vcom_writefds))
- {
- __fds[fds_idx].revents |= POLLOUT;
- }
- }
-#if defined __USE_XOPEN || defined __USE_XOPEN2K8
- if (__fds[fds_idx].events & POLLRDNORM)
- {
- if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds))
- {
- __fds[fds_idx].revents |= POLLRDNORM;
- }
- }
- if (__fds[fds_idx].events & POLLRDBAND)
- {
- if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds))
- {
- __fds[fds_idx].revents |= POLLRDBAND;
- }
- }
- if (__fds[fds_idx].events & POLLWRNORM)
- {
- if (FD_ISSET (__fds[fds_idx].fd, vcom_writefds))
- {
- __fds[fds_idx].revents |= POLLWRNORM;
- }
- }
- if (__fds[fds_idx].events & POLLWRBAND)
- {
- if (FD_ISSET (__fds[fds_idx].fd, vcom_writefds))
- {
- __fds[fds_idx].revents |= POLLWRBAND;
- }
- }
-#endif
- } /* for (fds_idx = 0; fds_idx < __nfds; fds_idx++) */
-
- /*
- * nfd:
- * the number of structures which have nonzero revents fields
- * (in other words, those descriptors with events or
- * errors reported)
- * */
- *nfd = 0;
- for (fds_idx = 0; fds_idx < __nfds; fds_idx++)
- {
- /* ignore negative fds */
- if (__fds[fds_idx].fd < 0)
- {
- continue;
- }
-
- if (__fds[fds_idx].revents)
- {
- (*nfd)++;
- }
- }
-}
-
-/*
- * PRE: parameters are validated,
- * vcom_socket_poll is always called with __timeout set to zero
- * hence returns immediately
- *
- * ACTION: handle non negative validated vcom fds and ignore rest
- */
-
-/*
- * implements vcom_socket_poll () interface
- *
- * internally uses vcom_socket_select ()
- * to realize the behavior
- * */
-int
-vcom_socket_poll_select_impl (struct pollfd *__fds, nfds_t __nfds,
- int __timeout)
-{
- int rv;
- pid_t pid = getpid ();
-
- nfds_t fds_idx = 0;
- int nfd = 0;
-
- /* vcom */
- int vcom_nfds = 0;
- fd_set vcom_readfds;
- fd_set vcom_writefds;
- fd_set vcom_exceptfds;
- int vcom_nfd = -1;
- /* invalid max_vcom_fd is -1 */
- int max_vcom_fd = -1;
-
- /* __timeout is zero to get ready events and return immediately */
- struct timeval tv = {.tv_sec = 0,.tv_usec = 0 };
-
- /* validate __nfds from select perspective */
- if (__nfds < 0 || __nfds > FD_SETSIZE)
- {
- rv = -EINVAL;
- goto poll_done;
- }
-
- /* zero vcom fd sets */
- /*
- * V vcom fd set
- */
-#define _(V) \
- FD_ZERO ((V))
-
- _(&vcom_readfds);
- _(&vcom_writefds);
- _(&vcom_exceptfds);
-#undef _
-
- vcom_nfds = 0;
- vcom_nfd = -1;
-
-
- for (fds_idx = 0; fds_idx < __nfds; fds_idx++)
- {
- /* ignore negative fds */
- if (__fds[fds_idx].fd < 0)
- {
- continue;
- }
-
- /* non negative validated vcom fds */
- if (__fds[fds_idx].fd > FD_SETSIZE)
- {
- rv = -EINVAL;
- goto poll_done;
- }
-
- /* max_vcom_fd and vcom_nfd */
- if (__fds[fds_idx].fd > max_vcom_fd)
- {
- /* requested events */
- if (__fds[fds_idx].events)
- {
- max_vcom_fd = __fds[fds_idx].fd;
- }
- }
- ++vcom_nfd;
- }
-
- vcom_nfds = max_vcom_fd != -1 ? max_vcom_fd + 1 : 0;
-
- if (!vcom_nfds)
- {
- rv = vcom_nfds;
- goto poll_done;
- }
-
- vcom_pollfds_2_selectfds (
- /* src */
- __fds, __nfds,
- /* dest */
- vcom_nfds,
- &vcom_readfds, &vcom_writefds, &vcom_exceptfds);
-
- /* select on vcom fds */
- vcom_nfd = vcom_socket_select (vcom_nfds,
- &vcom_readfds,
- &vcom_writefds, &vcom_exceptfds, &tv);
- if (VCOM_DEBUG > 2)
- fprintf (stderr,
- "[%d] vcom_socket_select: "
- "'%04d'='%04d'\n", pid, vcom_nfd, vcom_nfds);
-
- if (vcom_nfd < 0)
- {
- rv = vcom_nfd;
- goto poll_done;
- }
-
- vcom_selectfds_2_pollfds (
- /* dest */
- __fds, __nfds, &nfd,
- /* src */
- vcom_nfds,
- &vcom_readfds, &vcom_writefds, &vcom_exceptfds);
-
- rv = nfd;
-
-poll_done:
- return rv;
-}
-
-/*
- * TBD: remove this static function once vppcom
- * has an implementation in place
- *
- * ACTION:
- */
-static int
-vppcom_poll (struct pollfd *__fds, nfds_t __nfds, double time_to_wait)
-{
- return -EOPNOTSUPP;
-}
-
-int
-vcom_socket_poll_vppcom_impl (struct pollfd *__fds, nfds_t __nfds,
- int __timeout)
-{
- nfds_t fds_idx = 0;
-
- /* in seconds eg. 3.123456789 seconds */
- double time_to_wait = (double) 0;
-
- i32 sid;
- i32 vep_idx;
-
- /* replace vcom fd with session idx */
- for (fds_idx = 0; fds_idx < __nfds; fds_idx++)
- {
- /* ignore negative fds */
- if (__fds[fds_idx].fd < 0)
- {
- continue;
- }
-
- /* non negative validated vcom fds */
- sid = vcom_socket_get_sid (__fds[fds_idx].fd);
- if (sid != INVALID_SESSION_ID)
- {
- __fds[fds_idx].fd = sid;
- }
- else
- {
- /* get vep_idx */
- vep_idx = vcom_socket_get_vep_idx (__fds[fds_idx].fd);
- if (vep_idx != INVALID_VEP_IDX)
- {
- __fds[fds_idx].fd = vep_idx;
- }
- else
- {
- return -EBADF;
- }
- }
- }
-
- /* validate __timeout */
- if (__timeout > 0)
- {
- time_to_wait = (double) __timeout / (double) 1000;
- }
- else if (__timeout == 0)
- {
- time_to_wait = (double) 0;
- }
- else if (__timeout < 0)
- {
- time_to_wait = ~0;
- }
- else
- {
- return -EBADF;
- }
-
- return vppcom_poll (__fds, __nfds, time_to_wait);
-}
-
-int
-vcom_socket_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
-{
- /* select an implementation */
-
- /* return vcom_socket_poll_vppcom_impl (__fds, __nfds, __timeout); */
- return vcom_socket_poll_select_impl (__fds, __nfds, __timeout);
-}
-
-#ifdef __USE_GNU
-int
-vcom_socket_ppoll (struct pollfd *__fds, nfds_t __nfds,
- const struct timespec *__timeout, const __sigset_t * __ss)
-{
- return -EOPNOTSUPP;
-}
-#endif
-
-int
-vcom_socket_main_init (void)
-{
- vcom_socket_main_t *vsm = &vcom_socket_main;
-
- if (VCOM_DEBUG > 0)
- printf ("vcom_socket_main_init\n");
-
- if (!vsm->init)
- {
- /* TBD: define FD_MAXSIZE and use it here */
- pool_alloc (vsm->vsockets, FD_SETSIZE);
- vsm->sockidx_by_fd = hash_create (0, sizeof (i32));
-
- pool_alloc (vsm->vepolls, FD_SETSIZE);
- vsm->epollidx_by_epfd = hash_create (0, sizeof (i32));
-
- pool_alloc (vsm->vepitems, FD_SETSIZE);
- vsm->epitemidx_by_epfdfd = hash_create (0, sizeof (i32));
-
- vsm->epitemidxs_by_epfd = hash_create (0, sizeof (i32 *));
- vsm->epitemidxs_by_fd = hash_create (0, sizeof (i32 *));
-
- vsm->init = 1;
- }
-
- return 0;
-}
-
-
-void
-vcom_socket_main_show (void)
-{
- vcom_socket_main_t *vsm = &vcom_socket_main;
- vcom_socket_t *vsock;
-
- vcom_epoll_t *vepoll;
-
- vcom_epitem_t *vepitem;
-
- i32 epfd;
- i32 fd;
- i32 *vepitemidxs, *vepitemidxs_var;
-
- if (vsm->init)
- {
- /* from active list of vsockets show vsock */
-
- /* *INDENT-OFF* */
- pool_foreach (vsock, vsm->vsockets,
- ({
- printf(
- "fd='%04d', sid='%08x',type='%-30s'\n",
- vsock->fd, vsock->sid,
- vcom_socket_type_str (vsock->type));
- }));
- /* *INDENT-ON* */
-
- /* from active list of vepolls, show vepoll */
-
- /* *INDENT-OFF* */
- pool_foreach (vepoll, vsm->vepolls,
- ({
- printf(
- "epfd='%04d', vep_idx='%08x', "
- "type='%-30s', "
- "flags='%d', count='%d', close='%d'\n",
- vepoll->epfd, vepoll->vep_idx,
- vcom_socket_epoll_type_str (vepoll->type),
- vepoll->flags, vepoll->count, vepoll->close);
- }));
- /* *INDENT-ON* */
-
- /* from active list of vepitems, show vepitem */
-
- /* *INDENT-OFF* */
- pool_foreach (vepitem, vsm->vepitems,
- ({
- printf(
- "epfd='%04d', fd='%04d', "
- "next_fd='%04d', prev_fd='%04d', "
- "type='%-30s', "
- "events='%04x', revents='%04x'\n",
- vepitem->epfd, vepitem->fd,
- vepitem->next_fd, vepitem->prev_fd,
- vcom_socket_vcom_fd_type_str (vepitem->type),
- vepitem->event.events, vepitem->revent.events);
- }));
-
- /* *INDENT-ON* */
-
- /* show epitemidxs for epfd */
- /* *INDENT-OFF* */
- hash_foreach (epfd, vepitemidxs,
- vsm->epitemidxs_by_epfd,
- ({
- printf("\n[ '%04d': ", epfd);
- vec_foreach (vepitemidxs_var,vepitemidxs)
- {
- printf("'%04d' ", (int)vepitemidxs_var[0]);
- }
- printf("]\n");
- }));
- /* *INDENT-ON* */
-
- /* show epitemidxs for fd */
- /* *INDENT-OFF* */
- hash_foreach (fd, vepitemidxs,
- vsm->epitemidxs_by_fd,
- ({
- printf("\n{ '%04d': ", fd);
- vec_foreach (vepitemidxs_var,vepitemidxs)
- {
- printf("'%04d' ", (int)vepitemidxs_var[0]);
- }
- printf("}\n");
- }));
- /* *INDENT-ON* */
-
- }
-}
-
-void
-vcom_socket_main_destroy (void)
-{
- vcom_socket_main_t *vsm = &vcom_socket_main;
- vcom_socket_t *vsock;
-
- vcom_epoll_t *vepoll;
-
- vcom_epitem_t *vepitem;
-
- i32 epfd;
- i32 fd;
- i32 *vepitemidxs;
-
-
- if (VCOM_DEBUG > 0)
- printf ("vcom_socket_main_destroy\n");
-
- if (vsm->init)
- {
-
- /*
- * from active list of vepitems,
- * remove all "vepitem" elements from the pool in a safe way
- * */
-
- /* *INDENT-OFF* */
- pool_flush (vepitem, vsm->vepitems,
- ({
- if (vepitem->type == FD_TYPE_EPOLL || FD_TYPE_VCOM_SOCKET)
- {
- vcom_socket_epoll_ctl1 (vepitem->epfd, EPOLL_CTL_DEL,
- vepitem->fd, NULL);
- vepitem_init (vepitem);
- }
- }));
- /* *INDENT-ON* */
-
- pool_free (vsm->vepitems);
- hash_free (vsm->epitemidx_by_epfdfd);
-
- /* free vepitemidxs for each epfd */
- /* *INDENT-OFF* */
- hash_foreach (epfd, vepitemidxs,
- vsm->epitemidxs_by_epfd,
- ({
- vec_free (vepitemidxs);
- }));
- /* *INDENT-ON* */
- hash_free (vsm->epitemidxs_by_epfd);
-
- /* free vepitemidxs for each fd */
- /* *INDENT-OFF* */
- hash_foreach (fd, vepitemidxs,
- vsm->epitemidxs_by_fd,
- ({
- vec_free (vepitemidxs);
- }));
- /* *INDENT-ON* */
- hash_free (vsm->epitemidxs_by_fd);
-
-
- /*
- * from active list of vsockets,
- * close socket and vppcom session
- * */
-
- /* *INDENT-OFF* */
- pool_foreach (vsock, vsm->vsockets,
- ({
- if (vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
- {
- vppcom_session_close (vsock->sid);
- vcom_socket_close_socket (vsock->fd);
- vsocket_init (vsock);
- }
- }));
- /* *INDENT-ON* */
-
- /*
- * return vsocket element to the pool
- * */
-
- /* *INDENT-OFF* */
- pool_flush (vsock, vsm->vsockets,
- ({
- // vsocket_init(vsock);
- ;
- }));
- /* *INDENT-ON* */
-
- pool_free (vsm->vsockets);
- hash_free (vsm->sockidx_by_fd);
-
- /*
- * from active list of vepolls,
- * close epoll and vppcom_epoll
- * */
-
- /* *INDENT-OFF* */
- pool_foreach (vepoll, vsm->vepolls,
- ({
- if (vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
- {
- vppcom_session_close (vepoll->vep_idx);
- vcom_socket_close_epoll (vepoll->epfd); /* TBD: */
- vepoll_init (vepoll);
- }
- }));
- /* *INDENT-ON* */
-
- /*
- * return vepoll element to the pool
- * */
-
- /* *INDENT-OFF* */
- pool_flush (vepoll, vsm->vepolls,
- ({
- // vepoll_init(vepoll);
- ;
- }));
- /* *INDENT-ON* */
-
- pool_free (vsm->vepolls);
- hash_free (vsm->epollidx_by_epfd);
-
- vsm->init = 0;
- }
-}
-
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */