From: Jindrich Makovicka <makovick@xxxxxxxxx> 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@xxxxxxxxx> Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> --- via netfilter's bugzilla. src/libnftables.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/libnftables.c b/src/libnftables.c index fce52ad4003b..a180a9a30b3d 100644 --- a/src/libnftables.c +++ b/src/libnftables.c @@ -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); -- 2.20.1