diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c index 95a3dbf7cf..2ec9c7288a 100644 --- a/bin/named/interfacemgr.c +++ b/bin/named/interfacemgr.c @@ -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", diff --git a/bin/tests/dispatch_tcp_test.c b/bin/tests/dispatch_tcp_test.c index 278b4c774e..a8a4ab8dbc 100644 --- a/bin/tests/dispatch_tcp_test.c +++ b/bin/tests/dispatch_tcp_test.c @@ -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; diff --git a/bin/tests/dispatch_test.c b/bin/tests/dispatch_test.c index 4abafc57c3..038d07a9e4 100644 --- a/bin/tests/dispatch_test.c +++ b/bin/tests/dispatch_test.c @@ -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); diff --git a/bin/tests/res_test.c b/bin/tests/res_test.c index f0b3ad5323..faa7fb73c8 100644 --- a/bin/tests/res_test.c +++ b/bin/tests/res_test.c @@ -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; diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index 8f642ef509..ba6ee2bc4c 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -57,7 +57,7 @@ struct dns_dispentry { ISC_LINK(dns_dispentry_t) link; }; -#define INVALID_BUCKET (0xffffdead) +#define INVALID_BUCKET (0xffffdead) 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 */ 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); } diff --git a/lib/dns/include/dns/dispatch.h b/lib/dns/include/dns/dispatch.h index ca719fb8a2..f973b61986 100644 --- a/lib/dns/include/dns/dispatch.h +++ b/lib/dns/include/dns/dispatch.h @@ -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 diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 18c712d180..bd026819d9 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -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; } diff --git a/lib/dns/zone.c b/lib/dns/zone.c index cabe07f7cc..cfb3bb1fd1 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -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 @@ -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);