svn commit: r236397 - projects/pf/head/sys/contrib/pf/net

Gleb Smirnoff glebius at FreeBSD.org
Fri Jun 1 13:37:19 UTC 2012


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 *);


More information about the svn-src-projects mailing list