diff options
author | Joerg Zinke <zinke@cvs.openbsd.org> | 2011-07-03 23:37:56 +0000 |
---|---|---|
committer | Joerg Zinke <zinke@cvs.openbsd.org> | 2011-07-03 23:37:56 +0000 |
commit | c22be30ebe7d9c8ce80dfe223351edaf2c035c33 (patch) | |
tree | 6f0a3aeb262e5e409f9d53b6db53c04ed76b9253 /sys/net/pf_table.c | |
parent | 8c4fabd58502851b921aa22c22ff07c9d5e3769a (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.c | 145 |
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) { |