netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH nft,v2 1/5] src: remove useless parameter from cache_flush()
@ 2019-06-17 17:18 Pablo Neira Ayuso
  2019-06-17 17:18 ` [PATCH nft,v2 2/5] tests: shell: cannot use handle for non-existing rule in kernel Pablo Neira Ayuso
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Pablo Neira Ayuso @ 2019-06-17 17:18 UTC (permalink / raw)
  To: netfilter-devel; +Cc: phil, fw

Command type is never used in cache_flush().

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: no changes.

 include/rule.h | 3 +--
 src/evaluate.c | 2 +-
 src/rule.c     | 2 +-
 3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/include/rule.h b/include/rule.h
index b41825d000d6..299485ffeeaa 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -639,8 +639,7 @@ extern int do_command(struct netlink_ctx *ctx, struct cmd *cmd);
 extern int cache_evaluate(struct nft_ctx *nft, struct list_head *cmds);
 extern int cache_update(struct nft_ctx *ctx, enum cmd_ops cmd,
 			struct list_head *msgs);
-extern void cache_flush(struct nft_ctx *ctx, enum cmd_ops cmd,
-			struct list_head *msgs);
+extern void cache_flush(struct nft_ctx *ctx, struct list_head *msgs);
 extern void cache_release(struct nft_cache *cache);
 extern bool cache_is_complete(struct nft_cache *cache, enum cmd_ops cmd);
 
diff --git a/src/evaluate.c b/src/evaluate.c
index 70c7e597f3b0..73a4be339ce1 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -3682,7 +3682,7 @@ static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd)
 
 	switch (cmd->obj) {
 	case CMD_OBJ_RULESET:
-		cache_flush(ctx->nft, cmd->op, ctx->msgs);
+		cache_flush(ctx->nft, ctx->msgs);
 		break;
 	case CMD_OBJ_TABLE:
 		/* Flushing a table does not empty the sets in the table nor remove
diff --git a/src/rule.c b/src/rule.c
index 0c0fd07ec70c..4407b0b0ceaa 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -297,7 +297,7 @@ static void __cache_flush(struct list_head *table_list)
 	}
 }
 
-void cache_flush(struct nft_ctx *nft, enum cmd_ops cmd, struct list_head *msgs)
+void cache_flush(struct nft_ctx *nft, struct list_head *msgs)
 {
 	struct netlink_ctx ctx = {
 		.list		= LIST_HEAD_INIT(ctx.list),
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH nft,v2 2/5] tests: shell: cannot use handle for non-existing rule in kernel
  2019-06-17 17:18 [PATCH nft,v2 1/5] src: remove useless parameter from cache_flush() Pablo Neira Ayuso
@ 2019-06-17 17:18 ` Pablo Neira Ayuso
  2019-06-17 17:26   ` Phil Sutter
  2019-06-17 17:18 ` [PATCH nft,v2 3/5] rule: skip cache population from do_command_monitor() Pablo Neira Ayuso
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Pablo Neira Ayuso @ 2019-06-17 17:18 UTC (permalink / raw)
  To: netfilter-devel; +Cc: phil, fw

This test invokes the 'replace rule ... handle 2' command. However,
there are no rules in the kernel, therefore it always fails.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: no changes.

 tests/shell/testcases/nft-f/0006action_object_0 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/shell/testcases/nft-f/0006action_object_0 b/tests/shell/testcases/nft-f/0006action_object_0
index ffa6c9bda973..fab3070f493f 100755
--- a/tests/shell/testcases/nft-f/0006action_object_0
+++ b/tests/shell/testcases/nft-f/0006action_object_0
@@ -16,7 +16,7 @@ generate1()
 	add set $family t s {type inet_service;}
 	add element $family t s {8080}
 	insert rule $family t c meta l4proto tcp tcp dport @s accept
-	replace rule $family t c handle 2 meta l4proto tcp tcp dport {9090, 8080}
+	add rule $family t c meta l4proto tcp tcp dport {9090, 8080}
 	add map $family t m {type inet_service:verdict;}
 	add element $family t m {10080:drop}
 	insert rule $family t c meta l4proto tcp tcp dport vmap @m
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH nft,v2 3/5] rule: skip cache population from do_command_monitor()
  2019-06-17 17:18 [PATCH nft,v2 1/5] src: remove useless parameter from cache_flush() Pablo Neira Ayuso
  2019-06-17 17:18 ` [PATCH nft,v2 2/5] tests: shell: cannot use handle for non-existing rule in kernel Pablo Neira Ayuso
@ 2019-06-17 17:18 ` Pablo Neira Ayuso
  2019-06-17 17:18 ` [PATCH nft,v2 4/5] netlink: remove netlink_list_table() Pablo Neira Ayuso
  2019-06-17 17:18 ` [PATCH nft,v2 5/5] src: add cache level flags Pablo Neira Ayuso
  3 siblings, 0 replies; 8+ messages in thread
