netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [nft PATCH v4] Implement 'reset rule' and 'reset rules' commands
@ 2023-01-17 17:33 Phil Sutter
  2023-01-18 11:52 ` Pablo Neira Ayuso
  2023-01-18 13:59 ` Phil Sutter
  0 siblings, 2 replies; 3+ messages in thread
From: Phil Sutter @ 2023-01-17 17:33 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Reset rule counters and quotas in kernel, i.e. without having to reload
them. Requires respective kernel patch to support NFT_MSG_GETRULE_RESET
message type.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
Changes since v3:
- Have to cache anything a rule might reference.
- Update test case to include a set being referred to.

Changes since v2:
- Reduce cache requirements.
- Make list_rule_cb() work with NFPROTO_UNSPEC, too. Needed for full
  ruleset reset without rule cache.

Changes since v1:
- Rename struct nft_cache_filter::rule_id to rule_handle as requested
- Drop accidental whitespace change from parser_json.c
- Add test case
---
 doc/libnftables-json.adoc                     |   2 +-
 doc/nft.txt                                   |   6 +-
 include/cache.h                               |   7 +
 include/linux/netfilter/nf_tables.h           |   1 +
 include/mnl.h                                 |   4 +-
 include/netlink.h                             |   3 +
 include/rule.h                                |   1 +
 src/cache.c                                   |  43 ++++-
 src/evaluate.c                                |   2 +
 src/json.c                                    |   1 +
 src/mnl.c                                     |  18 +-
 src/netlink.c                                 |  49 +++++
 src/parser_bison.y                            |  16 ++
 src/parser_json.c                             |  35 ++++
 src/rule.c                                    |  10 ++
 src/scanner.l                                 |   1 +
 .../testcases/rule_management/0011reset_0     | 168 ++++++++++++++++++
 .../rule_management/dumps/0011reset_0.nft     |  31 ++++
 18 files changed, 384 insertions(+), 14 deletions(-)
 create mode 100755 tests/shell/testcases/rule_management/0011reset_0
 create mode 100644 tests/shell/testcases/rule_management/dumps/0011reset_0.nft

diff --git a/doc/libnftables-json.adoc b/doc/libnftables-json.adoc
index d985149a0af35..f4aea36eb5711 100644
--- a/doc/libnftables-json.adoc
+++ b/doc/libnftables-json.adoc
@@ -175,7 +175,7 @@ kind, optionally filtered by *family* and for some, also *table*.
 ____
 *{ "reset":* 'RESET_OBJECT' *}*
 
-'RESET_OBJECT' := 'COUNTER' | 'COUNTERS' | 'QUOTA' | 'QUOTAS'
+'RESET_OBJECT' := 'COUNTER' | 'COUNTERS' | 'QUOTA' | 'QUOTAS' | 'RULE' | 'RULES'
 ____
 
 Reset state in suitable objects, i.e. zero their internal counter.
diff --git a/doc/nft.txt b/doc/nft.txt
index eb8df1d95e53a..18c18468c31b0 100644
--- a/doc/nft.txt
+++ b/doc/nft.txt
@@ -481,7 +481,10 @@ RULES
 [verse]
 {*add* | *insert*} *rule* ['family'] 'table' 'chain' [*handle* 'handle' | *index* 'index'] 'statement' ... [*comment* 'comment']
 *replace rule* ['family'] 'table' 'chain' *handle* 'handle' 'statement' ... [*comment* 'comment']
-*delete rule* ['family'] 'table' 'chain' *handle* 'handle'
+{*delete* | *reset*} *rule* ['family'] 'table' 'chain' *handle* 'handle'
+*reset rules* ['family']
+*reset rules* *table* ['family'] 'table'
+*reset rules* *chain* ['family'] 'table' ['chain']
 
 Rules are added to chains in the given table. If the family is not specified, the
 ip family is used. Rules are constructed from two kinds of components according
@@ -509,6 +512,7 @@ case the rule is inserted after the specified rule.
 beginning of the chain or before the specified rule.
 *replace*:: Similar to *add*, but the rule replaces the specified rule.
 *delete*:: Delete the specified rule.
+*reset*:: Reset rule-contained state, i.e. counter and quota statement values.
 
 .*add a rule to ip table output chain*
 -------------
