]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: add cache infrastructure and use it for table objects
authorPablo Neira Ayuso <pablo@netfilter.org>
Fri, 26 Jun 2015 09:33:22 +0000 (11:33 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 17 Aug 2015 23:13:35 +0000 (01:13 +0200)
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>
include/rule.h
src/cli.c
src/evaluate.c
src/main.c
src/rule.c

index 3c915756cd915eeca8e6a90dd34c8b5040092905..adff92fbda4395fac68f803d8a5ed0c7f727b58d 100644 (file)
@@ -383,4 +383,7 @@ extern struct error_record *rule_postprocess(struct rule *rule);
 struct netlink_ctx;
 extern int do_command(struct netlink_ctx *ctx, struct cmd *cmd);
 
+extern int cache_update(enum cmd_ops cmd, struct list_head *msgs);
+extern void cache_release(void);
+
 #endif /* NFTABLES_RULE_H */
index fbae0ef3efeb590ca71d866ee374571470b5494b..adffd6b9e7c0d600c7bdac993d238b3456a53037 100644 (file)
--- 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();
 }
 
index 0bf4fecb99eba7f6ea6ea113572ffef2a38fddbc..018d1b983cd92041c630a4409cd0297493974db7 100644 (file)
@@ -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;
index a2c4f87d28525f0bca98eaf6718a7108b7bde003..d6c9cccf681002ae65f6961d719039a766c0408b 100644 (file)
@@ -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;
index 8e3ef5f670165a74398224fe9161fd3f30313b8b..ba2bf66dac98f12fb3b087228f4bf8af8a5b05c8 100644 (file)
@@ -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);
                }
        }