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;

Reply via email to