diff options
author | Ben Pfaff <blp@ovn.org> | 2016-10-06 17:54:19 -0700 |
---|---|---|
committer | Ben Pfaff <blp@ovn.org> | 2016-10-11 08:34:58 -0700 |
commit | 97ba1d55139d8348a7574b7947b21251befb2d4c (patch) | |
tree | c3df1ccceac54de718d98091a2567775721850c9 /ovn | |
parent | 85be6684f8afcfd215695a443fdbbc503286544b (diff) | |
download | openvswitch-97ba1d55139d8348a7574b7947b21251befb2d4c.tar.gz |
expr: Simplify "x == 0/0" into 1.
An expression like "x == 0/0" does not test any actual bits in field x,
so it resolves to true, but expr_simplify() was not smart enough to see
this.
This goes beyond an optimization, to become a bug fix, because
expr_normalize() will assert-fail for expressions that become trivial
when this simplification is omitted. For example:
$ echo 'eth.dst == 0/0 && eth.dst == 0/0' | tests/ovstest test-ovn normalize-expr
test-ovn: ../include/openvswitch/list.h:245: assertion !ovs_list_is_empty(list) failed in ovs_list_front()
Aborted (core dumped)
This commit fixes this and related problems.
The test added by this commit is very specific to the particular problem,
whereas a more general test would be better. A later commit adds the
general test.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Andy Zhou <azhou@ovn.org>
Diffstat (limited to 'ovn')
-rw-r--r-- | ovn/lib/expr.c | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/ovn/lib/expr.c b/ovn/lib/expr.c index 4ae6b0b6b..a5dbcfaa4 100644 --- a/ovn/lib/expr.c +++ b/ovn/lib/expr.c @@ -1669,6 +1669,18 @@ expr_annotate(struct expr *expr, const struct shash *symtab, char **errorp) } static struct expr * +expr_simplify_eq(struct expr *expr) +{ + const union mf_subvalue *mask = &expr->cmp.mask; + if (is_all_zeros(mask, sizeof *mask)) { + /* Simplify "ip4.dst == 0/0" to just "1" (plus a prerequisite). */ + expr_destroy(expr); + return expr_create_boolean(true); + } + return expr; +} + +static struct expr * expr_simplify_ne(struct expr *expr) { struct expr *new = NULL; @@ -1742,7 +1754,8 @@ expr_simplify(struct expr *expr) switch (expr->type) { case EXPR_T_CMP: - return (expr->cmp.relop == EXPR_R_EQ || !expr->cmp.symbol->width ? expr + return (!expr->cmp.symbol->width ? expr + : expr->cmp.relop == EXPR_R_EQ ? expr_simplify_eq(expr) : expr->cmp.relop == EXPR_R_NE ? expr_simplify_ne(expr) : expr_simplify_relational(expr)); |