From: Eric Jallot <ejallot@gmail.com>
To: netfilter-devel@vger.kernel.org
Cc: Eric Jallot <ejallot@gmail.com>
Subject: [PATCH nft] src: flowtable: add support for named flowtable listing
Date: Wed, 30 Oct 2019 18:06:19 +0100 [thread overview]
Message-ID: <20191030170619.45231-1-ejallot@gmail.com> (raw)
This patch allows you to dump a named flowtable.
# nft list flowtable inet t f
table inet t {
flowtable f {
hook ingress priority filter + 10
devices = { eth0, eth1 }
}
}
Also:
libnftables-json.adoc: fix missing quotes.
Fixes: db0697ce7f60 ("src: support for flowtable listing")
Fixes: 872f373dc50f ("doc: Add JSON schema documentation")
Signed-off-by: Eric Jallot <ejallot@gmail.com>
---
doc/libnftables-json.adoc | 8 ++--
include/rule.h | 12 ++++-
src/evaluate.c | 29 ++++++++++++
src/json.c | 20 ++++++++-
src/mnl.c | 4 +-
src/netlink.c | 2 +-
src/parser_bison.y | 12 +++--
src/parser_json.c | 4 +-
src/rule.c | 64 +++++++++++++++++++++++++--
tests/shell/testcases/listing/0020flowtable_0 | 21 +++++++++
10 files changed, 157 insertions(+), 19 deletions(-)
create mode 100755 tests/shell/testcases/listing/0020flowtable_0
diff --git a/doc/libnftables-json.adoc b/doc/libnftables-json.adoc
index 6877f0549db1..871480b95ceb 100644
--- a/doc/libnftables-json.adoc
+++ b/doc/libnftables-json.adoc
@@ -117,7 +117,7 @@ ____
*{ "add":* 'ADD_OBJECT' *}*
'ADD_OBJECT' := 'TABLE' | 'CHAIN' | 'RULE' | 'SET' | 'MAP' | 'ELEMENT' |
- 'FLOWTABLE' | 'COUNTER | QUOTA' | 'CT_HELPER' | 'LIMIT' |
+ 'FLOWTABLE' | 'COUNTER' | 'QUOTA' | 'CT_HELPER' | 'LIMIT' |
'CT_TIMEOUT' | 'CT_EXPECTATION'
____
@@ -161,9 +161,9 @@ ____
'LIST_OBJECT' := 'TABLE' | 'TABLES' | 'CHAIN' | 'CHAINS' | 'SET' | 'SETS' |
'MAP' | 'MAPS | COUNTER' | 'COUNTERS' | 'QUOTA' | 'QUOTAS' |
- 'CT_HELPER' | 'CT_HELPERS' | 'LIMIT' | 'LIMITS | RULESET' |
- 'METER' | 'METERS' | 'FLOWTABLES' | 'CT_TIMEOUT' |
- 'CT_EXPECTATION'
+ 'CT_HELPER' | 'CT_HELPERS' | 'LIMIT' | 'LIMITS' | 'RULESET' |
+ 'METER' | 'METERS' | 'FLOWTABLE' | 'FLOWTABLES' |
+ 'CT_TIMEOUT' | 'CT_EXPECTATION'
____
List ruleset elements. The plural forms are used to list all objects of that
diff --git a/include/rule.h b/include/rule.h
index ba40db8806fc..a718923b14a3 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -45,6 +45,11 @@ struct set_spec {
const char *name;
};
+struct flowtable_spec {
+ struct location location;
+ const char *name;
+};
+
struct obj_spec {
struct location location;
const char *name;
@@ -69,7 +74,7 @@ struct handle {
struct chain_spec chain;
struct set_spec set;
struct obj_spec obj;
- const char *flowtable;
+ struct flowtable_spec flowtable;
struct handle_spec handle;
struct position_spec position;
struct position_spec index;
@@ -470,6 +475,10 @@ extern struct flowtable *flowtable_alloc(const struct location *loc);
extern struct flowtable *flowtable_get(struct flowtable *flowtable);
extern void flowtable_free(struct flowtable *flowtable);
extern void flowtable_add_hash(struct flowtable *flowtable, struct table *table);
+extern struct flowtable *flowtable_lookup(const struct table *table, const char *name);
+extern struct flowtable *flowtable_lookup_fuzzy(const char *ft_name,
+ const struct nft_cache *cache,
+ const struct table **table);
void flowtable_print(const struct flowtable *n, struct output_ctx *octx);
@@ -535,7 +544,6 @@ enum cmd_ops {
* @CMD_OBJ_QUOTAS: multiple quotas
* @CMD_OBJ_LIMIT: limit
* @CMD_OBJ_LIMITS: multiple limits
- * @CMD_OBJ_FLOWTABLES: flow tables
* @CMD_OBJ_SECMARK: secmark
* @CMD_OBJ_SECMARKS: multiple secmarks
* @CMD_OBJ_SYNPROXY: synproxy
diff --git a/src/evaluate.c b/src/evaluate.c
index a56cd2a56e99..81230fc7f4be 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -218,6 +218,23 @@ static int set_not_found(struct eval_ctx *ctx, const struct location *loc,
table->handle.table.name);
}
+static int flowtable_not_found(struct eval_ctx *ctx, const struct location *loc,
+ const char *ft_name)
+{
+ const struct table *table;
+ struct flowtable *ft;
+
+ ft = flowtable_lookup_fuzzy(ft_name, &ctx->nft->cache, &table);
+ if (ft == NULL)
+ return cmd_error(ctx, loc, "%s", strerror(ENOENT));
+
+ return cmd_error(ctx, loc,
+ "%s; did you mean flowtable ‘%s’ in table %s ‘%s’?",
+ strerror(ENOENT), ft->handle.flowtable.name,
+ family2str(ft->handle.family),
+ table->handle.table.name);
+}
+
/*
* Symbol expression: parse symbol and evaluate resulting expression.
*/
@@ -3834,6 +3851,7 @@ static int cmd_evaluate_list_obj(struct eval_ctx *ctx, const struct cmd *cmd,
static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
{
+ struct flowtable *ft;
struct table *table;
struct set *set;
@@ -3899,6 +3917,17 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
return chain_not_found(ctx);
return 0;
+ case CMD_OBJ_FLOWTABLE:
+ table = table_lookup(&cmd->handle, &ctx->nft->cache);
+ if (table == NULL)
+ return table_not_found(ctx);
+
+ ft = flowtable_lookup(table, cmd->handle.flowtable.name);
+ if (ft == NULL)
+ return flowtable_not_found(ctx, &ctx->cmd->handle.flowtable.location,
+ ctx->cmd->handle.flowtable.name);
+
+ return 0;
case CMD_OBJ_QUOTA:
return cmd_evaluate_list_obj(ctx, cmd, NFT_OBJECT_QUOTA);
case CMD_OBJ_COUNTER:
diff --git a/src/json.c b/src/json.c
index 56b20549bd73..d079da9ea9eb 100644
--- a/src/json.c
+++ b/src/json.c
@@ -412,7 +412,7 @@ static json_t *flowtable_print_json(const struct flowtable *ftable)
BYTEORDER_HOST_ENDIAN, sizeof(int));
root = json_pack("{s:s, s:s, s:s, s:s, s:i}",
"family", family2str(ftable->handle.family),
- "name", ftable->handle.flowtable,
+ "name", ftable->handle.flowtable.name,
"table", ftable->handle.table.name,
"hook", hooknum2str(NFPROTO_NETDEV, ftable->hooknum),
"prio", priority);
@@ -1724,6 +1724,21 @@ static json_t *do_list_obj_json(struct netlink_ctx *ctx,
return root;
}
+static json_t *do_list_flowtable_json(struct netlink_ctx *ctx,
+ struct cmd *cmd, struct table *table)
+{
+ json_t *root = json_array();
+ struct flowtable *ft;
+
+ ft = flowtable_lookup(table, cmd->handle.flowtable.name);
+ if (ft == NULL)
+ return json_null();
+
+ json_array_append_new(root, flowtable_print_json(ft));
+
+ return root;
+}
+
static json_t *do_list_flowtables_json(struct netlink_ctx *ctx, struct cmd *cmd)
{
json_t *root = json_array(), *tmp;
@@ -1815,6 +1830,9 @@ int do_command_list_json(struct netlink_ctx *ctx, struct cmd *cmd)
case CMD_OBJ_SECMARKS:
root = do_list_obj_json(ctx, cmd, NFT_OBJECT_SECMARK);
break;
+ case CMD_OBJ_FLOWTABLE:
+ root = do_list_flowtable_json(ctx, cmd, table);
+ break;
case CMD_OBJ_FLOWTABLES:
root = do_list_flowtables_json(ctx, cmd);
break;
diff --git a/src/mnl.c b/src/mnl.c
index 933e18d97cbd..36ccda58c268 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -1429,7 +1429,7 @@ int mnl_nft_flowtable_add(struct netlink_ctx *ctx, const struct cmd *cmd,
nftnl_flowtable_set_str(flo, NFTNL_FLOWTABLE_TABLE,
cmd->handle.table.name);
nftnl_flowtable_set_str(flo, NFTNL_FLOWTABLE_NAME,
- cmd->handle.flowtable);
+ cmd->handle.flowtable.name);
nftnl_flowtable_set_u32(flo, NFTNL_FLOWTABLE_HOOKNUM,
cmd->flowtable->hooknum);
mpz_export_data(&priority, cmd->flowtable->priority.expr->value,
@@ -1475,7 +1475,7 @@ int mnl_nft_flowtable_del(struct netlink_ctx *ctx, const struct cmd *cmd)
nftnl_flowtable_set_str(flo, NFTNL_FLOWTABLE_TABLE,
cmd->handle.table.name);
nftnl_flowtable_set_str(flo, NFTNL_FLOWTABLE_NAME,
- cmd->handle.flowtable);
+ cmd->handle.flowtable.name);
nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
NFT_MSG_DELFLOWTABLE, cmd->handle.family,
diff --git a/src/netlink.c b/src/netlink.c
index c47771d3c801..a727c7eb76b0 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -1131,7 +1131,7 @@ netlink_delinearize_flowtable(struct netlink_ctx *ctx,
nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_FAMILY);
flowtable->handle.table.name =
xstrdup(nftnl_flowtable_get_str(nlo, NFTNL_FLOWTABLE_TABLE));
- flowtable->handle.flowtable =
+ flowtable->handle.flowtable.name =
xstrdup(nftnl_flowtable_get_str(nlo, NFTNL_FLOWTABLE_NAME));
dev_array = nftnl_flowtable_get(nlo, NFTNL_FLOWTABLE_DEVICES);
while (dev_array[len])
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 7f9b1752f41d..94494f6f5005 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -1315,6 +1315,10 @@ list_cmd : TABLE table_spec
{
$$ = cmd_alloc(CMD_LIST, CMD_OBJ_FLOWTABLES, &$2, &@$, NULL);
}
+ | FLOWTABLE flowtable_spec
+ {
+ $$ = cmd_alloc(CMD_LIST, CMD_OBJ_FLOWTABLE, &$2, &@$, NULL);
+ }
| MAPS ruleset_spec
{
$$ = cmd_alloc(CMD_LIST, CMD_OBJ_MAPS, &$2, &@$, NULL);
@@ -2224,15 +2228,17 @@ set_identifier : identifier
flowtable_spec : table_spec identifier
{
- $$ = $1;
- $$.flowtable = $2;
+ $$ = $1;
+ $$.flowtable.name = $2;
+ $$.flowtable.location = @2;
}
;
flowtable_identifier : identifier
{
memset(&$$, 0, sizeof($$));
- $$.flowtable = $1;
+ $$.flowtable.name = $1;
+ $$.flowtable.location = @1;
}
;
diff --git a/src/parser_json.c b/src/parser_json.c
index a9bcb84faf44..3b86a0ae543f 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -2967,7 +2967,7 @@ static struct cmd *json_parse_cmd_add_flowtable(struct json_ctx *ctx,
if (json_unpack_err(ctx, root, "{s:s, s:s, s:s}",
"family", &family,
"table", &h.table.name,
- "name", &h.flowtable))
+ "name", &h.flowtable.name))
return NULL;
if (parse_family(family, &h.family)) {
@@ -2975,7 +2975,7 @@ static struct cmd *json_parse_cmd_add_flowtable(struct json_ctx *ctx,
return NULL;
}
h.table.name = xstrdup(h.table.name);
- h.flowtable = xstrdup(h.flowtable);
+ h.flowtable.name = xstrdup(h.flowtable.name);
if (op == CMD_DELETE)
return cmd_alloc(op, cmd_obj, &h, int_loc, NULL);
diff --git a/src/rule.c b/src/rule.c
index c258f12e5c77..a2811d18fa31 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -105,7 +105,7 @@ void handle_free(struct handle *h)
xfree(h->table.name);
xfree(h->chain.name);
xfree(h->set.name);
- xfree(h->flowtable);
+ xfree(h->flowtable.name);
xfree(h->obj.name);
}
@@ -125,8 +125,8 @@ void handle_merge(struct handle *dst, const struct handle *src)
dst->set.name = xstrdup(src->set.name);
dst->set.location = src->set.location;
}
- if (dst->flowtable == NULL && src->flowtable != NULL)
- dst->flowtable = xstrdup(src->flowtable);
+ if (dst->flowtable.name == NULL && src->flowtable.name != NULL)
+ dst->flowtable.name = xstrdup(src->flowtable.name);
if (dst->obj.name == NULL && src->obj.name != NULL)
dst->obj.name = xstrdup(src->obj.name);
if (dst->handle.id == 0)
@@ -2156,7 +2156,7 @@ static void flowtable_print_declaration(const struct flowtable *flowtable,
if (opts->table != NULL)
nft_print(octx, " %s", opts->table);
- nft_print(octx, " %s {%s", flowtable->handle.flowtable, opts->nl);
+ nft_print(octx, " %s {%s", flowtable->handle.flowtable.name, opts->nl);
nft_print(octx, "%s%shook %s priority %s%s",
opts->tab, opts->tab,
@@ -2193,6 +2193,60 @@ void flowtable_print(const struct flowtable *s, struct output_ctx *octx)
do_flowtable_print(s, &opts, octx);
}
+struct flowtable *flowtable_lookup(const struct table *table, const char *name)
+{
+ struct flowtable *ft;
+
+ list_for_each_entry(ft, &table->flowtables, list) {
+ if (!strcmp(ft->handle.flowtable.name, name))
+ return ft;
+ }
+ return NULL;
+}
+
+struct flowtable *flowtable_lookup_fuzzy(const char *ft_name,
+ const struct nft_cache *cache,
+ const struct table **t)
+{
+ struct string_misspell_state st;
+ struct table *table;
+ struct flowtable *ft;
+
+ string_misspell_init(&st);
+
+ list_for_each_entry(table, &cache->list, list) {
+ list_for_each_entry(ft, &table->flowtables, list) {
+ if (!strcmp(ft->handle.flowtable.name, ft_name)) {
+ *t = table;
+ return ft;
+ }
+ if (string_misspell_update(ft->handle.flowtable.name,
+ ft_name, ft, &st))
+ *t = table;
+ }
+ }
+ return st.obj;
+}
+
+static int do_list_flowtable(struct netlink_ctx *ctx, struct cmd *cmd,
+ struct table *table)
+{
+ struct flowtable *ft;
+
+ ft = flowtable_lookup(table, cmd->handle.flowtable.name);
+ if (ft == NULL)
+ return -1;
+
+ nft_print(&ctx->nft->output, "table %s %s {\n",
+ family2str(table->handle.family),
+ table->handle.table.name);
+
+ flowtable_print(ft, &ctx->nft->output);
+ nft_print(&ctx->nft->output, "}\n");
+
+ return 0;
+}
+
static int do_list_flowtables(struct netlink_ctx *ctx, struct cmd *cmd)
{
struct print_fmt_options opts = {
@@ -2388,6 +2442,8 @@ static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd)
case CMD_OBJ_SYNPROXY:
case CMD_OBJ_SYNPROXYS:
return do_list_obj(ctx, cmd, NFT_OBJECT_SYNPROXY);
+ case CMD_OBJ_FLOWTABLE:
+ return do_list_flowtable(ctx, cmd, table);
case CMD_OBJ_FLOWTABLES:
return do_list_flowtables(ctx, cmd);
default:
diff --git a/tests/shell/testcases/listing/0020flowtable_0 b/tests/shell/testcases/listing/0020flowtable_0
new file mode 100755
index 000000000000..6f630f14a8ba
--- /dev/null
+++ b/tests/shell/testcases/listing/0020flowtable_0
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+# list only the flowtable asked for with table
+
+EXPECTED="table inet filter {
+ flowtable f {
+ hook ingress priority filter
+ devices = { lo }
+ }
+}"
+
+set -e
+
+$NFT -f - <<< "$EXPECTED"
+
+GET="$($NFT list flowtable inet filter f)"
+if [ "$EXPECTED" != "$GET" ] ; then
+ DIFF="$(which diff)"
+ [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET")
+ exit 1
+fi
--
2.11.0
next reply other threads:[~2019-10-30 17:18 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-10-30 17:06 Eric Jallot [this message]
2019-10-31 13:14 ` [PATCH nft] src: flowtable: add support for named flowtable listing Pablo Neira Ayuso
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191030170619.45231-1-ejallot@gmail.com \
--to=ejallot@gmail.com \
--cc=netfilter-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.