diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cache.c | 86 | ||||
-rw-r--r-- | src/evaluate.c | 3 | ||||
-rw-r--r-- | src/libnftables.c | 6 | ||||
-rw-r--r-- | src/rule.c | 106 |
4 files changed, 97 insertions, 104 deletions
diff --git a/src/cache.c b/src/cache.c index d7153f6f..d371c548 100644 --- a/src/cache.c +++ b/src/cache.c @@ -11,112 +11,116 @@ #include <rule.h> #include <erec.h> #include <utils.h> +#include <cache.h> -static unsigned int evaluate_cache_add(struct cmd *cmd) +static unsigned int evaluate_cache_add(struct cmd *cmd, unsigned int flags) { - unsigned int completeness = CMD_INVALID; - switch (cmd->obj) { case CMD_OBJ_SETELEM: - case CMD_OBJ_SET: - case CMD_OBJ_CHAIN: - case CMD_OBJ_FLOWTABLE: - completeness = cmd->op; + flags |= NFT_CACHE_SETELEM; break; case CMD_OBJ_RULE: - if (cmd->handle.index.id) - completeness = CMD_LIST; + if (cmd->handle.index.id || + cmd->handle.position.id) + flags |= NFT_CACHE_RULE; break; default: break; } - return completeness; + return flags; } -static unsigned int evaluate_cache_del(struct cmd *cmd) +static unsigned int evaluate_cache_del(struct cmd *cmd, unsigned int flags) { - unsigned int completeness = CMD_INVALID; - switch (cmd->obj) { case CMD_OBJ_SETELEM: - completeness = cmd->op; + flags |= NFT_CACHE_SETELEM; break; default: break; } - return completeness; + return flags; } -static unsigned int evaluate_cache_flush(struct cmd *cmd) +static unsigned int evaluate_cache_flush(struct cmd *cmd, unsigned int flags) { - unsigned int completeness = CMD_INVALID; - switch (cmd->obj) { - case CMD_OBJ_RULESET: - completeness = __CMD_FLUSH_RULESET; - break; case CMD_OBJ_SET: case CMD_OBJ_MAP: case CMD_OBJ_METER: - completeness = cmd->op; + flags |= NFT_CACHE_SET; break; + case CMD_OBJ_RULESET: default: + flags = NFT_CACHE_EMPTY; break; } - return completeness; + return flags; } -static unsigned int evaluate_cache_rename(struct cmd *cmd) +static unsigned int evaluate_cache_rename(struct cmd *cmd, unsigned int flags) { - unsigned int completeness = CMD_INVALID; - switch (cmd->obj) { case CMD_OBJ_CHAIN: - completeness = cmd->op; + flags |= NFT_CACHE_CHAIN; break; default: break; } - return completeness; + return flags; } -int cache_evaluate(struct nft_ctx *nft, struct list_head *cmds) +unsigned int cache_evaluate(struct nft_ctx *nft, struct list_head *cmds) { - unsigned int echo_completeness = CMD_INVALID; - unsigned int completeness = CMD_INVALID; + unsigned int flags = NFT_CACHE_EMPTY; struct cmd *cmd; list_for_each_entry(cmd, cmds, list) { switch (cmd->op) { case CMD_ADD: case CMD_INSERT: - case CMD_REPLACE: - if (nft_output_echo(&nft->output)) - echo_completeness = cmd->op; - + if (nft_output_echo(&nft->output)) { + flags = NFT_CACHE_FULL; + break; + } + + flags |= NFT_CACHE_TABLE | + NFT_CACHE_CHAIN | + NFT_CACHE_SET | + NFT_CACHE_FLOWTABLE | + NFT_CACHE_OBJECT; /* Fall through */ case CMD_CREATE: - completeness = evaluate_cache_add(cmd); + flags = evaluate_cache_add(cmd, flags); + break; + case CMD_REPLACE: + flags = NFT_CACHE_FULL; break; case CMD_DELETE: - completeness = evaluate_cache_del(cmd); + flags |= NFT_CACHE_TABLE | + NFT_CACHE_CHAIN | + NFT_CACHE_SET | + NFT_CACHE_FLOWTABLE | + NFT_CACHE_OBJECT; + + flags = evaluate_cache_del(cmd, flags); break; case CMD_GET: case CMD_LIST: case CMD_RESET: case CMD_EXPORT: case CMD_MONITOR: - completeness = cmd->op; + flags |= NFT_CACHE_FULL; break; case CMD_FLUSH: - completeness = evaluate_cache_flush(cmd); + flags = evaluate_cache_flush(cmd, flags); break; case CMD_RENAME: - completeness = evaluate_cache_rename(cmd); + flags = evaluate_cache_rename(cmd, flags); break; case CMD_DESCRIBE: case CMD_IMPORT: @@ -126,5 +130,5 @@ int cache_evaluate(struct nft_ctx *nft, struct list_head *cmds) } } - return max(completeness, echo_completeness); + return flags; } diff --git a/src/evaluate.c b/src/evaluate.c index 73a4be33..511f9f14 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -29,6 +29,7 @@ #include <netlink.h> #include <time.h> #include <rule.h> +#include <cache.h> #include <erec.h> #include <gmputil.h> #include <utils.h> @@ -3294,7 +3295,7 @@ static int rule_evaluate(struct eval_ctx *ctx, struct rule *rule, } /* add rules to cache only if it is complete enough to contain them */ - if (!cache_is_complete(&ctx->nft->cache, CMD_LIST)) + if (!cache_is_complete(&ctx->nft->cache, NFT_CACHE_RULE)) return 0; return rule_cache_update(ctx, op); diff --git a/src/libnftables.c b/src/libnftables.c index abd133be..dccb8ab4 100644 --- a/src/libnftables.c +++ b/src/libnftables.c @@ -381,11 +381,11 @@ static int nft_parse_bison_filename(struct nft_ctx *nft, const char *filename, static int nft_evaluate(struct nft_ctx *nft, struct list_head *msgs, struct list_head *cmds) { - unsigned int completeness; + unsigned int flags; struct cmd *cmd; - completeness = cache_evaluate(nft, cmds); - if (cache_update(nft, completeness, msgs) < 0) + flags = cache_evaluate(nft, cmds); + if (cache_update(nft, flags, msgs) < 0) return -1; list_for_each_entry(cmd, cmds, list) { @@ -24,6 +24,7 @@ #include <mnl.h> #include <misspell.h> #include <json.h> +#include <cache.h> #include <libnftnl/common.h> #include <libnftnl/ruleset.h> @@ -147,97 +148,85 @@ static int cache_init_tables(struct netlink_ctx *ctx, struct handle *h, return 0; } -static int cache_init_objects(struct netlink_ctx *ctx, enum cmd_ops cmd) +static int cache_init_objects(struct netlink_ctx *ctx, unsigned int flags) { + struct rule *rule, *nrule; struct table *table; struct chain *chain; - struct rule *rule, *nrule; struct set *set; int ret; list_for_each_entry(table, &ctx->nft->cache.list, list) { - ret = netlink_list_sets(ctx, &table->handle); - list_splice_tail_init(&ctx->list, &table->sets); - - if (ret < 0) - return -1; - - list_for_each_entry(set, &table->sets, list) { - ret = netlink_list_setelems(ctx, &set->handle, set); + if (flags & NFT_CACHE_SET_BIT) { + ret = netlink_list_sets(ctx, &table->handle); + list_splice_tail_init(&ctx->list, &table->sets); if (ret < 0) return -1; } - - ret = netlink_list_chains(ctx, &table->handle); - if (ret < 0) - return -1; - list_splice_tail_init(&ctx->list, &table->chains); - - ret = netlink_list_flowtables(ctx, &table->handle); - if (ret < 0) - return -1; - list_splice_tail_init(&ctx->list, &table->flowtables); - - if (cmd != CMD_RESET) { + if (flags & NFT_CACHE_SETELEM_BIT) { + list_for_each_entry(set, &table->sets, list) { + ret = netlink_list_setelems(ctx, &set->handle, + set); + if (ret < 0) + return -1; + } + } + if (flags & NFT_CACHE_CHAIN_BIT) { + ret = netlink_list_chains(ctx, &table->handle); + if (ret < 0) + return -1; + list_splice_tail_init(&ctx->list, &table->chains); + } + if (flags & NFT_CACHE_FLOWTABLE_BIT) { + ret = netlink_list_flowtables(ctx, &table->handle); + if (ret < 0) + return -1; + list_splice_tail_init(&ctx->list, &table->flowtables); + } + if (flags & NFT_CACHE_OBJECT_BIT) { ret = netlink_list_objs(ctx, &table->handle); if (ret < 0) return -1; list_splice_tail_init(&ctx->list, &table->objs); } - /* Skip caching other objects to speed up things: We only need - * a full cache when listing the existing ruleset. - */ - if (cmd != CMD_LIST) - continue; - - ret = netlink_list_rules(ctx, &table->handle); - list_for_each_entry_safe(rule, nrule, &ctx->list, list) { - chain = chain_lookup(table, &rule->handle); - list_move_tail(&rule->list, &chain->rules); + if (flags & NFT_CACHE_RULE_BIT) { + ret = netlink_list_rules(ctx, &table->handle); + list_for_each_entry_safe(rule, nrule, &ctx->list, list) { + chain = chain_lookup(table, &rule->handle); + list_move_tail(&rule->list, &chain->rules); + } + if (ret < 0) + return -1; } - - if (ret < 0) - return -1; } return 0; } -static int cache_init(struct netlink_ctx *ctx, enum cmd_ops cmd) +static int cache_init(struct netlink_ctx *ctx, unsigned int flags) { struct handle handle = { .family = NFPROTO_UNSPEC, }; int ret; - if (cmd == __CMD_FLUSH_RULESET) + if (flags == NFT_CACHE_EMPTY) return 0; + /* assume NFT_CACHE_TABLE is always set. */ ret = cache_init_tables(ctx, &handle, &ctx->nft->cache); if (ret < 0) return ret; - ret = cache_init_objects(ctx, cmd); + ret = cache_init_objects(ctx, flags); if (ret < 0) return ret; return 0; } -/* Return a "score" of how complete local cache will be if - * cache_init_objects() ran for given cmd. Higher value - * means more complete. */ -static int cache_completeness(enum cmd_ops cmd) +bool cache_is_complete(struct nft_cache *cache, unsigned int flags) { - if (cmd == CMD_LIST) - return 3; - if (cmd != CMD_RESET) - return 2; - return 1; -} - -bool cache_is_complete(struct nft_cache *cache, enum cmd_ops cmd) -{ - return cache_completeness(cache->cmd) >= cache_completeness(cmd); + return (cache->flags & flags) == flags; } static bool cache_is_updated(struct nft_cache *cache, uint16_t genid) @@ -245,7 +234,7 @@ static bool cache_is_updated(struct nft_cache *cache, uint16_t genid) return genid && genid == cache->genid; } -int cache_update(struct nft_ctx *nft, enum cmd_ops cmd, struct list_head *msgs) +int cache_update(struct nft_ctx *nft, unsigned int flags, struct list_head *msgs) { struct netlink_ctx ctx = { .list = LIST_HEAD_INIT(ctx.list), @@ -259,14 +248,14 @@ 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_is_complete(cache, cmd) && + if (cache_is_complete(cache, flags) && cache_is_updated(cache, genid)) return 0; if (cache->genid) cache_release(cache); - ret = cache_init(&ctx, cmd); + ret = cache_init(&ctx, flags); if (ret < 0) { cache_release(cache); if (errno == EINTR) { @@ -283,7 +272,7 @@ replay: } cache->genid = genid; - cache->cmd = cmd; + cache->flags = flags; return 0; } @@ -308,15 +297,14 @@ void cache_flush(struct nft_ctx *nft, struct list_head *msgs) __cache_flush(&cache->list); cache->genid = mnl_genid_get(&ctx); - cache->cmd = CMD_LIST; + cache->flags = NFT_CACHE_FULL; } void cache_release(struct nft_cache *cache) { __cache_flush(&cache->list); cache->genid = 0; - cache->cmd = CMD_INVALID; - + cache->flags = NFT_CACHE_EMPTY; } /* internal ID to uniquely identify a set in the batch */ |