Source-Changes-HG archive

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

[src/trunk]: src/sys/net/npf NPF: replace the TAILQ of the dynamic rules with...



details:   https://anonhg.NetBSD.org/src/rev/faa816b88124
branches:  trunk
changeset: 336807:faa816b88124
user:      rmind <rmind%NetBSD.org@localhost>
date:      Fri Mar 20 23:36:28 2015 +0000

description:
NPF: replace the TAILQ of the dynamic rules with a linked list and fix the
inheriting of the active dynamic rules during the reload; also, fix a bug
in the insert path by putting a memory barrier in the right place.

diffstat:

 sys/net/npf/npf_ctl.c     |    8 +-
 sys/net/npf/npf_ruleset.c |  230 +++++++++++++++++++++++++++------------------
 2 files changed, 142 insertions(+), 96 deletions(-)

diffs (truncated from 459 to 300 lines):

diff -r 46f05f2e9ef0 -r faa816b88124 sys/net/npf/npf_ctl.c
--- a/sys/net/npf/npf_ctl.c     Fri Mar 20 21:55:46 2015 +0000
+++ b/sys/net/npf/npf_ctl.c     Fri Mar 20 23:36:28 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf_ctl.c,v 1.40 2014/08/24 20:36:30 rmind Exp $       */
+/*     $NetBSD: npf_ctl.c,v 1.41 2015/03/20 23:36:28 rmind Exp $       */
 
 /*-
  * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.40 2014/08/24 20:36:30 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.41 2015/03/20 23:36:28 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/conf.h>
@@ -778,6 +778,9 @@
        }
        case NPF_CMD_RULE_LIST: {
                retdict = npf_ruleset_list(rlset, ruleset_name);
+               if (!retdict) {
+                       error = ESRCH;
+               }
                break;
        }
        case NPF_CMD_RULE_FLUSH: {
@@ -797,6 +800,7 @@
        npf_config_exit();
 
        if (rl) {
+               KASSERT(error);
                npf_rule_free(rl);
        }
 out:
diff -r 46f05f2e9ef0 -r faa816b88124 sys/net/npf/npf_ruleset.c
--- a/sys/net/npf/npf_ruleset.c Fri Mar 20 21:55:46 2015 +0000
+++ b/sys/net/npf/npf_ruleset.c Fri Mar 20 23:36:28 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf_ruleset.c,v 1.41 2015/02/02 00:31:39 rmind Exp $   */
+/*     $NetBSD: npf_ruleset.c,v 1.42 2015/03/20 23:36:28 rmind Exp $   */
 
 /*-
  * Copyright (c) 2009-2015 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.41 2015/02/02 00:31:39 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.42 2015/03/20 23:36:28 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -89,21 +89,24 @@
        npf_natpolicy_t *       r_natp;
        npf_rproc_t *           r_rproc;
 
-       /* Rule priority: (highest) 1, 2 ... n (lowest). */
-       pri_t                   r_priority;
+       union {
+               /*
+                * Dynamic group: rule subset and a group list entry.
+                */
+               struct {
+                       npf_rule_t *            r_subset;
+                       LIST_ENTRY(npf_rule)    r_dentry;
+               };
 
-       /*
-        * Dynamic group: subset queue and a dynamic group list entry.
-        * Dynamic rule: entry and the parent rule (the group).
-        */
-       union {
-               TAILQ_HEAD(npf_ruleq, npf_rule) r_subset;
-               TAILQ_ENTRY(npf_rule)   r_entry;
-       } /* C11 */;
-       union {
-               LIST_ENTRY(npf_rule)    r_dentry;
-               npf_rule_t *            r_parent;
-       } /* C11 */;
+               /*
+                * Dynamic rule: priority, parent group and next rule.
+                */
+               struct {
+                       int                     r_priority;
+                       npf_rule_t *            r_parent;
+                       npf_rule_t *            r_next;
+               };
+       };
 
        /* Rule ID, name and the optional key. */
        uint64_t                r_id;
