summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2015-06-26 11:33:22 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2015-08-18 01:13:35 +0200
commitbd21392a7cdfefdd4a069707da31474da5fe9458 (patch)
tree7420311471ac381318b7d36ef014d69af71258fe /src
parent94002b41384890224bfb14d1b0986bd8b279b17e (diff)
src: add cache infrastructure and use it for table objects
This patch introduces the generic object cache that is populated during the evaluation phase. The first client of this infrastructure are table objects. As a result, there is a single call to netlink_list_tables(). Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/cli.c1
-rw-r--r--src/evaluate.c6
-rw-r--r--src/main.c2
-rw-r--r--src/rule.c103
4 files changed, 84 insertions, 28 deletions
diff --git a/src/cli.c b/src/cli.c
index fbae0ef3..adffd6b9 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -124,6 +124,7 @@ static void cli_complete(char *line)
nft_run(scanner, state, &msgs);
erec_print_list(stdout, &msgs);
xfree(line);
+ cache_release();
iface_cache_release();
}
diff --git a/src/evaluate.c b/src/evaluate.c
index 0bf4fecb..018d1b98 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2005,6 +2005,12 @@ static int cmd_evaluate_monitor(struct eval_ctx *ctx, struct cmd *cmd)
int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd)
{
+ int ret;
+
+ ret = cache_update(cmd->op, ctx->msgs);
+ if (ret < 0)
+ return ret;
+
#ifdef DEBUG
if (debug_level & DEBUG_EVALUATION) {
struct error_record *erec;
diff --git a/src/main.c b/src/main.c
index a2c4f87d..d6c9cccf 100644
--- a/src/main.c
+++ b/src/main.c
@@ -182,7 +182,6 @@ static int nft_netlink(struct parser_state *state, struct list_head *msgs)
bool batch_supported = netlink_batch_supported();
int ret = 0;
- netlink_genid_get();
mnl_batch_init();
batch_seqnum = mnl_batch_begin();
@@ -366,6 +365,7 @@ out:
scanner_destroy(scanner);
erec_print_list(stderr, &msgs);
xfree(buf);
+ cache_release();
iface_cache_release();
return rc;
diff --git a/src/rule.c b/src/rule.c
index 8e3ef5f6..ba2bf66d 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -53,6 +53,73 @@ void handle_merge(struct handle *dst, const struct handle *src)
dst->comment = xstrdup(src->comment);
}
+static LIST_HEAD(table_list);
+
+static int cache_init_tables(struct netlink_ctx *ctx, struct handle *h)
+{
+ int ret;
+
+ ret = netlink_list_tables(ctx, h, &internal_location);
+ if (ret < 0)
+ return -1;
+
+ list_splice_tail_init(&ctx->list, &table_list);
+ return 0;
+}
+
+static int cache_init(enum cmd_ops cmd, struct list_head *msgs)
+{
+ struct handle handle = {
+ .family = NFPROTO_UNSPEC,
+ };
+ struct netlink_ctx ctx;
+ int ret;
+
+ memset(&ctx, 0, sizeof(ctx));
+ init_list_head(&ctx.list);
+ ctx.msgs = msgs;
+
+ ret = cache_init_tables(&ctx, &handle);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static bool cache_initialized;
+
+int cache_update(enum cmd_ops cmd, struct list_head *msgs)
+{
+ int ret;
+
+ if (cache_initialized)
+ return 0;
+replay:
+ netlink_genid_get();
+ ret = cache_init(cmd, msgs);
+ if (ret < 0) {
+ if (errno == EINTR) {
+ netlink_restart();
+ goto replay;
+ }
+ cache_release();
+ return -1;
+ }
+ cache_initialized = true;
+ return 0;
+}
+
+void cache_release(void)
+{
+ struct table *table, *next;
+
+ list_for_each_entry_safe(table, next, &table_list, list) {
+ list_del(&table->list);
+ table_free(table);
+ }
+ cache_initialized = false;
+}
+
struct set *set_alloc(const struct location *loc)
{
struct set *set;
@@ -535,8 +602,6 @@ void table_free(struct table *table)
xfree(table);
}
-static LIST_HEAD(table_list);
-
void table_add_hash(struct table *table)
{
list_add_tail(&table->list, &table_list);
@@ -864,8 +929,6 @@ static int do_list_table(struct netlink_ctx *ctx, struct cmd *cmd,
struct rule *rule, *nrule;
struct chain *chain;
- if (netlink_get_table(ctx, &cmd->handle, &cmd->location, table) < 0)
- goto err;
if (do_list_sets(ctx, &cmd->location, table) < 0)
goto err;
if (netlink_list_chains(ctx, &cmd->handle, &cmd->location) < 0)
@@ -895,25 +958,19 @@ err:
static int do_list_ruleset(struct netlink_ctx *ctx, struct cmd *cmd)
{
- struct table *table, *next;
- LIST_HEAD(tables);
-
- if (netlink_list_tables(ctx, &cmd->handle, &cmd->location) < 0)
- return -1;
-
- list_splice_tail_init(&ctx->list, &tables);
+ unsigned int family = cmd->handle.family;
+ struct table *table;
- list_for_each_entry_safe(table, next, &tables, list) {
- table_add_hash(table);
+ list_for_each_entry(table, &table_list, list) {
+ if (family != NFPROTO_UNSPEC &&
+ table->handle.family != family)
+ continue;
cmd->handle.family = table->handle.family;
cmd->handle.table = xstrdup(table->handle.table);
if (do_list_table(ctx, cmd, table) < 0)
return -1;
-
- list_del(&table->list);
- table_free(table);
}
return 0;
@@ -923,10 +980,7 @@ static int do_list_tables(struct netlink_ctx *ctx, struct cmd *cmd)
{
struct table *table;
- if (netlink_list_tables(ctx, &cmd->handle, &cmd->location) < 0)
- return -1;
-
- list_for_each_entry(table, &ctx->list, list)
+ list_for_each_entry(table, &table_list, list)
printf("table %s %s\n",
family2str(table->handle.family),
table->handle.table);
@@ -1034,7 +1088,7 @@ static int do_command_rename(struct netlink_ctx *ctx, struct cmd *cmd)
static int do_command_monitor(struct netlink_ctx *ctx, struct cmd *cmd)
{
- struct table *t, *nt;
+ struct table *t;
struct set *s, *ns;
struct netlink_ctx set_ctx;
LIST_HEAD(msgs);
@@ -1057,10 +1111,7 @@ static int do_command_monitor(struct netlink_ctx *ctx, struct cmd *cmd)
init_list_head(&msgs);
set_ctx.msgs = &msgs;
- if (netlink_list_tables(ctx, &cmd->handle, &cmd->location) < 0)
- return -1;
-
- list_for_each_entry_safe(t, nt, &ctx->list, list) {
+ list_for_each_entry(t, &table_list, list) {
set_handle.family = t->handle.family;
set_handle.table = t->handle.table;
@@ -1074,8 +1125,6 @@ static int do_command_monitor(struct netlink_ctx *ctx, struct cmd *cmd)
s->init = set_expr_alloc(&cmd->location);
set_add_hash(s, t);
}
-
- table_add_hash(t);
}
}