Hi Phil, On Tue, Oct 08, 2019 at 06:14:40PM +0200, Phil Sutter wrote: > Replace the simple have_cache boolean by a cache level indicator > defining how complete the cache is. Since have_cache indicated full > cache (including rules), make code depending on it check for cache level > NFT_CL_RULES. > > Core cache fetching routine __nft_build_cache() accepts a new level via > parameter and raises cache completeness to that level. > > Signed-off-by: Phil Sutter <phil@xxxxxx> > --- > iptables/nft-cache.c | 51 +++++++++++++++++++++++++++++++------------- > iptables/nft.h | 9 +++++++- > 2 files changed, 44 insertions(+), 16 deletions(-) > > diff --git a/iptables/nft-cache.c b/iptables/nft-cache.c > index 5444419a5cc3b..22a87e94efd76 100644 > --- a/iptables/nft-cache.c > +++ b/iptables/nft-cache.c > @@ -224,30 +224,49 @@ static int fetch_rule_cache(struct nft_handle *h) > return 0; > } > > -static void __nft_build_cache(struct nft_handle *h) > +static void __nft_build_cache(struct nft_handle *h, enum nft_cache_level level) > { > uint32_t genid_start, genid_stop; > > + if (level <= h->cache_level) > + return; > retry: > mnl_genid_get(h, &genid_start); > - fetch_table_cache(h); > - fetch_chain_cache(h); > - fetch_rule_cache(h); > - h->have_cache = true; > - mnl_genid_get(h, &genid_stop); > > + switch (h->cache_level) { > + case NFT_CL_NONE: > + fetch_table_cache(h); > + if (level == NFT_CL_TABLES) > + break; > + /* fall through */ > + case NFT_CL_TABLES: If the existing level is TABLES and use wants chains, then you have to invalidate the existing table cache, then fetch the tables and chains to make sure cache is consistent. I mean, extending an existing cache might lead to inconsistencies. Am I missing anything? > + fetch_chain_cache(h); > + if (level == NFT_CL_CHAINS) > + break; > + /* fall through */ > + case NFT_CL_CHAINS: > + fetch_rule_cache(h); > + if (level == NFT_CL_RULES) > + break; > + /* fall through */ > + case NFT_CL_RULES: > + break; > + } > + > + mnl_genid_get(h, &genid_stop); > if (genid_start != genid_stop) { > flush_chain_cache(h, NULL); > goto retry; > } > > + h->cache_level = level; > h->nft_genid = genid_start; > }