2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-04 16:45:24 +00:00

Fix the UDP recvmmsg support

Previously, the netmgr/udp.c tried to detect the recvmmsg detection in
libuv with #ifdef UV_UDP_<foo> preprocessor macros.  However, because
the UV_UDP_<foo> are not preprocessor macros, but enum members, the
detection didn't work.  Because the detection didn't work, the code
didn't have access to the information when we received the final chunk
of the recvmmsg and tried to free the uvbuf every time.  Fortunately,
the isc__nm_free_uvbuf() had a kludge that detected attempt to free in
the middle of the receive buffer, so the code worked.

However, libuv 1.37.0 changed the way the recvmmsg was enabled from
implicit to explicit, and we checked for yet another enum member
presence with preprocessor macro, so in fact libuv recvmmsg support was
never enabled with libuv >= 1.37.0.

This commit changes to the preprocessor macros to autoconf checks for
declaration, so the detection now works again.  On top of that, it's now
possible to cleanup the alloc_cb and free_uvbuf functions because now,
the information whether we can or cannot free the buffer is available to
us.
This commit is contained in:
Ondřej Surý
2022-01-11 12:14:23 +01:00
parent abe466e5b3
commit 7370725008
7 changed files with 137 additions and 61 deletions

View File

@@ -46,19 +46,51 @@
/* Must be different from ISC_NETMGR_TID_UNKNOWN */
#define ISC_NETMGR_NON_INTERLOCKED -2
#define ISC_NETMGR_TLSBUF_SIZE 65536
/*
* Receive buffers
*/
#if HAVE_DECL_UV_UDP_MMSG_CHUNK
/*
* The value 20 here is UV__MMSG_MAXWIDTH taken from the current libuv source,
* libuv will not receive more that 20 datagrams in a single recvmmsg call.
*/
#define ISC_NETMGR_UDP_RECVBUF_SIZE (20 * UINT16_MAX)
#else
/*
* A single DNS message size
*/
#define ISC_NETMGR_UDP_RECVBUF_SIZE UINT16_MAX
#endif
/*
* New versions of libuv support recvmmsg on unices.
* Since recvbuf is only allocated per worker allocating a bigger one is not
* that wasteful.
* 20 here is UV__MMSG_MAXWIDTH taken from the current libuv source, nothing
* will break if the original value changes.
* The TCP receive buffer can fit one maximum sized DNS message plus its size,
* the receive buffer here affects TCP, DoT and DoH.
*/
#define ISC_NETMGR_RECVBUF_SIZE (20 * 65536)
#define ISC_NETMGR_TCP_RECVBUF_SIZE (sizeof(uint16_t) + UINT16_MAX)
/* Pick the larger buffer */
#define ISC_NETMGR_RECVBUF_SIZE \
(ISC_NETMGR_UDP_RECVBUF_SIZE >= ISC_NETMGR_TCP_RECVBUF_SIZE \
? ISC_NETMGR_UDP_RECVBUF_SIZE \
: ISC_NETMGR_TCP_RECVBUF_SIZE)
/*
* Send buffer
*/
#define ISC_NETMGR_SENDBUF_SIZE (sizeof(uint16_t) + UINT16_MAX)
/*
* Make sure our RECVBUF size is large enough
*/
STATIC_ASSERT(ISC_NETMGR_UDP_RECVBUF_SIZE <= ISC_NETMGR_RECVBUF_SIZE,
"UDP receive buffer size must be smaller or equal than worker "
"receive buffer size");
STATIC_ASSERT(ISC_NETMGR_TCP_RECVBUF_SIZE <= ISC_NETMGR_RECVBUF_SIZE,
"TCP receive buffer size must be smaller or equal than worker "
"receive buffer size");
/*%
* Regular TCP buffer size.
*/
@@ -70,7 +102,7 @@
* most in TCPDNS or TLSDNS connections, so there's no risk of overrun
* when using a buffer this size.
*/
#define NM_BIG_BUF (65535 + 2) * 2
#define NM_BIG_BUF ISC_NETMGR_TCP_RECVBUF_SIZE * 2
#if defined(SO_REUSEPORT_LB) || (defined(SO_REUSEPORT) && defined(__linux__))
#define HAVE_SO_REUSEPORT_LB 1