[PATCH nft] src: update cache if cmd is more specific

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

 



If we've done a partial fetch of the cache and the genid is the same the
cache update will be skipped without fetching the needed items. This
change flushes the cache if the new request is more specific than the
current cache - forcing a cache update which includes the needed items.

Fixes: 816d8c7659c1 ("Support 'add/insert rule index <IDX>'")
---
# NFT=/usr/sbin/nft ./run-tests.sh ./testcases/cache/0003_cache_update_0                                                                                                                                                                                      
I: using nft binary /usr/sbin/nft                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                
W: [FAILED]     ./testcases/cache/0003_cache_update_0: got 1
Error: Could not process rule: No such file or directory                                                                                                                                                                                                                        
add table ip t2; add chain ip t2 c
                              ^^
/dev/stdin:1:18-24: Error: Could not process rule: No such file or directory
add rule ip t4 c index 0 drop
                 ^^^^^^^

I: results: [OK] 0 [FAILED] 1 [TOTAL] 1

# ./run-tests.sh ./testcases/cache/0003_cache_update_0                                                                                                                                                                                                        
I: using nft binary ./../../src/nft                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                
I: [OK]         ./testcases/cache/0003_cache_update_0
Error: No such file or directory; did you mean table 't' in family ip?                                                                                                                                                                                                          
add table ip t2; add chain ip t2 c
                              ^^

I: results: [OK] 1 [FAILED] 0 [TOTAL] 1
---
 include/nftables.h                              |  1 +
 src/rule.c                                      | 12 ++++++++++++
 tests/shell/testcases/cache/0003_cache_update_0 | 14 ++++++++++++++
 3 files changed, 27 insertions(+)

diff --git a/include/nftables.h b/include/nftables.h
index b17a16a4adef..bb9bb2091716 100644
--- a/include/nftables.h
+++ b/include/nftables.h
@@ -81,6 +81,7 @@ struct nft_cache {
 	uint16_t		genid;
 	struct list_head	list;
 	uint32_t		seqnum;
+	uint32_t		cmd;
 };
 
 struct mnl_socket;
diff --git a/src/rule.c b/src/rule.c
index dc75c7cd5fb0..afe37cd90b1d 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -220,6 +220,15 @@ static int cache_init(struct netlink_ctx *ctx, enum cmd_ops cmd)
 	return 0;
 }
 
+static int cache_needs_more(enum cmd_ops old_cmd, enum cmd_ops cmd)
+{
+	if (cmd == CMD_LIST && old_cmd != CMD_LIST)
+		return 1;
+	if (cmd == CMD_RESET && old_cmd != CMD_RESET)
+		return 1;
+	return 0;
+}
+
 int cache_update(struct nft_ctx *nft, enum cmd_ops cmd, struct list_head *msgs)
 {
 	uint16_t genid;
@@ -235,6 +244,8 @@ int cache_update(struct nft_ctx *nft, enum cmd_ops cmd, struct list_head *msgs)
 replay:
 	ctx.seqnum = cache->seqnum++;
 	genid = mnl_genid_get(&ctx);
+	if (cache->genid && cache_needs_more(cache->cmd, cmd))
+		cache_release(cache);
 	if (genid && genid == cache->genid)
 		return 0;
 	if (cache->genid)
@@ -250,6 +261,7 @@ replay:
 		return -1;
 	}
 	cache->genid = genid;
+	cache->cmd = cmd;
 	return 0;
 }
 
diff --git a/tests/shell/testcases/cache/0003_cache_update_0 b/tests/shell/testcases/cache/0003_cache_update_0
index deb45db2c43b..fa9b5df380a4 100755
--- a/tests/shell/testcases/cache/0003_cache_update_0
+++ b/tests/shell/testcases/cache/0003_cache_update_0
@@ -27,3 +27,17 @@ EOF
 $NFT -i >/dev/null <<EOF
 add table ip t3; add chain ip t c
 EOF
+
+# The following test exposes a problem with incremental cache update when
+# reading commands from a file that add a rule using the "index" keyword.
+#
+# add rule ip t4 c meta l4proto icmp accept -> rule to reference in next step
+# add rule ip t4 c index 0 drop -> index 0 is not found due to rule cache not
+#                                  being updated
+$NFT -i >/dev/null <<EOF
+add table ip t4; add chain ip t4 c
+add rule ip t4 c meta l4proto icmp accept
+EOF
+$NFT -f - >/dev/null <<EOF
+add rule ip t4 c index 0 drop
+EOF
-- 
2.20.1




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

  Powered by Linux