]> granicus.if.org Git - pdns/commitdiff
Port the 0x20 hashing to 3.7.3
authorbert hubert <bert.hubert@netherlabs.nl>
Wed, 9 Sep 2015 09:17:45 +0000 (11:17 +0200)
committerPieter Lexis <pieter.lexis@powerdns.com>
Tue, 15 Sep 2015 13:52:47 +0000 (15:52 +0200)
This is a combination of the commits:
6200227b6b3cfd8796d6cc75e8cf29bcec586f0c
af891b3d6d3f6ee6e848411cc9e477c96e955f98

And a port of the testcase

pdns/dns.cc
pdns/misc.cc
pdns/misc.hh
pdns/test-misc_hh.cc

index 1678f7072cea578174e57cca4675de020e5e2ec7..41da1ba365f609376673be4192bff8e9f09e3b04 100644 (file)
@@ -142,7 +142,7 @@ uint32_t hashQuestion(const char* packet, uint16_t len, uint32_t init)
   while((labellen=*pos++) && pos < end) { 
     if(pos + labellen + 1 > end) // include length field  in hash
       return 0;
-    ret=burtle(pos, labellen+1, ret);
+    ret=burtleCI(pos, labellen+1, ret);
     pos += labellen;
   }
   return ret;
index 01529cf054a9dc9a2da70e2162ae42e44ad03bea..5dc51c39b89b0c6c7fe6f44a05779b1eea42b852 100644 (file)
@@ -911,6 +911,47 @@ uint32_t burtle(const unsigned char* k, uint32_t length, uint32_t initval)
   return c;
 }
 
+uint32_t burtleCI(const unsigned char* k, uint32_t length, uint32_t initval)
+{
+  uint32_t a,b,c,len;
+
+   /* Set up the internal state */
+  len = length;
+  a = b = 0x9e3779b9;  /* the golden ratio; an arbitrary value */
+  c = initval;         /* the previous hash value */
+
+  /*---------------------------------------- handle most of the key */
+  while (len >= 12) {
+    a += (dns_tolower(k[0]) +((uint32_t)dns_tolower(k[1])<<8) +((uint32_t)dns_tolower(k[2])<<16) +((uint32_t)dns_tolower(k[3])<<24));
+    b += (dns_tolower(k[4]) +((uint32_t)dns_tolower(k[5])<<8) +((uint32_t)dns_tolower(k[6])<<16) +((uint32_t)dns_tolower(k[7])<<24));
+    c += (dns_tolower(k[8]) +((uint32_t)dns_tolower(k[9])<<8) +((uint32_t)dns_tolower(k[10])<<16)+((uint32_t)dns_tolower(k[11])<<24));
+    burtlemix(a,b,c);
+    k += 12; len -= 12;
+  }
+
+  /*------------------------------------- handle the last 11 bytes */
+  c += length;
+  switch(len) {             /* all the case statements fall through */
+  case 11: c+=((uint32_t)dns_tolower(k[10])<<24);
+  case 10: c+=((uint32_t)dns_tolower(k[9])<<16);
+  case 9 : c+=((uint32_t)dns_tolower(k[8])<<8);
+    /* the first byte of c is reserved for the length */
+  case 8 : b+=((uint32_t)dns_tolower(k[7])<<24);
+  case 7 : b+=((uint32_t)dns_tolower(k[6])<<16);
+  case 6 : b+=((uint32_t)dns_tolower(k[5])<<8);
+  case 5 : b+=dns_tolower(k[4]);
+  case 4 : a+=((uint32_t)dns_tolower(k[3])<<24);
+  case 3 : a+=((uint32_t)dns_tolower(k[2])<<16);
+  case 2 : a+=((uint32_t)dns_tolower(k[1])<<8);
+  case 1 : a+=dns_tolower(k[0]);
+    /* case 0: nothing left to add */
+  }
+  burtlemix(a,b,c);
+  /*-------------------------------------------- report the result */
+  return c;
+}
+
+
 void setSocketTimestamps(int fd)
 {
 #ifdef SO_TIMESTAMP
index 515e35fe5fc056ed8fbce940ae22499796e2c2a0..dcf7ba56159ffef5576d38a0ba1bb36d1ab6644a 100644 (file)
@@ -544,5 +544,6 @@ unsigned int getFilenumLimit(bool hardOrSoft=0);
 void setFilenumLimit(unsigned int lim);
 bool readFileIfThere(const char* fname, std::string* line);
 uint32_t burtle(const unsigned char* k, uint32_t lengh, uint32_t init);
+uint32_t burtleCI(const unsigned char* k, uint32_t lengh, uint32_t init);
 void setSocketTimestamps(int fd);
 #endif
index 8732264f3e95878588447e42c4aeef5c1c0c7b65..22739a8369b13ecd87799d1c25ecc9a312d167c2 100644 (file)
@@ -5,8 +5,11 @@
 #include <boost/assign/list_of.hpp>
 #include <boost/foreach.hpp>
 #include <boost/tuple/tuple.hpp>
+#include <math.h>
 #include "misc.hh"
 #include "dns.hh"
+#include "dnswriter.hh"
+#include "dnsrecords.hh"
 #include <utility>
 
 using std::string;
@@ -119,6 +122,40 @@ BOOST_AUTO_TEST_CASE(test_AtomicCounter) {
     BOOST_CHECK_EQUAL(ac, 2);
 }
 
+BOOST_AUTO_TEST_CASE(test_QuestionHash) {
+  vector<unsigned char> packet;
+  reportBasicTypes();
+  DNSPacketWriter dpw1(packet, "www.ds9a.nl.", QType::AAAA);
+  
+  uint32_t hash1=hashQuestion((char*)&packet[0], packet.size(), 0);
+  DNSPacketWriter dpw2(packet, "wWw.Ds9A.nL.", QType::AAAA);
+  uint32_t hash2=hashQuestion((char*)&packet[0], packet.size(), 0);
+  BOOST_CHECK_EQUAL(hash1, hash2);
+  vector<uint32_t> counts(1500);
+  for(unsigned int n=0; n < 100000; ++n) {
+    packet.clear();
+    DNSPacketWriter dpw1(packet, lexical_cast<string>(n)+"."+lexical_cast<string>(n*2)+".", QType::AAAA);
+    counts[hashQuestion((char*)&packet[0], packet.size(), 0) % counts.size()]++;
+  }
+  
+  double sum = 0.0;
+  BOOST_FOREACH(double d, counts){
+    sum += d;
+  }
+
+  double m =  sum / counts.size();
+
+  double accum = 0.0;
+  BOOST_FOREACH(double d, counts) {
+      accum += (d - m) * (d - m);
+  };
+      
+  double stdev = sqrt(accum / (counts.size()-1));
+  BOOST_CHECK(stdev < 10);
+}
+
 BOOST_AUTO_TEST_CASE(test_endianness) {
   uint32_t i = 1;
 #if BYTE_ORDER == BIG_ENDIAN