From owner-svn-src-projects@FreeBSD.ORG Fri Jun 1 13:37:19 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D75D5106566B; Fri, 1 Jun 2012 13:37:19 +0000 (UTC) (envelope-from glebius@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id C10658FC18; Fri, 1 Jun 2012 13:37:19 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q51DbJnP022081; Fri, 1 Jun 2012 13:37:19 GMT (envelope-from glebius@svn.freebsd.org) Received: (from glebius@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q51DbJ1b022076; Fri, 1 Jun 2012 13:37:19 GMT (envelope-from glebius@svn.freebsd.org) Message-Id: <201206011337.q51DbJ1b022076@svn.freebsd.org> From: Gleb Smirnoff Date: Fri, 1 Jun 2012 13:37:19 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r236397 - projects/pf/head/sys/contrib/pf/net X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 01 Jun 2012 13:37:19 -0000 Author: glebius Date: Fri Jun 1 13:37:19 2012 New Revision: 236397 URL: http://svn.freebsd.org/changeset/base/236397 Log: Make pf table code more re-entrant: - kill global V_pfr_sin, V_pfr_sin6, V_pfr_mask which are used in some functions and use instead structure on stack. - pfr_ffaddr can be initialized statically and doesn't need V Make pfr_pool_get() more smp-safe (not yet really safe, but better): - Don't pass raddr and rmask from pf_map_addr() to pfr_pool_get(), and thus do not modify pools cur. - Use on stack sockaddr_union instead of global. Modified: projects/pf/head/sys/contrib/pf/net/pf_ioctl.c projects/pf/head/sys/contrib/pf/net/pf_lb.c projects/pf/head/sys/contrib/pf/net/pf_table.c projects/pf/head/sys/contrib/pf/net/pfvar.h Modified: projects/pf/head/sys/contrib/pf/net/pf_ioctl.c ============================================================================== --- projects/pf/head/sys/contrib/pf/net/pf_ioctl.c Fri Jun 1 13:21:32 2012 (r236396) +++ projects/pf/head/sys/contrib/pf/net/pf_ioctl.c Fri Jun 1 13:37:19 2012 (r236397) @@ -252,7 +252,6 @@ pfattach(void) int error; pf_initialize(); - pfr_initialize(); pfi_initialize(); pf_osfp_initialize(); pf_normalize_init(); Modified: projects/pf/head/sys/contrib/pf/net/pf_lb.c ============================================================================== --- projects/pf/head/sys/contrib/pf/net/pf_lb.c Fri Jun 1 13:21:32 2012 (r236396) +++ projects/pf/head/sys/contrib/pf/net/pf_lb.c Fri Jun 1 13:37:19 2012 (r236397) @@ -458,13 +458,11 @@ pf_map_addr(sa_family_t af, struct pf_ru case PF_POOL_ROUNDROBIN: if (rpool->cur->addr.type == PF_ADDR_TABLE) { if (!pfr_pool_get(rpool->cur->addr.p.tbl, - &rpool->tblidx, &rpool->counter, - &raddr, &rmask, af)) + &rpool->tblidx, &rpool->counter, af)) goto get_addr; } 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)) + &rpool->tblidx, &rpool->counter, af)) goto get_addr; } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af)) goto get_addr; @@ -475,8 +473,7 @@ pf_map_addr(sa_family_t af, struct pf_ru if (rpool->cur->addr.type == PF_ADDR_TABLE) { rpool->tblidx = -1; if (pfr_pool_get(rpool->cur->addr.p.tbl, - &rpool->tblidx, &rpool->counter, - &raddr, &rmask, af)) { + &rpool->tblidx, &rpool->counter, af)) { /* table contains no address of type 'af' */ if (rpool->cur != acur) goto try_next; @@ -485,8 +482,7 @@ pf_map_addr(sa_family_t af, struct pf_ru } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) { rpool->tblidx = -1; if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt, - &rpool->tblidx, &rpool->counter, - &raddr, &rmask, af)) { + &rpool->tblidx, &rpool->counter, af)) { /* table contains no address of type 'af' */ if (rpool->cur != acur) goto try_next; Modified: projects/pf/head/sys/contrib/pf/net/pf_table.c ============================================================================== --- projects/pf/head/sys/contrib/pf/net/pf_table.c Fri Jun 1 13:21:32 2012 (r236396) +++ projects/pf/head/sys/contrib/pf/net/pf_table.c Fri Jun 1 13:37:19 2012 (r236397) @@ -122,14 +122,10 @@ VNET_DEFINE(uma_zone_t, pfr_ktable_z); VNET_DEFINE(uma_zone_t, pfr_kentry_z); VNET_DEFINE(uma_zone_t, pfr_kcounters_z); #define V_pfr_kcounters_z VNET(pfr_kcounters_z) -VNET_DEFINE(struct sockaddr_in, pfr_sin); -#define V_pfr_sin VNET(pfr_sin) -VNET_DEFINE(struct sockaddr_in6, pfr_sin6); -#define V_pfr_sin6 VNET(pfr_sin6) -VNET_DEFINE(union sockaddr_union, pfr_mask); -#define V_pfr_mask VNET(pfr_mask) -VNET_DEFINE(struct pf_addr, pfr_ffaddr); -#define V_pfr_ffaddr VNET(pfr_ffaddr) + +static struct pf_addr pfr_ffaddr = { + .addr32 = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } +}; static void pfr_copyout_addr(struct pfr_addr *, struct pfr_kentry *ke); @@ -189,17 +185,6 @@ struct pfr_ktablehead pfr_ktables; struct pfr_table pfr_nulltable; int pfr_ktable_cnt; -void -pfr_initialize(void) -{ - V_pfr_sin.sin_len = sizeof(V_pfr_sin); - V_pfr_sin.sin_family = AF_INET; - V_pfr_sin6.sin6_len = sizeof(V_pfr_sin6); - V_pfr_sin6.sin6_family = AF_INET6; - - memset(&V_pfr_ffaddr, 0xff, sizeof(V_pfr_ffaddr)); -} - int pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags) { @@ -1029,24 +1014,28 @@ pfr_walktree(struct radix_node *rn, void } break; case PFRW_DYNADDR_UPDATE: + { + union sockaddr_union pfr_mask; + if (ke->pfrke_af == AF_INET) { if (w->pfrw_dyn->pfid_acnt4++ > 0) break; - pfr_prepare_network(&V_pfr_mask, AF_INET, ke->pfrke_net); - w->pfrw_dyn->pfid_addr4 = *SUNION2PF( - &ke->pfrke_sa, AF_INET); - w->pfrw_dyn->pfid_mask4 = *SUNION2PF( - &V_pfr_mask, AF_INET); + pfr_prepare_network(&pfr_mask, AF_INET, ke->pfrke_net); + w->pfrw_dyn->pfid_addr4 = *SUNION2PF(&ke->pfrke_sa, + AF_INET); + w->pfrw_dyn->pfid_mask4 = *SUNION2PF(&pfr_mask, + AF_INET); } else if (ke->pfrke_af == AF_INET6){ if (w->pfrw_dyn->pfid_acnt6++ > 0) break; - pfr_prepare_network(&V_pfr_mask, AF_INET6, ke->pfrke_net); - w->pfrw_dyn->pfid_addr6 = *SUNION2PF( - &ke->pfrke_sa, AF_INET6); - w->pfrw_dyn->pfid_mask6 = *SUNION2PF( - &V_pfr_mask, AF_INET6); + pfr_prepare_network(&pfr_mask, AF_INET6, ke->pfrke_net); + w->pfrw_dyn->pfid_addr6 = *SUNION2PF(&ke->pfrke_sa, + AF_INET6); + w->pfrw_dyn->pfid_mask6 = *SUNION2PF(&pfr_mask, + AF_INET6); } break; + } } return (0); } @@ -1886,19 +1875,31 @@ pfr_match_addr(struct pfr_ktable *kt, st switch (af) { #ifdef INET case AF_INET: - V_pfr_sin.sin_addr.s_addr = a->addr32[0]; - ke = (struct pfr_kentry *)rn_match(&V_pfr_sin, kt->pfrkt_ip4); + { + struct sockaddr_in sin; + + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = a->addr32[0]; + ke = (struct pfr_kentry *)rn_match(&sin, kt->pfrkt_ip4); if (ke && KENTRY_RNF_ROOT(ke)) ke = NULL; break; + } #endif /* INET */ #ifdef INET6 case AF_INET6: - bcopy(a, &V_pfr_sin6.sin6_addr, sizeof(V_pfr_sin6.sin6_addr)); - ke = (struct pfr_kentry *)rn_match(&V_pfr_sin6, kt->pfrkt_ip6); + { + struct sockaddr_in6 sin6; + + sin6.sin6_len = sizeof(sin6); + sin6.sin6_family = AF_INET6; + bcopy(a, &sin6.sin6_addr, sizeof(sin6.sin6_addr)); + ke = (struct pfr_kentry *)rn_match(&sin6, kt->pfrkt_ip6); if (ke && KENTRY_RNF_ROOT(ke)) ke = NULL; break; + } #endif /* INET6 */ } match = (ke && !ke->pfrke_not); @@ -1923,19 +1924,31 @@ pfr_update_stats(struct pfr_ktable *kt, switch (af) { #ifdef INET case AF_INET: - V_pfr_sin.sin_addr.s_addr = a->addr32[0]; - ke = (struct pfr_kentry *)rn_match(&V_pfr_sin, kt->pfrkt_ip4); + { + struct sockaddr_in sin; + + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = a->addr32[0]; + ke = (struct pfr_kentry *)rn_match(&sin, kt->pfrkt_ip4); if (ke && KENTRY_RNF_ROOT(ke)) ke = NULL; break; + } #endif /* INET */ #ifdef INET6 case AF_INET6: - bcopy(a, &V_pfr_sin6.sin6_addr, sizeof(V_pfr_sin6.sin6_addr)); - ke = (struct pfr_kentry *)rn_match(&V_pfr_sin6, kt->pfrkt_ip6); + { + struct sockaddr_in6 sin6; + + sin6.sin6_len = sizeof(sin6); + sin6.sin6_family = AF_INET6; + bcopy(a, &sin6.sin6_addr, sizeof(sin6.sin6_addr)); + ke = (struct pfr_kentry *)rn_match(&sin6, kt->pfrkt_ip6); if (ke && KENTRY_RNF_ROOT(ke)) ke = NULL; break; + } #endif /* INET6 */ default: ; @@ -2011,17 +2024,25 @@ 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, sa_family_t af) + sa_family_t af) { + struct pf_addr *addr, *cur, *mask; + union sockaddr_union uaddr, umask; struct pfr_kentry *ke, *ke2 = NULL; - struct pf_addr *addr = NULL; - union sockaddr_union mask; int idx = -1, use_counter = 0; - if (af == AF_INET) - addr = (struct pf_addr *)&V_pfr_sin.sin_addr; - else if (af == AF_INET6) - addr = (struct pf_addr *)&V_pfr_sin6.sin6_addr; + switch (af) { + case AF_INET: + uaddr.sin.sin_len = sizeof(struct sockaddr_in); + uaddr.sin.sin_family = AF_INET; + break; + case AF_INET6: + uaddr.sin6.sin6_len = sizeof(struct sockaddr_in6); + uaddr.sin6.sin6_family = AF_INET6; + break; + } + addr = SUNION2PF(&uaddr, af); + if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL) kt = kt->pfrkt_root; if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) @@ -2040,13 +2061,13 @@ _next_block: kt->pfrkt_nomatch++; return (1); } - pfr_prepare_network(&V_pfr_mask, af, ke->pfrke_net); - *raddr = SUNION2PF(&ke->pfrke_sa, af); - *rmask = SUNION2PF(&V_pfr_mask, af); + pfr_prepare_network(&umask, af, ke->pfrke_net); + cur = SUNION2PF(&ke->pfrke_sa, af); + mask = SUNION2PF(&umask, af); if (use_counter) { /* is supplied address within block? */ - if (!PF_MATCHA(0, *raddr, *rmask, counter, af)) { + if (!PF_MATCHA(0, cur, mask, counter, af)) { /* no, go to next block in table */ idx++; use_counter = 0; @@ -2055,7 +2076,7 @@ _next_block: PF_ACPY(addr, counter, af); } else { /* use first address of block */ - PF_ACPY(addr, *raddr, af); + PF_ACPY(addr, cur, af); } if (!KENTRY_NETWORK(ke)) { @@ -2067,12 +2088,16 @@ _next_block: } for (;;) { /* we don't want to use a nested block */ - if (af == AF_INET) - ke2 = (struct pfr_kentry *)rn_match(&V_pfr_sin, + switch (af) { + case AF_INET: + ke2 = (struct pfr_kentry *)rn_match(&uaddr, kt->pfrkt_ip4); - else if (af == AF_INET6) - ke2 = (struct pfr_kentry *)rn_match(&V_pfr_sin6, + break; + case AF_INET6: + ke2 = (struct pfr_kentry *)rn_match(&uaddr, kt->pfrkt_ip6); + break; + } /* no need to check KENTRY_RNF_ROOT() here */ if (ke2 == ke) { /* lookup return the same block - perfect */ @@ -2083,10 +2108,10 @@ _next_block: } /* we need to increase the counter past the nested block */ - pfr_prepare_network(&mask, AF_INET, ke2->pfrke_net); - PF_POOLMASK(addr, addr, SUNION2PF(&mask, af), &V_pfr_ffaddr, af); + pfr_prepare_network(&umask, AF_INET, ke2->pfrke_net); + PF_POOLMASK(addr, addr, SUNION2PF(&umask, af), &pfr_ffaddr, af); PF_AINC(addr, af); - if (!PF_MATCHA(0, *raddr, *rmask, addr, af)) { + if (!PF_MATCHA(0, cur, mask, addr, af)) { /* ok, we reached the end of our main block */ /* go to next block in table */ idx++; Modified: projects/pf/head/sys/contrib/pf/net/pfvar.h ============================================================================== --- projects/pf/head/sys/contrib/pf/net/pfvar.h Fri Jun 1 13:21:32 2012 (r236396) +++ projects/pf/head/sys/contrib/pf/net/pfvar.h Fri Jun 1 13:37:19 2012 (r236397) @@ -1868,12 +1868,10 @@ int pf_routable(struct pf_addr *addr, sa int); int pf_socket_lookup(int, struct pf_pdesc *); struct pf_state_key *pf_alloc_state_key(int); -void pfr_initialize(void); int pfr_match_addr(struct pfr_ktable *, struct pf_addr *, sa_family_t); void pfr_update_stats(struct pfr_ktable *, struct pf_addr *, sa_family_t, u_int64_t, int, int, int); -int pfr_pool_get(struct pfr_ktable *, int *, struct pf_addr *, - struct pf_addr **, struct pf_addr **, sa_family_t); +int pfr_pool_get(struct pfr_ktable *, int *, struct pf_addr *, sa_family_t); void pfr_dynaddr_update(struct pfr_ktable *, struct pfi_dynaddr *); struct pfr_ktable * pfr_attach_table(struct pf_ruleset *, char *);