]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
libnftables: avoid repeated command list traversal on errors
authorJindrich Makovicka <makovick@gmail.com>
Sat, 2 May 2020 11:52:06 +0000 (13:52 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 14 Sep 2020 11:47:37 +0000 (13:47 +0200)
Because the command seqnums are monotonic, repeated traversals
of the cmds list from the beginning are not necessary as long as
the error seqnums are also monotonic.

Signed-off-by: Jindrich Makovicka <makovick@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/libnftables.c

index fce52ad4003b0d9f0c280ad5af0c1b81a10bb891..a180a9a30b3dda248610f194d96afd1b664f224f 100644 (file)
@@ -21,7 +21,7 @@ static int nft_netlink(struct nft_ctx *nft,
                       struct list_head *cmds, struct list_head *msgs,
                       struct mnl_socket *nf_sock)
 {
-       uint32_t batch_seqnum, seqnum = 0, num_cmds = 0;
+       uint32_t batch_seqnum, seqnum = 0, last_seqnum = UINT32_MAX, num_cmds = 0;
        struct netlink_ctx ctx = {
                .nft  = nft,
                .msgs = msgs,
@@ -65,7 +65,14 @@ static int nft_netlink(struct nft_ctx *nft,
                ret = -1;
 
        list_for_each_entry_safe(err, tmp, &err_list, head) {
-               list_for_each_entry(cmd, cmds, list) {
+               /* cmd seqnums are monotonic: only reset the starting position
+                * if the error seqnum is lower than the previous one.
+                */
+               if (err->seqnum < last_seqnum)
+                       cmd = list_first_entry(cmds, struct cmd, list);
+
+               list_for_each_entry_from(cmd, cmds, list) {
+                       last_seqnum = cmd->seqnum;
                        if (err->seqnum == cmd->seqnum ||
                            err->seqnum == batch_seqnum) {
                                nft_cmd_error(&ctx, cmd, err);
@@ -76,6 +83,11 @@ static int nft_netlink(struct nft_ctx *nft,
                                }
                        }
                }
+
+               if (&cmd->list == cmds) {
+                       /* not found, rewind */
+                       last_seqnum = UINT32_MAX;
+               }
        }
 out:
        mnl_batch_reset(ctx.batch);