summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorreyk <reyk@openbsd.org>2014-12-19 13:04:07 +0000
committerreyk <reyk@openbsd.org>2014-12-19 13:04:07 +0000
commit252a05523f8b93e11ba02b8ef3b3a195bb685de2 (patch)
treed552210362cc27b1905a0c16eb474e70fe3bb0fb /sys
parentComment is no longer true, remove it. (diff)
downloadwireguard-openbsd-252a05523f8b93e11ba02b8ef3b3a195bb685de2.tar.xz
wireguard-openbsd-252a05523f8b93e11ba02b8ef3b3a195bb685de2.zip
Support source-hash and random with tables and dynifs; not just pools.
This finally allows to use source-hash for dynamic loadbalancing, eg. "rdr-to <hosts> source-hash", instead of just round-robin and least-states. An older pre-siphash version of this diff was tested by many people. OK tedu@ benno@
Diffstat (limited to 'sys')
-rw-r--r--sys/net/pf_lb.c67
-rw-r--r--sys/net/pfvar.h8
2 files changed, 56 insertions, 19 deletions
diff --git a/sys/net/pf_lb.c b/sys/net/pf_lb.c
index e08b4092e94..bd7180c02c0 100644
--- a/sys/net/pf_lb.c
+++ b/sys/net/pf_lb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_lb.c,v 1.38 2014/12/19 12:31:03 mcbride Exp $ */
+/* $OpenBSD: pf_lb.c,v 1.39 2014/12/19 13:04:08 reyk Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -92,7 +92,7 @@
* Global variables
*/
-void pf_hash(struct pf_addr *, struct pf_addr *,
+u_int64_t pf_hash(struct pf_addr *, struct pf_addr *,
struct pf_poolhashkey *, sa_family_t);
int pf_get_sport(struct pf_pdesc *, struct pf_rule *,
struct pf_addr *, u_int16_t *, u_int16_t,
@@ -104,10 +104,11 @@ int pf_map_addr_sticky(sa_family_t, struct pf_rule *,
struct pf_src_node **, struct pf_pool *,
enum pf_sn_types);
-void
+u_int64_t
pf_hash(struct pf_addr *inaddr, struct pf_addr *hash,
struct pf_poolhashkey *key, sa_family_t af)
{
+ uint64_t res = 0;
#ifdef INET6
union {
uint64_t hash64;
@@ -118,14 +119,16 @@ pf_hash(struct pf_addr *inaddr, struct pf_addr *hash,
switch (af) {
#ifdef INET
case AF_INET:
- hash->addr32[0] = SipHash24((SIPHASH_KEY *)key,
+ res = SipHash24((SIPHASH_KEY *)key,
&inaddr->addr32[0], sizeof(inaddr->addr32[0]));
+ hash->addr32[0] = res;
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
- h.hash64 = SipHash24((SIPHASH_KEY *)key, &inaddr->addr32[0],
+ res = SipHash24((SIPHASH_KEY *)key, &inaddr->addr32[0],
4 * sizeof(inaddr->addr32[0]));
+ h.hash64 = res;
hash->addr32[0] = h.hash32[0];
hash->addr32[1] = h.hash32[1];
/*
@@ -137,6 +140,7 @@ pf_hash(struct pf_addr *inaddr, struct pf_addr *hash,
break;
#endif /* INET6 */
}
+ return (res);
}
int
@@ -337,6 +341,8 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
u_int16_t weight;
u_int64_t load;
u_int64_t cload;
+ u_int64_t hashidx;
+ int cnt;
if (sns[type] == NULL && rpool->opts & PF_POOL_STICKYADDR &&
(rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE &&
@@ -350,10 +356,7 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
#ifdef INET
case AF_INET:
if (rpool->addr.p.dyn->pfid_acnt4 < 1 &&
- ((rpool->opts & PF_POOL_TYPEMASK) !=
- PF_POOL_ROUNDROBIN) &&
- ((rpool->opts & PF_POOL_TYPEMASK) !=
- PF_POOL_LEASTSTATES))
+ !PF_POOL_DYNTYPE(rpool->opts))
return (1);
raddr = &rpool->addr.p.dyn->pfid_addr4;
rmask = &rpool->addr.p.dyn->pfid_mask4;
@@ -362,10 +365,7 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
#ifdef INET6
case AF_INET6:
if (rpool->addr.p.dyn->pfid_acnt6 < 1 &&
- ((rpool->opts & PF_POOL_TYPEMASK) !=
- PF_POOL_ROUNDROBIN) &&
- ((rpool->opts & PF_POOL_TYPEMASK) !=
- PF_POOL_LEASTSTATES))
+ !PF_POOL_DYNTYPE(rpool->opts))
return (1);
raddr = &rpool->addr.p.dyn->pfid_addr6;
rmask = &rpool->addr.p.dyn->pfid_mask6;
@@ -373,8 +373,7 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
#endif /* INET6 */
}
} else if (rpool->addr.type == PF_ADDR_TABLE) {
- if (((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN) &&
- ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_LEASTSTATES))
+ if (!PF_POOL_DYNTYPE(rpool->opts))
return (1); /* unsupported */
} else {
raddr = &rpool->addr.v.a.addr;
@@ -389,7 +388,21 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
PF_POOLMASK(naddr, raddr, rmask, saddr, af);
break;
case PF_POOL_RANDOM:
- if (init_addr != NULL && PF_AZERO(init_addr, af)) {
+ if (rpool->addr.type == PF_ADDR_TABLE) {
+ cnt = rpool->addr.p.tbl->pfrkt_cnt;
+ rpool->tblidx = (int)arc4random_uniform(cnt);
+ memset(&rpool->counter, 0, sizeof(rpool->counter));
+ if (pfr_pool_get(rpool, &raddr, &rmask, af))
+ return (1);
+ PF_ACPY(naddr, &rpool->counter, af);
+ } else if (rpool->addr.type == PF_ADDR_DYNIFTL) {
+ cnt = rpool->addr.p.dyn->pfid_kt->pfrkt_cnt;
+ rpool->tblidx = (int)arc4random_uniform(cnt);
+ memset(&rpool->counter, 0, sizeof(rpool->counter));
+ if (pfr_pool_get(rpool, &raddr, &rmask, af))
+ return (1);
+ PF_ACPY(naddr, &rpool->counter, af);
+ } else if (init_addr != NULL && PF_AZERO(init_addr, af)) {
switch (af) {
#ifdef INET
case AF_INET:
@@ -428,8 +441,26 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
}
break;
case PF_POOL_SRCHASH:
- pf_hash(saddr, (struct pf_addr *)&hash, &rpool->key, af);
- PF_POOLMASK(naddr, raddr, rmask, (struct pf_addr *)&hash, af);
+ hashidx =
+ pf_hash(saddr, (struct pf_addr *)&hash, &rpool->key, af);
+ if (rpool->addr.type == PF_ADDR_TABLE) {
+ cnt = rpool->addr.p.tbl->pfrkt_cnt;
+ rpool->tblidx = (int)(hashidx % cnt);
+ memset(&rpool->counter, 0, sizeof(rpool->counter));
+ if (pfr_pool_get(rpool, &raddr, &rmask, af))
+ return (1);
+ PF_ACPY(naddr, &rpool->counter, af);
+ } else if (rpool->addr.type == PF_ADDR_DYNIFTL) {
+ cnt = rpool->addr.p.dyn->pfid_kt->pfrkt_cnt;
+ rpool->tblidx = (int)(hashidx % cnt);
+ memset(&rpool->counter, 0, sizeof(rpool->counter));
+ if (pfr_pool_get(rpool, &raddr, &rmask, af))
+ return (1);
+ PF_ACPY(naddr, &rpool->counter, af);
+ } else {
+ PF_POOLMASK(naddr, raddr, rmask,
+ (struct pf_addr *)&hash, af);
+ }
break;
case PF_POOL_ROUNDROBIN:
if (rpool->addr.type == PF_ADDR_TABLE ||
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 25700e1f95c..08f6a98534e 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.404 2014/12/19 05:36:28 tedu Exp $ */
+/* $OpenBSD: pfvar.h,v 1.405 2014/12/19 13:04:08 reyk Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -118,6 +118,12 @@ enum { PF_ADDR_ADDRMASK, PF_ADDR_NOROUTE, PF_ADDR_DYNIFTL,
#define PF_WSCALE_FLAG 0x80
#define PF_WSCALE_MASK 0x0f
+#define PF_POOL_DYNTYPE(_o) \
+ ((((_o) & PF_POOL_TYPEMASK) == PF_POOL_ROUNDROBIN) || \
+ (((_o) & PF_POOL_TYPEMASK) == PF_POOL_LEASTSTATES) || \
+ (((_o) & PF_POOL_TYPEMASK) == PF_POOL_RANDOM) || \
+ (((_o) & PF_POOL_TYPEMASK) == PF_POOL_SRCHASH))
+
#define PF_LOG 0x01
#define PF_LOG_ALL 0x02
#define PF_LOG_SOCKET_LOOKUP 0x04