The sets constructed for meters are flagged as anonymous and dynamic.
However, in some places there are only checks that they are dynamic,
which can lead to normal sets being classified as meters.
For example:
# nft add table t
# nft add set t s { type ipv4_addr; size 256; flags dynamic,timeout; }
# nft add chain t c
# nft add rule t c tcp dport 80 meter m size 128 { ip saddr limit rate 10/second }
# nft list meters
table ip t {
set s {
type ipv4_addr
size 256
flags dynamic,timeout
}
meter m {
type ipv4_addr
size 128
flags dynamic
}
}
# nft list meter t m
table ip t {
meter m {
type ipv4_addr
size 128
flags dynamic
}
}
# nft list meter t s
Error: No such file or directory
list meter t s
^
Add a new helper `set_is_meter` and use it wherever there are checks for
meters.
Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
return !(set_is_anonymous(set_flags) || !set_is_map(set_flags));
}
+static inline bool set_is_meter(uint32_t set_flags)
+{
+ return set_is_anonymous(set_flags) && (set_flags & NFT_SET_EVAL);
+}
+
#include <statement.h>
struct counter {
if (set == NULL)
return set_not_found(ctx, &ctx->cmd->handle.set.location,
ctx->cmd->handle.set.name);
- else if (!(set->flags & NFT_SET_EVAL) ||
- !(set->flags & NFT_SET_ANONYMOUS))
+ else if (!set_is_meter(set->flags))
return cmd_error(ctx, &ctx->cmd->handle.set.location,
"%s", strerror(ENOENT));
if (set == NULL)
return set_not_found(ctx, &ctx->cmd->handle.set.location,
ctx->cmd->handle.set.name);
- else if (!(set->flags & NFT_SET_EVAL) ||
- !(set->flags & NFT_SET_ANONYMOUS))
+ else if (!set_is_meter(set->flags))
return cmd_error(ctx, &ctx->cmd->handle.set.location,
"%s", strerror(ENOENT));
static void set_ref_expr_print(const struct expr *expr, struct output_ctx *octx)
{
- if (set_is_anonymous(expr->set->flags)) {
- if (expr->set->flags & NFT_SET_EVAL)
- nft_print(octx, "%s", expr->set->handle.set.name);
- else
- expr_print(expr->set->init, octx);
- } else {
+ if (set_is_meter(expr->set->flags))
+ nft_print(octx, "%s", expr->set->handle.set.name);
+ else if (set_is_anonymous(expr->set->flags))
+ expr_print(expr->set->init, octx);
+ else
nft_print(octx, "@%s", expr->set->handle.set.name);
- }
}
static void set_ref_expr_clone(struct expr *new, const struct expr *expr)
} else if (set_is_objmap(set->flags)) {
type = "map";
datatype_ext = obj_type_name(set->objtype);
- } else if (set->flags & NFT_SET_EVAL) {
+ } else if (set_is_meter(set->flags)) {
type = "meter";
} else {
type = "set";
!set_is_literal(set->flags))
continue;
if (cmd->obj == CMD_OBJ_METERS &&
- !(set->flags & NFT_SET_EVAL))
+ !set_is_meter(set->flags))
continue;
if (cmd->obj == CMD_OBJ_MAPS &&
!map_is_literal(set->flags))
const char *type;
uint32_t flags;
- if ((set->flags & (NFT_SET_EVAL | NFT_SET_ANONYMOUS)) ==
- (NFT_SET_EVAL | NFT_SET_ANONYMOUS))
+ if (set_is_meter(set->flags))
type = "meter";
else if (set_is_map(set->flags))
type = "map";
}
static void do_set_print(const struct set *set, struct print_fmt_options *opts,
- struct output_ctx *octx)
+ struct output_ctx *octx)
{
set_print_declaration(set, opts, octx);
- if ((set->flags & NFT_SET_EVAL && nft_output_stateless(octx)) ||
+ if ((set_is_meter(set->flags) && nft_output_stateless(octx)) ||
nft_output_terse(octx)) {
nft_print(octx, "%s}%s", opts->tab, opts->nl);
return;
!set_is_literal(set->flags))
continue;
if (cmd->obj == CMD_OBJ_METERS &&
- !(set->flags & NFT_SET_EVAL))
+ !set_is_meter(set->flags))
continue;
if (cmd->obj == CMD_OBJ_MAPS &&
!map_is_literal(set->flags))
--- /dev/null
+#!/bin/bash
+
+#
+# Listing meters should not include dynamic sets in the output
+#
+
+set -e
+
+RULESET="
+ add table t
+ add set t s { type ipv4_addr; size 256; flags dynamic,timeout; }
+ add chain t c
+ add rule t c tcp dport 80 meter m size 128 { ip saddr limit rate 10/second }
+"
+
+expected_output="table ip t {
+ meter m {
+ type ipv4_addr
+ size 128
+ flags dynamic
+ }
+}"
+
+$NFT -f - <<< "$RULESET"
+
+test_output=$($NFT list meters)
+
+test "$test_output" = "$expected_output"
+