[iptables PATCH v3 07/21] nft: Simplify per table chain cache update

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Previously, each table's chain cache was potentially unallocated until
nftnl_chain_list_cb() saw a chain for it. This means said callback had to
check the chain_cache pointer for each chain belonging to that table.

In addition to the above, nft_chain_list_get() had to cover for the
possibility that a given table didn't have any chains at all in kernel,
so check requested table's chain cache once more and allocate it if
NULL.

Instead, simply iterate over all tables and preallocate their chain
caches prior to requesting the chain list from kernel. The only caveat
is to flush the chain cache completely before retrying in case of EINTR.

Signed-off-by: Phil Sutter <phil@xxxxxx>
---
 iptables/nft.c | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/iptables/nft.c b/iptables/nft.c
index a4a3d11ff5f35..b7ca6b4de51c6 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1286,12 +1286,6 @@ static int nftnl_chain_list_cb(const struct nlmsghdr *nlh, void *data)
 	if (!t)
 		goto out;
 
-	if (!h->table[t->type].chain_cache) {
-		h->table[t->type].chain_cache = nftnl_chain_list_alloc();
-		if (!h->table[t->type].chain_cache)
-			goto out;
-	}
-
 	nftnl_chain_list_add_tail(c, h->table[t->type].chain_cache);
 
 	return MNL_CB_OK;
@@ -1307,7 +1301,7 @@ struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
 	char buf[16536];
 	struct nlmsghdr *nlh;
 	const struct builtin_table *t;
-	int ret;
+	int i, ret;
 
 	t = nft_table_builtin_find(h, table);
 	if (!t)
@@ -1316,18 +1310,27 @@ struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
 	if (h->table[t->type].chain_cache)
 		return h->table[t->type].chain_cache;
 retry:
+	for (i = 0; i < NFT_TABLE_MAX; i++) {
+		enum nft_table_type type = h->tables[i].type;
+
+		if (!h->tables[i].name)
+			continue;
+
+		h->table[type].chain_cache = nftnl_chain_list_alloc();
+		if (!h->table[type].chain_cache)
+			return NULL;
+	}
+
 	nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family,
 					NLM_F_DUMP, h->seq);
 
 	ret = mnl_talk(h, nlh, nftnl_chain_list_cb, h);
 	if (ret < 0 && errno == EINTR) {
 		assert(nft_restart(h) >= 0);
+		flush_chain_cache(h, NULL);
 		goto retry;
 	}
 
-	if (!h->table[t->type].chain_cache)
-		h->table[t->type].chain_cache = nftnl_chain_list_alloc();
-
 	return h->table[t->type].chain_cache;
 }
 
-- 
2.19.0




[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux