\f
/* Formatting. */
+/* Searches bits [0,width) in 'sv' for a contiguous sequence of 1-bits. If one
+ * such sequence exists, stores the index of the first 1-bit into '*startp' and
+ * the number of 1-bits into '*n_bitsp'. Stores 0 into both variables if no
+ * such sequence, or more than one, exists. */
static void
find_bitwise_range(const union mf_subvalue *sv, int width,
int *startp, int *n_bitsp)
ovs_assert(n_bits > 0);
end = start + n_bits;
- struct expr *new;
- if (expr->cmp.relop == EXPR_R_LE || expr->cmp.relop == EXPR_R_GE) {
+ /* Handle some special cases.
+ *
+ * These optimize to just "true":
+ *
+ * tcp.dst >= 0
+ * tcp.dst <= 65535
+ *
+ * These are easier to understand, and equivalent, when treated as if
+ * > or < were !=:
+ *
+ * tcp.dst > 0
+ * tcp.dst < 65535
+ */
+ bool lt = expr->cmp.relop == EXPR_R_LT || expr->cmp.relop == EXPR_R_LE;
+ bool eq = expr->cmp.relop == EXPR_R_LE || expr->cmp.relop == EXPR_R_GE;
+ if (bitwise_scan(value, sizeof *value, !lt, start, end) == end) {
+ if (eq) {
+ expr_destroy(expr);
+ return expr_create_boolean(true);
+ } else {
+ return expr_simplify_ne(expr);
+ }
+ }
+
+ /* Reduce "tcp.dst >= 1234" to "tcp.dst == 1234 || tcp.dst > 1234",
+ * and similarly for "tcp.dst <= 1234". */
+ struct expr *new = NULL;
+ if (eq) {
new = xmemdup(expr, sizeof *expr);
new->cmp.relop = EXPR_R_EQ;
- } else {
- new = NULL;
}
- bool b = expr->cmp.relop == EXPR_R_LT || expr->cmp.relop == EXPR_R_LE;
- for (int z = bitwise_scan(value, sizeof *value, b, start, end);
+ for (int z = bitwise_scan(value, sizeof *value, lt, start, end);
z < end;
- z = bitwise_scan(value, sizeof *value, b, z + 1, end)) {
+ z = bitwise_scan(value, sizeof *value, lt, z + 1, end)) {
struct expr *e;
e = xmemdup(expr, sizeof *expr);
])
AT_CHECK([simplify 'eth.dst != 0/0'], [0], [0
])
+AT_CHECK([simplify 'tcp.dst >= 0'], [0],
+ [ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
+])
+AT_CHECK([simplify 'tcp.dst <= 65535'], [0],
+ [ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
+])
+AT_CHECK([simplify 'tcp.dst > 0'], [0],
+ [[(tcp.dst[0] || tcp.dst[1] || tcp.dst[2] || tcp.dst[3] || tcp.dst[4] || tcp.dst[5] || tcp.dst[6] || tcp.dst[7] || tcp.dst[8] || tcp.dst[9] || tcp.dst[10] || tcp.dst[11] || tcp.dst[12] || tcp.dst[13] || tcp.dst[14] || tcp.dst[15]) && ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
+]])
+AT_CHECK([simplify 'tcp.dst < 65535'], [0],
+ [[(!tcp.dst[0] || !tcp.dst[1] || !tcp.dst[2] || !tcp.dst[3] || !tcp.dst[4] || !tcp.dst[5] || !tcp.dst[6] || !tcp.dst[7] || !tcp.dst[8] || !tcp.dst[9] || !tcp.dst[10] || !tcp.dst[11] || !tcp.dst[12] || !tcp.dst[13] || !tcp.dst[14] || !tcp.dst[15]) && ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
+]])
AT_CLEANUP
AT_SETUP([ovn -- 4-term numeric expression normalization])