This diff converts relayd from hash32 to siphash. Relayd does not use the hash function for an actual hash table, but can select a host based on the hash of the source-address, destination-address and other data. The key is generated when the hash function is first used (this may happen in two different places, in relay.c or relay_http.c).
Previously, relayd used u_int32_t rlt_key to store either an intermediate hash value or the next index for round-robin. Since a SIPHASH_CTX is no u_int32_t, this had to be split into two variables. Comments? This compiles, but I haven't tested it. Index: usr.sbin/relayd/parse.y =================================================================== RCS file: /cvs/src/usr.sbin/relayd/parse.y,v retrieving revision 1.195 diff -u -p -r1.195 parse.y --- usr.sbin/relayd/parse.y 20 Nov 2014 05:51:20 -0000 1.195 +++ usr.sbin/relayd/parse.y 10 Dec 2014 02:12:02 -0000 @@ -30,7 +30,6 @@ #include <sys/stat.h> #include <sys/queue.h> #include <sys/ioctl.h> -#include <sys/hash.h> #include <net/if.h> #include <net/pfvar.h> Index: usr.sbin/relayd/relay.c =================================================================== RCS file: /cvs/src/usr.sbin/relayd/relay.c,v retrieving revision 1.181 diff -u -p -r1.181 relay.c --- usr.sbin/relayd/relay.c 19 Nov 2014 10:24:40 -0000 1.181 +++ usr.sbin/relayd/relay.c 10 Dec 2014 02:12:02 -0000 @@ -41,6 +41,7 @@ #include <pwd.h> #include <event.h> #include <fnmatch.h> +#include <siphash.h> #include <openssl/dh.h> #include <openssl/ssl.h> @@ -72,7 +73,7 @@ int relay_socket_connect(struct sockad void relay_accept(int, short, void *); void relay_input(struct rsession *); -u_int32_t relay_hash_addr(struct sockaddr_storage *, u_int32_t); +void relay_hash_addr(struct sockaddr_storage *, SIPHASH_CTX *); DH * relay_ssl_get_dhparams(int); void relay_ssl_callback_info(const SSL *, int, int); @@ -441,16 +442,21 @@ relay_launch(void) switch (rlt->rlt_mode) { case RELAY_DSTMODE_ROUNDROBIN: case RELAY_DSTMODE_RANDOM: - rlt->rlt_key = 0; + rlt->rlt_rr_key = 0; break; case RELAY_DSTMODE_LOADBALANCE: case RELAY_DSTMODE_HASH: case RELAY_DSTMODE_SRCHASH: - rlt->rlt_key = - hash32_str(rlay->rl_conf.name, HASHINIT); - rlt->rlt_key = - hash32_str(rlt->rlt_table->conf.name, - rlt->rlt_key); + if (sip_key == NULL) { + sip_key = malloc(SIPHASH_KEY_LENGTH); + arc4random_buf(sip_key, SIPHASH_KEY_LENGTH); + } + SipHash24_Init(&rlt->rlt_ctx, sip_key); + SipHash24_Update(&rlt->rlt_ctx, rlay->rl_conf.name, + strlen(rlay->rl_conf.name)); + SipHash24_Update(&rlt->rlt_ctx, + rlt->rlt_table->conf.name, + strlen(rlt->rlt_table->conf.name)); break; } rlt->rlt_nhosts = 0; @@ -1180,23 +1186,20 @@ relay_accept(int fd, short event, void * } } -u_int32_t -relay_hash_addr(struct sockaddr_storage *ss, u_int32_t p) +void +relay_hash_addr(struct sockaddr_storage *ss, SIPHASH_CTX *ctxp) { struct sockaddr_in *sin4; struct sockaddr_in6 *sin6; if (ss->ss_family == AF_INET) { sin4 = (struct sockaddr_in *)ss; - p = hash32_buf(&sin4->sin_addr, - sizeof(struct in_addr), p); + SipHash24_Update(ctxp, &sin4->sin_addr, sizeof(struct in_addr)); } else { sin6 = (struct sockaddr_in6 *)ss; - p = hash32_buf(&sin6->sin6_addr, - sizeof(struct in6_addr), p); + SipHash24_Update(ctxp, &sin6->sin6_addr, + sizeof(struct in6_addr)); } - - return (p); } int @@ -1206,7 +1209,7 @@ relay_from_table(struct rsession *con) struct host *host; struct relay_table *rlt = NULL; struct table *table = NULL; - u_int32_t p = con->se_hashkey; + SIPHASH_CTX ctx = con->se_hashctx; int idx = -1; /* the table is already selected */ @@ -1234,16 +1237,16 @@ relay_from_table(struct rsession *con) __func__, con->se_id); return (-1); } - if (!con->se_hashkeyset) { - p = con->se_hashkey = rlt->rlt_key; - con->se_hashkeyset = 1; + if (!con->se_hashctxset) { + ctx = con->se_hashctx = rlt->rlt_ctx; + con->se_hashctxset = 1; } switch (rlt->rlt_mode) { case RELAY_DSTMODE_ROUNDROBIN: - if ((int)rlt->rlt_key >= rlt->rlt_nhosts) - rlt->rlt_key = 0; - idx = (int)rlt->rlt_key; + if ((int)rlt->rlt_rr_key >= rlt->rlt_nhosts) + rlt->rlt_rr_key = 0; + idx = (int)rlt->rlt_rr_key; break; case RELAY_DSTMODE_RANDOM: idx = (int)arc4random_uniform(rlt->rlt_nhosts); @@ -1251,21 +1254,22 @@ relay_from_table(struct rsession *con) case RELAY_DSTMODE_SRCHASH: case RELAY_DSTMODE_LOADBALANCE: /* Source IP address without port */ - p = relay_hash_addr(&con->se_in.ss, p); + relay_hash_addr(&con->se_in.ss, &ctx); if (rlt->rlt_mode == RELAY_DSTMODE_SRCHASH) break; /* FALLTHROUGH */ case RELAY_DSTMODE_HASH: /* Local "destination" IP address and port */ - p = relay_hash_addr(&rlay->rl_conf.ss, p); - p = hash32_buf(&rlay->rl_conf.port, - sizeof(rlay->rl_conf.port), p); + relay_hash_addr(&rlay->rl_conf.ss, &ctx); + SipHash24_Update(&ctx, &rlay->rl_conf.port, + sizeof(rlay->rl_conf.port)); break; default: fatalx("relay_from_table: unsupported mode"); /* NOTREACHED */ } - if (idx == -1 && (idx = p % rlt->rlt_nhosts) >= RELAY_MAXHOSTS) + if (idx == -1 && (idx = SipHash24_End(&ctx) % rlt->rlt_nhosts) + >= RELAY_MAXHOSTS) return (-1); host = rlt->rlt_host[idx]; DPRINTF("%s: session %d: table %s host %s, p 0x%08x, idx %d", @@ -1289,7 +1293,7 @@ relay_from_table(struct rsession *con) found: if (rlt->rlt_mode == RELAY_DSTMODE_ROUNDROBIN) - rlt->rlt_key = host->idx + 1; + rlt->rlt_rr_key = host->idx + 1; con->se_retry = host->conf.retry; con->se_out.port = table->conf.port; bcopy(&host->conf.ss, &con->se_out.ss, sizeof(con->se_out.ss)); Index: usr.sbin/relayd/relay_http.c =================================================================== RCS file: /cvs/src/usr.sbin/relayd/relay_http.c,v retrieving revision 1.35 diff -u -p -r1.35 relay_http.c --- usr.sbin/relayd/relay_http.c 25 Oct 2014 03:23:49 -0000 1.35 +++ usr.sbin/relayd/relay_http.c 10 Dec 2014 02:12:03 -0000 @@ -41,6 +41,7 @@ #include <pwd.h> #include <event.h> #include <fnmatch.h> +#include <siphash.h> #include <openssl/ssl.h> @@ -1487,12 +1488,19 @@ relay_apply_actions(struct ctl_relay_eve value = match->kv_value; break; } - if (!con->se_hashkeyset) - con->se_hashkey = HASHINIT; - con->se_hashkey = hash32_str(value, con->se_hashkey); - con->se_hashkeyset = 1; + if (!con->se_hashctxset) { + if (sip_key == NULL) { + sip_key = malloc(SIPHASH_KEY_LENGTH); + arc4random_buf(sip_key, SIPHASH_KEY_LENGTH); + } + } + SipHash_Init(&con->se_hashctx, sip_key); + SipHash24_Update(&con->se_hashctx, value, strlen(value)); + con->se_hashctxset = 1; + /* log_debug("%s: hashkey 0x%04x", __func__, - con->se_hashkey); + con->se_hashctx); + */ break; case KEY_OPTION_LOG: /* perform this later */ Index: usr.sbin/relayd/relay_udp.c =================================================================== RCS file: /cvs/src/usr.sbin/relayd/relay_udp.c,v retrieving revision 1.34 diff -u -p -r1.34 relay_udp.c --- usr.sbin/relayd/relay_udp.c 19 Nov 2014 10:24:40 -0000 1.34 +++ usr.sbin/relayd/relay_udp.c 10 Dec 2014 02:12:03 -0000 @@ -23,7 +23,6 @@ #include <sys/socket.h> #include <sys/un.h> #include <sys/tree.h> -#include <sys/hash.h> #include <net/if.h> #include <netinet/in.h> Index: usr.sbin/relayd/relayd.c =================================================================== RCS file: /cvs/src/usr.sbin/relayd/relayd.c,v retrieving revision 1.133 diff -u -p -r1.133 relayd.c --- usr.sbin/relayd/relayd.c 22 Nov 2014 00:24:22 -0000 1.133 +++ usr.sbin/relayd/relayd.c 10 Dec 2014 02:12:03 -0000 @@ -22,7 +22,6 @@ #include <sys/socket.h> #include <sys/wait.h> #include <sys/resource.h> -#include <sys/hash.h> #include <net/if.h> #include <netinet/in.h> Index: usr.sbin/relayd/relayd.h =================================================================== RCS file: /cvs/src/usr.sbin/relayd/relayd.h,v retrieving revision 1.197 diff -u -p -r1.197 relayd.h --- usr.sbin/relayd/relayd.h 19 Nov 2014 10:24:40 -0000 1.197 +++ usr.sbin/relayd/relayd.h 10 Dec 2014 02:12:03 -0000 @@ -26,6 +26,7 @@ #include <sys/param.h> /* MAXHOSTNAMELEN */ #include <limits.h> #include <imsg.h> +#include <siphash.h> /* SIPHASH_KEY, SIPHASH_CTX */ #ifndef nitems #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) @@ -515,8 +516,8 @@ struct rsession { struct ctl_relay_event se_in; struct ctl_relay_event se_out; void *se_priv; - u_int32_t se_hashkey; - int se_hashkeyset; + SIPHASH_CTX se_hashctx; + int se_hashctxset; struct relay_table *se_table; struct event se_ev; struct timeval se_timeout; @@ -695,11 +696,14 @@ struct protocol { }; TAILQ_HEAD(protolist, protocol); +SIPHASH_KEY *sip_key; + struct relay_table { struct table *rlt_table; u_int32_t rlt_flags; int rlt_mode; - u_int32_t rlt_key; + u_int32_t rlt_rr_key; /* round-robin */ + SIPHASH_CTX rlt_ctx; struct host *rlt_host[RELAY_MAXHOSTS]; int rlt_nhosts; TAILQ_ENTRY(relay_table) rlt_entry;