@@ -147,19 +150,6 @@
        return rlset;
 }
 
-static void
-npf_ruleset_unlink(npf_ruleset_t *rlset, npf_rule_t *rl)
-{
-       if (NPF_DYNAMIC_GROUP_P(rl->r_attr)) {
-               LIST_REMOVE(rl, r_dentry);
-       }
-       if (NPF_DYNAMIC_RULE_P(rl->r_attr)) {
-               npf_rule_t *rg = rl->r_parent;
-               TAILQ_REMOVE(&rg->r_subset, rl, r_entry);
-       }
-       LIST_REMOVE(rl, r_aentry);
-}
-
 void
 npf_ruleset_destroy(npf_ruleset_t *rlset)
 {
@@ -167,7 +157,19 @@
        npf_rule_t *rl;
 
        while ((rl = LIST_FIRST(&rlset->rs_all)) != NULL) {
-               npf_ruleset_unlink(rlset, rl);
+               if (NPF_DYNAMIC_GROUP_P(rl->r_attr)) {
+                       /*
+                        * Note: r_subset may point to the rules which
+                        * were inherited by a new ruleset.
+                        */
+                       rl->r_subset = NULL;
+                       LIST_REMOVE(rl, r_dentry);
+               }
+               if (NPF_DYNAMIC_RULE_P(rl->r_attr)) {
+                       /* Not removing from r_subset, see above. */
+                       KASSERT(rl->r_parent != NULL);
+               }
+               LIST_REMOVE(rl, r_aentry);
                npf_rule_free(rl);
        }
        KASSERT(LIST_EMPTY(&rlset->rs_dynamic));
@@ -222,16 +224,16 @@
 int
 npf_ruleset_add(npf_ruleset_t *rlset, const char *rname, npf_rule_t *rl)
 {
-       npf_rule_t *rg, *it;
-       pri_t priocmd;
+       npf_rule_t *rg, *it, *target;
+       int priocmd;
 
+       if (!NPF_DYNAMIC_RULE_P(rl->r_attr)) {
+               return EINVAL;
+       }
        rg = npf_ruleset_lookup(rlset, rname);
        if (rg == NULL) {
                return ESRCH;
        }
-       if (!NPF_DYNAMIC_RULE_P(rl->r_attr)) {
-               return EINVAL;
-       }
 
        /* Dynamic rule - assign a unique ID and save the parent. */
        rl->r_id = ++rlset->rs_idcnt;
@@ -245,29 +247,32 @@
                rl->r_priority = 0;
        }
 
+       /*
+        * WARNING: once rg->subset or target->r_next of an *active*
+        * rule is set, then our rule becomes globally visible and active.
+        * Must issue a load fence to ensure rl->r_next visibility first.
+        */
        switch (priocmd) {
-       case NPF_PRI_FIRST:
-               TAILQ_FOREACH(it, &rg->r_subset, r_entry) {
-                       if (rl->r_priority <= it->r_priority)
-                               break;
-               }
-               if (it) {
-                       TAILQ_INSERT_BEFORE(it, rl, r_entry);
-               } else {
-                       TAILQ_INSERT_HEAD(&rg->r_subset, rl, r_entry);
-               }
-               break;
        case NPF_PRI_LAST:
        default:
-               TAILQ_FOREACH(it, &rg->r_subset, r_entry) {
-                       if (rl->r_priority < it->r_priority)
-                               break;
+               target = NULL;
+               it = rg->r_subset;
+               while (it && it->r_priority <= rl->r_priority) {
+                       target = it;
+                       it = it->r_next;
                }
-               if (it) {
-                       TAILQ_INSERT_BEFORE(it, rl, r_entry);
-               } else {
-                       TAILQ_INSERT_TAIL(&rg->r_subset, rl, r_entry);
+               if (target) {
+                       rl->r_next = target->r_next;
+                       membar_producer();
+                       target->r_next = rl;
+                       break;
                }
+               /* FALLTHROUGH */
+
+       case NPF_PRI_FIRST:
+               rl->r_next = rg->r_subset;
+               membar_producer();
+               rg->r_subset = rl;
                break;
        }
 
@@ -276,26 +281,41 @@
        return 0;
 }
 
+static void
+npf_ruleset_unlink(npf_rule_t *rl, npf_rule_t *prev)
+{
+       KASSERT(NPF_DYNAMIC_RULE_P(rl->r_attr));
+       if (prev) {
+               prev->r_next = rl->r_next;
+       } else {
+               npf_rule_t *rg = rl->r_parent;
+               rg->r_subset = rl->r_next;
+       }
+       LIST_REMOVE(rl, r_aentry);
+}
+
 /*
  * npf_ruleset_remove: remove the dynamic rule given the rule ID.
  */
 int
 npf_ruleset_remove(npf_ruleset_t *rlset, const char *rname, uint64_t id)
 {
-       npf_rule_t *rg, *rl;
+       npf_rule_t *rg, *prev = NULL;
 
        if ((rg = npf_ruleset_lookup(rlset, rname)) == NULL) {
                return ESRCH;
        }
-       TAILQ_FOREACH(rl, &rg->r_subset, r_entry) {
+       for (npf_rule_t *rl = rg->r_subset; rl; rl = rl->r_next) {
                KASSERT(rl->r_parent == rg);
+               KASSERT(NPF_DYNAMIC_RULE_P(rl->r_attr));
 
                /* Compare ID.  On match, remove and return. */
                if (rl->r_id == id) {
-                       npf_ruleset_unlink(rlset, rl);
+                       npf_ruleset_unlink(rl, prev);
                        LIST_INSERT_HEAD(&rlset->rs_gc, rl, r_aentry);
                        return 0;
                }
+               prev = rl;
        }
        return ENOENT;
 }
@@ -307,7 +327,7 @@
 npf_ruleset_remkey(npf_ruleset_t *rlset, const char *rname,
     const void *key, size_t len)
 {
-       npf_rule_t *rg, *rl;
+       npf_rule_t *rg, *rlast = NULL, *prev = NULL, *lastprev = NULL;
 
        KASSERT(len && len <= NPF_RULE_MAXKEYLEN);
 
@@ -315,18 +335,22 @@
                return ESRCH;
        }
 
-       /* Find the last in the list. */
-       TAILQ_FOREACH_REVERSE(rl, &rg->r_subset, npf_ruleq, r_entry) {
+       /* Compare the key and find the last in the list. */
+       for (npf_rule_t *rl = rg->r_subset; rl; rl = rl->r_next) {
                KASSERT(rl->r_parent == rg);
-
-               /* Compare the key.  On match, remove and return. */
+               KASSERT(NPF_DYNAMIC_RULE_P(rl->r_attr));
                if (memcmp(rl->r_key, key, len) == 0) {
-                       npf_ruleset_unlink(rlset, rl);
-                       LIST_INSERT_HEAD(&rlset->rs_gc, rl, r_aentry);
-                       return 0;
+                       lastprev = prev;
+                       rlast = rl;
                }
+               prev = rl;
        }
-       return ENOENT;
+       if (!rlast) {
+               return ENOENT;
+       }
+       npf_ruleset_unlink(rlast, lastprev);
+       LIST_INSERT_HEAD(&rlset->rs_gc, rlast, r_aentry);
+       return 0;
 }
 
 /*
@@ -337,7 +361,7 @@
 {
        prop_dictionary_t rgdict;
        prop_array_t rules;
-       npf_rule_t *rg, *rl;
+       npf_rule_t *rg;
 
        KASSERT(npf_config_locked_p());



Home | Main Index | Thread Index | Old Index