summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorAlexandr Nedvedicky <Alexandr.Nedvedicky@Sun.COM>2009-09-21 11:09:02 +0200
committerAlexandr Nedvedicky <Alexandr.Nedvedicky@Sun.COM>2009-09-21 11:09:02 +0200
commit14d3298ea5ac04e3c29e86a4769ff92a49e9f4af (patch)
treecb14b8f94b1fe79ac1e9272959045176c519e271 /usr/src
parent92e8aa2f28291f13555b38cb0adf7e84b2b83cae (diff)
downloadillumos-gate-14d3298ea5ac04e3c29e86a4769ff92a49e9f4af.tar.gz
6859313 large number of rules in ipfilter decreases throughput performance
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/inet/ipf/fil.c45
-rw-r--r--usr/src/uts/common/inet/ipf/ip_fil_solaris.c3
-rw-r--r--usr/src/uts/common/inet/ipf/netinet/ipf_stack.h2
-rw-r--r--usr/src/uts/common/inet/ipf/solaris.c5
4 files changed, 51 insertions, 4 deletions
diff --git a/usr/src/uts/common/inet/ipf/fil.c b/usr/src/uts/common/inet/ipf/fil.c
index 360516b692..9cb19345b6 100644
--- a/usr/src/uts/common/inet/ipf/fil.c
+++ b/usr/src/uts/common/inet/ipf/fil.c
@@ -2151,6 +2151,7 @@ fr_info_t *fin;
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 @@ u_32_t *passp;
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 @@ ipf_stack_t *ifs;
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 @@ ipf_stack_t *ifs;
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) ||
diff --git a/usr/src/uts/common/inet/ipf/ip_fil_solaris.c b/usr/src/uts/common/inet/ipf/ip_fil_solaris.c
index 15a189239a..912efb0826 100644
--- a/usr/src/uts/common/inet/ipf/ip_fil_solaris.c
+++ b/usr/src/uts/common/inet/ipf/ip_fil_solaris.c
@@ -260,6 +260,7 @@ ipf_stack_t *ifs;
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 @@ int *rp;
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));
diff --git a/usr/src/uts/common/inet/ipf/netinet/ipf_stack.h b/usr/src/uts/common/inet/ipf/netinet/ipf_stack.h
index 35b646c301..75703994a5 100644
--- a/usr/src/uts/common/inet/ipf/netinet/ipf_stack.h
+++ b/usr/src/uts/common/inet/ipf/netinet/ipf_stack.h
@@ -45,6 +45,7 @@ struct ipf_stack {
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 @@ struct ipf_stack {
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;
diff --git a/usr/src/uts/common/inet/ipf/solaris.c b/usr/src/uts/common/inet/ipf/solaris.c
index f6a39aeb60..1a1d94def5 100644
--- a/usr/src/uts/common/inet/ipf/solaris.c
+++ b/usr/src/uts/common/inet/ipf/solaris.c
@@ -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 @@ ipf_stack_create(const netid_t id)
*/
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 @@ ipf_stack_destroy(const netid_t id, void *arg)
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);