2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-04 08:35:31 +00:00

make dispatcher hash sizes be primes, and provide an increment to help

resolve hash collisions
This commit is contained in:
Michael Graff
1999-12-15 17:14:52 +00:00
parent 271154eafd
commit 607dc8013a
8 changed files with 46 additions and 40 deletions

View File

@@ -146,11 +146,11 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
/* /*
* XXXRTH hardwired constants. We're going to need to determine if * XXXRTH hardwired constants. We're going to need to determine if
* this UDP socket will be shared with the resolver, and if so, we * this UDP socket will be shared with the resolver, and if so, we
* need to set the hashsize to be be something bigger than 4. * need to set the hashsize to be be something bigger than 17.
*/ */
ifp->udpdispatch = NULL; ifp->udpdispatch = NULL;
result = dns_dispatch_create(mgr->mctx, ifp->udpsocket, ifp->task, result = dns_dispatch_create(mgr->mctx, ifp->udpsocket, ifp->task,
4096, 50, 50, 4, &ifp->udpdispatch); 4096, 50, 50, 17, 19, &ifp->udpdispatch);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__, UNEXPECTED_ERROR(__FILE__, __LINE__,
"UDP dns_dispatch_create(): %s", "UDP dns_dispatch_create(): %s",

View File

@@ -107,7 +107,7 @@ my_accept(isc_task_t *task, isc_event_t *ev_in)
*/ */
disp = NULL; disp = NULL;
RUNTIME_CHECK(dns_dispatch_create(mctx, ev->newsocket, task, RUNTIME_CHECK(dns_dispatch_create(mctx, ev->newsocket, task,
512, 6, 1024, 4, &disp) 512, 6, 1024, 17, 19, &disp)
== ISC_R_SUCCESS); == ISC_R_SUCCESS);
resp = NULL; resp = NULL;

View File

@@ -405,7 +405,7 @@ main(int argc, char *argv[])
*/ */
disp = NULL; disp = NULL;
RUNTIME_CHECK(dns_dispatch_create(mctx, s0, t0, 512, 6, 1024, RUNTIME_CHECK(dns_dispatch_create(mctx, s0, t0, 512, 6, 1024,
4, &disp) == ISC_R_SUCCESS); 17, 19, &disp) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_mutex_init(&client_lock) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_mutex_init(&client_lock) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_mutex_lock(&client_lock) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_mutex_lock(&client_lock) == ISC_R_SUCCESS);

View File

@@ -205,8 +205,8 @@ main(int argc, char *argv[]) {
&view) == ISC_R_SUCCESS); &view) == ISC_R_SUCCESS);
dispatch = NULL; dispatch = NULL;
RUNTIME_CHECK(dns_dispatch_create(mctx, s, task1, 4096, 1000, 1000, 4, RUNTIME_CHECK(dns_dispatch_create(mctx, s, task1, 4096, 1000, 1000,
&dispatch) == DNS_R_SUCCESS); 17, 19, &dispatch) == DNS_R_SUCCESS);
#ifdef notyet #ifdef notyet
res = NULL; res = NULL;

View File