From: Pablo Neira Ayuso @ 2019-06-17 17:18 UTC (permalink / raw)
  To: netfilter-devel; +Cc: phil, fw

nft_evaluate() already populates the cache before running the monitor
command. Remove this code.

Fixes: 7df42800cf89 ("src: single cache_update() call to build cache before evaluation")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: move patch from 4/5 to 3/5.

 src/rule.c | 32 --------------------------------
 1 file changed, 32 deletions(-)

diff --git a/src/rule.c b/src/rule.c
index 4407b0b0ceaa..bcd1c0bf73e8 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -2427,8 +2427,6 @@ static bool need_cache(const struct cmd *cmd)
 
 static int do_command_monitor(struct netlink_ctx *ctx, struct cmd *cmd)
 {
-	struct table *t;
-	struct set *s;
 	struct netlink_mon_handler monhandler = {
 		.monitor_flags	= cmd->monitor->flags,
 		.format		= cmd->monitor->format,
@@ -2442,36 +2440,6 @@ static int do_command_monitor(struct netlink_ctx *ctx, struct cmd *cmd)
 		monhandler.format = NFTNL_OUTPUT_JSON;
 
 	monhandler.cache_needed = need_cache(cmd);
-	if (monhandler.cache_needed) {
-		struct rule *rule, *nrule;
-		struct chain *chain;
-		int ret;
-
-		list_for_each_entry(t, &ctx->nft->cache.list, list) {
-			list_for_each_entry(s, &t->sets, list)
-				s->init = set_expr_alloc(&cmd->location, s);
-
-			if (!(cmd->monitor->flags & (1 << NFT_MSG_TRACE)))
-				continue;
-
-			/* When tracing we'd like to translate the rule handle
-			 * we receive in the trace messages to the actual rule
-			 * struct to print that out.  Populate rule cache now.
-			 */
-			ret = netlink_list_table(ctx, &t->handle);
-
-			if (ret != 0)
-				/* Shouldn't happen and doesn't break things
-				 * too badly
-				 */
-				continue;
-
-			list_for_each_entry_safe(rule, nrule, &ctx->list, list) {
-				chain = chain_lookup(t, &rule->handle);
-				list_move_tail(&rule->list, &chain->rules);
-			}
-		}
-	}
 
 	return netlink_monitor(&monhandler, ctx->nft->nf_sock);
 }
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH nft,v2 4/5] netlink: remove netlink_list_table()
  2019-06-17 17:18 [PATCH nft,v2 1/5] src: remove useless parameter from cache_flush() Pablo Neira Ayuso
  2019-06-17 17:18 ` [PATCH nft,v2 2/5] tests: shell: cannot use handle for non-existing rule in kernel Pablo Neira Ayuso
  2019-06-17 17:18 ` [PATCH nft,v2 3/5] rule: skip cache population from do_command_monitor() Pablo Neira Ayuso
@ 2019-06-17 17:18 ` Pablo Neira Ayuso
  2019-06-17 17:18 ` [PATCH nft,v2 5/5] src: add cache level flags Pablo Neira Ayuso
  3 siblings, 0 replies; 8+ messages in thread
From: Pablo Neira Ayuso @ 2019-06-17 17:18 UTC (permalink / raw)
  To: netfilter-devel; +Cc: phil, fw

Remove this wrapper, call netlink_list_rules() instead.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: move patch from 5/5 to 4/5.

 include/netlink.h | 2 +-
 src/netlink.c     | 7 +------
 src/rule.c        | 2 +-
 3 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/include/netlink.h b/include/netlink.h
index 0c08b1abbf6a..279723f33d31 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -104,6 +104,7 @@ extern struct expr *netlink_alloc_data(const struct location *loc,
 				       const struct nft_data_delinearize *nld,
 				       enum nft_registers dreg);
 
+extern int netlink_list_rules(struct netlink_ctx *ctx, const struct handle *h);
 extern void netlink_linearize_rule(struct netlink_ctx *ctx,
 				   struct nftnl_rule *nlr,
 				   const struct rule *rule);
@@ -115,7 +116,6 @@ extern struct chain *netlink_delinearize_chain(struct netlink_ctx *ctx,
 					       const struct nftnl_chain *nlc);
 
 extern int netlink_list_tables(struct netlink_ctx *ctx, const struct handle *h);
