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/2d62bd60b028
branches: trunk
changeset: 806949:2d62bd60b028
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 9a947c0d02b2 -r 2d62bd60b028 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 9a947c0d02b2 -r 2d62bd60b028 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