[PATCH v2,xtables 3/4] xtables: rework rule cache logic

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

 



Perform incremental tracking on rule cache updates, instead of flushing
and resynchronizing with the kernel over and over again.

Note that there is no need to call flush_rule_cache() from
nft_rule_delete() and nft_rule_delete_num(), since __nft_rule_del()
already deletes the rule from the list.

Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
---
v2: set built-in table initialization to false on *tablename.

 iptables/nft.c | 87 ++++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 58 insertions(+), 29 deletions(-)

diff --git a/iptables/nft.c b/iptables/nft.c
index 6940b30dedf1..03a9f29df0ee 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -681,13 +681,30 @@ int nft_init(struct nft_handle *h, struct builtin_table *t)
 	return 0;
 }
 
-static void flush_rule_cache(struct nft_handle *h)
+static int __flush_rule_cache(struct nftnl_rule *r, void *data)
+{
+	const char *tablename = data;
+
+	if (!strcmp(nftnl_rule_get_str(r, NFTNL_RULE_TABLE), tablename)) {
+		nftnl_rule_list_del(r);
+		nftnl_rule_free(r);
+	}
+
+	return 0;
+}
+
+static void flush_rule_cache(struct nft_handle *h, const char *tablename)
 {
 	if (!h->rule_cache)
 		return;
 
-	nftnl_rule_list_free(h->rule_cache);
-	h->rule_cache = NULL;
+	if (tablename) {
+		nftnl_rule_list_foreach(h->rule_cache, __flush_rule_cache,
+					(void *)tablename);
+	} else {
+		nftnl_rule_list_free(h->rule_cache);
+		h->rule_cache = NULL;
+	}
 }
 
 static int __flush_chain_cache(struct nftnl_chain *c, void *data)
@@ -719,7 +736,7 @@ static void flush_chain_cache(struct nft_handle *h, const char *tablename)
 void nft_fini(struct nft_handle *h)
 {
 	flush_chain_cache(h, NULL);
-	flush_rule_cache(h);
+	flush_rule_cache(h, NULL);
 	mnl_socket_close(h->nl);
 }
 
@@ -1036,6 +1053,8 @@ err:
 	return NULL;
 }
 
+static struct nftnl_rule_list *nft_rule_list_get(struct nft_handle *h);
+
 int
 nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
 		void *data, uint64_t handle, bool verbose)
@@ -1062,7 +1081,10 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
 	if (batch_rule_add(h, type, r) < 0)
 		nftnl_rule_free(r);
 
-	flush_rule_cache(h);
+	nft_rule_list_get(h);
+
+	nftnl_rule_list_add_tail(r, h->rule_cache);
+
 	return 1;
 }
 
@@ -1405,9 +1427,8 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table)
 next:
 		c = nftnl_chain_list_iter_next(iter);
 	}
-
 	nftnl_chain_list_iter_destroy(iter);
-	flush_rule_cache(h);
+	flush_rule_cache(h, table);
 err:
 	/* the core expects 1 for success and 0 for error */
 	return ret == 0 ? 1 : 0;
@@ -1702,6 +1723,7 @@ int nft_for_each_table(struct nft_handle *h,
 
 static int __nft_table_flush(struct nft_handle *h, const char *table)
 {
+	struct builtin_table *_t;
 	struct nftnl_table *t;
 
 	t = nftnl_table_alloc();
@@ -1712,7 +1734,12 @@ static int __nft_table_flush(struct nft_handle *h, const char *table)
 
 	batch_table_add(h, NFT_COMPAT_TABLE_FLUSH, t);
 
+	_t = nft_table_builtin_find(h, table);
+	assert(t);
+	_t->initialized = false;
+
 	flush_chain_cache(h, table);
+	flush_rule_cache(h, table);
 
 	return 0;
 }
@@ -1753,6 +1780,10 @@ next:
 		t = nftnl_table_list_iter_next(iter);
 	}
 
+	h->rule_cache = nftnl_rule_list_alloc();
+	if (h->rule_cache == NULL)
+		return -1;
+
 err_table_iter:
 	nftnl_table_list_iter_destroy(iter);
 err_table_list:
