2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 22:45:39 +00:00

Merge branch 'ondrej/remove-isc_hash_function' into 'main'

Use incremental hashing in the isc_sockaddr_hash() function

See merge request isc-projects/bind9!8298
This commit is contained in:
Ondřej Surý
2023-09-19 18:48:56 +00:00
6 changed files with 102 additions and 60 deletions

View File

@@ -373,12 +373,15 @@ setup_socket(dns_dispatch_t *disp, dns_dispentry_t *resp,
static uint32_t
qid_hash(const dns_dispentry_t *dispentry) {
/*
* TODO(OS): Add incremental isc_sockaddr_hash() function and then use
* isc_hash32 API
*/
uint32_t hashval = isc_sockaddr_hash(&dispentry->peer, true);
return (hashval ^ (((uint32_t)dispentry->id << 16) | dispentry->port));
isc_hash32_t hash;
isc_hash32_init(&hash);
isc_sockaddr_hash_ex(&hash, &dispentry->peer, true);
isc_hash32_hash(&hash, &dispentry->id, sizeof(dispentry->id), true);
isc_hash32_hash(&hash, &dispentry->port, sizeof(dispentry->port), true);
return (isc_hash32_finalize(&hash));
}
static int

View File

@@ -44,8 +44,6 @@ isc_hash_get_initializer(void);
void
isc_hash_set_initializer(const void *initializer);
#define isc_hash_function isc_hash64
void
isc_hash32_init(isc_hash32_t *restrict state);
void

View File

@@ -85,7 +85,16 @@ isc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
* If 'b''s scope is zero then 'a''s scope will be ignored.
*/
unsigned int
void
isc_sockaddr_hash_ex(isc_hash32_t *hash, const isc_sockaddr_t *sockaddr,
bool address_only);
/*%<
* Add the hash of the sockaddr into the hash for incremental hashing
*
* See isc_sockaddr_hash() for details.
*/
uint32_t
isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, bool address_only);
/*%<
* Return a hash value for the socket address 'sockaddr'. If 'address_only'

View File

@@ -216,11 +216,11 @@ add_trace_entry(isc_mem_t *mctx, const void *ptr, size_t size FLARG) {
#ifdef __COVERITY__
/*
* Use simple conversion from pointer to hash to avoid
* tainting 'ptr' due to byte swap in isc_hash_function.
* tainting 'ptr' due to byte swap in isc_hash32.
*/
hash = (uintptr_t)ptr >> 3;
#else
hash = isc_hash_function(&ptr, sizeof(ptr), true);
hash = isc_hash32(&ptr, sizeof(ptr), true);
#endif
idx = hash % DEBUG_TABLE_COUNT;
@@ -260,11 +260,11 @@ delete_trace_entry(isc_mem_t *mctx, const void *ptr, size_t size,
#ifdef __COVERITY__
/*
* Use simple conversion from pointer to hash to avoid
* tainting 'ptr' due to byte swap in isc_hash_function.
* tainting 'ptr' due to byte swap in isc_hash32.
*/
hash = (uintptr_t)ptr >> 3;
#else
hash = isc_hash_function(&ptr, sizeof(ptr), true);
hash = isc_hash32(&ptr, sizeof(ptr), true);
#endif
idx = hash % DEBUG_TABLE_COUNT;

View File

@@ -187,51 +187,56 @@ isc_sockaddr_format(const isc_sockaddr_t *sa, char *array, unsigned int size) {
}
}
unsigned int
isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, bool address_only) {
unsigned int length = 0;
const unsigned char *s = NULL;
unsigned int h = 0;
void
isc_sockaddr_hash_ex(isc_hash32_t *hash, const isc_sockaddr_t *sockaddr,
bool address_only) {
REQUIRE(sockaddr != NULL);
size_t len = 0;
const uint8_t *s = NULL;
unsigned int p = 0;
const struct in6_addr *in6;
REQUIRE(sockaddr != NULL);
switch (sockaddr->type.sa.sa_family) {
case AF_INET:
s = (const unsigned char *)&sockaddr->type.sin.sin_addr;
s = (const uint8_t *)&sockaddr->type.sin.sin_addr;
len = sizeof(sockaddr->type.sin.sin_addr.s_addr);
if (!address_only) {
p = ntohs(sockaddr->type.sin.sin_port);
length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
}
break;
case AF_INET6:
in6 = &sockaddr->type.sin6.sin6_addr;
s = (const unsigned char *)in6;
s = (const uint8_t *)in6;
if (IN6_IS_ADDR_V4MAPPED(in6)) {
s += 12;
length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
len = sizeof(sockaddr->type.sin.sin_addr.s_addr);
} else {
length = sizeof(sockaddr->type.sin6.sin6_addr);
len = sizeof(sockaddr->type.sin6.sin6_addr);
}
if (!address_only) {
p = ntohs(sockaddr->type.sin6.sin6_port);
}
break;
default:
UNEXPECTED_ERROR("unknown address family: %d",
(int)sockaddr->type.sa.sa_family);
s = (const unsigned char *)&sockaddr->type;
length = sockaddr->length;
p = 0;
UNREACHABLE();
}
uint8_t buf[sizeof(struct sockaddr_storage) + sizeof(p)];
memmove(buf, s, length);
isc_hash32_hash(hash, s, len, true);
if (!address_only) {
memmove(buf + length, &p, sizeof(p));
h = isc_hash_function(buf, length + sizeof(p), true);
} else {
h = isc_hash_function(buf, length, true);
isc_hash32_hash(hash, &p, sizeof(p), true);
}
}
return (h);
uint32_t
isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, bool address_only) {
isc_hash32_t hash;
isc_hash32_init(&hash);
isc_sockaddr_hash_ex(&hash, sockaddr, address_only);
return (isc_hash32_finalize(&hash));
}
void

