[v9_9] backport performance changes from 9.10

3316.   [tuning]        Improved locking performance when recursing.
                        [RT #28836]

3315.   [tuning]        Use multiple dispatch objects for sending upstream
                        queries; this can improve performance on busy
                        multiprocessor systems by reducing lock contention.
                        [RT #28605]
This commit is contained in:
Evan Hunt 2012-10-26 10:14:29 -07:00
parent 76e34eb2fd
commit 7cec7ec1d2
20 changed files with 688 additions and 133 deletions

View file

@ -97,6 +97,14 @@
add NS RRsets to the additional section or not.
[RT #30479]
3316. [tuning] Improved locking performance when recursing.
[RT #28836]
3315. [tuning] Use multiple dispatch objects for sending upstream
queries; this can improve performance on busy
multiprocessor systems by reducing lock contention.
[RT #28605]
--- 9.9.2 released ---
3373. [bug] win32: open raw files in binary mode. [RT #30944]

View file

@ -1701,7 +1701,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
ns_cache_t *nsc;
isc_boolean_t zero_no_soattl;
dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL;
unsigned int query_timeout;
unsigned int query_timeout, ndisp;
struct cfg_context *nzctx;
REQUIRE(DNS_VIEW_VALID(view));
@ -2228,7 +2228,9 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
result = ISC_R_UNEXPECTED;
goto cleanup;
}
CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31,
ndisp = 4 * ISC_MIN(ns_g_udpdisp, MAX_UDP_DISPATCH);
CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31, ndisp,
ns_g_socketmgr, ns_g_timermgr,
resopts, ns_g_dispatchmgr,
dispatch4, dispatch6));

View file

@ -216,7 +216,7 @@ create_view(void) {
== ISC_R_SUCCESS);
INSIST(disp6 != NULL);
RUNTIME_CHECK(dns_view_createresolver(view, taskmgr, 10,
RUNTIME_CHECK(dns_view_createresolver(view, taskmgr, 10, 1,
socketmgr,
timermgr, 0,
dispatchmgr,

View file

@ -184,7 +184,7 @@ main(int argc, char *argv[]) {
INSIST(disp6 != NULL);
}
RUNTIME_CHECK(dns_view_createresolver(view, taskmgr, 10,
RUNTIME_CHECK(dns_view_createresolver(view, taskmgr, 10, 1,
socketmgr,
timermgr, 0,
dispatchmgr,

View file

@ -303,7 +303,7 @@ main(int argc, char *argv[]) {
INSIST(disp6 != NULL);
}
RUNTIME_CHECK(dns_view_createresolver(view, taskmgr, 10,
RUNTIME_CHECK(dns_view_createresolver(view, taskmgr, 10, 1,
socketmgr,
timermgr, 0,
dispatchmgr,

View file

@ -85,7 +85,7 @@ make_resolver(dns_resolver_t **resolverp) {
isc_result_t result;
result = dns_resolver_create(view,
task_manager, 1,
task_manager, 1, 1,
socket_manager,
timer_manager,
0, /* unsigned int options, */

View file

@ -318,7 +318,7 @@ dns_client_createview(isc_mem_t *mctx, dns_rdataclass_t rdclass,
return (result);
}
result = dns_view_createresolver(view, taskmgr, ntasks, socketmgr,
result = dns_view_createresolver(view, taskmgr, ntasks, 1, socketmgr,
timermgr, 0, dispatchmgr,
dispatchv4, dispatchv6);
if (result != ISC_R_SUCCESS) {

View file

@ -32,6 +32,7 @@
#include <isc/portset.h>
#include <isc/print.h>
#include <isc/random.h>
#include <isc/socket.h>
#include <isc/stats.h>
#include <isc/string.h>
#include <isc/task.h>
@ -101,12 +102,16 @@ struct dns_dispatchmgr {
unsigned int maxbuffers; /*%< max buffers */
/* Locked internally. */
isc_mutex_t pool_lock;
isc_mempool_t *epool; /*%< memory pool for events */
isc_mempool_t *rpool; /*%< memory pool for replies */
isc_mutex_t depool_lock;
isc_mempool_t *depool; /*%< pool for dispatch events */
isc_mutex_t rpool_lock;
isc_mempool_t *rpool; /*%< pool for replies */
isc_mutex_t dpool_lock;
isc_mempool_t *dpool; /*%< dispatch allocations */
isc_mempool_t *bpool; /*%< memory pool for buffers */
isc_mempool_t *spool; /*%< memory pool for dispsocs */
isc_mutex_t bpool_lock;
isc_mempool_t *bpool; /*%< pool for buffers */
isc_mutex_t spool_lock;
isc_mempool_t *spool; /*%< pool for dispsocks */
/*%
* Locked by qid->lock if qid exists; otherwise, can be used without
@ -226,6 +231,9 @@ struct dns_dispatch {
unsigned int maxrequests; /*%< max requests */
isc_event_t *ctlevent;
isc_mutex_t sepool_lock;
isc_mempool_t *sepool; /*%< pool for socket events */
/*% Locked by mgr->lock. */
ISC_LINK(dns_dispatch_t) link;
@ -301,8 +309,8 @@ static isc_uint32_t dns_hash(dns_qid_t *, isc_sockaddr_t *, dns_messageid_t,
in_port_t);
static void free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len);
static void *allocate_udp_buffer(dns_dispatch_t *disp);
static inline void free_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev);
static inline dns_dispatchevent_t *allocate_event(dns_dispatch_t *disp);
static inline void free_devent(dns_dispatch_t *disp, dns_dispatchevent_t *ev);
static inline dns_dispatchevent_t *allocate_devent(dns_dispatch_t *disp);
static void do_cancel(dns_dispatch_t *disp);
static dns_dispentry_t *linear_first(dns_qid_t *disp);
static dns_dispentry_t *linear_next(dns_qid_t *disp,
@ -723,6 +731,11 @@ destroy_disp(isc_task_t *task, isc_event_t *event) {
"shutting down; detaching from sock %p, task %p",
disp->socket, disp->task[0]); /* XXXX */
if (disp->sepool != NULL) {
isc_mempool_destroy(&disp->sepool);
isc_mutex_destroy(&disp->sepool_lock);
}
if (disp->socket != NULL)
isc_socket_detach(&disp->socket);
while ((dispsocket = ISC_LIST_HEAD(disp->inactivesockets)) != NULL) {
@ -787,6 +800,7 @@ new_portentry(dns_dispatch_t *disp, in_port_t port) {
static void
deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) {
dispportentry_t *portentry = *portentryp;
isc_boolean_t unlink = ISC_FALSE;
dns_qid_t *qid;
REQUIRE(disp->port_table != NULL);
@ -795,7 +809,10 @@ deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) {
qid = DNS_QID(disp);
LOCK(&qid->lock);
portentry->refs--;
if (portentry->refs == 0) {
unlink = ISC_TF(portentry->refs == 0);
UNLOCK(&qid->lock);
if (unlink) {
ISC_LIST_UNLINK(disp->port_table[portentry->port %
DNS_DISPATCH_PORTTABLESIZE],
portentry, link);
@ -803,7 +820,6 @@ deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) {
}
*portentryp = NULL;
UNLOCK(&qid->lock);
}
/*%
@ -833,12 +849,12 @@ socket_search(dns_qid_t *qid, isc_sockaddr_t *dest, in_port_t port,
/*%
* Make a new socket for a single dispatch with a random port number.
* The caller must hold the disp->lock and qid->lock.
* The caller must hold the disp->lock
*/
static isc_result_t
get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest,
isc_socketmgr_t *sockmgr, dns_qid_t *qid,
dispsocket_t **dispsockp, in_port_t *portp)
isc_socketmgr_t *sockmgr, dispsocket_t **dispsockp,
in_port_t *portp)
{
int i;
isc_uint32_t r;
@ -853,6 +869,7 @@ get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest,
in_port_t *ports;
unsigned int bindoptions;
dispportentry_t *portentry = NULL;
dns_qid_t *qid;
if (isc_sockaddr_pf(&disp->local) == AF_INET) {
nports = disp->mgr->nv4ports;
@ -893,16 +910,23 @@ get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest,
* very likely to fail in bind(2) or connect(2).
*/
localaddr = disp->local;
qid = DNS_QID(disp);
for (i = 0; i < 64; i++) {
port = ports[dispatch_uniformrandom(DISP_ARC4CTX(disp),
nports)];
isc_sockaddr_setport(&localaddr, port);
LOCK(&qid->lock);
bucket = dns_hash(qid, dest, 0, port);
if (socket_search(qid, dest, port, bucket) != NULL)
if (socket_search(qid, dest, port, bucket) != NULL) {
UNLOCK(&qid->lock);
continue;
}
UNLOCK(&qid->lock);
bindoptions = 0;
portentry = port_search(disp, port);
if (portentry != NULL)
bindoptions |= ISC_SOCKET_REUSEADDRESS;
result = open_socket(sockmgr, &localaddr, bindoptions, &sock,
@ -932,7 +956,9 @@ get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest,
dispsock->host = *dest;
dispsock->portentry = portentry;
dispsock->bucket = bucket;
LOCK(&qid->lock);
ISC_LIST_APPEND(qid->sock_table[bucket], dispsock, blink);
UNLOCK(&qid->lock);
*dispsockp = dispsock;
*portp = port;
} else {
@ -1067,6 +1093,7 @@ entry_search(dns_qid_t *qid, isc_sockaddr_t *dest, dns_messageid_t id,
static void
free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len) {
isc_mempool_t *bpool;
INSIST(buf != NULL && len != 0);
@ -1081,8 +1108,9 @@ free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len) {
INSIST(disp->mgr->buffers > 0);
INSIST(len == disp->mgr->buffersize);
disp->mgr->buffers--;
isc_mempool_put(disp->mgr->bpool, buf);
bpool = disp->mgr->bpool;
UNLOCK(&disp->mgr->buffer_lock);
isc_mempool_put(bpool, buf);
break;
default:
INSIST(0);
@ -1092,20 +1120,60 @@ free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len) {
static void *
allocate_udp_buffer(dns_dispatch_t *disp) {
isc_mempool_t *bpool;
void *temp;
LOCK(&disp->mgr->buffer_lock);
temp = isc_mempool_get(disp->mgr->bpool);
if (temp != NULL)
disp->mgr->buffers++;
bpool = disp->mgr->bpool;
disp->mgr->buffers++;
UNLOCK(&disp->mgr->buffer_lock);
temp = isc_mempool_get(bpool);
if (temp == NULL) {
LOCK(&disp->mgr->buffer_lock);
disp->mgr->buffers--;
UNLOCK(&disp->mgr->buffer_lock);
}
return (temp);
}
static inline void
free_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev) {
free_sevent(isc_event_t *ev) {
isc_mempool_t *pool = ev->ev_destroy_arg;
isc_socketevent_t *sev = (isc_socketevent_t *) ev;
isc_mempool_put(pool, sev);
}
static inline isc_socketevent_t *
allocate_sevent(dns_dispatch_t *disp, isc_socket_t *socket,
isc_eventtype_t type, isc_taskaction_t action, const void *arg)
{
isc_socketevent_t *ev;
void *deconst_arg;
ev = isc_mempool_get(disp->sepool);
if (ev == NULL)
return (NULL);
DE_CONST(arg, deconst_arg);
ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, type,
action, deconst_arg, socket,
free_sevent, disp->sepool);
ev->result = ISC_R_UNSET;
ISC_LINK_INIT(ev, ev_link);
ISC_LIST_INIT(ev->bufferlist);
ev->region.base = NULL;
ev->n = 0;
ev->offset = 0;
ev->attributes = 0;
return (ev);
}
static inline void
free_devent(dns_dispatch_t *disp, dns_dispatchevent_t *ev) {
if (disp->failsafe_ev == ev) {
INSIST(disp->shutdown_out == 1);
disp->shutdown_out = 0;
@ -1113,14 +1181,14 @@ free_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev) {
return;
}
isc_mempool_put(disp->mgr->epool, ev);
isc_mempool_put(disp->mgr->depool, ev);
}
static inline dns_dispatchevent_t *
allocate_event(dns_dispatch_t *disp) {
allocate_devent(dns_dispatch_t *disp) {
dns_dispatchevent_t *ev;
ev = isc_mempool_get(disp->mgr->epool);
ev = isc_mempool_get(disp->mgr->depool);
if (ev == NULL)
return (NULL);
ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, 0,
@ -1385,7 +1453,7 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) {
sendresponse:
queue_response = resp->item_out;
rev = allocate_event(resp->disp);
rev = allocate_devent(resp->disp);
if (rev == NULL) {
free_buffer(disp, ev->region.base, ev->region.length);
goto unlock;
@ -1583,7 +1651,7 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) {
if (resp == NULL)
goto unlock;
queue_response = resp->item_out;
rev = allocate_event(disp);
rev = allocate_devent(disp);
if (rev == NULL)
goto unlock;
@ -1664,16 +1732,33 @@ startrecv(dns_dispatch_t *disp, dispsocket_t *dispsock) {
if (region.base == NULL)
return (ISC_R_NOMEMORY);
if (dispsock != NULL) {
res = isc_socket_recv(socket, &region, 1,
dispsock->task, udp_exrecv,
dispsock);
isc_task_t *dt = dispsock->task;
isc_socketevent_t *sev =
allocate_sevent(disp, socket,
ISC_SOCKEVENT_RECVDONE,
udp_exrecv, dispsock);
if (sev == NULL) {
free_buffer(disp, region.base, region.length);
return (ISC_R_NOMEMORY);
}
res = isc_socket_recv2(socket, &region, 1, dt, sev, 0);
if (res != ISC_R_SUCCESS) {
free_buffer(disp, region.base, region.length);
return (res);
}
} else {
res = isc_socket_recv(socket, &region, 1,
disp->task[0], udp_shrecv, disp);
isc_task_t *dt = disp->task[0];
isc_socketevent_t *sev =
allocate_sevent(disp, socket,
ISC_SOCKEVENT_RECVDONE,
udp_shrecv, disp);
if (sev == NULL) {
free_buffer(disp, region.base, region.length);
return (ISC_R_NOMEMORY);
}
res = isc_socket_recv2(socket, &region, 1, dt, sev, 0);
if (res != ISC_R_SUCCESS) {
free_buffer(disp, region.base, region.length);
disp->shutdown_why = res;
@ -1713,16 +1798,16 @@ static isc_boolean_t
destroy_mgr_ok(dns_dispatchmgr_t *mgr) {
mgr_log(mgr, LVL(90),
"destroy_mgr_ok: shuttingdown=%d, listnonempty=%d, "
"epool=%d, rpool=%d, dpool=%d",
"depool=%d, rpool=%d, dpool=%d",
MGR_IS_SHUTTINGDOWN(mgr), !ISC_LIST_EMPTY(mgr->list),
isc_mempool_getallocated(mgr->epool),
isc_mempool_getallocated(mgr->depool),
isc_mempool_getallocated(mgr->rpool),
isc_mempool_getallocated(mgr->dpool));
if (!MGR_IS_SHUTTINGDOWN(mgr))
return (ISC_FALSE);
if (!ISC_LIST_EMPTY(mgr->list))
return (ISC_FALSE);
if (isc_mempool_getallocated(mgr->epool) != 0)
if (isc_mempool_getallocated(mgr->depool) != 0)
return (ISC_FALSE);
if (isc_mempool_getallocated(mgr->rpool) != 0)
return (ISC_FALSE);
@ -1752,7 +1837,7 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) {
DESTROYLOCK(&mgr->arc4_lock);
isc_mempool_destroy(&mgr->epool);
isc_mempool_destroy(&mgr->depool);
isc_mempool_destroy(&mgr->rpool);
isc_mempool_destroy(&mgr->dpool);
if (mgr->bpool != NULL)
@ -1760,7 +1845,11 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) {
if (mgr->spool != NULL)
isc_mempool_destroy(&mgr->spool);
DESTROYLOCK(&mgr->pool_lock);
DESTROYLOCK(&mgr->spool_lock);
DESTROYLOCK(&mgr->bpool_lock);
DESTROYLOCK(&mgr->dpool_lock);
DESTROYLOCK(&mgr->rpool_lock);
DESTROYLOCK(&mgr->depool_lock);
#ifdef BIND9
if (mgr->entropy != NULL)
@ -1900,22 +1989,38 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy,
if (result != ISC_R_SUCCESS)
goto kill_arc4_lock;
result = isc_mutex_init(&mgr->pool_lock);
result = isc_mutex_init(&mgr->depool_lock);
if (result != ISC_R_SUCCESS)
goto kill_buffer_lock;
mgr->epool = NULL;
result = isc_mutex_init(&mgr->rpool_lock);
if (result != ISC_R_SUCCESS)
goto kill_depool_lock;
result = isc_mutex_init(&mgr->dpool_lock);
if (result != ISC_R_SUCCESS)
goto kill_rpool_lock;
result = isc_mutex_init(&mgr->bpool_lock);
if (result != ISC_R_SUCCESS)
goto kill_dpool_lock;
result = isc_mutex_init(&mgr->spool_lock);
if (result != ISC_R_SUCCESS)
goto kill_bpool_lock;
mgr->depool = NULL;
if (isc_mempool_create(mgr->mctx, sizeof(dns_dispatchevent_t),
&mgr->epool) != ISC_R_SUCCESS) {
&mgr->depool) != ISC_R_SUCCESS) {
result = ISC_R_NOMEMORY;
goto kill_pool_lock;
goto kill_spool_lock;
}
mgr->rpool = NULL;
if (isc_mempool_create(mgr->mctx, sizeof(dns_dispentry_t),
&mgr->rpool) != ISC_R_SUCCESS) {
result = ISC_R_NOMEMORY;
goto kill_epool;
goto kill_depool;
}
mgr->dpool = NULL;
@ -1925,17 +2030,23 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy,
goto kill_rpool;
}
isc_mempool_setname(mgr->epool, "dispmgr_epool");
isc_mempool_setfreemax(mgr->epool, 1024);
isc_mempool_associatelock(mgr->epool, &mgr->pool_lock);
isc_mempool_setname(mgr->depool, "dispmgr_depool");
isc_mempool_setmaxalloc(mgr->depool, 32768);
isc_mempool_setfreemax(mgr->depool, 32768);
isc_mempool_associatelock(mgr->depool, &mgr->depool_lock);
isc_mempool_setfillcount(mgr->depool, 256);
isc_mempool_setname(mgr->rpool, "dispmgr_rpool");
isc_mempool_setfreemax(mgr->rpool, 1024);
isc_mempool_associatelock(mgr->rpool, &mgr->pool_lock);
isc_mempool_setmaxalloc(mgr->rpool, 32768);
isc_mempool_setfreemax(mgr->rpool, 32768);
isc_mempool_associatelock(mgr->rpool, &mgr->rpool_lock);
isc_mempool_setfillcount(mgr->rpool, 256);
isc_mempool_setname(mgr->dpool, "dispmgr_dpool");
isc_mempool_setfreemax(mgr->dpool, 1024);
isc_mempool_associatelock(mgr->dpool, &mgr->pool_lock);
isc_mempool_setmaxalloc(mgr->dpool, 32768);
isc_mempool_setfreemax(mgr->dpool, 32768);
isc_mempool_associatelock(mgr->dpool, &mgr->dpool_lock);
isc_mempool_setfillcount(mgr->dpool, 256);
mgr->buffers = 0;
mgr->buffersize = 0;
@ -1984,10 +2095,18 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy,
isc_mempool_destroy(&mgr->dpool);
kill_rpool:
isc_mempool_destroy(&mgr->rpool);
kill_epool:
isc_mempool_destroy(&mgr->epool);
kill_pool_lock:
DESTROYLOCK(&mgr->pool_lock);
kill_depool:
isc_mempool_destroy(&mgr->depool);
kill_spool_lock:
DESTROYLOCK(&mgr->spool_lock);
kill_bpool_lock:
DESTROYLOCK(&mgr->bpool_lock);
kill_dpool_lock:
DESTROYLOCK(&mgr->dpool_lock);
kill_rpool_lock:
DESTROYLOCK(&mgr->rpool_lock);
kill_depool_lock:
DESTROYLOCK(&mgr->depool_lock);
kill_buffer_lock:
DESTROYLOCK(&mgr->buffer_lock);
kill_arc4_lock:
@ -2141,6 +2260,7 @@ dns_dispatchmgr_setudp(dns_dispatchmgr_t *mgr,
*/
if (maxbuffers > mgr->maxbuffers) {
isc_mempool_setmaxalloc(mgr->bpool, maxbuffers);
isc_mempool_setfreemax(mgr->bpool, maxbuffers);
mgr->maxbuffers = maxbuffers;
}
} else {
@ -2151,12 +2271,16 @@ dns_dispatchmgr_setudp(dns_dispatchmgr_t *mgr,
}
isc_mempool_setname(mgr->bpool, "dispmgr_bpool");
isc_mempool_setmaxalloc(mgr->bpool, maxbuffers);
isc_mempool_associatelock(mgr->bpool, &mgr->pool_lock);
isc_mempool_setfreemax(mgr->bpool, maxbuffers);
isc_mempool_associatelock(mgr->bpool, &mgr->bpool_lock);
isc_mempool_setfillcount(mgr->bpool, 256);
}
/* Create or adjust socket pool */
if (mgr->spool != NULL) {
isc_mempool_setmaxalloc(mgr->spool, DNS_DISPATCH_POOLSOCKS * 2);
if (maxrequests < DNS_DISPATCH_POOLSOCKS * 2)
isc_mempool_setmaxalloc(mgr->spool, DNS_DISPATCH_POOLSOCKS * 2);
isc_mempool_setfreemax(mgr->spool, DNS_DISPATCH_POOLSOCKS * 2);
UNLOCK(&mgr->buffer_lock);
return (ISC_R_SUCCESS);
}
@ -2168,7 +2292,9 @@ dns_dispatchmgr_setudp(dns_dispatchmgr_t *mgr,
}
isc_mempool_setname(mgr->spool, "dispmgr_spool");
isc_mempool_setmaxalloc(mgr->spool, maxrequests);
isc_mempool_associatelock(mgr->spool, &mgr->pool_lock);
isc_mempool_setfreemax(mgr->spool, maxrequests);
isc_mempool_associatelock(mgr->spool, &mgr->spool_lock);
isc_mempool_setfillcount(mgr->spool, 256);
result = qid_allocate(mgr, buckets, increment, &mgr->qid, ISC_TRUE);
if (result != ISC_R_SUCCESS)
@ -2494,7 +2620,7 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests,
if (result != ISC_R_SUCCESS)
goto deallocate;
disp->failsafe_ev = allocate_event(disp);
disp->failsafe_ev = allocate_devent(disp);
if (disp->failsafe_ev == NULL) {
result = ISC_R_NOMEMORY;
goto kill_lock;
@ -2545,7 +2671,7 @@ dispatch_free(dns_dispatch_t **dispp)
INSIST(ISC_LIST_EMPTY(disp->activesockets));
INSIST(ISC_LIST_EMPTY(disp->inactivesockets));
isc_mempool_put(mgr->epool, disp->failsafe_ev);
isc_mempool_put(mgr->depool, disp->failsafe_ev);
disp->failsafe_ev = NULL;
if (disp->qid != NULL)
@ -2609,6 +2735,8 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
disp->socket = NULL;
isc_socket_attach(sock, &disp->socket);
disp->sepool = NULL;
disp->ntasks = 1;
disp->task[0] = NULL;
result = isc_task_create(taskmgr, 0, &disp->task[0]);
@ -2972,6 +3100,24 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
goto kill_task;
}
disp->sepool = NULL;
if (isc_mempool_create(mgr->mctx, sizeof(isc_socketevent_t),
&disp->sepool) != ISC_R_SUCCESS)
{
result = ISC_R_NOMEMORY;
goto kill_ctlevent;
}
result = isc_mutex_init(&disp->sepool_lock);
if (result != ISC_R_SUCCESS)
goto kill_sepool;
isc_mempool_setname(disp->sepool, "disp_sepool");
isc_mempool_setmaxalloc(disp->sepool, 32768);
isc_mempool_setfreemax(disp->sepool, 32768);
isc_mempool_associatelock(disp->sepool, &disp->sepool_lock);
isc_mempool_setfillcount(disp->sepool, 16);
attributes &= ~DNS_DISPATCHATTR_TCP;
attributes |= DNS_DISPATCHATTR_UDP;
disp->attributes = attributes;
@ -2993,6 +3139,10 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
/*
* Error returns.
*/
kill_sepool:
isc_mempool_destroy(&disp->sepool);
kill_ctlevent:
isc_event_free(&disp->ctlevent);
kill_task:
for (i = 0; i < disp->ntasks; i++)
isc_task_detach(&disp->task[i]);
@ -3109,7 +3259,7 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest,
oldestsocket = ISC_LIST_HEAD(disp->activesockets);
oldestresp = oldestsocket->resp;
if (oldestresp != NULL && !oldestresp->item_out) {
rev = allocate_event(oldestresp->disp);
rev = allocate_devent(oldestresp->disp);
if (rev != NULL) {
rev->buffer.base = NULL;
rev->result = ISC_R_CANCELED;
@ -3136,16 +3286,14 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest,
}
qid = DNS_QID(disp);
LOCK(&qid->lock);
if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
/*
* Get a separate UDP socket with a random port number.
*/
result = get_dispsocket(disp, dest, sockmgr, qid, &dispsocket,
result = get_dispsocket(disp, dest, sockmgr, &dispsocket,
&localport);
if (result != ISC_R_SUCCESS) {
UNLOCK(&qid->lock);
UNLOCK(&disp->lock);
inc_stats(disp->mgr, dns_resstatscounter_dispsockfail);
return (result);
@ -3157,6 +3305,7 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest,
/*
* Try somewhat hard to find an unique ID.
*/
LOCK(&qid->lock);
id = (dns_messageid_t)dispatch_random(DISP_ARC4CTX(disp));
bucket = dns_hash(qid, dest, id, localport);
ok = ISC_FALSE;
@ -3169,16 +3318,15 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest,
id &= 0x0000ffff;
bucket = dns_hash(qid, dest, id, localport);
}
UNLOCK(&qid->lock);
if (!ok) {
UNLOCK(&qid->lock);
UNLOCK(&disp->lock);
return (ISC_R_NOMORE);
}
res = isc_mempool_get(disp->mgr->rpool);
if (res == NULL) {
UNLOCK(&qid->lock);
UNLOCK(&disp->lock);
if (dispsocket != NULL)
destroy_dispsocket(disp, &dispsocket);
@ -3203,6 +3351,8 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest,
ISC_LIST_INIT(res->items);
ISC_LINK_INIT(res, link);
res->magic = RESPONSE_MAGIC;
LOCK(&qid->lock);
ISC_LIST_APPEND(qid->qid_table[bucket], res, link);
UNLOCK(&qid->lock);
@ -3350,7 +3500,7 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp,
res->item_out = ISC_FALSE;
if (ev->buffer.base != NULL)
free_buffer(disp, ev->buffer.base, ev->buffer.length);
free_event(disp, ev);
free_devent(disp, ev);
}
request_log(disp, res, LVL(90), "detaching from task %p", res->task);
@ -3370,7 +3520,7 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp,
ISC_LIST_UNLINK(res->items, ev, ev_link);
if (ev->buffer.base != NULL)
free_buffer(disp, ev->buffer.base, ev->buffer.length);
free_event(disp, ev);
free_devent(disp, ev);
ev = ISC_LIST_HEAD(res->items);
}
res->magic = 0;
@ -3567,6 +3717,128 @@ dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event) {
isc_task_send(disp->task[0], ISC_EVENT_PTR(&newsevent));
}
dns_dispatch_t *
dns_dispatchset_get(dns_dispatchset_t *dset) {
dns_dispatch_t *disp;
/* 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);
return (disp);
}
isc_result_t
dns_dispatchset_create(isc_mem_t *mctx, isc_socketmgr_t *sockmgr,
isc_taskmgr_t *taskmgr, dns_dispatch_t *source,
dns_dispatchset_t **dsetp, int n)
{
isc_result_t result;
dns_dispatchset_t *dset;
dns_dispatchmgr_t *mgr;
int i, j;
REQUIRE(VALID_DISPATCH(source));
REQUIRE((source->attributes & DNS_DISPATCHATTR_UDP) != 0);
REQUIRE(dsetp != NULL && *dsetp == NULL);
mgr = source->mgr;
dset = isc_mem_get(mctx, sizeof(dns_dispatchset_t));
if (dset == NULL)
return (ISC_R_NOMEMORY);
memset(dset, 0, sizeof(*dset));
result = isc_mutex_init(&dset->lock);
if (result != ISC_R_SUCCESS)
goto fail_alloc;
dset->dispatches = isc_mem_get(mctx, sizeof(dns_dispatch_t *) * n);
if (dset == NULL) {
result = ISC_R_NOMEMORY;
goto fail_lock;
}
isc_mem_attach(mctx, &dset->mctx);
dset->ndisp = n;
dset->cur = 0;
dset->dispatches[0] = NULL;
dns_dispatch_attach(source, &dset->dispatches[0]);
LOCK(&mgr->lock);
for (i = 1; i < n; i++) {
dset->dispatches[i] = NULL;
result = dispatch_createudp(mgr, sockmgr, taskmgr,
&source->local,
source->maxrequests,
source->attributes,
&dset->dispatches[i],
source->socket);
if (result != ISC_R_SUCCESS)
goto fail;
}
UNLOCK(&mgr->lock);
*dsetp = dset;
return (ISC_R_SUCCESS);
fail:
UNLOCK(&mgr->lock);
for (j = 0; j < i; j++)
dns_dispatch_detach(&(dset->dispatches[j]));
isc_mem_put(mctx, dset->dispatches, sizeof(dns_dispatch_t *) * n);
if (dset->mctx == mctx)
isc_mem_detach(&dset->mctx);
fail_lock:
DESTROYLOCK(&dset->lock);
fail_alloc:
isc_mem_put(mctx, dset, sizeof(dns_dispatchset_t));
return (result);
}
void
dns_dispatchset_cancelall(dns_dispatchset_t *dset, isc_task_t *task) {
int i;
REQUIRE(dset != NULL);
for (i = 0; i < dset->ndisp; i++) {
isc_socket_t *sock;
sock = dns_dispatch_getsocket(dset->dispatches[i]);
isc_socket_cancel(sock, task, ISC_SOCKCANCEL_ALL);
}
}
void
dns_dispatchset_destroy(dns_dispatchset_t **dsetp) {
dns_dispatchset_t *dset;
int i;
REQUIRE(dsetp != NULL && *dsetp != NULL);
dset = *dsetp;
for (i = 0; i < dset->ndisp; i++)
dns_dispatch_detach(&(dset->dispatches[i]));
isc_mem_put(dset->mctx, dset->dispatches,
sizeof(dns_dispatch_t *) * dset->ndisp);
DESTROYLOCK(&dset->lock);
isc_mem_putanddetach(&dset->mctx, dset, sizeof(dns_dispatchset_t));
*dsetp = NULL;
}
#if 0
void
dns_dispatchmgr_dump(dns_dispatchmgr_t *mgr) {

View file

@ -54,6 +54,7 @@
#include <isc/buffer.h>
#include <isc/lang.h>
#include <isc/mutex.h>
#include <isc/socket.h>
#include <isc/types.h>
@ -88,6 +89,18 @@ struct dns_dispatchevent {
isc_uint32_t attributes; /*%< mirrored from socket.h */
};
/*%
* This is a set of one or more dispatches which can be retrieved
* round-robin fashion.
*/
struct dns_dispatchset {
isc_mem_t *mctx;
dns_dispatch_t **dispatches;
int ndisp;
int cur;
isc_mutex_t lock;
};
/*@{*/
/*%
* Attributes for added dispatchers.
@ -505,6 +518,46 @@ dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event);
* event != NULL
*/
dns_dispatch_t *
dns_dispatchset_get(dns_dispatchset_t *dset);
/*%<
* Retrieve the next dispatch from dispatch set 'dset', and increment
* the round-robin counter.
*
* Requires:
*\li dset != NULL
*/
isc_result_t
dns_dispatchset_create(isc_mem_t *mctx, isc_socketmgr_t *sockmgr,
isc_taskmgr_t *taskmgr, dns_dispatch_t *source,
dns_dispatchset_t **dsetp, int n);
/*%<
* Given a valid dispatch 'source', create a dispatch set containing
* 'n' UDP dispatches, with the remainder filled out by clones of the
* source.
*
* Requires:
*\li source is a valid UDP dispatcher
*\li dsetp != NULL, *dsetp == NULL
*/
void
dns_dispatchset_cancelall(dns_dispatchset_t *dset, isc_task_t *task);
/*%<
* Cancel socket operations for the dispatches in 'dset'.
*/
void
dns_dispatchset_destroy(dns_dispatchset_t **dsetp);
/*%<
* Dereference all the dispatches in '*dsetp', free the dispatchset
* memory, and set *dsetp to NULL.
*
* Requires:
*\li dset is valid
*/
ISC_LANG_ENDDECLS
#endif /* DNS_DISPATCH_H */

View file

@ -126,7 +126,8 @@ typedef struct dns_fetchevent {
isc_result_t
dns_resolver_create(dns_view_t *view,
isc_taskmgr_t *taskmgr, unsigned int ntasks,
isc_taskmgr_t *taskmgr,
unsigned int ntasks, unsigned int ndisp,
isc_socketmgr_t *socketmgr,
isc_timermgr_t *timermgr,
unsigned int options,
@ -155,9 +156,11 @@ dns_resolver_create(dns_view_t *view,
*
*\li 'timermgr' is a valid timer manager.
*
*\li 'dispatchv4' is a valid dispatcher with an IPv4 UDP socket, or is 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.
*
*\li 'dispatchv6' is a valid dispatcher with an IPv6 UDP socket, or is NULL.
*\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.
*
*\li resp != NULL && *resp == NULL.
*

View file

@ -65,6 +65,7 @@ typedef struct dns_decompress dns_decompress_t;
typedef struct dns_dispatch dns_dispatch_t;
typedef struct dns_dispatchevent dns_dispatchevent_t;
typedef struct dns_dispatchlist dns_dispatchlist_t;
typedef struct dns_dispatchset dns_dispatchset_t;
typedef struct dns_dispatchmgr dns_dispatchmgr_t;
typedef struct dns_dispentry dns_dispentry_t;
typedef struct dns_dns64 dns_dns64_t;

View file

@ -313,7 +313,8 @@ dns_view_weakdetach(dns_view_t **targetp);
isc_result_t
dns_view_createresolver(dns_view_t *view,
isc_taskmgr_t *taskmgr, unsigned int ntasks,
isc_taskmgr_t *taskmgr,
unsigned int ntasks, unsigned int ndisp,
isc_socketmgr_t *socketmgr,
isc_timermgr_t *timermgr,
unsigned int options,

View file

@ -25,8 +25,9 @@
#include <isc/print.h>
#include <isc/string.h>
#include <isc/random.h>
#include <isc/task.h>
#include <isc/socket.h>
#include <isc/stats.h>
#include <isc/task.h>
#include <isc/timer.h>
#include <isc/util.h>
@ -156,6 +157,7 @@ typedef struct query {
isc_buffer_t buffer;
isc_buffer_t *tsig;
dns_tsigkey_t *tsigkey;
isc_socketevent_t sendevent;
unsigned int options;
unsigned int attributes;
unsigned int sends;
@ -389,11 +391,10 @@ struct dns_resolver {
isc_boolean_t frozen;
unsigned int options;
dns_dispatchmgr_t * dispatchmgr;
dns_dispatch_t * dispatchv4;
dns_dispatchset_t * dispatches4;
isc_boolean_t exclusivev4;
dns_dispatch_t * dispatchv6;
dns_dispatchset_t * dispatches6;
isc_boolean_t exclusivev6;
unsigned int ndisps;
unsigned int nbuckets;
fctxbucket_t * buckets;
isc_uint32_t lame_ttl;
@ -420,7 +421,6 @@ struct dns_resolver {
unsigned int activebuckets;
isc_boolean_t priming;
unsigned int spillat; /* clients-per-query */
unsigned int nextdisp;
/* Bad cache. */
dns_badcache_t ** badcache;
@ -1210,7 +1210,8 @@ process_sendevent(resquery_t *query, isc_event_t *event) {
}
}
isc_event_free(&event);
if (event->ev_type == ISC_SOCKEVENT_CONNECT)
isc_event_free(&event);
if (retry) {
/*
@ -1457,14 +1458,14 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
if (!have_addr) {
switch (pf) {
case PF_INET:
result =
dns_dispatch_getlocaladdress(res->dispatchv4,
&addr);
result = dns_dispatch_getlocaladdress(
res->dispatches4->dispatches[0],
&addr);
break;
case PF_INET6:
result =
dns_dispatch_getlocaladdress(res->dispatchv6,
&addr);
result = dns_dispatch_getlocaladdress(
res->dispatches6->dispatches[0],
&addr);
break;
default:
result = ISC_R_NOTIMPLEMENTED;
@ -1520,13 +1521,15 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
} else {
switch (isc_sockaddr_pf(&addrinfo->sockaddr)) {
case PF_INET:
dns_dispatch_attach(res->dispatchv4,
&query->dispatch);
dns_dispatch_attach(
dns_resolver_dispatchv4(res),
&query->dispatch);
query->exclusivesocket = res->exclusivev4;
break;
case PF_INET6:
dns_dispatch_attach(res->dispatchv6,
&query->dispatch);
dns_dispatch_attach(
dns_resolver_dispatchv6(res),
&query->dispatch);
query->exclusivesocket = res->exclusivev6;
break;
default:
@ -2010,8 +2013,11 @@ resquery_send(resquery_t *query) {
* XXXRTH Make sure we don't send to ourselves! We should probably
* prune out these addresses when we get them from the ADB.
*/
result = isc_socket_sendto(socket, &r, task, resquery_senddone,
query, address, NULL);
ISC_EVENT_INIT(&query->sendevent, sizeof(query->sendevent), 0, NULL,
ISC_SOCKEVENT_SENDDONE, resquery_senddone, query,
NULL, NULL, NULL);
result = isc_socket_sendto2(socket, &r, task, address, NULL,
&query->sendevent, 0);
if (result != ISC_R_SUCCESS) {
if (connecting) {
/*
@ -2545,9 +2551,9 @@ findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
*/
if (need_alternate != NULL &&
!*need_alternate && unshared &&
((res->dispatchv4 == NULL &&
((res->dispatches4 == NULL &&
find->result_v6 != DNS_R_NXDOMAIN) ||
(res->dispatchv6 == NULL &&
(res->dispatches6 == NULL &&
find->result_v4 != DNS_R_NXDOMAIN)))
*need_alternate = ISC_TRUE;
} else {
@ -2562,9 +2568,9 @@ findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
* an alternative server.
*/
if (need_alternate != NULL && !*need_alternate &&
((res->dispatchv4 == NULL &&
((res->dispatches4 == NULL &&
find->result_v6 == DNS_R_NXRRSET) ||
(res->dispatchv6 == NULL &&
(res->dispatches6 == NULL &&
find->result_v4 == DNS_R_NXRRSET)))
*need_alternate = ISC_TRUE;
dns_adb_destroyfind(&find);
@ -2662,9 +2668,9 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
while (sa != NULL) {
if ((isc_sockaddr_pf(sa) == AF_INET &&
fctx->res->dispatchv4 == NULL) ||
fctx->res->dispatches4 == NULL) ||
(isc_sockaddr_pf(sa) == AF_INET6 &&
fctx->res->dispatchv6 == NULL)) {
fctx->res->dispatches6 == NULL)) {
sa = ISC_LIST_NEXT(sa, link);
continue;
}
@ -2712,9 +2718,9 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
*/
stdoptions |= DNS_ADBFIND_AVOIDFETCHES;
}
if (res->dispatchv4 != NULL)
if (res->dispatches4 != NULL)
stdoptions |= DNS_ADBFIND_INET;
if (res->dispatchv6 != NULL)
if (res->dispatches6 != NULL)
stdoptions |= DNS_ADBFIND_INET6;
isc_stdtime_get(&now);
@ -2747,7 +2753,7 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
if (need_alternate) {
int family;
alternate_t *a;
family = (res->dispatchv6 != NULL) ? AF_INET6 : AF_INET;
family = (res->dispatches6 != NULL) ? AF_INET6 : AF_INET;
for (a = ISC_LIST_HEAD(fctx->res->alternates);
a != NULL;
a = ISC_LIST_NEXT(a, link)) {
@ -7363,10 +7369,10 @@ destroy(dns_resolver_t *res) {
}
isc_mem_put(res->mctx, res->buckets,
res->nbuckets * sizeof(fctxbucket_t));
if (res->dispatchv4 != NULL)
dns_dispatch_detach(&res->dispatchv4);
if (res->dispatchv6 != NULL)
dns_dispatch_detach(&res->dispatchv6);
if (res->dispatches4 != NULL)
dns_dispatchset_destroy(&res->dispatches4);
if (res->dispatches6 != NULL)
dns_dispatchset_destroy(&res->dispatches6);
while ((a = ISC_LIST_HEAD(res->alternates)) != NULL) {
ISC_LIST_UNLINK(res->alternates, a, link);
if (!a->isaddress)
@ -7456,7 +7462,8 @@ spillattimer_countdown(isc_task_t *task, isc_event_t *event) {
isc_result_t
dns_resolver_create(dns_view_t *view,
isc_taskmgr_t *taskmgr, unsigned int ntasks,
isc_taskmgr_t *taskmgr,
unsigned int ntasks, unsigned int ndisp,
isc_socketmgr_t *socketmgr,
isc_timermgr_t *timermgr,
unsigned int options,
@ -7478,6 +7485,7 @@ dns_resolver_create(dns_view_t *view,
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(ntasks > 0);
REQUIRE(ndisp > 0);
REQUIRE(resp != NULL && *resp == NULL);
REQUIRE(dispatchmgr != NULL);
REQUIRE(dispatchv4 != NULL || dispatchv6 != NULL);
@ -7508,8 +7516,6 @@ dns_resolver_create(dns_view_t *view,
res->spillattimer = NULL;
res->zero_no_soa_ttl = ISC_FALSE;
res->query_timeout = DEFAULT_QUERY_TIMEOUT;
res->ndisps = 0;
res->nextdisp = 0; /* meaningless at this point, but init it */
res->nbuckets = ntasks;
res->activebuckets = ntasks;
res->buckets = isc_mem_get(view->mctx,
@ -7552,17 +7558,19 @@ dns_resolver_create(dns_view_t *view,
buckets_created++;
}
res->dispatchv4 = NULL;
res->dispatches4 = NULL;
if (dispatchv4 != NULL) {
dns_dispatch_attach(dispatchv4, &res->dispatchv4);
dns_dispatchset_create(view->mctx, socketmgr, taskmgr,
dispatchv4, &res->dispatches4, ndisp);
dispattr = dns_dispatch_getattributes(dispatchv4);
res->exclusivev4 =
ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
}
res->dispatchv6 = NULL;
res->dispatches6 = NULL;
if (dispatchv6 != NULL) {
dns_dispatch_attach(dispatchv6, &res->dispatchv6);
dns_dispatchset_create(view->mctx, socketmgr, taskmgr,
dispatchv6, &res->dispatches6, ndisp);
dispattr = dns_dispatch_getattributes(dispatchv6);
res->exclusivev6 =
ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
@ -7638,10 +7646,10 @@ dns_resolver_create(dns_view_t *view,
DESTROYLOCK(&res->lock);
cleanup_dispatches:
if (res->dispatchv6 != NULL)
dns_dispatch_detach(&res->dispatchv6);
if (res->dispatchv4 != NULL)
dns_dispatch_detach(&res->dispatchv4);
if (res->dispatches6 != NULL)
dns_dispatchset_destroy(&res->dispatches6);
if (res->dispatches4 != NULL)
dns_dispatchset_destroy(&res->dispatches4);
cleanup_buckets:
for (i = 0; i < buckets_created; i++) {
@ -7830,7 +7838,6 @@ void
dns_resolver_shutdown(dns_resolver_t *res) {
unsigned int i;
fetchctx_t *fctx;
isc_socket_t *sock;
isc_result_t result;
REQUIRE(VALID_RESOLVER(res));
@ -7849,15 +7856,13 @@ dns_resolver_shutdown(dns_resolver_t *res) {
fctx != NULL;
fctx = ISC_LIST_NEXT(fctx, link))
fctx_shutdown(fctx);
if (res->dispatchv4 != NULL && !res->exclusivev4) {
sock = dns_dispatch_getsocket(res->dispatchv4);
isc_socket_cancel(sock, res->buckets[i].task,
ISC_SOCKCANCEL_ALL);
if (res->dispatches4 != NULL && !res->exclusivev4) {
dns_dispatchset_cancelall(res->dispatches4,
res->buckets[i].task);
}
if (res->dispatchv6 != NULL && !res->exclusivev6) {
sock = dns_dispatch_getsocket(res->dispatchv6);
isc_socket_cancel(sock, res->buckets[i].task,
ISC_SOCKCANCEL_ALL);
if (res->dispatches6 != NULL && !res->exclusivev6) {
dns_dispatchset_cancelall(res->dispatches6,
res->buckets[i].task);
}
res->buckets[i].exiting = ISC_TRUE;
if (ISC_LIST_EMPTY(res->buckets[i].fctxs)) {
@ -8240,13 +8245,13 @@ dns_resolver_dispatchmgr(dns_resolver_t *resolver) {
dns_dispatch_t *
dns_resolver_dispatchv4(dns_resolver_t *resolver) {
REQUIRE(VALID_RESOLVER(resolver));
return (resolver->dispatchv4);
return (dns_dispatchset_get(resolver->dispatches4));
}
dns_dispatch_t *
dns_resolver_dispatchv6(dns_resolver_t *resolver) {
REQUIRE(VALID_RESOLVER(resolver));
return (resolver->dispatchv6);
return (dns_dispatchset_get(resolver->dispatches6));
}
isc_socketmgr_t *

View file

@ -39,13 +39,15 @@ LIBS = @LIBS@ @ATFLIBS@
OBJS = dnstest.@O@
SRCS = dnstest.c master_test.c dbiterator_test.c time_test.c \
private_test.c update_test.c zonemgr_test.c zt_test.c \
dbdiff_test.c nsec3_test.c rdataset_test.c rdata_test.c
dbdiff_test.c dispatch_test.c nsec3_test.c \
rdataset_test.c rdata_test.c
SUBDIRS =
TARGETS = master_test@EXEEXT@ dbiterator_test@EXEEXT@ time_test@EXEEXT@ \
private_test@EXEEXT@ update_test@EXEEXT@ zonemgr_test@EXEEXT@ \
zt_test@EXEEXT@ dbversion_test@EXEEXT@ dbdiff_test@EXEEXT@ \
nsec3_test@EXEEXT@ rdataset_test@EXEEXT@ rdata_test@EXEEXT@
dispatch_test@EXEEXT@ nsec3_test@EXEEXT@ \
rdataset_test@EXEEXT@ rdata_test@EXEEXT@
@BIND9_MAKE_RULES@
@ -114,6 +116,16 @@ rdata_test@EXEEXT@: rdata_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
rdata_test.@O@ ${DNSLIBS} ${ISCLIBS} ${LIBS}
dispatch_test@EXEEXT@: dispatch_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
dispatch_test.@O@ dnstest.@O@ ${DNSLIBS} \
${ISCLIBS} ${LIBS}
dispatch_test@EXEEXT@: dispatch_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
dispatch_test.@O@ dnstest.@O@ ${DNSLIBS} \
${ISCLIBS} ${LIBS}
unit::
sh ${top_srcdir}/unit/unittest.sh

View file

@ -0,0 +1,160 @@
/*
* Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id$ */
/*! \file */
#include <config.h>
#include <atf-c.h>
#include <unistd.h>
#include <isc/buffer.h>
#include <isc/socket.h>
#include <isc/task.h>
#include <isc/timer.h>
#include <dns/dispatch.h>
#include <dns/name.h>
#include <dns/view.h>
#include "dnstest.h"
dns_dispatchmgr_t *dispatchmgr = NULL;
dns_dispatchset_t *dset = NULL;
static isc_result_t
make_dispatchset(unsigned int ndisps) {
isc_result_t result;
isc_sockaddr_t any;
unsigned int attrs;
dns_dispatch_t *disp = NULL;
result = dns_dispatchmgr_create(mctx, NULL, &dispatchmgr);
if (result != ISC_R_SUCCESS)
return (result);
isc_sockaddr_any(&any);
attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP;
result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
&any, 512, 6, 1024, 17, 19, attrs,
attrs, &disp);
if (result != ISC_R_SUCCESS)
return (result);
result = dns_dispatchset_create(mctx, socketmgr, taskmgr, disp,
&dset, ndisps);
dns_dispatch_detach(&disp);
return (result);
}
static void
teardown() {
if (dset != NULL)
dns_dispatchset_destroy(&dset);
if (dispatchmgr != NULL)
dns_dispatchmgr_destroy(&dispatchmgr);
}
/*
* Individual unit tests
*/
ATF_TC(dispatchset_create);
ATF_TC_HEAD(dispatchset_create, tc) {
atf_tc_set_md_var(tc, "descr", "create dispatch set");
}
ATF_TC_BODY(dispatchset_create, tc) {
isc_result_t result;
UNUSED(tc);
result = dns_test_begin(NULL, ISC_TRUE);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
result = make_dispatchset(1);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
teardown();
result = make_dispatchset(10);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
teardown();
dns_test_end();
}
ATF_TC(dispatchset_get);
ATF_TC_HEAD(dispatchset_get, tc) {
atf_tc_set_md_var(tc, "descr", "test dispatch set round-robin");
}
ATF_TC_BODY(dispatchset_get, tc) {
isc_result_t result;
dns_dispatch_t *d1, *d2, *d3, *d4, *d5;
UNUSED(tc);
result = dns_test_begin(NULL, ISC_TRUE);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
result = make_dispatchset(1);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
d1 = dns_dispatchset_get(dset);
d2 = dns_dispatchset_get(dset);
d3 = dns_dispatchset_get(dset);
d4 = dns_dispatchset_get(dset);
d5 = dns_dispatchset_get(dset);
ATF_CHECK_EQ(d1, d2);
ATF_CHECK_EQ(d2, d3);
ATF_CHECK_EQ(d3, d4);
ATF_CHECK_EQ(d4, d5);
teardown();
result = make_dispatchset(4);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
d1 = dns_dispatchset_get(dset);
d2 = dns_dispatchset_get(dset);
d3 = dns_dispatchset_get(dset);
d4 = dns_dispatchset_get(dset);
d5 = dns_dispatchset_get(dset);
ATF_CHECK_EQ(d1, d5);
ATF_CHECK(d1 != d2);
ATF_CHECK(d2 != d3);
ATF_CHECK(d3 != d4);
ATF_CHECK(d4 != d5);
teardown();
dns_test_end();
}
/*
* Main
*/
ATF_TP_ADD_TCS(tp) {
ATF_TP_ADD_TC(tp, dispatchset_create);
ATF_TP_ADD_TC(tp, dispatchset_get);
return (atf_no_error());
}

View file

@ -35,6 +35,7 @@
#include <dns/adb.h>
#include <dns/cache.h>
#include <dns/db.h>
#include <dns/dispatch.h>
#include <dns/dlz.h>
#ifdef BIND9
#include <dns/dns64.h>
@ -670,7 +671,8 @@ req_shutdown(isc_task_t *task, isc_event_t *event) {
isc_result_t
dns_view_createresolver(dns_view_t *view,
isc_taskmgr_t *taskmgr, unsigned int ntasks,
isc_taskmgr_t *taskmgr,
unsigned int ntasks, unsigned int ndisp,
isc_socketmgr_t *socketmgr,
isc_timermgr_t *timermgr,
unsigned int options,
@ -691,7 +693,7 @@ dns_view_createresolver(dns_view_t *view,
return (result);
isc_task_setname(view->task, "view", view);
result = dns_resolver_create(view, taskmgr, ntasks, socketmgr,
result = dns_resolver_create(view, taskmgr, ntasks, ndisp, socketmgr,
timermgr, options, dispatchmgr,
dispatchv4, dispatchv6,
&view->resolver);
@ -723,8 +725,7 @@ dns_view_createresolver(dns_view_t *view,
result = dns_requestmgr_create(view->mctx, timermgr, socketmgr,
dns_resolver_taskmgr(view->resolver),
dns_resolver_dispatchmgr(view->resolver),
dns_resolver_dispatchv4(view->resolver),
dns_resolver_dispatchv6(view->resolver),
dispatchv4, dispatchv6,
&view->requestmgr);
if (result != ISC_R_SUCCESS) {
dns_adb_shutdown(view->adb);

View file

@ -191,6 +191,10 @@ dns_dispatchmgr_setavailports
dns_dispatchmgr_setblackhole
dns_dispatchmgr_setblackportlist
dns_dispatchmgr_setstats
dns_dispatchset_cancelall
dns_dispatchset_create
dns_dispatchset_destroy
dns_dispatchset_get
dns_dlz_writeablezone
dns_dlzallowzonexfr
dns_dlzconfigure

View file

@ -283,12 +283,20 @@ typedef struct isc_socketmethods {
isc_task_t *task, isc_taskaction_t action,
const void *arg, isc_sockaddr_t *address,
struct in6_pktinfo *pktinfo);
isc_result_t (*sendto2)(isc_socket_t *sock, isc_region_t *region,
isc_task_t *task, isc_sockaddr_t *address,
struct in6_pktinfo *pktinfo,
isc_socketevent_t *event,
unsigned int flags);
isc_result_t (*connect)(isc_socket_t *sock, isc_sockaddr_t *addr,
isc_task_t *task, isc_taskaction_t action,
const void *arg);
isc_result_t (*recv)(isc_socket_t *sock, isc_region_t *region,
unsigned int minimum, isc_task_t *task,
isc_taskaction_t action, const void *arg);
isc_result_t (*recv2)(isc_socket_t *sock, isc_region_t *region,
unsigned int minimum, isc_task_t *task,
isc_socketevent_t *event, unsigned int flags);
void (*cancel)(isc_socket_t *sock, isc_task_t *task,
unsigned int how);
isc_result_t (*getsockname)(isc_socket_t *sock,

View file

@ -140,6 +140,18 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region, isc_task_t *task,
pktinfo));
}
isc_result_t
isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
isc_task_t *task, isc_sockaddr_t *address,
struct in6_pktinfo *pktinfo, isc_socketevent_t *event,
unsigned int flags)
{
REQUIRE(ISCAPI_SOCKET_VALID(sock));
return (sock->methods->sendto2(sock, region, task, address,
pktinfo, event, flags));
}
isc_result_t
isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, isc_task_t *task,
isc_taskaction_t action, const void *arg)
@ -158,6 +170,17 @@ isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
return (sock->methods->recv(sock, region, minimum, task, action, arg));
}
isc_result_t
isc_socket_recv2(isc_socket_t *sock, isc_region_t *region,
unsigned int minimum, isc_task_t *task,
isc_socketevent_t *event, unsigned int flags)
{
REQUIRE(ISCAPI_SOCKET_VALID(sock));
return (sock->methods->recv2(sock, region, minimum, task,
event, flags));
}
void
isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
REQUIRE(ISCAPI_SOCKET_VALID(sock));

View file

@ -572,8 +572,10 @@ static struct {
isc__socket_detach,
isc__socket_bind,
isc__socket_sendto,
isc__socket_sendto2,
isc__socket_connect,
isc__socket_recv,
isc__socket_recv2,
isc__socket_cancel,
isc__socket_getsockname,
isc__socket_gettype,