diff --git a/bin/plugins/filter-a.c b/bin/plugins/filter-a.c index 2ba52df081..ac05305e18 100644 --- a/bin/plugins/filter-a.c +++ b/bin/plugins/filter-a.c @@ -347,7 +347,7 @@ plugin_register(const char *parameters, const void *cfg, const char *cfg_file, cfg_line, mctx, lctx, actx)); } - isc_ht_init(&inst->ht, mctx, 16); + isc_ht_init(&inst->ht, mctx, 1, ISC_HT_CASE_SENSITIVE); isc_mutex_init(&inst->hlock); /* diff --git a/bin/plugins/filter-aaaa.c b/bin/plugins/filter-aaaa.c index 7f6fac12ac..a83f0f5dde 100644 --- a/bin/plugins/filter-aaaa.c +++ b/bin/plugins/filter-aaaa.c @@ -350,7 +350,7 @@ plugin_register(const char *parameters, const void *cfg, const char *cfg_file, cfg_line, mctx, lctx, actx)); } - isc_ht_init(&inst->ht, mctx, 16); + isc_ht_init(&inst->ht, mctx, 1, ISC_HT_CASE_SENSITIVE); isc_mutex_init(&inst->hlock); /* diff --git a/bin/tests/system/hooks/driver/test-async.c b/bin/tests/system/hooks/driver/test-async.c index 577d5de6f8..90ff1fb33a 100644 --- a/bin/tests/system/hooks/driver/test-async.c +++ b/bin/tests/system/hooks/driver/test-async.c @@ -143,7 +143,7 @@ plugin_register(const char *parameters, const void *cfg, const char *cfg_file, *inst = (async_instance_t){ .mctx = NULL }; isc_mem_attach(mctx, &inst->mctx); - isc_ht_init(&inst->ht, mctx, 16); + isc_ht_init(&inst->ht, mctx, 1, ISC_HT_CASE_SENSITIVE); isc_mutex_init(&inst->hlock); /* diff --git a/lib/dns/catz.c b/lib/dns/catz.c index b02157618a..9be7b91ed8 100644 --- a/lib/dns/catz.c +++ b/lib/dns/catz.c @@ -392,9 +392,9 @@ dns_catz_zones_merge(dns_catz_zone_t *target, dns_catz_zone_t *newzone) { dns_name_format(&target->name, czname, DNS_NAME_FORMATSIZE); - isc_ht_init(&toadd, target->catzs->mctx, 16); + isc_ht_init(&toadd, target->catzs->mctx, 1, ISC_HT_CASE_SENSITIVE); - isc_ht_init(&tomod, target->catzs->mctx, 16); + isc_ht_init(&tomod, target->catzs->mctx, 1, ISC_HT_CASE_SENSITIVE); isc_ht_iter_create(newzone->entries, &iter1); @@ -579,7 +579,7 @@ dns_catz_new_zones(dns_catz_zones_t **catzsp, dns_catz_zonemodmethods_t *zmm, isc_refcount_init(&new_zones->refs, 1); - isc_ht_init(&new_zones->zones, mctx, 4); + isc_ht_init(&new_zones->zones, mctx, 4, ISC_HT_CASE_SENSITIVE); isc_mem_attach(mctx, &new_zones->mctx); new_zones->zmm = zmm; @@ -630,7 +630,7 @@ dns_catz_new_zone(dns_catz_zones_t *catzs, dns_catz_zone_t **zonep, dns_name_init(&new_zone->name, NULL); dns_name_dup(name, catzs->mctx, &new_zone->name); - isc_ht_init(&new_zone->entries, catzs->mctx, 4); + isc_ht_init(&new_zone->entries, catzs->mctx, 4, ISC_HT_CASE_SENSITIVE); new_zone->updatetimer = NULL; isc_timer_create(catzs->timermgr, catzs->updater, diff --git a/lib/dns/name.c b/lib/dns/name.c index f1939d27d1..58cdc100a5 100644 --- a/lib/dns/name.c +++ b/lib/dns/name.c @@ -466,7 +466,6 @@ dns_name_hash(const dns_name_t *name, bool case_sensitive) { length = 16; } - /* High bits are more random. */ return (isc_hash32(name->ndata, length, case_sensitive)); } @@ -481,7 +480,6 @@ dns_name_fullhash(const dns_name_t *name, bool case_sensitive) { return (0); } - /* High bits are more random. */ return (isc_hash32(name->ndata, name->length, case_sensitive)); } diff --git a/lib/dns/rbt.c b/lib/dns/rbt.c index 0bdaaf8a8a..8cc2e3b1d8 100644 --- a/lib/dns/rbt.c +++ b/lib/dns/rbt.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -60,24 +61,8 @@ #define CHAIN_MAGIC ISC_MAGIC('0', '-', '0', '-') #define VALID_CHAIN(chain) ISC_MAGIC_VALID(chain, CHAIN_MAGIC) -#define RBT_HASH_NO_BITS 0 -#define RBT_HASH_MIN_BITS 4 -#define RBT_HASH_MAX_BITS 32 -#define RBT_HASH_OVERCOMMIT 3 - #define RBT_HASH_NEXTTABLE(hindex) ((hindex == 0) ? 1 : 0) -#define GOLDEN_RATIO_32 0x61C88647 - -#define HASHSIZE(bits) (UINT64_C(1) << (bits)) - -static uint32_t -hash_32(uint32_t val, unsigned int bits) { - REQUIRE(bits <= RBT_HASH_MAX_BITS); - /* High bits are more random. */ - return (val * GOLDEN_RATIO_32 >> (32 - bits)); -} - struct dns_rbt { unsigned int magic; isc_mem_t *mctx; @@ -322,7 +307,7 @@ dns_rbt_create(isc_mem_t *mctx, dns_rbtdeleter_t deleter, void *deleter_arg, isc_mem_attach(mctx, &rbt->mctx); - hashtable_new(rbt, 0, RBT_HASH_MIN_BITS); + hashtable_new(rbt, 0, ISC_HASH_MIN_BITS); rbt->magic = RBT_MAGIC; @@ -932,7 +917,7 @@ dns_rbt_findnode(dns_rbt_t *rbt, const dns_name_t *name, dns_name_t *foundname, * by the computed hash value. */ - hash = hash_32(hashval, rbt->hashbits[hindex]); + hash = isc_hash_bits32(hashval, rbt->hashbits[hindex]); for (hnode = rbt->hashtable[hindex][hash]; hnode != NULL; hnode = HASHNEXT(hnode)) @@ -1616,7 +1601,7 @@ hash_add_node(dns_rbt_t *rbt, dns_rbtnode_t *node, const dns_name_t *name) { HASHVAL(node) = dns_name_fullhash(name, false); - hash = hash_32(HASHVAL(node), rbt->hashbits[rbt->hindex]); + hash = isc_hash_bits32(HASHVAL(node), rbt->hashbits[rbt->hindex]); HASHNEXT(node) = rbt->hashtable[rbt->hindex][hash]; rbt->hashtable[rbt->hindex][hash] = node; @@ -1629,24 +1614,25 @@ static void hashtable_new(dns_rbt_t *rbt, uint8_t index, uint8_t bits) { size_t size; - REQUIRE(rbt->hashbits[index] == RBT_HASH_NO_BITS); + REQUIRE(rbt->hashbits[index] == 0U); REQUIRE(rbt->hashtable[index] == NULL); - REQUIRE(bits >= RBT_HASH_MIN_BITS); - REQUIRE(bits < RBT_HASH_MAX_BITS); + REQUIRE(bits >= ISC_HASH_MIN_BITS); + REQUIRE(bits < ISC_HASH_MAX_BITS); rbt->hashbits[index] = bits; - size = HASHSIZE(rbt->hashbits[index]) * sizeof(dns_rbtnode_t *); + size = ISC_HASHSIZE(rbt->hashbits[index]) * sizeof(dns_rbtnode_t *); rbt->hashtable[index] = isc_mem_get(rbt->mctx, size); memset(rbt->hashtable[index], 0, size); } static void hashtable_free(dns_rbt_t *rbt, uint8_t index) { - size_t size = HASHSIZE(rbt->hashbits[index]) * sizeof(dns_rbtnode_t *); + size_t size = ISC_HASHSIZE(rbt->hashbits[index]) * + sizeof(dns_rbtnode_t *); isc_mem_put(rbt->mctx, rbt->hashtable[index], size); - rbt->hashbits[index] = RBT_HASH_NO_BITS; + rbt->hashbits[index] = 0U; rbt->hashtable[index] = NULL; } @@ -1654,7 +1640,8 @@ static uint32_t rehash_bits(dns_rbt_t *rbt, size_t newcount) { uint32_t newbits = rbt->hashbits[rbt->hindex]; - while (newcount >= HASHSIZE(newbits) && newbits < RBT_HASH_MAX_BITS) { + while (newcount >= ISC_HASHSIZE(newbits) && newbits < ISC_HASH_MAX_BITS) + { newbits += 1; } @@ -1670,12 +1657,12 @@ hashtable_rehash(dns_rbt_t *rbt, uint32_t newbits) { uint32_t oldbits = rbt->hashbits[oldindex]; uint8_t newindex = RBT_HASH_NEXTTABLE(oldindex); - REQUIRE(rbt->hashbits[oldindex] >= RBT_HASH_MIN_BITS); - REQUIRE(rbt->hashbits[oldindex] <= RBT_HASH_MAX_BITS); + REQUIRE(rbt->hashbits[oldindex] >= ISC_HASH_MIN_BITS); + REQUIRE(rbt->hashbits[oldindex] <= ISC_HASH_MAX_BITS); REQUIRE(rbt->hashtable[oldindex] != NULL); - REQUIRE(newbits <= RBT_HASH_MAX_BITS); - REQUIRE(rbt->hashbits[newindex] == RBT_HASH_NO_BITS); + REQUIRE(newbits <= ISC_HASH_MAX_BITS); + REQUIRE(rbt->hashbits[newindex] == 0U); REQUIRE(rbt->hashtable[newindex] == NULL); REQUIRE(newbits > oldbits); @@ -1691,7 +1678,7 @@ static void hashtable_rehash_one(dns_rbt_t *rbt) { dns_rbtnode_t **newtable = rbt->hashtable[rbt->hindex]; uint32_t oldsize = - HASHSIZE(rbt->hashbits[RBT_HASH_NEXTTABLE(rbt->hindex)]); + ISC_HASHSIZE(rbt->hashbits[RBT_HASH_NEXTTABLE(rbt->hindex)]); dns_rbtnode_t **oldtable = rbt->hashtable[RBT_HASH_NEXTTABLE(rbt->hindex)]; dns_rbtnode_t *node = NULL; @@ -1711,8 +1698,8 @@ hashtable_rehash_one(dns_rbt_t *rbt) { /* Move the first non-empty node from old hashtable to new hashtable */ for (node = oldtable[rbt->hiter]; node != NULL; node = nextnode) { - uint32_t hash = hash_32(HASHVAL(node), - rbt->hashbits[rbt->hindex]); + uint32_t hash = isc_hash_bits32(HASHVAL(node), + rbt->hashbits[rbt->hindex]); nextnode = HASHNEXT(node); HASHNEXT(node) = newtable[hash]; newtable[hash] = node; @@ -1728,7 +1715,7 @@ maybe_rehash(dns_rbt_t *rbt, size_t newcount) { uint32_t newbits = rehash_bits(rbt, newcount); if (rbt->hashbits[rbt->hindex] < newbits && - newbits <= RBT_HASH_MAX_BITS) { + newbits <= ISC_HASH_MAX_BITS) { hashtable_rehash(rbt, newbits); } } @@ -1740,8 +1727,8 @@ rehashing_in_progress(dns_rbt_t *rbt) { static bool hashtable_is_overcommited(dns_rbt_t *rbt) { - return (rbt->nodecount >= - (HASHSIZE(rbt->hashbits[rbt->hindex]) * RBT_HASH_OVERCOMMIT)); + return (rbt->nodecount >= (ISC_HASHSIZE(rbt->hashbits[rbt->hindex]) * + ISC_HASH_OVERCOMMIT)); } /* @@ -1781,7 +1768,7 @@ unhash_node(dns_rbt_t *rbt, dns_rbtnode_t *dnode) { * c) other table: the node hasn't been moved yet. */ nexttable: - hash = hash_32(HASHVAL(dnode), rbt->hashbits[hindex]); + hash = isc_hash_bits32(HASHVAL(dnode), rbt->hashbits[hindex]); hnode = rbt->hashtable[hindex][hash]; diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 29dce2ed02..a4c9aec6a8 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -309,20 +309,7 @@ typedef ISC_LIST(dns_rbtnode_t) rbtnodelist_t; (((header)->rdh_ttl > (now)) || \ ((header)->rdh_ttl == (now) && ZEROTTL(header))) -#define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */ -#define RBTDB_GLUE_TABLE_INIT_BITS 2U -#define RBTDB_GLUE_TABLE_MAX_BITS 32U -#define RBTDB_GLUE_TABLE_OVERCOMMIT 3 - -#define GOLDEN_RATIO_32 0x61C88647 -#define HASHSIZE(bits) (UINT64_C(1) << (bits)) - -static uint32_t -hash_32(uint32_t val, unsigned int bits) { - REQUIRE(bits <= RBTDB_GLUE_TABLE_MAX_BITS); - /* High bits are more random. */ - return (val * GOLDEN_RATIO_32 >> (32 - bits)); -} +#define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */ /*% * Number of buckets for cache DB entries (locks, LRU lists, TTL heaps). @@ -1252,10 +1239,10 @@ allocate_version(isc_mem_t *mctx, rbtdb_serial_t serial, isc_refcount_init(&version->references, references); isc_rwlock_init(&version->glue_rwlock, 0, 0); - version->glue_table_bits = RBTDB_GLUE_TABLE_INIT_BITS; + version->glue_table_bits = ISC_HASH_MIN_BITS; version->glue_table_nodecount = 0U; - size = HASHSIZE(version->glue_table_bits) * + size = ISC_HASHSIZE(version->glue_table_bits) * sizeof(version->glue_table[0]); version->glue_table = isc_mem_get(mctx, size); memset(version->glue_table, 0, size); @@ -9494,7 +9481,7 @@ free_gluetable(rbtdb_version_t *version) { rbtdb = version->rbtdb; - for (i = 0; i < HASHSIZE(version->glue_table_bits); i++) { + for (i = 0; i < ISC_HASHSIZE(version->glue_table_bits); i++) { rbtdb_glue_table_node_t *cur, *cur_next; cur = version->glue_table[i]; @@ -9510,7 +9497,7 @@ free_gluetable(rbtdb_version_t *version) { version->glue_table[i] = NULL; } - size = HASHSIZE(version->glue_table_bits) * + size = ISC_HASHSIZE(version->glue_table_bits) * sizeof(*version->glue_table); isc_mem_put(rbtdb->common.mctx, version->glue_table, size); @@ -9522,8 +9509,8 @@ rehash_bits(rbtdb_version_t *version, size_t newcount) { uint32_t oldbits = version->glue_table_bits; uint32_t newbits = oldbits; - while (newcount >= HASHSIZE(newbits) && - newbits <= RBTDB_GLUE_TABLE_MAX_BITS) { + while (newcount >= ISC_HASHSIZE(newbits) && + newbits <= ISC_HASH_MAX_BITS) { newbits += 1; } @@ -9540,11 +9527,11 @@ rehash_gluetable(rbtdb_version_t *version) { rbtdb_glue_table_node_t **oldtable; oldbits = version->glue_table_bits; - oldcount = HASHSIZE(oldbits); + oldcount = ISC_HASHSIZE(oldbits); oldtable = version->glue_table; newbits = rehash_bits(version, version->glue_table_nodecount); - newsize = HASHSIZE(newbits) * sizeof(version->glue_table[0]); + newsize = ISC_HASHSIZE(newbits) * sizeof(version->glue_table[0]); version->glue_table = isc_mem_get(version->rbtdb->common.mctx, newsize); version->glue_table_bits = newbits; @@ -9557,7 +9544,7 @@ rehash_gluetable(rbtdb_version_t *version) { gluenode = nextgluenode) { uint32_t hash = isc_hash32( &gluenode->node, sizeof(gluenode->node), true); - uint32_t idx = hash_32(hash, newbits); + uint32_t idx = isc_hash_bits32(hash, newbits); nextgluenode = gluenode->next; gluenode->next = version->glue_table[idx]; version->glue_table[idx] = gluenode; @@ -9577,8 +9564,8 @@ rehash_gluetable(rbtdb_version_t *version) { static void maybe_rehash_gluetable(rbtdb_version_t *version) { - size_t overcommit = HASHSIZE(version->glue_table_bits) * - RBTDB_GLUE_TABLE_OVERCOMMIT; + size_t overcommit = ISC_HASHSIZE(version->glue_table_bits) * + ISC_HASH_OVERCOMMIT; if (version->glue_table_nodecount < overcommit) { return; } @@ -9740,7 +9727,7 @@ restart: */ RWLOCK(&rbtversion->glue_rwlock, isc_rwlocktype_read); - idx = hash_32(hash, rbtversion->glue_table_bits); + idx = isc_hash_bits32(hash, rbtversion->glue_table_bits); for (cur = rbtversion->glue_table[idx]; cur != NULL; cur = cur->next) { if (cur->node == node) { @@ -9901,7 +9888,7 @@ no_glue: RWLOCK(&rbtversion->glue_rwlock, isc_rwlocktype_write); maybe_rehash_gluetable(rbtversion); - idx = hash_32(hash, rbtversion->glue_table_bits); + idx = isc_hash_bits32(hash, rbtversion->glue_table_bits); (void)dns_rdataset_additionaldata(rdataset, dns_rootname, glue_nsdname_cb, &ctx); diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 686eb0a489..53f3c2fa92 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -211,22 +212,8 @@ #endif /* ifndef RES_DOMAIN_HASH_BITS */ #define RES_NOBUCKET 0xffffffff -#define GOLDEN_RATIO_32 0x61C88647 - -#define HASHSIZE(bits) (UINT64_C(1) << (bits)) - -#define RES_DOMAIN_MAX_BITS 32 -#define RES_DOMAIN_OVERCOMMIT 3 - #define RES_DOMAIN_NEXTTABLE(hindex) ((hindex == 0) ? 1 : 0) -static uint32_t -hash_32(uint32_t val, unsigned int bits) { - REQUIRE(bits <= RES_DOMAIN_MAX_BITS); - /* High bits are more random. */ - return (val * GOLDEN_RATIO_32 >> (32 - bits)); -} - /*% * Maximum EDNS0 input packet size. */ @@ -1578,7 +1565,7 @@ fcount_incr(fetchctx_t *fctx, bool force) { INSIST(fctx->dbucketnum == RES_NOBUCKET); hashval = dns_name_fullhash(fctx->domain, false); - dbucketnum = hash_32(hashval, fctx->res->dhashbits); + dbucketnum = isc_hash_bits32(hashval, fctx->res->dhashbits); dbucket = &fctx->res->dbuckets[dbucketnum]; @@ -10108,12 +10095,12 @@ destroy(dns_resolver_t *res) { } isc_mem_put(res->mctx, res->buckets, res->nbuckets * sizeof(fctxbucket_t)); - for (i = 0; i < HASHSIZE(res->dhashbits); i++) { + for (i = 0; i < ISC_HASHSIZE(res->dhashbits); i++) { INSIST(ISC_LIST_EMPTY(res->dbuckets[i].list)); isc_mutex_destroy(&res->dbuckets[i].lock); } isc_mem_put(res->mctx, res->dbuckets, - HASHSIZE(res->dhashbits) * sizeof(zonebucket_t)); + ISC_HASHSIZE(res->dhashbits) * sizeof(zonebucket_t)); if (res->dispatches4 != NULL) { dns_dispatchset_destroy(&res->dispatches4); } @@ -10285,9 +10272,9 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, } res->dbuckets = isc_mem_get(view->mctx, - HASHSIZE(res->dhashbits) * + ISC_HASHSIZE(res->dhashbits) * sizeof(res->dbuckets[0])); - for (size_t i = 0; i < HASHSIZE(res->dhashbits); i++) { + for (size_t i = 0; i < ISC_HASHSIZE(res->dhashbits); i++) { res->dbuckets[i] = (zonebucket_t){ .list = { 0 } }; ISC_LIST_INIT(res->dbuckets[i].list); isc_mutex_init(&res->dbuckets[i].lock); @@ -10333,11 +10320,11 @@ cleanup_primelock: dns_dispatchset_destroy(&res->dispatches4); } - for (size_t i = 0; i < HASHSIZE(res->dhashbits); i++) { + for (size_t i = 0; i < ISC_HASHSIZE(res->dhashbits); i++) { isc_mutex_destroy(&res->dbuckets[i].lock); } isc_mem_put(view->mctx, res->dbuckets, - HASHSIZE(res->dhashbits) * sizeof(zonebucket_t)); + ISC_HASHSIZE(res->dhashbits) * sizeof(zonebucket_t)); cleanup_buckets: for (size_t i = 0; i < ntasks; i++) { @@ -11518,7 +11505,7 @@ dns_resolver_dumpfetches(dns_resolver_t *resolver, isc_statsformat_t format, REQUIRE(fp != NULL); REQUIRE(format == isc_statsformat_file); - for (size_t i = 0; i < HASHSIZE(resolver->dhashbits); i++) { + for (size_t i = 0; i < ISC_HASHSIZE(resolver->dhashbits); i++) { fctxcount_t *fc; LOCK(&resolver->dbuckets[i].lock); for (fc = ISC_LIST_HEAD(resolver->dbuckets[i].list); fc != NULL; diff --git a/lib/dns/rpz.c b/lib/dns/rpz.c index aa611d7c73..d0feec756e 100644 --- a/lib/dns/rpz.c +++ b/lib/dns/rpz.c @@ -1530,7 +1530,7 @@ dns_rpz_new_zone(dns_rpz_zones_t *rpzs, dns_rpz_zone_t **rpzp) { * simplifies update_from_db */ - isc_ht_init(&zone->nodes, rpzs->mctx, 1); + isc_ht_init(&zone->nodes, rpzs->mctx, 1, ISC_HT_CASE_SENSITIVE); dns_name_init(&zone->origin, NULL); dns_name_init(&zone->client_ip, NULL); @@ -1676,30 +1676,12 @@ static isc_result_t setup_update(dns_rpz_zone_t *rpz) { isc_result_t result; char domain[DNS_NAME_FORMATSIZE]; - unsigned int nodecount; - uint32_t hashsize; dns_name_format(&rpz->origin, domain, DNS_NAME_FORMATSIZE); isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER, ISC_LOG_INFO, "rpz: %s: reload start", domain); - nodecount = dns_db_nodecount(rpz->updb, dns_dbtree_main); - hashsize = 1; - while (nodecount != 0 && - hashsize <= (DNS_RPZ_HTSIZE_MAX + DNS_RPZ_HTSIZE_DIV)) { - hashsize++; - nodecount >>= 1; - } - - if (hashsize > DNS_RPZ_HTSIZE_DIV) { - hashsize -= DNS_RPZ_HTSIZE_DIV; - } - - isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER, - ISC_LOG_DEBUG(1), "rpz: %s: using hashtable size %d", - domain, hashsize); - - isc_ht_init(&rpz->newnodes, rpz->rpzs->mctx, hashsize); + isc_ht_init(&rpz->newnodes, rpz->rpzs->mctx, 1, ISC_HT_CASE_SENSITIVE); result = dns_db_createiterator(rpz->updb, DNS_DB_NONSEC3, &rpz->updbit); if (result != ISC_R_SUCCESS) { diff --git a/lib/dns/zone.c b/lib/dns/zone.c index baa4b0abe2..31443d6815 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -18504,26 +18505,10 @@ dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) { *** Zone manager. ***/ -#define KEYMGMT_OVERCOMMIT 3 -#define KEYMGMT_BITS_MIN 2U -#define KEYMGMT_BITS_MAX 32U - -/* - * WMM: Static hash functions copied from lib/dns/rbtdb.c. Should be moved to - * lib/isc/hash.c when we refactor the hash table code. - */ -#define GOLDEN_RATIO_32 0x61C88647 -#define HASHSIZE(bits) (UINT64_C(1) << (bits)) - -static uint32_t -hash_index(uint32_t val, uint32_t bits) { - return (val * GOLDEN_RATIO_32 >> (32 - bits)); -} - static uint32_t hash_bits_grow(uint32_t bits, uint32_t count) { uint32_t newbits = bits; - while (count >= HASHSIZE(newbits) && newbits < KEYMGMT_BITS_MAX) { + while (count >= ISC_HASHSIZE(newbits) && newbits < ISC_HASH_MAX_BITS) { newbits++; } return (newbits); @@ -18532,7 +18517,7 @@ hash_bits_grow(uint32_t bits, uint32_t count) { static uint32_t hash_bits_shrink(uint32_t bits, uint32_t count) { uint32_t newbits = bits; - while (count <= HASHSIZE(newbits) && newbits > KEYMGMT_BITS_MIN) { + while (count <= ISC_HASHSIZE(newbits) && newbits > ISC_HASH_MIN_BITS) { newbits--; } return (newbits); @@ -18544,12 +18529,12 @@ zonemgr_keymgmt_init(dns_zonemgr_t *zmgr) { uint32_t size; *mgmt = (dns_keymgmt_t){ - .bits = KEYMGMT_BITS_MIN, + .bits = ISC_HASH_MIN_BITS, }; isc_mem_attach(zmgr->mctx, &mgmt->mctx); isc_rwlock_init(&mgmt->lock, 0, 0); - size = HASHSIZE(mgmt->bits); + size = ISC_HASHSIZE(mgmt->bits); mgmt->table = isc_mem_get(mgmt->mctx, sizeof(*mgmt->table) * size); memset(mgmt->table, 0, size * sizeof(mgmt->table[0])); @@ -18568,7 +18553,7 @@ zonemgr_keymgmt_destroy(dns_zonemgr_t *zmgr) { REQUIRE(DNS_KEYMGMT_VALID(mgmt)); RWLOCK(&mgmt->lock, isc_rwlocktype_write); - size = HASHSIZE(mgmt->bits); + size = ISC_HASHSIZE(mgmt->bits); for (unsigned int i = 0; atomic_load_relaxed(&mgmt->count) > 0 && i < size; i++) { for (curr = mgmt->table[i]; curr != NULL; curr = next) { @@ -18601,10 +18586,10 @@ zonemgr_keymgmt_resize(dns_zonemgr_t *zmgr) { bits = mgmt->bits; RWUNLOCK(&mgmt->lock, isc_rwlocktype_read); - size = HASHSIZE(bits); + size = ISC_HASHSIZE(bits); INSIST(size > 0); - if (count >= (size * KEYMGMT_OVERCOMMIT)) { + if (count >= (size * ISC_HASH_OVERCOMMIT)) { grow = true; } else if (count < (size / 2)) { grow = false; @@ -18627,7 +18612,7 @@ zonemgr_keymgmt_resize(dns_zonemgr_t *zmgr) { return; } - newsize = HASHSIZE(newbits); + newsize = ISC_HASHSIZE(newbits); INSIST(newsize > 0); RWLOCK(&mgmt->lock, isc_rwlocktype_write); @@ -18638,7 +18623,7 @@ zonemgr_keymgmt_resize(dns_zonemgr_t *zmgr) { for (unsigned int i = 0; i < size; i++) { dns_keyfileio_t *kfio, *next; for (kfio = mgmt->table[i]; kfio != NULL; kfio = next) { - uint32_t hash = hash_index(kfio->hashval, newbits); + uint32_t hash = isc_hash_bits32(kfio->hashval, newbits); next = kfio->next; kfio->next = newtable[hash]; newtable[hash] = kfio; @@ -18665,7 +18650,7 @@ zonemgr_keymgmt_add(dns_zonemgr_t *zmgr, dns_zone_t *zone, RWLOCK(&mgmt->lock, isc_rwlocktype_write); hashval = dns_name_hash(&zone->origin, false); - hash = hash_index(hashval, mgmt->bits); + hash = isc_hash_bits32(hashval, mgmt->bits); for (kfio = mgmt->table[hash]; kfio != NULL; kfio = next) { next = kfio->next; @@ -18718,7 +18703,7 @@ zonemgr_keymgmt_delete(dns_zonemgr_t *zmgr, dns_zone_t *zone) { RWLOCK(&mgmt->lock, isc_rwlocktype_write); hashval = dns_name_hash(&zone->origin, false); - hash = hash_index(hashval, mgmt->bits); + hash = isc_hash_bits32(hashval, mgmt->bits); prev = NULL; for (kfio = mgmt->table[hash]; kfio != NULL; kfio = next) { @@ -18776,7 +18761,7 @@ zonemgr_keymgmt_find(dns_zonemgr_t *zmgr, dns_zone_t *zone, } hashval = dns_name_hash(&zone->origin, false); - hash = hash_index(hashval, mgmt->bits); + hash = isc_hash_bits32(hashval, mgmt->bits); for (kfio = mgmt->table[hash]; kfio != NULL; kfio = next) { next = kfio->next; diff --git a/lib/isc/ht.c b/lib/isc/ht.c index fa805c9a51..cc2b139531 100644 --- a/lib/isc/ht.c +++ b/lib/isc/ht.c @@ -51,6 +51,7 @@ struct isc_ht { unsigned int magic; isc_mem_t *mctx; size_t count; + bool case_sensitive; size_t size[2]; uint8_t hashbits[2]; isc_ht_node_t **table[2]; @@ -234,15 +235,19 @@ hashtable_free(isc_ht_t *ht, const uint8_t idx) { } void -isc_ht_init(isc_ht_t **htp, isc_mem_t *mctx, uint8_t bits) { +isc_ht_init(isc_ht_t **htp, isc_mem_t *mctx, uint8_t bits, + unsigned int options) { isc_ht_t *ht = NULL; + bool case_sensitive = ((options & ISC_HT_CASE_INSENSITIVE) == 0); REQUIRE(htp != NULL && *htp == NULL); REQUIRE(mctx != NULL); REQUIRE(bits >= 1 && bits <= HT_MAX_BITS); ht = isc_mem_get(mctx, sizeof(*ht)); - *ht = (isc_ht_t){ 0 }; + *ht = (isc_ht_t){ + .case_sensitive = case_sensitive, + }; isc_mem_attach(mctx, &ht->mctx); @@ -313,7 +318,7 @@ isc_ht_add(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize, maybe_rehash(ht, ht->count); } - hashval = isc_hash32(key, keysize, true); + hashval = isc_hash32(key, keysize, ht->case_sensitive); if (isc__ht_find(ht, key, keysize, hashval, ht->hindex) != NULL) { return (ISC_R_EXISTS); @@ -361,7 +366,7 @@ isc_ht_find(const isc_ht_t *ht, const unsigned char *key, REQUIRE(key != NULL && keysize > 0); REQUIRE(valuep == NULL || *valuep == NULL); - hashval = isc_hash32(key, keysize, true); + hashval = isc_hash32(key, keysize, ht->case_sensitive); node = isc__ht_find(ht, key, keysize, hashval, ht->hindex); if (node == NULL) { @@ -417,7 +422,7 @@ isc_ht_delete(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize) { } hindex = ht->hindex; - hashval = isc_hash32(key, keysize, true); + hashval = isc_hash32(key, keysize, ht->case_sensitive); nexttable: result = isc__ht_delete(ht, key, keysize, hashval, hindex); diff --git a/lib/isc/include/isc/hash.h b/lib/isc/include/isc/hash.h index ee9e74f2d9..80e50da83d 100644 --- a/lib/isc/include/isc/hash.h +++ b/lib/isc/include/isc/hash.h @@ -16,8 +16,14 @@ #include #include -#include "isc/lang.h" -#include "isc/types.h" +#include +#include +#include + +#define ISC_HASHSIZE(bits) (UINT64_C(1) << (bits)) +#define ISC_HASH_OVERCOMMIT 3 +#define ISC_HASH_MIN_BITS 2U +#define ISC_HASH_MAX_BITS 32U /*** *** Functions @@ -60,4 +66,26 @@ isc_hash64(const void *data, const size_t length, const bool case_sensitive); * \li 32 or 64-bit hash value */ +/*! + * \brief Return a hash value of a specified number of bits + * + * This function uses Fibonacci Hashing to convert a 32 bit hash value + * 'val' into a smaller hash value of up to 'bits' bits. This results + * in better hash table distribution than the use of modulo. + * + * Requires: + * \li 'bits' is less than 32. + * + * Returns: + * \li a hash value of length 'bits'. + */ +#define ISC_HASH_GOLDENRATIO_32 0x61C88647 +#define isc_hash_bits32(val, bits) \ + ({ \ + REQUIRE(bits <= 32U); \ + uint32_t __v = (val & 0xffff); \ + __v = ((__v * ISC_HASH_GOLDENRATIO_32) >> (32 - bits)); \ + __v; \ + }) + ISC_LANG_ENDDECLS diff --git a/lib/isc/include/isc/ht.h b/lib/isc/include/isc/ht.h index de347b945b..163fbefb79 100644 --- a/lib/isc/include/isc/ht.h +++ b/lib/isc/include/isc/ht.h @@ -24,9 +24,15 @@ typedef struct isc_ht isc_ht_t; typedef struct isc_ht_iter isc_ht_iter_t; +enum { ISC_HT_CASE_SENSITIVE = 0x00, ISC_HT_CASE_INSENSITIVE = 0x01 }; + /*% * Initialize hashtable at *htp, using memory context and size of (1<references, 1); isc_mem_attach(mctx, &nc->mctx); - isc_ht_init(&nc->data, mctx, 5); + isc_ht_init(&nc->data, mctx, 5, ISC_HT_CASE_SENSITIVE); isc_rwlock_init(&nc->rwlock, 0, 0); return (nc);