Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src NPF checkpoint:



details:   https://anonhg.NetBSD.org/src/rev/ed5de796875c
branches:  trunk
changeset: 759848:ed5de796875c
user:      rmind <rmind%NetBSD.org@localhost>
date:      Sat Dec 18 01:07:25 2010 +0000

description:
NPF checkpoint:
- Add support for session saving/restoring.
- Add packet logging support (can tcpdump a pseudo-interface).
- Support reload without flushing of sessions; rework some locking.
- Revisit session mangement, replace linking with npf_sentry_t entries.
- Add some counters for statistics, using percpu(9).
- Add IP_DF flag cleansing.
- Fix various bugs; misc clean-up.

diffstat:

 sys/modules/npf/Makefile         |    3 +-
 sys/net/npf/files.npf            |    3 +-
 sys/net/npf/npf.c                |  219 ++++++++-
 sys/net/npf/npf.h                |   37 +-
 sys/net/npf/npf_alg_icmp.c       |    8 +-
 sys/net/npf/npf_ctl.c            |  253 +++++-----
 sys/net/npf/npf_handler.c        |   33 +-
 sys/net/npf/npf_impl.h           |   78 ++-
 sys/net/npf/npf_inet.c           |   30 +-
 sys/net/npf/npf_log.c            |  175 +++++++
 sys/net/npf/npf_nat.c            |  408 ++++++++++++-----
 sys/net/npf/npf_ncode.h          |   19 +-
 sys/net/npf/npf_processor.c      |   16 +-
 sys/net/npf/npf_ruleset.c        |  367 +++++++++------
 sys/net/npf/npf_session.c        |  887 ++++++++++++++++++++++++--------------
 sys/net/npf/npf_state.c          |   44 +-
 sys/net/npf/npf_tableset.c       |   71 +--
 usr.sbin/npf/npfctl/npf_data.c   |   83 ++-
 usr.sbin/npf/npfctl/npf_ncgen.c  |   19 +-
 usr.sbin/npf/npfctl/npf_parser.c |   38 +-
 usr.sbin/npf/npfctl/npfctl.c     |   91 +++-
 usr.sbin/npf/npfctl/npfctl.h     |    7 +-
 22 files changed, 1943 insertions(+), 946 deletions(-)

diffs (truncated from 4772 to 300 lines):

diff -r e32309caf39d -r ed5de796875c sys/modules/npf/Makefile
--- a/sys/modules/npf/Makefile  Sat Dec 18 00:01:46 2010 +0000
+++ b/sys/modules/npf/Makefile  Sat Dec 18 01:07:25 2010 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.3 2010/11/11 06:30:39 rmind Exp $
+# $NetBSD: Makefile,v 1.4 2010/12/18 01:07:26 rmind Exp $
 
 .include "../Makefile.inc"
 
@@ -9,5 +9,6 @@
 SRCS=          npf.c npf_ctl.c npf_handler.c npf_instr.c npf_mbuf.c
 SRCS+=         npf_processor.c npf_ruleset.c npf_tableset.c npf_inet.c
 SRCS+=         npf_session.c npf_state.c npf_nat.c npf_alg.c npf_sendpkt.c
+SRCS+=         npf_log.c
 
 .include <bsd.kmodule.mk>
diff -r e32309caf39d -r ed5de796875c sys/net/npf/files.npf
--- a/sys/net/npf/files.npf     Sat Dec 18 00:01:46 2010 +0000
+++ b/sys/net/npf/files.npf     Sat Dec 18 01:07:25 2010 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: files.npf,v 1.3 2010/11/11 06:30:39 rmind Exp $
+# $NetBSD: files.npf,v 1.4 2010/12/18 01:07:25 rmind Exp $
 #
 # Public Domain.
 #
@@ -24,6 +24,7 @@
 file   net/npf/npf_nat.c                       npf
 file   net/npf/npf_alg.c                       npf
 file   net/npf/npf_sendpkt.c                   npf
+file   net/npf/npf_log.c                       npf
 
 # ALGs
 file   net/npf/npf_alg_icmp.c                  npf
