261 lines
8.3 KiB
Diff
261 lines
8.3 KiB
Diff
|
From 8cfbb8c3427f232484bacab3116f6925f3976c7b Mon Sep 17 00:00:00 2001
|
||
|
From: Phil Sutter <psutter@redhat.com>
|
||
|
Date: Thu, 7 Nov 2024 18:38:46 +0100
|
||
|
Subject: [PATCH] monitor: Recognize flowtable add/del events
|
||
|
|
||
|
JIRA: https://issues.redhat.com/browse/RHEL-65346
|
||
|
Upstream Status: nftables commit 73a8adfc2432ec8337288cc90e7c9f4509139846
|
||
|
|
||
|
commit 73a8adfc2432ec8337288cc90e7c9f4509139846
|
||
|
Author: Phil Sutter <phil@nwl.cc>
|
||
|
Date: Wed May 15 16:01:20 2024 +0200
|
||
|
|
||
|
monitor: Recognize flowtable add/del events
|
||
|
|
||
|
These were entirely ignored before, add the necessary code analogous to
|
||
|
e.g. objects.
|
||
|
|
||
|
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||
|
|
||
|
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||
|
---
|
||
|
include/json.h | 10 ++++
|
||
|
include/netlink.h | 1 +
|
||
|
include/rule.h | 1 +
|
||
|
src/json.c | 6 +++
|
||
|
src/monitor.c | 61 ++++++++++++++++++++++
|
||
|
src/parser_json.c | 6 +++
|
||
|
src/rule.c | 15 ++++++
|
||
|
tests/monitor/testcases/flowtable-simple.t | 10 ++++
|
||
|
8 files changed, 110 insertions(+)
|
||
|
create mode 100644 tests/monitor/testcases/flowtable-simple.t
|
||
|
|
||
|
diff --git a/include/json.h b/include/json.h
|
||
|
index 39be892..0670b87 100644
|
||
|
--- a/include/json.h
|
||
|
+++ b/include/json.h
|
||
|
@@ -11,6 +11,7 @@ struct nlmsghdr;
|
||
|
struct rule;
|
||
|
struct set;
|
||
|
struct obj;
|
||
|
+struct flowtable;
|
||
|
struct stmt;
|
||
|
struct symbol_table;
|
||
|
struct table;
|
||
|
@@ -113,6 +114,8 @@ void monitor_print_element_json(struct netlink_mon_handler *monh,
|
||
|
const char *cmd, struct set *s);
|
||
|
void monitor_print_obj_json(struct netlink_mon_handler *monh,
|
||
|
const char *cmd, struct obj *o);
|
||
|
+void monitor_print_flowtable_json(struct netlink_mon_handler *monh,
|
||
|
+ const char *cmd, struct flowtable *ft);
|
||
|
void monitor_print_rule_json(struct netlink_mon_handler *monh,
|
||
|
const char *cmd, struct rule *r);
|
||
|
|
||
|
@@ -254,6 +257,13 @@ static inline void monitor_print_obj_json(struct netlink_mon_handler *monh,
|
||
|
/* empty */
|
||
|
}
|
||
|
|
||
|
+static inline void
|
||
|
+monitor_print_flowtable_json(struct netlink_mon_handler *monh,
|
||
|
+ const char *cmd, struct flowtable *ft)
|
||
|
+{
|
||
|
+ /* empty */
|
||
|
+}
|
||
|
+
|
||
|
static inline void monitor_print_rule_json(struct netlink_mon_handler *monh,
|
||
|
const char *cmd, struct rule *r)
|
||
|
{
|
||
|
diff --git a/include/netlink.h b/include/netlink.h
|
||
|
index cf7ba36..e9667a2 100644
|
||
|
--- a/include/netlink.h
|
||
|
+++ b/include/netlink.h
|
||
|
@@ -97,6 +97,7 @@ extern struct nftnl_table *netlink_table_alloc(const struct nlmsghdr *nlh);
|
||
|
extern struct nftnl_chain *netlink_chain_alloc(const struct nlmsghdr *nlh);
|
||
|
extern struct nftnl_set *netlink_set_alloc(const struct nlmsghdr *nlh);
|
||
|
extern struct nftnl_obj *netlink_obj_alloc(const struct nlmsghdr *nlh);
|
||
|
+extern struct nftnl_flowtable *netlink_flowtable_alloc(const struct nlmsghdr *nlh);
|
||
|
extern struct nftnl_rule *netlink_rule_alloc(const struct nlmsghdr *nlh);
|
||
|
|
||
|
struct nft_data_linearize {
|
||
|
diff --git a/include/rule.h b/include/rule.h
|
||
|
index 48e148e..238be23 100644
|
||
|
--- a/include/rule.h
|
||
|
+++ b/include/rule.h
|
||
|
@@ -551,6 +551,7 @@ extern struct flowtable *flowtable_lookup_fuzzy(const char *ft_name,
|
||
|
const struct table **table);
|
||
|
|
||
|
void flowtable_print(const struct flowtable *n, struct output_ctx *octx);
|
||
|
+void flowtable_print_plain(const struct flowtable *ft, struct output_ctx *octx);
|
||
|
|
||
|
/**
|
||
|
* enum cmd_ops - command operations
|
||
|
diff --git a/src/json.c b/src/json.c
|
||
|
index 1f609bf..64a6888 100644
|
||
|
--- a/src/json.c
|
||
|
+++ b/src/json.c
|
||
|
@@ -2108,6 +2108,12 @@ void monitor_print_obj_json(struct netlink_mon_handler *monh,
|
||
|
monitor_print_json(monh, cmd, obj_print_json(o));
|
||
|
}
|
||
|
|
||
|
+void monitor_print_flowtable_json(struct netlink_mon_handler *monh,
|
||
|
+ const char *cmd, struct flowtable *ft)
|
||
|
+{
|
||
|
+ monitor_print_json(monh, cmd, flowtable_print_json(ft));
|
||
|
+}
|
||
|
+
|
||
|
void monitor_print_rule_json(struct netlink_mon_handler *monh,
|
||
|
const char *cmd, struct rule *r)
|
||
|
{
|
||
|
diff --git a/src/monitor.c b/src/monitor.c
|
||
|
index 2fc16d6..a787db8 100644
|
||
|
--- a/src/monitor.c
|
||
|
+++ b/src/monitor.c
|
||
|
@@ -127,6 +127,19 @@ struct nftnl_obj *netlink_obj_alloc(const struct nlmsghdr *nlh)
|
||
|
return nlo;
|
||
|
}
|
||
|
|
||
|
+struct nftnl_flowtable *netlink_flowtable_alloc(const struct nlmsghdr *nlh)
|
||
|
+{
|
||
|
+ struct nftnl_flowtable *nlf;
|
||
|
+
|
||
|
+ nlf = nftnl_flowtable_alloc();
|
||
|
+ if (nlf == NULL)
|
||
|
+ memory_allocation_error();
|
||
|
+ if (nftnl_flowtable_nlmsg_parse(nlh, nlf) < 0)
|
||
|
+ netlink_abi_error();
|
||
|
+
|
||
|
+ return nlf;
|
||
|
+}
|
||
|
+
|
||
|
static uint32_t netlink_msg2nftnl_of(uint32_t type, uint16_t flags)
|
||
|
{
|
||
|
switch (type) {
|
||
|
@@ -542,6 +555,50 @@ static int netlink_events_obj_cb(const struct nlmsghdr *nlh, int type,
|
||
|
return MNL_CB_OK;
|
||
|
}
|
||
|
|
||
|
+static int netlink_events_flowtable_cb(const struct nlmsghdr *nlh, int type,
|
||
|
+ struct netlink_mon_handler *monh)
|
||
|
+{
|
||
|
+ const char *family, *cmd;
|
||
|
+ struct nftnl_flowtable *nlf;
|
||
|
+ struct flowtable *ft;
|
||
|
+
|
||
|
+ nlf = netlink_flowtable_alloc(nlh);
|
||
|
+
|
||
|
+ ft = netlink_delinearize_flowtable(monh->ctx, nlf);
|
||
|
+ if (!ft) {
|
||
|
+ nftnl_flowtable_free(nlf);
|
||
|
+ return MNL_CB_ERROR;
|
||
|
+ }
|
||
|
+ family = family2str(ft->handle.family);
|
||
|
+ cmd = netlink_msg2cmd(type, nlh->nlmsg_flags);
|
||
|
+
|
||
|
+ switch (monh->format) {
|
||
|
+ case NFTNL_OUTPUT_DEFAULT:
|
||
|
+ nft_mon_print(monh, "%s ", cmd);
|
||
|
+
|
||
|
+ switch (type) {
|
||
|
+ case NFT_MSG_NEWFLOWTABLE:
|
||
|
+ flowtable_print_plain(ft, &monh->ctx->nft->output);
|
||
|
+ break;
|
||
|
+ case NFT_MSG_DELFLOWTABLE:
|
||
|
+ nft_mon_print(monh, "flowtable %s %s %s", family,
|
||
|
+ ft->handle.table.name,
|
||
|
+ ft->handle.flowtable.name);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ nft_mon_print(monh, "\n");
|
||
|
+ break;
|
||
|
+ case NFTNL_OUTPUT_JSON:
|
||
|
+ monitor_print_flowtable_json(monh, cmd, ft);
|
||
|
+ if (!nft_output_echo(&monh->ctx->nft->output))
|
||
|
+ nft_mon_print(monh, "\n");
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ flowtable_free(ft);
|
||
|
+ nftnl_flowtable_free(nlf);
|
||
|
+ return MNL_CB_OK;
|
||
|
+}
|
||
|
+
|
||
|
static void rule_map_decompose_cb(struct set *s, void *data)
|
||
|
{
|
||
|
if (!set_is_anonymous(s->flags))
|
||
|
@@ -962,6 +1019,10 @@ static int netlink_events_cb(const struct nlmsghdr *nlh, void *data)
|
||
|
case NFT_MSG_DELOBJ:
|
||
|
ret = netlink_events_obj_cb(nlh, type, monh);
|
||
|
break;
|
||
|
+ case NFT_MSG_NEWFLOWTABLE:
|
||
|
+ case NFT_MSG_DELFLOWTABLE:
|
||
|
+ ret = netlink_events_flowtable_cb(nlh, type, monh);
|
||
|
+ break;
|
||
|
case NFT_MSG_NEWGEN:
|
||
|
ret = netlink_events_newgen_cb(nlh, type, monh);
|
||
|
break;
|
||
|
diff --git a/src/parser_json.c b/src/parser_json.c
|
||
|
index 02cfcd6..bae2c3c 100644
|
||
|
--- a/src/parser_json.c
|
||
|
+++ b/src/parser_json.c
|
||
|
@@ -4437,6 +4437,7 @@ static int json_echo_error(struct netlink_mon_handler *monh,
|
||
|
|
||
|
static uint64_t handle_from_nlmsg(const struct nlmsghdr *nlh)
|
||
|
{
|
||
|
+ struct nftnl_flowtable *nlf;
|
||
|
struct nftnl_table *nlt;
|
||
|
struct nftnl_chain *nlc;
|
||
|
struct nftnl_rule *nlr;
|
||
|
@@ -4473,6 +4474,11 @@ static uint64_t handle_from_nlmsg(const struct nlmsghdr *nlh)
|
||
|
handle = nftnl_obj_get_u64(nlo, NFTNL_OBJ_HANDLE);
|
||
|
nftnl_obj_free(nlo);
|
||
|
break;
|
||
|
+ case NFT_MSG_NEWFLOWTABLE:
|
||
|
+ nlf = netlink_flowtable_alloc(nlh);
|
||
|
+ handle = nftnl_flowtable_get_u64(nlf, NFTNL_FLOWTABLE_HANDLE);
|
||
|
+ nftnl_flowtable_free(nlf);
|
||
|
+ break;
|
||
|
}
|
||
|
return handle;
|
||
|
}
|
||
|
diff --git a/src/rule.c b/src/rule.c
|
||
|
index 9536e68..151ed53 100644
|
||
|
--- a/src/rule.c
|
||
|
+++ b/src/rule.c
|
||
|
@@ -2154,6 +2154,21 @@ void flowtable_print(const struct flowtable *s, struct output_ctx *octx)
|
||
|
do_flowtable_print(s, &opts, octx);
|
||
|
}
|
||
|
|
||
|
+void flowtable_print_plain(const struct flowtable *ft, struct output_ctx *octx)
|
||
|
+{
|
||
|
+ struct print_fmt_options opts = {
|
||
|
+ .tab = "",
|
||
|
+ .nl = " ",
|
||
|
+ .table = ft->handle.table.name,
|
||
|
+ .family = family2str(ft->handle.family),
|
||
|
+ .stmt_separator = "; ",
|
||
|
+ };
|
||
|
+
|
||
|
+ flowtable_print_declaration(ft, &opts, octx);
|
||
|
+ nft_print(octx, "}");
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
struct flowtable *flowtable_lookup_fuzzy(const char *ft_name,
|
||
|
const struct nft_cache *cache,
|
||
|
const struct table **t)
|
||
|
diff --git a/tests/monitor/testcases/flowtable-simple.t b/tests/monitor/testcases/flowtable-simple.t
|
||
|
new file mode 100644
|
||
|
index 0000000..df8eccb
|
||
|
--- /dev/null
|
||
|
+++ b/tests/monitor/testcases/flowtable-simple.t
|
||
|
@@ -0,0 +1,10 @@
|
||
|
+# setup first
|
||
|
+I add table ip t
|
||
|
+I add flowtable ip t ft { hook ingress priority 0; devices = { lo }; }
|
||
|
+O -
|
||
|
+J {"add": {"table": {"family": "ip", "name": "t", "handle": 0}}}
|
||
|
+J {"add": {"flowtable": {"family": "ip", "name": "ft", "table": "t", "handle": 0, "hook": "ingress", "prio": 0, "dev": "lo"}}}
|
||
|
+
|
||
|
+I delete flowtable ip t ft
|
||
|
+O -
|
||
|
+J {"delete": {"flowtable": {"family": "ip", "name": "ft", "table": "t", "handle": 0, "hook": "ingress", "prio": 0, "dev": "lo"}}}
|