* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+#ifdef HAVE_GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <stdarg.h>
#include <sys/resource.h>
#include <netinet/tcp.h>
+#include <linux/udp.h>
#include <vcl/ldp_socket_wrapper.h>
#include <vcl/ldp.h>
#define LDP_MAX_NWORKERS 32
+#ifdef HAVE_GNU_SOURCE
+#define SOCKADDR_GET_SA(__addr) __addr.__sockaddr__;
+#else
+#define SOCKADDR_GET_SA(__addr) _addr;
+#endif
+
typedef struct ldp_worker_ctx_
{
u8 *io_buffer;
/* Make sure there are enough bits in the fd set for vcl sessions */
if (ldp->vlsh_bit_val > FD_SETSIZE / 2)
{
- LDBG (0, "ERROR: LDP vlsh bit value %d > FD_SETSIZE/2 %d!",
+ /* Only valid for select/pselect, so just WARNING and not exit */
+ LDBG (0,
+ "WARNING: LDP vlsh bit value %d > FD_SETSIZE/2 %d, "
+ "select/pselect not supported now!",
ldp->vlsh_bit_val, FD_SETSIZE / 2);
- ldp->init = 0;
- return -1;
}
}
env_var_str = getenv (LDP_ENV_TLS_TRANS);
time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ?
(f64) 0 : (f64) timeout->tv_sec + (f64) timeout->tv_nsec / (f64) 1e9;
+ time_out += clib_time_now (&ldpw->clib_time);
+
/* select as fine grained sleep */
if (!nfds)
{
- time_out += clib_time_now (&ldpw->clib_time);
while (clib_time_now (&ldpw->clib_time) < time_out)
;
return 0;
return -1;
ckp_len = sizeof (ldp->ckpair_index);
- return vppcom_session_attr (vlsh_to_session_index (vlsh),
- VPPCOM_ATTR_SET_CKPAIR, &ldp->ckpair_index,
- &ckp_len);
+ return vls_attr (vlsh, VPPCOM_ATTR_SET_CKPAIR, &ldp->ckpair_index, &ckp_len);
}
int
}
int
-bind (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
+bind (int fd, __CONST_SOCKADDR_ARG _addr, socklen_t len)
{
+ const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
vls_handle_t vlsh;
int rv;
}
static inline int
-ldp_copy_ep_to_sockaddr (__SOCKADDR_ARG addr, socklen_t * __restrict len,
- vppcom_endpt_t * ep)
+ldp_copy_ep_to_sockaddr (struct sockaddr *addr, socklen_t *__restrict len,
+ vppcom_endpt_t *ep)
{
- int rv = 0;
- int sa_len, copy_len;
+ int rv = 0, sa_len, copy_len;
ldp_init_check ();
}
int
-getsockname (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
+getsockname (int fd, __SOCKADDR_ARG _addr, socklen_t *__restrict len)
{
+ struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
vls_handle_t vlsh;
int rv;
}
else
{
- rv = libc_getsockname (fd, addr, len);
+ rv = libc_getsockname (fd, _addr, len);
}
return rv;
}
int
-connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
+connect (int fd, __CONST_SOCKADDR_ARG _addr, socklen_t len)
{
+ const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
vls_handle_t vlsh;
int rv;
}
int
-getpeername (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
+getpeername (int fd, __SOCKADDR_ARG _addr, socklen_t *__restrict len)
{
+ struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
vls_handle_t vlsh;
int rv;
return size;
}
-static int
-ldp_vls_sendo (vls_handle_t vlsh, const void *buf, size_t n, int flags,
- __CONST_SOCKADDR_ARG addr, socklen_t addr_len)
+ssize_t
+__recv_chk (int fd, void *buf, size_t n, size_t buflen, int flags)
{
+ if (n > buflen)
+ return -1;
+
+ return recv (fd, buf, n, flags);
+}
+
+static inline int
+ldp_vls_sendo (vls_handle_t vlsh, const void *buf, size_t n,
+ vppcom_endpt_tlv_t *ep_tlv, int flags,
+ __CONST_SOCKADDR_ARG _addr, socklen_t addr_len)
+{
+ const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
vppcom_endpt_t *ep = 0;
vppcom_endpt_t _ep;
+ if (ep_tlv)
+ {
+ _ep.app_data = *ep_tlv;
+ }
+
if (addr)
{
ep = &_ep;
}
static int
-ldp_vls_recvfrom (vls_handle_t vlsh, void *__restrict buf, size_t n,
- int flags, __SOCKADDR_ARG addr,
- socklen_t * __restrict addr_len)
+ldp_vls_recvfrom (vls_handle_t vlsh, void *__restrict buf, size_t n, int flags,
+ __SOCKADDR_ARG _addr, socklen_t *__restrict addr_len)
{
u8 src_addr[sizeof (struct sockaddr_in6)];
+ struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
vppcom_endpt_t ep;
ssize_t size;
int rv;
ssize_t
sendto (int fd, const void *buf, size_t n, int flags,
- __CONST_SOCKADDR_ARG addr, socklen_t addr_len)
+ __CONST_SOCKADDR_ARG _addr, socklen_t addr_len)
{
+ const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
vls_handle_t vlsh;
ssize_t size;
ldp_init_check ();
vlsh = ldp_fd_to_vlsh (fd);
- if (vlsh != INVALID_SESSION_ID)
+ if (vlsh != VLS_INVALID_HANDLE)
{
- size = ldp_vls_sendo (vlsh, buf, n, flags, addr, addr_len);
+ size = ldp_vls_sendo (vlsh, buf, n, NULL, flags, addr, addr_len);
if (size < 0)
{
errno = -size;
{
struct iovec *iov = msg->msg_iov;
ssize_t total = 0;
- int i, rv;
+ int i, rv = 0;
+ struct cmsghdr *cmsg;
+ uint16_t *valp;
+ vppcom_endpt_tlv_t _app_data;
+ vppcom_endpt_tlv_t *p_app_data = NULL;
+
+ cmsg = CMSG_FIRSTHDR (msg);
+ if (cmsg && cmsg->cmsg_type == UDP_SEGMENT)
+ {
+ p_app_data = &_app_data;
+ valp = (void *) CMSG_DATA (cmsg);
+ p_app_data->data_type = VCL_UDP_SEGMENT;
+ p_app_data->data_len = sizeof (*valp);
+ p_app_data->value = *valp;
+ }
for (i = 0; i < msg->msg_iovlen; ++i)
{
- rv = ldp_vls_sendo (vlsh, iov[i].iov_base, iov[i].iov_len, flags,
- msg->msg_name, msg->msg_namelen);
+ rv =
+ ldp_vls_sendo (vlsh, iov[i].iov_base, iov[i].iov_len, p_app_data,
+ flags, msg->msg_name, msg->msg_namelen);
if (rv < 0)
break;
else
return size;
}
-#ifdef USE_GNU
+#ifdef _GNU_SOURCE
int
sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
{
ldp_init_check ();
- if (sh != INVALID_SESSION_ID)
+ if (sh != VLS_INVALID_HANDLE)
{
clib_warning ("LDP<%d>: LDP-TBD", getpid ());
errno = ENOSYS;
return size;
}
-#ifdef USE_GNU
+#ifdef _GNU_SOURCE
int
recvmmsg (int fd, struct mmsghdr *vmessages,
unsigned int vlen, int flags, struct timespec *tmo)
{
- ssize_t size;
- const char *func_str;
- u32 sh = ldp_fd_to_vlsh (fd);
+ ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
+ u32 sh;
ldp_init_check ();
- if (sh != INVALID_SESSION_ID)
- {
- clib_warning ("LDP<%d>: LDP-TBD", getpid ());
- errno = ENOSYS;
- size = -1;
- }
- else
- {
- func_str = "libc_recvmmsg";
+ sh = ldp_fd_to_vlsh (fd);
- if (LDP_DEBUG > 2)
- clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
- "vmessages %p, vlen %u, flags 0x%x, tmo %p",
- getpid (), fd, fd, func_str, vmessages, vlen,
- flags, tmo);
-
- size = libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
- }
-
- if (LDP_DEBUG > 2)
+ if (sh != VLS_INVALID_HANDLE)
{
- if (size < 0)
+ struct mmsghdr *mh;
+ ssize_t rv = 0;
+ u32 nvecs = 0;
+ f64 time_out;
+
+ if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
+ clib_time_init (&ldpw->clib_time);
+ if (tmo)
{
- int errno_val = errno;
- perror (func_str);
- clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
- "rv %d, errno = %d", getpid (), fd, fd,
- func_str, size, errno_val);
- errno = errno_val;
+ time_out = (f64) tmo->tv_sec + (f64) tmo->tv_nsec / (f64) 1e9;
+ time_out += clib_time_now (&ldpw->clib_time);
}
else
- clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
- getpid (), fd, fd, size, size);
+ {
+ time_out = (f64) ~0;
+ }
+
+ while (nvecs < vlen)
+ {
+ mh = &vmessages[nvecs];
+ rv = recvmsg (fd, &mh->msg_hdr, flags);
+ if (rv > 0)
+ {
+ mh->msg_len = rv;
+ nvecs += 1;
+ continue;
+ }
+
+ if (!time_out || clib_time_now (&ldpw->clib_time) >= time_out)
+ break;
+
+ usleep (1);
+ }
+
+ return nvecs > 0 ? nvecs : rv;
+ }
+ else
+ {
+ return libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
}
- return size;
}
#endif
}
static inline int
-ldp_accept4 (int listen_fd, __SOCKADDR_ARG addr,
- socklen_t * __restrict addr_len, int flags)
+ldp_accept4 (int listen_fd, __SOCKADDR_ARG _addr,
+ socklen_t *__restrict addr_len, int flags)
{
+ struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
vls_handle_t listen_vlsh, accept_vlsh;
int rv;
return rv;
}
-#ifdef USE_GNU
+#ifdef _GNU_SOURCE
int
ppoll (struct pollfd *fds, nfds_t nfds,
const struct timespec *timeout, const sigset_t * sigmask)