diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2021-09-29 13:09:03 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2021-09-30 00:26:16 +0200 |
commit | 3f1d3912c3a6b42158149a97f59d1c01debfd132 (patch) | |
tree | 37cdee6545be7d41756c8d5c6bade037a767eb20 /src | |
parent | a1a6b0a5c3c4b4b305fa34a77932ee1c6452d1c8 (diff) |
cache: filter out tables that are not requested
Do not fetch table content for list commands that specify a
table name, e.g.
# nft list table filter
This speeds up listing of a given table by not populating the
cache with tables that are not needed.
- Full ruleset (huge with ~100k lines).
# sudo nft list ruleset &> /dev/null
real 0m3,049s
user 0m2,080s
sys 0m0,968s
- Listing per table is now faster:
# nft list table nat &> /dev/null
real 0m1,969s
user 0m1,412s
sys 0m0,556s
# nft list table filter &> /dev/null
real 0m0,697s
user 0m0,478s
sys 0m0,220s
Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1326
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/cache.c | 41 | ||||
-rw-r--r-- | src/cmd.c | 2 | ||||
-rw-r--r-- | src/libnftables.c | 5 |
3 files changed, 35 insertions, 13 deletions
diff --git a/src/cache.c b/src/cache.c index a0898a97..6684111f 100644 --- a/src/cache.c +++ b/src/cache.c @@ -127,9 +127,16 @@ static unsigned int evaluate_cache_rename(struct cmd *cmd, unsigned int flags) return flags; } -static unsigned int evaluate_cache_list(struct cmd *cmd, unsigned int flags) +static unsigned int evaluate_cache_list(struct cmd *cmd, unsigned int flags, + struct nft_cache_filter *filter) { switch (cmd->obj) { + case CMD_OBJ_TABLE: + if (filter && cmd->handle.table.name) + filter->table = cmd->handle.table.name; + + flags |= NFT_CACHE_FULL | NFT_CACHE_REFRESH; + break; case CMD_OBJ_CHAINS: flags |= NFT_CACHE_TABLE | NFT_CACHE_CHAIN; break; @@ -148,12 +155,16 @@ static unsigned int evaluate_cache_list(struct cmd *cmd, unsigned int flags) return flags; } -unsigned int nft_cache_evaluate(struct nft_ctx *nft, struct list_head *cmds) +unsigned int nft_cache_evaluate(struct nft_ctx *nft, struct list_head *cmds, + struct nft_cache_filter *filter) { unsigned int flags = NFT_CACHE_EMPTY; struct cmd *cmd; list_for_each_entry(cmd, cmds, list) { + if (filter->table && cmd->op != CMD_LIST) + memset(filter, 0, sizeof(*filter)); + switch (cmd->op) { case CMD_ADD: case CMD_INSERT: @@ -181,7 +192,7 @@ unsigned int nft_cache_evaluate(struct nft_ctx *nft, struct list_head *cmds) flags |= NFT_CACHE_TABLE; break; case CMD_LIST: - flags |= evaluate_cache_list(cmd, flags); + flags |= evaluate_cache_list(cmd, flags, filter); break; case CMD_MONITOR: flags |= NFT_CACHE_FULL; @@ -582,7 +593,8 @@ struct flowtable *ft_cache_find(const struct table *table, const char *name) } static int cache_init_tables(struct netlink_ctx *ctx, struct handle *h, - struct nft_cache *cache) + struct nft_cache *cache, + const struct nft_cache_filter *filter) { struct table *table, *next; int ret; @@ -593,13 +605,20 @@ static int cache_init_tables(struct netlink_ctx *ctx, struct handle *h, list_for_each_entry_safe(table, next, &ctx->list, list) { list_del(&table->list); + + if (filter && filter->table && + (strcmp(filter->table, table->handle.table.name))) { + table_free(table); + continue; + } table_cache_add(table, cache); } return 0; } -static int cache_init_objects(struct netlink_ctx *ctx, unsigned int flags) +static int cache_init_objects(struct netlink_ctx *ctx, unsigned int flags, + const struct nft_cache_filter *filter) { struct nftnl_flowtable_list *ft_list = NULL; struct nftnl_chain_list *chain_list = NULL; @@ -721,7 +740,8 @@ cache_fails: return ret; } -static int nft_cache_init(struct netlink_ctx *ctx, unsigned int flags) +static int nft_cache_init(struct netlink_ctx *ctx, unsigned int flags, + const struct nft_cache_filter *filter) { struct handle handle = { .family = NFPROTO_UNSPEC, @@ -732,10 +752,10 @@ static int nft_cache_init(struct netlink_ctx *ctx, unsigned int flags) return 0; /* assume NFT_CACHE_TABLE is always set. */ - ret = cache_init_tables(ctx, &handle, &ctx->nft->cache); + ret = cache_init_tables(ctx, &handle, &ctx->nft->cache, filter); if (ret < 0) return ret; - ret = cache_init_objects(ctx, flags); + ret = cache_init_objects(ctx, flags, filter); if (ret < 0) return ret; @@ -763,7 +783,8 @@ bool nft_cache_needs_update(struct nft_cache *cache) } int nft_cache_update(struct nft_ctx *nft, unsigned int flags, - struct list_head *msgs) + struct list_head *msgs, + const struct nft_cache_filter *filter) { struct netlink_ctx ctx = { .list = LIST_HEAD_INIT(ctx.list), @@ -792,7 +813,7 @@ replay: goto skip; } - ret = nft_cache_init(&ctx, flags); + ret = nft_cache_init(&ctx, flags, filter); if (ret < 0) { if (errno == EINTR) { nft_cache_release(cache); @@ -81,7 +81,7 @@ static int nft_cmd_enoent_rule(struct netlink_ctx *ctx, const struct cmd *cmd, const struct table *table = NULL; struct chain *chain; - if (nft_cache_update(ctx->nft, flags, ctx->msgs) < 0) + if (nft_cache_update(ctx->nft, flags, ctx->msgs, NULL) < 0) return 0; chain = chain_lookup_fuzzy(&cmd->handle, &ctx->nft->cache, &table); diff --git a/src/libnftables.c b/src/libnftables.c index fc52fbc3..2b2ed1a4 100644 --- a/src/libnftables.c +++ b/src/libnftables.c @@ -459,11 +459,12 @@ static int nft_parse_bison_filename(struct nft_ctx *nft, const char *filename, static int nft_evaluate(struct nft_ctx *nft, struct list_head *msgs, struct list_head *cmds) { + struct nft_cache_filter filter = {}; unsigned int flags; struct cmd *cmd; - flags = nft_cache_evaluate(nft, cmds); - if (nft_cache_update(nft, flags, msgs) < 0) + flags = nft_cache_evaluate(nft, cmds, &filter); + if (nft_cache_update(nft, flags, msgs, &filter) < 0) return -1; list_for_each_entry(cmd, cmds, list) { |