summaryrefslogtreecommitdiffstats
path: root/src/evaluate.c
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2019-01-25 16:50:23 +0100
committerFlorian Westphal <fw@strlen.de>2021-06-07 22:50:55 +0200
commitfee6bda064037b2abd0510241ac59d5358a7f684 (patch)
tree850586f9d02d25b82b91dd97445127ab492328f7 /src/evaluate.c
parentec1ea13314fa55e43e3034bf43297829b25ba582 (diff)
evaluate: remove anon sets with exactly one element
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>
Diffstat (limited to 'src/evaluate.c')
-rw-r--r--src/evaluate.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/src/evaluate.c b/src/evaluate.c
index 384e2fa7..2ed68aad 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -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;