-extern int netlink_list_table(struct netlink_ctx *ctx, const struct handle *h);
 extern struct table *netlink_delinearize_table(struct netlink_ctx *ctx,
 					       const struct nftnl_table *nlt);
 
diff --git a/src/netlink.c b/src/netlink.c
index a6d81b4f6424..24d8f03ae4be 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -333,7 +333,7 @@ static int list_rule_cb(struct nftnl_rule *nlr, void *arg)
 	return 0;
 }
 
-static int netlink_list_rules(struct netlink_ctx *ctx, const struct handle *h)
+int netlink_list_rules(struct netlink_ctx *ctx, const struct handle *h)
 {
 	struct nftnl_rule_list *rule_cache;
 
@@ -485,11 +485,6 @@ int netlink_list_tables(struct netlink_ctx *ctx, const struct handle *h)
 	return 0;
 }
 
-int netlink_list_table(struct netlink_ctx *ctx, const struct handle *h)
-{
-	return netlink_list_rules(ctx, h);
-}
-
 enum nft_data_types dtype_map_to_kernel(const struct datatype *dtype)
 {
 	switch (dtype->type) {
diff --git a/src/rule.c b/src/rule.c
index bcd1c0bf73e8..ed199889702f 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -191,7 +191,7 @@ static int cache_init_objects(struct netlink_ctx *ctx, enum cmd_ops cmd)
 		if (cmd != CMD_LIST)
 			continue;
 
-		ret = netlink_list_table(ctx, &table->handle);
+		ret = netlink_list_rules(ctx, &table->handle);
 		list_for_each_entry_safe(rule, nrule, &ctx->list, list) {
 			chain = chain_lookup(table, &rule->handle);
 			list_move_tail(&rule->list, &chain->rules);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH nft,v2 5/5] src: add cache level flags
  2019-06-17 17:18 [PATCH nft,v2 1/5] src: remove useless parameter from cache_flush() Pablo Neira Ayuso
                   ` (2 preceding siblings ...)
  2019-06-17 17:18 ` [PATCH nft,v2 4/5] netlink: remove netlink_list_table() Pablo Neira Ayuso
@ 2019-06-17 17:18 ` Pablo Neira Ayuso
  3 siblings, 0 replies; 8+ messages in thread
From: Pablo Neira Ayuso @ 2019-06-17 17:18 UTC (permalink / raw)
  To: netfilter-devel; +Cc: phil, fw

The score approach based on command type is confusing.

This patch introduces cache level flags, each flag specifies what kind
of object type is needed. These flags are set on/off depending on the
list of commands coming in this batch.

cache_is_complete() now checks if the cache contains the objects that
are needed through these new flags.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: use 'enum cache_level_bits' as proposed by Phil Sutter.

 include/Makefile.am |   1 +
 include/cache.h     |  35 +++++++++++++++++
 include/nftables.h  |   2 +-
 include/rule.h      |   3 +-
 src/cache.c         |  87 ++++++++++++++++++++++--------------------
 src/evaluate.c      |   1 +
 src/libnftables.c   |   6 +--
 src/rule.c          | 106 +++++++++++++++++++++++-----------------------------
 8 files changed, 135 insertions(+), 106 deletions(-)
 create mode 100644 include/cache.h

diff --git a/include/Makefile.am b/include/Makefile.am
index b1f4fcf29015..2d77a768acb0 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -2,6 +2,7 @@ SUBDIRS =		linux		\
 			nftables
 
 noinst_HEADERS = 	cli.h		\
+			cache.h		\
 			datatype.h	\
 			expression.h	\
 			fib.h		\
diff --git a/include/cache.h b/include/cache.h
new file mode 100644
index 000000000000..d3502a8a6039
--- /dev/null
+++ b/include/cache.h
@@ -0,0 +1,35 @@
+#ifndef _NFT_CACHE_H_
+#define _NFT_CACHE_H_
+
+enum cache_level_bits {
+	NFT_CACHE_TABLE_BIT	= (1 << 0),
+	NFT_CACHE_CHAIN_BIT	= (1 << 1),
+	NFT_CACHE_SET_BIT	= (1 << 2),
+	NFT_CACHE_FLOWTABLE_BIT	= (1 << 3),
+	NFT_CACHE_OBJECT_BIT	= (1 << 4),
+	NFT_CACHE_SETELEM_BIT	= (1 << 5),
+	NFT_CACHE_RULE_BIT	= (1 << 6),
+	__NFT_CACHE_MAX_BIT	= (1 << 7),
+};
+
+enum cache_level_flags {
+	NFT_CACHE_EMPTY		= 0,
+	NFT_CACHE_TABLE		= NFT_CACHE_TABLE_BIT,
+	NFT_CACHE_CHAIN		= NFT_CACHE_TABLE_BIT |
+				  NFT_CACHE_CHAIN_BIT,
+	NFT_CACHE_SET		= NFT_CACHE_TABLE_BIT |
+				  NFT_CACHE_SET_BIT,
+	NFT_CACHE_FLOWTABLE	= NFT_CACHE_TABLE_BIT |
+				  NFT_CACHE_FLOWTABLE_BIT,
+	NFT_CACHE_OBJECT	= NFT_CACHE_TABLE_BIT |
+				  NFT_CACHE_OBJECT_BIT,
+	NFT_CACHE_SETELEM	= NFT_CACHE_TABLE_BIT |
+				  NFT_CACHE_SET_BIT |
+				  NFT_CACHE_SETELEM_BIT,
+	NFT_CACHE_RULE		= NFT_CACHE_TABLE_BIT |
+				  NFT_CACHE_CHAIN_BIT |
+				  NFT_CACHE_RULE_BIT,
+	NFT_CACHE_FULL		= __NFT_CACHE_MAX_BIT - 1,
+};
+
+#endif /* _NFT_CACHE_H_ */
diff --git a/include/nftables.h b/include/nftables.h
index b7c78572da77..ed446e2d16cf 100644
--- a/include/nftables.h
+++ b/include/nftables.h
@@ -81,7 +81,7 @@ struct nft_cache {
 	uint32_t		genid;
 	struct list_head	list;
 	uint32_t		seqnum;
-	uint32_t		cmd;
+	uint32_t		flags;
 };
 
 struct mnl_socket;
diff --git a/include/rule.h b/include/rule.h
index 299485ffeeaa..aefb24d95163 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -462,7 +462,6 @@ enum cmd_ops {
 	CMD_EXPORT,
 	CMD_MONITOR,
 	CMD_DESCRIBE,
-	__CMD_FLUSH_RULESET,
 };
 
 /**
@@ -636,7 +635,7 @@ extern struct error_record *rule_postprocess(struct rule *rule);
 struct netlink_ctx;
 extern int do_command(struct netlink_ctx *ctx, struct cmd *cmd);
 
-extern int cache_evaluate(struct nft_ctx *nft, struct list_head *cmds);
+extern unsigned int cache_evaluate(struct nft_ctx *nft, struct list_head *cmds);
 extern int cache_update(struct nft_ctx *ctx, enum cmd_ops cmd,
 			struct list_head *msgs);
 extern void cache_flush(struct nft_ctx *ctx, struct list_head *msgs);
diff --git a/src/cache.c b/src/cache.c
index d7153f6f6b8f..f9b8080e0b3c 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -11,112 +11,117 @@
 #include <rule.h>
 #include <erec.h>
 #include <utils.h>
+#include <cache.h>
 
-static unsigned int evaluate_cache_add(struct cmd *cmd)
+static unsigned int evaluate_cache_add(struct cmd *cmd, unsigned int flags)
 {
-	unsigned int completeness = CMD_INVALID;
-
 	switch (cmd->obj) {
 	case CMD_OBJ_SETELEM:
-	case CMD_OBJ_SET:
-	case CMD_OBJ_CHAIN:
-	case CMD_OBJ_FLOWTABLE:
-		completeness = cmd->op;
+		flags |= NFT_CACHE_SETELEM;
 		break;
 	case CMD_OBJ_RULE:
-		if (cmd->handle.index.id)
-			completeness = CMD_LIST;
+		if (cmd->handle.index.id ||
+		    cmd->handle.position.id ||
+		    cmd->handle.handle.id)
+			flags |= NFT_CACHE_RULE;
 		break;
 	default:
 		break;
 	}
 
-	return completeness;
+	return flags;
 }
 
-static unsigned int evaluate_cache_del(struct cmd *cmd)
+static unsigned int evaluate_cache_del(struct cmd *cmd, unsigned int flags)
 {
-	unsigned int completeness = CMD_INVALID;
-
 	switch (cmd->obj) {
 	case CMD_OBJ_SETELEM:
-		completeness = cmd->op;
+		flags |= NFT_CACHE_SETELEM;
 		break;
 	default:
 		break;
 	}
 
-	return completeness;
+	return flags;
 }
 
-static unsigned int evaluate_cache_flush(struct cmd *cmd)
+static unsigned int evaluate_cache_flush(struct cmd *cmd, unsigned int flags)
 {
-	unsigned int completeness = CMD_INVALID;
-
 	switch (cmd->obj) {
-	case CMD_OBJ_RULESET:
-		completeness = __CMD_FLUSH_RULESET;
-		break;
 	case CMD_OBJ_SET:
 	case CMD_OBJ_MAP:
 	case CMD_OBJ_METER:
-		completeness = cmd->op;
+		flags |= NFT_CACHE_SET;
 		break;
+	case CMD_OBJ_RULESET:
 	default:
+		flags = NFT_CACHE_EMPTY;
 		break;
 	}
 
-	return completeness;
+	return flags;
 }
 
-static unsigned int evaluate_cache_rename(struct cmd *cmd)
+static unsigned int evaluate_cache_rename(struct cmd *cmd, unsigned int flags)
 {
-	unsigned int completeness = CMD_INVALID;
-
 	switch (cmd->obj) {
 	case CMD_OBJ_CHAIN:
-		completeness = cmd->op;
+		flags |= NFT_CACHE_CHAIN;
 		break;
 	default:
 		break;
 	}
 
-	return completeness;
+	return flags;
 }
 
-int cache_evaluate(struct nft_ctx *nft, struct list_head *cmds)
+unsigned int cache_evaluate(struct nft_ctx *nft, struct list_head *cmds)
 {
-	unsigned int echo_completeness = CMD_INVALID;
-	unsigned int completeness = CMD_INVALID;
+	unsigned int flags = NFT_CACHE_EMPTY;
 	struct cmd *cmd;
 
 	list_for_each_entry(cmd, cmds, list) {
 		switch (cmd->op) {
 		case CMD_ADD:
 		case CMD_INSERT:
-		case CMD_REPLACE:
-			if (nft_output_echo(&nft->output))
-				echo_completeness = cmd->op;
-
+			if (nft_output_echo(&nft->output)) {
+				flags = NFT_CACHE_FULL;
+				break;
+			}
+
+			flags |= NFT_CACHE_TABLE |
+				 NFT_CACHE_CHAIN |
+				 NFT_CACHE_SET |
+				 NFT_CACHE_FLOWTABLE |
+				 NFT_CACHE_OBJECT;
 			/* Fall through */
 		case CMD_CREATE:
-			completeness = evaluate_cache_add(cmd);
+			flags = evaluate_cache_add(cmd, flags);
+			break;
+		case CMD_REPLACE:
+			flags = NFT_CACHE_FULL;
 			break;
 		case CMD_DELETE:
-			completeness = evaluate_cache_del(cmd);
+			flags |= NFT_CACHE_TABLE |
+				 NFT_CACHE_CHAIN |
+				 NFT_CACHE_SET |
+				 NFT_CACHE_FLOWTABLE |
+				 NFT_CACHE_OBJECT;
+
+			flags = evaluate_cache_del(cmd, flags);
 			break;
 		case CMD_GET:
 		case CMD_LIST:
 		case CMD_RESET:
 		case CMD_EXPORT:
 		case CMD_MONITOR:
-			completeness = cmd->op;
+			flags |= NFT_CACHE_FULL;
 			break;
 		case CMD_FLUSH:
-			completeness = evaluate_cache_flush(cmd);
+			flags = evaluate_cache_flush(cmd, flags);
 			break;
 		case CMD_RENAME:
-			completeness = evaluate_cache_rename(cmd);
+			flags = evaluate_cache_rename(cmd, flags);
 			break;
 		case CMD_DESCRIBE:
 		case CMD_IMPORT:
@@ -126,5 +131,5 @@ int cache_evaluate(struct nft_ctx *nft, struct list_head *cmds)
 		}
 	}
 
-	return max(completeness, echo_completeness);
+	return flags;
 }
diff --git a/src/evaluate.c b/src/evaluate.c
index 73a4be339ce1..ff0888d0c784 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -29,6 +29,7 @@
 #include <netlink.h>
 #include <time.h>
 #include <rule.h>
+#include <cache.h>
 #include <erec.h>
 #include <gmputil.h>
 #include <utils.h>
diff --git a/src/libnftables.c b/src/libnftables.c
index abd133bee127..dccb8ab4da42 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -381,11 +381,11 @@ static int nft_parse_bison_filename(struct nft_ctx *nft, const char *filename,
 static int nft_evaluate(struct nft_ctx *nft, struct list_head *msgs,
 			struct list_head *cmds)
 {
-	unsigned int completeness;
+	unsigned int flags;
 	struct cmd *cmd;
 
-	completeness = cache_evaluate(nft, cmds);
-	if (cache_update(nft, completeness, msgs) < 0)
+	flags = cache_evaluate(nft, cmds);
+	if (cache_update(nft, flags, msgs) < 0)
 		return -1;
 
 	list_for_each_entry(cmd, cmds, list) {
diff --git a/src/rule.c b/src/rule.c
index ed199889702f..f60374abcfbc 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -24,6 +24,7 @@
 #include <mnl.h>
 #include <misspell.h>
 #include <json.h>
+#include <cache.h>
 
 #include <libnftnl/common.h>
 #include <libnftnl/ruleset.h>
@@ -147,97 +148,85 @@ static int cache_init_tables(struct netlink_ctx *ctx, struct handle *h,
 	return 0;
 }
 
-static int cache_init_objects(struct netlink_ctx *ctx, enum cmd_ops cmd)
+static int cache_init_objects(struct netlink_ctx *ctx, unsigned int flags)
 {
+	struct rule *rule, *nrule;
 	struct table *table;
 	struct chain *chain;
-	struct rule *rule, *nrule;
 	struct set *set;
 	int ret;
 
 	list_for_each_entry(table, &ctx->nft->cache.list, list) {
-		ret = netlink_list_sets(ctx, &table->handle);
-		list_splice_tail_init(&ctx->list, &table->sets);
-
-		if (ret < 0)
-			return -1;
-
-		list_for_each_entry(set, &table->sets, list) {
-			ret = netlink_list_setelems(ctx, &set->handle, set);
+		if (flags & NFT_CACHE_SET_BIT) {
+			ret = netlink_list_sets(ctx, &table->handle);
+			list_splice_tail_init(&ctx->list, &table->sets);
 			if (ret < 0)
 				return -1;
 		}
-
-		ret = netlink_list_chains(ctx, &table->handle);
-		if (ret < 0)
-			return -1;
-		list_splice_tail_init(&ctx->list, &table->chains);
-
-		ret = netlink_list_flowtables(ctx, &table->handle);
-		if (ret < 0)
-			return -1;
-		list_splice_tail_init(&ctx->list, &table->flowtables);
-
-		if (cmd != CMD_RESET) {
+		if (flags & NFT_CACHE_SETELEM_BIT) {
+			list_for_each_entry(set, &table->sets, list) {
+				ret = netlink_list_setelems(ctx, &set->handle,
+							    set);
+				if (ret < 0)
+					return -1;
+			}
+		}
+		if (flags & NFT_CACHE_CHAIN_BIT) {
+			ret = netlink_list_chains(ctx, &table->handle);
+			if (ret < 0)
+				return -1;
+			list_splice_tail_init(&ctx->list, &table->chains);
+		}
+		if (flags & NFT_CACHE_FLOWTABLE_BIT) {
+			ret = netlink_list_flowtables(ctx, &table->handle);
+			if (ret < 0)
+				return -1;
+			list_splice_tail_init(&ctx->list, &table->flowtables);
+		}
+		if (flags & NFT_CACHE_OBJECT_BIT) {
 			ret = netlink_list_objs(ctx, &table->handle);
 			if (ret < 0)
 				return -1;
 			list_splice_tail_init(&ctx->list, &table->objs);
 		}
 
-		/* Skip caching other objects to speed up things: We only need
-		 * a full cache when listing the existing ruleset.
-		 */
-		if (cmd != CMD_LIST)
-			continue;
-
-		ret = netlink_list_rules(ctx, &table->handle);
-		list_for_each_entry_safe(rule, nrule, &ctx->list, list) {
-			chain = chain_lookup(table, &rule->handle);
-			list_move_tail(&rule->list, &chain->rules);
+		if (flags & NFT_CACHE_RULE_BIT) {
+			ret = netlink_list_rules(ctx, &table->handle);
+			list_for_each_entry_safe(rule, nrule, &ctx->list, list) {
+				chain = chain_lookup(table, &rule->handle);
+				list_move_tail(&rule->list, &chain->rules);
+			}
+			if (ret < 0)
+				return -1;
 		}
-
-		if (ret < 0)
-			return -1;
 	}
 	return 0;
 }
 
-static int cache_init(struct netlink_ctx *ctx, enum cmd_ops cmd)
+static int cache_init(struct netlink_ctx *ctx, unsigned int flags)
 {
 	struct handle handle = {
 		.family = NFPROTO_UNSPEC,
 	};
 	int ret;
 
-	if (cmd == __CMD_FLUSH_RULESET)
+	if (flags == NFT_CACHE_EMPTY)
 		return 0;
 
+	/* assume NFT_CACHE_TABLE is always set. */
 	ret = cache_init_tables(ctx, &handle, &ctx->nft->cache);
 	if (ret < 0)
 		return ret;
-	ret = cache_init_objects(ctx, cmd);
+	ret = cache_init_objects(ctx, flags);
 	if (ret < 0)
 		return ret;
 
 	return 0;
 }
 
-/* Return a "score" of how complete local cache will be if
- * cache_init_objects() ran for given cmd. Higher value
- * means more complete. */
-static int cache_completeness(enum cmd_ops cmd)
+bool cache_is_complete(struct nft_cache *cache, unsigned int flags)
 {
-	if (cmd == CMD_LIST)
-		return 3;
-	if (cmd != CMD_RESET)
-		return 2;
-	return 1;
-}
-
-bool cache_is_complete(struct nft_cache *cache, enum cmd_ops cmd)
-{
-	return cache_completeness(cache->cmd) >= cache_completeness(cmd);
+	return (cache->flags & flags) == flags;
 }
 
 static bool cache_is_updated(struct nft_cache *cache, uint16_t genid)
@@ -245,7 +234,7 @@ static bool cache_is_updated(struct nft_cache *cache, uint16_t genid)
 	return genid && genid == cache->genid;
 }
 
-int cache_update(struct nft_ctx *nft, enum cmd_ops cmd, struct list_head *msgs)
+int cache_update(struct nft_ctx *nft, unsigned int flags, struct list_head *msgs)
 {
 	struct netlink_ctx ctx = {
 		.list		= LIST_HEAD_INIT(ctx.list),
@@ -259,14 +248,14 @@ int cache_update(struct nft_ctx *nft, enum cmd_ops cmd, struct list_head *msgs)
 replay:
 	ctx.seqnum = cache->seqnum++;
 	genid = mnl_genid_get(&ctx);
-	if (cache_is_complete(cache, cmd) &&
+	if (cache_is_complete(cache, flags) &&
 	    cache_is_updated(cache, genid))
 		return 0;
 
 	if (cache->genid)
 		cache_release(cache);
 
-	ret = cache_init(&ctx, cmd);
+	ret = cache_init(&ctx, flags);
 	if (ret < 0) {
 		cache_release(cache);
 		if (errno == EINTR) {
@@ -283,7 +272,7 @@ replay:
 	}
 
 	cache->genid = genid;
-	cache->cmd = cmd;
+	cache->flags = flags;
 	return 0;
 }
 
@@ -308,15 +297,14 @@ void cache_flush(struct nft_ctx *nft, struct list_head *msgs)
 
 	__cache_flush(&cache->list);
 	cache->genid = mnl_genid_get(&ctx);
-	cache->cmd = CMD_LIST;
+	cache->flags = NFT_CACHE_FULL;
 }
 
 void cache_release(struct nft_cache *cache)
 {
 	__cache_flush(&cache->list);
 	cache->genid = 0;
-	cache->cmd = CMD_INVALID;
-
+	cache->flags = NFT_CACHE_EMPTY;
 }
 
 /* internal ID to uniquely identify a set in the batch */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH nft,v2 2/5] tests: shell: cannot use handle for non-existing rule in kernel
  2019-06-17 17:18 ` [PATCH nft,v2 2/5] tests: shell: cannot use handle for non-existing rule in kernel Pablo Neira Ayuso
@ 2019-06-17 17:26   ` Phil Sutter
  2019-06-17 17:34     ` Pablo Neira Ayuso
  0 siblings, 1 reply; 8+ messages in thread
From: Phil Sutter @ 2019-06-17 17:26 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel, fw

Hey Pablo!

On Mon, Jun 17, 2019 at 07:18:39PM +0200, Pablo Neira Ayuso wrote:
> This test invokes the 'replace rule ... handle 2' command. However,
> there are no rules in the kernel, therefore it always fails.

I found the cause for why this stopped working: You forgot to adjust
rule_evaluate(), what you need is something like this:

diff --git a/src/evaluate.c b/src/evaluate.c
index ff0888d0c7842..f17bebe4a5f22 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -3295,7 +3295,7 @@ static int rule_evaluate(struct eval_ctx *ctx, struct rule *rule,
        }
 
        /* add rules to cache only if it is complete enough to contain them */
-       if (!cache_is_complete(&ctx->nft->cache, CMD_LIST))
+       if (!(ctx->nft->cache.flags & NFT_CACHE_RULE))
                return 0;
 
        return rule_cache_update(ctx, op);

Then handle guessing works again. :)

Cheers, Phil

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH nft,v2 2/5] tests: shell: cannot use handle for non-existing rule in kernel
  2019-06-17 17:26   ` Phil Sutter
@ 2019-06-17 17:34     ` Pablo Neira Ayuso
  2019-06-17 17:53       ` Pablo Neira Ayuso
  0 siblings, 1 reply; 8+ messages in thread
From: Pablo Neira Ayuso @ 2019-06-17 17:34 UTC (permalink / raw)
  To: Phil Sutter, netfilter-devel, fw

On Mon, Jun 17, 2019 at 07:26:53PM +0200, Phil Sutter wrote:
> Hey Pablo!
> 
> On Mon, Jun 17, 2019 at 07:18:39PM +0200, Pablo Neira Ayuso wrote:
> > This test invokes the 'replace rule ... handle 2' command. However,
> > there are no rules in the kernel, therefore it always fails.
> 
> I found the cause for why this stopped working: You forgot to adjust
> rule_evaluate(), what you need is something like this:
> 
> diff --git a/src/evaluate.c b/src/evaluate.c
> index ff0888d0c7842..f17bebe4a5f22 100644
> --- a/src/evaluate.c
> +++ b/src/evaluate.c
> @@ -3295,7 +3295,7 @@ static int rule_evaluate(struct eval_ctx *ctx, struct rule *rule,
>         }
>  
>         /* add rules to cache only if it is complete enough to contain them */
> -       if (!cache_is_complete(&ctx->nft->cache, CMD_LIST))
> +       if (!(ctx->nft->cache.flags & NFT_CACHE_RULE))
>                 return 0;

Thanks! I'll fix this an send a new version.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH nft,v2 2/5] tests: shell: cannot use handle for non-existing rule in kernel
  2019-06-17 17:34     ` Pablo Neira Ayuso
