summaryrefslogtreecommitdiff
path: root/sys/net/pf_table.c
diff options
context:
space:
mode:
authorJoerg Zinke <zinke@cvs.openbsd.org>2011-07-03 23:37:56 +0000
committerJoerg Zinke <zinke@cvs.openbsd.org>2011-07-03 23:37:56 +0000
commitc22be30ebe7d9c8ce80dfe223351edaf2c035c33 (patch)
tree6f0a3aeb262e5e409f9d53b6db53c04ed76b9253 /sys/net/pf_table.c
parent8c4fabd58502851b921aa22c22ff07c9d5e3769a (diff)
bring in least-states load balancing algorithm
ok mcbride@ henning@
Diffstat (limited to 'sys/net/pf_table.c')
-rw-r--r--sys/net/pf_table.c145
1 files changed, 128 insertions, 17 deletions
diff --git a/sys/net/pf_table.c b/sys/net/pf_table.c
index 433888272d0..c6f6f74ecc7 100644
--- a/sys/net/pf_table.c
+++ b/sys/net/pf_table.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_table.c,v 1.90 2011/06/14 10:14:01 mcbride Exp $ */
+/* $OpenBSD: pf_table.c,v 1.91 2011/07/03 23:37:55 zinke Exp $ */
/*
* Copyright (c) 2002 Cedric Berger
@@ -148,7 +148,7 @@ void pfr_enqueue_addrs(struct pfr_ktable *,
void pfr_mark_addrs(struct pfr_ktable *);
struct pfr_kentry *pfr_lookup_addr(struct pfr_ktable *,
struct pfr_addr *, int);
-struct pfr_kentry *pfr_create_kentry(struct pfr_addr *);
+struct pfr_kentry *pfr_create_kentry(struct pfr_addr *, u_int32_t);
void pfr_destroy_kentries(struct pfr_kentryworkq *);
void pfr_destroy_kentry(struct pfr_kentry *);
void pfr_insert_kentries(struct pfr_ktable *,
@@ -203,6 +203,8 @@ pfr_initialize(void)
0, 0, 0, "pfrke_plain", NULL);
pool_init(&pfr_kentry_pl[PFRKE_ROUTE], sizeof(struct pfr_kentry_route),
0, 0, 0, "pfrke_route", NULL);
+ pool_init(&pfr_kentry_pl[PFRKE_COST], sizeof(struct pfr_kentry_cost),
+ 0, 0, 0, "pfrke_cost", NULL);
pool_init(&pfr_kcounters_pl, sizeof(struct pfr_kcounters),
0, 0, 0, "pfrkcounters", NULL);
@@ -287,7 +289,7 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
ad.pfra_fback = PFR_FB_NONE;
}
if (p == NULL && q == NULL) {
- p = pfr_create_kentry(&ad);
+ p = pfr_create_kentry(&ad, kt->pfrkt_flags);
if (p == NULL)
senderr(ENOMEM);
if (pfr_route_kentry(tmpkt, p)) {
@@ -463,7 +465,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
ad.pfra_fback = PFR_FB_DUPLICATE;
goto _skip;
}
- p = pfr_create_kentry(&ad);
+ p = pfr_create_kentry(&ad, kt->pfrkt_flags);
if (p == NULL)
senderr(ENOMEM);
if (pfr_route_kentry(tmpkt, p)) {
@@ -798,10 +800,25 @@ pfr_lookup_addr(struct pfr_ktable *kt, struct pfr_addr *ad, int exact)
}
struct pfr_kentry *
-pfr_create_kentry(struct pfr_addr *ad)
+pfr_create_kentry(struct pfr_addr *ad, u_int32_t flags)
{
struct pfr_kentry_all *ke;
+ if (flags & PFR_TFLAG_COST) {
+ switch (ad->pfra_type) {
+ case PFRKE_PLAIN:
+ case PFRKE_ROUTE:
+ ad->pfra_type = PFRKE_COST;
+ break;
+ case PFRKE_COST:
+ break;
+ default:
+ /* not compatible with PFR_FLAG_COST */
+ /* XXX debug output? check earlier? */
+ return (NULL);
+ }
+ }
+
ke = pool_get(&pfr_kentry_pl[ad->pfra_type], PR_NOWAIT | PR_ZERO);
if (ke == NULL)
return (NULL);
@@ -809,13 +826,14 @@ pfr_create_kentry(struct pfr_addr *ad)
ke->pfrke_type = ad->pfra_type;
switch (ke->pfrke_type) {
- case PFRKE_PLAIN:
- break;
case PFRKE_ROUTE:
+ case PFRKE_COST:
ke->pfrke_rkif = pfi_kif_get(ad->pfra_ifname);
if (ke->pfrke_rkif)
pfi_kif_ref(ke->pfrke_rkif, PFI_KIF_REF_ROUTE);
break;
+ case PFRKE_PLAIN:
+ break;
default:
panic("unknown pfrke_type %d", ke->pfrke_type);
break;
@@ -884,7 +902,7 @@ pfr_insert_kentry(struct pfr_ktable *kt, struct pfr_addr *ad, long tzero)
p = pfr_lookup_addr(kt, ad, 1);
if (p != NULL)
return (0);
- p = pfr_create_kentry(ad);
+ p = pfr_create_kentry(ad, kt->pfrkt_flags);
if (p == NULL)
return (EINVAL);
@@ -1046,17 +1064,26 @@ pfr_copyout_addr(struct pfr_addr *ad, struct pfr_kentry *ke)
return;
ad->pfra_af = ke->pfrke_af;
ad->pfra_net = ke->pfrke_net;
+ ad->pfra_type = ke->pfrke_type;
if (ke->pfrke_flags & PFRKE_FLAG_NOT)
ad->pfra_not = 1;
if (ad->pfra_af == AF_INET)
ad->pfra_ip4addr = ke->pfrke_sa.sin.sin_addr;
else if (ad->pfra_af == AF_INET6)
ad->pfra_ip6addr = ke->pfrke_sa.sin6.sin6_addr;
- if (ke->pfrke_type == PFRKE_ROUTE &&
- ((struct pfr_kentry_route *)ke)->kif != NULL)
- strlcpy(ad->pfra_ifname,
- ((struct pfr_kentry_route *)ke)->kif->pfik_name,
- IFNAMSIZ);
+ switch (ke->pfrke_type) {
+ case PFRKE_COST:
+ ad->pfra_states = ((struct pfr_kentry_cost *)ke)->states;
+ /* FALLTHROUGH */
+ case PFRKE_ROUTE:
+ if (((struct pfr_kentry_route *)ke)->kif != NULL)
+ strlcpy(ad->pfra_ifname,
+ ((struct pfr_kentry_route *)ke)->kif->pfik_name,
+ IFNAMSIZ);
+ break;
+ default:
+ break;
+ }
}
int
@@ -1555,7 +1582,7 @@ _skip:
senderr(EINVAL);
if (pfr_lookup_addr(shadow, &ad, 1) != NULL)
continue;
- p = pfr_create_kentry(&ad);
+ p = pfr_create_kentry(&ad, kt->pfrkt_flags);
if (p == NULL)
senderr(ENOMEM);
if (pfr_route_kentry(shadow, p)) {
@@ -2115,7 +2142,8 @@ pfr_detach_table(struct pfr_ktable *kt)
int
pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter,
struct pf_addr **raddr, struct pf_addr **rmask, struct pfi_kif **kif,
- sa_family_t af, int (*filter)(sa_family_t, struct pf_addr *))
+ u_int32_t *states, sa_family_t af,
+ int (*filter)(sa_family_t, struct pf_addr *))
{
struct pfr_kentry *ke, *ke2;
struct pf_addr *addr;
@@ -2176,8 +2204,16 @@ _next_block:
PF_ACPY(counter, addr, af);
*pidx = idx;
kt->pfrkt_match++;
- if (ke->pfrke_type == PFRKE_ROUTE)
+ switch (ke->pfrke_type) {
+ case PFRKE_COST:
+ *states = ((struct pfr_kentry_cost *)ke)->states;
+ /* FALLTHROUGH */
+ case PFRKE_ROUTE:
*kif = ((struct pfr_kentry_route *)ke)->kif;
+ break;
+ default:
+ break;
+ }
return (0);
}
for (;;) {
@@ -2196,8 +2232,17 @@ _next_block:
PF_ACPY(counter, addr, af);
*pidx = idx;
kt->pfrkt_match++;
- if (ke->pfrke_type == PFRKE_ROUTE)
+ switch (ke->pfrke_type) {
+ case PFRKE_COST:
+ *states =
+ ((struct pfr_kentry_cost *)ke)->states;
+ /* FALLTHROUGH */
+ case PFRKE_ROUTE:
*kif = ((struct pfr_kentry_route *)ke)->kif;
+ break;
+ default:
+ break;
+ }
return (0);
}
_next_entry:
@@ -2240,6 +2285,72 @@ pfr_kentry_byidx(struct pfr_ktable *kt, int idx, int af)
}
}
+/* added for slb counter use */
+int
+pfr_states_increase(struct pfr_ktable *kt, struct pf_addr *addr, int af)
+{
+ struct pfr_kentry *ke;
+
+ ke = pfr_kentry_byaddr(kt, addr, af, 1);
+ if (ke == NULL || ke->pfrke_type != PFRKE_COST)
+ return (-1);
+
+ ((struct pfr_kentry_cost *)ke)->states++;
+ return (((struct pfr_kentry_cost *)ke)->states);
+}
+
+/* added for slb counter use */
+int
+pfr_states_decrease(struct pfr_ktable *kt, struct pf_addr *addr, int af)
+{
+ struct pfr_kentry *ke;
+
+ ke = pfr_kentry_byaddr(kt, addr, af, 1);
+ if (ke == NULL || ke->pfrke_type != PFRKE_COST)
+ return (-1);
+
+ if (((struct pfr_kentry_cost *)ke)->states > 0)
+ ((struct pfr_kentry_cost *)ke)->states--;
+ else
+ DPFPRINTF(LOG_DEBUG,
+ "pfr_states_increase: states-- when states <= 0");
+
+ return (((struct pfr_kentry_cost *)ke)->states);
+}
+
+/*
+ * Added for slb to find a kentry outside of the table.
+ * We need to create a custom pfr_addr struct.
+ */
+struct pfr_kentry *
+pfr_kentry_byaddr(struct pfr_ktable *kt, struct pf_addr *addr, sa_family_t af,
+ int exact)
+{
+ struct pfr_kentry *ke;
+ struct pfr_addr p;
+
+ bzero(&p, sizeof(p));
+ p.pfra_af = af;
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ p.pfra_net = 32;
+ p.pfra_ip4addr = addr->v4;
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ p.pfra_net = 128;
+ p.pfra_ip6addr = addr->v6;
+ break;
+#endif /* INET6 */
+ }
+
+ ke = pfr_lookup_addr(kt, &p, exact);
+
+ return ke;
+}
+
void
pfr_dynaddr_update(struct pfr_ktable *kt, struct pfi_dynaddr *dyn)
{