mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 05:57:52 +00:00
Merge branch '2137-so_reuseport-doesn-t-distribute-udp-queries-to-multiple-netmgr-workers-on-macos' into 'main'
Distribute queries among threads even on platforms without SO_REUSEPORT_LB Closes #2137 See merge request isc-projects/bind9!4459
This commit is contained in:
commit
48a52234ee
4
CHANGES
4
CHANGES
@ -1,3 +1,7 @@
|
|||||||
|
5545. [func] Restore reading of incoming queries by multiple netmgr
|
||||||
|
threads on platforms other than Linux and FreeBSD 12.
|
||||||
|
[GL #2137]
|
||||||
|
|
||||||
5544. [func] Restore the default value of nocookie-udp-size to 4096.
|
5544. [func] Restore the default value of nocookie-udp-size to 4096.
|
||||||
[GL #2250]
|
[GL #2250]
|
||||||
|
|
||||||
|
@ -19,11 +19,7 @@ Security Fixes
|
|||||||
Known Issues
|
Known Issues
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
- The ``named`` daemon uses load-balanced sockets to increase performance by
|
- None.
|
||||||
distributing the incoming queries among multiple threads. Currently, the only
|
|
||||||
operating systems that support load-balanced sockets are Linux and FreeBSD 12,
|
|
||||||
thus both UDP and TCP performance is limited to a single-thread on systems
|
|
||||||
without load-balancing socket support. [GL #2137]
|
|
||||||
|
|
||||||
New Features
|
New Features
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
@ -70,3 +66,10 @@ Bug Fixes
|
|||||||
|
|
||||||
- Building with native PKCS#11 support for AEP Keyper has been broken
|
- Building with native PKCS#11 support for AEP Keyper has been broken
|
||||||
since BIND 9.17.4. This has been fixed. [GL #2315]
|
since BIND 9.17.4. This has been fixed. [GL #2315]
|
||||||
|
|
||||||
|
- The ``named`` daemon uses load-balanced sockets to increase performance by
|
||||||
|
distributing the incoming queries among multiple threads. Currently, the only
|
||||||
|
operating systems that support load-balanced sockets are Linux and FreeBSD 12,
|
||||||
|
thus both UDP and TCP performance was limited to a single-thread on systems
|
||||||
|
without load-balancing socket support. This has been fixed on all platforms
|
||||||
|
except Windows. [GL #2137]
|
||||||
|
@ -52,6 +52,10 @@
|
|||||||
#define ISC_NETMGR_RECVBUF_SIZE (65536)
|
#define ISC_NETMGR_RECVBUF_SIZE (65536)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(SO_REUSEPORT_LB) || (defined(SO_REUSEPORT) && defined(__linux__))
|
||||||
|
#define HAVE_REUSEPORT_LB 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define NETMGR_TRACE to activate tracing of handles and sockets.
|
* Define NETMGR_TRACE to activate tracing of handles and sockets.
|
||||||
* This will impair performance but enables us to quickly determine,
|
* This will impair performance but enables us to quickly determine,
|
||||||
|
@ -169,22 +169,6 @@ isc__nm_in_netthread(void) {
|
|||||||
return (isc__nm_tid_v >= 0);
|
return (isc__nm_tid_v >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
|
||||||
isc__nm_test_lb_socket(sa_family_t sa_family, int protocol) {
|
|
||||||
isc_result_t result;
|
|
||||||
uv_os_sock_t fd = -1;
|
|
||||||
|
|
||||||
result = isc__nm_socket(sa_family, protocol, 0, &fd);
|
|
||||||
REQUIRE(result == ISC_R_SUCCESS);
|
|
||||||
|
|
||||||
result = isc__nm_socket_reuse_lb(fd);
|
|
||||||
REQUIRE(result == ISC_R_SUCCESS || result == ISC_R_NOTIMPLEMENTED);
|
|
||||||
|
|
||||||
isc__nm_closesocket(fd);
|
|
||||||
|
|
||||||
return (result == ISC_R_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
static void
|
static void
|
||||||
isc__nm_winsock_initialize(void) {
|
isc__nm_winsock_initialize(void) {
|
||||||
@ -231,14 +215,6 @@ isc_nm_start(isc_mem_t *mctx, uint32_t workers) {
|
|||||||
|
|
||||||
isc__nm_tls_initialize();
|
isc__nm_tls_initialize();
|
||||||
|
|
||||||
if (!isc__nm_test_lb_socket(AF_INET, SOCK_DGRAM) ||
|
|
||||||
!isc__nm_test_lb_socket(AF_INET, SOCK_STREAM) ||
|
|
||||||
!isc__nm_test_lb_socket(AF_INET6, SOCK_DGRAM) ||
|
|
||||||
!isc__nm_test_lb_socket(AF_INET6, SOCK_STREAM))
|
|
||||||
{
|
|
||||||
workers = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
mgr = isc_mem_get(mctx, sizeof(*mgr));
|
mgr = isc_mem_get(mctx, sizeof(*mgr));
|
||||||
*mgr = (isc_nm_t){ .nworkers = workers };
|
*mgr = (isc_nm_t){ .nworkers = workers };
|
||||||
|
|
||||||
@ -2307,6 +2283,10 @@ isc__nm_socket_dontfrag(uv_os_sock_t fd, sa_family_t sa_family) {
|
|||||||
#define TIMEOUT_TYPE unsigned int
|
#define TIMEOUT_TYPE unsigned int
|
||||||
#define TIMEOUT_DIV 1
|
#define TIMEOUT_DIV 1
|
||||||
#define TIMEOUT_OPTNAME TCP_USER_TIMEOUT
|
#define TIMEOUT_OPTNAME TCP_USER_TIMEOUT
|
||||||
|
#elif defined(TCP_KEEPINIT)
|
||||||
|
#define TIMEOUT_TYPE int
|
||||||
|
#define TIMEOUT_DIV 1000
|
||||||
|
#define TIMEOUT_OPTNAME TCP_KEEPINIT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
|
@ -378,27 +378,27 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
|
|||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static isc_result_t
|
static uv_os_sock_t
|
||||||
isc__nm_tcp_lb_socket(sa_family_t sa_family, uv_os_sock_t *sockp) {
|
isc__nm_tcp_lb_socket(sa_family_t sa_family) {
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
uv_os_sock_t sock;
|
uv_os_sock_t sock;
|
||||||
|
|
||||||
result = isc__nm_socket(sa_family, SOCK_STREAM, 0, &sock);
|
result = isc__nm_socket(sa_family, SOCK_STREAM, 0, &sock);
|
||||||
REQUIRE(result == ISC_R_SUCCESS);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
|
||||||
(void)isc__nm_socket_incoming_cpu(sock);
|
(void)isc__nm_socket_incoming_cpu(sock);
|
||||||
|
|
||||||
/* FIXME: set mss */
|
/* FIXME: set mss */
|
||||||
|
|
||||||
result = isc__nm_socket_reuse(sock);
|
result = isc__nm_socket_reuse(sock);
|
||||||
REQUIRE(result == ISC_R_SUCCESS || result == ISC_R_NOTIMPLEMENTED);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
|
||||||
|
#if HAVE_SO_REUSEPORT_LB
|
||||||
result = isc__nm_socket_reuse_lb(sock);
|
result = isc__nm_socket_reuse_lb(sock);
|
||||||
REQUIRE(result == ISC_R_SUCCESS || result == ISC_R_NOTIMPLEMENTED);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
#endif
|
||||||
|
|
||||||
*sockp = sock;
|
return (sock);
|
||||||
|
|
||||||
return (result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
@ -410,6 +410,7 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface,
|
|||||||
isc_nmsocket_t *sock = NULL;
|
isc_nmsocket_t *sock = NULL;
|
||||||
sa_family_t sa_family = iface->addr.type.sa.sa_family;
|
sa_family_t sa_family = iface->addr.type.sa.sa_family;
|
||||||
size_t children_size = 0;
|
size_t children_size = 0;
|
||||||
|
uv_os_sock_t fd = -1;
|
||||||
|
|
||||||
REQUIRE(VALID_NM(mgr));
|
REQUIRE(VALID_NM(mgr));
|
||||||
|
|
||||||
@ -417,7 +418,11 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface,
|
|||||||
isc__nmsocket_init(sock, mgr, isc_nm_tcplistener, iface);
|
isc__nmsocket_init(sock, mgr, isc_nm_tcplistener, iface);
|
||||||
|
|
||||||
sock->rchildren = 0;
|
sock->rchildren = 0;
|
||||||
|
#if defined(WIN32)
|
||||||
|
sock->nchildren = 1;
|
||||||
|
#else
|
||||||
sock->nchildren = mgr->nworkers;
|
sock->nchildren = mgr->nworkers;
|
||||||
|
#endif
|
||||||
children_size = sock->nchildren * sizeof(sock->children[0]);
|
children_size = sock->nchildren * sizeof(sock->children[0]);
|
||||||
sock->children = isc_mem_get(mgr->mctx, children_size);
|
sock->children = isc_mem_get(mgr->mctx, children_size);
|
||||||
memset(sock->children, 0, children_size);
|
memset(sock->children, 0, children_size);
|
||||||
@ -426,6 +431,10 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface,
|
|||||||
sock->tid = isc_random_uniform(mgr->nworkers);
|
sock->tid = isc_random_uniform(mgr->nworkers);
|
||||||
sock->fd = -1;
|
sock->fd = -1;
|
||||||
|
|
||||||
|
#if !HAVE_SO_REUSEPORT_LB && !defined(WIN32)
|
||||||
|
fd = isc__nm_tcp_lb_socket(sa_family);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (size_t i = 0; i < mgr->nworkers; i++) {
|
for (size_t i = 0; i < mgr->nworkers; i++) {
|
||||||
isc__netievent_tcplisten_t *ievent = NULL;
|
isc__netievent_tcplisten_t *ievent = NULL;
|
||||||
isc_nmsocket_t *csock = &sock->children[i];
|
isc_nmsocket_t *csock = &sock->children[i];
|
||||||
@ -444,9 +453,11 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface,
|
|||||||
csock->pquota = quota;
|
csock->pquota = quota;
|
||||||
isc_quota_cb_init(&csock->quotacb, quota_accept_cb, csock);
|
isc_quota_cb_init(&csock->quotacb, quota_accept_cb, csock);
|
||||||
|
|
||||||
result = isc__nm_tcp_lb_socket(sa_family, &csock->fd);
|
#if HAVE_SO_REUSEPORT_LB || defined(WIN32)
|
||||||
REQUIRE(result == ISC_R_SUCCESS ||
|
csock->fd = isc__nm_tcp_lb_socket(sa_family);
|
||||||
result == ISC_R_NOTIMPLEMENTED);
|
#else
|
||||||
|
csock->fd = dup(fd);
|
||||||
|
#endif
|
||||||
REQUIRE(csock->fd >= 0);
|
REQUIRE(csock->fd >= 0);
|
||||||
|
|
||||||
ievent = isc__nm_get_netievent_tcplisten(mgr, csock);
|
ievent = isc__nm_get_netievent_tcplisten(mgr, csock);
|
||||||
@ -454,6 +465,10 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface,
|
|||||||
(isc__netievent_t *)ievent);
|
(isc__netievent_t *)ievent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !HAVE_SO_REUSEPORT_LB && !defined(WIN32)
|
||||||
|
isc__nm_closesocket(fd);
|
||||||
|
#endif
|
||||||
|
|
||||||
LOCK(&sock->lock);
|
LOCK(&sock->lock);
|
||||||
while (sock->rchildren != mgr->nworkers) {
|
while (sock->rchildren != mgr->nworkers) {
|
||||||
WAIT(&sock->cond, &sock->lock);
|
WAIT(&sock->cond, &sock->lock);
|
||||||
@ -479,11 +494,12 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface,
|
|||||||
void
|
void
|
||||||
isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||||
isc__netievent_tcplisten_t *ievent = (isc__netievent_tcplisten_t *)ev0;
|
isc__netievent_tcplisten_t *ievent = (isc__netievent_tcplisten_t *)ev0;
|
||||||
isc_nmiface_t *iface;
|
isc_nmiface_t *iface = NULL;
|
||||||
sa_family_t sa_family;
|
sa_family_t sa_family;
|
||||||
int r;
|
int r;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
isc_nmsocket_t *sock = NULL;
|
isc_nmsocket_t *sock = NULL;
|
||||||
|
isc_result_t result;
|
||||||
|
|
||||||
REQUIRE(VALID_NMSOCK(ievent->sock));
|
REQUIRE(VALID_NMSOCK(ievent->sock));
|
||||||
REQUIRE(ievent->sock->tid == isc_nm_tid());
|
REQUIRE(ievent->sock->tid == isc_nm_tid());
|
||||||
@ -502,14 +518,18 @@ isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
|
|
||||||
r = uv_tcp_init(&worker->loop, &sock->uv_handle.tcp);
|
r = uv_tcp_init(&worker->loop, &sock->uv_handle.tcp);
|
||||||
RUNTIME_CHECK(r == 0);
|
RUNTIME_CHECK(r == 0);
|
||||||
|
|
||||||
uv_handle_set_data(&sock->uv_handle.handle, sock);
|
uv_handle_set_data(&sock->uv_handle.handle, sock);
|
||||||
/* This keeps the socket alive after everything else is gone */
|
/* This keeps the socket alive after everything else is gone */
|
||||||
isc__nmsocket_attach(sock, &(isc_nmsocket_t *){ NULL });
|
isc__nmsocket_attach(sock, &(isc_nmsocket_t *){ NULL });
|
||||||
|
|
||||||
r = uv_timer_init(&worker->loop, &sock->timer);
|
r = uv_timer_init(&worker->loop, &sock->timer);
|
||||||
RUNTIME_CHECK(r == 0);
|
RUNTIME_CHECK(r == 0);
|
||||||
|
|
||||||
uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
|
uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
|
||||||
|
|
||||||
|
LOCK(&sock->parent->lock);
|
||||||
|
|
||||||
r = uv_tcp_open(&sock->uv_handle.tcp, sock->fd);
|
r = uv_tcp_open(&sock->uv_handle.tcp, sock->fd);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
isc__nm_closesocket(sock->fd);
|
isc__nm_closesocket(sock->fd);
|
||||||
@ -522,12 +542,29 @@ isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
flags = UV_TCP_IPV6ONLY;
|
flags = UV_TCP_IPV6ONLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HAVE_SO_REUSEPORT_LB || defined(WIN32)
|
||||||
r = isc_uv_tcp_freebind(&sock->uv_handle.tcp,
|
r = isc_uv_tcp_freebind(&sock->uv_handle.tcp,
|
||||||
&sock->iface->addr.type.sa, flags);
|
&sock->iface->addr.type.sa, flags);
|
||||||
if (r < 0 && r != UV_EINVAL) {
|
if (r < 0) {
|
||||||
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_BINDFAIL]);
|
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_BINDFAIL]);
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (sock->parent->fd == -1) {
|
||||||
|
r = isc_uv_tcp_freebind(&sock->uv_handle.tcp,
|
||||||
|
&sock->iface->addr.type.sa, flags);
|
||||||
|
if (r < 0) {
|
||||||
|
isc__nm_incstats(sock->mgr,
|
||||||
|
sock->statsindex[STATID_BINDFAIL]);
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
sock->parent->uv_handle.tcp.flags = sock->uv_handle.tcp.flags;
|
||||||
|
sock->parent->fd = sock->fd;
|
||||||
|
} else {
|
||||||
|
/* The socket is already bound, just copy the flags */
|
||||||
|
sock->uv_handle.tcp.flags = sock->parent->uv_handle.tcp.flags;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The callback will run in the same thread uv_listen() was called
|
* The callback will run in the same thread uv_listen() was called
|
||||||
@ -535,7 +572,7 @@ isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
*/
|
*/
|
||||||
r = uv_listen((uv_stream_t *)&sock->uv_handle.tcp, sock->backlog,
|
r = uv_listen((uv_stream_t *)&sock->uv_handle.tcp, sock->backlog,
|
||||||
tcp_connection_cb);
|
tcp_connection_cb);
|
||||||
if (r < 0) {
|
if (r != 0) {
|
||||||
isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
|
isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
|
||||||
ISC_LOGMODULE_NETMGR, ISC_LOG_ERROR,
|
ISC_LOGMODULE_NETMGR, ISC_LOG_ERROR,
|
||||||
"uv_listen failed: %s",
|
"uv_listen failed: %s",
|
||||||
@ -546,27 +583,15 @@ isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
|
|
||||||
atomic_store(&sock->listening, true);
|
atomic_store(&sock->listening, true);
|
||||||
|
|
||||||
LOCK(&sock->parent->lock);
|
|
||||||
sock->parent->rchildren += 1;
|
|
||||||
if (sock->parent->result == ISC_R_DEFAULT) {
|
|
||||||
sock->parent->result = ISC_R_SUCCESS;
|
|
||||||
}
|
|
||||||
SIGNAL(&sock->parent->cond);
|
|
||||||
if (!atomic_load(&sock->parent->active)) {
|
|
||||||
WAIT(&sock->parent->scond, &sock->parent->lock);
|
|
||||||
}
|
|
||||||
INSIST(atomic_load(&sock->parent->active));
|
|
||||||
UNLOCK(&sock->parent->lock);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
failure:
|
failure:
|
||||||
sock->pquota = NULL;
|
result = isc__nm_uverr2result(r);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
sock->pquota = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
LOCK(&sock->parent->lock);
|
|
||||||
sock->parent->rchildren += 1;
|
sock->parent->rchildren += 1;
|
||||||
if (sock->parent->result == ISC_R_DEFAULT) {
|
if (sock->parent->result == ISC_R_DEFAULT) {
|
||||||
sock->parent->result = isc__nm_uverr2result(r);
|
sock->parent->result = result;
|
||||||
}
|
}
|
||||||
SIGNAL(&sock->parent->cond);
|
SIGNAL(&sock->parent->cond);
|
||||||
if (!atomic_load(&sock->parent->active)) {
|
if (!atomic_load(&sock->parent->active)) {
|
||||||
@ -926,7 +951,7 @@ isc__nm_tcp_resumeread(isc_nmhandle_t *handle) {
|
|||||||
static void
|
static void
|
||||||
read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {
|
read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {
|
||||||
isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)stream);
|
isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)stream);
|
||||||
isc__nm_uvreq_t *req;
|
isc__nm_uvreq_t *req = NULL;
|
||||||
|
|
||||||
REQUIRE(VALID_NMSOCK(sock));
|
REQUIRE(VALID_NMSOCK(sock));
|
||||||
REQUIRE(sock->tid == isc_nm_tid());
|
REQUIRE(sock->tid == isc_nm_tid());
|
||||||
@ -1027,7 +1052,7 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) {
|
|||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
struct sockaddr_storage ss;
|
struct sockaddr_storage ss;
|
||||||
isc_sockaddr_t local;
|
isc_sockaddr_t local;
|
||||||
isc_nmhandle_t *handle;
|
isc_nmhandle_t *handle = NULL;
|
||||||
|
|
||||||
REQUIRE(VALID_NMSOCK(ssock));
|
REQUIRE(VALID_NMSOCK(ssock));
|
||||||
REQUIRE(ssock->tid == isc_nm_tid());
|
REQUIRE(ssock->tid == isc_nm_tid());
|
||||||
|
@ -421,27 +421,27 @@ isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
|
|||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static isc_result_t
|
static uv_os_sock_t
|
||||||
isc__nm_tcpdns_lb_socket(sa_family_t sa_family, uv_os_sock_t *sockp) {
|
isc__nm_tcpdns_lb_socket(sa_family_t sa_family) {
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
uv_os_sock_t sock;
|
uv_os_sock_t sock;
|
||||||
|
|
||||||
result = isc__nm_socket(sa_family, SOCK_STREAM, 0, &sock);
|
result = isc__nm_socket(sa_family, SOCK_STREAM, 0, &sock);
|
||||||
REQUIRE(result == ISC_R_SUCCESS);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
|
||||||
(void)isc__nm_socket_incoming_cpu(sock);
|
(void)isc__nm_socket_incoming_cpu(sock);
|
||||||
|
|
||||||
/* FIXME: set mss */
|
/* FIXME: set mss */
|
||||||
|
|
||||||
result = isc__nm_socket_reuse(sock);
|
result = isc__nm_socket_reuse(sock);
|
||||||
REQUIRE(result == ISC_R_SUCCESS || result == ISC_R_NOTIMPLEMENTED);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
|
||||||
|
#if HAVE_SO_REUSEPORT_LB
|
||||||
result = isc__nm_socket_reuse_lb(sock);
|
result = isc__nm_socket_reuse_lb(sock);
|
||||||
REQUIRE(result == ISC_R_SUCCESS || result == ISC_R_NOTIMPLEMENTED);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
#endif
|
||||||
|
|
||||||
*sockp = sock;
|
return (sock);
|
||||||
|
|
||||||
return (result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
@ -454,6 +454,7 @@ isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface,
|
|||||||
isc_nmsocket_t *sock = NULL;
|
isc_nmsocket_t *sock = NULL;
|
||||||
sa_family_t sa_family = iface->addr.type.sa.sa_family;
|
sa_family_t sa_family = iface->addr.type.sa.sa_family;
|
||||||
size_t children_size = 0;
|
size_t children_size = 0;
|
||||||
|
uv_os_sock_t fd = -1;
|
||||||
|
|
||||||
REQUIRE(VALID_NM(mgr));
|
REQUIRE(VALID_NM(mgr));
|
||||||
|
|
||||||
@ -461,7 +462,11 @@ isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface,
|
|||||||
isc__nmsocket_init(sock, mgr, isc_nm_tcpdnslistener, iface);
|
isc__nmsocket_init(sock, mgr, isc_nm_tcpdnslistener, iface);
|
||||||
|
|
||||||
sock->rchildren = 0;
|
sock->rchildren = 0;
|
||||||
|
#if defined(WIN32)
|
||||||
|
sock->nchildren = 1;
|
||||||
|
#else
|
||||||
sock->nchildren = mgr->nworkers;
|
sock->nchildren = mgr->nworkers;
|
||||||
|
#endif
|
||||||
children_size = sock->nchildren * sizeof(sock->children[0]);
|
children_size = sock->nchildren * sizeof(sock->children[0]);
|
||||||
sock->children = isc_mem_get(mgr->mctx, children_size);
|
sock->children = isc_mem_get(mgr->mctx, children_size);
|
||||||
memset(sock->children, 0, children_size);
|
memset(sock->children, 0, children_size);
|
||||||
@ -470,6 +475,10 @@ isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface,
|
|||||||
sock->tid = isc_random_uniform(mgr->nworkers);
|
sock->tid = isc_random_uniform(mgr->nworkers);
|
||||||
sock->fd = -1;
|
sock->fd = -1;
|
||||||
|
|
||||||
|
#if !HAVE_SO_REUSEPORT_LB && !defined(WIN32)
|
||||||
|
fd = isc__nm_tcpdns_lb_socket(sa_family);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (size_t i = 0; i < mgr->nworkers; i++) {
|
for (size_t i = 0; i < mgr->nworkers; i++) {
|
||||||
isc__netievent_tcpdnslisten_t *ievent = NULL;
|
isc__netievent_tcpdnslisten_t *ievent = NULL;
|
||||||
isc_nmsocket_t *csock = &sock->children[i];
|
isc_nmsocket_t *csock = &sock->children[i];
|
||||||
@ -490,9 +499,11 @@ isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface,
|
|||||||
csock->pquota = quota;
|
csock->pquota = quota;
|
||||||
isc_quota_cb_init(&csock->quotacb, quota_accept_cb, csock);
|
isc_quota_cb_init(&csock->quotacb, quota_accept_cb, csock);
|
||||||
|
|
||||||
result = isc__nm_tcpdns_lb_socket(sa_family, &csock->fd);
|
#if HAVE_SO_REUSEPORT_LB || defined(WIN32)
|
||||||
REQUIRE(result == ISC_R_SUCCESS ||
|
csock->fd = isc__nm_tcpdns_lb_socket(sa_family);
|
||||||
result == ISC_R_NOTIMPLEMENTED);
|
#else
|
||||||
|
csock->fd = dup(fd);
|
||||||
|
#endif
|
||||||
REQUIRE(csock->fd >= 0);
|
REQUIRE(csock->fd >= 0);
|
||||||
|
|
||||||
ievent = isc__nm_get_netievent_tcpdnslisten(mgr, csock);
|
ievent = isc__nm_get_netievent_tcpdnslisten(mgr, csock);
|
||||||
@ -500,6 +511,10 @@ isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface,
|
|||||||
(isc__netievent_t *)ievent);
|
(isc__netievent_t *)ievent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !HAVE_SO_REUSEPORT_LB && !defined(WIN32)
|
||||||
|
isc__nm_closesocket(fd);
|
||||||
|
#endif
|
||||||
|
|
||||||
LOCK(&sock->lock);
|
LOCK(&sock->lock);
|
||||||
while (sock->rchildren != mgr->nworkers) {
|
while (sock->rchildren != mgr->nworkers) {
|
||||||
WAIT(&sock->cond, &sock->lock);
|
WAIT(&sock->cond, &sock->lock);
|
||||||
@ -526,11 +541,12 @@ void
|
|||||||
isc__nm_async_tcpdnslisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
isc__nm_async_tcpdnslisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||||
isc__netievent_tcpdnslisten_t *ievent =
|
isc__netievent_tcpdnslisten_t *ievent =
|
||||||
(isc__netievent_tcpdnslisten_t *)ev0;
|
(isc__netievent_tcpdnslisten_t *)ev0;
|
||||||
isc_nmiface_t *iface;
|
isc_nmiface_t *iface = NULL;
|
||||||
sa_family_t sa_family;
|
sa_family_t sa_family;
|
||||||
int r;
|
int r;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
isc_nmsocket_t *sock = NULL;
|
isc_nmsocket_t *sock = NULL;
|
||||||
|
isc_result_t result = ISC_R_DEFAULT;
|
||||||
|
|
||||||
REQUIRE(VALID_NMSOCK(ievent->sock));
|
REQUIRE(VALID_NMSOCK(ievent->sock));
|
||||||
REQUIRE(ievent->sock->tid == isc_nm_tid());
|
REQUIRE(ievent->sock->tid == isc_nm_tid());
|
||||||
@ -557,6 +573,8 @@ isc__nm_async_tcpdnslisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
RUNTIME_CHECK(r == 0);
|
RUNTIME_CHECK(r == 0);
|
||||||
uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
|
uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
|
||||||
|
|
||||||
|
LOCK(&sock->parent->lock);
|
||||||
|
|
||||||
r = uv_tcp_open(&sock->uv_handle.tcp, sock->fd);
|
r = uv_tcp_open(&sock->uv_handle.tcp, sock->fd);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
isc__nm_closesocket(sock->fd);
|
isc__nm_closesocket(sock->fd);
|
||||||
@ -569,12 +587,29 @@ isc__nm_async_tcpdnslisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
flags = UV_TCP_IPV6ONLY;
|
flags = UV_TCP_IPV6ONLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HAVE_SO_REUSEPORT_LB || defined(WIN32)
|
||||||
r = isc_uv_tcp_freebind(&sock->uv_handle.tcp,
|
r = isc_uv_tcp_freebind(&sock->uv_handle.tcp,
|
||||||
&sock->iface->addr.type.sa, flags);
|
&sock->iface->addr.type.sa, flags);
|
||||||
if (r < 0 && r != UV_EINVAL) {
|
if (r < 0) {
|
||||||
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_BINDFAIL]);
|
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_BINDFAIL]);
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (sock->parent->fd == -1) {
|
||||||
|
r = isc_uv_tcp_freebind(&sock->uv_handle.tcp,
|
||||||
|
&sock->iface->addr.type.sa, flags);
|
||||||
|
if (r < 0) {
|
||||||
|
isc__nm_incstats(sock->mgr,
|
||||||
|
sock->statsindex[STATID_BINDFAIL]);
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
sock->parent->uv_handle.tcp.flags = sock->uv_handle.tcp.flags;
|
||||||
|
sock->parent->fd = sock->fd;
|
||||||
|
} else {
|
||||||
|
/* The socket is already bound, just copy the flags */
|
||||||
|
sock->uv_handle.tcp.flags = sock->parent->uv_handle.tcp.flags;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The callback will run in the same thread uv_listen() was called
|
* The callback will run in the same thread uv_listen() was called
|
||||||
@ -582,7 +617,7 @@ isc__nm_async_tcpdnslisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
*/
|
*/
|
||||||
r = uv_listen((uv_stream_t *)&sock->uv_handle.tcp, sock->backlog,
|
r = uv_listen((uv_stream_t *)&sock->uv_handle.tcp, sock->backlog,
|
||||||
tcpdns_connection_cb);
|
tcpdns_connection_cb);
|
||||||
if (r < 0) {
|
if (r != 0) {
|
||||||
isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
|
isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
|
||||||
ISC_LOGMODULE_NETMGR, ISC_LOG_ERROR,
|
ISC_LOGMODULE_NETMGR, ISC_LOG_ERROR,
|
||||||
"uv_listen failed: %s",
|
"uv_listen failed: %s",
|
||||||
@ -593,27 +628,15 @@ isc__nm_async_tcpdnslisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
|
|
||||||
atomic_store(&sock->listening, true);
|
atomic_store(&sock->listening, true);
|
||||||
|
|
||||||
LOCK(&sock->parent->lock);
|
|
||||||
sock->parent->rchildren += 1;
|
|
||||||
if (sock->parent->result == ISC_R_DEFAULT) {
|
|
||||||
sock->parent->result = ISC_R_SUCCESS;
|
|
||||||
}
|
|
||||||
SIGNAL(&sock->parent->cond);
|
|
||||||
if (!atomic_load(&sock->parent->active)) {
|
|
||||||
WAIT(&sock->parent->scond, &sock->parent->lock);
|
|
||||||
}
|
|
||||||
INSIST(atomic_load(&sock->parent->active));
|
|
||||||
UNLOCK(&sock->parent->lock);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
failure:
|
failure:
|
||||||
sock->pquota = NULL;
|
result = isc__nm_uverr2result(r);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
sock->pquota = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
LOCK(&sock->parent->lock);
|
|
||||||
sock->parent->rchildren += 1;
|
sock->parent->rchildren += 1;
|
||||||
if (sock->parent->result == ISC_R_DEFAULT) {
|
if (sock->parent->result == ISC_R_DEFAULT) {
|
||||||
sock->parent->result = isc__nm_uverr2result(r);
|
sock->parent->result = result;
|
||||||
}
|
}
|
||||||
SIGNAL(&sock->parent->cond);
|
SIGNAL(&sock->parent->cond);
|
||||||
if (!atomic_load(&sock->parent->active)) {
|
if (!atomic_load(&sock->parent->active)) {
|
||||||
@ -921,7 +944,7 @@ isc__nm_async_tcpdnsread(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
static isc_result_t
|
static isc_result_t
|
||||||
processbuffer(isc_nmsocket_t *sock) {
|
processbuffer(isc_nmsocket_t *sock) {
|
||||||
size_t len;
|
size_t len;
|
||||||
isc__nm_uvreq_t *req;
|
isc__nm_uvreq_t *req = NULL;
|
||||||
isc_nmhandle_t *handle = NULL;
|
isc_nmhandle_t *handle = NULL;
|
||||||
|
|
||||||
REQUIRE(VALID_NMSOCK(sock));
|
REQUIRE(VALID_NMSOCK(sock));
|
||||||
@ -1049,14 +1072,15 @@ free:
|
|||||||
static void
|
static void
|
||||||
quota_accept_cb(isc_quota_t *quota, void *sock0) {
|
quota_accept_cb(isc_quota_t *quota, void *sock0) {
|
||||||
isc_nmsocket_t *sock = (isc_nmsocket_t *)sock0;
|
isc_nmsocket_t *sock = (isc_nmsocket_t *)sock0;
|
||||||
isc__netievent_tcpdnsaccept_t *ievent = NULL;
|
|
||||||
|
|
||||||
REQUIRE(VALID_NMSOCK(sock));
|
REQUIRE(VALID_NMSOCK(sock));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a tcpdnsaccept event and pass it using the async channel.
|
* Create a tcpdnsaccept event and pass it using the async channel.
|
||||||
*/
|
*/
|
||||||
ievent = isc__nm_get_netievent_tcpdnsaccept(sock->mgr, sock, quota);
|
|
||||||
|
isc__netievent_tcpdnsaccept_t *ievent =
|
||||||
|
isc__nm_get_netievent_tcpdnsaccept(sock->mgr, sock, quota);
|
||||||
isc__nm_maybe_enqueue_ievent(&sock->mgr->workers[sock->tid],
|
isc__nm_maybe_enqueue_ievent(&sock->mgr->workers[sock->tid],
|
||||||
(isc__netievent_t *)ievent);
|
(isc__netievent_t *)ievent);
|
||||||
}
|
}
|
||||||
@ -1068,15 +1092,14 @@ void
|
|||||||
isc__nm_async_tcpdnsaccept(isc__networker_t *worker, isc__netievent_t *ev0) {
|
isc__nm_async_tcpdnsaccept(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||||
isc__netievent_tcpdnsaccept_t *ievent =
|
isc__netievent_tcpdnsaccept_t *ievent =
|
||||||
(isc__netievent_tcpdnsaccept_t *)ev0;
|
(isc__netievent_tcpdnsaccept_t *)ev0;
|
||||||
isc_nmsocket_t *sock = ievent->sock;
|
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
|
|
||||||
UNUSED(worker);
|
UNUSED(worker);
|
||||||
|
|
||||||
REQUIRE(VALID_NMSOCK(sock));
|
REQUIRE(VALID_NMSOCK(ievent->sock));
|
||||||
REQUIRE(sock->tid == isc_nm_tid());
|
REQUIRE(ievent->sock->tid == isc_nm_tid());
|
||||||
|
|
||||||
result = accept_connection(sock, ievent->quota);
|
result = accept_connection(ievent->sock, ievent->quota);
|
||||||
if (result != ISC_R_SUCCESS && result != ISC_R_NOCONN) {
|
if (result != ISC_R_SUCCESS && result != ISC_R_NOCONN) {
|
||||||
if ((result != ISC_R_QUOTA && result != ISC_R_SOFTQUOTA) ||
|
if ((result != ISC_R_QUOTA && result != ISC_R_SOFTQUOTA) ||
|
||||||
can_log_tcpdns_quota())
|
can_log_tcpdns_quota())
|
||||||
@ -1098,7 +1121,7 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) {
|
|||||||
struct sockaddr_storage peer_ss;
|
struct sockaddr_storage peer_ss;
|
||||||
struct sockaddr_storage local_ss;
|
struct sockaddr_storage local_ss;
|
||||||
isc_sockaddr_t local;
|
isc_sockaddr_t local;
|
||||||
isc_nmhandle_t *handle;
|
isc_nmhandle_t *handle = NULL;
|
||||||
|
|
||||||
REQUIRE(VALID_NMSOCK(ssock));
|
REQUIRE(VALID_NMSOCK(ssock));
|
||||||
REQUIRE(ssock->tid == isc_nm_tid());
|
REQUIRE(ssock->tid == isc_nm_tid());
|
||||||
|
@ -77,27 +77,26 @@ inactive(isc_nmsocket_t *sock) {
|
|||||||
(sock->server != NULL && !isc__nmsocket_active(sock->server)));
|
(sock->server != NULL && !isc__nmsocket_active(sock->server)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static isc_result_t
|
static uv_os_sock_t
|
||||||
isc__nm_udp_lb_socket(sa_family_t sa_family, uv_os_sock_t *sockp) {
|
isc__nm_udp_lb_socket(sa_family_t sa_family) {
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
uv_os_sock_t sock;
|
uv_os_sock_t sock;
|
||||||
|
|
||||||
result = isc__nm_socket(sa_family, SOCK_DGRAM, 0, &sock);
|
result = isc__nm_socket(sa_family, SOCK_DGRAM, 0, &sock);
|
||||||
REQUIRE(result == ISC_R_SUCCESS);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
|
||||||
(void)isc__nm_socket_incoming_cpu(sock);
|
(void)isc__nm_socket_incoming_cpu(sock);
|
||||||
|
|
||||||
(void)isc__nm_socket_dontfrag(sock, sa_family);
|
(void)isc__nm_socket_dontfrag(sock, sa_family);
|
||||||
|
|
||||||
result = isc__nm_socket_reuse(sock);
|
result = isc__nm_socket_reuse(sock);
|
||||||
REQUIRE(result == ISC_R_SUCCESS);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
|
||||||
|
#if HAVE_SO_REUSEPORT_LB
|
||||||
result = isc__nm_socket_reuse_lb(sock);
|
result = isc__nm_socket_reuse_lb(sock);
|
||||||
REQUIRE(result == ISC_R_SUCCESS || result == ISC_R_NOTIMPLEMENTED);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
#endif
|
||||||
|
|
||||||
*sockp = sock;
|
return (sock);
|
||||||
|
|
||||||
return (result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
@ -107,6 +106,7 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
|
|||||||
isc_nmsocket_t *sock = NULL;
|
isc_nmsocket_t *sock = NULL;
|
||||||
sa_family_t sa_family = iface->addr.type.sa.sa_family;
|
sa_family_t sa_family = iface->addr.type.sa.sa_family;
|
||||||
size_t children_size = 0;
|
size_t children_size = 0;
|
||||||
|
uv_os_sock_t fd = -1;
|
||||||
|
|
||||||
REQUIRE(VALID_NM(mgr));
|
REQUIRE(VALID_NM(mgr));
|
||||||
|
|
||||||
@ -118,7 +118,12 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
|
|||||||
isc__nmsocket_init(sock, mgr, isc_nm_udplistener, iface);
|
isc__nmsocket_init(sock, mgr, isc_nm_udplistener, iface);
|
||||||
|
|
||||||
sock->rchildren = 0;
|
sock->rchildren = 0;
|
||||||
|
#if defined(WIN32)
|
||||||
|
sock->nchildren = 1;
|
||||||
|
#else
|
||||||
sock->nchildren = mgr->nworkers;
|
sock->nchildren = mgr->nworkers;
|
||||||
|
#endif
|
||||||
|
|
||||||
children_size = sock->nchildren * sizeof(sock->children[0]);
|
children_size = sock->nchildren * sizeof(sock->children[0]);
|
||||||
sock->children = isc_mem_get(mgr->mctx, children_size);
|
sock->children = isc_mem_get(mgr->mctx, children_size);
|
||||||
memset(sock->children, 0, children_size);
|
memset(sock->children, 0, children_size);
|
||||||
@ -130,6 +135,10 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
|
|||||||
sock->tid = isc_random_uniform(mgr->nworkers);
|
sock->tid = isc_random_uniform(mgr->nworkers);
|
||||||
sock->fd = -1;
|
sock->fd = -1;
|
||||||
|
|
||||||
|
#if !HAVE_SO_REUSEPORT_LB && !defined(WIN32)
|
||||||
|
fd = isc__nm_udp_lb_socket(sa_family);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (size_t i = 0; i < mgr->nworkers; i++) {
|
for (size_t i = 0; i < mgr->nworkers; i++) {
|
||||||
isc__netievent_udplisten_t *ievent = NULL;
|
isc__netievent_udplisten_t *ievent = NULL;
|
||||||
isc_nmsocket_t *csock = &sock->children[i];
|
isc_nmsocket_t *csock = &sock->children[i];
|
||||||
@ -143,7 +152,11 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
|
|||||||
csock->extrahandlesize = sock->extrahandlesize;
|
csock->extrahandlesize = sock->extrahandlesize;
|
||||||
csock->tid = i;
|
csock->tid = i;
|
||||||
|
|
||||||
(void)isc__nm_udp_lb_socket(sa_family, &csock->fd);
|
#if HAVE_SO_REUSEPORT_LB || defined(WIN32)
|
||||||
|
csock->fd = isc__nm_udp_lb_socket(sa_family);
|
||||||
|
#else
|
||||||
|
csock->fd = dup(fd);
|
||||||
|
#endif
|
||||||
REQUIRE(csock->fd >= 0);
|
REQUIRE(csock->fd >= 0);
|
||||||
|
|
||||||
ievent = isc__nm_get_netievent_udplisten(mgr, csock);
|
ievent = isc__nm_get_netievent_udplisten(mgr, csock);
|
||||||
@ -151,6 +164,10 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
|
|||||||
(isc__netievent_t *)ievent);
|
(isc__netievent_t *)ievent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !HAVE_SO_REUSEPORT_LB && !defined(WIN32)
|
||||||
|
isc__nm_closesocket(fd);
|
||||||
|
#endif
|
||||||
|
|
||||||
LOCK(&sock->lock);
|
LOCK(&sock->lock);
|
||||||
while (sock->rchildren != mgr->nworkers) {
|
while (sock->rchildren != mgr->nworkers) {
|
||||||
WAIT(&sock->cond, &sock->lock);
|
WAIT(&sock->cond, &sock->lock);
|
||||||
@ -205,11 +222,12 @@ udp_alloc_cb(uv_handle_t *handle, size_t size, uv_buf_t *buf) {
|
|||||||
void
|
void
|
||||||
isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||||
isc__netievent_udplisten_t *ievent = (isc__netievent_udplisten_t *)ev0;
|
isc__netievent_udplisten_t *ievent = (isc__netievent_udplisten_t *)ev0;
|
||||||
isc_nmiface_t *iface;
|
isc_nmiface_t *iface = NULL;
|
||||||
isc_nmsocket_t *sock = NULL;
|
isc_nmsocket_t *sock = NULL;
|
||||||
int r, uv_bind_flags = 0;
|
int r, uv_bind_flags = 0;
|
||||||
int uv_init_flags = 0;
|
int uv_init_flags = 0;
|
||||||
sa_family_t sa_family;
|
sa_family_t sa_family;
|
||||||
|
isc_result_t result = ISC_R_DEFAULT;
|
||||||
|
|
||||||
REQUIRE(VALID_NMSOCK(ievent->sock));
|
REQUIRE(VALID_NMSOCK(ievent->sock));
|
||||||
REQUIRE(ievent->sock->tid == isc_nm_tid());
|
REQUIRE(ievent->sock->tid == isc_nm_tid());
|
||||||
@ -237,6 +255,8 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
RUNTIME_CHECK(r == 0);
|
RUNTIME_CHECK(r == 0);
|
||||||
uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
|
uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
|
||||||
|
|
||||||
|
LOCK(&sock->parent->lock);
|
||||||
|
|
||||||
r = uv_udp_open(&sock->uv_handle.udp, sock->fd);
|
r = uv_udp_open(&sock->uv_handle.udp, sock->fd);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
isc__nm_closesocket(sock->fd);
|
isc__nm_closesocket(sock->fd);
|
||||||
@ -249,13 +269,33 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
uv_bind_flags |= UV_UDP_IPV6ONLY;
|
uv_bind_flags |= UV_UDP_IPV6ONLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HAVE_SO_REUSEPORT_LB || WIN32
|
||||||
r = isc_uv_udp_freebind(&sock->uv_handle.udp,
|
r = isc_uv_udp_freebind(&sock->uv_handle.udp,
|
||||||
&sock->parent->iface->addr.type.sa,
|
&sock->parent->iface->addr.type.sa,
|
||||||
uv_bind_flags);
|
uv_bind_flags);
|
||||||
if (r < 0 && r != UV_EINVAL) {
|
if (r < 0) {
|
||||||
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_BINDFAIL]);
|
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_BINDFAIL]);
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (sock->parent->fd == -1) {
|
||||||
|
/* This thread is first, bind the socket */
|
||||||
|
r = isc_uv_udp_freebind(&sock->uv_handle.udp,
|
||||||
|
&sock->parent->iface->addr.type.sa,
|
||||||
|
uv_bind_flags);
|
||||||
|
if (r < 0) {
|
||||||
|
isc__nm_incstats(sock->mgr,
|
||||||
|
sock->statsindex[STATID_BINDFAIL]);
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
sock->parent->uv_handle.udp.flags = sock->uv_handle.udp.flags;
|
||||||
|
sock->parent->fd = sock->fd;
|
||||||
|
} else {
|
||||||
|
/* The socket is already bound, just copy the flags */
|
||||||
|
sock->uv_handle.udp.flags = sock->parent->uv_handle.udp.flags;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ISC_RECV_BUFFER_SIZE
|
#ifdef ISC_RECV_BUFFER_SIZE
|
||||||
uv_recv_buffer_size(&sock->uv_handle.handle,
|
uv_recv_buffer_size(&sock->uv_handle.handle,
|
||||||
&(int){ ISC_RECV_BUFFER_SIZE });
|
&(int){ ISC_RECV_BUFFER_SIZE });
|
||||||
@ -272,24 +312,11 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
|
|
||||||
atomic_store(&sock->listening, true);
|
atomic_store(&sock->listening, true);
|
||||||
|
|
||||||
LOCK(&sock->parent->lock);
|
|
||||||
sock->parent->rchildren += 1;
|
|
||||||
if (sock->parent->result == ISC_R_DEFAULT) {
|
|
||||||
sock->parent->result = ISC_R_SUCCESS;
|
|
||||||
}
|
|
||||||
SIGNAL(&sock->parent->cond);
|
|
||||||
if (!atomic_load(&sock->parent->active)) {
|
|
||||||
WAIT(&sock->parent->scond, &sock->parent->lock);
|
|
||||||
}
|
|
||||||
INSIST(atomic_load(&sock->parent->active));
|
|
||||||
UNLOCK(&sock->parent->lock);
|
|
||||||
|
|
||||||
return;
|
|
||||||
failure:
|
failure:
|
||||||
LOCK(&sock->parent->lock);
|
result = isc__nm_uverr2result(r);
|
||||||
sock->parent->rchildren += 1;
|
sock->parent->rchildren += 1;
|
||||||
if (sock->parent->result == ISC_R_DEFAULT) {
|
if (sock->parent->result == ISC_R_DEFAULT) {
|
||||||
sock->parent->result = isc__nm_uverr2result(r);
|
sock->parent->result = result;
|
||||||
}
|
}
|
||||||
SIGNAL(&sock->parent->cond);
|
SIGNAL(&sock->parent->cond);
|
||||||
if (!atomic_load(&sock->parent->active)) {
|
if (!atomic_load(&sock->parent->active)) {
|
||||||
@ -359,7 +386,7 @@ static void
|
|||||||
udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
|
udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
|
||||||
const struct sockaddr *addr, unsigned flags) {
|
const struct sockaddr *addr, unsigned flags) {
|
||||||
isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)handle);
|
isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)handle);
|
||||||
isc__nm_uvreq_t *req;
|
isc__nm_uvreq_t *req = NULL;
|
||||||
uint32_t maxudp;
|
uint32_t maxudp;
|
||||||
bool free_buf;
|
bool free_buf;
|
||||||
isc_sockaddr_t sockaddr;
|
isc_sockaddr_t sockaddr;
|
||||||
@ -1224,7 +1251,7 @@ isc__nm_udp_cancelread(isc_nmhandle_t *handle) {
|
|||||||
void
|
void
|
||||||
isc__nm_async_udpcancel(isc__networker_t *worker, isc__netievent_t *ev0) {
|
isc__nm_async_udpcancel(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||||
isc__netievent_udpcancel_t *ievent = (isc__netievent_udpcancel_t *)ev0;
|
isc__netievent_udpcancel_t *ievent = (isc__netievent_udpcancel_t *)ev0;
|
||||||
isc_nmsocket_t *sock;
|
isc_nmsocket_t *sock = NULL;
|
||||||
|
|
||||||
UNUSED(worker);
|
UNUSED(worker);
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@ isc_result_t
|
|||||||
isc___nm_uverr2result(int uverr, bool dolog, const char *file,
|
isc___nm_uverr2result(int uverr, bool dolog, const char *file,
|
||||||
unsigned int line, const char *func) {
|
unsigned int line, const char *func) {
|
||||||
switch (uverr) {
|
switch (uverr) {
|
||||||
|
case 0:
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
case UV_ENOTDIR:
|
case UV_ENOTDIR:
|
||||||
case UV_ELOOP:
|
case UV_ELOOP:
|
||||||
case UV_EINVAL: /* XXX sometimes this is not for files */
|
case UV_EINVAL: /* XXX sometimes this is not for files */
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* information regarding copyright ownership.
|
* information regarding copyright ownership.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if HAVE_CMOCKA && defined(__linux__)
|
#if HAVE_CMOCKA
|
||||||
#include <sched.h> /* IWYU pragma: keep */
|
#include <sched.h> /* IWYU pragma: keep */
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* information regarding copyright ownership.
|
* information regarding copyright ownership.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if HAVE_CMOCKA && defined(__linux__)
|
#if HAVE_CMOCKA
|
||||||
#include <sched.h> /* IWYU pragma: keep */
|
#include <sched.h> /* IWYU pragma: keep */
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* information regarding copyright ownership.
|
* information regarding copyright ownership.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if HAVE_CMOCKA && defined(__linux__)
|
#if HAVE_CMOCKA
|
||||||
#include <sched.h> /* IWYU pragma: keep */
|
#include <sched.h> /* IWYU pragma: keep */
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* information regarding copyright ownership.
|
* information regarding copyright ownership.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if HAVE_CMOCKA && defined(__linux__)
|
#if HAVE_CMOCKA
|
||||||
#include <sched.h> /* IWYU pragma: keep */
|
#include <sched.h> /* IWYU pragma: keep */
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user