@@ -57,7 +57,7 @@ struct dns_dispentry {
ISC_LINK(dns_dispentry_t) link; ISC_LINK(dns_dispentry_t) link;
}; };
#define INVALID_BUCKET (0xffffdead) #define INVALID_BUCKET (0xffffdead)
typedef ISC_LIST(dns_dispentry_t) dns_displist_t; typedef ISC_LIST(dns_dispentry_t) dns_displist_t;
@@ -89,8 +89,8 @@ struct dns_dispatch {
ISC_LIST(dns_dispatchevent_t) rq_events; /* holder for rq events */ ISC_LIST(dns_dispatchevent_t) rq_events; /* holder for rq events */
dns_tcpmsg_t tcpmsg; /* for tcp streams */ dns_tcpmsg_t tcpmsg; /* for tcp streams */
isc_lfsr_t qid_lfsr; /* state generator info */ isc_lfsr_t qid_lfsr; /* state generator info */
unsigned int qid_hashsize; /* hash table size */ unsigned int qid_nbuckets; /* hash table size */
unsigned int qid_mask; /* mask for hash table */ unsigned int qid_increment; /* id increment on collision */
dns_displist_t *qid_table; /* the table itself */ dns_displist_t *qid_table; /* the table itself */
}; };
@@ -146,7 +146,7 @@ linear_first(dns_dispatch_t *disp)
bucket = 0; bucket = 0;
while (bucket < disp->qid_hashsize) { while (bucket < disp->qid_nbuckets) {
ret = ISC_LIST_HEAD(disp->qid_table[bucket]); ret = ISC_LIST_HEAD(disp->qid_table[bucket]);
if (ret != NULL) if (ret != NULL)
return (ret); return (ret);
@@ -167,7 +167,7 @@ linear_next(dns_dispatch_t *disp, dns_dispentry_t *resp)
return (ret); return (ret);
bucket = resp->bucket; bucket = resp->bucket;
while (bucket < disp->qid_hashsize) { while (bucket < disp->qid_nbuckets) {
ret = ISC_LIST_HEAD(disp->qid_table[bucket]); ret = ISC_LIST_HEAD(disp->qid_table[bucket]);
if (ret != NULL) if (ret != NULL)
return (ret); return (ret);
@@ -178,20 +178,18 @@ linear_next(dns_dispatch_t *disp, dns_dispentry_t *resp)
} }
/* /*
* Return a hash of the destination and message id. For now, just return * Return a hash of the destination and message id.
* the message id bits, and mask off the low order bits of that.
*/ */
static unsigned int static unsigned int
hash(dns_dispatch_t *disp, isc_sockaddr_t *dest, dns_messageid_t id) hash(dns_dispatch_t *disp, isc_sockaddr_t *dest, dns_messageid_t id)
{ {
unsigned int ret; unsigned int ret;
(void)dest; /* shut up compiler warning. */ ret = isc_sockaddr_hash(dest, ISC_TRUE);
ret ^= (id & 0x0000ffff); /* important to mask off garbage bits */
ret %= disp->qid_nbuckets;
ret = id; INSIST(ret < disp->qid_nbuckets);
ret &= disp->qid_mask;
INSIST(ret < disp->qid_hashsize);
return (ret); return (ret);
} }
@@ -235,7 +233,7 @@ destroy(dns_dispatch_t *disp)
isc_mempool_destroy(&disp->bpool); isc_mempool_destroy(&disp->bpool);
isc_mempool_destroy(&disp->epool); isc_mempool_destroy(&disp->epool);
isc_mem_put(disp->mctx, disp->qid_table, isc_mem_put(disp->mctx, disp->qid_table,
disp->qid_hashsize * sizeof(dns_displist_t)); disp->qid_nbuckets * sizeof(dns_displist_t));
isc_mem_put(disp->mctx, disp, sizeof(dns_dispatch_t)); isc_mem_put(disp->mctx, disp, sizeof(dns_dispatch_t));
} }
@@ -247,7 +245,7 @@ bucket_search(dns_dispatch_t *disp, isc_sockaddr_t *dest, dns_messageid_t id,
{ {
dns_dispentry_t *res; dns_dispentry_t *res;
REQUIRE(bucket < disp->qid_hashsize); REQUIRE(bucket < disp->qid_nbuckets);
res = ISC_LIST_HEAD(disp->qid_table[bucket]); res = ISC_LIST_HEAD(disp->qid_table[bucket]);
@@ -775,11 +773,10 @@ isc_result_t
dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task, dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
unsigned int maxbuffersize, unsigned int maxbuffersize,
unsigned int maxbuffers, unsigned int maxrequests, unsigned int maxbuffers, unsigned int maxrequests,
unsigned int hashsize, unsigned int buckets, unsigned int increment,
dns_dispatch_t **dispp) dns_dispatch_t **dispp)
{ {
dns_dispatch_t *disp; dns_dispatch_t *disp;
unsigned int tablesize;
isc_result_t res; isc_result_t res;
isc_sockettype_t socktype; isc_sockettype_t socktype;
unsigned int i; unsigned int i;
@@ -787,7 +784,8 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
REQUIRE(mctx != NULL); REQUIRE(mctx != NULL);
REQUIRE(sock != NULL); REQUIRE(sock != NULL);
REQUIRE(task != NULL); REQUIRE(task != NULL);
REQUIRE(hashsize <= 24); REQUIRE(buckets < 2097169); /* next prime > 65536 * 32 */
REQUIRE(increment > buckets);
REQUIRE(maxbuffersize >= 512 && maxbuffersize < (64 * 1024)); REQUIRE(maxbuffersize >= 512 && maxbuffersize < (64 * 1024));
REQUIRE(maxbuffers > 0); REQUIRE(maxbuffers > 0);
REQUIRE(dispp != NULL && *dispp == NULL); REQUIRE(dispp != NULL && *dispp == NULL);
@@ -822,20 +820,18 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
ISC_LIST_INIT(disp->rq_handlers); ISC_LIST_INIT(disp->rq_handlers);
ISC_LIST_INIT(disp->rq_events); ISC_LIST_INIT(disp->rq_events);
tablesize = (1 << hashsize);
disp->qid_table = isc_mem_get(disp->mctx, disp->qid_table = isc_mem_get(disp->mctx,
tablesize * sizeof(dns_displist_t)); buckets * sizeof(dns_displist_t));
if (disp->qid_table == NULL) { if (disp->qid_table == NULL) {
res = DNS_R_NOMEMORY; res = DNS_R_NOMEMORY;
goto out1; goto out1;
} }
for (i = 0 ; i < tablesize ; i++) for (i = 0 ; i < buckets ; i++)
ISC_LIST_INIT(disp->qid_table[i]); ISC_LIST_INIT(disp->qid_table[i]);
disp->qid_mask = tablesize - 1; disp->qid_nbuckets = buckets;
disp->qid_hashsize = tablesize; disp->qid_increment = increment;
if (isc_mutex_init(&disp->lock) != ISC_R_SUCCESS) { if (isc_mutex_init(&disp->lock) != ISC_R_SUCCESS) {
res = DNS_R_UNEXPECTED; res = DNS_R_UNEXPECTED;
@@ -924,7 +920,7 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
out3: out3:
isc_mutex_destroy(&disp->lock); isc_mutex_destroy(&disp->lock);
out2: out2:
isc_mem_put(mctx, disp->mctx, disp->qid_hashsize * sizeof(void *)); isc_mem_put(mctx, disp->mctx, disp->qid_nbuckets * sizeof(void *));
out1: out1:
isc_mem_put(mctx, disp, sizeof(dns_dispatch_t)); isc_mem_put(mctx, disp, sizeof(dns_dispatch_t));
@@ -1015,7 +1011,8 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
ok = ISC_TRUE; ok = ISC_TRUE;
break; break;
} }
id = randomid(disp); id += disp->qid_increment;
id &= 0x0000ffff;
bucket = hash(disp, dest, id); bucket = hash(disp, dest, id);
} }

View File

@@ -91,7 +91,8 @@ isc_result_t
dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task, dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
unsigned int maxbuffersize, unsigned int maxbuffersize,
unsigned int maxbuffers, unsigned int maxrequests, unsigned int maxbuffers, unsigned int maxrequests,
unsigned int hashsize, dns_dispatch_t **dispp); unsigned int buckets, unsigned int increment,
dns_dispatch_t **dispp);
/* /*
* Create a new dns_dispatch and attach it to the provided isc_socket_t. * Create a new dns_dispatch and attach it to the provided isc_socket_t.
* *
@@ -102,8 +103,10 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
* overall system and the number of buffers which can be allocated to * overall system and the number of buffers which can be allocated to
* requests. * requests.
* *
* "hashsize" is the size of the hash table used to handle responses. The * "buckets" is the number of buckets to use, and should be prime.
* size is 2^hashsize, maximum of 2^24. *
* "increment" is used in a collision avoidance function, and needs to be
* a prime > buckets, and not 2.
* *
* Requires: * Requires:
* *
@@ -120,7 +123,9 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
* *
* maxrequests <= maxbuffers. * maxrequests <= maxbuffers.
* *
* hashsize <= 24. * buckets < 2097169 (the next prime after 65536 * 32)
*
* increment > buckets (and prime)
*/ */
void void