diff -r e32309caf39d -r ed5de796875c sys/net/npf/npf.c
--- a/sys/net/npf/npf.c Sat Dec 18 00:01:46 2010 +0000
+++ b/sys/net/npf/npf.c Sat Dec 18 01:07:25 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf.c,v 1.1 2010/08/22 18:56:22 rmind Exp $    */
+/*     $NetBSD: npf.c,v 1.2 2010/12/18 01:07:25 rmind Exp $    */
 
 /*-
  * Copyright (c) 2009-2010 The NetBSD Foundation, Inc.
@@ -34,15 +34,19 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.1 2010/08/22 18:56:22 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.2 2010/12/18 01:07:25 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
 
+#include <sys/atomic.h>
 #include <sys/conf.h>
 #include <sys/kauth.h>
+#include <sys/kmem.h>
 #include <sys/lwp.h>
 #include <sys/module.h>
+#include <sys/percpu.h>
+#include <sys/rwlock.h>
 #include <sys/socketvar.h>
 #include <sys/uio.h>
 
@@ -61,6 +65,19 @@
 static int     npf_dev_poll(dev_t, int, lwp_t *);
 static int     npf_dev_read(dev_t, struct uio *, int);
 
+typedef struct {
+       npf_ruleset_t *         n_rules;
+       npf_tableset_t *        n_tables;
+       npf_ruleset_t *         n_nat_rules;
+} npf_core_t;
+
+static void    npf_core_destroy(npf_core_t *);
+static int     npfctl_stats(void *);
+
+static krwlock_t               npf_lock                __cacheline_aligned;
+static npf_core_t *            npf_core                __cacheline_aligned;
+static percpu_t *              npf_stats_percpu        __read_mostly;
+
 const struct cdevsw npf_cdevsw = {
        npf_dev_open, npf_dev_close, npf_dev_read, nowrite, npf_dev_ioctl,
        nostop, notty, npf_dev_poll, nommap, nokqfilter, D_OTHER | D_MPSAFE
@@ -72,39 +89,31 @@
 #ifdef _MODULE
        devmajor_t bmajor = NODEVMAJOR, cmajor = NODEVMAJOR;
 #endif
-       int error;
-
-       /*
-        * Initialise ruleset, tables and session structures.
-        */
-
-       error = npf_ruleset_sysinit();
-       if (error)
-               return error;
+       npf_ruleset_t *rset, *nset;
+       npf_tableset_t *tset;
+       int error = 0;
 
-       error = npf_tableset_sysinit();
-       if (error) {
-               npf_ruleset_sysfini();
-               return error;
-       }
-
-       error = npf_session_sysinit();
-       if (error) {
-               npf_tableset_sysfini();
-               npf_ruleset_sysfini();
-               return error;
-       }
+       rw_init(&npf_lock);
+       npf_stats_percpu = percpu_alloc(NPF_STATS_SIZE);
+       npf_tableset_sysinit();
+       npf_session_sysinit();
        npf_nat_sysinit();
        npf_alg_sysinit();
+       npflogattach(1);
+
+       /* Load empty configuration. */
+       rset = npf_ruleset_create();
+       tset = npf_tableset_create();
+       nset = npf_ruleset_create();
+       npf_reload(rset, tset, nset);
+       KASSERT(npf_core != NULL);
 
 #ifdef _MODULE
        /* Attach /dev/npf device. */
        error = devsw_attach("npf", NULL, &bmajor, &npf_cdevsw, &cmajor);
        if (error) {
-               npf_nat_sysfini();
-               npf_session_sysfini();
-               npf_tableset_sysfini();
-               npf_ruleset_sysfini();
+               /* It will call devsw_detach(), which is safe. */
+               (void)npf_fini();
        }
 #endif
        return error;
@@ -114,15 +123,24 @@
 npf_fini(void)
 {
 
+       /*
+        * At first, detach device, remove pfil hooks and unload existing
+        * configuration, destroy structures.
+        */
 #ifdef _MODULE
-       /* At first, detach device and remove pfil hooks. */
        devsw_detach(NULL, &npf_cdevsw);
 #endif
+       npf_unregister_pfil();
+       npf_core_destroy(npf_core);
+       npflogdetach();
+
+       /* Note: order is particular. */
        npf_nat_sysfini();
        npf_alg_sysfini();
        npf_session_sysfini();
        npf_tableset_sysfini();
-       npf_ruleset_sysfini();
+       percpu_free(npf_stats_percpu, NPF_STATS_SIZE);
+       rw_destroy(&npf_lock);
 
        return 0;
 }
