vBulletin Search Engine Optimization
| |||||||
| Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| Hi, no replies on this? Not even a rude comment about bad style or something? No one interested in load balancing improvements in pf? Would be really nice to get any feedback. Maybe I should show some motivating numbers, measured with this patch and the following http_load command: # http_load -checksum -parallel 250 -seconds 300 urls First the (more or less) homegenous case: round robin load balancing: 136231 fetches, 250 max parallel, 2.44418e+09 bytes, in 300.067 seconds 17941.4 mean bytes/connection 454.003 fetches/sec, 8.14546e+06 bytes/sec msecs/connect: 69.3413 mean, 6062.48 max, 0.298 min msecs/first-response: 92.1632 mean, 1816.77 max, 1.595 min 155 timeouts 155 bad checksums HTTP response codes: code 200 -- 136076 least connection load balancing: 134761 fetches, 250 max parallel, 2.43179e+09 bytes, in 300.005 seconds 18045.2 mean bytes/connection 449.197 fetches/sec, 8.10586e+06 bytes/sec msecs/connect: 71.0781 mean, 6215.56 max, 0.282 min msecs/first-response: 98.1345 mean, 3214.45 max, 1.354 min 114 timeouts 114 bad checksums HTTP response codes: code 200 -- 134647 The homogenous case is not so exciting and not really surprisingly, nearly the same numbers. But now the heterogenous case (same hardware setup but with a heavily throttled webserver): round robin load balancing: 3694 fetches, 250 max parallel, 6.21951e+07 bytes, in 300.007 seconds 16836.8 mean bytes/connection 12.3131 fetches/sec, 207312 bytes/sec msecs/connect: 2.18098 mean, 26.07 max, 0.247 min msecs/first-response: 8.98524 mean, 183.417 max, 0.43 min 1 timeouts 1 bad checksums HTTP response codes: code 200 -- 3694 least connection load balancing: 49043 fetches, 250 max parallel, 8.82868e+08 bytes, in 300.028 seconds 18001.9 mean bytes/connection 163.461 fetches/sec, 2.94262e+06 bytes/sec msecs/connect: 3.32824 mean, 203.877 max, 0.25 min msecs/first-response: 4.26748 mean, 216.211 max, 0.37 min 1 timeouts 1 bad checksums HTTP response codes: code 200 -- 49043 Especially in heterogenous environemnts e.g. heterogenous requests on dynamic websites, LC has advantages over simple RR. Regards, Joerg On Sun, 20 Apr 2008 00:16:39 +0200 Joerg Zinke <umaxx@oleco.net> wrote: > > Hi, > > > > here comes a diff wich implements a more sophisticated load balancing > > algorithm for PF-pools called: least connection (LC). > > > > Something like the following in pf.conf works fine for me: > > > > table <first> const { 192.168.100.233/32 } > > table <second> const { 192.168.100.234/32 } > > > > rdr pass log on msk0 proto tcp from any to 192.168.100.102 port 80 -> > > { <first>, <second> } port 80 least-connection > > > > This diff is very simple for now: every connection to a destination is > > counted with the same weight. I wanted to keep the first initial diff > > as simple as possible but I plan to improve things - see todo/roadmap > > below. > > > > This diff does the following: > > > > - adds a new simple RB-tree based state table for counting > > redirected connections of destinations (similar to src nodes) > > - insert/remove and updates states in this new RB-tree > > - implements a new redirection algorithm based on this RB-tree: least > > connection > > > > Todo/roadmap: > > > > - mention new keyword in manpage > > - sync new RB-Tree via pfsync too > > - make a difference between active and inactive connections > > (time_wait) for LC > > - maybe create dependency from counts to rules (like src_node does) > > - implement more algorithms like shortest expected delay (SED) and > > never queue (based on the new RB-Tree too) > > - provide new algorithms in relayd too > > - add weights and weighted variants of algorithms: weighted round > > robin (WRR) and weighted least connectin (WLC) -> this needs some way > > to set these weights via pfctl and pf.conf (which syntax?) > > - maybe seperate load balancing code out of pf.c into an own file: > > pf_lb.c > > > > Diff is below and can be downloaded from: > > > > https://www.umaxx.net/src/pf-lc1.diff > > > > Comments, suggestions, hints, rants and flames are welcome... > > > > Regards, > > > > Joerg > > Index: pf.c > ================================================== ================= > RCS file: /cvs/src/sys/net/pf.c,v > retrieving revision 1.567 > diff -u -p -r1.567 pf.c > --- pf.c 20 Feb 2008 23:40:13 -0000 1.567 > +++ pf.c 19 Apr 2008 19:41:13 -0000 > @@ -124,7 +124,7 @@ struct pf_anchor_stackframe { > struct pf_anchor *child; > } pf_anchor_stack[64]; > > -struct pool pf_src_tree_pl, pf_rule_pl, pf_pooladdr_pl; > +struct pool pf_src_tree_pl, pf_rdr_dst_tree_pl, pf_rule_pl, pf_pooladdr_pl; > struct pool pf_state_pl, pf_state_key_pl; > struct pool pf_altq_pl; > > @@ -196,7 +196,7 @@ int pf_step_out_of_anchor(int *, stru > void pf_hash(struct pf_addr *, struct pf_addr *, > struct pf_poolhashkey *, sa_family_t); > int pf_map_addr(u_int8_t, struct pf_rule *, > - struct pf_addr *, struct pf_addr *, > + struct pf_addr *, struct pf_addr *, struct pf_addr *, > struct pf_addr *, struct pf_src_node **); > int pf_get_sport(sa_family_t, u_int8_t, struct pf_rule *, > struct pf_addr *, struct pf_addr *, u_int16_t, > @@ -216,7 +216,7 @@ u_int16_t pf_get_mss(struct mbuf *, in > u_int16_t pf_calc_mss(struct pf_addr *, sa_family_t, > u_int16_t); > void pf_set_rt_ifp(struct pf_state *, > - struct pf_addr *); > + struct pf_addr *, struct pf_addr *); > int pf_check_proto_cksum(struct mbuf *, int, int, > u_int8_t, sa_family_t); > int pf_addr_wrap_neq(struct pf_addr_wrap *, > @@ -234,6 +234,7 @@ extern struct pool pfr_kentry_pl; > struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = { > { &pf_state_pl, PFSTATE_HIWAT }, > { &pf_src_tree_pl, PFSNODE_HIWAT }, > + { &pf_rdr_dst_tree_pl, PFRDNODE_HIWAT }, > { &pf_frent_pl, PFFRAG_FRENT_HIWAT }, > { &pfr_ktable_pl, PFR_KTABLE_HIWAT }, > { &pfr_kentry_pl, PFR_KENTRY_HIWAT } > @@ -284,6 +285,7 @@ struct pf_pool_limit pf_pool_limits[PF_L > } while (0) > > static __inline int pf_src_compare(struct pf_src_node *, struct pf_src_node *); > +static __inline int pf_rdr_dst_compare(struct pf_rdr_dst_node *, struct pf_rdr_dst_node *); > static __inline int pf_state_compare_lan_ext(struct pf_state_key *, > struct pf_state_key *); > static __inline int pf_state_compare_ext_gwy(struct pf_state_key *, > @@ -292,11 +294,13 @@ static __inline int pf_state_compare_id( > struct pf_state *); > > struct pf_src_tree tree_src_tracking; > +struct pf_rdr_dst_tree tree_rdr_dst_tracking; > > struct pf_state_tree_id tree_id; > struct pf_state_queue state_list; > > RB_GENERATE(pf_src_tree, pf_src_node, entry, pf_src_compare); > +RB_GENERATE(pf_rdr_dst_tree, pf_rdr_dst_node, entry, pf_rdr_dst_compare); > RB_GENERATE(pf_state_tree_lan_ext, pf_state_key, > entry_lan_ext, pf_state_compare_lan_ext); > RB_GENERATE(pf_state_tree_ext_gwy, pf_state_key, > @@ -352,6 +356,52 @@ pf_src_compare(struct pf_src_node *a, st > } > > static __inline int > +pf_rdr_dst_compare(struct pf_rdr_dst_node *a, struct pf_rdr_dst_node *b) > +{ > + int diff; > + > + /* > + * No need to track ports or protocol for > + * destination connection counting. > + */ > + > + if ((diff = a->af - b->af) != 0) > + return (diff); > + switch (a->af) { > +#ifdef INET > + case AF_INET: > + if (a->addr.addr32[0] > b->addr.addr32[0]) > + return (1); > + if (a->addr.addr32[0] < b->addr.addr32[0]) > + return (-1); > + break; > +#endif /* INET */ > +#ifdef INET6 > + case AF_INET6: > + if (a->addr.addr32[3] > b->addr.addr32[3]) > + return (1); > + if (a->addr.addr32[3] < b->addr.addr32[3]) > + return (-1); > + if (a->addr.addr32[2] > b->addr.addr32[2]) > + return (1); > + if (a->addr.addr32[2] < b->addr.addr32[2]) > + return (-1); > + if (a->addr.addr32[1] > b->addr.addr32[1]) > + return (1); > + if (a->addr.addr32[1] < b->addr.addr32[1]) > + return (-1); > + if (a->addr.addr32[0] > b->addr.addr32[0]) > + return (1); > + if (a->addr.addr32[0] < b->addr.addr32[0]) > + return (-1); > + break; > +#endif /* INET6 */ > + } > + > + return (0); > +} > + > +static __inline int > pf_state_compare_lan_ext(struct pf_state_key *a, struct pf_state_key *b) > { > int diff; > @@ -814,7 +864,10 @@ pf_insert_state(struct pfi_kif *kif, str > { > struct pf_state_key *cur; > struct pf_state *sp; > - > + struct pf_rdr_dst_node *rdr_dst = NULL; > + struct pf_rdr_dst_node *new_rdr_dst = NULL; > + struct pf_rdr_dst_node rdr_dst_key; > + > KASSERT(s->state_key != NULL); > s->kif = kif; > > @@ -841,6 +894,42 @@ pf_insert_state(struct pfi_kif *kif, str > return (-1); > } > > + /* update redirection destination state counter */ > + if (s->state_key->direction == PF_IN) { > + rdr_dst_key.af = s->state_key->af; > + PF_ACPY(&rdr_dst_key.addr, &s->state_key->lan.addr, s->state_key->af); > + if((rdr_dst = RB_FIND(pf_rdr_dst_tree, &tree_rdr_dst_tracking, &rdr_dst_key)) == NULL) { > + new_rdr_dst = pool_get(&pf_rdr_dst_tree_pl, PR_NOWAIT); > + if (new_rdr_dst == NULL) { > + if (pf_status.debug >= PF_DEBUG_MISC) { > + printf("pf: state insert failed: " > + "allocate element with pool_get failed"); > + /* > + * if (s->sync_flags & PFSTATE_FROMSYNC) > + * printf(" (from sync)"); > + */ > + printf("\n"); > + } > + pf_detach_state(s, 0); > + return (-1); > + } > + bzero(new_rdr_dst, sizeof(*new_rdr_dst)); > + /* add a new entry */ > + new_rdr_dst->addr = s->state_key->lan.addr; > + new_rdr_dst->connections = 1; > + new_rdr_dst->af = s->state_key->af; > + if (RB_INSERT(pf_rdr_dst_tree, &tree_rdr_dst_tracking, new_rdr_dst) != NULL) { > + pf_stateins_err("tree_rdr_dst_tracking", s, kif); > + pf_detach_state(s, 0); > + return (-1); > + } > + } > + else { > + /* update existing entry */ > + rdr_dst->connections++; > + } > + } > + > if (s->id == 0 && s->creatorid == 0) { > s->id = htobe64(pf_status.stateid++); > s->creatorid = pf_status.hostid; > @@ -2098,7 +2187,7 @@ pf_hash(struct pf_addr *inaddr, struct p > } > > int > -pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr, > +pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr, struct pf_addr *daddr, > struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_src_node **sn) > { > unsigned char hash[16]; > @@ -2107,6 +2196,10 @@ pf_map_addr(sa_family_t af, struct pf_ru > struct pf_addr *rmask = &rpool->cur->addr.v.a.mask; > struct pf_pooladdr *acur = rpool->cur; > struct pf_src_node k; > + struct pf_rdr_dst_node *rdr_dst = NULL; > + struct pf_rdr_dst_node *rdr_dst_least = NULL; > + struct pf_rdr_dst_node rdr_dst_key; > + int res = 0; > > if (*sn == NULL && r->rpool.opts & PF_POOL_STICKYADDR && > (r->rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) { > @@ -2140,7 +2233,9 @@ pf_map_addr(sa_family_t af, struct pf_ru > case AF_INET: > if (rpool->cur->addr.p.dyn->pfid_acnt4 < 1 && > (rpool->opts & PF_POOL_TYPEMASK) != > - PF_POOL_ROUNDROBIN) > + PF_POOL_ROUNDROBIN && > + (rpool->opts & PF_POOL_TYPEMASK) != > + PF_POOL_LEASTCONNECTION) > return (1); > raddr = &rpool->cur->addr.p.dyn->pfid_addr4; > rmask = &rpool->cur->addr.p.dyn->pfid_mask4; > @@ -2150,7 +2245,9 @@ pf_map_addr(sa_family_t af, struct pf_ru > case AF_INET6: > if (rpool->cur->addr.p.dyn->pfid_acnt6 < 1 && > (rpool->opts & PF_POOL_TYPEMASK) != > - PF_POOL_ROUNDROBIN) > + PF_POOL_ROUNDROBIN && > + (rpool->opts & PF_POOL_TYPEMASK) != > + PF_POOL_LEASTCONNECTION) > return (1); > raddr = &rpool->cur->addr.p.dyn->pfid_addr6; > rmask = &rpool->cur->addr.p.dyn->pfid_mask6; > @@ -2158,7 +2255,8 @@ pf_map_addr(sa_family_t af, struct pf_ru > #endif /* INET6 */ > } > } else if (rpool->cur->addr.type == PF_ADDR_TABLE) { > - if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN) > + if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN && > + (rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_LEASTCONNECTION) > return (1); /* unsupported */ > } else { > raddr = &rpool->cur->addr.v.a.addr; > @@ -2264,15 +2362,93 @@ pf_map_addr(sa_family_t af, struct pf_ru > PF_ACPY(init_addr, naddr, af); > PF_AINC(&rpool->counter, af); > break; > + case PF_POOL_LEASTCONNECTION: > + if (rpool->cur->addr.type == PF_ADDR_TABLE) { > + if (!pfr_pool_get(rpool->cur->addr.p.tbl, > + &rpool->tblidx, &rpool->counter, > + &raddr, &rmask, af)) > + goto get_addr_lc; > + } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) { > + if (!pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt, > + &rpool->tblidx, &rpool->counter, > + &raddr, &rmask, af)) > + goto get_addr_lc; > + } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af)) > + goto get_addr_lc; > + > + /* > + * least connection: loop once over all addresses and find the > + * one with least connections > + */ > + rdr_dst_least = NULL; > + while(rpool->cur != NULL) { > + res = 0; > + if (rpool->cur->addr.type == PF_ADDR_TABLE) { > + rpool->tblidx = -1; > + res = pfr_pool_get(rpool->cur->addr.p.tbl, > + &rpool->tblidx, &rpool->counter, > + &raddr, &rmask, af); > + } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) { > + rpool->tblidx = -1; > + res = pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt, > + &rpool->tblidx, &rpool->counter, > + &raddr, &rmask, af); > + } else { > + raddr = &rpool->cur->addr.v.a.addr; > + rmask = &rpool->cur->addr.v.a.mask; > + PF_ACPY(&rpool->counter, raddr, af); > + } > + > + if(res == 0) { > + /* find connection count for actual address */ > + rdr_dst_key.af = af; > + PF_ACPY(&rdr_dst_key.addr, &rpool->counter, af); > + if((rdr_dst = RB_FIND(pf_rdr_dst_tree, &tree_rdr_dst_tracking, &rdr_dst_key)) != NULL) { > + if (rdr_dst_least == NULL || rdr_dst->connections < rdr_dst_least->connections) { > + rdr_dst_least = rdr_dst; > + } > + } > + else { > + /* > + * no connections found for destination > + * break while and use this address > + */ > + break; > + } > + /* copy the current least one */ > + PF_ACPY(&rpool->counter, &rdr_dst_least->addr, af); > + } > + > + /* try next element in pool */ > + rpool->cur = TAILQ_NEXT(rpool->cur, entries); > + } > + > + /* finished loop once set to back to first element */ > + if(rpool->cur == NULL) > + rpool->cur = TAILQ_FIRST(&rpool->list); > + > + get_addr_lc: > + PF_ACPY(naddr, &rpool->counter, af); > + if (init_addr != NULL && PF_AZERO(init_addr, af)) > + PF_ACPY(init_addr, naddr, af); > + PF_AINC(&rpool->counter, af); > + break; > } > + > if (*sn != NULL) > PF_ACPY(&(*sn)->raddr, naddr, af); > > - if (pf_status.debug >= PF_DEBUG_MISC && > + if (pf_status.debug >= PF_DEBUG_MISC && > (rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) { > printf("pf_map_addr: selected address "); > pf_print_host(naddr, 0, af); > printf("\n"); > + if((rpool->opts & PF_POOL_TYPEMASK) == PF_POOL_LEASTCONNECTION) { > + if (rdr_dst_least == NULL) > + printf("least-connection count: 0\n"); > + else > + printf("least-connection count: %d\n", rdr_dst_least->connections); > + } > } > > return (0); > @@ -2289,7 +2465,7 @@ pf_get_sport(sa_family_t af, u_int8_t pr > u_int16_t cut; > > bzero(&init_addr, sizeof(init_addr)); > - if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn)) > + if (pf_map_addr(af, r, saddr, daddr, naddr, &init_addr, sn)) > return (1); > > if (proto == IPPROTO_ICMP) { > @@ -2355,7 +2531,8 @@ pf_get_sport(sa_family_t af, u_int8_t pr > switch (r->rpool.opts & PF_POOL_TYPEMASK) { > case PF_POOL_RANDOM: > case PF_POOL_ROUNDROBIN: > - if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn)) > + case PF_POOL_LEASTCONNECTION: > + if (pf_map_addr(af, r, saddr, daddr, naddr, &init_addr, sn)) > return (1); > break; > case PF_POOL_NONE: > @@ -2568,7 +2745,7 @@ pf_get_translation(struct pf_pdesc *pd, > } > break; > case PF_RDR: { > - if (pf_map_addr(pd->af, r, saddr, naddr, NULL, sn)) > + if (pf_map_addr(pd->af, r, saddr, daddr, naddr, NULL, sn)) > return (NULL); > if ((r->rpool.opts & PF_POOL_TYPEMASK) == > PF_POOL_BITMASK) > @@ -2807,7 +2984,7 @@ pf_calc_mss(struct pf_addr *addr, sa_fam > } > > void > -pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr) > +pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr, struct pf_addr *daddr) > { > struct pf_rule *r = s->rule.ptr; > > @@ -2817,14 +2994,14 @@ pf_set_rt_ifp(struct pf_state *s, struct > switch (s->state_key->af) { > #ifdef INET > case AF_INET: > - pf_map_addr(AF_INET, r, saddr, &s->rt_addr, NULL, > + pf_map_addr(AF_INET, r, saddr, daddr, &s->rt_addr, NULL, > &s->nat_src_node); > s->rt_kif = r->rpool.cur->kif; > break; > #endif /* INET */ > #ifdef INET6 > case AF_INET6: > - pf_map_addr(AF_INET6, r, saddr, &s->rt_addr, NULL, > + pf_map_addr(AF_INET6, r, saddr, daddr, &s->rt_addr, NULL, > &s->nat_src_node); > s->rt_kif = r->rpool.cur->kif; > break; > @@ -2849,10 +3026,25 @@ void > pf_detach_state(struct pf_state *s, int flags) > { > struct pf_state_key *sk = s->state_key; > + struct pf_rdr_dst_node *rdr_dst = NULL; > + struct pf_rdr_dst_node rdr_dst_key; > > if (sk == NULL) > return; > > + /* update redirection destinations state counter */ > + if (sk->direction == PF_IN) { > + rdr_dst_key.af = sk->af; > + PF_ACPY(&rdr_dst_key.addr, &sk->lan.addr, sk->af); > + if((rdr_dst = RB_FIND(pf_rdr_dst_tree, &tree_rdr_dst_tracking, &rdr_dst_key)) != NULL) { > + rdr_dst->connections--; > + if(rdr_dst->connections == 0) { > + RB_REMOVE(pf_rdr_dst_tree, &tree_rdr_dst_tracking, rdr_dst); > + pool_put(&pf_rdr_dst_tree_pl, rdr_dst); > + } > + } > + } > + > s->state_key = NULL; > TAILQ_REMOVE(&sk->states, s, next); > if (--sk->refcnt == 0) { > @@ -3524,7 +3716,7 @@ cleanup: > } > } > > - pf_set_rt_ifp(s, saddr); /* needs s->state_key set */ > + pf_set_rt_ifp(s, saddr, daddr); /* needs s->state_key set */ > > if (pf_insert_state(BOUND_IFACE(r, kif), s)) { > if (pd->proto == IPPROTO_TCP) > @@ -5123,7 +5315,7 @@ pf_route(struct mbuf **m, struct pf_rule > } > if (s == NULL) { > pf_map_addr(AF_INET, r, (struct pf_addr *)&ip->ip_src, > - &naddr, NULL, &sn); > + (struct pf_addr *)&ip->ip_dst, &naddr, NULL, &sn); > if (!PF_AZERO(&naddr, AF_INET)) > dst->sin_addr.s_addr = naddr.v4.s_addr; > ifp = r->rpool.cur->kif ? > @@ -5307,7 +5499,7 @@ pf_route6(struct mbuf **m, struct pf_rul > } > if (s == NULL) { > pf_map_addr(AF_INET6, r, (struct pf_addr *)&ip6->ip6_src, > - &naddr, NULL, &sn); > + (struct pf_addr *)&ip6->ip6_dst, &naddr, NULL, &sn); > if (!PF_AZERO(&naddr, AF_INET6)) > PF_ACPY((struct pf_addr *)&dst->sin6_addr, > &naddr, AF_INET6); > Index: pf_ioctl.c > ================================================== ================= > RCS file: /cvs/src/sys/net/pf_ioctl.c,v > retrieving revision 1.193 > diff -u -p -r1.193 pf_ioctl.c > --- pf_ioctl.c 2 Dec 2007 12:08:04 -0000 1.193 > +++ pf_ioctl.c 19 Apr 2008 19:41:14 -0000 > @@ -145,6 +145,8 @@ pfattach(int num) > &pool_allocator_nointr); > pool_init(&pf_src_tree_pl, sizeof(struct pf_src_node), 0, 0, 0, > "pfsrctrpl", NULL); > + pool_init(&pf_rdr_dst_tree_pl, sizeof(struct pf_rdr_dst_node), 0, 0, 0, > + "pfrdrdsttrpl", NULL); > pool_init(&pf_state_pl, sizeof(struct pf_state), 0, 0, 0, "pfstatepl", > NULL); > pool_init(&pf_state_key_pl, sizeof(struct pf_state_key), 0, 0, 0, > Index: pfvar.h > ================================================== ================= > RCS file: /cvs/src/sys/net/pfvar.h,v > retrieving revision 1.259 > diff -u -p -r1.259 pfvar.h > --- pfvar.h 2 Dec 2007 12:08:04 -0000 1.259 > +++ pfvar.h 19 Apr 2008 19:41:15 -0000 > @@ -105,11 +105,11 @@ enum { PFTM_TCP_FIRST_PACKET, PFTM_TCP_O > #define PFTM_TS_DIFF_VAL 30 /* Allowed TS diff */ > > enum { PF_NOPFROUTE, PF_FASTROUTE, PF_ROUTETO, PF_DUPTO, PF_REPLYTO }; > -enum { PF_LIMIT_STATES, PF_LIMIT_SRC_NODES, PF_LIMIT_FRAGS, > +enum { PF_LIMIT_STATES, PF_LIMIT_SRC_NODES, PF_LIMIT_RDR_DST_NODES, PF_LIMIT_FRAGS, > PF_LIMIT_TABLES, PF_LIMIT_TABLE_ENTRIES, PF_LIMIT_MAX }; > #define PF_POOL_IDMASK 0x0f > enum { PF_POOL_NONE, PF_POOL_BITMASK, PF_POOL_RANDOM, > - PF_POOL_SRCHASH, PF_POOL_ROUNDROBIN }; > + PF_POOL_SRCHASH, PF_POOL_ROUNDROBIN, PF_POOL_LEASTCONNECTION}; > enum { PF_ADDR_ADDRMASK, PF_ADDR_NOROUTE, PF_ADDR_DYNIFTL, > PF_ADDR_TABLE, PF_ADDR_RTLABEL, PF_ADDR_URPFFAILED, > PF_ADDR_RANGE }; > @@ -651,6 +651,15 @@ struct pf_src_node { > > #define PFSNODE_HIWAT 10000 /* default source node table size */ > > +struct pf_rdr_dst_node { > + RB_ENTRY(pf_rdr_dst_node) entry; > + struct pf_addr addr; > + u_int32_t connections; > + sa_family_t af; > +}; > + > +#define PFRDNODE_HIWAT 10000 /* default rdr dest node table size */ > + > struct pf_state_scrub { > struct timeval pfss_last; /* time received last packet */ > u_int32_t pfss_tsecr; /* last echoed timestamp */ > @@ -1536,6 +1545,10 @@ RB_HEAD(pf_src_tree, pf_src_node); > RB_PROTOTYPE(pf_src_tree, pf_src_node, entry, pf_src_compare); > extern struct pf_src_tree tree_src_tracking; > > +RB_HEAD(pf_rdr_dst_tree, pf_rdr_dst_node); > +RB_PROTOTYPE(pf_rdr_dst_tree, pf_rdr_dst_node, entry, pf_rdr_dst_compare); > +extern struct pf_rdr_dst_tree tree_rdr_dst_tracking; > + > RB_HEAD(pf_state_tree_id, pf_state); > RB_PROTOTYPE(pf_state_tree_id, pf_state, > entry_id, pf_state_compare_id); > @@ -1561,7 +1574,7 @@ extern int pf_tbladdr_setup(struct pf > extern void pf_tbladdr_remove(struct pf_addr_wrap *); > extern void pf_tbladdr_copyout(struct pf_addr_wrap *); > extern void pf_calc_skip_steps(struct pf_rulequeue *); > -extern struct pool pf_src_tree_pl, pf_rule_pl; > +extern struct pool pf_src_tree_pl, pf_rdr_dst_tree_pl, pf_rule_pl; > extern struct pool pf_state_pl, pf_state_key_pl, pf_altq_pl, > pf_pooladdr_pl; > extern struct pool pf_state_scrub_pl; |
| Thread Tools | |
| Display Modes | |
| |