6859313 large number of rules in ipfilter decreases throughput performance
authorAlexandr Nedvedicky <Alexandr.Nedvedicky@Sun.COM>
Mon, 21 Sep 2009 11:09:02 +0200
changeset 10587 e0d280fab007
parent 10586 252cfb0aebde
child 10588 dc03f981ea18
6859313 large number of rules in ipfilter decreases throughput performance
usr/src/uts/common/inet/ipf/fil.c
usr/src/uts/common/inet/ipf/ip_fil_solaris.c
usr/src/uts/common/inet/ipf/netinet/ipf_stack.h
usr/src/uts/common/inet/ipf/solaris.c
--- a/usr/src/uts/common/inet/ipf/fil.c	Sun Sep 20 07:48:31 2009 -0700
+++ b/usr/src/uts/common/inet/ipf/fil.c	Mon Sep 21 11:09:02 2009 +0200
@@ -2151,6 +2151,7 @@
 u_32_t *passp;
 {
 	frentry_t *fr;
+	fr_info_t *fc;
 	u_32_t pass;
 	int out;
 	ipf_stack_t *ifs = fin->fin_ifs;
@@ -2164,13 +2165,51 @@
 	else
 #endif
 		fin->fin_fr = ifs->ifs_ipfilter[out][ifs->ifs_fr_active];
-	if (fin->fin_fr != NULL)
+
+	/*
+	 * If there are no rules loaded skip all checks and return.
+	 */
+	if (fin->fin_fr == NULL) {
+
+		if ((pass & FR_NOMATCH)) {
+			IPF_BUMP(ifs->ifs_frstats[out].fr_nom);
+		}
+
+		return (NULL);
+	}
+
+	fc = &ifs->ifs_frcache[out][CACHE_HASH(fin)];
+	READ_ENTER(&ifs->ifs_ipf_frcache);
+	if (!bcmp((char *)fin, (char *)fc, FI_CSIZE)) {
+		/*
+		 * copy cached data so we can unlock the mutexes earlier.
+		 */
+		bcopy((char *)fc, (char *)fin, FI_COPYSIZE);
+		RWLOCK_EXIT(&ifs->ifs_ipf_frcache);
+		IPF_BUMP(ifs->ifs_frstats[out].fr_chit);
+
+		if ((fr = fin->fin_fr) != NULL) {
+			IPF_BUMP(fr->fr_hits);
+			pass = fr->fr_flags;
+		}
+	} else {
+		RWLOCK_EXIT(&ifs->ifs_ipf_frcache);
+
 		pass = fr_scanlist(fin, ifs->ifs_fr_pass);
 
+		if (((pass & FR_KEEPSTATE) == 0) &&
+		    ((fin->fin_flx & FI_DONTCACHE) == 0)) {
+			WRITE_ENTER(&ifs->ifs_ipf_frcache);
+			bcopy((char *)fin, (char *)fc, FI_COPYSIZE);
+			RWLOCK_EXIT(&ifs->ifs_ipf_frcache);
+		}
+
+		fr = fin->fin_fr;
+	}
+
 	if ((pass & FR_NOMATCH)) {
 		IPF_BUMP(ifs->ifs_frstats[out].fr_nom);
 	}
-	fr = fin->fin_fr;
 
 	/*
 	 * Apply packets per second rate-limiting to a rule as required.
@@ -3520,6 +3559,7 @@
 	int flushed = 0, set;
 
 	WRITE_ENTER(&ifs->ifs_ipf_mutex);
+	bzero((char *)ifs->ifs_frcache, sizeof (ifs->ifs_frcache));
 
 	set = ifs->ifs_fr_active;
 	if ((flags & FR_INACTIVE) == FR_INACTIVE)
@@ -4504,6 +4544,7 @@
 		fp->fr_cksum += *p;
 
 	WRITE_ENTER(&ifs->ifs_ipf_mutex);
+	bzero((char *)ifs->ifs_frcache, sizeof (ifs->ifs_frcache));
 
 	for (; (f = *ftail) != NULL; ftail = &f->fr_next) {
 		if ((fp->fr_cksum != f->fr_cksum) ||
--- a/usr/src/uts/common/inet/ipf/ip_fil_solaris.c	Sun Sep 20 07:48:31 2009 -0700
+++ b/usr/src/uts/common/inet/ipf/ip_fil_solaris.c	Mon Sep 21 11:09:02 2009 +0200
@@ -260,6 +260,7 @@
 	ifs->ifs_fr_pass = (IPF_DEFAULT_PASS)|FR_NOMATCH;
 #endif
 
+	bzero((char *)ifs->ifs_frcache, sizeof(ifs->ifs_frcache));
 	MUTEX_INIT(&ifs->ifs_ipf_rw, "ipf rw mutex");
 	MUTEX_INIT(&ifs->ifs_ipf_timeoutlock, "ipf timeout lock mutex");
 	RWLOCK_INIT(&ifs->ifs_ipf_ipidfrag, "ipf IP NAT-Frag rwlock");
@@ -643,6 +644,8 @@
 			error = EPERM;
 		else {
 			WRITE_ENTER(&ifs->ifs_ipf_mutex);
+			bzero((char *)ifs->ifs_frcache,
+			    sizeof (ifs->ifs_frcache));
 			error = COPYOUT((caddr_t)&ifs->ifs_fr_active,
 					(caddr_t)data,
 					sizeof(ifs->ifs_fr_active));
--- a/usr/src/uts/common/inet/ipf/netinet/ipf_stack.h	Sun Sep 20 07:48:31 2009 -0700
+++ b/usr/src/uts/common/inet/ipf/netinet/ipf_stack.h	Mon Sep 21 11:09:02 2009 +0200
@@ -45,6 +45,7 @@
 	zoneid_t		ifs_zone;
 
 	/* ipf module */
+	fr_info_t		ifs_frcache[2][8];
 
 	filterstats_t		ifs_frstats[2];
 	frentry_t		*ifs_ipfilter[2][2];
@@ -91,6 +92,7 @@
 	ipfmutex_t	ifs_ipf_timeoutlock;
 	ipfrwlock_t	ifs_ipf_mutex;
 	ipfrwlock_t	ifs_ipf_global;
+	ipfrwlock_t	ifs_ipf_frcache;
 	ipfrwlock_t	ifs_ip_poolrw;
 	ipfrwlock_t	ifs_ipf_frag;
 	ipfrwlock_t	ifs_ipf_state;
--- a/usr/src/uts/common/inet/ipf/solaris.c	Sun Sep 20 07:48:31 2009 -0700
+++ b/usr/src/uts/common/inet/ipf/solaris.c	Mon Sep 21 11:09:02 2009 +0200
@@ -3,7 +3,7 @@
  *
  * See the IPFILTER.LICENCE file for details on licencing.
  *
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -396,7 +396,7 @@
 	 */
 	RWLOCK_INIT(&ifs->ifs_ipf_global, "ipf filter load/unload mutex");
 	RWLOCK_INIT(&ifs->ifs_ipf_mutex, "ipf filter rwlock");
-
+	RWLOCK_INIT(&ifs->ifs_ipf_frcache, "ipf cache rwlock");
 	ifs->ifs_netid = id;
 	ifs->ifs_zone = net_getzoneidbynetid(id);
 	ipf_kstat_init(ifs);
@@ -553,6 +553,7 @@
 
 	RWLOCK_EXIT(&ifs->ifs_ipf_global);
 	RW_DESTROY(&ifs->ifs_ipf_mutex);
+	RW_DESTROY(&ifs->ifs_ipf_frcache);
 	RW_DESTROY(&ifs->ifs_ipf_global);
 
 	KFREE(ifs);