]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
nft: Speed up immediate parsing
authorPhil Sutter <phil@nwl.cc>
Tue, 1 Mar 2022 18:46:21 +0000 (19:46 +0100)
committerPhil Sutter <phil@nwl.cc>
Thu, 10 Mar 2022 16:38:31 +0000 (17:38 +0100)
Parsing of rules which jump to a chain pointlessly causes a call to
xtables_find_target() despite the code already knowing the outcome.

Avoid the significant delay for rulesets with many chain jumps by
performing the (standard) target lookup only for accept/drop/return
verdicts.

From a biased test-case on my VM:

| # iptables-nft-save | grep -c -- '-j'
| 133943
| # time ./old/iptables-nft-save >/dev/null
| real 0m45.566s
| user 0m1.308s
| sys 0m8.430s
| # time ./new/iptables-nft-save >/dev/null
| real 0m3.547s
| user 0m0.762s
| sys 0m2.476s

Signed-off-by: Phil Sutter <phil@nwl.cc>
Acked-by: Florian Westphal <fw@strlen.de>
iptables/nft-bridge.c
iptables/nft-shared.c

index d6a0d6e518fcb7582147ad39143c1f3bbd972bb5..d342858e1d9d856310cf764434b86e585907c910 100644 (file)
@@ -502,6 +502,7 @@ static void nft_bridge_parse_target(struct xtables_target *t, void *data)
        }
 
        cs->target = t;
+       cs->jumpto = t->name;
 }
 
 static void nft_rule_to_ebtables_command_state(struct nft_handle *h,
index daa251ae0982a8430995bb104fd4972202884523..861aa0642061e76cb7020f77be2d015684e51024 100644 (file)
@@ -907,6 +907,8 @@ static void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
 {
        const char *chain = nftnl_expr_get_str(e, NFTNL_EXPR_IMM_CHAIN);
        struct iptables_command_state *cs = ctx->cs;
+       struct xt_entry_target *t;
+       uint32_t size;
        int verdict;
 
        if (nftnl_expr_is_set(e, NFTNL_EXPR_IMM_DATA)) {
@@ -943,8 +945,21 @@ static void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
                /* fall through */
        case NFT_JUMP:
                cs->jumpto = chain;
-               break;
+               /* fall through */
+       default:
+               return;
        }
+
+       cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD);
+       if (!cs->target)
+               return;
+
+       size = XT_ALIGN(sizeof(struct xt_entry_target)) + cs->target->size;
+       t = xtables_calloc(1, size);
+       t->u.target_size = size;
+       t->u.user.revision = cs->target->revision;
+       strcpy(t->u.user.name, cs->jumpto);
+       cs->target->t = t;
 }
 
 static void nft_parse_limit(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
@@ -1143,25 +1158,8 @@ void nft_rule_to_iptables_command_state(struct nft_handle *h,
                }
        }
 
-       if (cs->target != NULL) {
-               cs->jumpto = cs->target->name;
-       } else if (cs->jumpto != NULL) {
-               struct xt_entry_target *t;
-               uint32_t size;
-
-               cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD);
-               if (!cs->target)
-                       return;
-
-               size = XT_ALIGN(sizeof(struct xt_entry_target)) + cs->target->size;
-               t = xtables_calloc(1, size);
-               t->u.target_size = size;
-               t->u.user.revision = cs->target->revision;
-               strcpy(t->u.user.name, cs->jumpto);
-               cs->target->t = t;
-       } else {
+       if (!cs->jumpto)
                cs->jumpto = "";
-       }
 }
 
 void nft_clear_iptables_command_state(struct iptables_command_state *cs)
@@ -1326,6 +1324,7 @@ void nft_ipv46_parse_target(struct xtables_target *t, void *data)
        struct iptables_command_state *cs = data;
 
        cs->target = t;
+       cs->jumpto = t->name;
 }
 
 void nft_check_xt_legacy(int family, bool is_ipt_save)