diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2014-12-19 13:04:09 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2014-12-19 13:04:09 +0000 |
commit | de2084475fd45c082f773f17d848f2cce4ed7992 (patch) | |
tree | 5052ceb963abb9b22944594aef4d2e7ee93c98c6 /sys/net/pf_lb.c | |
parent | 9cd70453e5bf244511b40278a8965742a203f0ed (diff) |
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/net/pf_lb.c')
-rw-r--r-- | sys/net/pf_lb.c | 67 |
1 files changed, 49 insertions, 18 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 || |