Patchwork [nf-next/nf_tables-experiments,-,v2,4/4] nf_tables: Add support for replacing a rule by another one.

login
register
mail settings
Submitter Tomasz Bursztyka
Date Nov. 1, 2012, 11:38 a.m.
Message ID <1351769913-5851-5-git-send-email-tomasz.bursztyka@linux.intel.com>
Download mbox | patch
Permalink /patch/196168/
State Accepted
Headers show

Comments

Tomasz Bursztyka - Nov. 1, 2012, 11:38 a.m.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
 net/netfilter/nf_tables_api.c | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

Patch

diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 43eccbb..72881d2 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -1309,7 +1309,7 @@  static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
 	const struct nft_af_info *afi;
 	const struct nft_table *table;
 	struct nft_chain *chain;
-	struct nft_rule *rule;
+	struct nft_rule *rule, *old_rule = NULL;
 	struct nft_expr_info info[NFT_RULE_MAXEXPRS];
 	struct nft_expr *expr;
 	struct nft_ctx ctx;
@@ -1345,9 +1345,11 @@  static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
 		if (rule != NULL) {
 			if (nlh->nlmsg_flags & NLM_F_EXCL)
 				return -EEXIST;
-			if (nlh->nlmsg_flags & NLM_F_REPLACE)
-				return -EOPNOTSUPP;
-			return 0;
+			if (nlh->nlmsg_flags & NLM_F_REPLACE) {
+				old_rule = rule;
+				rule = NULL;
+			} else
+				return 0;
 		}
 	} else
 		handle = nf_tables_rule_alloc_handle(chain);
@@ -1390,7 +1392,19 @@  static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
 		expr = nft_expr_next(expr);
 	}
 
-	if (nlh->nlmsg_flags & NLM_F_APPEND)
+	if (nlh->nlmsg_flags & NLM_F_REPLACE) {
+		if (old_rule == NULL)
+			goto err2;
+
+		list_replace_rcu(&old_rule->list, &rule->list);
+
+		// FIXME: this makes deletion performance *really* suck
+		synchronize_rcu();
+
+		nf_tables_rule_notify(skb, nlh, table, chain, old_rule,
+				      NFT_MSG_DELRULE, nfmsg->nfgen_family);
+		nf_tables_rule_destroy(&ctx, old_rule);
+	} else if (nlh->nlmsg_flags & NLM_F_APPEND)
 		list_add_tail_rcu(&rule->list, &chain->rules);
 	else
 		list_add_rcu(&rule->list, &chain->rules);