]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
cache: populate chains on demand from error path
authorPablo Neira Ayuso <pablo@netfilter.org>
Thu, 15 Aug 2024 10:34:11 +0000 (12:34 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 19 Aug 2024 15:24:31 +0000 (17:24 +0200)
Updates on verdict maps that require many non-base chains are slowed
down due to fetching existing non-base chains into the cache.

Chains are only required for error reporting hints if kernel reports
ENOENT. Populate the cache from this error path only.

Similar approach already exists from rule ENOENT error path since:

  deb7c5927fad ("cmd: add misspelling suggestions for rule commands")

however, NFT_CACHE_CHAIN was toggled inconditionally for rule
commands, rendering this on-demand cache population useless.

before this patch, running Neels' nft_slew benchmark (peak values):

  created idx 4992 in 52587950 ns   (128 in 7122 ms)
  ...
  deleted idx  128 in 43542500 ns   (127 in 6187 ms)

after this patch:

  created idx 4992 in 11361299 ns   (128 in 1612 ms)
  ...
  deleted idx 1664 in  5239633 ns   (128 in 733 ms)

Tested-by: Eric Garver <eric@garver.life>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/cache.h
src/cache.c
src/cmd.c

index 8ca4a9a79c03300459b9c2bf30151e2784b0a9a4..44e8430ce1fd00cf5ad6c49c256669aa0c123d71 100644 (file)
@@ -31,7 +31,6 @@ enum cache_level_flags {
                                  NFT_CACHE_SET_BIT |
                                  NFT_CACHE_SETELEM_BIT,
        NFT_CACHE_RULE          = NFT_CACHE_TABLE_BIT |
-                                 NFT_CACHE_CHAIN_BIT |
                                  NFT_CACHE_RULE_BIT,
        NFT_CACHE_FULL          = __NFT_CACHE_MAX_BIT - 1,
        NFT_CACHE_TERSE         = (1 << 27),
index 42e60dfa12865ee502e252a8bf2d3e772d190b77..36c6f12d8720006d9598494a663724ae4b4b6c31 100644 (file)
@@ -30,7 +30,6 @@ static unsigned int evaluate_cache_add(struct cmd *cmd, unsigned int flags)
                        break;
 
                flags |= NFT_CACHE_TABLE |
-                        NFT_CACHE_CHAIN |
                         NFT_CACHE_SET |
                         NFT_CACHE_OBJECT |
                         NFT_CACHE_FLOWTABLE;
@@ -54,14 +53,12 @@ static unsigned int evaluate_cache_add(struct cmd *cmd, unsigned int flags)
                break;
        case CMD_OBJ_ELEMENTS:
                flags |= NFT_CACHE_TABLE |
-                        NFT_CACHE_CHAIN |
                         NFT_CACHE_SET |
                         NFT_CACHE_OBJECT |
                         NFT_CACHE_SETELEM_MAYBE;
                break;
        case CMD_OBJ_RULE:
                flags |= NFT_CACHE_TABLE |
-                        NFT_CACHE_CHAIN |
                         NFT_CACHE_SET |
                         NFT_CACHE_OBJECT |
                         NFT_CACHE_FLOWTABLE;
@@ -435,7 +432,6 @@ int nft_cache_evaluate(struct nft_ctx *nft, struct list_head *cmds,
                case CMD_DELETE:
                case CMD_DESTROY:
                        flags |= NFT_CACHE_TABLE |
-                                NFT_CACHE_CHAIN |
                                 NFT_CACHE_SET |
                                 NFT_CACHE_FLOWTABLE |
                                 NFT_CACHE_OBJECT;
index 37d93abc2cd4083c7f9c0976f60d604341d720f1..381f404266de962b684041e15e205c02c6106273 100644 (file)
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -75,6 +75,10 @@ static int nft_cmd_enoent_chain(struct netlink_ctx *ctx, const struct cmd *cmd,
        if (!cmd->handle.chain.name)
                return 0;
 
+       if (nft_cache_update(ctx->nft, NFT_CACHE_TABLE | NFT_CACHE_CHAIN,
+                            ctx->msgs, NULL) < 0)
+               return 0;
+
        chain = chain_lookup_fuzzy(&cmd->handle, &ctx->nft->cache, &table);
        /* check table first. */
        if (!table)
@@ -271,6 +275,13 @@ static int nft_cmd_chain_error(struct netlink_ctx *ctx, struct cmd *cmd,
                        return netlink_io_error(ctx, &chain->priority.loc,
                                                "Chains of type \"nat\" must have a priority value above -200");
 
+               if (nft_cache_update(ctx->nft, NFT_CACHE_TABLE | NFT_CACHE_CHAIN,
+                                    ctx->msgs, NULL) < 0) {
+                       return netlink_io_error(ctx, &chain->loc,
+                                               "Chain of type \"%s\" is not supported, perhaps kernel support is missing?",
+                                               chain->type.str);
+               }
+
                table = table_cache_find(&ctx->nft->cache.table_cache,
                                         cmd->handle.table.name, cmd->handle.family);
                if (table) {