View File

@@ -594,7 +594,8 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto cleanup_query; goto cleanup_query;
result = dns_dispatch_create(res->mctx, socket, task, result = dns_dispatch_create(res->mctx, socket, task,
4096, 2, 1, 1, &query->dispatch); 4096, 2, 1, 1, 3,
&query->dispatch);
/* /*
* Regardless of whether dns_dispatch_create() succeeded or * Regardless of whether dns_dispatch_create() succeeded or
* not, we don't need our reference to the socket anymore. * not, we don't need our reference to the socket anymore.
@@ -3226,7 +3227,8 @@ dns_resolver_create(dns_view_t *view,
} }
result = dns_dispatch_create(res->mctx, res->udpsocket4, result = dns_dispatch_create(res->mctx, res->udpsocket4,
res->buckets[0].task, 4096, res->buckets[0].task, 4096,
1000, 32768, 14, &res->dispatch4); 1000, 32768, 16411, 16433,
&res->dispatch4);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto cleanup_udpsocket4; goto cleanup_udpsocket4;
} }
@@ -3247,7 +3249,8 @@ dns_resolver_create(dns_view_t *view,
goto cleanup_dispatch4; goto cleanup_dispatch4;
result = dns_dispatch_create(res->mctx, res->udpsocket6, result = dns_dispatch_create(res->mctx, res->udpsocket6,
res->buckets[0].task, 4096, res->buckets[0].task, 4096,
1000, 32768, 14, &res->dispatch6); 1000, 32768, 16411, 16433,
&res->dispatch6);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto cleanup_udpsocket6; goto cleanup_udpsocket6;
} }

View File

@@ -15,7 +15,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
/* $Id: zone.c,v 1.44 1999/12/13 07:56:26 marka Exp $ */ /* $Id: zone.c,v 1.45 1999/12/15 17:14:52 explorer Exp $ */
#include <config.h> #include <config.h>
@@ -1815,7 +1815,8 @@ dns_zone_manage(dns_zone_t *zone, isc_taskmgr_t *tmgr) {
isc_sockettype_udp, &s) == ISC_R_SUCCESS); isc_sockettype_udp, &s) == ISC_R_SUCCESS);
dispatch = NULL; dispatch = NULL;
RUNTIME_CHECK(dns_dispatch_create(zone->mctx, s, zone->task, RUNTIME_CHECK(dns_dispatch_create(zone->mctx, s, zone->task,
4096, 1000, 1000, 4, &dispatch) == DNS_R_SUCCESS); 4096, 1000, 1000, 17, 19,
&dispatch) == DNS_R_SUCCESS);
result = dns_resolver_create(zone->mctx, tmgr, 10, zone->timgr, result = dns_resolver_create(zone->mctx, tmgr, 10, zone->timgr,
zone->rdclass, dispatch, zone->rdclass, dispatch,
&zone->res); &zone->res);