diff options
author | Florian Westphal <fw@strlen.de> | 2019-01-25 16:50:23 +0100 |
---|---|---|
committer | Florian Westphal <fw@strlen.de> | 2021-06-07 22:50:55 +0200 |
commit | fee6bda064037b2abd0510241ac59d5358a7f684 (patch) | |
tree | 850586f9d02d25b82b91dd97445127ab492328f7 | |
parent | ec1ea13314fa55e43e3034bf43297829b25ba582 (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>
-rw-r--r-- | src/evaluate.c | 21 |
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; |