View File

@@ -34,60 +34,87 @@
#include <tests/isc.h>
/* Hash function test */
ISC_RUN_TEST_IMPL(isc_hash_function) {
unsigned int h1;
unsigned int h2;
UNUSED(state);
ISC_RUN_TEST_IMPL(isc_hash32) {
uint32_t h1;
uint32_t h2;
/* Immutability of hash function */
h1 = isc_hash_function(NULL, 0, true);
h2 = isc_hash_function(NULL, 0, true);
h1 = isc_hash32(NULL, 0, true);
h2 = isc_hash32(NULL, 0, true);
assert_int_equal(h1, h2);
/* Hash function characteristics */
h1 = isc_hash_function("Hello world", 12, true);
h2 = isc_hash_function("Hello world", 12, true);
h1 = isc_hash32("Hello world", 12, true);
h2 = isc_hash32("Hello world", 12, true);
assert_int_equal(h1, h2);
/* Case */
h1 = isc_hash_function("Hello world", 12, false);
h2 = isc_hash_function("heLLo WorLd", 12, false);
h1 = isc_hash32("Hello world", 12, false);
h2 = isc_hash32("heLLo WorLd", 12, false);
assert_int_equal(h1, h2);
/* Unequal */
h1 = isc_hash_function("Hello world", 12, true);
h2 = isc_hash_function("heLLo WorLd", 12, true);
h1 = isc_hash32("Hello world", 12, true);
h2 = isc_hash32("heLLo WorLd", 12, true);
assert_int_not_equal(h1, h2);
}
/* Hash function test */
ISC_RUN_TEST_IMPL(isc_hash64) {
uint64_t h1;
uint64_t h2;
/* Immutability of hash function */
h1 = isc_hash64(NULL, 0, true);
h2 = isc_hash64(NULL, 0, true);
assert_int_equal(h1, h2);
/* Hash function characteristics */
h1 = isc_hash64("Hello world", 12, true);
h2 = isc_hash64("Hello world", 12, true);
assert_int_equal(h1, h2);
/* Case */
h1 = isc_hash64("Hello world", 12, false);
h2 = isc_hash64("heLLo WorLd", 12, false);
assert_int_equal(h1, h2);
/* Unequal */
h1 = isc_hash64("Hello world", 12, true);
h2 = isc_hash64("heLLo WorLd", 12, true);
assert_int_not_equal(h1, h2);
}
/* Hash function initializer test */
ISC_RUN_TEST_IMPL(isc_hash_initializer) {
unsigned int h1;
unsigned int h2;
uint64_t h1;
uint64_t h2;
UNUSED(state);
h1 = isc_hash_function("Hello world", 12, true);
h2 = isc_hash_function("Hello world", 12, true);
h1 = isc_hash64("Hello world", 12, true);
h2 = isc_hash64("Hello world", 12, true);
assert_int_equal(h1, h2);
isc_hash_set_initializer(isc_hash_get_initializer());
/* Hash value must not change */
h2 = isc_hash_function("Hello world", 12, true);
h2 = isc_hash64("Hello world", 12, true);
assert_int_equal(h1, h2);
}
ISC_TEST_LIST_START
ISC_TEST_ENTRY(isc_hash_function)
ISC_TEST_ENTRY(isc_hash32)
ISC_TEST_ENTRY(isc_hash64)
ISC_TEST_ENTRY(isc_hash_initializer)
ISC_TEST_LIST_END