From: Ondřej Surý Date: Sat, 22 May 2021 16:12:11 +0000 (+0200) Subject: Reduce the number of clientmgr objects created X-Git-Tag: v9.17.14~30^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=28b65d8256ffcf7adac1c14db4cf90cd0aec5598;p=thirdparty%2Fbind9.git Reduce the number of clientmgr objects created Previously, as a way of reducing the contention between threads a clientmgr object would be created for each interface/IP address. We tasks being more strictly bound to netmgr workers, this is no longer needed and we can just create clientmgr object per worker queue (ncpus). Each clientmgr object than would have a single task and single memory context. --- diff --git a/bin/named/server.c b/bin/named/server.c index 9bcf3aa3062..07f853fa959 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -5081,8 +5081,8 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, /* * Copy the aclenv object. */ - dns_aclenv_copy(&view->aclenv, ns_interfacemgr_getaclenv( - named_g_server->interfacemgr)); + dns_aclenv_copy(view->aclenv, ns_interfacemgr_getaclenv( + named_g_server->interfacemgr)); /* * Configure the "match-clients" and "match-destinations" ACL. diff --git a/lib/dns/acl.c b/lib/dns/acl.c index 21eeb25f60e..33fcefef0a8 100644 --- a/lib/dns/acl.c +++ b/lib/dns/acl.c @@ -22,6 +22,9 @@ #include #include +#define DNS_ACLENV_MAGIC ISC_MAGIC('a', 'c', 'n', 'v') +#define VALID_ACLENV(a) ISC_MAGIC_VALID(a, DNS_ACLENV_MAGIC) + /* * Create a new ACL, including an IP table and an array with room * for 'n' ACL elements. The elements are uninitialized and the @@ -617,11 +620,14 @@ dns_acl_allowed(isc_netaddr_t *addr, const dns_name_t *signer, dns_acl_t *acl, * Initialize ACL environment, setting up localhost and localnets ACLs */ isc_result_t -dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env) { +dns_aclenv_create(isc_mem_t *mctx, dns_aclenv_t **envp) { isc_result_t result; + dns_aclenv_t *env = isc_mem_get(mctx, sizeof(*env)); + *env = (dns_aclenv_t){ 0 }; + + isc_mem_attach(mctx, &env->mctx); + isc_refcount_init(&env->references, 1); - env->localhost = NULL; - env->localnets = NULL; result = dns_acl_create(mctx, 0, &env->localhost); if (result != ISC_R_SUCCESS) { goto cleanup_nothing; @@ -634,6 +640,11 @@ dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env) { #if defined(HAVE_GEOIP2) env->geoip = NULL; #endif /* if defined(HAVE_GEOIP2) */ + + env->magic = DNS_ACLENV_MAGIC; + + *envp = env; + return (ISC_R_SUCCESS); cleanup_localhost: @@ -644,22 +655,55 @@ cleanup_nothing: void dns_aclenv_copy(dns_aclenv_t *t, dns_aclenv_t *s) { + REQUIRE(VALID_ACLENV(s)); + REQUIRE(VALID_ACLENV(t)); + dns_acl_detach(&t->localhost); dns_acl_attach(s->localhost, &t->localhost); dns_acl_detach(&t->localnets); dns_acl_attach(s->localnets, &t->localnets); + t->match_mapped = s->match_mapped; #if defined(HAVE_GEOIP2) t->geoip = s->geoip; #endif /* if defined(HAVE_GEOIP2) */ } -void -dns_aclenv_destroy(dns_aclenv_t *env) { - if (env->localhost != NULL) { - dns_acl_detach(&env->localhost); +static void +dns__aclenv_destroy(dns_aclenv_t *aclenv) { + REQUIRE(VALID_ACLENV(aclenv)); + + aclenv->magic = 0; + + if (aclenv->localhost != NULL) { + dns_acl_detach(&aclenv->localhost); + } + if (aclenv->localnets != NULL) { + dns_acl_detach(&aclenv->localnets); } - if (env->localnets != NULL) { - dns_acl_detach(&env->localnets); + + isc_mem_putanddetach(&aclenv->mctx, aclenv, sizeof(*aclenv)); +} + +void +dns_aclenv_attach(dns_aclenv_t *source, dns_aclenv_t **targetp) { + REQUIRE(VALID_ACLENV(source)); + REQUIRE(targetp != NULL && *targetp == NULL); + + isc_refcount_increment(&source->references); + *targetp = source; +} + +void +dns_aclenv_detach(dns_aclenv_t **aclenvp) { + dns_aclenv_t *aclenv = NULL; + + REQUIRE(aclenvp != NULL && VALID_ACLENV(*aclenvp)); + + aclenv = *aclenvp; + *aclenvp = NULL; + + if (isc_refcount_decrement(&aclenv->references) == 1) { + dns__aclenv_destroy(aclenv); } } diff --git a/lib/dns/include/dns/acl.h b/lib/dns/include/dns/acl.h index 3070a35bac0..adbead90f5b 100644 --- a/lib/dns/include/dns/acl.h +++ b/lib/dns/include/dns/acl.h @@ -87,9 +87,12 @@ struct dns_acl { }; struct dns_aclenv { - dns_acl_t *localhost; - dns_acl_t *localnets; - bool match_mapped; + unsigned int magic; + isc_mem_t * mctx; + isc_refcount_t references; + dns_acl_t * localhost; + dns_acl_t * localnets; + bool match_mapped; #if defined(HAVE_GEOIP2) dns_geoip_databases_t *geoip; #endif /* HAVE_GEOIP2 */ @@ -191,16 +194,38 @@ dns_acl_allowed(isc_netaddr_t *addr, const dns_name_t *signer, dns_acl_t *acl, */ isc_result_t -dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env); +dns_aclenv_create(isc_mem_t *mctx, dns_aclenv_t **envp); /*%< - * Initialize ACL environment, setting up localhost and localnets ACLs + * Create ACL environment, setting up localhost and localnets ACLs */ void dns_aclenv_copy(dns_aclenv_t *t, dns_aclenv_t *s); +/*%< + * Copy the ACLs from one ACL environment object to another. + * + * Requires: + *\li both 's' and 't' are valid ACL environments. + */ + +void +dns_aclenv_attach(dns_aclenv_t *source, dns_aclenv_t **targetp); +/*%< + * Attach '*targetp' to ACL environment 'source'. + * + * Requires: + *\li 'source' is a valid ACL environment. + *\li 'targetp' is not NULL and '*targetp' is NULL. + */ void -dns_aclenv_destroy(dns_aclenv_t *env); +dns_aclenv_detach(dns_aclenv_t **aclenvp); +/*%< + * Detach an ACL environment; on final detach, destroy it. + * + * Requires: + *\li '*aclenvp' to be a valid ACL environment + */ isc_result_t dns_acl_match(const isc_netaddr_t *reqaddr, const dns_name_t *reqsigner, diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index 575b57e4cfd..bfe9abd763f 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -163,7 +163,7 @@ struct dns_view { dns_ttl_t prefetch_trigger; dns_ttl_t prefetch_eligible; in_port_t dstport; - dns_aclenv_t aclenv; + dns_aclenv_t * aclenv; dns_rdatatype_t preferred_glue; bool flush; dns_namelist_t * delonly; diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 53b76e9974f..294678d046f 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -3933,7 +3933,7 @@ possibly_mark(fetchctx_t *fctx, dns_adbaddrinfo_t *addr) { if (blackhole != NULL) { int match; - if ((dns_acl_match(&ipaddr, NULL, blackhole, &res->view->aclenv, + if ((dns_acl_match(&ipaddr, NULL, blackhole, res->view->aclenv, &match, NULL) == ISC_R_SUCCESS) && match > 0) { @@ -7165,7 +7165,7 @@ is_answeraddress_allowed(dns_view_t *view, dns_name_t *name, } result = dns_acl_match(&netaddr, NULL, view->denyansweracl, - &view->aclenv, &match, NULL); + view->aclenv, &match, NULL); if (result == ISC_R_SUCCESS && match > 0) { isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf)); dns_name_format(name, namebuf, sizeof(namebuf)); diff --git a/lib/dns/rrl.c b/lib/dns/rrl.c index 0bde96a7c4d..9c009b2fdc2 100644 --- a/lib/dns/rrl.c +++ b/lib/dns/rrl.c @@ -1048,7 +1048,7 @@ dns_rrl(dns_view_t *view, const isc_sockaddr_t *client_addr, bool is_tcp, if (rrl->exempt != NULL) { isc_netaddr_fromsockaddr(&netclient, client_addr); result = dns_acl_match(&netclient, NULL, rrl->exempt, - &view->aclenv, &exempt_match, NULL); + view->aclenv, &exempt_match, NULL); if (result == ISC_R_SUCCESS && exempt_match > 0) { return (DNS_RRL_RESULT_OK); } diff --git a/lib/dns/view.c b/lib/dns/view.c index 0d2f8545097..dacb875a53d 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -274,7 +274,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, const char *name, goto cleanup_order; } - result = dns_aclenv_init(view->mctx, &view->aclenv); + result = dns_aclenv_create(view->mctx, &view->aclenv); if (result != ISC_R_SUCCESS) { goto cleanup_peerlist; } @@ -590,7 +590,7 @@ destroy(dns_view_t *view) { } #endif /* HAVE_LMDB */ dns_fwdtable_destroy(&view->fwdtable); - dns_aclenv_destroy(&view->aclenv); + dns_aclenv_detach(&view->aclenv); if (view->failcache != NULL) { dns_badcache_destroy(&view->failcache); } diff --git a/lib/dns/win32/libdns.def.in b/lib/dns/win32/libdns.def.in index 1683cccb7de..ab01b696df0 100644 --- a/lib/dns/win32/libdns.def.in +++ b/lib/dns/win32/libdns.def.in @@ -24,9 +24,10 @@ dns_acl_match dns_acl_merge dns_acl_none dns_aclelement_match +dns_aclenv_attach dns_aclenv_copy -dns_aclenv_destroy -dns_aclenv_init +dns_aclenv_create +dns_aclenv_detach dns_adb_adjustsrtt dns_adb_agesrtt dns_adb_attach diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 775a8f00349..9084a434b98 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15170,7 +15170,7 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from, if (isc_sockaddr_eqaddr(from, &zone->masters[i])) { break; } - if (zone->view->aclenv.match_mapped && + if (zone->view->aclenv->match_mapped && IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) && isc_sockaddr_pf(&zone->masters[i]) == AF_INET) { @@ -15190,9 +15190,8 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from, tsigkey = dns_message_gettsigkey(msg); tsig = dns_tsigkey_identity(tsigkey); if (i >= zone->masterscnt && zone->notify_acl != NULL && - (dns_acl_match(&netaddr, tsig, zone->notify_acl, - &zone->view->aclenv, &match, - NULL) == ISC_R_SUCCESS) && + (dns_acl_match(&netaddr, tsig, zone->notify_acl, zone->view->aclenv, + &match, NULL) == ISC_R_SUCCESS) && match > 0) { /* Accept notify. */ diff --git a/lib/isc/include/isc/netmgr.h b/lib/isc/include/isc/netmgr.h index 89ef001a716..864dea92f49 100644 --- a/lib/isc/include/isc/netmgr.h +++ b/lib/isc/include/isc/netmgr.h @@ -528,3 +528,10 @@ isc_nm_task_enqueue(isc_nm_t *mgr, isc_task_t *task, int threadid); * tid will be picked randomly. The threadid is capped (by modulo) to * maximum number of 'workers' as specifed in isc_nm_start() */ + +void +isc__nm_force_tid(int tid); +/*%< + * Force the thread ID to 'tid'. This is STRICTLY for use in unit + * tests and should not be used in any production code. + */ diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index 0ad9bd42c8c..907896ac72e 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -1111,7 +1111,7 @@ struct isc_nmsocket { bool isc__nm_in_netthread(void); -/*% +/*%< * Returns 'true' if we're in the network thread. */ diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index 2662b22050e..063f7a892dd 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -216,6 +216,11 @@ isc__nm_in_netthread(void) { return (isc__nm_tid_v >= 0); } +void +isc__nm_force_tid(int tid) { + isc__nm_tid_v = tid; +} + #ifdef WIN32 static void isc__nm_winsock_initialize(void) { diff --git a/lib/isc/win32/libisc.def.in b/lib/isc/win32/libisc.def.in index ff7df3c51ca..fdf402a572a 100644 --- a/lib/isc/win32/libisc.def.in +++ b/lib/isc/win32/libisc.def.in @@ -440,6 +440,7 @@ isc_netaddr_setzone isc_netaddr_totext isc_netaddr_unspec isc_netscope_pton +isc__nm_force_tid isc__nmhandle_attach isc__nmhandle_detach isc_nmhandle_cleartimeout diff --git a/lib/ns/client.c b/lib/ns/client.c index 66f184a1eb6..ba3c3116731 100644 --- a/lib/ns/client.c +++ b/lib/ns/client.c @@ -132,8 +132,6 @@ ns_client_dumpmessage(ns_client_t *client, const char *reason); static void compute_cookie(ns_client_t *client, uint32_t when, uint32_t nonce, const unsigned char *secret, isc_buffer_t *buf); -static void -get_clienttask(ns_clientmgr_t *manager, isc_task_t **taskp); void ns_client_recursing(ns_client_t *client) { @@ -321,10 +319,10 @@ client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) { void ns_client_sendraw(ns_client_t *client, dns_message_t *message) { isc_result_t result; - unsigned char *data; + unsigned char *data = NULL; isc_buffer_t buffer; isc_region_t r; - isc_region_t *mr; + isc_region_t *mr = NULL; REQUIRE(NS_CLIENT_VALID(client)); @@ -387,7 +385,7 @@ done: void ns_client_send(ns_client_t *client) { isc_result_t result; - unsigned char *data; + unsigned char *data = NULL; isc_buffer_t buffer = { .magic = 0 }; isc_region_t r; dns_compress_t cctx; @@ -396,7 +394,7 @@ ns_client_send(ns_client_t *client) { unsigned int preferred_glue; bool opt_included = false; size_t respsize; - dns_aclenv_t *env; + dns_aclenv_t *env = NULL; #ifdef HAVE_DNSTAP unsigned char zone[DNS_NAME_MAXWIRE]; dns_dtmsgtype_t dtmsgtype; @@ -414,7 +412,7 @@ ns_client_send(ns_client_t *client) { * Delay the response according to the -T delay option */ - env = ns_interfacemgr_getaclenv(client->manager->interface->mgr); + env = client->manager->aclenv; CTRACE("send"); @@ -876,24 +874,24 @@ isc_result_t ns_client_addopt(ns_client_t *client, dns_message_t *message, dns_rdataset_t **opt) { unsigned char ecs[ECS_SIZE]; - char nsid[BUFSIZ], *nsidp; + char nsid[BUFSIZ], *nsidp = NULL; unsigned char cookie[COOKIE_SIZE]; isc_result_t result; - dns_view_t *view; - dns_resolver_t *resolver; + dns_view_t *view = NULL; + dns_resolver_t *resolver = NULL; uint16_t udpsize; dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS]; int count = 0; unsigned int flags; unsigned char expire[4]; unsigned char advtimo[2]; - dns_aclenv_t *env; + dns_aclenv_t *env = NULL; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(opt != NULL && *opt == NULL); REQUIRE(message != NULL); - env = ns_interfacemgr_getaclenv(client->manager->interface->mgr); + env = client->manager->aclenv; view = client->view; resolver = (view != NULL) ? view->resolver : NULL; if (resolver != NULL) { @@ -1569,10 +1567,6 @@ ns__client_put_cb(void *client0) { client->magic = 0; client->shuttingdown = true; - if (client->manager != NULL) { - clientmgr_detach(&client->manager); - } - isc_mem_put(client->mctx, client->sendbuf, NS_CLIENT_SEND_BUFFER_SIZE); if (client->opt != NULL) { INSIST(dns_rdataset_isassociated(client->opt)); @@ -1582,6 +1576,10 @@ ns__client_put_cb(void *client0) { dns_message_detach(&client->message); + if (client->manager != NULL) { + clientmgr_detach(&client->manager); + } + /* * Detaching the task must be done after unlinking from * the manager's lists because the manager accesses @@ -1601,9 +1599,7 @@ ns__client_put_cb(void *client0) { ns_server_detach(&client->sctx); } - if (client->mctx != NULL) { - isc_mem_detach(&client->mctx); - } + isc_mem_detach(&client->mctx); } /* @@ -1628,6 +1624,7 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult, bool notimp; size_t reqsize; dns_aclenv_t *env = NULL; + isc_sockaddr_t sockaddr; #ifdef HAVE_DNSTAP dns_dtmsgtype_t dtmsgtype; #endif /* ifdef HAVE_DNSTAP */ @@ -1639,12 +1636,14 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult, client = isc_nmhandle_getdata(handle); if (client == NULL) { ns_interface_t *ifp = (ns_interface_t *)arg; + ns_clientmgr_t *clientmgr = + ns_interfacemgr_getclientmgr(ifp->mgr); - INSIST(VALID_MANAGER(ifp->clientmgr)); + INSIST(VALID_MANAGER(clientmgr)); client = isc_nmhandle_getextra(handle); - result = ns__client_setup(client, ifp->clientmgr, true); + result = ns__client_setup(client, clientmgr, true); if (result != ISC_R_SUCCESS) { return; } @@ -1705,7 +1704,7 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult, } #endif /* if NS_CLIENT_DROPPORT */ - env = ns_interfacemgr_getaclenv(client->manager->interface->mgr); + env = client->manager->aclenv; if (client->sctx->blackholeacl != NULL && (dns_acl_match(&netaddr, NULL, client->sctx->blackholeacl, env, &match, NULL) == ISC_R_SUCCESS) && @@ -1921,26 +1920,8 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult, return; } - /* - * Determine the destination address. If the receiving interface is - * bound to a specific address, we simply use it regardless of the - * address family. All IPv4 queries should fall into this case. - * Otherwise, if this is a TCP query, get the address from the - * receiving socket (this needs a system call and can be heavy). - * For IPv6 UDP queries, we get this from the pktinfo structure (if - * supported). - * - * If all the attempts fail (this can happen due to memory shortage, - * etc), we regard this as an error for safety. - */ - if ((client->manager->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0) - { - isc_netaddr_fromsockaddr(&client->destaddr, - &client->manager->interface->addr); - } else { - isc_sockaddr_t sockaddr = isc_nmhandle_localaddr(handle); - isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr); - } + sockaddr = isc_nmhandle_localaddr(handle); + isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr); isc_sockaddr_fromnetaddr(&client->destsockaddr, &client->destaddr, 0); @@ -2202,17 +2183,6 @@ ns__client_tcpconn(isc_nmhandle_t *handle, isc_result_t result, void *arg) { return (ISC_R_SUCCESS); } -static void -get_clienttask(ns_clientmgr_t *manager, isc_task_t **taskp) { - MTRACE("clienttask"); - - int tid = isc_nm_tid(); - REQUIRE(tid >= 0); - REQUIRE(tid < manager->ncpus); - - isc_task_attach(manager->taskpool[tid], taskp); -} - isc_result_t ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) { isc_result_t result; @@ -2225,16 +2195,17 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) { * The caller is responsible for that. */ - REQUIRE(NS_CLIENT_VALID(client) || (new &&client != NULL)); - REQUIRE(VALID_MANAGER(mgr) || !new); - if (new) { - *client = (ns_client_t){ .magic = 0 }; + REQUIRE(VALID_MANAGER(mgr)); + REQUIRE(client != NULL); + REQUIRE(mgr->tid == isc_nm_tid()); + + *client = (ns_client_t){ .magic = 0, .tid = mgr->tid }; isc_mem_attach(mgr->mctx, &client->mctx); clientmgr_attach(mgr, &client->manager); ns_server_attach(mgr->sctx, &client->sctx); - get_clienttask(mgr, &client->task); + isc_task_attach(mgr->task, &client->task); dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE, &client->message); @@ -2251,6 +2222,9 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) { goto cleanup; } } else { + REQUIRE(NS_CLIENT_VALID(client)); + REQUIRE(client->tid == isc_nm_tid()); + ns_clientmgr_t *oldmgr = client->manager; ns_server_t *sctx = client->sctx; isc_task_t *task = client->task; @@ -2258,6 +2232,7 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) { dns_message_t *message = client->message; isc_mem_t *oldmctx = client->mctx; ns_query_t query = client->query; + int tid = client->tid; /* * Retain these values from the existing client, but @@ -2270,7 +2245,8 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) { .task = task, .sendbuf = sendbuf, .message = message, - .query = query }; + .query = query, + .tid = tid }; } client->query.attributes &= ~NS_QUERYATTR_ANSWERED; @@ -2308,9 +2284,7 @@ cleanup: if (client->manager != NULL) { clientmgr_detach(&client->manager); } - if (client->mctx != NULL) { - isc_mem_detach(&client->mctx); - } + isc_mem_detach(&client->mctx); if (client->sctx != NULL) { ns_server_detach(&client->sctx); } @@ -2359,16 +2333,12 @@ clientmgr_detach(ns_clientmgr_t **mp) { static void clientmgr_destroy(ns_clientmgr_t *manager) { - int i; - MTRACE("clientmgr_destroy"); isc_refcount_destroy(&manager->references); manager->magic = 0; - if (manager->interface != NULL) { - ns_interface_detach(&manager->interface); - } + dns_aclenv_detach(&manager->aclenv); isc_mutex_destroy(&manager->lock); isc_mutex_destroy(&manager->reclock); @@ -2377,54 +2347,45 @@ clientmgr_destroy(ns_clientmgr_t *manager) { isc_task_detach(&manager->excl); } - for (i = 0; i < manager->ncpus; i++) { - if (manager->taskpool[i] != NULL) { - isc_task_detach(&manager->taskpool[i]); - } - } - isc_mem_put(manager->mctx, manager->taskpool, - manager->ncpus * sizeof(manager->taskpool[0])); + isc_task_detach(&manager->task); ns_server_detach(&manager->sctx); - isc_mem_put(manager->mctx, manager, sizeof(*manager)); + isc_mem_putanddetach(&manager->mctx, manager, sizeof(*manager)); } isc_result_t -ns_clientmgr_create(isc_mem_t *mctx, ns_server_t *sctx, isc_taskmgr_t *taskmgr, - isc_timermgr_t *timermgr, ns_interface_t *interface, - int ncpus, ns_clientmgr_t **managerp) { - ns_clientmgr_t *manager; +ns_clientmgr_create(ns_server_t *sctx, isc_taskmgr_t *taskmgr, + isc_timermgr_t *timermgr, dns_aclenv_t *aclenv, int tid, + ns_clientmgr_t **managerp) { + ns_clientmgr_t *manager = NULL; + isc_mem_t *mctx = NULL; isc_result_t result; - int i; - manager = isc_mem_get(mctx, sizeof(*manager)); - *manager = (ns_clientmgr_t){ .magic = 0 }; + isc_mem_create(&mctx); - isc_mutex_init(&manager->lock); - isc_mutex_init(&manager->reclock); + manager = isc_mem_get(mctx, sizeof(*manager)); + *manager = (ns_clientmgr_t){ .magic = 0, .mctx = mctx }; - manager->excl = NULL; result = isc_taskmgr_excltask(taskmgr, &manager->excl); if (result != ISC_R_SUCCESS) { - goto cleanup_reclock; + isc_mem_put(mctx, manager, sizeof(*manager)); + return (result); } - manager->mctx = mctx; + isc_mutex_init(&manager->lock); + isc_mutex_init(&manager->reclock); + manager->taskmgr = taskmgr; manager->timermgr = timermgr; - manager->ncpus = ncpus; + manager->tid = tid; - ns_interface_attach(interface, &manager->interface); + dns_aclenv_attach(aclenv, &manager->aclenv); manager->exiting = false; - manager->taskpool = isc_mem_get( - mctx, manager->ncpus * sizeof(manager->taskpool[0])); - for (i = 0; i < manager->ncpus; i++) { - manager->taskpool[i] = NULL; - result = isc_task_create_bound(manager->taskmgr, 20, - &manager->taskpool[i], i); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - } + result = isc_task_create_bound(manager->taskmgr, 20, &manager->task, + manager->tid); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + isc_refcount_init(&manager->references, 1); manager->sctx = NULL; ns_server_attach(sctx, &manager->sctx); @@ -2438,14 +2399,6 @@ ns_clientmgr_create(isc_mem_t *mctx, ns_server_t *sctx, isc_taskmgr_t *taskmgr, *managerp = manager; return (ISC_R_SUCCESS); - -cleanup_reclock: - isc_mutex_destroy(&manager->reclock); - isc_mutex_destroy(&manager->lock); - - isc_mem_put(mctx, manager, sizeof(*manager)); - - return (result); } void @@ -2496,8 +2449,7 @@ isc_result_t ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr, dns_acl_t *acl, bool default_allow) { isc_result_t result; - dns_aclenv_t *env = - ns_interfacemgr_getaclenv(client->manager->interface->mgr); + dns_aclenv_t *env = client->manager->aclenv; isc_netaddr_t tmpnetaddr; int match; diff --git a/lib/ns/include/ns/client.h b/lib/ns/include/ns/client.h index c107277f848..8a369585456 100644 --- a/lib/ns/include/ns/client.h +++ b/lib/ns/include/ns/client.h @@ -150,12 +150,12 @@ struct ns_clientmgr { isc_timermgr_t *timermgr; isc_task_t * excl; isc_refcount_t references; - int ncpus; + int tid; /* Attached by clients, needed for e.g. recursion */ - isc_task_t **taskpool; + isc_task_t *task; - ns_interface_t *interface; + dns_aclenv_t *aclenv; /* Lock covers manager state. */ isc_mutex_t lock; @@ -170,6 +170,7 @@ struct ns_clientmgr { struct ns_client { unsigned int magic; isc_mem_t * mctx; + int tid; bool allocated; /* Do we need to free it? */ ns_server_t * sctx; ns_clientmgr_t * manager; @@ -344,8 +345,8 @@ ns_client_settimeout(ns_client_t *client, unsigned int seconds); */ isc_result_t -ns_clientmgr_create(isc_mem_t *mctx, ns_server_t *sctx, isc_taskmgr_t *taskmgr, - isc_timermgr_t *timermgr, ns_interface_t *ifp, int ncpus, +ns_clientmgr_create(ns_server_t *sctx, isc_taskmgr_t *taskmgr, + isc_timermgr_t *timermgr, dns_aclenv_t *aclenv, int tid, ns_clientmgr_t **managerp); /*%< * Create a client manager. diff --git a/lib/ns/include/ns/interfacemgr.h b/lib/ns/include/ns/interfacemgr.h index 152ce4b76cc..c6482e2040a 100644 --- a/lib/ns/include/ns/interfacemgr.h +++ b/lib/ns/include/ns/interfacemgr.h @@ -9,8 +9,7 @@ * information regarding copyright ownership. */ -#ifndef NS_INTERFACEMGR_H -#define NS_INTERFACEMGR_H 1 +#pragma once /***** ***** Module Info @@ -91,8 +90,7 @@ struct ns_interface { * servicing TCP queries * (whether accepting or * connected) */ - int nudpdispatch; /*%< Number of UDP dispatches */ - ns_clientmgr_t *clientmgr; /*%< Client manager. */ + int nudpdispatch; /*%< Number of UDP dispatches */ ISC_LINK(ns_interface_t) link; }; @@ -205,12 +203,19 @@ ns_interfacemgr_getserver(ns_interfacemgr_t *mgr); * Returns the ns_server object associated with the interface manager. */ +ns_clientmgr_t * +ns_interfacemgr_getclientmgr(ns_interfacemgr_t *mgr); +/*%< + * + * Returns the client manager for the current worker thread. + * (This cannot be run from outside a network manager thread.) + */ + ns_interface_t * ns__interfacemgr_getif(ns_interfacemgr_t *mgr); ns_interface_t * ns__interfacemgr_nextif(ns_interface_t *ifp); -/* +/*%< * Functions to allow external callers to walk the interfaces list. * (Not intended for use outside this module and associated tests.) */ -#endif /* NS_INTERFACEMGR_H */ diff --git a/lib/ns/interfacemgr.c b/lib/ns/interfacemgr.c index 8ae657abce6..267b77acee7 100644 --- a/lib/ns/interfacemgr.c +++ b/lib/ns/interfacemgr.c @@ -67,28 +67,28 @@ /*% nameserver interface manager structure */ struct ns_interfacemgr { - unsigned int magic; /*%< Magic number. */ + unsigned int magic; /*%< Magic number */ isc_refcount_t references; isc_mutex_t lock; - isc_mem_t *mctx; /*%< Memory context. */ - ns_server_t *sctx; /*%< Server context. */ - isc_taskmgr_t *taskmgr; /*%< Task manager. */ - isc_task_t *excl; /*%< Exclusive task. */ - isc_timermgr_t *timermgr; /*%< Timer manager. */ - isc_socketmgr_t *socketmgr; /*%< Socket manager. */ - isc_nm_t *nm; /*%< Net manager. */ - int ncpus; /*%< Number of workers . */ + isc_mem_t *mctx; /*%< Memory context */ + ns_server_t *sctx; /*%< Server context */ + isc_taskmgr_t *taskmgr; /*%< Task manager */ + isc_task_t *excl; /*%< Exclusive task */ + isc_timermgr_t *timermgr; /*%< Timer manager */ + isc_socketmgr_t *socketmgr; /*%< Socket manager */ + isc_nm_t *nm; /*%< Net manager */ + int ncpus; /*%< Number of workers */ dns_dispatchmgr_t *dispatchmgr; - unsigned int generation; /*%< Current generation no. */ + unsigned int generation; /*%< Current generation no */ ns_listenlist_t *listenon4; ns_listenlist_t *listenon6; - dns_aclenv_t aclenv; /*%< Localhost/localnets ACLs */ - ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces. */ + dns_aclenv_t *aclenv; /*%< Localhost/localnets ACLs */ + ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces */ ISC_LIST(isc_sockaddr_t) listenon; - int backlog; /*%< Listen queue size */ - unsigned int udpdisp; /*%< UDP dispatch count */ - atomic_bool shuttingdown; /*%< Interfacemgr is shutting - * down */ + int backlog; /*%< Listen queue size */ + unsigned int udpdisp; /*%< UDP dispatch count */ + atomic_bool shuttingdown; /*%< Interfacemgr shutting down */ + ns_clientmgr_t **clientmgrs; /*%< Client managers */ #ifdef USE_ROUTE_SOCKET isc_task_t *task; isc_socket_t *route; @@ -232,16 +232,16 @@ ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx, */ result = ns_listenlist_create(mctx, &mgr->listenon4); if (result != ISC_R_SUCCESS) { - goto cleanup_ctx; + goto cleanup_sctx; } ns_listenlist_attach(mgr->listenon4, &mgr->listenon6); - result = dns_aclenv_init(mctx, &mgr->aclenv); + result = dns_aclenv_create(mctx, &mgr->aclenv); if (result != ISC_R_SUCCESS) { goto cleanup_listenon; } #if defined(HAVE_GEOIP2) - mgr->aclenv.geoip = geoip; + mgr->aclenv->geoip = geoip; #else /* if defined(HAVE_GEOIP2) */ UNUSED(geoip); #endif /* if defined(HAVE_GEOIP2) */ @@ -271,6 +271,15 @@ ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx, mgr->magic = IFMGR_MAGIC; *mgrp = mgr; + mgr->clientmgrs = isc_mem_get(mgr->mctx, + mgr->ncpus * sizeof(*mgr->clientmgrs[0])); + for (size_t i = 0; i < (size_t)mgr->ncpus; i++) { + result = ns_clientmgr_create(mgr->sctx, mgr->taskmgr, + mgr->timermgr, mgr->aclenv, (int)i, + &mgr->clientmgrs[i]); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + } + #ifdef USE_ROUTE_SOCKET if (mgr->route != NULL) { isc_region_t r = { mgr->buf, sizeof(mgr->buf) }; @@ -288,14 +297,14 @@ ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx, #ifdef USE_ROUTE_SOCKET cleanup_aclenv: - dns_aclenv_destroy(&mgr->aclenv); + dns_aclenv_detach(&mgr->aclenv); #endif /* ifdef USE_ROUTE_SOCKET */ cleanup_listenon: ns_listenlist_detach(&mgr->listenon4); ns_listenlist_detach(&mgr->listenon6); cleanup_lock: isc_mutex_destroy(&mgr->lock); -cleanup_ctx: +cleanup_sctx: ns_server_detach(&mgr->sctx); isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr)); return (result); @@ -315,11 +324,17 @@ ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) { isc_task_detach(&mgr->task); } #endif /* ifdef USE_ROUTE_SOCKET */ - dns_aclenv_destroy(&mgr->aclenv); + dns_aclenv_detach(&mgr->aclenv); ns_listenlist_detach(&mgr->listenon4); ns_listenlist_detach(&mgr->listenon6); clearlistenon(mgr); isc_mutex_destroy(&mgr->lock); + for (size_t i = 0; i < (size_t)mgr->ncpus; i++) { + ns_clientmgr_destroy(&mgr->clientmgrs[i]); + } + isc_mem_put(mgr->mctx, mgr->clientmgrs, + mgr->ncpus * sizeof(*mgr->clientmgrs[0])); + if (mgr->sctx != NULL) { ns_server_detach(&mgr->sctx); } @@ -342,7 +357,7 @@ dns_aclenv_t * ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) { REQUIRE(NS_INTERFACEMGR_VALID(mgr)); - return (&mgr->aclenv); + return (mgr->aclenv); } void @@ -390,7 +405,6 @@ static isc_result_t ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, const char *name, ns_interface_t **ifpret) { ns_interface_t *ifp; - isc_result_t result; int disp; REQUIRE(NS_INTERFACEMGR_VALID(mgr)); @@ -427,16 +441,6 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, isc_refcount_init(&ifp->references, 1); ifp->magic = IFACE_MAGIC; - result = ns_clientmgr_create(mgr->mctx, mgr->sctx, mgr->taskmgr, - mgr->timermgr, ifp, mgr->ncpus, - &ifp->clientmgr); - if (result != ISC_R_SUCCESS) { - isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, - "ns_clientmgr_create() failed: %s", - isc_result_totext(result)); - goto failure; - } - ifp->tcplistensocket = NULL; ifp->http_listensocket = NULL; ifp->http_secure_listensocket = NULL; @@ -444,14 +448,6 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, *ifpret = ifp; return (ISC_R_SUCCESS); - -failure: - isc_mutex_destroy(&ifp->lock); - - ifp->magic = 0; - isc_mem_put(mgr->mctx, ifp, sizeof(*ifp)); - - return (ISC_R_UNEXPECTED); } static isc_result_t @@ -682,9 +678,6 @@ ns_interface_shutdown(ns_interface_t *ifp) { isc_nm_stoplistening(ifp->http_secure_listensocket); isc_nmsocket_close(&ifp->http_secure_listensocket); } - if (ifp->clientmgr != NULL) { - ns_clientmgr_destroy(&ifp->clientmgr); - } } static void @@ -810,7 +803,7 @@ setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) { /* First add localhost address */ prefixlen = (netaddr->family == AF_INET) ? 32 : 128; - result = dns_iptable_addprefix(mgr->aclenv.localhost->iptable, netaddr, + result = dns_iptable_addprefix(mgr->aclenv->localhost->iptable, netaddr, prefixlen, true); if (result != ISC_R_SUCCESS) { return (result); @@ -841,7 +834,7 @@ setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) { return (ISC_R_SUCCESS); } - result = dns_iptable_addprefix(mgr->aclenv.localnets->iptable, netaddr, + result = dns_iptable_addprefix(mgr->aclenv->localnets->iptable, netaddr, prefixlen, true); if (result != ISC_R_SUCCESS) { return (result); @@ -1006,11 +999,11 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, bool verbose) { } if (!adjusting) { - result = clearacl(mgr->mctx, &mgr->aclenv.localhost); + result = clearacl(mgr->mctx, &mgr->aclenv->localhost); if (result != ISC_R_SUCCESS) { goto cleanup_iter; } - result = clearacl(mgr->mctx, &mgr->aclenv.localnets); + result = clearacl(mgr->mctx, &mgr->aclenv->localnets); if (result != ISC_R_SUCCESS) { goto cleanup_iter; } @@ -1108,7 +1101,7 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, bool verbose) { * if not, ignore the interface. */ (void)dns_acl_match(&listen_netaddr, NULL, le->acl, - &mgr->aclenv, &match, NULL); + mgr->aclenv, &match, NULL); if (match <= 0) { continue; } @@ -1347,17 +1340,11 @@ ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) { void ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) { - ns_interface_t *interface; - REQUIRE(NS_INTERFACEMGR_VALID(mgr)); LOCK(&mgr->lock); - interface = ISC_LIST_HEAD(mgr->interfaces); - while (interface != NULL) { - if (interface->clientmgr != NULL) { - ns_client_dumprecursing(f, interface->clientmgr); - } - interface = ISC_LIST_NEXT(interface, link); + for (size_t i = 0; i < (size_t)mgr->ncpus; i++) { + ns_client_dumprecursing(f, mgr->clientmgrs[i]); } UNLOCK(&mgr->lock); } @@ -1415,3 +1402,14 @@ ns__interfacemgr_nextif(ns_interface_t *ifp) { UNLOCK(&ifp->lock); return (next); } + +ns_clientmgr_t * +ns_interfacemgr_getclientmgr(ns_interfacemgr_t *mgr) { + int tid = isc_nm_tid(); + + REQUIRE(NS_INTERFACEMGR_VALID(mgr)); + REQUIRE(tid >= 0); + REQUIRE(tid < mgr->ncpus); + + return (mgr->clientmgrs[tid]); +} diff --git a/lib/ns/query.c b/lib/ns/query.c index a6fcaec8240..2ef0d67c91b 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -4722,8 +4722,7 @@ static bool dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { isc_netaddr_t netaddr; - dns_aclenv_t *env = - ns_interfacemgr_getaclenv(client->manager->interface->mgr); + dns_aclenv_t *env = client->manager->aclenv; dns_dns64_t *dns64 = ISC_LIST_HEAD(client->view->dns64); unsigned int flags = 0; unsigned int i, count; @@ -8188,8 +8187,7 @@ cleanup: static isc_result_t query_dns64(query_ctx_t *qctx) { ns_client_t *client = qctx->client; - dns_aclenv_t *env = - ns_interfacemgr_getaclenv(client->manager->interface->mgr); + dns_aclenv_t *env = client->manager->aclenv; dns_name_t *name, *mname; dns_rdata_t *dns64_rdata; dns_rdata_t rdata = DNS_RDATA_INIT; @@ -11536,8 +11534,7 @@ static void query_setup_sortlist(query_ctx_t *qctx) { isc_netaddr_t netaddr; ns_client_t *client = qctx->client; - dns_aclenv_t *env = - ns_interfacemgr_getaclenv(client->manager->interface->mgr); + dns_aclenv_t *env = client->manager->aclenv; const void *order_arg = NULL; isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); diff --git a/lib/ns/tests/listenlist_test.c b/lib/ns/tests/listenlist_test.c index 1a7f46451a4..94012e9fdc2 100644 --- a/lib/ns/tests/listenlist_test.c +++ b/lib/ns/tests/listenlist_test.c @@ -41,6 +41,8 @@ _setup(void **state) { UNUSED(state); + isc__nm_force_tid(0); + result = ns_test_begin(NULL, true); assert_int_equal(result, ISC_R_SUCCESS); @@ -51,6 +53,8 @@ static int _teardown(void **state) { UNUSED(state); + isc__nm_force_tid(-1); + ns_test_end(); return (0); diff --git a/lib/ns/tests/notify_test.c b/lib/ns/tests/notify_test.c index 5fbea8966e1..73651243b75 100644 --- a/lib/ns/tests/notify_test.c +++ b/lib/ns/tests/notify_test.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,8 @@ _setup(void **state) { UNUSED(state); + isc__nm_force_tid(0); + result = ns_test_begin(NULL, true); assert_int_equal(result, ISC_R_SUCCESS); @@ -54,6 +57,8 @@ static int _teardown(void **state) { UNUSED(state); + isc__nm_force_tid(-1); + ns_test_end(); return (0); diff --git a/lib/ns/tests/nstest.c b/lib/ns/tests/nstest.c index 6cf7ac91a9a..3c880291518 100644 --- a/lib/ns/tests/nstest.c +++ b/lib/ns/tests/nstest.c @@ -253,8 +253,7 @@ create_managers(void) { * we'll just sleep for a bit and hope. */ ns_test_nap(500000); - ns_interface_t *ifp = ns__interfacemgr_getif(interfacemgr); - clientmgr = ifp->clientmgr; + clientmgr = ns_interfacemgr_getclientmgr(interfacemgr); atomic_store(&run_managers, true); diff --git a/lib/ns/tests/query_test.c b/lib/ns/tests/query_test.c index 6630ee33697..d09333a0038 100644 --- a/lib/ns/tests/query_test.c +++ b/lib/ns/tests/query_test.c @@ -46,6 +46,8 @@ _setup(void **state) { UNUSED(state); + isc__nm_force_tid(0); + result = ns_test_begin(NULL, true); assert_int_equal(result, ISC_R_SUCCESS); @@ -56,6 +58,8 @@ static int _teardown(void **state) { UNUSED(state); + isc__nm_force_tid(-1); + ns_test_end(); return (0); diff --git a/lib/ns/update.c b/lib/ns/update.c index 2820ff769ee..b1753de9106 100644 --- a/lib/ns/update.c +++ b/lib/ns/update.c @@ -2583,8 +2583,7 @@ update_action(isc_task_t *task, isc_event_t *event) { dns_ttl_t maxttl = 0; uint32_t maxrecords; uint64_t records; - dns_aclenv_t *env = - ns_interfacemgr_getaclenv(client->manager->interface->mgr); + dns_aclenv_t *env = client->manager->aclenv; size_t ruleslen = 0; size_t rule; const dns_ssurule_t **rules = NULL; diff --git a/lib/ns/win32/libns.def b/lib/ns/win32/libns.def index a08ba68d1d8..a149b26868e 100644 --- a/lib/ns/win32/libns.def +++ b/lib/ns/win32/libns.def @@ -55,6 +55,7 @@ ns_interfacemgr_create ns_interfacemgr_detach ns_interfacemgr_dumprecursing ns_interfacemgr_getaclenv +ns_interfacemgr_getclientmgr ns_interfacemgr_getserver ns_interfacemgr_islistening ns_interfacemgr_listeningon