[iptables PATCH 08/14] xtables-restore: Avoid cache population when flushing

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

 



When called without --noflush, don't fetch full ruleset from kernel but
merely list of tables and the current genid. Locally, initialize chain
lists and set have_cache to simulate an empty ruleset.

Doing so reduces execution time significantly if a large ruleset exists
in kernel space. A simple test case consisting of a dump with 100,000
rules can be restored within 15s on my testing VM. Restoring it a second
time took 21s before this patch and only 17s after it.

Signed-off-by: Phil Sutter <phil@xxxxxx>
---
 iptables/nft.c             | 27 ++++++++++++++++++++++++++-
 iptables/nft.h             |  1 +
 iptables/xtables-restore.c |  7 +++++--
 3 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/iptables/nft.c b/iptables/nft.c
index 7f0f9e1234ae4..820f3392dd495 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -882,7 +882,8 @@ static int flush_cache(struct nft_cache *c, const struct builtin_table *tables,
 		nftnl_chain_list_free(c->table[i].chains);
 		c->table[i].chains = NULL;
 	}
-	nftnl_table_list_free(c->tables);
+	if (c->tables)
+		nftnl_table_list_free(c->tables);
 	c->tables = NULL;
 
 	return 1;
@@ -1617,6 +1618,30 @@ void nft_build_cache(struct nft_handle *h)
 		__nft_build_cache(h);
 }
 
+void nft_fake_cache(struct nft_handle *h)
+{
+	int i;
+
+	if (h->have_cache)
+		return;
+
+	/* fetch tables so conditional table delete logic works */
+	if (!h->cache->tables)
+		fetch_table_cache(h);
+
+	for (i = 0; i < NFT_TABLE_MAX; i++) {
+		enum nft_table_type type = h->tables[i].type;
+
+		if (!h->tables[i].name ||
+		    h->cache->table[type].chains)
+			continue;
+
+		h->cache->table[type].chains = nftnl_chain_list_alloc();
+	}
+	mnl_genid_get(h, &h->nft_genid);
+	h->have_cache = true;
+}
+
 static void __nft_flush_cache(struct nft_handle *h)
 {
 	if (!h->cache_index) {
diff --git a/iptables/nft.h b/iptables/nft.h
index 43463d7f262e8..d9eb30a2a2413 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -74,6 +74,7 @@ int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
 int nft_init(struct nft_handle *h, const struct builtin_table *t);
 void nft_fini(struct nft_handle *h);
 void nft_build_cache(struct nft_handle *h);
+void nft_fake_cache(struct nft_handle *h);
 
 /*
  * Operations with tables.
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index f930f5ba2d167..d1486afedc480 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -96,6 +96,11 @@ void xtables_restore_parse(struct nft_handle *h,
 
 	line = 0;
 
+	if (h->noflush)
+		nft_build_cache(h);
+	else
+		nft_fake_cache(h);
+
 	/* Grab standard input. */
 	while (fgets(buffer, sizeof(buffer), p->in)) {
 		int ret = 0;
@@ -146,8 +151,6 @@ void xtables_restore_parse(struct nft_handle *h,
 			if (p->tablename && (strcmp(p->tablename, table) != 0))
 				continue;
 
-			nft_build_cache(h);
-
 			if (h->noflush == 0) {
 				DEBUGP("Cleaning all chains of table '%s'\n",
 					table);
-- 
2.23.0




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux