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.
This commit is contained in:
Ondřej Surý 2021-05-22 18:12:11 +02:00
parent aad7856b8e
commit 28b65d8256
24 changed files with 264 additions and 217 deletions

View file

@ -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.

View file

@ -22,6 +22,9 @@
#include <dns/acl.h>
#include <dns/iptable.h>
#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 (env->localnets != NULL) {
dns_acl_detach(&env->localnets);
if (aclenv->localnets != NULL) {
dns_acl_detach(&aclenv->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);
}
}

View file

@ -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_destroy(dns_aclenv_t *env);
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_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,

View file

@ -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;

View file

@ -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));

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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

View file

@ -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. */

View file

@ -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.
*/

View file

@ -1111,7 +1111,7 @@ struct isc_nmsocket {
bool
isc__nm_in_netthread(void);
/*%
/*%<
* Returns 'true' if we're in the network thread.
*/

View file

@ -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) {

View file

@ -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

View file

@ -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;
isc_mem_create(&mctx);
manager = isc_mem_get(mctx, sizeof(*manager));
*manager = (ns_clientmgr_t){ .magic = 0 };
*manager = (ns_clientmgr_t){ .magic = 0, .mctx = mctx };
result = isc_taskmgr_excltask(taskmgr, &manager->excl);
if (result != ISC_R_SUCCESS) {
isc_mem_put(mctx, manager, sizeof(*manager));
return (result);
}
isc_mutex_init(&manager->lock);
isc_mutex_init(&manager->reclock);
manager->excl = NULL;
result = isc_taskmgr_excltask(taskmgr, &manager->excl);
if (result != ISC_R_SUCCESS) {
goto cleanup_reclock;
}
manager->mctx = mctx;
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;

View file

@ -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.

View file

@ -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 */

View file

@ -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]);
}

View file

@ -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);

View file

@ -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);

View file

@ -28,6 +28,7 @@
#include <isc/event.h>
#include <isc/print.h>
#include <isc/task.h>
#include <isc/thread.h>
#include <dns/acl.h>
#include <dns/rcode.h>
@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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