]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
monitor: Recognize flowtable add/del events
authorPhil Sutter <phil@nwl.cc>
Wed, 15 May 2024 14:01:20 +0000 (16:01 +0200)
committerPhil Sutter <phil@nwl.cc>
Wed, 6 Nov 2024 10:00:21 +0000 (11:00 +0100)
These were entirely ignored before, add the necessary code analogous to
e.g. objects.

Signed-off-by: Phil Sutter <phil@nwl.cc>
include/json.h
include/netlink.h
include/rule.h
src/json.c
src/monitor.c
src/parser_json.c
src/rule.c
tests/monitor/testcases/flowtable-simple.t [new file with mode: 0644]

index 39be8928e8ee0585532ec4f8742741cf826535ae..0670b8714519b55ccfaf2b6d3843cf71ec3dc979 100644 (file)
@@ -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)
 {
index cf7ba3693885ab43c161810ba59bf941bbbc0b22..e9667a24b0d118874f7570bf19af39abc511eb6b 100644 (file)
@@ -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 {
index 48e148e6afdd9723965fa2eda762723bda227188..238be23eca90715c780de0e8f7079c5acfc08ea8 100644 (file)
@@ -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
index 1f609bf2b03e9b6d4df61762dbdfa0cc36f6c1c4..64a6888f9e0ac4bc49d2896c2c1a1fa0efcf31fe 100644 (file)
@@ -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)
 {
index 2fc16d6776a2878bfd1b01d6fe21f9d83b9023f2..a787db8cbf5a322d079baab42c8f5a41115e3f23 100644 (file)
@@ -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;
index 02cfcd69adbc626ec6bebdc52dc77e5185ec3491..bae2c3c099e97a7b4beefbaf78e1f932fec7907e 100644 (file)
@@ -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;
 }
index 9536e68c75242a1a69207c29290c190bbcdce465..151ed531969c25fadd3fc8ee7c0479f686bdfa26 100644 (file)
@@ -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 (file)
index 0000000..df8eccb
--- /dev/null
@@ -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"}}}