diff --git a/include/cache.h b/include/cache.h
index 575381ef971bc..5bf78fe025501 100644
--- a/include/cache.h
+++ b/include/cache.h
@@ -3,6 +3,8 @@
 
 #include <string.h>
 
+struct handle;
+
 enum cache_level_bits {
 	NFT_CACHE_TABLE_BIT	= (1 << 0),
 	NFT_CACHE_CHAIN_BIT	= (1 << 1),
@@ -55,6 +57,7 @@ struct nft_cache_filter {
 		const char	*chain;
 		const char	*set;
 		const char	*ft;
+		uint64_t	rule_handle;
 	} list;
 
 	struct {
@@ -138,4 +141,8 @@ struct nft_cache {
 void nft_chain_cache_update(struct netlink_ctx *ctx, struct table *table,
 			    const char *chain);
 
+int rule_cache_dump(struct netlink_ctx *ctx, const struct handle *h,
+		    const struct nft_cache_filter *filter,
+		    bool dump, bool reset);
+
 #endif /* _NFT_CACHE_H_ */
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index e4b739d57480a..3d045030e3ad3 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -124,6 +124,7 @@ enum nf_tables_msg_types {
 	NFT_MSG_NEWFLOWTABLE,
 	NFT_MSG_GETFLOWTABLE,
 	NFT_MSG_DELFLOWTABLE,
+	NFT_MSG_GETRULE_RESET,
 	NFT_MSG_MAX,
 };
 
diff --git a/include/mnl.h b/include/mnl.h
index 8e0a7e3fccab9..c067669125395 100644
--- a/include/mnl.h
+++ b/include/mnl.h
@@ -34,7 +34,9 @@ int mnl_nft_rule_del(struct netlink_ctx *ctx, struct cmd *cmd);
 int mnl_nft_rule_replace(struct netlink_ctx *ctx, struct cmd *cmd);
 
 struct nftnl_rule_list *mnl_nft_rule_dump(struct netlink_ctx *ctx, int family,
-					  const char *table, const char *chain);
+					  const char *table, const char *chain,
+					  uint64_t rule_handle,
+					  bool dump, bool reset);
 
 int mnl_nft_chain_add(struct netlink_ctx *ctx, struct cmd *cmd,
 		      unsigned int flags);
diff --git a/include/netlink.h b/include/netlink.h
index 5a7f6a1e28ef3..0d97f71ccff37 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -183,6 +183,9 @@ extern int netlink_list_flowtables(struct netlink_ctx *ctx,
 extern struct flowtable *netlink_delinearize_flowtable(struct netlink_ctx *ctx,
 						       struct nftnl_flowtable *nlo);
 
+extern int netlink_reset_rules(struct netlink_ctx *ctx, const struct cmd *cmd,
+			       bool dump);
+
 extern void netlink_dump_chain(const struct nftnl_chain *nlc,
 			       struct netlink_ctx *ctx);
 extern void netlink_dump_rule(const struct nftnl_rule *nlr,
diff --git a/include/rule.h b/include/rule.h
index d829f484a9afa..22c611f6068f3 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -620,6 +620,7 @@ enum cmd_obj {
 	CMD_OBJ_SETELEMS,
 	CMD_OBJ_SETS,
 	CMD_OBJ_RULE,
+	CMD_OBJ_RULES,
 	CMD_OBJ_CHAIN,
 	CMD_OBJ_CHAINS,
 	CMD_OBJ_TABLE,
diff --git a/src/cache.c b/src/cache.c
index 85de970f76448..0f5d1099f1027 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -263,6 +263,30 @@ static unsigned int evaluate_cache_list(struct nft_ctx *nft, struct cmd *cmd,
 	return flags;
 }
 
+static unsigned int evaluate_cache_reset(struct cmd *cmd, unsigned int flags,
+					 struct nft_cache_filter *filter)
+{
+	switch (cmd->obj) {
+	case CMD_OBJ_RULES:
+		if (filter) {
+			if (cmd->handle.table.name) {
+				filter->list.family = cmd->handle.family;
+				filter->list.table = cmd->handle.table.name;
+			}
+			if (cmd->handle.chain.name)
+				filter->list.chain = cmd->handle.chain.name;
+		}
+		flags |= NFT_CACHE_SET | NFT_CACHE_FLOWTABLE |
+			 NFT_CACHE_OBJECT | NFT_CACHE_CHAIN;
+		break;
+	default:
+		flags |= NFT_CACHE_TABLE;
+		break;
+	}
+
+	return flags;
+}
+
 static int nft_handle_validate(const struct cmd *cmd, struct list_head *msgs)
 {
 	const struct handle *h = &cmd->handle;
@@ -277,6 +301,7 @@ static int nft_handle_validate(const struct cmd *cmd, struct list_head *msgs)
 		}
 		break;
 	case CMD_OBJ_RULE:
+	case CMD_OBJ_RULES:
 	case CMD_OBJ_CHAIN:
 	case CMD_OBJ_CHAINS:
 		if (h->table.name &&
@@ -403,7 +428,7 @@ int nft_cache_evaluate(struct nft_ctx *nft, struct list_head *cmds,
 			flags = evaluate_cache_get(cmd, flags);
 			break;
 		case CMD_RESET:
-			flags |= NFT_CACHE_TABLE;
+			flags |= evaluate_cache_reset(cmd, flags, filter);
 			break;
 		case CMD_LIST:
 			flags |= evaluate_cache_list(nft, cmd, flags, filter);
@@ -591,8 +616,8 @@ static int list_rule_cb(struct nftnl_rule *nlr, void *data)
 	table  = nftnl_rule_get_str(nlr, NFTNL_RULE_TABLE);
 	chain  = nftnl_rule_get_str(nlr, NFTNL_RULE_CHAIN);
 
-	if (h->family != family ||
-	    strcmp(table, h->table.name) != 0 ||
+	if ((h->family != NFPROTO_UNSPEC && h->family != family) ||
+	    (h->table.name && strcmp(table, h->table.name) != 0) ||
 	    (h->chain.name && strcmp(chain, h->chain.name) != 0))
 		return 0;
 
@@ -604,19 +629,23 @@ static int list_rule_cb(struct nftnl_rule *nlr, void *data)
 	return 0;
 }
 
-static int rule_cache_dump(struct netlink_ctx *ctx, const struct handle *h,
-			   const struct nft_cache_filter *filter)
+int rule_cache_dump(struct netlink_ctx *ctx, const struct handle *h,
+		    const struct nft_cache_filter *filter,
+		    bool dump, bool reset)
 {
 	struct nftnl_rule_list *rule_cache;
 	const char *table = NULL;
 	const char *chain = NULL;
+	uint64_t rule_handle = 0;
 
 	if (filter) {
 		table = filter->list.table;
 		chain = filter->list.chain;
+		rule_handle = filter->list.rule_handle;
 	}
 
-	rule_cache = mnl_nft_rule_dump(ctx, h->family, table, chain);
+	rule_cache = mnl_nft_rule_dump(ctx, h->family,
+				       table, chain, rule_handle, dump, reset);
 	if (rule_cache == NULL) {
 		if (errno == EINTR)
 			return -1;
@@ -948,7 +977,7 @@ static int rule_init_cache(struct netlink_ctx *ctx, struct table *table,
 	struct chain *chain;
 	int ret;
 
-	ret = rule_cache_dump(ctx, &table->handle, filter);
+	ret = rule_cache_dump(ctx, &table->handle, filter, true, false);
 
 	list_for_each_entry_safe(rule, nrule, &ctx->list, list) {
 		chain = chain_cache_find(table, rule->handle.chain.name);
diff --git a/src/evaluate.c b/src/evaluate.c
index 21de18409c873..61ebcbfc81cf7 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -5286,6 +5286,8 @@ static int cmd_evaluate_reset(struct eval_ctx *ctx, struct cmd *cmd)
 	case CMD_OBJ_QUOTA:
 	case CMD_OBJ_COUNTERS:
 	case CMD_OBJ_QUOTAS:
+	case CMD_OBJ_RULES:
+	case CMD_OBJ_RULE:
 		if (cmd->handle.table.name == NULL)
 			return 0;
 		if (!table_cache_find(&ctx->nft->cache.table_cache,
diff --git a/src/json.c b/src/json.c
index f57f2f77f48ec..f15461d33894c 100644
--- a/src/json.c
+++ b/src/json.c
@@ -1911,6 +1911,7 @@ int do_command_list_json(struct netlink_ctx *ctx, struct cmd *cmd)
 	case CMD_OBJ_SET:
 		root = do_list_set_json(ctx, cmd, table);
 		break;
+	case CMD_OBJ_RULES:
 	case CMD_OBJ_RULESET:
 		root = do_list_ruleset_json(ctx, cmd);
 		break;
diff --git a/src/mnl.c b/src/mnl.c
index 62b0b59c2da8a..0f749af066af2 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -654,13 +654,21 @@ static int rule_cb(const struct nlmsghdr *nlh, void *data)
 }
 
 struct nftnl_rule_list *mnl_nft_rule_dump(struct netlink_ctx *ctx, int family,
-					  const char *table, const char *chain)
+					  const char *table, const char *chain,
+					  uint64_t rule_handle,
+					  bool dump, bool reset)
 {
+	uint16_t nl_flags = dump ? NLM_F_DUMP : NLM_F_ACK;
 	char buf[MNL_SOCKET_BUFFER_SIZE];
 	struct nftnl_rule_list *nlr_list;
 	struct nftnl_rule *nlr = NULL;
 	struct nlmsghdr *nlh;
-	int ret;
+	int msg_type, ret;
+
+	if (reset)
+		msg_type = NFT_MSG_GETRULE_RESET;
+	else
+		msg_type = NFT_MSG_GETRULE;
 
 	if (table) {
 		nlr = nftnl_rule_alloc();
@@ -670,14 +678,16 @@ struct nftnl_rule_list *mnl_nft_rule_dump(struct netlink_ctx *ctx, int family,
 		nftnl_rule_set_str(nlr, NFTNL_RULE_TABLE, table);
 		if (chain)
 			nftnl_rule_set_str(nlr, NFTNL_RULE_CHAIN, chain);
+		if (rule_handle)
+			nftnl_rule_set_u64(nlr, NFTNL_RULE_HANDLE, rule_handle);
 	}
 
 	nlr_list = nftnl_rule_list_alloc();
 	if (nlr_list == NULL)
 		memory_allocation_error();
 
-	nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, family,
-				    NLM_F_DUMP, ctx->seqnum);
+	nlh = nftnl_nlmsg_build_hdr(buf, msg_type, family,
+				    nl_flags, ctx->seqnum);
 	if (nlr) {
 		nftnl_rule_nlmsg_build_payload(nlh, nlr);
 		nftnl_rule_free(nlr);
diff --git a/src/netlink.c b/src/netlink.c
index 51de9c9c8edb2..1e0f43d8e5200 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -1767,6 +1767,55 @@ int netlink_reset_objs(struct netlink_ctx *ctx, const struct cmd *cmd,
 	return err;
 }
 
+int netlink_reset_rules(struct netlink_ctx *ctx, const struct cmd *cmd,
+		        bool dump)
+{
+	const struct handle *h = &cmd->handle;
+	struct nft_cache_filter f = {
+		.list.table		= h->table.name,
+		.list.chain		= h->chain.name,
+		.list.rule_handle	= h->handle.id,
+	};
+	struct rule *rule, *next, *crule, *cnext;
+	struct table *table;
+	struct chain *chain;
+	int ret;
+
+	ret = rule_cache_dump(ctx, h, &f, dump, true);
+
+	list_for_each_entry_safe(rule, next, &ctx->list, list) {
+		table = table_cache_find(&ctx->nft->cache.table_cache,
+					 rule->handle.table.name,
+					 rule->handle.family);
+		if (!table)
+			continue;
+
+		chain = chain_cache_find(table, rule->handle.chain.name);
+		if (!chain)
+			continue;
+
+		list_del(&rule->list);
+		list_for_each_entry_safe(crule, cnext, &chain->rules, list) {
+			if (crule->handle.handle.id != rule->handle.handle.id)
+				continue;
+
+			list_replace(&crule->list, &rule->list);
+			rule_free(crule);
+			rule = NULL;
+			break;
+		}
+		if (rule) {
+			list_add_tail(&rule->list, &chain->rules);
+		}
+	}
+	list_for_each_entry_safe(rule, next, &ctx->list, list) {
+		list_del(&rule->list);
+		rule_free(rule);
+	}
+
+	return ret;
+}
+
 struct flowtable *
 netlink_delinearize_flowtable(struct netlink_ctx *ctx,
 			      struct nftnl_flowtable *nlo)
diff --git a/src/parser_bison.y b/src/parser_bison.y
index ccf07a30fbfc5..62a4809b9ee7e 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -1597,6 +1597,22 @@ reset_cmd		:	COUNTERS	ruleset_spec
 			{
 				$$ = cmd_alloc(CMD_RESET, CMD_OBJ_QUOTA, &$2, &@$, NULL);
 			}
+			|	RULES		ruleset_spec
+			{
+				$$ = cmd_alloc(CMD_RESET, CMD_OBJ_RULES, &$2, &@$, NULL);
+			}
+			|	RULES		TABLE	table_spec
+			{
+				$$ = cmd_alloc(CMD_RESET, CMD_OBJ_RULES, &$3, &@$, NULL);
+			}
+			|	RULES		CHAIN	chain_spec
+			{
+				$$ = cmd_alloc(CMD_RESET, CMD_OBJ_RULES, &$3, &@$, NULL);
+			}
+			|	RULE		ruleid_spec
+			{
+				$$ = cmd_alloc(CMD_RESET, CMD_OBJ_RULE, &$2, &@$, NULL);
+			}
 			;
 
 flush_cmd		:	TABLE		table_spec
diff --git a/src/parser_json.c b/src/parser_json.c
index ae68331424351..dfab3f9cbc7d3 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -3763,6 +3763,39 @@ static struct cmd *json_parse_cmd_list(struct json_ctx *ctx,
 	return NULL;
 }
 
+static struct cmd *json_parse_cmd_reset_rule(struct json_ctx *ctx,
+					     json_t *root, enum cmd_ops op,
+					     enum cmd_obj obj)
+{
+	struct handle h = {
+		.family = NFPROTO_UNSPEC,
+	};
+	const char *family = NULL, *table = NULL, *chain = NULL;
+
+
+	if (obj == CMD_OBJ_RULE &&
+	    json_unpack_err(ctx, root, "{s:s, s:s, s:s, s:I}",
+			    "family", &family, "table", &table,
+			    "chain", &chain, "handle", &h.handle.id))
+		return NULL;
+	else if (obj == CMD_OBJ_RULES) {
+		json_unpack(root, "{s:s}", "family", &family);
+		json_unpack(root, "{s:s}", "table", &table);
+		json_unpack(root, "{s:s}", "chain", &chain);
+	}
+
+	if (family && parse_family(family, &h.family)) {
+		json_error(ctx, "Unknown family '%s'.", family);
+		return NULL;
+	}
+	if (table) {
+		h.table.name = xstrdup(table);
+		if (chain)
+			h.chain.name = xstrdup(chain);
+	}
+	return cmd_alloc(op, obj, &h, int_loc, NULL);
+}
+
 static struct cmd *json_parse_cmd_reset(struct json_ctx *ctx,
 				        json_t *root, enum cmd_ops op)
 {
@@ -3776,6 +3809,8 @@ static struct cmd *json_parse_cmd_reset(struct json_ctx *ctx,
 		{ "counters", CMD_OBJ_COUNTERS, json_parse_cmd_list_multiple },
 		{ "quota", CMD_OBJ_QUOTA, json_parse_cmd_add_object },
 		{ "quotas", CMD_OBJ_QUOTAS, json_parse_cmd_list_multiple },
+		{ "rule", CMD_OBJ_RULE, json_parse_cmd_reset_rule },
+		{ "rules", CMD_OBJ_RULES, json_parse_cmd_reset_rule },
 	};
 	unsigned int i;
 	json_t *tmp;
diff --git a/src/rule.c b/src/rule.c
index 903c01f53825a..371c803a57c60 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -2504,6 +2504,8 @@ static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd)
 	case CMD_OBJ_SET:
 		return do_list_set(ctx, cmd, table);
 	case CMD_OBJ_RULESET:
+	case CMD_OBJ_RULES:
+	case CMD_OBJ_RULE:
 		return do_list_ruleset(ctx, cmd);
 	case CMD_OBJ_METERS:
 		return do_list_sets(ctx, cmd);
@@ -2611,6 +2613,14 @@ static int do_command_reset(struct netlink_ctx *ctx, struct cmd *cmd)
 	case CMD_OBJ_QUOTA:
 		type = NFT_OBJECT_QUOTA;
 		break;
+	case CMD_OBJ_RULES:
+		ret = netlink_reset_rules(ctx, cmd, true);
+		if (ret < 0)
+			return ret;
+
+		return do_command_list(ctx, cmd);
+	case CMD_OBJ_RULE:
+		return netlink_reset_rules(ctx, cmd, false);
 	default:
 		BUG("invalid command object type %u\n", cmd->obj);
 	}
diff --git a/src/scanner.l b/src/scanner.l
index 9c85ee3769bc9..aa0a0a9f94fdf 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -402,6 +402,7 @@ addrstring	({macaddr}|{ip4addr}|{ip6addr})
 <SCANSTATE_CMD_LIST,SCANSTATE_CMD_RESET>{
 	"counters"		{ return COUNTERS; }
 	"quotas"		{ return QUOTAS; }
+	"rules"			{ return RULES; }
 }
 
 "log"			{ scanner_push_start_cond(yyscanner, SCANSTATE_STMT_LOG); return LOG; }
diff --git a/tests/shell/testcases/rule_management/0011reset_0 b/tests/shell/testcases/rule_management/0011reset_0
new file mode 100755
index 0000000000000..1a28b49fa8a75
--- /dev/null
+++ b/tests/shell/testcases/rule_management/0011reset_0
@@ -0,0 +1,168 @@
+#!/bin/sh
+
+set -e
+
+echo "loading ruleset"
+$NFT -f - <<EOF
+table ip t {
+	set s {
+		type ipv4_addr
+		counter
+		elements = { 1.1.1.1 counter packets 1 bytes 11 }
+	}
+	chain c {
+		counter packets 1 bytes 11 update @s { ip saddr } accept
+		counter packets 2 bytes 12 drop
+	}
+
+	chain c2 {
+		counter packets 3 bytes 13 accept
+		counter packets 4 bytes 14 drop
+	}
+}
+table inet t {
+	chain c {
+		counter packets 5 bytes 15 accept
+		counter packets 6 bytes 16 drop
+	}
+}
+table ip t2 {
+	chain c2 {
+		counter packets 7 bytes 17 accept
+		counter packets 8 bytes 18 drop
+	}
+}
+EOF
+
+echo "resetting specific rule"
+handle=$($NFT -a list chain t c | sed -n 's/.*accept # handle \([0-9]*\)$/\1/p')
+$NFT reset rule t c handle $handle
+EXPECT='table ip t {
+	set s {
+		type ipv4_addr
+		size 65535
+		flags dynamic
+		counter
+		elements = { 1.1.1.1 counter packets 1 bytes 11 }
+	}
+
+	chain c {
+		counter packets 0 bytes 0 update @s { ip saddr } accept
+		counter packets 2 bytes 12 drop
+	}
+
+	chain c2 {
+		counter packets 3 bytes 13 accept
+		counter packets 4 bytes 14 drop
+	}
+}
+table inet t {
+	chain c {
+		counter packets 5 bytes 15 accept
+		counter packets 6 bytes 16 drop
+	}
+}
+table ip t2 {
+	chain c2 {
+		counter packets 7 bytes 17 accept
+		counter packets 8 bytes 18 drop
+	}
+}'
+$DIFF -u <(echo "$EXPECT") <($NFT list ruleset)
+
+echo "resetting specific chain"
+EXPECT='table ip t {
+	set s {
+		type ipv4_addr
+		size 65535
+		flags dynamic
+		counter
+	}
+
+	chain c2 {
+		counter packets 3 bytes 13 accept
+		counter packets 4 bytes 14 drop
+	}
+}'
+$DIFF -u <(echo "$EXPECT") <($NFT reset rules chain t c2)
+
+echo "resetting specific table"
+EXPECT='table ip t {
+	set s {
+		type ipv4_addr
+		size 65535
+		flags dynamic
+		counter
+	}
+
+	chain c {
+		counter packets 0 bytes 0 update @s { ip saddr } accept
+		counter packets 2 bytes 12 drop
+	}
+
+	chain c2 {
+		counter packets 0 bytes 0 accept
+		counter packets 0 bytes 0 drop
+	}
+}'
+$DIFF -u <(echo "$EXPECT") <($NFT reset rules table t)
+
+echo "resetting specific family"
+EXPECT='table ip t {
+	set s {
+		type ipv4_addr
+		size 65535
+		flags dynamic
+		counter
+	}
+
+	chain c {
+		counter packets 0 bytes 0 update @s { ip saddr } accept
+		counter packets 0 bytes 0 drop
+	}
+
+	chain c2 {
+		counter packets 0 bytes 0 accept
+		counter packets 0 bytes 0 drop
+	}
+}
+table ip t2 {
+	chain c2 {
+		counter packets 7 bytes 17 accept
+		counter packets 8 bytes 18 drop
+	}
+}'
+$DIFF -u <(echo "$EXPECT") <($NFT reset rules ip)
+
+echo "resetting whole ruleset"
+EXPECT='table ip t {
+	set s {
+		type ipv4_addr
+		size 65535
+		flags dynamic
+		counter
+	}
+
+	chain c {
+		counter packets 0 bytes 0 update @s { ip saddr } accept
+		counter packets 0 bytes 0 drop
+	}
+
+	chain c2 {
+		counter packets 0 bytes 0 accept
+		counter packets 0 bytes 0 drop
+	}
+}
+table inet t {
+	chain c {
+		counter packets 5 bytes 15 accept
+		counter packets 6 bytes 16 drop
+	}
+}
+table ip t2 {
+	chain c2 {
+		counter packets 0 bytes 0 accept
+		counter packets 0 bytes 0 drop
+	}
+}'
+$DIFF -u <(echo "$EXPECT") <($NFT reset rules)
diff --git a/tests/shell/testcases/rule_management/dumps/0011reset_0.nft b/tests/shell/testcases/rule_management/dumps/0011reset_0.nft
new file mode 100644
index 0000000000000..3b4f5a11a96ee
--- /dev/null
+++ b/tests/shell/testcases/rule_management/dumps/0011reset_0.nft
@@ -0,0 +1,31 @@
+table ip t {
+	set s {
+		type ipv4_addr
+		size 65535
+		flags dynamic
+		counter
+		elements = { 1.1.1.1 counter packets 1 bytes 11 }
+	}
+
+	chain c {
+		counter packets 0 bytes 0 update @s { ip saddr } accept
+		counter packets 0 bytes 0 drop
+	}
+
+	chain c2 {
+		counter packets 0 bytes 0 accept
+		counter packets 0 bytes 0 drop
+	}
+}
+table inet t {
+	chain c {
+		counter packets 0 bytes 0 accept
+		counter packets 0 bytes 0 drop
+	}
+}
+table ip t2 {
+	chain c2 {
+		counter packets 0 bytes 0 accept
+		counter packets 0 bytes 0 drop
+	}
+}
-- 
2.38.0


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

* Re: [nft PATCH v4] Implement 'reset rule' and 'reset rules' commands
  2023-01-17 17:33 [nft PATCH v4] Implement 'reset rule' and 'reset rules' commands Phil Sutter
@ 2023-01-18 11:52 ` Pablo Neira Ayuso
  2023-01-18 13:59 ` Phil Sutter
  1 sibling, 0 replies; 3+ messages in thread
From: Pablo Neira Ayuso @ 2023-01-18 11:52 UTC (permalink / raw)
  To: Phil Sutter; +Cc: netfilter-devel

On Tue, Jan 17, 2023 at 06:33:10PM +0100, Phil Sutter wrote:
> Reset rule counters and quotas in kernel, i.e. without having to reload
> them. Requires respective kernel patch to support NFT_MSG_GETRULE_RESET
> message type.

LGTM.

As said, there will be time to explore better integration with the
cache to address the EINTR issue and this kernel code can start being
exercise with some userspace.

Thanks.

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

* Re: [nft PATCH v4] Implement 'reset rule' and 'reset rules' commands
  2023-01-17 17:33 [nft PATCH v4] Implement 'reset rule' and 'reset rules' commands Phil Sutter
  2023-01-18 11:52 ` Pablo Neira Ayuso
@ 2023-01-18 13:59 ` Phil Sutter
  1 sibling, 0 replies; 3+ messages in thread
From: Phil Sutter @ 2023-01-18 13:59 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

On Tue, Jan 17, 2023 at 06:33:10PM +0100, Phil Sutter wrote:
> Reset rule counters and quotas in kernel, i.e. without having to reload
> them. Requires respective kernel patch to support NFT_MSG_GETRULE_RESET
> message type.
> 
> Signed-off-by: Phil Sutter <phil@nwl.cc>

Patch applied.

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

end of thread, other threads:[~2023-01-18 14:19 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-01-17 17:33 [nft PATCH v4] Implement 'reset rule' and 'reset rules' commands Phil Sutter
2023-01-18 11:52 ` Pablo Neira Ayuso
2023-01-18 13:59 ` Phil Sutter

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).