* [nft PATCH 0/3] Implement 'reset {set,map,element}' commands
@ 2023-06-15 14:44 Phil Sutter
2023-06-15 14:44 ` [nft PATCH 1/3] evaluate: Merge some cases in cmd_evaluate_list() Phil Sutter
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Phil Sutter @ 2023-06-15 14:44 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel
This series makes use of the new NFT_MSG_GETSETELEM_RESET message type
to reset state in set elements.
Patches one and two are fallout from working on the actual
implementation in patch three.
Phil Sutter (3):
evaluate: Merge some cases in cmd_evaluate_list()
evaluate: Cache looked up set for list commands
Implement 'reset {set,map,element}' commands
doc/libnftables-json.adoc | 2 +-
doc/nft.txt | 13 ++--
include/linux/netfilter/nf_tables.h | 2 +
include/mnl.h | 6 +-
include/netlink.h | 5 +-
src/cache.c | 9 ++-
src/evaluate.c | 42 +++--------
src/json.c | 9 ++-
src/mnl.c | 22 ++++--
src/netlink.c | 8 +--
src/parser_bison.y | 12 ++++
src/parser_json.c | 4 ++
src/rule.c | 27 +++++--
tests/shell/testcases/sets/reset_command_0 | 82 ++++++++++++++++++++++
14 files changed, 181 insertions(+), 62 deletions(-)
create mode 100755 tests/shell/testcases/sets/reset_command_0
--
2.40.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [nft PATCH 1/3] evaluate: Merge some cases in cmd_evaluate_list()
2023-06-15 14:44 [nft PATCH 0/3] Implement 'reset {set,map,element}' commands Phil Sutter
@ 2023-06-15 14:44 ` Phil Sutter
2023-06-15 14:44 ` [nft PATCH 2/3] evaluate: Cache looked up set for list commands Phil Sutter
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Phil Sutter @ 2023-06-15 14:44 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel
The code for set, map and meter were almost identical apart from the
specific last check. Fold them together and make the distinction in that
spot only.
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
src/evaluate.c | 36 ++++--------------------------------
1 file changed, 4 insertions(+), 32 deletions(-)
diff --git a/src/evaluate.c b/src/evaluate.c
index 00bb8988bd4c9..3983fcaa35880 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -5337,38 +5337,8 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
return 0;
case CMD_OBJ_SET:
- table = table_cache_find(&ctx->nft->cache.table_cache,
- cmd->handle.table.name,
- cmd->handle.family);
- if (!table)
- return table_not_found(ctx);
-
- set = set_cache_find(table, cmd->handle.set.name);
- if (set == NULL)
- return set_not_found(ctx, &ctx->cmd->handle.set.location,
- ctx->cmd->handle.set.name);
- else if (!set_is_literal(set->flags))
- return cmd_error(ctx, &ctx->cmd->handle.set.location,
- "%s", strerror(ENOENT));
-
- return 0;
- case CMD_OBJ_METER:
- table = table_cache_find(&ctx->nft->cache.table_cache,
- cmd->handle.table.name,
- cmd->handle.family);
- if (!table)
- return table_not_found(ctx);
-
- set = set_cache_find(table, cmd->handle.set.name);
- if (set == NULL)
- return set_not_found(ctx, &ctx->cmd->handle.set.location,
- ctx->cmd->handle.set.name);
- else if (!set_is_meter(set->flags))
- return cmd_error(ctx, &ctx->cmd->handle.set.location,
- "%s", strerror(ENOENT));
-
- return 0;
case CMD_OBJ_MAP:
+ case CMD_OBJ_METER:
table = table_cache_find(&ctx->nft->cache.table_cache,
cmd->handle.table.name,
cmd->handle.family);
@@ -5379,7 +5349,9 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
if (set == NULL)
return set_not_found(ctx, &ctx->cmd->handle.set.location,
ctx->cmd->handle.set.name);
- else if (!map_is_literal(set->flags))
+ if ((cmd->obj == CMD_OBJ_SET && !set_is_literal(set->flags)) ||
+ (cmd->obj == CMD_OBJ_MAP && !map_is_literal(set->flags)) ||
+ (cmd->obj == CMD_OBJ_METER && !set_is_meter(set->flags)))
return cmd_error(ctx, &ctx->cmd->handle.set.location,
"%s", strerror(ENOENT));
--
2.40.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [nft PATCH 2/3] evaluate: Cache looked up set for list commands
2023-06-15 14:44 [nft PATCH 0/3] Implement 'reset {set,map,element}' commands Phil Sutter
2023-06-15 14:44 ` [nft PATCH 1/3] evaluate: Merge some cases in cmd_evaluate_list() Phil Sutter
@ 2023-06-15 14:44 ` Phil Sutter
2023-06-15 14:44 ` [nft PATCH 3/3] Implement 'reset {set,map,element}' commands Phil Sutter
2023-07-13 15:12 ` [nft PATCH 0/3] " Phil Sutter
3 siblings, 0 replies; 5+ messages in thread
From: Phil Sutter @ 2023-06-15 14:44 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel
Evaluation phase checks the given table and set exist in cache. Relieve
execution phase from having to perform the lookup again by storing the
set reference in cmd->set. Just have to increase the ref counter so
cmd_free() does the right thing (which lacked handling of MAP and METER
objects for some reason).
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
src/evaluate.c | 1 +
src/json.c | 9 ++++++---
src/rule.c | 12 ++++++++----
3 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/src/evaluate.c b/src/evaluate.c
index 3983fcaa35880..af7c273c3a0b2 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -5355,6 +5355,7 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
return cmd_error(ctx, &ctx->cmd->handle.set.location,
"%s", strerror(ENOENT));
+ cmd->set = set_get(set);
return 0;
case CMD_OBJ_CHAIN:
table = table_cache_find(&ctx->nft->cache.table_cache,
diff --git a/src/json.c b/src/json.c
index 981d177b75d4f..12eac36edba93 100644
--- a/src/json.c
+++ b/src/json.c
@@ -1783,10 +1783,13 @@ static json_t *do_list_chains_json(struct netlink_ctx *ctx, struct cmd *cmd)
static json_t *do_list_set_json(struct netlink_ctx *ctx,
struct cmd *cmd, struct table *table)
{
- struct set *set = set_cache_find(table, cmd->handle.set.name);
+ struct set *set = cmd->set;
- if (set == NULL)
- return json_null();
+ if (!set) {
+ set = set_cache_find(table, cmd->handle.set.name);
+ if (set == NULL)
+ return json_null();
+ }
return json_pack("[o]", set_print_json(&ctx->nft->output, set));
}
diff --git a/src/rule.c b/src/rule.c
index 633a5a12486d0..900352d25d6d4 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -1356,6 +1356,8 @@ void cmd_free(struct cmd *cmd)
set_free(cmd->elem.set);
break;
case CMD_OBJ_SET:
+ case CMD_OBJ_MAP:
+ case CMD_OBJ_METER:
case CMD_OBJ_SETELEMS:
set_free(cmd->set);
break;
@@ -2289,11 +2291,13 @@ static void __do_list_set(struct netlink_ctx *ctx, struct cmd *cmd,
static int do_list_set(struct netlink_ctx *ctx, struct cmd *cmd,
struct table *table)
{
- struct set *set;
+ struct set *set = cmd->set;
- set = set_cache_find(table, cmd->handle.set.name);
- if (set == NULL)
- return -1;
+ if (!set) {
+ set = set_cache_find(table, cmd->handle.set.name);
+ if (set == NULL)
+ return -1;
+ }
__do_list_set(ctx, cmd, set);
--
2.40.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [nft PATCH 3/3] Implement 'reset {set,map,element}' commands
2023-06-15 14:44 [nft PATCH 0/3] Implement 'reset {set,map,element}' commands Phil Sutter
2023-06-15 14:44 ` [nft PATCH 1/3] evaluate: Merge some cases in cmd_evaluate_list() Phil Sutter
2023-06-15 14:44 ` [nft PATCH 2/3] evaluate: Cache looked up set for list commands Phil Sutter
@ 2023-06-15 14:44 ` Phil Sutter
2023-07-13 15:12 ` [nft PATCH 0/3] " Phil Sutter
3 siblings, 0 replies; 5+ messages in thread
From: Phil Sutter @ 2023-06-15 14:44 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel
All these are used to reset state in set/map elements, i.e. reset the
timeout or zero quota and counter values.
While 'reset element' expects a (list of) elements to be specified which
should be reset, 'reset set/map' will reset all elements in the given
set/map.
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
doc/libnftables-json.adoc | 2 +-
doc/nft.txt | 13 ++--
include/linux/netfilter/nf_tables.h | 2 +
include/mnl.h | 6 +-
include/netlink.h | 5 +-
src/cache.c | 9 ++-
src/evaluate.c | 5 ++
src/mnl.c | 22 ++++--
src/netlink.c | 8 +--
src/parser_bison.y | 12 ++++
src/parser_json.c | 4 ++
src/rule.c | 15 +++-
tests/shell/testcases/sets/reset_command_0 | 82 ++++++++++++++++++++++
13 files changed, 162 insertions(+), 23 deletions(-)
create mode 100755 tests/shell/testcases/sets/reset_command_0
diff --git a/doc/libnftables-json.adoc b/doc/libnftables-json.adoc
index f9288487e4b25..3e6e1db381d8f 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' | 'RULE' | 'RULES'
+'RESET_OBJECT' := 'COUNTER' | 'COUNTERS' | 'QUOTA' | 'QUOTAS' | 'RULE' | 'RULES' | 'SET' | 'MAP' | 'ELEMENT'
____
Reset state in suitable objects, i.e. zero their internal counter.
diff --git a/doc/nft.txt b/doc/nft.txt
index 19ba55d965055..fe123d04f9b95 100644
--- a/doc/nft.txt
+++ b/doc/nft.txt
@@ -570,7 +570,7 @@ section describes nft set syntax in more detail.
[verse]
*add set* ['family'] 'table' 'set' *{ type* 'type' | *typeof* 'expression' *;* [*flags* 'flags' *;*] [*timeout* 'timeout' *;*] [*gc-interval* 'gc-interval' *;*] [*elements = {* 'element'[*,* ...] *} ;*] [*size* 'size' *;*] [*comment* 'comment' *;*'] [*policy* 'policy' *;*] [*auto-merge ;*] *}*
-{*delete* | *destroy* | *list* | *flush*} *set* ['family'] 'table' 'set'
+{*delete* | *destroy* | *list* | *flush* | *reset* } *set* ['family'] 'table' 'set'
*list sets* ['family']
*delete set* ['family'] 'table' *handle* 'handle'
{*add* | *delete* | *destroy* } *element* ['family'] 'table' 'set' *{* 'element'[*,* ...] *}*
@@ -585,6 +585,7 @@ be tuned with the flags that can be specified at set creation time.
*destroy*:: Delete the specified set, it does not fail if it does not exist.
*list*:: Display the elements in the specified set.
*flush*:: Remove all elements from the specified set.
+*reset*:: Reset timeout and other state in all contained elements.
.Set specifications
[options="header"]
@@ -623,7 +624,7 @@ MAPS
-----
[verse]
*add map* ['family'] 'table' 'map' *{ type* 'type' | *typeof* 'expression' [*flags* 'flags' *;*] [*elements = {* 'element'[*,* ...] *} ;*] [*size* 'size' *;*] [*comment* 'comment' *;*'] [*policy* 'policy' *;*] *}*
-{*delete* | *destroy* | *list* | *flush*} *map* ['family'] 'table' 'map'
+{*delete* | *destroy* | *list* | *flush* | *reset* } *map* ['family'] 'table' 'map'
*list maps* ['family']
Maps store data based on some specific key used as input. They are uniquely identified by a user-defined name and attached to tables.
@@ -634,8 +635,7 @@ Maps store data based on some specific key used as input. They are uniquely iden
*destroy*:: Delete the specified map, it does not fail if it does not exist.
*list*:: Display the elements in the specified map.
*flush*:: Remove all elements from the specified map.
-*add element*:: Comma-separated list of elements to add into the specified map.
-*delete element*:: Comma-separated list of element keys to delete from the specified map.
+*reset*:: Reset timeout and other state in all contained elements.
.Map specifications
[options="header"]
@@ -682,7 +682,7 @@ ELEMENTS
--------
[verse]
____
-{*add* | *create* | *delete* | *destroy* | *get* } *element* ['family'] 'table' 'set' *{* 'ELEMENT'[*,* ...] *}*
+{*add* | *create* | *delete* | *destroy* | *get* | *reset* } *element* ['family'] 'table' 'set' *{* 'ELEMENT'[*,* ...] *}*
'ELEMENT' := 'key_expression' 'OPTIONS' [*:* 'value_expression']
'OPTIONS' := [*timeout* 'TIMESPEC'] [*expires* 'TIMESPEC'] [*comment* 'string']
@@ -702,6 +702,9 @@ listed elements may already exist.
be non-trivial in very large and/or interval sets. In the latter case, the
containing interval is returned instead of just the element itself.
+*reset* command resets timeout or other state attached to the given
+element(s).
+
.Element options
[options="header"]
|=================
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 673e05073de82..c62e6ac563988 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -105,6 +105,7 @@ enum nft_verdicts {
* @NFT_MSG_DESTROYSETELEM: destroy a set element (enum nft_set_elem_attributes)
* @NFT_MSG_DESTROYOBJ: destroy a stateful object (enum nft_object_attributes)
* @NFT_MSG_DESTROYFLOWTABLE: destroy flow table (enum nft_flowtable_attributes)
+ * @NFT_MSG_GETSETELEM_RESET: get set elements and reset attached stateful expressio ns (enum nft_set_elem_attributes)
*/
enum nf_tables_msg_types {
NFT_MSG_NEWTABLE,
@@ -140,6 +141,7 @@ enum nf_tables_msg_types {
NFT_MSG_DESTROYSETELEM,
NFT_MSG_DESTROYOBJ,
NFT_MSG_DESTROYFLOWTABLE,
+ NFT_MSG_GETSETELEM_RESET,
NFT_MSG_MAX,
};
diff --git a/include/mnl.h b/include/mnl.h
index c067669125395..cd5a2053b1661 100644
--- a/include/mnl.h
+++ b/include/mnl.h
@@ -68,9 +68,11 @@ int mnl_nft_setelem_add(struct netlink_ctx *ctx, struct cmd *cmd,
int mnl_nft_setelem_del(struct netlink_ctx *ctx, struct cmd *cmd,
const struct handle *h, const struct expr *init);
int mnl_nft_setelem_flush(struct netlink_ctx *ctx, const struct cmd *cmd);
-int mnl_nft_setelem_get(struct netlink_ctx *ctx, struct nftnl_set *nls);
+int mnl_nft_setelem_get(struct netlink_ctx *ctx, struct nftnl_set *nls,
+ bool reset);
struct nftnl_set *mnl_nft_setelem_get_one(struct netlink_ctx *ctx,
- struct nftnl_set *nls);
+ struct nftnl_set *nls,
+ bool reset);
struct nftnl_obj_list *mnl_nft_obj_dump(struct netlink_ctx *ctx, int family,
const char *table,
diff --git a/include/netlink.h b/include/netlink.h
index d52434c72bc2c..6766d7e8563fe 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -165,10 +165,11 @@ extern struct stmt *netlink_parse_set_expr(const struct set *set,
const struct nftnl_expr *nle);
extern int netlink_list_setelems(struct netlink_ctx *ctx,
- const struct handle *h, struct set *set);
+ const struct handle *h, struct set *set,
+ bool reset);
extern int netlink_get_setelem(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc, struct set *cache_set,
- struct set *set, struct expr *init);
+ struct set *set, struct expr *init, bool reset);
extern int netlink_delinearize_setelem(struct nftnl_set_elem *nlse,
struct set *set,
struct nft_cache *cache);
diff --git a/src/cache.c b/src/cache.c
index 95adee7f8ac17..2dae94183bd80 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -280,6 +280,11 @@ static unsigned int evaluate_cache_reset(struct cmd *cmd, unsigned int flags,
flags |= NFT_CACHE_SET | NFT_CACHE_FLOWTABLE |
NFT_CACHE_OBJECT | NFT_CACHE_CHAIN;
break;
+ case CMD_OBJ_ELEMENTS:
+ case CMD_OBJ_SET:
+ case CMD_OBJ_MAP:
+ flags |= NFT_CACHE_SET;
+ break;
default:
flags |= NFT_CACHE_TABLE;
break;
@@ -1066,7 +1071,7 @@ static int cache_init_objects(struct netlink_ctx *ctx, unsigned int flags,
continue;
ret = netlink_list_setelems(ctx, &set->handle,
- set);
+ set, false);
if (ret < 0)
goto cache_fails;
}
@@ -1079,7 +1084,7 @@ static int cache_init_objects(struct netlink_ctx *ctx, unsigned int flags,
continue;
ret = netlink_list_setelems(ctx, &set->handle,
- set);
+ set, false);
if (ret < 0)
goto cache_fails;
}
diff --git a/src/evaluate.c b/src/evaluate.c
index af7c273c3a0b2..14927ac0bef60 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -5450,6 +5450,11 @@ static int cmd_evaluate_reset(struct eval_ctx *ctx, struct cmd *cmd)
return table_not_found(ctx);
return 0;
+ case CMD_OBJ_ELEMENTS:
+ return setelem_evaluate(ctx, cmd);
+ case CMD_OBJ_SET:
+ case CMD_OBJ_MAP:
+ return cmd_evaluate_list(ctx, cmd);
default:
BUG("invalid command object type %u\n", cmd->obj);
}
diff --git a/src/mnl.c b/src/mnl.c
index 91775c41b2461..9406fc4821236 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -1870,14 +1870,21 @@ int mnl_nft_setelem_del(struct netlink_ctx *ctx, struct cmd *cmd,
}
struct nftnl_set *mnl_nft_setelem_get_one(struct netlink_ctx *ctx,
- struct nftnl_set *nls_in)
+ struct nftnl_set *nls_in,
+ bool reset)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nftnl_set *nls_out;
struct nlmsghdr *nlh;
+ int msg_type;
int err;
- nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETSETELEM,
+ if (reset)
+ msg_type = NFT_MSG_GETSETELEM_RESET;
+ else
+ msg_type = NFT_MSG_GETSETELEM;
+
+ nlh = nftnl_nlmsg_build_hdr(buf, msg_type,
nftnl_set_get_u32(nls_in, NFTNL_SET_FAMILY),
NLM_F_ACK, ctx->seqnum);
nftnl_set_elems_nlmsg_build_payload(nlh, nls_in);
@@ -1900,12 +1907,19 @@ struct nftnl_set *mnl_nft_setelem_get_one(struct netlink_ctx *ctx,
return nls_out;
}
-int mnl_nft_setelem_get(struct netlink_ctx *ctx, struct nftnl_set *nls)
+int mnl_nft_setelem_get(struct netlink_ctx *ctx, struct nftnl_set *nls,
+ bool reset)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
+ int msg_type;
+
+ if (reset)
+ msg_type = NFT_MSG_GETSETELEM_RESET;
+ else
+ msg_type = NFT_MSG_GETSETELEM;
- nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETSETELEM,
+ nlh = nftnl_nlmsg_build_hdr(buf, msg_type,
nftnl_set_get_u32(nls, NFTNL_SET_FAMILY),
NLM_F_DUMP, ctx->seqnum);
nftnl_set_elems_nlmsg_build_payload(nlh, nls);
diff --git a/src/netlink.c b/src/netlink.c
index 3352ad0abb610..ed61cd896511a 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -1515,7 +1515,7 @@ static int list_setelements(struct nftnl_set *s, struct netlink_ctx *ctx)
}
int netlink_list_setelems(struct netlink_ctx *ctx, const struct handle *h,
- struct set *set)
+ struct set *set, bool reset)
{
struct nftnl_set *nls;
int err;
@@ -1530,7 +1530,7 @@ int netlink_list_setelems(struct netlink_ctx *ctx, const struct handle *h,
if (h->handle.id)
nftnl_set_set_u64(nls, NFTNL_SET_HANDLE, h->handle.id);
- err = mnl_nft_setelem_get(ctx, nls);
+ err = mnl_nft_setelem_get(ctx, nls, reset);
if (err < 0) {
nftnl_set_free(nls);
if (errno == EINTR)
@@ -1558,7 +1558,7 @@ int netlink_list_setelems(struct netlink_ctx *ctx, const struct handle *h,
int netlink_get_setelem(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc, struct set *cache_set,
- struct set *set, struct expr *init)
+ struct set *set, struct expr *init, bool reset)
{
struct nftnl_set *nls, *nls_out = NULL;
int err = 0;
@@ -1577,7 +1577,7 @@ int netlink_get_setelem(struct netlink_ctx *ctx, const struct handle *h,
netlink_dump_set(nls, ctx);
- nls_out = mnl_nft_setelem_get_one(ctx, nls);
+ nls_out = mnl_nft_setelem_get_one(ctx, nls, reset);
if (!nls_out) {
nftnl_set_free(nls);
return -1;
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 763c1b2dcd612..979deab88470c 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -1716,6 +1716,18 @@ reset_cmd : COUNTERS ruleset_spec
{
$$ = cmd_alloc(CMD_RESET, CMD_OBJ_RULE, &$2, &@$, NULL);
}
+ | ELEMENT set_spec set_block_expr
+ {
+ $$ = cmd_alloc(CMD_RESET, CMD_OBJ_ELEMENTS, &$2, &@$, $3);
+ }
+ | SET set_or_id_spec
+ {
+ $$ = cmd_alloc(CMD_RESET, CMD_OBJ_SET, &$2, &@$, NULL);
+ }
+ | MAP set_or_id_spec
+ {
+ $$ = cmd_alloc(CMD_RESET, CMD_OBJ_MAP, &$2, &@$, NULL);
+ }
;
flush_cmd : TABLE table_spec
diff --git a/src/parser_json.c b/src/parser_json.c
index f1cc39505382c..6ac2d11a1a800 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -3099,6 +3099,7 @@ static struct cmd *json_parse_cmd_add_set(struct json_ctx *ctx, json_t *root,
case CMD_DESTROY:
case CMD_LIST:
case CMD_FLUSH:
+ case CMD_RESET:
return cmd_alloc(op, obj, &h, int_loc, NULL);
default:
break;
@@ -3848,6 +3849,9 @@ static struct cmd *json_parse_cmd_reset(struct json_ctx *ctx,
{ "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 },
+ { "element", CMD_OBJ_ELEMENTS, json_parse_cmd_add_element },
+ { "set", CMD_OBJ_SET, json_parse_cmd_add_set },
+ { "map", CMD_OBJ_MAP, json_parse_cmd_add_set },
};
unsigned int i;
json_t *tmp;
diff --git a/src/rule.c b/src/rule.c
index 900352d25d6d4..b69855ec8b0fe 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -2386,7 +2386,7 @@ static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd)
return 0;
}
-static int do_get_setelems(struct netlink_ctx *ctx, struct cmd *cmd)
+static int do_get_setelems(struct netlink_ctx *ctx, struct cmd *cmd, bool reset)
{
struct set *set, *new_set;
struct expr *init;
@@ -2404,7 +2404,7 @@ static int do_get_setelems(struct netlink_ctx *ctx, struct cmd *cmd)
/* Fetch from kernel the elements that have been requested .*/
err = netlink_get_setelem(ctx, &cmd->handle, &cmd->location,
- cmd->elem.set, new_set, init);
+ cmd->elem.set, new_set, init, reset);
if (err >= 0)
__do_list_set(ctx, cmd, new_set);
@@ -2420,7 +2420,7 @@ static int do_command_get(struct netlink_ctx *ctx, struct cmd *cmd)
{
switch (cmd->obj) {
case CMD_OBJ_ELEMENTS:
- return do_get_setelems(ctx, cmd);
+ return do_get_setelems(ctx, cmd, false);
default:
BUG("invalid command object type %u\n", cmd->obj);
}
@@ -2457,6 +2457,15 @@ static int do_command_reset(struct netlink_ctx *ctx, struct cmd *cmd)
return do_command_list(ctx, cmd);
case CMD_OBJ_RULE:
return netlink_reset_rules(ctx, cmd, false);
+ case CMD_OBJ_ELEMENTS:
+ return do_get_setelems(ctx, cmd, true);
+ case CMD_OBJ_SET:
+ case CMD_OBJ_MAP:
+ ret = netlink_list_setelems(ctx, &cmd->handle, cmd->set, true);
+ if (ret < 0)
+ return ret;
+
+ return do_command_list(ctx, cmd);
default:
BUG("invalid command object type %u\n", cmd->obj);
}
diff --git a/tests/shell/testcases/sets/reset_command_0 b/tests/shell/testcases/sets/reset_command_0
new file mode 100755
index 0000000000000..7a088aea2c2f4
--- /dev/null
+++ b/tests/shell/testcases/sets/reset_command_0
@@ -0,0 +1,82 @@
+#!/bin/bash
+
+set -e
+set -x
+
+RULESET="table t {
+ set s {
+ type ipv4_addr . inet_proto . inet_service
+ flags interval, timeout
+ counter
+ timeout 30s
+ elements = {
+ 1.0.0.1 . udp . 53 counter packets 5 bytes 30,
+ 2.0.0.2 . tcp . 22 counter packets 10 bytes 100 timeout 15s
+ }
+ }
+ map m {
+ type ipv4_addr : ipv4_addr
+ quota 50 bytes
+ elements = {
+ 1.2.3.4 quota 50 bytes used 10 bytes : 10.2.3.4,
+ 5.6.7.8 quota 100 bytes used 50 bytes : 50.6.7.8
+ }
+ }
+}"
+
+$NFT -f - <<< "$RULESET"
+
+sleep 2
+
+drop_ms() {
+ sed 's/s[0-9]*ms/s/g'
+}
+expires_seconds() {
+ sed -n 's/.*expires \([0-9]*\)s.*/\1/p'
+}
+
+# 'reset element' output is supposed to match 'get element' one
+# apart from changing expires ms value
+EXP=$($NFT get element t s '{ 1.0.0.1 . udp . 53 }' | drop_ms)
+OUT=$($NFT reset element t s '{ 1.0.0.1 . udp . 53 }' | drop_ms)
+$DIFF -u <(echo "$EXP") <(echo "$OUT")
+
+EXP=$($NFT get element t m '{ 1.2.3.4 }')
+OUT=$($NFT reset element t m '{ 1.2.3.4 }')
+$DIFF -u <(echo "$EXP") <(echo "$OUT")
+
+# assert counter value is zeroed
+$NFT get element t s '{ 1.0.0.1 . udp . 53 }' | grep -q 'counter packets 0 bytes 0'
+
+# assert expiry is reset
+VAL=$($NFT get element t s '{ 1.0.0.1 . udp . 53 }' | expires_seconds)
+[[ $VAL -gt 28 ]]
+
+# assert quota value is reset
+$NFT get element t m '{ 1.2.3.4 }' | grep -q 'quota 50 bytes : 10.2.3.4'
+
+# assert other elements remain unchanged
+$NFT get element t s '{ 2.0.0.2 . tcp . 22 }'
+OUT=$($NFT get element t s '{ 2.0.0.2 . tcp . 22 }')
+grep -q 'counter packets 10 bytes 100 timeout 15s' <<< "$OUT"
+VAL=$(expires_seconds <<< "$OUT")
+[[ $val -lt 14 ]]
+$NFT get element t m '{ 5.6.7.8 }' | grep -q 'quota 100 bytes used 50 bytes'
+
+# 'reset set' output is supposed to match 'list set' one, again strip the ms values
+EXP=$($NFT list set t s | drop_ms)
+OUT=$($NFT reset set t s | drop_ms)
+$DIFF -u <(echo "$EXP") <(echo "$OUT")
+
+EXP=$($NFT list map t m | drop_ms)
+OUT=$($NFT reset map t m | drop_ms)
+$DIFF -u <(echo "$EXP") <(echo "$OUT")
+
+# assert expiry of element with custom timeout is correct
+VAL=$($NFT get element t s '{ 2.0.0.2 . tcp . 22 }' | expires_seconds)
+[[ $VAL -lt 15 ]]
+
+# assert remaining elements are now all reset
+OUT=$($NFT list ruleset)
+grep -q '2.0.0.2 . tcp . 22 counter packets 0 bytes 0' <<< "$OUT"
+grep -q '5.6.7.8 quota 100 bytes : 50.6.7.8' <<< "$OUT"
--
2.40.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [nft PATCH 0/3] Implement 'reset {set,map,element}' commands
2023-06-15 14:44 [nft PATCH 0/3] Implement 'reset {set,map,element}' commands Phil Sutter
` (2 preceding siblings ...)
2023-06-15 14:44 ` [nft PATCH 3/3] Implement 'reset {set,map,element}' commands Phil Sutter
@ 2023-07-13 15:12 ` Phil Sutter
3 siblings, 0 replies; 5+ messages in thread
From: Phil Sutter @ 2023-07-13 15:12 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel
On Thu, Jun 15, 2023 at 04:44:11PM +0200, Phil Sutter wrote:
> This series makes use of the new NFT_MSG_GETSETELEM_RESET message type
> to reset state in set elements.
>
> Patches one and two are fallout from working on the actual
> implementation in patch three.
Series applied.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2023-07-13 15:12 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-15 14:44 [nft PATCH 0/3] Implement 'reset {set,map,element}' commands Phil Sutter
2023-06-15 14:44 ` [nft PATCH 1/3] evaluate: Merge some cases in cmd_evaluate_list() Phil Sutter
2023-06-15 14:44 ` [nft PATCH 2/3] evaluate: Cache looked up set for list commands Phil Sutter
2023-06-15 14:44 ` [nft PATCH 3/3] Implement 'reset {set,map,element}' commands Phil Sutter
2023-07-13 15:12 ` [nft PATCH 0/3] " Phil Sutter
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.