Flow ID, LACP, and igb

T.C. Gubatayao tgubatayao at barracuda.com
Thu Aug 29 19:53:44 UTC 2013


On Aug 29, 2013, at 12:45 PM, Alan Somers <asomers at freebsd.org> wrote:

> I pulled all four hash functions out into userland and microbenchmarked them.
> The upshot is that hash32 and fnv_hash are the fastest, jenkins_hash is
> slower, and siphash24 is the slowest.  Also, Clang resulted in much faster
> code than gcc.

I didn't realize that you were testing incremental hashing with 4 and 6 byte
keys.

There might be advantages to conditionally filling out a contiguous key
and then performing the hash on that.  You could guarantee key alignment, for  
one, and this would benefit the hashes which perform word-sized reads. 

Based on my quick tests, lookup3 and SipHash improve significantly.

T.C.

diff -u a/lagg_hash.c b/lagg_hash.c
--- a/lagg_hash.c       2013-08-29 14:21:17.255307349 -0400
+++ b/lagg_hash.c       2013-08-29 15:16:31.135653259 -0400
@@ -7,22 +7,30 @@
 #include <sys/hash.h>
 #include <sys/fnv_hash.h>
 #include <sys/time.h>
-
-uint32_t jenkins_hash32(const uint32_t *, size_t, uint32_t);
+#include <string.h>
 
 #define ITERATIONS     100000000
 
 typedef uint32_t do_hash_t(void);
 
-// Pad the MACs with 0s because jenkins_hash operates on 32-bit inputs
-const uint8_t ether_shost[] = {181, 16, 73, 9, 219, 22, 0, 0};
-const uint8_t ether_dhost[] = {69, 170, 210, 111, 24, 120, 0, 0};
+const uint8_t ether_shost[] = {181, 16, 73, 9, 219, 22};
+const uint8_t ether_dhost[] = {69, 170, 210, 111, 24, 120};
+const uint8_t ether_hosts[] = { 181, 16, 73, 9, 219, 22,
+                               69, 170, 210, 111, 24, 120 };
 const struct in_addr ip_src = {.s_addr = 1329258245};
 const struct in_addr ip_dst = {.s_addr = 1319097119};
+const struct in_addr ips[2] = { { .s_addr = 1329258245 },
+                               { .s_addr = 1319097119 } };
 const uint32_t ports = 3132895450;
 const uint8_t sipkey[16] = {7, 239, 255, 43, 68, 53, 56, 225,
                            98, 81, 177, 80, 92, 235, 242, 39};
 
+struct key {
+       uint8_t ether_hosts[12];
+       struct in_addr ips[2];
+       uint16_t ports[2];
+} __attribute__((packed));
+
 /*
  * Simulate how lagg_hashmbuf uses FNV hash for a TCP/IP packet
  * No VLAN tagging
@@ -58,6 +66,15 @@
        return (p);
 }
 
+static __inline init_key(struct key *key)
+{
+
+       /* Simulate copying the info out of the mbuf. */
+       memcpy(key->ether_hosts, ether_hosts, sizeof(ether_hosts));
+       memcpy(key->ips, ips, sizeof(ips));
+       memcpy(key->ports, &ports, sizeof(ports));
+}
+
 /*
  * Simulate how lagg_hashmbuf would use siphash24 for a TCP/IP packet
  * No VLAN tagging
@@ -65,16 +82,11 @@
 uint32_t do_siphash24(void)
 {
        SIPHASH_CTX ctx;
+       struct key key;
 
-       SipHash24_Init(&ctx);
-       SipHash_SetKey(&ctx, sipkey);
+       init_key(&key);
 
-       SipHash_Update(&ctx, ether_shost, 6);
-       SipHash_Update(&ctx, ether_dhost, 6);
-       SipHash_Update(&ctx, &ip_src, sizeof(struct in_addr));
-       SipHash_Update(&ctx, &ip_dst, sizeof(struct in_addr));
-       SipHash_Update(&ctx, &ports, sizeof(ports));
-       return (SipHash_End(&ctx) & 0xFFFFFFFF);
+       return (SipHash24(&ctx, sipkey, &key, sizeof(key)) & 0xFFFFFFFF);
 }
 
 /*
@@ -83,19 +95,11 @@
  */
 uint32_t do_jenkins(void)
 {
-       /* Jenkins hash does not recommend any specific initializer */
-       uint32_t p = FNV1_32_INIT;
+       struct key key;
 
-       /* 
-        * jenkins_hash uses 32-bit inputs, so we need to present the MACs as
-        * arrays of 2 32-bit values
-        */
-       p = jenkins_hash32((uint32_t*)ether_shost, 2, p);
-       p = jenkins_hash32((uint32_t*)ether_dhost, 2, p);
-       p = jenkins_hash32((uint32_t*)&ip_src, sizeof(struct in_addr) / 4, p);
-       p = jenkins_hash32((uint32_t*)&ip_dst, sizeof(struct in_addr) / 4, p);
-       p = jenkins_hash32(&ports, sizeof(ports) / 4, p);
-       return (p);
+       init_key(&key);
+
+       return (jenkins_hash(&key, sizeof(key), FNV1_32_INIT));
 }
 
 
diff -u a/siphash.h b/siphash.h
--- a/siphash.h 2013-08-29 14:21:21.851306417 -0400
+++ b/siphash.h 2013-08-29 14:26:44.470240137 -0400
@@ -73,8 +73,8 @@
 void SipHash_Final(void *, SIPHASH_CTX *);
 uint64_t SipHash_End(SIPHASH_CTX *);
 
-#define SipHash24(x, y, z, i)  SipHashX((x), 2, 4, (y), (z), (i));
-#define SipHash48(x, y, z, i)  SipHashX((x), 4, 8, (y), (z), (i));
+#define SipHash24(x, y, z, i)  SipHashX((x), 2, 4, (y), (z), (i))
+#define SipHash48(x, y, z, i)  SipHashX((x), 4, 8, (y), (z), (i))
 uint64_t SipHashX(SIPHASH_CTX *, int, int, const uint8_t [16], const void *,
     size_t);
 


More information about the freebsd-net mailing list