summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2019-07-23 15:03:23 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2019-07-23 20:47:19 +0200
commit3ab02db5f836ae0cf9fe7fba616d7eb52139d537 (patch)
tree38004431535ef5da7de95a31e2b0783ba2e5d8c8
parentf4d0f16834f62e7e895f05f2e961d62487327f4b (diff)
cache: add NFT_CACHE_UPDATE and NFT_CACHE_FLUSHED flags
NFT_CACHE_FLUSHED tells cache_update() to skip the netlink dump to populate the cache, since the existing ruleset is going to flushed by this batch. NFT_CACHE_UPDATE tells rule_evaluate() to perform incremental updates to the cache based on the existing batch, this is required by the rule commands that use the index and the position selectors. This patch removes cache_flush() which is not required anymore. This cache removal is coming too late, in the evaluation phase, after the initial cache_update() invocation. Be careful with NFT_CACHE_UPDATE, this flag needs to be left in place if NFT_CACHE_FLUSHED is set on. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/cache.h2
-rw-r--r--include/rule.h3
-rw-r--r--src/cache.c4
-rw-r--r--src/evaluate.c8
-rw-r--r--src/rule.c33
5 files changed, 25 insertions, 25 deletions
diff --git a/include/cache.h b/include/cache.h
index d3502a8a..86a7eff7 100644
--- a/include/cache.h
+++ b/include/cache.h
@@ -30,6 +30,8 @@ enum cache_level_flags {
NFT_CACHE_CHAIN_BIT |
NFT_CACHE_RULE_BIT,
NFT_CACHE_FULL = __NFT_CACHE_MAX_BIT - 1,
+ NFT_CACHE_UPDATE = (1 << 30),
+ NFT_CACHE_FLUSHED = (1 << 31),
};
#endif /* _NFT_CACHE_H_ */
diff --git a/include/rule.h b/include/rule.h
index 67c3d331..ee881b9c 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -679,9 +679,8 @@ extern int do_command(struct netlink_ctx *ctx, struct cmd *cmd);
extern unsigned int cache_evaluate(struct nft_ctx *nft, struct list_head *cmds);
extern int cache_update(struct nft_ctx *ctx, enum cmd_ops cmd,
struct list_head *msgs);
-extern void cache_flush(struct nft_ctx *ctx, struct list_head *msgs);
+extern bool cache_needs_update(struct nft_cache *cache);
extern void cache_release(struct nft_cache *cache);
-extern bool cache_is_complete(struct nft_cache *cache, enum cmd_ops cmd);
struct timeout_protocol {
uint32_t array_size;
diff --git a/src/cache.c b/src/cache.c
index e04ead85..0d38034e 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -41,7 +41,7 @@ static unsigned int evaluate_cache_add(struct cmd *cmd, unsigned int flags)
if (cmd->handle.index.id ||
cmd->handle.position.id)
- flags |= NFT_CACHE_RULE;
+ flags |= NFT_CACHE_RULE | NFT_CACHE_UPDATE;
break;
default:
break;
@@ -72,6 +72,8 @@ static unsigned int evaluate_cache_flush(struct cmd *cmd, unsigned int flags)
flags |= NFT_CACHE_SET;
break;
case CMD_OBJ_RULESET:
+ flags |= NFT_CACHE_FLUSHED;
+ break;
default:
flags = NFT_CACHE_EMPTY;
break;
diff --git a/src/evaluate.c b/src/evaluate.c
index e7f16ba6..48c65cd2 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -3394,11 +3394,10 @@ static int rule_evaluate(struct eval_ctx *ctx, struct rule *rule,
return -1;
}
- /* add rules to cache only if it is complete enough to contain them */
- if (!cache_is_complete(&ctx->nft->cache, NFT_CACHE_RULE))
- return 0;
+ if (cache_needs_update(&ctx->nft->cache))
+ return rule_cache_update(ctx, op);
- return rule_cache_update(ctx, op);
+ return 0;
}
static uint32_t str2hooknum(uint32_t family, const char *hook)
@@ -3824,7 +3823,6 @@ static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd)
switch (cmd->obj) {
case CMD_OBJ_RULESET:
- cache_flush(ctx->nft, ctx->msgs);
break;
case CMD_OBJ_TABLE:
/* Flushing a table does not empty the sets in the table nor remove
diff --git a/src/rule.c b/src/rule.c
index 0ebe91e7..29360657 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -224,7 +224,7 @@ static int cache_init(struct netlink_ctx *ctx, unsigned int flags)
return 0;
}
-bool cache_is_complete(struct nft_cache *cache, unsigned int flags)
+static bool cache_is_complete(struct nft_cache *cache, unsigned int flags)
{
return (cache->flags & flags) == flags;
}
@@ -234,6 +234,11 @@ static bool cache_is_updated(struct nft_cache *cache, uint16_t genid)
return genid && genid == cache->genid;
}
+bool cache_needs_update(struct nft_cache *cache)
+{
+ return cache->flags & NFT_CACHE_UPDATE;
+}
+
int cache_update(struct nft_ctx *nft, unsigned int flags, struct list_head *msgs)
{
struct netlink_ctx ctx = {
@@ -242,7 +247,7 @@ int cache_update(struct nft_ctx *nft, unsigned int flags, struct list_head *msgs
.msgs = msgs,
};
struct nft_cache *cache = &nft->cache;
- uint32_t genid, genid_stop;
+ uint32_t genid, genid_stop, oldflags;
int ret;
replay:
ctx.seqnum = cache->seqnum++;
@@ -254,6 +259,14 @@ replay:
if (cache->genid)
cache_release(cache);
+ if (flags & NFT_CACHE_FLUSHED) {
+ oldflags = flags;
+ flags = NFT_CACHE_EMPTY;
+ if (oldflags & NFT_CACHE_UPDATE)
+ flags |= NFT_CACHE_UPDATE;
+ goto skip;
+ }
+
ret = cache_init(&ctx, flags);
if (ret < 0) {
cache_release(cache);
@@ -269,7 +282,7 @@ replay:
cache_release(cache);
goto replay;
}
-
+skip:
cache->genid = genid;
cache->flags = flags;
return 0;
@@ -285,20 +298,6 @@ static void __cache_flush(struct list_head *table_list)
}
}
-void cache_flush(struct nft_ctx *nft, struct list_head *msgs)
-{
- struct netlink_ctx ctx = {
- .list = LIST_HEAD_INIT(ctx.list),
- .nft = nft,
- .msgs = msgs,
- };
- struct nft_cache *cache = &nft->cache;
-
- __cache_flush(&cache->list);
- cache->genid = mnl_genid_get(&ctx);
- cache->flags = NFT_CACHE_FULL;
-}
-
void cache_release(struct nft_cache *cache)
{
__cache_flush(&cache->list);