typedef int __wchar_t; #include #include #include #include "siphash.h" #include #include #include uint32_t jenkins_hash32(const uint32_t *, size_t, uint32_t); #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 struct in_addr ip_src = {.s_addr = 1329258245}; const struct in_addr ip_dst = {.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}; /* * Simulate how lagg_hashmbuf uses FNV hash for a TCP/IP packet * No VLAN tagging */ uint32_t do_fnv(void) { uint32_t p = FNV1_32_INIT; p = fnv_32_buf(ether_shost, 6, p); p = fnv_32_buf(ether_dhost, 6, p); p = fnv_32_buf(&ip_src, sizeof(struct in_addr), p); p = fnv_32_buf(&ip_dst, sizeof(struct in_addr), p); p = fnv_32_buf(&ports, sizeof(ports), p); return (p); } /* * Simulate how lagg_hashmbuf uses hash32 for a TCP/IP packet * No VLAN tagging */ uint32_t do_hash32(void) { // Actually, if_lagg used a pseudorandom number determined at interface // creation time. But this should have the same timing // characteristics. uint32_t p = HASHINIT; p = hash32_buf(ether_shost, 6, p); p = hash32_buf(ether_dhost, 6, p); p = hash32_buf(&ip_src, sizeof(struct in_addr), p); p = hash32_buf(&ip_dst, sizeof(struct in_addr), p); p = hash32_buf(&ports, sizeof(ports), p); return (p); } /* * Simulate how lagg_hashmbuf would use siphash24 for a TCP/IP packet * No VLAN tagging */ uint32_t do_siphash24(void) { SIPHASH_CTX ctx; SipHash24_Init(&ctx); SipHash_SetKey(&ctx, sipkey); 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); } /* * Simulate how lagg_hashmbuf would use lookup3 aka jenkins_hash * No VLAN tagging */ uint32_t do_jenkins(void) { /* Jenkins hash does not recommend any specific initializer */ uint32_t p = FNV1_32_INIT; /* * 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); } struct { do_hash_t *f; const char* name; } funcs[] = { {do_fnv, "FNV"}, {do_hash32, "hash32"}, {do_siphash24, "SipHash24"}, {do_jenkins, "Jenkins"}, }; int main(int argc, char** argv) { int i; for (i=0; i < sizeof(funcs) / sizeof(funcs[0]); i++) { struct timeval tv_old, tv_new, tv_diff; double t; int j; gettimeofday(&tv_old, NULL); for (j=0; j