From c41b98babd55f35834e5fea599a914d69d60a9bd Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Wed, 28 Aug 2019 12:33:55 +0200 Subject: nft: Optimize flushing all chains of a table Leverage nftables' support for flushing all chains of a table by omitting NFTNL_RULE_CHAIN attribute in NFT_MSG_DELRULE payload. The only caveat is with verbose output, as that still requires to have a list of (existing) chains to iterate over. Apart from that, implementing this shortcut is pretty straightforward: Don't retrieve a chain list and just call __nft_rule_flush() directly which doesn't set above attribute if chain name pointer is NULL. A bigger deal is keeping rule cache consistent: Instead of just clearing rule list for each flushed chain, flush_rule_cache() is updated to iterate over all cached chains of the given table, clearing their rule lists if not called for a specific chain. While being at it, sort local variable declarations in nft_rule_flush() from longest to shortest and drop the loop-local 'chain_name' variable (but instead use 'chain' function parameter which is not used at that point). Signed-off-by: Phil Sutter Acked-by: Pablo Neira Ayuso --- iptables/nft-cache.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'iptables/nft-cache.c') diff --git a/iptables/nft-cache.c b/iptables/nft-cache.c index 64dcda57..c55970d0 100644 --- a/iptables/nft-cache.c +++ b/iptables/nft-cache.c @@ -384,7 +384,7 @@ static void __nft_flush_cache(struct nft_handle *h) } } -static int __flush_rule_cache(struct nftnl_rule *r, void *data) +static int ____flush_rule_cache(struct nftnl_rule *r, void *data) { nftnl_rule_list_del(r); nftnl_rule_free(r); @@ -392,9 +392,25 @@ static int __flush_rule_cache(struct nftnl_rule *r, void *data) return 0; } -void flush_rule_cache(struct nftnl_chain *c) +static int __flush_rule_cache(struct nftnl_chain *c, void *data) { - nftnl_rule_foreach(c, __flush_rule_cache, NULL); + return nftnl_rule_foreach(c, ____flush_rule_cache, NULL); +} + +int flush_rule_cache(struct nft_handle *h, const char *table, + struct nftnl_chain *c) +{ + const struct builtin_table *t; + + if (c) + return __flush_rule_cache(c, NULL); + + t = nft_table_builtin_find(h, table); + if (!t || !h->cache->table[t->type].chains) + return 0; + + return nftnl_chain_list_foreach(h->cache->table[t->type].chains, + __flush_rule_cache, NULL); } static int __flush_chain_cache(struct nftnl_chain *c, void *data) -- cgit v1.2.3