Make dns_dispatch bound to threads

Instead of high number of dispatches (4 * named_g_udpdisp)[1], make the
dispatches bound to threads and make dns_dispatchset_t create a dispatch
for each thread (event loop).

This required couple of other changes:

1. The dns_dispatch_createudp() must be called on loop, so the isc_tid()
   is already initialized - changes to nsupdate and mdig were required.

2. The dns_requestmgr had only a single dispatch per v4 and v6.  Instead
   of using single dispatch, use dns_dispatchset_t for each protocol -
   this is same as dns_resolver.
This commit is contained in:
Ondřej Surý 2023-09-15 11:36:28 +02:00
parent 282c4709b8
commit 6fd06c461b
No known key found for this signature in database
GPG key ID: 2820F37E873DEA41
19 changed files with 132 additions and 208 deletions

View file

@ -2165,7 +2165,7 @@ run_server(void *arg) {
dns_view_initsecroots(view);
CHECK(setup_dnsseckeys(NULL, view));
CHECK(dns_view_createresolver(view, loopmgr, 1, netmgr, 0,
CHECK(dns_view_createresolver(view, loopmgr, netmgr, 0,
tlsctx_client_cache, dispatch, NULL));
isc_stats_create(mctx, &resstats, dns_resstatscounter_max);

View file

@ -50,7 +50,6 @@
EXTERN isc_mem_t *named_g_mctx INIT(NULL);
EXTERN unsigned int named_g_cpus INIT(0);
EXTERN unsigned int named_g_udpdisp INIT(0);
EXTERN isc_loop_t *named_g_mainloop INIT(NULL);
EXTERN isc_loopmgr_t *named_g_loopmgr INIT(NULL);
EXTERN bool named_g_loopmgr_running INIT(false);

View file

@ -949,9 +949,7 @@ parse_command_line(int argc, char *argv[]) {
parse_T_opt(isc_commandline_argument);
break;
case 'U':
named_g_udpdisp = parse_int(isc_commandline_argument,
"number of UDP listeners "
"per interface");
/* Obsolete. No longer in use. Ignore. */
break;
case 'u':
named_g_username = isc_commandline_argument;
@ -1044,16 +1042,6 @@ create_managers(void) {
ISC_LOG_INFO, "found %u CPU%s, using %u worker thread%s",
named_g_cpus_detected, named_g_cpus_detected == 1 ? "" : "s",
named_g_cpus, named_g_cpus == 1 ? "" : "s");
if (named_g_udpdisp == 0) {
named_g_udpdisp = named_g_cpus_detected;
}
if (named_g_udpdisp > named_g_cpus) {
named_g_udpdisp = named_g_cpus;
}
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
"using %u UDP listener%s per interface", named_g_udpdisp,
named_g_udpdisp == 1 ? "" : "s");
isc_managers_create(&named_g_mctx, named_g_cpus, &named_g_loopmgr,
&named_g_netmgr);

View file

@ -4033,7 +4033,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
named_cache_t *nsc;
bool zero_no_soattl;
dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL;
unsigned int query_timeout, ndisp;
unsigned int query_timeout;
bool old_rpz_ok = false;
dns_dyndbctx_t *dctx = NULL;
unsigned int resolver_param;
@ -4685,9 +4685,8 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
goto cleanup;
}
ndisp = 4 * ISC_MIN(named_g_udpdisp, MAX_UDP_DISPATCH);
CHECK(dns_view_createresolver(
view, named_g_loopmgr, ndisp, named_g_netmgr, resopts,
view, named_g_loopmgr, named_g_netmgr, resopts,
named_g_server->tlsctx_client_cache, dispatch4, dispatch6));
if (resstats == NULL) {
@ -12148,10 +12147,6 @@ named_server_status(named_server_t *server, isc_buffer_t **text) {
snprintf(line, sizeof(line), "worker threads: %u\n", named_g_cpus);
CHECK(putstr(text, line));
snprintf(line, sizeof(line), "UDP listeners per interface: %u\n",
named_g_udpdisp);
CHECK(putstr(text, line));
snprintf(line, sizeof(line), "number of zones: %u (%u automatic)\n",
zonecount, automatic);
CHECK(putstr(text, line));

View file

@ -798,7 +798,7 @@ create_name(const char *str, char *namedata, size_t len, dns_name_t *name) {
}
static void
setup_system(void) {
setup_system(void *arg ISC_ATTR_UNUSED) {
isc_result_t result;
isc_sockaddr_t bind_any, bind_any6;
isc_sockaddrlist_t *nslist;
@ -3475,8 +3475,7 @@ main(int argc, char **argv) {
timeoutms = timeout * 1000;
isc_nm_settimeouts(netmgr, timeoutms, timeoutms, timeoutms, timeoutms);
setup_system();
isc_loopmgr_setup(loopmgr, setup_system, NULL);
isc_loopmgr_setup(loopmgr, getinput, NULL);
isc_loopmgr_teardown(loopmgr, shutdown_program, NULL);
isc_loopmgr_run(loopmgr);

View file

@ -116,6 +116,12 @@ static unsigned char cookie_secret[33];
static int onfly = 0;
static char hexcookie[81];
static isc_sockaddr_t bind_any;
static isc_nm_t *netmgr = NULL;
static dns_dispatchmgr_t *dispatchmgr = NULL;
static dns_dispatch_t *dispatchvx = NULL;
static dns_view_t *view = NULL;
struct query {
char textname[MXNAME]; /*% Name we're going to be
* looking up */
@ -2069,43 +2075,42 @@ set_source_ports(dns_dispatchmgr_t *manager) {
}
static void
teardown_view(void *arg) {
dns_view_t *view = arg;
teardown(void *arg ISC_ATTR_UNUSED) {
dns_view_detach(&view);
}
static void
teardown_requestmgr(void *arg) {
dns_requestmgr_t *mgr = arg;
dns_requestmgr_shutdown(mgr);
dns_requestmgr_detach(&mgr);
}
static void
teardown_dispatch(void *arg) {
dns_dispatch_t *dispatchv4 = arg;
dns_dispatch_detach(&dispatchv4);
}
static void
teardown_dispatchmgr(void *arg) {
dns_dispatchmgr_t *dispatchmgr = arg;
dns_requestmgr_shutdown(requestmgr);
dns_requestmgr_detach(&requestmgr);
dns_dispatch_detach(&dispatchvx);
dns_dispatchmgr_detach(&dispatchmgr);
}
static void
setup(void *arg ISC_ATTR_UNUSED) {
RUNCHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr));
set_source_ports(dispatchmgr);
if (have_ipv4) {
isc_sockaddr_any(&bind_any);
} else {
isc_sockaddr_any6(&bind_any);
}
RUNCHECK(dns_dispatch_createudp(
dispatchmgr, have_src ? &srcaddr : &bind_any, &dispatchvx));
RUNCHECK(dns_requestmgr_create(
mctx, loopmgr, dispatchmgr, have_ipv4 ? dispatchvx : NULL,
have_ipv6 ? dispatchvx : NULL, &requestmgr));
RUNCHECK(dns_view_create(mctx, NULL, 0, "_mdig", &view));
}
/*% Main processing routine for mdig */
int
main(int argc, char *argv[]) {
struct query *query = NULL;
isc_result_t result;
isc_sockaddr_t bind_any;
isc_log_t *lctx = NULL;
isc_logconfig_t *lcfg = NULL;
isc_nm_t *netmgr = NULL;
dns_dispatchmgr_t *dispatchmgr = NULL;
dns_dispatch_t *dispatchvx = NULL;
dns_view_t *view = NULL;
unsigned int i;
int ns;
@ -2151,30 +2156,10 @@ main(int argc, char *argv[]) {
fatal("can't choose between IPv4 and IPv6");
}
RUNCHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr));
set_source_ports(dispatchmgr);
if (have_ipv4) {
isc_sockaddr_any(&bind_any);
} else {
isc_sockaddr_any6(&bind_any);
}
RUNCHECK(dns_dispatch_createudp(
dispatchmgr, have_src ? &srcaddr : &bind_any, &dispatchvx));
RUNCHECK(dns_requestmgr_create(
mctx, loopmgr, dispatchmgr, have_ipv4 ? dispatchvx : NULL,
have_ipv6 ? dispatchvx : NULL, &requestmgr));
RUNCHECK(dns_view_create(mctx, NULL, 0, "_mdig", &view));
query = ISC_LIST_HEAD(queries);
isc_loopmgr_setup(loopmgr, setup, NULL);
isc_loopmgr_setup(loopmgr, sendqueries, query);
isc_loopmgr_teardown(loopmgr, teardown_view, view);
isc_loopmgr_teardown(loopmgr, teardown_requestmgr, requestmgr);
isc_loopmgr_teardown(loopmgr, teardown_dispatch, dispatchvx);
isc_loopmgr_teardown(loopmgr, teardown_dispatchmgr, dispatchmgr);
isc_loopmgr_teardown(loopmgr, teardown, NULL);
/*
* Stall to the start of a new second.

View file

@ -215,9 +215,8 @@ createview(isc_mem_t *mctx, dns_rdataclass_t rdclass, isc_loopmgr_t *loopmgr,
/* Initialize view security roots */
dns_view_initsecroots(view);
CHECK(dns_view_createresolver(view, loopmgr, 1, nm, 0,
tlsctx_client_cache, dispatchv4,
dispatchv6));
CHECK(dns_view_createresolver(view, loopmgr, nm, 0, tlsctx_client_cache,
dispatchv4, dispatchv6));
CHECK(dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_cache,
rdclass, 0, NULL, &view->cachedb));

View file

@ -19,7 +19,6 @@
#include <sys/types.h>
#include <unistd.h>
#include <isc/atomic.h>
#include <isc/hash.h>
#include <isc/hashmap.h>
#include <isc/loop.h>
@ -119,8 +118,6 @@ struct dns_dispatch {
/*% Locked by mgr->lock. */
ISC_LINK(dns_dispatch_t) link;
/* Locked by "lock". */
isc_mutex_t lock; /*%< locks all below */
isc_socktype_t socktype;
dns_dispatchstate_t state;
isc_refcount_t references;
@ -130,7 +127,7 @@ struct dns_dispatch {
dns_displist_t pending;
dns_displist_t active;
unsigned int requests; /*%< how many requests we have */
uint_fast32_t requests; /*%< how many requests we have */
unsigned int timedout;
};
@ -188,7 +185,7 @@ static void
dispentry_cancel(dns_dispentry_t *resp, isc_result_t result);
static isc_result_t
dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
dns_dispatch_t **dispp);
uint32_t tid, dns_dispatch_t **dispp);
static void
udp_startrecv(isc_nmhandle_t *handle, dns_dispentry_t *resp);
static void
@ -417,10 +414,8 @@ dispentry_destroy(dns_dispentry_t *resp) {
*/
dispentry_cancel(resp, ISC_R_CANCELED);
LOCK(&disp->lock);
INSIST(disp->requests > 0);
disp->requests--;
UNLOCK(&disp->lock);
isc_refcount_destroy(&resp->references);
@ -504,7 +499,7 @@ udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
disp = resp->disp;
LOCK(&disp->lock);
REQUIRE(disp->tid == isc_tid());
INSIST(resp->reading);
resp->reading = false;
@ -518,7 +513,7 @@ udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
eresult = ISC_R_CANCELED;
}
dispentry_log(resp, LVL(90), "read callback:%s, requests %d",
dispentry_log(resp, LVL(90), "read callback:%s, requests %" PRIuFAST32,
isc_result_totext(eresult), disp->requests);
if (eresult != ISC_R_SUCCESS) {
@ -617,8 +612,6 @@ next:
udp_dispatch_getnext(resp, timeout);
done:
UNLOCK(&disp->lock);
if (respond) {
dispentry_log(resp, LVL(90), "UDP read callback on %p: %s",
handle, isc_result_totext(eresult));
@ -781,11 +774,11 @@ tcp_recv(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region,
REQUIRE(VALID_DISPATCH(disp));
LOCK(&disp->lock);
REQUIRE(disp->tid == isc_tid());
INSIST(disp->reading);
disp->reading = false;
dispatch_log(disp, LVL(90), "TCP read:%s:requests %u",
dispatch_log(disp, LVL(90), "TCP read:%s:requests %" PRIuFAST32,
isc_result_totext(result), disp->requests);
peer = isc_nmhandle_peeraddr(handle);
@ -886,7 +879,6 @@ tcp_recv(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region,
isc_nmhandle_settimeout(handle, timeout);
}
UNLOCK(&disp->lock);
rcu_read_unlock();
/*
@ -1082,7 +1074,7 @@ dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats) {
* Allocate and set important limits.
*/
static void
dispatch_allocate(dns_dispatchmgr_t *mgr, isc_socktype_t type,
dispatch_allocate(dns_dispatchmgr_t *mgr, isc_socktype_t type, uint32_t tid,
dns_dispatch_t **dispp) {
dns_dispatch_t *disp = NULL;
@ -1100,7 +1092,7 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, isc_socktype_t type,
.link = ISC_LINK_INITIALIZER,
.active = ISC_LIST_INITIALIZER,
.pending = ISC_LIST_INITIALIZER,
.tid = isc_tid(),
.tid = tid,
.magic = DISPATCH_MAGIC,
};
@ -1110,7 +1102,6 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, isc_socktype_t type,
__func__, __FILE__, __LINE__, disp);
#endif
isc_refcount_init(&disp->references, 1); /* DISPATCH000 */
isc_mutex_init(&disp->lock);
*dispp = disp;
}
@ -1125,7 +1116,7 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
LOCK(&mgr->lock);
dispatch_allocate(mgr, isc_socktype_tcp, &disp);
dispatch_allocate(mgr, isc_socktype_tcp, isc_tid(), &disp);
disp->peer = *destaddr;
@ -1181,13 +1172,12 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr,
isc_sockaddr_t sockname;
isc_sockaddr_t peeraddr;
LOCK(&disp->lock);
if (disp->tid != isc_tid()) {
UNLOCK(&disp->lock);
continue;
}
REQUIRE(disp->tid == isc_tid());
if (disp->handle != NULL) {
sockname = isc_nmhandle_localaddr(disp->handle);
peeraddr = isc_nmhandle_peeraddr(disp->handle);
@ -1207,7 +1197,6 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr,
(localaddr != NULL &&
!isc_sockaddr_eqaddr(localaddr, &sockname)))
{
UNLOCK(&disp->lock);
continue;
}
@ -1240,8 +1229,6 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr,
UNREACHABLE();
}
UNLOCK(&disp->lock);
if (disp_connected != NULL) {
break;
}
@ -1281,7 +1268,7 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
REQUIRE(dispp != NULL && *dispp == NULL);
LOCK(&mgr->lock);
result = dispatch_createudp(mgr, localaddr, &disp);
result = dispatch_createudp(mgr, localaddr, isc_tid(), &disp);
if (result == ISC_R_SUCCESS) {
*dispp = disp;
}
@ -1292,7 +1279,7 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
static isc_result_t
dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
dns_dispatch_t **dispp) {
uint32_t tid, dns_dispatch_t **dispp) {
isc_result_t result = ISC_R_SUCCESS;
dns_dispatch_t *disp = NULL;
isc_sockaddr_t sa_any;
@ -1308,7 +1295,7 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
}
}
dispatch_allocate(mgr, isc_socktype_udp, &disp);
dispatch_allocate(mgr, isc_socktype_udp, tid, &disp);
if (isc_log_wouldlog(dns_lctx, 90)) {
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
@ -1361,8 +1348,6 @@ dispatch_destroy(dns_dispatch_t *disp) {
isc_nmhandle_detach(&disp->handle);
}
isc_mutex_destroy(&disp->lock);
isc_mem_put(mgr->mctx, disp, sizeof(*disp));
/*
@ -1401,10 +1386,9 @@ dns_dispatch_add(dns_dispatch_t *disp, isc_loop_t *loop, unsigned int options,
REQUIRE(sent != NULL);
REQUIRE(loop != NULL);
LOCK(&disp->lock);
REQUIRE(disp->tid == isc_tid());
if (disp->state == DNS_DISPATCHSTATE_CANCELED) {
UNLOCK(&disp->lock);
return (ISC_R_CANCELED);
}
@ -1436,7 +1420,6 @@ dns_dispatch_add(dns_dispatch_t *disp, isc_loop_t *loop, unsigned int options,
result = setup_socket(disp, resp, dest, &localport);
if (result != ISC_R_SUCCESS) {
isc_mem_put(disp->mgr->mctx, resp, sizeof(*resp));
UNLOCK(&disp->lock);
inc_stats(disp->mgr, dns_resstatscounter_dispsockfail);
return (result);
}
@ -1496,7 +1479,6 @@ fail:
: dns_resstatscounter_dispreqtcp);
rcu_read_unlock();
UNLOCK(&disp->lock);
*idp = resp->id;
*respp = resp;
@ -1521,7 +1503,7 @@ dns_dispatch_getnext(dns_dispentry_t *resp) {
return (ISC_R_TIMEDOUT);
}
LOCK(&disp->lock);
REQUIRE(disp->tid == isc_tid());
switch (disp->socktype) {
case isc_socktype_udp:
udp_dispatch_getnext(resp, timeout);
@ -1532,7 +1514,6 @@ dns_dispatch_getnext(dns_dispentry_t *resp) {
default:
UNREACHABLE();
}
UNLOCK(&disp->lock);
return (result);
}
@ -1549,10 +1530,10 @@ udp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) {
dns_dispatch_t *disp = resp->disp;
bool respond = false;
LOCK(&disp->lock);
REQUIRE(disp->tid == isc_tid());
dispentry_log(resp, LVL(90),
"canceling response: %s, %s/%s (%s/%s), "
"requests %u",
"requests %" PRIuFAST32,
isc_result_totext(result), state2str(resp->state),
resp->reading ? "reading" : "not reading",
state2str(disp->state),
@ -1593,8 +1574,6 @@ udp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) {
resp->state = DNS_DISPATCHSTATE_CANCELED;
unlock:
UNLOCK(&disp->lock);
if (respond) {
dispentry_log(resp, LVL(90), "read callback: %s",
isc_result_totext(result));
@ -1614,10 +1593,10 @@ tcp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) {
dns_dispatch_t *disp = resp->disp;
dns_displist_t resps = ISC_LIST_INITIALIZER;
LOCK(&disp->lock);
REQUIRE(disp->tid == isc_tid());
dispentry_log(resp, LVL(90),
"canceling response: %s, %s/%s (%s/%s), "
"requests %u",
"requests %" PRIuFAST32,
isc_result_totext(result), state2str(resp->state),
resp->reading ? "reading" : "not reading",
state2str(disp->state),
@ -1692,7 +1671,6 @@ tcp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) {
resp->state = DNS_DISPATCHSTATE_CANCELED;
unlock:
UNLOCK(&disp->lock);
/*
* NOTE: Calling the response callback directly from here should be done
@ -1797,7 +1775,7 @@ tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
localbuf, peerbuf, isc_result_totext(eresult));
}
LOCK(&disp->lock);
REQUIRE(disp->tid == isc_tid());
INSIST(disp->state == DNS_DISPATCHSTATE_CONNECTING);
/*
@ -1833,8 +1811,6 @@ tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
disp->state = DNS_DISPATCHSTATE_NONE;
}
UNLOCK(&disp->lock);
for (resp = ISC_LIST_HEAD(resps); resp != NULL; resp = next) {
next = ISC_LIST_NEXT(resp, rlink);
ISC_LIST_UNLINK(resps, resp, rlink);
@ -1856,8 +1832,7 @@ udp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
dispentry_log(resp, LVL(90), "connected: %s",
isc_result_totext(eresult));
LOCK(&disp->lock);
REQUIRE(disp->tid == isc_tid());
switch (resp->state) {
case DNS_DISPATCHSTATE_CANCELED:
eresult = ISC_R_CANCELED;
@ -1885,7 +1860,6 @@ udp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
/* probably a port collision; try a different one */
result = setup_socket(disp, resp, &resp->peer, &localport);
if (result == ISC_R_SUCCESS) {
UNLOCK(&disp->lock);
udp_dispatch_connect(disp, resp);
goto detach;
}
@ -1897,7 +1871,6 @@ udp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
break;
}
unlock:
UNLOCK(&disp->lock);
dispentry_log(resp, LVL(90), "connect callback: %s",
isc_result_totext(eresult));
@ -1909,12 +1882,11 @@ detach:
static void
udp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) {
LOCK(&disp->lock);
REQUIRE(disp->tid == isc_tid());
resp->state = DNS_DISPATCHSTATE_CONNECTING;
resp->start = isc_loop_now(resp->loop);
dns_dispentry_ref(resp); /* DISPENTRY004 */
ISC_LIST_APPEND(disp->pending, resp, plink);
UNLOCK(&disp->lock);
isc_nm_udpconnect(disp->mgr->nm, &resp->local, &resp->peer,
udp_connected, resp, resp->timeout);
@ -1944,7 +1916,7 @@ tcp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) {
}
/* Check whether the dispatch is already connecting or connected. */
LOCK(&disp->lock);
REQUIRE(disp->tid == isc_tid());
switch (disp->state) {
case DNS_DISPATCHSTATE_NONE:
/* First connection, continue with connecting */
@ -1953,7 +1925,6 @@ tcp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) {
resp->start = isc_loop_now(resp->loop);
dns_dispentry_ref(resp); /* DISPENTRY005 */
ISC_LIST_APPEND(disp->pending, resp, plink);
UNLOCK(&disp->lock);
char localbuf[ISC_SOCKADDR_FORMATSIZE];
char peerbuf[ISC_SOCKADDR_FORMATSIZE];
@ -1979,7 +1950,6 @@ tcp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) {
resp->start = isc_loop_now(resp->loop);
dns_dispentry_ref(resp); /* DISPENTRY005 */
ISC_LIST_APPEND(disp->pending, resp, plink);
UNLOCK(&disp->lock);
break;
case DNS_DISPATCHSTATE_CONNECTED:
@ -1996,7 +1966,6 @@ tcp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) {
tcp_startrecv(disp, resp);
}
UNLOCK(&disp->lock);
/* We are already connected; call the connected cb */
dispentry_log(resp, LVL(90), "connect callback: %s",
isc_result_totext(ISC_R_SUCCESS));
@ -2105,7 +2074,7 @@ dns_dispatch_resume(dns_dispentry_t *resp, uint16_t timeout) {
dispentry_log(resp, LVL(90), "resume");
LOCK(&disp->lock);
REQUIRE(disp->tid == isc_tid());
switch (disp->socktype) {
case isc_socktype_udp: {
udp_dispatch_getnext(resp, timeout);
@ -2119,8 +2088,6 @@ dns_dispatch_resume(dns_dispentry_t *resp, uint16_t timeout) {
default:
UNREACHABLE();
}
UNLOCK(&disp->lock);
}
void
@ -2180,31 +2147,25 @@ dns_dispentry_getlocaladdress(dns_dispentry_t *resp, isc_sockaddr_t *addrp) {
dns_dispatch_t *
dns_dispatchset_get(dns_dispatchset_t *dset) {
dns_dispatch_t *disp = NULL;
uint32_t tid = isc_tid();
/* check that dispatch set is configured */
if (dset == NULL || dset->ndisp == 0) {
return (NULL);
}
LOCK(&dset->lock);
disp = dset->dispatches[dset->cur];
dset->cur++;
if (dset->cur == dset->ndisp) {
dset->cur = 0;
}
UNLOCK(&dset->lock);
INSIST(tid < dset->ndisp);
return (disp);
return (dset->dispatches[tid]);
}
isc_result_t
dns_dispatchset_create(isc_mem_t *mctx, dns_dispatch_t *source,
dns_dispatchset_t **dsetp, int n) {
dns_dispatchset_t **dsetp, uint32_t ndisp) {
isc_result_t result;
dns_dispatchset_t *dset = NULL;
dns_dispatchmgr_t *mgr = NULL;
int i, j;
size_t i;
REQUIRE(VALID_DISPATCH(source));
REQUIRE(source->socktype == isc_socktype_udp);
@ -2213,21 +2174,19 @@ dns_dispatchset_create(isc_mem_t *mctx, dns_dispatch_t *source,
mgr = source->mgr;
dset = isc_mem_get(mctx, sizeof(dns_dispatchset_t));
*dset = (dns_dispatchset_t){ .ndisp = n };
isc_mutex_init(&dset->lock);
dset->dispatches = isc_mem_cget(mctx, n, sizeof(dns_dispatch_t *));
*dset = (dns_dispatchset_t){ .ndisp = ndisp };
isc_mem_attach(mctx, &dset->mctx);
dset->dispatches = isc_mem_cget(dset->mctx, ndisp,
sizeof(dns_dispatch_t *));
dset->dispatches[0] = NULL;
dns_dispatch_attach(source, &dset->dispatches[0]); /* DISPATCH004 */
LOCK(&mgr->lock);
for (i = 1; i < n; i++) {
dset->dispatches[i] = NULL;
result = dispatch_createudp(mgr, &source->local,
for (i = 1; i < dset->ndisp; i++) {
result = dispatch_createudp(mgr, &source->local, i,
&dset->dispatches[i]);
if (result != ISC_R_SUCCESS) {
goto fail;
@ -2242,34 +2201,28 @@ dns_dispatchset_create(isc_mem_t *mctx, dns_dispatch_t *source,
fail:
UNLOCK(&mgr->lock);
for (j = 0; j < i; j++) {
for (size_t j = 0; j < i; j++) {
dns_dispatch_detach(&(dset->dispatches[j])); /* DISPATCH004 */
}
isc_mem_cput(mctx, dset->dispatches, n, sizeof(dns_dispatch_t *));
if (dset->mctx == mctx) {
isc_mem_detach(&dset->mctx);
}
isc_mem_cput(dset->mctx, dset->dispatches, ndisp,
sizeof(dns_dispatch_t *));
isc_mutex_destroy(&dset->lock);
isc_mem_put(mctx, dset, sizeof(dns_dispatchset_t));
isc_mem_putanddetach(&dset->mctx, dset, sizeof(dns_dispatchset_t));
return (result);
}
void
dns_dispatchset_destroy(dns_dispatchset_t **dsetp) {
dns_dispatchset_t *dset = NULL;
int i;
REQUIRE(dsetp != NULL && *dsetp != NULL);
dset = *dsetp;
dns_dispatchset_t *dset = *dsetp;
*dsetp = NULL;
for (i = 0; i < dset->ndisp; i++) {
for (size_t i = 0; i < dset->ndisp; i++) {
dns_dispatch_detach(&(dset->dispatches[i])); /* DISPATCH004 */
}
isc_mem_cput(dset->mctx, dset->dispatches, dset->ndisp,
sizeof(dns_dispatch_t *));
isc_mutex_destroy(&dset->lock);
isc_mem_putanddetach(&dset->mctx, dset, sizeof(dns_dispatchset_t));
}

View file

@ -69,9 +69,7 @@ ISC_LANG_BEGINDECLS
struct dns_dispatchset {
isc_mem_t *mctx;
dns_dispatch_t **dispatches;
int ndisp;
int cur;
isc_mutex_t lock;
uint32_t ndisp;
};
/*
@ -358,7 +356,7 @@ dns_dispatchset_get(dns_dispatchset_t *dset);
isc_result_t
dns_dispatchset_create(isc_mem_t *mctx, dns_dispatch_t *source,
dns_dispatchset_t **dsetp, int n);
dns_dispatchset_t **dsetp, uint32_t n);
/*%<
* Given a valid dispatch 'source', create a dispatch set containing
* 'n' UDP dispatches, with the remainder filled out by clones of the

View file

@ -165,9 +165,8 @@ enum {
#define DNS_QMIN_MAX_NO_DELEGATION 3
isc_result_t
dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
unsigned int ndisp, isc_nm_t *nm, unsigned int options,
isc_tlsctx_cache_t *tlsctx_cache,
dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr, isc_nm_t *nm,
unsigned int options, isc_tlsctx_cache_t *tlsctx_cache,
dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
dns_resolver_t **resp);
@ -183,17 +182,15 @@ dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
*
*\li 'view' is a valid view.
*
*\li 'ndisp' > 0.
*
*\li 'nm' is a valid network manager.
*
*\li 'tlsctx_cache' != NULL.
*
*\li 'dispatchv4' is a dispatch with an IPv4 UDP socket, or is NULL.
* If not NULL, 'ndisp' clones of it will be created by the resolver.
* If not NULL, clones per loop of it will be created by the resolver.
*
*\li 'dispatchv6' is a dispatch with an IPv6 UDP socket, or is NULL.
* If not NULL, 'ndisp' clones of it will be created by the resolver.
* If not NULL, clones per loop of it will be created by the resolver.
*
*\li resp != NULL && *resp == NULL.
*

View file

@ -365,8 +365,8 @@ dns_view_weakdetach(dns_view_t **targetp);
isc_result_t
dns_view_createresolver(dns_view_t *view, isc_loopmgr_t *loopmgr,
unsigned int ndisp, isc_nm_t *netmgr,
unsigned int options, isc_tlsctx_cache_t *tlsctx_cache,
isc_nm_t *netmgr, unsigned int options,
isc_tlsctx_cache_t *tlsctx_cache,
dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6);
/*%<
* Create a resolver and address database for the view.

View file

@ -54,8 +54,8 @@ struct dns_requestmgr {
atomic_bool shuttingdown;
dns_dispatchmgr_t *dispatchmgr;
dns_dispatch_t *dispatchv4;
dns_dispatch_t *dispatchv6;
dns_dispatchset_t *dispatches4;
dns_dispatchset_t *dispatches6;
dns_requestlist_t *requests;
};
@ -150,10 +150,14 @@ dns_requestmgr_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr,
dns_dispatchmgr_attach(dispatchmgr, &requestmgr->dispatchmgr);
if (dispatchv4 != NULL) {
dns_dispatch_attach(dispatchv4, &requestmgr->dispatchv4);
dns_dispatchset_create(requestmgr->mctx, dispatchv4,
&requestmgr->dispatches4,
isc_loopmgr_nloops(requestmgr->loopmgr));
}
if (dispatchv6 != NULL) {
dns_dispatch_attach(dispatchv6, &requestmgr->dispatchv6);
dns_dispatchset_create(requestmgr->mctx, dispatchv6,
&requestmgr->dispatches6,
isc_loopmgr_nloops(requestmgr->loopmgr));
}
isc_refcount_init(&requestmgr->references, 1);
@ -232,11 +236,11 @@ requestmgr_destroy(dns_requestmgr_t *requestmgr) {
isc_mem_cput(requestmgr->mctx, requestmgr->requests, nloops,
sizeof(requestmgr->requests[0]));
if (requestmgr->dispatchv4 != NULL) {
dns_dispatch_detach(&requestmgr->dispatchv4);
if (requestmgr->dispatches4 != NULL) {
dns_dispatchset_destroy(&requestmgr->dispatches4);
}
if (requestmgr->dispatchv6 != NULL) {
dns_dispatch_detach(&requestmgr->dispatchv6);
if (requestmgr->dispatches6 != NULL) {
dns_dispatchset_destroy(&requestmgr->dispatches6);
}
if (requestmgr->dispatchmgr != NULL) {
dns_dispatchmgr_detach(&requestmgr->dispatchmgr);
@ -360,11 +364,11 @@ udp_dispatch(dns_requestmgr_t *requestmgr, const isc_sockaddr_t *srcaddr,
if (srcaddr == NULL) {
switch (isc_sockaddr_pf(destaddr)) {
case PF_INET:
disp = requestmgr->dispatchv4;
disp = dns_dispatchset_get(requestmgr->dispatches4);
break;
case PF_INET6:
disp = requestmgr->dispatchv6;
disp = dns_dispatchset_get(requestmgr->dispatches6);
break;
default:

View file

@ -9930,9 +9930,8 @@ spillattimer_countdown(void *arg) {
}
isc_result_t
dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
unsigned int ndisp, isc_nm_t *nm, unsigned int options,
isc_tlsctx_cache_t *tlsctx_cache,
dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr, isc_nm_t *nm,
unsigned int options, isc_tlsctx_cache_t *tlsctx_cache,
dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
dns_resolver_t **resp) {
dns_resolver_t *res = NULL;
@ -9942,7 +9941,6 @@ dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
*/
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(ndisp > 0);
REQUIRE(resp != NULL && *resp == NULL);
REQUIRE(tlsctx_cache != NULL);
REQUIRE(dispatchv4 != NULL || dispatchv6 != NULL);
@ -9989,12 +9987,12 @@ dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
if (dispatchv4 != NULL) {
dns_dispatchset_create(res->mctx, dispatchv4, &res->dispatches4,
ndisp);
isc_loopmgr_nloops(res->loopmgr));
}
if (dispatchv6 != NULL) {
dns_dispatchset_create(res->mctx, dispatchv6, &res->dispatches6,
ndisp);
isc_loopmgr_nloops(res->loopmgr));
}
isc_mutex_init(&res->lock);

View file

@ -589,8 +589,8 @@ dns_view_weakdetach(dns_view_t **viewp) {
isc_result_t
dns_view_createresolver(dns_view_t *view, isc_loopmgr_t *loopmgr,
unsigned int ndisp, isc_nm_t *netmgr,
unsigned int options, isc_tlsctx_cache_t *tlsctx_cache,
isc_nm_t *netmgr, unsigned int options,
isc_tlsctx_cache_t *tlsctx_cache,
dns_dispatch_t *dispatchv4,
dns_dispatch_t *dispatchv6) {
isc_result_t result;
@ -601,7 +601,7 @@ dns_view_createresolver(dns_view_t *view, isc_loopmgr_t *loopmgr,
REQUIRE(view->resolver == NULL);
REQUIRE(view->dispatchmgr != NULL);
result = dns_resolver_create(view, loopmgr, ndisp, netmgr, options,
result = dns_resolver_create(view, loopmgr, netmgr, options,
tlsctx_cache, dispatchv4, dispatchv6,
&view->resolver);
if (result != ISC_R_SUCCESS) {

View file

@ -28,11 +28,11 @@ isc_tid_count(void);
* Returns the number of threads.
*/
extern thread_local uint32_t tid_local;
extern thread_local uint32_t isc__tid_local;
static inline uint32_t
isc_tid(void) {
return (tid_local);
return (isc__tid_local);
}
/*%<
* Returns the thread ID of the currently-running loop.

View file

@ -23,7 +23,7 @@
/**
* Private
*/
thread_local uint32_t tid_local = ISC_TID_UNKNOWN;
thread_local uint32_t isc__tid_local = ISC_TID_UNKNOWN;
/*
* Zero is a better nonsense value in this case than ISC_TID_UNKNOWN;
@ -37,8 +37,8 @@ static uint32_t tid_count = 0;
void
isc__tid_init(uint32_t tid) {
REQUIRE(tid_local == ISC_TID_UNKNOWN || tid_local == tid);
tid_local = tid;
REQUIRE(isc__tid_local == ISC_TID_UNKNOWN || isc__tid_local == tid);
isc__tid_local = tid;
}
void

View file

@ -65,9 +65,6 @@
#define NS_INTERFACEFLAG_ANYADDR 0x01U /*%< bound to "any" address */
#define NS_INTERFACEFLAG_LISTENING 0x02U /*%< listening */
#define MAX_UDP_DISPATCH \
128 /*%< Maximum number of UDP dispatchers \
* to start per interface */
/*% The nameserver interface structure */
struct ns_interface {
unsigned int magic; /*%< Magic number. */

View file

@ -261,11 +261,12 @@ ISC_LOOP_TEST_IMPL(dispatchset_create) {
isc_loopmgr_shutdown(loopmgr);
}
/* test dispatch set round-robin */
/* test dispatch set per-loop dispatch */
ISC_LOOP_TEST_IMPL(dispatchset_get) {
isc_result_t result;
dns_dispatchset_t *dset = NULL;
dns_dispatch_t *d1, *d2, *d3, *d4, *d5;
uint32_t tid_saved;
UNUSED(arg);
@ -291,10 +292,21 @@ ISC_LOOP_TEST_IMPL(dispatchset_get) {
result = make_dispatchset(4, &dset);
assert_int_equal(result, ISC_R_SUCCESS);
/*
* Temporarily modify and then restore the current thread's
* ID value, in order to confirm that different threads get
* different dispatch sets but the same thread gets the same
* one.
*/
tid_saved = isc__tid_local;
d1 = dns_dispatchset_get(dset);
isc__tid_local++;
d2 = dns_dispatchset_get(dset);
isc__tid_local++;
d3 = dns_dispatchset_get(dset);
isc__tid_local++;
d4 = dns_dispatchset_get(dset);
isc__tid_local = tid_saved;
d5 = dns_dispatchset_get(dset);
assert_ptr_equal(d1, d5);

View file

@ -76,7 +76,7 @@ mkres(dns_resolver_t **resolverp) {
isc_result_t result;
isc_tlsctx_cache_create(mctx, &tlsctx_cache);
result = dns_resolver_create(view, loopmgr, 1, netmgr, 0, tlsctx_cache,
result = dns_resolver_create(view, loopmgr, netmgr, 0, tlsctx_cache,
dispatch, NULL, resolverp);
assert_int_equal(result, ISC_R_SUCCESS);
}