]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
cache: Filter tables on kernel side
authorPhil Sutter <phil@nwl.cc>
Mon, 29 Nov 2021 14:28:33 +0000 (15:28 +0100)
committerPhil Sutter <phil@nwl.cc>
Fri, 3 Dec 2021 11:50:18 +0000 (12:50 +0100)
Instead of requesting a dump of all tables and filtering the data in
user space, construct a non-dump request if filter contains a table so
kernel returns only that single table.

This should improve nft performance in rulesets with many tables
present.

Signed-off-by: Phil Sutter <phil@nwl.cc>
include/mnl.h
include/netlink.h
src/cache.c
src/mnl.c
src/netlink.c

index 68ec80cd22821703b37ee9fc3f15e062e650873c..344030f30694024cf5a713c6bbd6f53ac9657b00 100644 (file)
@@ -50,7 +50,7 @@ int mnl_nft_table_add(struct netlink_ctx *ctx, struct cmd *cmd,
 int mnl_nft_table_del(struct netlink_ctx *ctx, struct cmd *cmd);
 
 struct nftnl_table_list *mnl_nft_table_dump(struct netlink_ctx *ctx,
-                                           int family);
+                                           int family, const char *table);
 
 int mnl_nft_set_add(struct netlink_ctx *ctx, struct cmd *cmd,
                    unsigned int flags);
index a692edcdb5bf24b54fd420d5dedc28ae5aef0692..0e439061e3800799aeb19749067c23ee6f001ea0 100644 (file)
@@ -135,7 +135,8 @@ extern int netlink_list_chains(struct netlink_ctx *ctx, const struct handle *h);
 extern struct chain *netlink_delinearize_chain(struct netlink_ctx *ctx,
                                               const struct nftnl_chain *nlc);
 
-extern int netlink_list_tables(struct netlink_ctx *ctx, const struct handle *h);
+extern int netlink_list_tables(struct netlink_ctx *ctx, const struct handle *h,
+                              const struct nft_cache_filter *filter);
 extern struct table *netlink_delinearize_table(struct netlink_ctx *ctx,
                                               const struct nftnl_table *nlt);
 
index 6d20716d73110d2256a9d45010345b8d330ff0f3..66da2b347573256391769cae060c8b70ec176b82 100644 (file)
@@ -772,19 +772,12 @@ static int cache_init_tables(struct netlink_ctx *ctx, struct handle *h,
        struct table *table, *next;
        int ret;
 
-       ret = netlink_list_tables(ctx, h);
+       ret = netlink_list_tables(ctx, h, filter);
        if (ret < 0)
                return -1;
 
        list_for_each_entry_safe(table, next, &ctx->list, list) {
                list_del(&table->list);
-
-               if (filter && filter->list.table &&
-                   (filter->list.family != table->handle.family ||
-                    strcmp(filter->list.table, table->handle.table.name))) {
-                       table_free(table);
-                       continue;
-               }
                table_cache_add(table, cache);
        }
 
index 23348e1393bce565b6500432037709c597673b31..21b98e34ed1762d8c5504c292714e87256713886 100644 (file)
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -1016,10 +1016,12 @@ err_free:
 }
 
 struct nftnl_table_list *mnl_nft_table_dump(struct netlink_ctx *ctx,
-                                           int family)
+                                           int family, const char *table)
 {
        char buf[MNL_SOCKET_BUFFER_SIZE];
        struct nftnl_table_list *nlt_list;
+       struct nftnl_table *nlt = NULL;
+       int flags = NLM_F_DUMP;
        struct nlmsghdr *nlh;
        int ret;
 
@@ -1027,11 +1029,25 @@ struct nftnl_table_list *mnl_nft_table_dump(struct netlink_ctx *ctx,
        if (nlt_list == NULL)
                return NULL;
 
+       if (table) {
+               nlt = nftnl_table_alloc();
+               if (!nlt)
+                       memory_allocation_error();
+
+               nftnl_table_set_u32(nlt, NFTNL_TABLE_FAMILY, family);
+               nftnl_table_set_str(nlt, NFTNL_TABLE_NAME, table);
+               flags = NLM_F_ACK;
+       }
+
        nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, family,
-                                   NLM_F_DUMP, ctx->seqnum);
+                                   flags, ctx->seqnum);
+       if (nlt) {
+               nftnl_table_nlmsg_build_payload(nlh, nlt);
+               nftnl_table_free(nlt);
+       }
 
        ret = nft_mnl_talk(ctx, nlh, nlh->nlmsg_len, table_cb, nlt_list);
-       if (ret < 0)
+       if (ret < 0 && errno != ENOENT)
                goto err;
 
        return nlt_list;
index ab90d0c05acaf80e9ae2cb8822794930a4ea3a3b..f74c0383a0db374046c2f4b911ec7a971191d6ee 100644 (file)
@@ -664,11 +664,19 @@ static int list_table_cb(struct nftnl_table *nlt, void *arg)
        return 0;
 }
 
-int netlink_list_tables(struct netlink_ctx *ctx, const struct handle *h)
+int netlink_list_tables(struct netlink_ctx *ctx, const struct handle *h,
+                       const struct nft_cache_filter *filter)
 {
        struct nftnl_table_list *table_cache;
+       uint32_t family = h->family;
+       const char *table = NULL;
 
-       table_cache = mnl_nft_table_dump(ctx, h->family);
+       if (filter) {
+               family = filter->list.family;
+               table = filter->list.table;
+       }
+
+       table_cache = mnl_nft_table_dump(ctx, family, table);
        if (table_cache == NULL) {
                if (errno == EINTR)
                        return -1;