ntp: improve hashing of sources

Use 32-bit hash and switch to quadratic probing. This will be useful to
allow resizing of the hash table and not limit the number of sources.
This commit is contained in:
Miroslav Lichvar 2014-09-23 17:12:56 +02:00
parent 37bc30c8d9
commit 4e0df8c2a6

View file

@ -159,23 +159,23 @@ NSR_Finalise(void)
static void static void
find_slot(NTP_Remote_Address *remote_addr, int *slot, int *found) find_slot(NTP_Remote_Address *remote_addr, int *slot, int *found)
{ {
unsigned long hash; uint32_t hash;
unsigned long ip; unsigned int i, size;
unsigned short port; unsigned short port;
uint8_t *ip6; uint8_t *ip6;
assert(N_RECORDS == 256); size = N_RECORDS;
switch (remote_addr->ip_addr.family) { switch (remote_addr->ip_addr.family) {
case IPADDR_INET6: case IPADDR_INET6:
ip6 = remote_addr->ip_addr.addr.in6; ip6 = remote_addr->ip_addr.addr.in6;
ip = (ip6[0] ^ ip6[4] ^ ip6[8] ^ ip6[12]) | hash = (ip6[0] ^ ip6[4] ^ ip6[8] ^ ip6[12]) |
(ip6[1] ^ ip6[5] ^ ip6[9] ^ ip6[13]) << 8 | (ip6[1] ^ ip6[5] ^ ip6[9] ^ ip6[13]) << 8 |
(ip6[2] ^ ip6[6] ^ ip6[10] ^ ip6[14]) << 16 | (ip6[2] ^ ip6[6] ^ ip6[10] ^ ip6[14]) << 16 |
(ip6[3] ^ ip6[7] ^ ip6[11] ^ ip6[15]) << 24; (ip6[3] ^ ip6[7] ^ ip6[11] ^ ip6[15]) << 24;
break; break;
case IPADDR_INET4: case IPADDR_INET4:
ip = remote_addr->ip_addr.addr.in4; hash = remote_addr->ip_addr.addr.in4;
break; break;
default: default:
*found = *slot = 0; *found = *slot = 0;
@ -183,28 +183,22 @@ find_slot(NTP_Remote_Address *remote_addr, int *slot, int *found)
} }
port = remote_addr->port; port = remote_addr->port;
/* Compute hash value just by xor'ing the 4 bytes of the address together */
hash = ip ^ (ip >> 16);
hash = (hash ^ (hash >> 8)) & 0xff;
while (records[hash].remote_addr && for (i = 0; i < size / 2; i++) {
UTI_CompareIPs(&records[hash].remote_addr->ip_addr, /* Use quadratic probing */
&remote_addr->ip_addr, NULL)) { *slot = (hash + (i + i * i) / 2) % size;
hash++;
if (hash == 256) hash = 0;
}
if (records[hash].remote_addr) { if (!records[*slot].remote_addr)
if (records[hash].remote_addr->port == port) { break;
*found = 2;
} else { if (!UTI_CompareIPs(&records[*slot].remote_addr->ip_addr,
*found = 1; &remote_addr->ip_addr, NULL)) {
*found = records[*slot].remote_addr->port == port ? 2 : 1;
return;
} }
*slot = hash;
} else {
*found = 0;
*slot = hash;
} }
*found = 0;
} }
/* ================================================== */ /* ================================================== */