@@ -1864,12 +1895,10 @@ int nft_rule_delete(struct nft_handle *h, const char *chain,
 	} else
 		errno = ENOENT;
 
-	flush_rule_cache(h);
-
 	return ret;
 }
 
-static int
+static struct nftnl_rule *
 nft_rule_add(struct nft_handle *h, const char *chain,
 	     const char *table, struct iptables_command_state *cs,
 	     uint64_t handle, bool verbose)
@@ -1878,25 +1907,24 @@ nft_rule_add(struct nft_handle *h, const char *chain,
 
 	r = nft_rule_new(h, chain, table, cs);
 	if (r == NULL)
-		return 0;
+		return NULL;
 
 	if (handle > 0)
 		nftnl_rule_set_u64(r, NFTNL_RULE_POSITION, handle);
 
 	if (batch_rule_add(h, NFT_COMPAT_RULE_INSERT, r) < 0) {
 		nftnl_rule_free(r);
-		return 0;
+		return NULL;
 	}
 
-	flush_rule_cache(h);
-	return 1;
+	return r;
 }
 
 int nft_rule_insert(struct nft_handle *h, const char *chain,
 		    const char *table, void *data, int rulenum, bool verbose)
 {
+	struct nftnl_rule *r, *new_rule;
 	struct nftnl_rule_list *list;
-	struct nftnl_rule *r;
 	uint64_t handle = 0;
 
 	/* If built-in chains don't exist for this table, create them */
@@ -1917,11 +1945,9 @@ int nft_rule_insert(struct nft_handle *h, const char *chain,
 			 */
 			r = nft_rule_find(h, list, chain, table, data,
 					  rulenum - 1);
-			if (r != NULL) {
-				flush_rule_cache(h);
+			if (r != NULL)
 				return nft_rule_append(h, chain, table, data,
 						       0, verbose);
-			}
 
 			errno = ENOENT;
 			goto err;
@@ -1929,13 +1955,21 @@ int nft_rule_insert(struct nft_handle *h, const char *chain,
 
 		handle = nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE);
 		DEBUGP("adding after rule handle %"PRIu64"\n", handle);
-
-		flush_rule_cache(h);
+	} else {
+		nft_rule_list_get(h);
 	}
 
-	return nft_rule_add(h, chain, table, data, handle, verbose);
+	new_rule = nft_rule_add(h, chain, table, data, handle, verbose);
+	if (!new_rule)
+		goto err;
+
+	if (handle)
+		nftnl_rule_list_insert_at(new_rule, r);
+	else
+		nftnl_rule_list_add(new_rule, h->rule_cache);
+
+	return 1;
 err:
-	flush_rule_cache(h);
 	return 0;
 }
 
@@ -1963,8 +1997,6 @@ int nft_rule_delete_num(struct nft_handle *h, const char *chain,
 	} else
 		errno = ENOENT;
 
-	flush_rule_cache(h);
-
 	return ret;
 }
 
@@ -1987,14 +2019,14 @@ int nft_rule_replace(struct nft_handle *h, const char *chain,
 			(unsigned long long)
 			nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE));
 
+		nftnl_rule_list_del(r);
+
 		ret = nft_rule_append(h, chain, table, data,
 				      nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE),
 				      verbose);
 	} else
 		errno = ENOENT;
 
-	flush_rule_cache(h);
-
 	return ret;
 }
 
@@ -2275,8 +2307,6 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain,
 			       false);
 
 error:
-	flush_rule_cache(h);
-
 	return ret;
 }
 
@@ -2314,7 +2344,6 @@ static void nft_compat_rule_batch_add(struct nft_handle *h, uint16_t type,
 				       type, h->family, flags, seq);
 	nftnl_rule_nlmsg_build_payload(nlh, rule);
 	nft_rule_print_debug(rule, nlh);
-	nftnl_rule_free(rule);
 }
 
 static int nft_action(struct nft_handle *h, int action)
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



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

  Powered by Linux