git: bc830a1acca6 - main - pf: use siphash for pf_lb
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 20 Feb 2025 09:35:26 UTC
The branch main has been updated by kp:
URL: https://cgit.FreeBSD.org/src/commit/?id=bc830a1acca67b74283d40d7ebdb048f9af3567e
commit bc830a1acca67b74283d40d7ebdb048f9af3567e
Author: Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2025-02-12 16:56:45 +0000
Commit: Kristof Provost <kp@FreeBSD.org>
CommitDate: 2025-02-20 08:25:50 +0000
pf: use siphash for pf_lb
for ipv6, we stretch it out a bit, but good enough.
ok reyk
Obtained from: OpenBSD, tedu <tedu@openbsd.org>, a558d13e2f
Sponsored by: Rubicon Communications, LLC ("Netgate")
---
sys/netpfil/pf/pf_lb.c | 60 +++++++++++++++++++-------------------------------
1 file changed, 23 insertions(+), 37 deletions(-)
diff --git a/sys/netpfil/pf/pf_lb.c b/sys/netpfil/pf/pf_lb.c
index 9c2d7b4c71b6..dce0520793fa 100644
--- a/sys/netpfil/pf/pf_lb.c
+++ b/sys/netpfil/pf/pf_lb.c
@@ -47,6 +47,8 @@
#include <sys/socket.h>
#include <sys/sysctl.h>
+#include <crypto/siphash/siphash.h>
+
#include <net/if.h>
#include <net/if_var.h>
#include <net/vnet.h>
@@ -82,19 +84,6 @@ static int pf_get_sport(struct pf_pdesc *, struct pf_krule *,
pf_sn_types_t);
static bool pf_islinklocal(const sa_family_t, const struct pf_addr *);
-#define mix(a,b,c) \
- do { \
- a -= b; a -= c; a ^= (c >> 13); \
- b -= c; b -= a; b ^= (a << 8); \
- c -= a; c -= b; c ^= (b >> 13); \
- a -= b; a -= c; a ^= (c >> 12); \
- b -= c; b -= a; b ^= (a << 16); \
- c -= a; c -= b; c ^= (b >> 5); \
- a -= b; a -= c; a ^= (c >> 3); \
- b -= c; b -= a; b ^= (a << 10); \
- c -= a; c -= b; c ^= (b >> 15); \
- } while (0)
-
/*
* hash function based on bridge_hash in if_bridge.c
*/
@@ -102,38 +91,35 @@ static void
pf_hash(struct pf_addr *inaddr, struct pf_addr *hash,
struct pf_poolhashkey *key, sa_family_t af)
{
- u_int32_t a = 0x9e3779b9, b = 0x9e3779b9, c = key->key32[0];
+ SIPHASH_CTX ctx;
+#ifdef INET6
+ union {
+ uint64_t hash64;
+ uint32_t hash32[2];
+ } h;
+#endif
+
+ _Static_assert(sizeof(*key) >= SIPHASH_KEY_LENGTH, "");
switch (af) {
#ifdef INET
case AF_INET:
- a += inaddr->addr32[0];
- b += key->key32[1];
- mix(a, b, c);
- hash->addr32[0] = c + key->key32[2];
+ hash->addr32[0] = SipHash24(&ctx, (const uint8_t *)key,
+ &inaddr->addr32[0], sizeof(inaddr->addr32[0]));
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
- a += inaddr->addr32[0];
- b += inaddr->addr32[2];
- mix(a, b, c);
- hash->addr32[0] = c;
- a += inaddr->addr32[1];
- b += inaddr->addr32[3];
- c += key->key32[1];
- mix(a, b, c);
- hash->addr32[1] = c;
- a += inaddr->addr32[2];
- b += inaddr->addr32[1];
- c += key->key32[2];
- mix(a, b, c);
- hash->addr32[2] = c;
- a += inaddr->addr32[3];
- b += inaddr->addr32[0];
- c += key->key32[3];
- mix(a, b, c);
- hash->addr32[3] = c;
+ h.hash64 = SipHash24(&ctx, (const uint8_t *)key,
+ &inaddr->addr32[0], 4 * sizeof(inaddr->addr32[0]));
+ hash->addr32[0] = h.hash32[0];
+ hash->addr32[1] = h.hash32[1];
+ /*
+ * siphash isn't big enough, but flipping it around is
+ * good enough here.
+ */
+ hash->addr32[2] = ~h.hash32[1];
+ hash->addr32[3] = ~h.hash32[0];
break;
#endif /* INET6 */
}