@@ -194,6 +212,15 @@
        case IOC_NPF_TABLE:
                error = npfctl_table(data);
                break;
+       case IOC_NPF_STATS:
+               error = npfctl_stats(data);
+               break;
+       case IOC_NPF_SESSIONS_SAVE:
+               error = npfctl_sessions_save(cmd, data);
+               break;
+       case IOC_NPF_SESSIONS_LOAD:
+               error = npfctl_sessions_load(cmd, data);
+               break;
        default:
                error = ENOTTY;
                break;
@@ -214,3 +241,137 @@
 
        return ENOTSUP;
 }
+
+/*
+ * NPF core loading/reloading/unloading mechanism.
+ */
+
+static void
+npf_core_destroy(npf_core_t *nc)
+{
+
+       npf_tableset_destroy(nc->n_tables);
+       npf_ruleset_destroy(nc->n_rules);
+       npf_ruleset_destroy(nc->n_nat_rules);
+       kmem_free(nc, sizeof(npf_core_t));
+}
+
+/*
+ * npf_reload: atomically load new ruleset, tableset and NAT policies.
+ * Then destroy old (unloaded) structures.
+ */
+void
+npf_reload(npf_ruleset_t *rset, npf_tableset_t *tset, npf_ruleset_t *nset)
+{
+       npf_core_t *nc, *onc;
+
+       /* Setup a new core structure. */
+       nc = kmem_alloc(sizeof(npf_core_t), KM_SLEEP);
+       nc->n_rules = rset;
+       nc->n_tables = tset;
+       nc->n_nat_rules = nset;
+
+       /* Lock and load the core structure. */
+       rw_enter(&npf_lock, RW_WRITER);
+       onc = atomic_swap_ptr(&npf_core, nc);
+       if (onc) {
+               /* Reload only necessary NAT policies. */
+               npf_ruleset_natreload(nset, onc->n_nat_rules);
+       }
+       /* Unlock.  Everything goes "live" now. */
+       rw_exit(&npf_lock);
+
+       /* Turn on/off session tracking accordingly. */
+       npf_session_tracking(true);
+
+       if (onc) {
+               /* Destroy unloaded structures. */
+               npf_core_destroy(onc);
+       }
+}
+
+void
+npf_core_enter(void)
+{
+       rw_enter(&npf_lock, RW_READER);
+}
+
+npf_ruleset_t *
+npf_core_ruleset(void)
+{
+       KASSERT(rw_lock_held(&npf_lock));
+       return npf_core->n_rules;
+}
+
+npf_ruleset_t *
+npf_core_natset(void)
+{
+       KASSERT(rw_lock_held(&npf_lock));
+       return npf_core->n_nat_rules;
+}
+
+npf_tableset_t *
+npf_core_tableset(void)
+{
+       KASSERT(rw_lock_held(&npf_lock));
+       return npf_core->n_tables;
+}
+
+void
+npf_core_exit(void)
+{
+       rw_exit(&npf_lock);
+}
+
+bool
+npf_core_locked(void)
+{
+       return rw_lock_held(&npf_lock);
+}
+
+/*
+ * NPF statistics interface.
+ */
+
+void
+npf_stats_inc(npf_stats_t st)
+{
+       uint64_t *stats = percpu_getref(npf_stats_percpu);
+       stats[st]++;
+       percpu_putref(npf_stats_percpu);
+}
+
+void
+npf_stats_dec(npf_stats_t st)
+{
+       uint64_t *stats = percpu_getref(npf_stats_percpu);
+       stats[st]--;
+       percpu_putref(npf_stats_percpu);
+}
+
+static void
+npf_stats_collect(void *mem, void *arg, struct cpu_info *ci)
+{
+       uint64_t *percpu_stats = mem, *full_stats = arg;
+       int i;



Home | Main Index | Thread Index | Old Index