From 8cfbb8c3427f232484bacab3116f6925f3976c7b Mon Sep 17 00:00:00 2001 From: Phil Sutter 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 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 Signed-off-by: Phil Sutter --- 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"}}}