mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-03 08:05:21 +00:00
make dispatcher hash sizes be primes, and provide an increment to help
resolve hash collisions
This commit is contained in:
@@ -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
|
||||
* 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;
|
||||
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) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"UDP dns_dispatch_create(): %s",
|
||||
|
@@ -107,7 +107,7 @@ my_accept(isc_task_t *task, isc_event_t *ev_in)
|
||||
*/
|
||||
disp = NULL;
|
||||
RUNTIME_CHECK(dns_dispatch_create(mctx, ev->newsocket, task,
|
||||
512, 6, 1024, 4, &disp)
|
||||
512, 6, 1024, 17, 19, &disp)
|
||||
== ISC_R_SUCCESS);
|
||||
|
||||
resp = NULL;
|
||||
|
@@ -405,7 +405,7 @@ main(int argc, char *argv[])
|
||||
*/
|
||||
disp = NULL;
|
||||
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_lock(&client_lock) == ISC_R_SUCCESS);
|
||||
|
@@ -205,8 +205,8 @@ main(int argc, char *argv[]) {
|
||||
&view) == ISC_R_SUCCESS);
|
||||
|
||||
dispatch = NULL;
|
||||
RUNTIME_CHECK(dns_dispatch_create(mctx, s, task1, 4096, 1000, 1000, 4,
|
||||
&dispatch) == DNS_R_SUCCESS);
|
||||
RUNTIME_CHECK(dns_dispatch_create(mctx, s, task1, 4096, 1000, 1000,
|
||||
17, 19, &dispatch) == DNS_R_SUCCESS);
|
||||
|
||||
#ifdef notyet
|
||||
res = NULL;
|
||||
|
@@ -89,8 +89,8 @@ struct dns_dispatch {
|
||||
ISC_LIST(dns_dispatchevent_t) rq_events; /* holder for rq events */
|
||||
dns_tcpmsg_t tcpmsg; /* for tcp streams */
|
||||
isc_lfsr_t qid_lfsr; /* state generator info */
|
||||
unsigned int qid_hashsize; /* hash table size */
|
||||
unsigned int qid_mask; /* mask for hash table */
|
||||
unsigned int qid_nbuckets; /* hash table size */
|
||||
unsigned int qid_increment; /* id increment on collision */
|
||||
dns_displist_t *qid_table; /* the table itself */
|
||||
};
|
||||
|
||||
@@ -146,7 +146,7 @@ linear_first(dns_dispatch_t *disp)
|
||||
|
||||
bucket = 0;
|
||||
|
||||
while (bucket < disp->qid_hashsize) {
|
||||
while (bucket < disp->qid_nbuckets) {
|
||||
ret = ISC_LIST_HEAD(disp->qid_table[bucket]);
|
||||
if (ret != NULL)
|
||||
return (ret);
|
||||
@@ -167,7 +167,7 @@ linear_next(dns_dispatch_t *disp, dns_dispentry_t *resp)
|
||||
return (ret);
|
||||
|
||||
bucket = resp->bucket;
|
||||
while (bucket < disp->qid_hashsize) {
|
||||
while (bucket < disp->qid_nbuckets) {
|
||||
ret = ISC_LIST_HEAD(disp->qid_table[bucket]);
|
||||
if (ret != NULL)
|
||||
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
|
||||
* the message id bits, and mask off the low order bits of that.
|
||||
* Return a hash of the destination and message id.
|
||||
*/
|
||||
static unsigned int
|
||||
hash(dns_dispatch_t *disp, isc_sockaddr_t *dest, dns_messageid_t id)
|
||||
{
|
||||
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;
|
||||
ret &= disp->qid_mask;
|
||||
|
||||
INSIST(ret < disp->qid_hashsize);
|
||||
INSIST(ret < disp->qid_nbuckets);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@@ -235,7 +233,7 @@ destroy(dns_dispatch_t *disp)
|
||||
isc_mempool_destroy(&disp->bpool);
|
||||
isc_mempool_destroy(&disp->epool);
|
||||
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));
|
||||
}
|
||||
@@ -247,7 +245,7 @@ bucket_search(dns_dispatch_t *disp, isc_sockaddr_t *dest, dns_messageid_t id,
|
||||
{
|
||||
dns_dispentry_t *res;
|
||||
|
||||
REQUIRE(bucket < disp->qid_hashsize);
|
||||
REQUIRE(bucket < disp->qid_nbuckets);
|
||||
|
||||
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,
|
||||
unsigned int maxbuffersize,
|
||||
unsigned int maxbuffers, unsigned int maxrequests,
|
||||
unsigned int hashsize,
|
||||
unsigned int buckets, unsigned int increment,
|
||||
dns_dispatch_t **dispp)
|
||||
{
|
||||
dns_dispatch_t *disp;
|
||||
unsigned int tablesize;
|
||||
isc_result_t res;
|
||||
isc_sockettype_t socktype;
|
||||
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(sock != NULL);
|
||||
REQUIRE(task != NULL);
|
||||
REQUIRE(hashsize <= 24);
|
||||
REQUIRE(buckets < 2097169); /* next prime > 65536 * 32 */
|
||||
REQUIRE(increment > buckets);
|
||||
REQUIRE(maxbuffersize >= 512 && maxbuffersize < (64 * 1024));
|
||||
REQUIRE(maxbuffers > 0);
|
||||
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_events);
|
||||
|
||||
tablesize = (1 << hashsize);
|
||||
|
||||
disp->qid_table = isc_mem_get(disp->mctx,
|
||||
tablesize * sizeof(dns_displist_t));
|
||||
buckets * sizeof(dns_displist_t));
|
||||
if (disp->qid_table == NULL) {
|
||||
res = DNS_R_NOMEMORY;
|
||||
goto out1;
|
||||
}
|
||||
|
||||
for (i = 0 ; i < tablesize ; i++)
|
||||
for (i = 0 ; i < buckets ; i++)
|
||||
ISC_LIST_INIT(disp->qid_table[i]);
|
||||
|
||||
disp->qid_mask = tablesize - 1;
|
||||
disp->qid_hashsize = tablesize;
|
||||
disp->qid_nbuckets = buckets;
|
||||
disp->qid_increment = increment;
|
||||
|
||||
if (isc_mutex_init(&disp->lock) != ISC_R_SUCCESS) {
|
||||
res = DNS_R_UNEXPECTED;
|
||||
@@ -924,7 +920,7 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
|
||||
out3:
|
||||
isc_mutex_destroy(&disp->lock);
|
||||
out2:
|
||||
isc_mem_put(mctx, disp->mctx, disp->qid_hashsize * sizeof(void *));
|
||||
isc_mem_put(mctx, disp->mctx, disp->qid_nbuckets * sizeof(void *));
|
||||
out1:
|
||||
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;
|
||||
break;
|
||||
}
|
||||
id = randomid(disp);
|
||||
id += disp->qid_increment;
|
||||
id &= 0x0000ffff;
|
||||
bucket = hash(disp, dest, id);
|
||||
}
|
||||
|
||||
|
@@ -91,7 +91,8 @@ isc_result_t
|
||||
dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
|
||||
unsigned int maxbuffersize,
|
||||
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.
|
||||
*
|
||||
@@ -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
|
||||
* requests.
|
||||
*
|
||||
* "hashsize" is the size of the hash table used to handle responses. The
|
||||
* size is 2^hashsize, maximum of 2^24.
|
||||
* "buckets" is the number of buckets to use, and should be prime.
|
||||
*
|
||||
* "increment" is used in a collision avoidance function, and needs to be
|
||||
* a prime > buckets, and not 2.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
@@ -120,7 +123,9 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
|
||||
*
|
||||
* maxrequests <= maxbuffers.
|
||||
*
|
||||
* hashsize <= 24.
|
||||
* buckets < 2097169 (the next prime after 65536 * 32)
|
||||
*
|
||||
* increment > buckets (and prime)
|
||||
*/
|
||||
|
||||
void
|
||||
|
@@ -594,7 +594,8 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_query;
|
||||
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
|
||||
* 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,
|
||||
res->buckets[0].task, 4096,
|
||||
1000, 32768, 14, &res->dispatch4);
|
||||
1000, 32768, 16411, 16433,
|
||||
&res->dispatch4);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_udpsocket4;
|
||||
}
|
||||
@@ -3247,7 +3249,8 @@ dns_resolver_create(dns_view_t *view,
|
||||
goto cleanup_dispatch4;
|
||||
result = dns_dispatch_create(res->mctx, res->udpsocket6,
|
||||
res->buckets[0].task, 4096,
|
||||
1000, 32768, 14, &res->dispatch6);
|
||||
1000, 32768, 16411, 16433,
|
||||
&res->dispatch6);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_udpsocket6;
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* 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>
|
||||
|
||||
@@ -1815,7 +1815,8 @@ dns_zone_manage(dns_zone_t *zone, isc_taskmgr_t *tmgr) {
|
||||
isc_sockettype_udp, &s) == ISC_R_SUCCESS);
|
||||
dispatch = NULL;
|
||||
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,
|
||||
zone->rdclass, dispatch,
|
||||
&zone->res);
|
||||
|
Reference in New Issue
Block a user