return 0;
}
-static int
-vppcom_session_fcntl_va (int __sid, int __cmd, va_list __ap)
+static inline int
+vcom_session_fcntl_va (int __sid, int __cmd, va_list __ap)
{
int flags = va_arg (__ap, int);
int rv = -EOPNOTSUPP;
break;
/* cmd handled by vppcom */
case 3:
- rv = vppcom_session_fcntl_va (vsock->sid, __cmd, __ap);
+ rv = vcom_session_fcntl_va (vsock->sid, __cmd, __ap);
break;
default:
return rc;
}
-static int
-vppcom_session_ioctl_va (int __sid, int __cmd, va_list __ap)
+static inline int
+vcom_session_ioctl_va (int __sid, int __cmd, va_list __ap)
{
int rv;
/* cmd handled by vppcom */
case 3:
- rv = vppcom_session_ioctl_va (vsock->sid, __cmd, __ap);
+ rv = vcom_session_ioctl_va (vsock->sid, __cmd, __ap);
break;
default:
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 ();
fd_set vcom_rd_sid_fds;
fd_set vcom_wr_sid_fds;
fd_set vcom_ex_sid_fds;
- unsigned long vcom_nsid_fds = 0;
- int vcom_nsid = 0;
/* in seconds eg. 3.123456789 seconds */
double time_to_wait = (double) 0;
_(&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 */
NULL,
vcom_exceptfds ? (unsigned long *) &vcom_ex_sid_fds :
NULL, time_to_wait);
- if (VCOM_DEBUG > 0)
- fprintf (stderr, "[%d] vppcom_select: "
+ 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 */
}
rv = vppcom_session_bind (vsock->sid, &ep);
- /* TBD: remove libc_bind code snippet
- * once vppcom implements vppcom_session_getsockname */
- if (rv == 0)
- {
- rv = libc_bind (__fd, __addr, __len);
- if (rv != 0)
- {
- rv = -errno;
- }
- }
return rv;
}
-int
-vppcom_session_getsockname (int sid, vppcom_endpt_t * ep)
+static inline int
+vcom_session_getsockname (int sid, vppcom_endpt_t * ep)
{
- /* TBD: move it to vppcom */
- return 0;
+ int rv;
+ uint32_t size = sizeof (*ep);
+
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LCL_ADDR, ep, &size);
+ return rv;
}
int
return -EINVAL;
}
- /* TBD: remove libc_getsockname code snippet
- * once vppcom implements vppcom_session_getsockname */
- rv = libc_getsockname (__fd, __addr, __len);
- if (rv != 0)
- {
- rv = -errno;
- return rv;
- }
-
- /* TBD: use the below code snippet when vppcom
- * implements vppcom_session_getsockname */
-#if 0
vppcom_endpt_t ep;
ep.ip = (u8 *) & ((const struct sockaddr_in *) __addr)->sin_addr;
- rv = vppcom_session_getsockname (vsock->sid, &ep);
+ rv = vcom_session_getsockname (vsock->sid, &ep);
if (rv == 0)
{
if (ep.vrf == VPPCOM_VRF_DEFAULT)
}
}
}
-#endif
return rv;
}
return rv;
}
-int
-vppcom_session_getpeername (int sid, vppcom_endpt_t * ep)
+static inline int
+vcom_session_getpeername (int sid, vppcom_endpt_t * ep)
{
- /* TBD: move it to vppcom */
- return 0;
+ int rv;
+ uint32_t size = sizeof (*ep);
+
+ rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PEER_ADDR, ep, &size);
+ return rv;
}
int
return -EINVAL;
}
- /* DAW: hack to allow iperf3 to be happy w/ getpeername output */
- {
- uint8_t *a;
- ((struct sockaddr_in *) __addr)->sin_family = AF_INET;
- ((struct sockaddr_in *) __addr)->sin_port = 0x1000;
- a = (uint8_t *) & ((struct sockaddr_in *) __addr)->sin_addr;
- a[0] = 0x7f;
- a[1] = 0x00;
- a[2] = 0x00;
- a[3] = 0x01;
- *__len = sizeof (struct sockaddr_in);
- return 0;
- }
-
- /* TBD: remove libc_getpeername code snippet
- * once vppcom implements vppcom_session_getpeername */
- rv = libc_getpeername (__fd, __addr, __len);
- if (rv != 0)
- {
- rv = -errno;
- return rv;
- }
-
- /* TBD: use the below code snippet when vppcom
- * implements vppcom_session_getpeername */
-#if 0
vppcom_endpt_t ep;
ep.ip = (u8 *) & ((const struct sockaddr_in *) __addr)->sin_addr;
- rv = vppcom_session_getpeername (vsock->sid, &ep);
+ rv = vcom_session_getpeername (vsock->sid, &ep);
if (rv == 0)
{
if (ep.vrf == VPPCOM_VRF_DEFAULT)
}
}
}
-#endif
return rv;
}
return 0;
}
-ssize_t
-vvppcom_session_sendto (int __sid, const void *__buf, size_t __n,
- int __flags, __CONST_SOCKADDR_ARG __addr,
- socklen_t __addr_len)
+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 */
if (!vsock)
return -ENOTSOCK;
- if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
- return -EINVAL;
-
- if (!__buf || __n < 0)
+ if ((vsock->type != SOCKET_TYPE_VPPCOM_BOUND) || !__buf || __n < 0)
{
return -EINVAL;
}
}
}
- rv = vvppcom_session_sendto (vsock->sid, (void *) __buf, (int) __n,
- __flags, __addr, __addr_len);
+ rv = vcom_session_sendto (vsock->sid, (void *) __buf, (int) __n,
+ __flags, __addr, __addr_len);
return rv;
}
-/* TBD: move it to vppcom */
-static ssize_t
-vppcom_session_recvfrom (int __sid, void *__restrict __buf, size_t __n,
- int __flags, __SOCKADDR_ARG __addr,
- socklen_t * __restrict __addr_len)
+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;
if (!vsock)
return -ENOTSOCK;
- if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
- return -EINVAL;
-
- if (!__buf || __n < 0)
+ if ((vsock->type != SOCKET_TYPE_VPPCOM_BOUND) ||
+ !__buf || __n < 0 || !__addr || !__addr_len || (__addr_len < 0))
{
return -EINVAL;
}
- if (__addr || __addr_len < 0)
- {
- return -EINVAL;
- }
-
- rv = vppcom_session_recvfrom (vsock->sid, __buf, __n,
- __flags, __addr, __addr_len);
+ rv = vcom_session_recvfrom (vsock->sid, __buf, __n,
+ __flags, __addr, __addr_len);
return rv;
}
/* TBD: move it to vppcom */
-static ssize_t
-vppcom_sendmsg (int __sid, const struct msghdr *__message, int __flags)
+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,
;
}
- rv = vppcom_sendmsg (vsock->sid, __message, __flags);
+ rv = vcom_session_sendmsg (vsock->sid, __message, __flags);
return rv;
}
#endif
/* TBD: move it to vppcom */
-static ssize_t
-vppcom_recvmsg (int __sid, struct msghdr *__message, int __flags)
+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,
/* validate __flags */
- rv = vppcom_recvmsg (vsock->sid, __message, __flags);
+ rv = vcom_session_recvmsg (vsock->sid, __message, __flags);
return rv;
}
#endif
/* TBD: move it to vppcom */
-static int
-vppcom_getsockopt (int __sid, int __level, int __optname,
- void *__restrict __optval, socklen_t * __restrict __optlen)
+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 */
-#if 0
return 0;
-#endif
-
- /* 2. unhandled options */
- return -ENOPROTOOPT;
}
int
default:
/* 1. handle options that are NOT socket level options,
* but have corresponding vpp otions. */
- rv = vppcom_getsockopt (vsock->sid, __level, __optname,
- __optval, __optlen);
-
- return rv;
-#if 0
- /* 2. unhandled options */
- return -ENOPROTOOPT;
-#endif
+ rv = vcom_session_get_sockopt (vsock->sid, __level, __optname,
+ __optval, __optlen);
+ break;
}
return rv;
}
/* TBD: move it to vppcom */
-int
-vppcom_session_setsockopt (int __sid, int __level, int __optname,
- const void *__optval, socklen_t __optlen)
+static inline int
+vcom_session_setsockopt (int __sid, int __level, int __optname,
+ const void *__optval, socklen_t __optlen)
{
int rv = -EOPNOTSUPP;
switch (__optname)
{
case IPV6_V6ONLY:
- rv = vppcom_session_setsockopt (vsock->sid, __level, __optname,
- __optval, __optlen);
+ rv = vcom_session_setsockopt (vsock->sid, __level, __optname,
+ __optval, __optlen);
break;
default:
return -EOPNOTSUPP;
return 0;
case TCP_KEEPIDLE:
case TCP_KEEPINTVL:
- rv = vppcom_session_setsockopt (vsock->sid, __level, __optname,
- __optval, __optlen);
+ rv = vcom_session_setsockopt (vsock->sid, __level, __optname,
+ __optval, __optlen);
break;
default:
return -EOPNOTSUPP;
case SO_REUSEADDR:
case SO_BROADCAST:
case SO_KEEPALIVE:
- rv = vppcom_session_setsockopt (vsock->sid, __level, __optname,
- __optval, __optlen);
+ rv = vcom_session_setsockopt (vsock->sid, __level, __optname,
+ __optval, __optlen);
break;
/*
#endif
/* TBD: move it to vppcom */
-int
-vppcom_session_shutdown (int __fd, int __how)
+static inline int
+vcom_session_shutdown (int __fd, int __how)
{
return 0;
}
case SHUT_RD:
case SHUT_WR:
case SHUT_RDWR:
- rv = vppcom_session_shutdown (vsock->sid, __how);
+ rv = vcom_session_shutdown (vsock->sid, __how);
return rv;
break;
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)
{