]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
evaluate: remove anon sets with exactly one element
authorFlorian Westphal <fw@strlen.de>
Fri, 25 Jan 2019 15:50:23 +0000 (16:50 +0100)
committerFlorian Westphal <fw@strlen.de>
Mon, 7 Jun 2021 20:50:55 +0000 (22:50 +0200)
Auto-replace lookups in single-element anon sets with a standard compare.

'add rule foo bar meta iif { "lo" }' gets replaced with
'add rule foo bar meta iif "lo"'.

The former is a set lookup, the latter is a comparision.
Comparisions are faster for the one-element case.

Only prefixes, ranges and values are handled at this time.

Anonymous maps are left alone, same for concatenations.

Concatenations could be handled, but it would require more work:
the concatenation would have to be replaced with a singleton value.
Evaluation step rejects concat RHS on a relational expression.

Signed-off-by: Florian Westphal <fw@strlen.de>
src/evaluate.c

index 384e2fa786e065d796d32ad195d4aca5c53a942b..2ed68aad03928706ee40e7d6e37c319018bf3068 100644 (file)
@@ -1455,8 +1455,25 @@ static int expr_evaluate_set(struct eval_ctx *ctx, struct expr **expr)
                }
        }
 
-       if (ctx->set && (ctx->set->flags & NFT_SET_CONCAT))
-               set->set_flags |= NFT_SET_CONCAT;
+       if (ctx->set) {
+               if (ctx->set->flags & NFT_SET_CONCAT)
+                       set->set_flags |= NFT_SET_CONCAT;
+       } else if (set->size == 1) {
+               i = list_first_entry(&set->expressions, struct expr, list);
+               if (i->etype == EXPR_SET_ELEM) {
+                       switch (i->key->etype) {
+                       case EXPR_PREFIX:
+                       case EXPR_RANGE:
+                       case EXPR_VALUE:
+                               *expr = i->key;
+                               i->key = NULL;
+                               expr_free(set);
+                               return 0;
+                       default:
+                               break;
+                       }
+               }
+       }
 
        set->set_flags |= NFT_SET_CONSTANT;