]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
Implement 'reset rule' and 'reset rules' commands
authorPhil Sutter <phil@nwl.cc>
Fri, 14 Oct 2022 21:19:22 +0000 (23:19 +0200)
committerPhil Sutter <phil@nwl.cc>
Wed, 18 Jan 2023 13:58:48 +0000 (14:58 +0100)
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>
18 files changed:
doc/libnftables-json.adoc
doc/nft.txt
include/cache.h
include/linux/netfilter/nf_tables.h
include/mnl.h
include/netlink.h
include/rule.h
src/cache.c
src/evaluate.c
src/json.c
src/mnl.c
src/netlink.c
src/parser_bison.y
src/parser_json.c
src/rule.c
src/scanner.l
tests/shell/testcases/rule_management/0011reset_0 [new file with mode: 0755]
tests/shell/testcases/rule_management/dumps/0011reset_0.nft [new file with mode: 0644]

index d985149a0af357680ae9ce5835768974a9dadcb1..f4aea36eb57113f17519961aeb2ae2f72e778412 100644 (file)
@@ -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.
index eb8df1d95e53ad3a0815087c229c4efd21abf98e..18c18468c31b0bce8865092227e69e96970699ce 100644 (file)
@@ -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*
 -------------
index 575381ef971bc360c1ac716075a5b8abe92e8df0..5bf78fe0255016838e8b5f69eb0731fc66b728be 100644 (file)
@@ -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_ */
index e4b739d57480a51d20a9932da78cb5a15177576d..3d045030e3ad3f2418cddb222433cdc61a1f1644 100644 (file)
@@ -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,
 };
 
index 8e0a7e3fccab9e0f7e101b0505f95e7c517c9f1c..c06766912539507c31290a439f64b8d31a738696 100644 (file)
@@ -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);
index 5a7f6a1e28ef3ad8c40dea3ed56e8edc4857d63f..0d97f71ccff37729188a98dce4d0f41e1419f621 100644 (file)
@@ -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,
index d829f484a9afa3e774c869d2d0a51dec60734541..22c611f6068f3afbe2728c5d7a9b56414ec3ed7d 100644 (file)
@@ -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,
index 85de970f76448ff7e25657eafae07c4c4533a81f..0f5d1099f1027767f3367238e5b0763969fe68b8 100644 (file)
@@ -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);
index 21de18409c8734f072b79d8d919d0160b844f1d9..61ebcbfc81cf729c905375b2b2b7e41f8b97ccce 100644 (file)
@@ -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,
index f57f2f77f48ec0b723df2f2110aa80c89227467d..f15461d33894c1c26f7065df241eb3c27e7e5731 100644 (file)
@@ -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;
index 46d86f0fd9502df3f3ad8c3c8efc618ed5a3765b..ca01516ca72a2c0785ec840111c380b1cef1d34a 100644 (file)
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -654,13 +654,21 @@ err_free:
 }
 
 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);
index efae125148b8c3b0f445825f5526c57818d9a765..f1452d48f42401f361cb3a352089b38c7fcf4184 100644 (file)
@@ -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)
index ccf07a30fbfc5e0e35d19eeadb07fd10a0bc8790..62a4809b9ee7e7c09d898e19ba41dd149e7a4fa5 100644 (file)
@@ -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
index ae683314243515c3fca83461688bd68e938ad67b..dfab3f9cbc7d3e5fca263d92b4bed4d177c969e8 100644 (file)
@@ -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;
index 903c01f53825a43d21a1c5ceeff9111407d209bd..371c803a57c6067695d822bd86d8fa18b9c71795 100644 (file)
@@ -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);
        }
index 9c85ee3769bc9bfba78ca24479f66443a71649b0..aa0a0a9f94fdf62860fae219c23abadd237ab0be 100644 (file)
@@ -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 (executable)
index 0000000..1a28b49
--- /dev/null
@@ -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 (file)
index 0000000..3b4f5a1
--- /dev/null
@@ -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
+       }
+}