Commit 5cf2228d authored by Daniel Salzman's avatar Daniel Salzman

udp-handler: simplify recvmmsg/sendmmsg detection

parent 11241916
......@@ -123,27 +123,21 @@ PKG_CHECK_MODULES([gnutls], [gnutls >= 3.3 nettle], [
# JSON for DNSSEC status storage
PKG_CHECK_MODULES([jansson], [jansson >= 2.3])
# recvmmsg() (valgrind doesn't support it, so disable for debugging)
# The check for struct mmsghdr is required when libc doesn't have an API but the function links
AC_ARG_ENABLE([recvmmsg],
AS_HELP_STRING([--enable-recvmmsg=yes|no], [enable recvmmsg() network API under Linux (kernel support required) (set to 'no' if you have trouble running server under valgrind) [default=yes]]),
[case "${enableval}" in
yes)
AC_CHECK_FUNCS([sendmmsg])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/socket.h>]], [[struct mmsghdr v; recvmmsg(0,0,0,0,0);]])],
[AC_DEFINE(HAVE_RECVMMSG, 1, [Define if struct mmsghdr and recvmmsg() exists.])])
;;
no)
;;
*)
AC_MSG_ERROR([bad value ${enableval} for --enable-recvmmsg])
;;
esac],
[
AC_CHECK_FUNCS([sendmmsg])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/socket.h>]], [[struct mmsghdr v; recvmmsg(0,0,0,0,0);]])],
[AC_DEFINE(HAVE_RECVMMSG, 1, [Define if struct mmsghdr and recvmmsg() exists.])])
])
AS_HELP_STRING([--enable-recvmmsg=auto|yes|no], [enable recvmmsg() network API [default=auto]]),
[], [enable_recvmmsg=auto])
AS_CASE([$enable_recvmmsg],
[auto|yes],[
AC_CHECK_FUNC([recvmmsg],
[AC_CHECK_FUNC([sendmmsg],[enable_recvmmsg=yes],[enable_recvmmsg=no])],
[enable_recvmmsg=no])],
[no],[],
[*], [AC_MSG_ERROR([Invalid value of --enable-recvmmsg.]
)])
AS_IF([test "$enable_recvmmsg" = yes],[
AC_DEFINE([ENABLE_RECVMMSG], [1], [Use recvmmsg().])])
AC_ARG_ENABLE([reuseport],
AS_HELP_STRING([--enable-reuseport=auto|yes|no], [enable Linux SO_REUSEPORT support [default=auto]]),
......@@ -572,6 +566,7 @@ AC_MSG_RESULT([
Knot DNS utils: ${enable_utilities}
Knot DNS documentation: ${enable_documentation}
Use recvmmsg: ${enable_recvmmsg}
Use SO_REUSEPORT: ${enable_reuseport}
Fast zone parser: ${enable_fastparser}
Utilities with IDN: ${with_libidn}
......
......@@ -21,7 +21,6 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/syscall.h>
#include <string.h>
#include <assert.h>
#include <sys/param.h>
......@@ -105,15 +104,6 @@ static void udp_handle(udp_context_t *udp, int fd, struct sockaddr_storage *ss,
knot_pkt_free(&ans);
}
/* Check for sendmmsg syscall. */
#ifdef HAVE_SENDMMSG
#define ENABLE_SENDMMSG 1
#else
#ifdef SYS_sendmmsg
#define ENABLE_SENDMMSG 1
#endif
#endif
/*! \brief Pointer to selected UDP master implementation. */
static void* (*_udp_init)(void) = 0;
static int (*_udp_deinit)(void *) = 0;
......@@ -239,49 +229,7 @@ static int udp_recvfrom_send(void *d)
return 0;
}
#ifdef HAVE_RECVMMSG
/*! \brief Pointer to selected UDP send implementation. */
static int (*_send_mmsg)(int, struct sockaddr *, struct mmsghdr *, size_t) = 0;
/*!
* \brief Send multiple packets.
*
* Basic, sendmsg() based implementation.
*/
static int udp_sendmsg(int sock, struct sockaddr *addrs, struct mmsghdr *msgs, size_t count)
{
int sent = 0;
for (unsigned i = 0; i < count; ++i) {
if (sendmsg(sock, &msgs[i].msg_hdr, 0) > 0) {
++sent;
}
}
return sent;
}
#ifdef ENABLE_SENDMMSG
/*! \brief sendmmsg() syscall interface. */
#ifndef HAVE_SENDMMSG
static inline int sendmmsg(int fd, struct mmsghdr *mmsg, unsigned vlen,
unsigned flags)
{
return syscall(SYS_sendmmsg, fd, mmsg, vlen, flags, NULL);
}
#endif /* HAVE_SENDMMSG */
/*!
* \brief Send multiple packets.
*
* sendmmsg() implementation.
*/
static int udp_sendmmsg(int sock, struct sockaddr *_, struct mmsghdr *msgs, size_t count)
{
UNUSED(_);
return sendmmsg(sock, msgs, count, 0);
}
#endif /* ENABLE_SENDMMSG */
#ifdef ENABLE_RECVMMSG
/* UDP recvmmsg() request struct. */
struct udp_recvmmsg {
......@@ -374,7 +322,7 @@ static int udp_recvmmsg_handle(udp_context_t *ctx, void *d)
static int udp_recvmmsg_send(void *d)
{
struct udp_recvmmsg *rq = (struct udp_recvmmsg *)d;
int rc = _send_mmsg(rq->fd, (struct sockaddr *)rq->addrs, rq->msgs[TX], rq->rcvd);
int rc = sendmmsg(rq->fd, rq->msgs[TX], rq->rcvd, 0);
for (unsigned i = 0; i < rq->rcvd; ++i) {
/* Reset buffer size and address len. */
struct iovec *rx = rq->msgs[RX][i].msg_hdr.msg_iov;
......@@ -389,38 +337,25 @@ static int udp_recvmmsg_send(void *d)
}
return rc;
}
#endif /* HAVE_RECVMMSG */
#endif /* ENABLE_RECVMMSG */
/*! \brief Initialize UDP master routine on run-time. */
void __attribute__ ((constructor)) udp_master_init(void)
{
/* Initialize defaults. */
_udp_init = udp_recvfrom_init;
_udp_init = udp_recvfrom_init;
_udp_deinit = udp_recvfrom_deinit;
_udp_recv = udp_recvfrom_recv;
_udp_send = udp_recvfrom_send;
_udp_recv = udp_recvfrom_recv;
_udp_handle = udp_recvfrom_handle;
/* Optimized functions. */
#ifdef HAVE_RECVMMSG
recvmmsg(0, NULL, 0, 0, 0);
if (errno != ENOSYS) {
_udp_init = udp_recvmmsg_init;
_udp_deinit = udp_recvmmsg_deinit;
_udp_recv = udp_recvmmsg_recv;
_udp_send = udp_recvmmsg_send;
_udp_handle = udp_recvmmsg_handle;
}
/* Check for sendmmsg() support. */
_send_mmsg = udp_sendmsg;
#ifdef ENABLE_SENDMMSG
sendmmsg(0, 0, 0, 0); /* Just check if syscall exists */
if (errno != ENOSYS) {
_send_mmsg = udp_sendmmsg;
}
#endif /* ENABLE_SENDMMSG */
#endif /* HAVE_RECVMMSG */
_udp_send = udp_recvfrom_send;
#ifdef ENABLE_RECVMMSG
_udp_init = udp_recvmmsg_init;
_udp_deinit = udp_recvmmsg_deinit;
_udp_recv = udp_recvmmsg_recv;
_udp_handle = udp_recvmmsg_handle;
_udp_send = udp_recvmmsg_send;
#endif /* ENABLE_RECVMMSG */
}
/*! \brief Get interface UDP descriptor for a given thread. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment