X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvcl%2Fvcom_socket.c;h=a84359e84179616ed18345fb4467040815ea47d7;hb=0cdd5bd05bbb78c28a6995eff1d80eeabb9d6fd1;hp=de558e7beed069e9e6b215d1777aebab19b4d619;hpb=c981b0970e2709d7bc84363eec0f1326adb2505d;p=vpp.git diff --git a/src/vcl/vcom_socket.c b/src/vcl/vcom_socket.c index de558e7beed..a84359e8417 100644 --- a/src/vcl/vcom_socket.c +++ b/src/vcl/vcom_socket.c @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -41,6 +42,8 @@ typedef struct vcom_socket_main_t_ { u8 init; + clib_time_t clib_time; + pid_t my_pid; /* vcom_socket pool */ vcom_socket_t *vsockets; @@ -54,7 +57,6 @@ typedef struct vcom_socket_main_t_ /* 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 */ @@ -779,10 +781,24 @@ 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; + switch (__cmd) + { + case FIONREAD: + rv = vppcom_session_attr (__sid, VPPCOM_ATTR_GET_NREAD, 0, 0); + break; + + case FIONBIO: + { + u32 flags = va_arg (__ap, int) ? O_NONBLOCK : 0; + u32 len = sizeof (flags); + rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_FLAGS, &flags, &len); + } + break; + + default: + rv = -EOPNOTSUPP; + break; + } return rv; } @@ -1015,7 +1031,6 @@ vcom_socket_select (int vcom_nfds, fd_set * __restrict vcom_readfds, 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; @@ -1084,13 +1099,14 @@ vcom_socket_select (int vcom_nfds, fd_set * __restrict vcom_readfds, if (VCOM_DEBUG > 0) fprintf (stderr, "[%d] vcom_socket_select called to " - "emulate delay_ns()!\n", pid); + "emulate delay_ns()!\n", getpid ()); 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); + "and invalid time_to_wait (%f)!\n", + getpid (), time_to_wait); } return 0; } @@ -1125,7 +1141,7 @@ vcom_socket_select (int vcom_nfds, fd_set * __restrict vcom_readfds, NULL, time_to_wait); if (VCOM_DEBUG > 2) fprintf (stderr, "[%d] called vppcom_select(): " - "'%04d'='%04d'\n", pid, rv, (int) vcom_nsid_fds); + "'%04d'='%04d'\n", getpid (), rv, (int) vcom_nsid_fds); /* check if any file descriptors changed status */ if (rv > 0) @@ -1397,6 +1413,47 @@ vcom_session_getpeername (int sid, vppcom_endpt_t * ep) return rv; } +static inline int +vcom_socket_copy_ep_to_sockaddr (__SOCKADDR_ARG __addr, + socklen_t * __restrict __len, + vppcom_endpt_t * ep) +{ + int rv = 0; + int sa_len, copy_len; + + __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; +} + int vcom_socket_getpeername (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __len) @@ -1405,7 +1462,8 @@ vcom_socket_getpeername (int __fd, __SOCKADDR_ARG __addr, vcom_socket_main_t *vsm = &vcom_socket_main; uword *p; vcom_socket_t *vsock; - + u8 src_addr[sizeof (struct sockaddr_in6)]; + vppcom_endpt_t ep; p = hash_get (vsm->sockidx_by_fd, __fd); if (!p) @@ -1421,31 +1479,10 @@ vcom_socket_getpeername (int __fd, __SOCKADDR_ARG __addr, if (!__addr || !__len) return -EFAULT; - vppcom_endpt_t ep; - ep.ip = (u8 *) & ((const struct sockaddr_in *) __addr)->sin_addr; + ep.ip = src_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; - } - } - } + rv = vcom_socket_copy_ep_to_sockaddr (__addr, __len, &ep); return rv; } @@ -1617,37 +1654,7 @@ vcom_session_recvfrom (int __sid, void *__restrict __buf, size_t __n, rv = vppcom_session_recvfrom (__sid, __buf, __n, __flags, &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; - memcpy (&((struct sockaddr_in *) __addr)->sin_addr, - src_addr, sizeof (struct in_addr)); - - *__addr_len = sizeof (struct sockaddr_in); - break; - - case AF_INET6: - ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port; - memcpy (((struct sockaddr_in6 *) __addr)->sin6_addr. - __in6_u.__u6_addr8, src_addr, - sizeof (struct in6_addr)); - *__addr_len = sizeof (struct sockaddr_in6); - break; - - default: - rv = -EAFNOSUPPORT; - break; - } - } - else - rv = -1; - } + rv = vcom_socket_copy_ep_to_sockaddr (__addr, __addr_len, &ep); } else rv = vppcom_session_recvfrom (__sid, __buf, __n, __flags, NULL); @@ -2275,9 +2282,17 @@ vcom_socket_accept_flags (int __fd, __SOCKADDR_ARG __addr, /* flags can be 0 or can be bitwise OR * of any of SOCK_NONBLOCK and SOCK_CLOEXEC */ + if (VCOM_DEBUG > 2) + fprintf (stderr, "[%d] vcom_socket_accept_flags: " + "fd = %d, __addr = %p, __addr_len = %p flags = %d (0x%x)\n", + getpid (), __fd, __addr, __addr_len, flags, flags); + if (!(!flags || (flags & (SOCK_NONBLOCK | SOCK_CLOEXEC)))) { /* TBD: return proper error code */ + fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: " + "invalid flags = %d (0x%x)\n", getpid (), flags, flags); + return -1; } @@ -2285,6 +2300,8 @@ vcom_socket_accept_flags (int __fd, __SOCKADDR_ARG __addr, if (!vcom_socket_is_connection_mode_socket (__fd)) { + fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: " + "connection mode socket support TBD!\n", getpid ()); return -EOPNOTSUPP; } @@ -2297,6 +2314,8 @@ vcom_socket_accept_flags (int __fd, __SOCKADDR_ARG __addr, rv = vcom_fcntl (vsock->fd, F_GETFL, 0); if (rv < 0) { + fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: " + "vcom_fcnt() returned %d!\n", getpid (), rv); return rv; } @@ -2331,6 +2350,9 @@ vcom_socket_accept_flags (int __fd, __SOCKADDR_ARG __addr, } if (rv < 0) { + if (rv != VPPCOM_EAGAIN) + fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: " + "vppcom_session_accept() returned %d!", getpid (), rv); return rv; } @@ -2344,6 +2366,9 @@ vcom_socket_accept_flags (int __fd, __SOCKADDR_ARG __addr, &domain, &type, &protocol, flags); if (fd < 0) { + fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: " + "vcom_socket_connected_socket() returned %d!", + getpid (), rv); return fd; } @@ -2423,18 +2448,6 @@ vcom_socket_accept_flags (int __fd, __SOCKADDR_ARG __addr, } } } - 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; @@ -2448,7 +2461,6 @@ vcom_socket_accept (int __fd, __SOCKADDR_ARG __addr, 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) @@ -2456,7 +2468,6 @@ vcom_socket_accept4 (int __fd, __SOCKADDR_ARG __addr, /* 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 @@ -2755,21 +2766,11 @@ vcom_socket_epoll_ctl_internal (int __epfd, int __op, int __fd, int free_vepitem_on_del) { int rv = -1; - - /* vcom_socket_main_t *vsm = &vcom_socket_main; */ + i32 cnt; 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 */ + i32 sid; /* get vep_idx and vepoll */ vep_idx = vcom_socket_get_vep_idx_and_vepoll (__epfd, &vepoll); @@ -2779,37 +2780,45 @@ vcom_socket_epoll_ctl_internal (int __epfd, int __op, int __fd, } /* 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) + sid = vcom_socket_get_sid_and_vsock (__fd, &vfd_vsock); + if ((sid != INVALID_SESSION_ID) && + vcom_socket_type_is_vppcom_bound (vfd_vsock->type)) { - type = FD_TYPE_EPOLL; - vfd = vfd_vepoll; + rv = vppcom_epoll_ctl (vep_idx, __op, sid, __event); + if (rv == VPPCOM_OK) + { + cnt = ((__op == EPOLL_CTL_ADD) ? 1 : + (__op == EPOLL_CTL_DEL) ? -1 : 0); + vepoll->count += cnt; + vepoll->vcl_cnt += cnt; + } + if (VCOM_DEBUG > 0) + fprintf (stderr, + "[%d] vcom_socket_epoll_ctl_i: vppcom_epoll_ctl() " + "returned %d\n\tepfd %d, vep_idx %d, fd %d sid %d op %d" + "\n\tcount %d, vcl_cnt %d, libc_cnt %d\n", + getpid (), rv, __epfd, vep_idx, __fd, sid, __op, + vepoll->count, vepoll->vcl_cnt, vepoll->libc_cnt); } 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 = libc_epoll_ctl (__epfd, __op, __fd, __event); + if (rv == 0) + { + cnt = ((__op == EPOLL_CTL_ADD) ? 1 : + (__op == EPOLL_CTL_DEL) ? -1 : 0); + vepoll->count += cnt; + vepoll->libc_cnt += cnt; + } + if (VCOM_DEBUG > 0) + fprintf (stderr, + "[%d] vcom_socket_epoll_ctl_i: libc_epoll_ctl() " + "returned %d\n\tepfd %d, vep_idx %d, fd %d sid %d op %d" + "\n\tcount %d, vcl_cnt %d, libc_cnt %d\n", + getpid (), rv, __epfd, vep_idx, __fd, sid, __op, + vepoll->count, vepoll->vcl_cnt, vepoll->libc_cnt); } - rv = vcom_socket_ctl_vepitem (__epfd, __op, __fd, - __event, - vep_idx, vepoll, - vfd_id, vfd, type, free_vepitem_on_del); return rv; } @@ -2838,46 +2847,113 @@ vcom_socket_epoll_pwait (int __epfd, struct epoll_event *__events, int __maxevents, int __timeout, const __sigset_t * __ss) { + vcom_socket_main_t *vsm = &vcom_socket_main; int rv = -EBADF; - - /* in seconds eg. 3.123456789 seconds */ + int rv2; double time_to_wait = (double) 0; - + double timeout, now = 0; + vcom_epoll_t *vepoll; i32 vep_idx; + static struct epoll_event *libc_ev = 0; /* validate __event */ - if (!__events) + if (!__events || (__timeout < -1)) { + fprintf (stderr, "[%d] ERROR: vcom_socket_epoll_pwait: " + "Bad args __events %p, __timeout %d\n", getpid (), + __events, __timeout); rv = -EFAULT; goto out; } - /* validate __timeout */ - if (__timeout > 0) + time_to_wait = ((__timeout >= 0) ? (double) __timeout / (double) 1000 : 0); + + vep_idx = vcom_socket_get_vep_idx_and_vepoll (__epfd, &vepoll); + if (vep_idx == INVALID_VEP_IDX) { - time_to_wait = (double) __timeout / (double) 1000; + fprintf (stderr, "[%d] ERROR: vcom_socket_epoll_pwait: " + "Bad epoll fd %d\n", getpid (), __epfd); + return -EBADF; } - else if (__timeout == 0) + + if (vepoll->count <= 0) { - time_to_wait = (double) 0; + fprintf (stderr, "[%d] ERROR: vcom_socket_epoll_pwait: No events" + " in epfd!\n\tcount %d, vcl_cnt %d, libc_cnt %d\n", + getpid (), vepoll->count, vepoll->vcl_cnt, vepoll->libc_cnt); + rv = -EINVAL; + goto out; } - else if (__timeout == -1) + + if (vepoll->libc_cnt == 0) { - time_to_wait = ~0; + if (VCOM_DEBUG > 2) + fprintf (stderr, "[%d] vcom_socket_epoll_pwait: libc_cnt = 0, " + "calling vppcom_epoll_wait() time_to_wait = %f\n", + getpid (), time_to_wait); + rv = vppcom_epoll_wait (vep_idx, __events, __maxevents, time_to_wait); } - else + else if (vepoll->vcl_cnt == 0) { - rv = -EBADF; - goto out; + if (VCOM_DEBUG > 2) + fprintf (stderr, "[%d] vcom_socket_epoll_pwait: vcl_cnt = 0, " + "calling libc_epoll_pwait()\n", getpid ()); + rv = libc_epoll_pwait (__epfd, __events, __maxevents, __timeout, __ss); } - - /* get vep_idx */ - vep_idx = vcom_socket_get_vep_idx (__epfd); - if (vep_idx != INVALID_VEP_IDX) + else { - rv = vppcom_epoll_wait (vep_idx, __events, __maxevents, time_to_wait); + if (VCOM_DEBUG > 2) + fprintf (stderr, "[%d] vcom_socket_epoll_pwait: vcl_cnt = %d, " + "libc_cnt = %d -> mixed polling (time_to_wait = %f, " + "__timeout = %d)\n", + getpid (), vepoll->vcl_cnt, vepoll->libc_cnt, + time_to_wait, __timeout); + vec_validate (libc_ev, __maxevents); + timeout = clib_time_now (&vsm->clib_time) + time_to_wait; + do + { + rv = vppcom_epoll_wait (vep_idx, __events, __maxevents, 0); + rv2 = libc_epoll_pwait (__epfd, libc_ev, __maxevents, 1, __ss); + if (VCOM_DEBUG == 666) + fprintf (stderr, "[%d] vcom_socket_epoll_pwait: " + "rv = %d, rv2 = %d, timeout = %f, now = %f\n", + getpid (), rv, rv2, timeout, now); + if ((rv > 0) || (rv2 > 0)) + { + if (VCOM_DEBUG > 2) + fprintf (stderr, "[%d] vcom_socket_epoll_pwait: " + "rv = %d, rv2 = %d\n", getpid (), rv, rv2); + int n = __maxevents - rv; + n = rv2 <= n ? rv2 : n; + rv = (rv > 0) ? rv : 0; + + clib_memcpy (&__events[rv], libc_ev, n * sizeof (*libc_ev)); + rv += rv2; + goto out; + } + else if ((rv < 0) || (rv2 < 0)) + { + if (rv < 0) + fprintf (stderr, + "[%d] ERROR: vppcom_epoll_wait() returned %d\n", + getpid (), rv); + if (rv2 < 0) + { + fprintf (stderr, + "[%d] ERROR: libc_epoll_wait() failed, errno %d\n", + getpid (), errno); + rv = (rv < 0) ? rv : -errno; + } + goto out; + } + if (__timeout != -1) + now = clib_time_now (&vsm->clib_time); + } + while (now < timeout); } + out: + vec_reset_length (libc_ev); return rv; } @@ -3067,7 +3143,6 @@ 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; @@ -3156,7 +3231,7 @@ vcom_socket_poll_select_impl (struct pollfd *__fds, nfds_t __nfds, if (VCOM_DEBUG > 2) fprintf (stderr, "[%d] vcom_socket_select: " - "'%04d'='%04d'\n", pid, vcom_nfd, vcom_nfds); + "'%04d'='%04d'\n", getpid (), vcom_nfd, vcom_nfds); if (vcom_nfd < 0) { @@ -3289,6 +3364,8 @@ vcom_socket_main_init (void) vsm->epitemidxs_by_epfd = hash_create (0, sizeof (i32 *)); vsm->epitemidxs_by_fd = hash_create (0, sizeof (i32 *)); + clib_time_init (&vsm->clib_time); + vsm->init = 1; }