summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2021-09-29 13:09:03 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2021-09-30 00:26:16 +0200
commit3f1d3912c3a6b42158149a97f59d1c01debfd132 (patch)
tree37cdee6545be7d41756c8d5c6bade037a767eb20 /src
parenta1a6b0a5c3c4b4b305fa34a77932ee1c6452d1c8 (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.c41
-rw-r--r--src/cmd.c2
-rw-r--r--src/libnftables.c5
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);
diff --git a/src/cmd.c b/src/cmd.c
index d956919b..f6a8aa11 100644
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -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) {