@ 2019-06-17 17:53       ` Pablo Neira Ayuso
  0 siblings, 0 replies; 8+ messages in thread
From: Pablo Neira Ayuso @ 2019-06-17 17:53 UTC (permalink / raw)
  To: Phil Sutter, netfilter-devel, fw

On Mon, Jun 17, 2019 at 07:34:42PM +0200, Pablo Neira Ayuso wrote:
> On Mon, Jun 17, 2019 at 07:26:53PM +0200, Phil Sutter wrote:
> > Hey Pablo!
> > 
> > On Mon, Jun 17, 2019 at 07:18:39PM +0200, Pablo Neira Ayuso wrote:
> > > This test invokes the 'replace rule ... handle 2' command. However,
> > > there are no rules in the kernel, therefore it always fails.
> > 
> > I found the cause for why this stopped working: You forgot to adjust
> > rule_evaluate(), what you need is something like this:
> > 
> > diff --git a/src/evaluate.c b/src/evaluate.c
> > index ff0888d0c7842..f17bebe4a5f22 100644
> > --- a/src/evaluate.c
> > +++ b/src/evaluate.c
> > @@ -3295,7 +3295,7 @@ static int rule_evaluate(struct eval_ctx *ctx, struct rule *rule,
> >         }
> >  
> >         /* add rules to cache only if it is complete enough to contain them */
> > -       if (!cache_is_complete(&ctx->nft->cache, CMD_LIST))
> > +       if (!(ctx->nft->cache.flags & NFT_CACHE_RULE))
> >                 return 0;
> 
> Thanks! I'll fix this an send a new version.

If you're fine with this patchset, I propose to rewrite this commit log to:

    tests: shell: cannot use handle for non-existing rule in kernel

    Do not guess handle for an unexisting rule.

    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

Thanks!

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2019-06-17 17:53 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-06-17 17:18 [PATCH nft,v2 1/5] src: remove useless parameter from cache_flush() Pablo Neira Ayuso
2019-06-17 17:18 ` [PATCH nft,v2 2/5] tests: shell: cannot use handle for non-existing rule in kernel Pablo Neira Ayuso
2019-06-17 17:26   ` Phil Sutter
2019-06-17 17:34     ` Pablo Neira Ayuso
2019-06-17 17:53       ` Pablo Neira Ayuso
2019-06-17 17:18 ` [PATCH nft,v2 3/5] rule: skip cache population from do_command_monitor() Pablo Neira Ayuso
2019-06-17 17:18 ` [PATCH nft,v2 4/5] netlink: remove netlink_list_table() Pablo Neira Ayuso
2019-06-17 17:18 ` [PATCH nft,v2 5/5] src: add cache level flags Pablo Neira Ayuso

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).