]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
nft: Reduce overhead in nft_rule_find()
authorPhil Sutter <phil@nwl.cc>
Wed, 31 Jul 2024 00:16:05 +0000 (02:16 +0200)
committerPhil Sutter <phil@nwl.cc>
Wed, 14 Aug 2024 07:50:31 +0000 (09:50 +0200)
When iterating through the list of rules in a chain comparing against a
sample, there is no point in carrying that sample as nftnl_rule object
and converting into iptables_command_state object prior to each
comparison. Just do it up front and adjust the callback accordingly.

Signed-off-by: Phil Sutter <phil@nwl.cc>
iptables/nft.c

index 8b1803181b207969ca5efcb82215233ec020c878..88be5ede5171d904aec1c71649bd348e20d4cdf2 100644 (file)
@@ -2392,25 +2392,22 @@ static int __nft_rule_del(struct nft_handle *h, struct nftnl_rule *r)
 }
 
 static bool nft_rule_cmp(struct nft_handle *h, struct nftnl_rule *r,
-                        struct nftnl_rule *rule)
+                        struct iptables_command_state *cs)
 {
-       struct iptables_command_state _cs = {}, this = {}, *cs = &_cs;
-       bool ret = false, ret_this, ret_that;
+       struct iptables_command_state this = {};
+       bool ret = false, ret_this;
 
-       if (h->ops->init_cs) {
+       if (h->ops->init_cs)
                h->ops->init_cs(&this);
-               h->ops->init_cs(cs);
-       }
 
        ret_this = h->ops->rule_to_cs(h, r, &this);
-       ret_that = h->ops->rule_to_cs(h, rule, cs);
 
-       DEBUGP("comparing with... ");
+       DEBUGP("with ... ");
 #ifdef DEBUG_DEL
        nft_rule_print_save(h, r, NFT_RULE_APPEND, 0);
 #endif
-       if (!ret_this || !ret_that)
-               DEBUGP("Cannot convert rules: %d %d\n", ret_this, ret_that);
+       if (!ret_this)
+               DEBUGP("Cannot convert rule: %d\n", ret_this);
 
        if (!h->ops->is_same(cs, &this))
                goto out;
@@ -2434,7 +2431,6 @@ static bool nft_rule_cmp(struct nft_handle *h, struct nftnl_rule *r,
        ret = true;
 out:
        h->ops->clear_cs(&this);
-       h->ops->clear_cs(cs);
        return ret;
 }
 
@@ -2442,6 +2438,7 @@ static struct nftnl_rule *
 nft_rule_find(struct nft_handle *h, struct nft_chain *nc,
              struct nftnl_rule *rule, int rulenum)
 {
+       struct iptables_command_state cs = {};
        struct nftnl_chain *c = nc->nftnl;
        struct nftnl_rule *r;
        struct nftnl_rule_iter *iter;
@@ -2455,9 +2452,20 @@ nft_rule_find(struct nft_handle *h, struct nft_chain *nc,
        if (iter == NULL)
                return 0;
 
+       if (h->ops->init_cs)
+               h->ops->init_cs(&cs);
+
+       if (!h->ops->rule_to_cs(h, rule, &cs))
+               return NULL;
+
+       DEBUGP("comparing ... ");
+#ifdef DEBUG_DEL
+       nft_rule_print_save(h, rule, NFT_RULE_APPEND, 0);
+#endif
+
        r = nftnl_rule_iter_next(iter);
        while (r != NULL) {
-               found = nft_rule_cmp(h, r, rule);
+               found = nft_rule_cmp(h, r, &cs);
                if (found)
                        break;
                r = nftnl_rule_iter_next(iter);
@@ -2465,6 +2473,8 @@ nft_rule_find(struct nft_handle *h, struct nft_chain *nc,
 
        nftnl_rule_iter_destroy(iter);
 
+       h->ops->clear_cs(&cs);
+
        return found ? r : NULL;
 }