mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-04 08:35:31 +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:
@@ -1599,20 +1599,10 @@ isc__nm_free_uvbuf(isc_nmsocket_t *sock, const uv_buf_t *buf) {
|
||||
isc__networker_t *worker = NULL;
|
||||
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
if (buf->base == NULL) {
|
||||
/* Empty buffer: might happen in case of error. */
|
||||
return;
|
||||
}
|
||||
worker = &sock->mgr->workers[sock->tid];
|
||||
|
||||
REQUIRE(worker->recvbuf_inuse);
|
||||
if (sock->type == isc_nm_udpsocket && buf->base > worker->recvbuf &&
|
||||
buf->base <= worker->recvbuf + ISC_NETMGR_RECVBUF_SIZE)
|
||||
{
|
||||
/* Can happen in case of out-of-order recvmmsg in libuv1.36 */
|
||||
return;
|
||||
}
|
||||
worker = &sock->mgr->workers[sock->tid];
|
||||
REQUIRE(buf->base == worker->recvbuf);
|
||||
|
||||
worker->recvbuf_inuse = false;
|
||||
}
|
||||
|
||||
@@ -2187,7 +2177,7 @@ isc__nm_get_read_req(isc_nmsocket_t *sock, isc_sockaddr_t *sockaddr) {
|
||||
}
|
||||
|
||||
/*%<
|
||||
* Allocator for read operations. Limited to size 2^16.
|
||||
* Allocator callback for read operations.
|
||||
*
|
||||
* Note this doesn't actually allocate anything, it just assigns the
|
||||
* worker's receive buffer to a socket, and marks it as "in use".
|
||||
@@ -2199,35 +2189,34 @@ isc__nm_alloc_cb(uv_handle_t *handle, size_t size, uv_buf_t *buf) {
|
||||
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
REQUIRE(isc__nm_in_netthread());
|
||||
/*
|
||||
* The size provided by libuv is only suggested size, and it always
|
||||
* defaults to 64 * 1024 in the current versions of libuv (see
|
||||
* src/unix/udp.c and src/unix/stream.c).
|
||||
*/
|
||||
UNUSED(size);
|
||||
|
||||
worker = &sock->mgr->workers[sock->tid];
|
||||
INSIST(!worker->recvbuf_inuse);
|
||||
INSIST(worker->recvbuf != NULL);
|
||||
|
||||
switch (sock->type) {
|
||||
case isc_nm_udpsocket:
|
||||
REQUIRE(size <= ISC_NETMGR_RECVBUF_SIZE);
|
||||
size = ISC_NETMGR_RECVBUF_SIZE;
|
||||
buf->len = ISC_NETMGR_UDP_RECVBUF_SIZE;
|
||||
break;
|
||||
case isc_nm_tcpsocket:
|
||||
case isc_nm_tcpdnssocket:
|
||||
break;
|
||||
case isc_nm_tlsdnssocket:
|
||||
/*
|
||||
* We need to limit the individual chunks to be read, so the
|
||||
* BIO_write() will always succeed and the consumed before the
|
||||
* next readcb is called.
|
||||
*/
|
||||
if (size >= ISC_NETMGR_TLSBUF_SIZE) {
|
||||
size = ISC_NETMGR_TLSBUF_SIZE;
|
||||
}
|
||||
buf->len = ISC_NETMGR_TCP_RECVBUF_SIZE;
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
}
|
||||
|
||||
worker = &sock->mgr->workers[sock->tid];
|
||||
INSIST(!worker->recvbuf_inuse || sock->type == isc_nm_udpsocket);
|
||||
|
||||
REQUIRE(buf->len <= ISC_NETMGR_RECVBUF_SIZE);
|
||||
buf->base = worker->recvbuf;
|
||||
buf->len = size;
|
||||
|
||||
worker->recvbuf_inuse = true;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user