]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: remove cache lookups after the evaluation phase
authorPablo Neira Ayuso <pablo@netfilter.org>
Tue, 28 Jul 2020 15:57:20 +0000 (17:57 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 29 Jul 2020 21:40:58 +0000 (23:40 +0200)
This patch adds a new field to the cmd structure for elements to store a
reference to the set. This saves an extra lookup in the netlink bytecode
generation step.

This patch also allows to incrementally update during the evaluation
phase according to the command actions, which is required by the follow
up ("evaluate: remove table from cache on delete table") bugfix patch.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/expression.h
include/netlink.h
include/rule.h
src/evaluate.c
src/netlink.c
src/rule.c
src/segtree.c

index 0210a3cb5314105d3428d2c4504fab8cca91b690..130912a89e04c0d48d13d4f799cf11705a867b5e 100644 (file)
@@ -479,7 +479,7 @@ extern void interval_map_decompose(struct expr *set);
 extern struct expr *get_set_intervals(const struct set *set,
                                      const struct expr *init);
 struct table;
-extern int get_set_decompose(struct table *table, struct set *set);
+extern int get_set_decompose(struct set *cache_set, struct set *set);
 
 extern struct expr *mapping_expr_alloc(const struct location *loc,
                                       struct expr *from, struct expr *to);
index 14fcec160e20f8b4fe2a0033dc8459571af23293..1077096ea0b1a07eb42c78e5dad1b3dfb3685fd7 100644 (file)
@@ -149,7 +149,7 @@ extern struct stmt *netlink_parse_set_expr(const struct set *set,
 extern int netlink_list_setelems(struct netlink_ctx *ctx,
                                 const struct handle *h, struct set *set);
 extern int netlink_get_setelem(struct netlink_ctx *ctx, const struct handle *h,
-                              const struct location *loc, struct table *table,
+                              const struct location *loc, struct set *cache_set,
                               struct set *set, struct expr *init);
 extern int netlink_delinearize_setelem(struct nftnl_set_elem *nlse,
                                       struct set *set,
index 4de7a0d950ec5844abfaba44a9ee22f39680b68c..60eadfa3c9a26e8fa1d8fb627c2d0654c9c0478d 100644 (file)
@@ -683,6 +683,10 @@ struct cmd {
                void            *data;
                struct expr     *expr;
                struct set      *set;
+               struct {
+                       struct expr     *expr;  /* same offset as cmd->expr */
+                       struct set      *set;
+               } elem;
                struct rule     *rule;
                struct chain    *chain;
                struct table    *table;
index bb504962ea8d0c1be0095711c8b671acfe5addc1..26d73959db583f649fd9bf56ee4e8ae4b6174f8a 100644 (file)
@@ -3560,7 +3560,7 @@ int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt)
        }
 }
 
-static int setelem_evaluate(struct eval_ctx *ctx, struct expr **expr)
+static int setelem_evaluate(struct eval_ctx *ctx, struct cmd *cmd)
 {
        struct table *table;
        struct set *set;
@@ -3576,9 +3576,12 @@ static int setelem_evaluate(struct eval_ctx *ctx, struct expr **expr)
 
        ctx->set = set;
        expr_set_context(&ctx->ectx, set->key->dtype, set->key->len);
-       if (expr_evaluate(ctx, expr) < 0)
+       if (expr_evaluate(ctx, &cmd->expr) < 0)
                return -1;
        ctx->set = NULL;
+
+       cmd->elem.set = set_get(set);
+
        return 0;
 }
 
@@ -4141,7 +4144,7 @@ static int cmd_evaluate_add(struct eval_ctx *ctx, struct cmd *cmd)
 {
        switch (cmd->obj) {
        case CMD_OBJ_ELEMENTS:
-               return setelem_evaluate(ctx, &cmd->expr);
+               return setelem_evaluate(ctx, cmd);
        case CMD_OBJ_SET:
                handle_merge(&cmd->set->handle, &cmd->handle);
                return set_evaluate(ctx, cmd->set);
@@ -4173,7 +4176,7 @@ static int cmd_evaluate_delete(struct eval_ctx *ctx, struct cmd *cmd)
 {
        switch (cmd->obj) {
        case CMD_OBJ_ELEMENTS:
-               return setelem_evaluate(ctx, &cmd->expr);
+               return setelem_evaluate(ctx, cmd);
        case CMD_OBJ_SET:
        case CMD_OBJ_RULE:
        case CMD_OBJ_CHAIN:
@@ -4197,7 +4200,7 @@ static int cmd_evaluate_get(struct eval_ctx *ctx, struct cmd *cmd)
 {
        switch (cmd->obj) {
        case CMD_OBJ_ELEMENTS:
-               return setelem_evaluate(ctx, &cmd->expr);
+               return setelem_evaluate(ctx, cmd);
        default:
                BUG("invalid command object type %u\n", cmd->obj);
        }
index b57e1c55850173949e08dacc96de6ba0af9147da..2f1dbe179ed590b0447cf0530859f4e9ca71bf70 100644 (file)
@@ -1228,7 +1228,7 @@ int netlink_list_setelems(struct netlink_ctx *ctx, const struct handle *h,
 }
 
 int netlink_get_setelem(struct netlink_ctx *ctx, const struct handle *h,
-                       const struct location *loc, struct table *table,
+                       const struct location *loc, struct set *cache_set,
                        struct set *set, struct expr *init)
 {
        struct nftnl_set *nls, *nls_out = NULL;
@@ -1261,7 +1261,7 @@ int netlink_get_setelem(struct netlink_ctx *ctx, const struct handle *h,
        if (set->flags & NFT_SET_INTERVAL && set->desc.field_count > 1)
                concat_range_aggregate(set->init);
        else if (set->flags & NFT_SET_INTERVAL)
-               err = get_set_decompose(table, set);
+               err = get_set_decompose(cache_set, set);
        else
                list_expr_sort(&ctx->set->init->expressions);
 
index 65973ccb296ea71ba7cc7418d444129727303d33..fed9e1238af131549911ac2765aea2bbfd53ee0f 100644 (file)
@@ -1577,6 +1577,8 @@ void cmd_free(struct cmd *cmd)
                switch (cmd->obj) {
                case CMD_OBJ_ELEMENTS:
                        expr_free(cmd->expr);
+                       if (cmd->elem.set)
+                               set_free(cmd->elem.set);
                        break;
                case CMD_OBJ_SET:
                case CMD_OBJ_SETELEMS:
@@ -1647,13 +1649,8 @@ static int __do_add_setelems(struct netlink_ctx *ctx, struct set *set,
 static int do_add_setelems(struct netlink_ctx *ctx, struct cmd *cmd,
                           uint32_t flags)
 {
-       struct handle *h = &cmd->handle;
        struct expr *init = cmd->expr;
-       struct table *table;
-       struct set *set;
-
-       table = table_lookup(h, &ctx->nft->cache);
-       set = set_lookup(table, h->set.name);
+       struct set *set = cmd->elem.set;
 
        if (set_is_non_concat_range(set) &&
            set_to_intervals(ctx->msgs, set, init, true,
@@ -1750,13 +1747,8 @@ static int do_command_insert(struct netlink_ctx *ctx, struct cmd *cmd)
 
 static int do_delete_setelems(struct netlink_ctx *ctx, struct cmd *cmd)
 {
-       struct handle *h = &cmd->handle;
-       struct expr *expr = cmd->expr;
-       struct table *table;
-       struct set *set;
-
-       table = table_lookup(h, &ctx->nft->cache);
-       set = set_lookup(table, h->set.name);
+       struct expr *expr = cmd->elem.expr;
+       struct set *set = cmd->elem.set;
 
        if (set_is_non_concat_range(set) &&
            set_to_intervals(ctx->msgs, set, expr, false,
@@ -2521,9 +2513,15 @@ static int do_list_chains(struct netlink_ctx *ctx, struct cmd *cmd)
 }
 
 static void __do_list_set(struct netlink_ctx *ctx, struct cmd *cmd,
-                         struct table *table, struct set *set)
+                         struct set *set)
 {
+       struct table *table = table_alloc();
+
+       table->handle.table.name = xstrdup(cmd->handle.table.name);
+       table->handle.family = cmd->handle.family;
        table_print_declaration(table, &ctx->nft->output);
+       table_free(table);
+
        set_print(set, &ctx->nft->output);
        nft_print(&ctx->nft->output, "}\n");
 }
@@ -2537,7 +2535,7 @@ static int do_list_set(struct netlink_ctx *ctx, struct cmd *cmd,
        if (set == NULL)
                return -1;
 
-       __do_list_set(ctx, cmd, table, set);
+       __do_list_set(ctx, cmd, set);
 
        return 0;
 }
@@ -2608,14 +2606,13 @@ static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd)
        return 0;
 }
 
-static int do_get_setelems(struct netlink_ctx *ctx, struct cmd *cmd,
-                          struct table *table)
+static int do_get_setelems(struct netlink_ctx *ctx, struct cmd *cmd)
 {
        struct set *set, *new_set;
        struct expr *init;
        int err;
 
-       set = set_lookup(table, cmd->handle.set.name);
+       set = cmd->elem.set;
 
        /* Create a list of elements based of what we got from command line. */
        if (set_is_non_concat_range(set))
@@ -2627,9 +2624,9 @@ static int do_get_setelems(struct netlink_ctx *ctx, struct cmd *cmd,
 
        /* Fetch from kernel the elements that have been requested .*/
        err = netlink_get_setelem(ctx, &cmd->handle, &cmd->location,
-                                 table, new_set, init);
+                                 cmd->elem.set, new_set, init);
        if (err >= 0)
-               __do_list_set(ctx, cmd, table, new_set);
+               __do_list_set(ctx, cmd, new_set);
 
        if (set_is_non_concat_range(set))
                expr_free(init);
@@ -2641,14 +2638,9 @@ static int do_get_setelems(struct netlink_ctx *ctx, struct cmd *cmd,
 
 static int do_command_get(struct netlink_ctx *ctx, struct cmd *cmd)
 {
-       struct table *table = NULL;
-
-       if (cmd->handle.table.name != NULL)
-               table = table_lookup(&cmd->handle, &ctx->nft->cache);
-
        switch (cmd->obj) {
        case CMD_OBJ_ELEMENTS:
-               return do_get_setelems(ctx, cmd, table);
+               return do_get_setelems(ctx, cmd);
        default:
                BUG("invalid command object type %u\n", cmd->obj);
        }
index 49169e733cffdf9df89e72d4efa0c6757a5e9d5e..a9b4b1bd6e2c2a4719a43dacb59e9f924e7f19d1 100644 (file)
@@ -687,17 +687,15 @@ struct expr *get_set_intervals(const struct set *set, const struct expr *init)
        return new_init;
 }
 
-static struct expr *get_set_interval_find(const struct table *table,
-                                         const char *set_name,
+static struct expr *get_set_interval_find(const struct set *cache_set,
                                          struct expr *left,
                                          struct expr *right)
 {
+       const struct set *set = cache_set;
        struct expr *range = NULL;
-       struct set *set;
        struct expr *i;
        mpz_t val;
 
-       set = set_lookup(table, set_name);
        mpz_init2(val, set->key->len);
 
        list_for_each_entry(i, &set->init->expressions, list) {
@@ -724,7 +722,7 @@ out:
        return range;
 }
 
-int get_set_decompose(struct table *table, struct set *set)
+int get_set_decompose(struct set *cache_set, struct set *set)
 {
        struct expr *i, *next, *range;
        struct expr *left = NULL;
@@ -737,8 +735,7 @@ int get_set_decompose(struct table *table, struct set *set)
                        list_del(&left->list);
                        list_del(&i->list);
                        mpz_sub_ui(i->key->value, i->key->value, 1);
-                       range = get_set_interval_find(table, set->handle.set.name,
-                                                   left, i);
+                       range = get_set_interval_find(cache_set, left, i);
                        if (!range) {
                                expr_free(new_init);
                                errno = ENOENT;
@@ -751,8 +748,7 @@ int get_set_decompose(struct table *table, struct set *set)
                        left = NULL;
                } else {
                        if (left) {
-                               range = get_set_interval_find(table,
-                                                             set->handle.set.name,
+                               range = get_set_interval_find(cache_set,
                                                              left, NULL);
                                if (range)
                                        compound_expr_add(new_init, range);
@@ -764,8 +760,7 @@ int get_set_decompose(struct table *table, struct set *set)
                }
        }
        if (left) {
-               range = get_set_interval_find(table, set->handle.set.name,
-                                             left, NULL);
+               range = get_set_interval_find(cache_set, left, NULL);
                if (range)
                        compound_expr_add(new_init, range);
                else