2 * Copyright (c) 2015, 2016 Nicira, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #include "command-line.h"
22 #include "fatal-signal.h"
24 #include "openvswitch/dynamic-string.h"
25 #include "openvswitch/match.h"
26 #include "openvswitch/ofp-actions.h"
27 #include "openvswitch/ofpbuf.h"
28 #include "openvswitch/vlog.h"
29 #include "ovn/lib/actions.h"
30 #include "ovn/lib/expr.h"
31 #include "ovn/lib/lex.h"
32 #include "ovs-thread.h"
38 /* --relops: Bitmap of the relational operators to test, in exhaustive test. */
39 static unsigned int test_relops;
41 /* --nvars: Number of numeric variables to test, in exhaustive test. */
42 static int test_nvars = 2;
44 /* --svars: Number of string variables to test, in exhaustive test. */
45 static int test_svars = 2;
47 /* --bits: Number of bits per variable, in exhaustive test. */
48 static int test_bits = 3;
50 /* --operation: The operation to test, in exhaustive test. */
51 static enum { OP_CONVERT, OP_SIMPLIFY, OP_NORMALIZE, OP_FLOW } operation
54 /* --parallel: Number of parallel processes to use in test. */
55 static int test_parallel = 1;
57 /* -m, --more: Message verbosity */
61 compare_token(const struct lex_token *a, const struct lex_token *b)
63 if (a->type != b->type) {
64 fprintf(stderr, "type differs: %d -> %d\n", a->type, b->type);
68 if (!((a->s && b->s && !strcmp(a->s, b->s))
69 || (!a->s && !b->s))) {
70 fprintf(stderr, "string differs: %s -> %s\n",
71 a->s ? a->s : "(null)",
72 b->s ? b->s : "(null)");
76 if (a->type == LEX_T_INTEGER || a->type == LEX_T_MASKED_INTEGER) {
77 if (memcmp(&a->value, &b->value, sizeof a->value)) {
78 fprintf(stderr, "value differs\n");
82 if (a->type == LEX_T_MASKED_INTEGER
83 && memcmp(&a->mask, &b->mask, sizeof a->mask)) {
84 fprintf(stderr, "mask differs\n");
88 if (a->format != b->format
89 && !(a->format == LEX_F_HEXADECIMAL
90 && b->format == LEX_F_DECIMAL
91 && a->value.integer == 0)) {
92 fprintf(stderr, "format differs: %d -> %d\n",
93 a->format, b->format);
99 test_lex(struct ovs_cmdl_context *ctx OVS_UNUSED)
106 while (!ds_get_test_line(&input, stdin)) {
109 lexer_init(&lexer, ds_cstr(&input));
111 while (lexer_get(&lexer) != LEX_T_END) {
112 size_t len = output.length;
113 lex_token_format(&lexer.token, &output);
115 /* Check that the formatted version can really be parsed back
117 if (lexer.token.type != LEX_T_ERROR) {
118 const char *s = ds_cstr(&output) + len;
123 compare_token(&lexer.token, &l2.token);
126 ds_put_char(&output, ' ');
128 lexer_destroy(&lexer);
130 ds_chomp(&output, ' ');
131 puts(ds_cstr(&output));
138 create_symtab(struct shash *symtab)
142 /* Reserve a pair of registers for the logical inport and outport. A full
143 * 32-bit register each is bigger than we need, but the expression code
144 * doesn't yet support string fields that occupy less than a full OXM. */
145 expr_symtab_add_string(symtab, "inport", MFF_REG6, NULL);
146 expr_symtab_add_string(symtab, "outport", MFF_REG7, NULL);
148 expr_symtab_add_field(symtab, "xreg0", MFF_XREG0, NULL, false);
149 expr_symtab_add_field(symtab, "xreg1", MFF_XREG1, NULL, false);
150 expr_symtab_add_field(symtab, "xreg2", MFF_XREG2, NULL, false);
152 expr_symtab_add_subfield(symtab, "reg0", NULL, "xreg0[32..63]");
153 expr_symtab_add_subfield(symtab, "reg1", NULL, "xreg0[0..31]");
154 expr_symtab_add_subfield(symtab, "reg2", NULL, "xreg1[32..63]");
155 expr_symtab_add_subfield(symtab, "reg3", NULL, "xreg1[0..31]");
156 expr_symtab_add_subfield(symtab, "reg4", NULL, "xreg2[32..63]");
157 expr_symtab_add_subfield(symtab, "reg5", NULL, "xreg2[0..31]");
159 expr_symtab_add_field(symtab, "eth.src", MFF_ETH_SRC, NULL, false);
160 expr_symtab_add_field(symtab, "eth.dst", MFF_ETH_DST, NULL, false);
161 expr_symtab_add_field(symtab, "eth.type", MFF_ETH_TYPE, NULL, true);
163 expr_symtab_add_field(symtab, "vlan.tci", MFF_VLAN_TCI, NULL, false);
164 expr_symtab_add_predicate(symtab, "vlan.present", "vlan.tci[12]");
165 expr_symtab_add_subfield(symtab, "vlan.pcp", "vlan.present",
167 expr_symtab_add_subfield(symtab, "vlan.vid", "vlan.present",
170 expr_symtab_add_predicate(symtab, "ip4", "eth.type == 0x800");
171 expr_symtab_add_predicate(symtab, "ip6", "eth.type == 0x86dd");
172 expr_symtab_add_predicate(symtab, "ip", "ip4 || ip6");
173 expr_symtab_add_field(symtab, "ip.proto", MFF_IP_PROTO, "ip", true);
174 expr_symtab_add_field(symtab, "ip.dscp", MFF_IP_DSCP, "ip", false);
175 expr_symtab_add_field(symtab, "ip.ecn", MFF_IP_ECN, "ip", false);
176 expr_symtab_add_field(symtab, "ip.ttl", MFF_IP_TTL, "ip", false);
178 expr_symtab_add_field(symtab, "ip4.src", MFF_IPV4_SRC, "ip4", false);
179 expr_symtab_add_field(symtab, "ip4.dst", MFF_IPV4_DST, "ip4", false);
181 expr_symtab_add_predicate(symtab, "icmp4", "ip4 && ip.proto == 1");
182 expr_symtab_add_field(symtab, "icmp4.type", MFF_ICMPV4_TYPE, "icmp4",
184 expr_symtab_add_field(symtab, "icmp4.code", MFF_ICMPV4_CODE, "icmp4",
187 expr_symtab_add_field(symtab, "ip6.src", MFF_IPV6_SRC, "ip6", false);
188 expr_symtab_add_field(symtab, "ip6.dst", MFF_IPV6_DST, "ip6", false);
189 expr_symtab_add_field(symtab, "ip6.label", MFF_IPV6_LABEL, "ip6", false);
191 expr_symtab_add_predicate(symtab, "icmp6", "ip6 && ip.proto == 58");
192 expr_symtab_add_field(symtab, "icmp6.type", MFF_ICMPV6_TYPE, "icmp6",
194 expr_symtab_add_field(symtab, "icmp6.code", MFF_ICMPV6_CODE, "icmp6",
197 expr_symtab_add_predicate(symtab, "icmp", "icmp4 || icmp6");
199 expr_symtab_add_field(symtab, "ip.frag", MFF_IP_FRAG, "ip", false);
200 expr_symtab_add_predicate(symtab, "ip.is_frag", "ip.frag[0]");
201 expr_symtab_add_predicate(symtab, "ip.later_frag", "ip.frag[1]");
202 expr_symtab_add_predicate(symtab, "ip.first_frag", "ip.is_frag && !ip.later_frag");
204 expr_symtab_add_predicate(symtab, "arp", "eth.type == 0x806");
205 expr_symtab_add_field(symtab, "arp.op", MFF_ARP_OP, "arp", false);
206 expr_symtab_add_field(symtab, "arp.spa", MFF_ARP_SPA, "arp", false);
207 expr_symtab_add_field(symtab, "arp.sha", MFF_ARP_SHA, "arp", false);
208 expr_symtab_add_field(symtab, "arp.tpa", MFF_ARP_TPA, "arp", false);
209 expr_symtab_add_field(symtab, "arp.tha", MFF_ARP_THA, "arp", false);
211 expr_symtab_add_predicate(symtab, "nd", "icmp6.type == {135, 136} && icmp6.code == 0");
212 expr_symtab_add_field(symtab, "nd.target", MFF_ND_TARGET, "nd", false);
213 expr_symtab_add_field(symtab, "nd.sll", MFF_ND_SLL,
214 "nd && icmp6.type == 135", false);
215 expr_symtab_add_field(symtab, "nd.tll", MFF_ND_TLL,
216 "nd && icmp6.type == 136", false);
218 expr_symtab_add_predicate(symtab, "tcp", "ip.proto == 6");
219 expr_symtab_add_field(symtab, "tcp.src", MFF_TCP_SRC, "tcp", false);
220 expr_symtab_add_field(symtab, "tcp.dst", MFF_TCP_DST, "tcp", false);
221 expr_symtab_add_field(symtab, "tcp.flags", MFF_TCP_FLAGS, "tcp", false);
223 expr_symtab_add_predicate(symtab, "udp", "ip.proto == 17");
224 expr_symtab_add_field(symtab, "udp.src", MFF_UDP_SRC, "udp", false);
225 expr_symtab_add_field(symtab, "udp.dst", MFF_UDP_DST, "udp", false);
227 expr_symtab_add_predicate(symtab, "sctp", "ip.proto == 132");
228 expr_symtab_add_field(symtab, "sctp.src", MFF_SCTP_SRC, "sctp", false);
229 expr_symtab_add_field(symtab, "sctp.dst", MFF_SCTP_DST, "sctp", false);
231 /* For negative testing. */
232 expr_symtab_add_field(symtab, "bad_prereq", MFF_XREG0, "xyzzy", false);
233 expr_symtab_add_field(symtab, "self_recurse", MFF_XREG0,
234 "self_recurse != 0", false);
235 expr_symtab_add_field(symtab, "mutual_recurse_1", MFF_XREG0,
236 "mutual_recurse_2 != 0", false);
237 expr_symtab_add_field(symtab, "mutual_recurse_2", MFF_XREG0,
238 "mutual_recurse_1 != 0", false);
239 expr_symtab_add_string(symtab, "big_string", MFF_XREG0, NULL);
243 lookup_port_cb(const void *ports_, const char *port_name, unsigned int *portp)
245 const struct simap *ports = ports_;
246 const struct simap_node *node = simap_find(ports, port_name);
255 test_parse_expr__(int steps)
261 create_symtab(&symtab);
264 simap_put(&ports, "eth0", 5);
265 simap_put(&ports, "eth1", 6);
266 simap_put(&ports, "LOCAL", ofp_to_u16(OFPP_LOCAL));
269 while (!ds_get_test_line(&input, stdin)) {
273 expr = expr_parse_string(ds_cstr(&input), &symtab, &error);
274 if (!error && steps > 0) {
275 expr = expr_annotate(expr, &symtab, &error);
279 expr = expr_simplify(expr);
282 expr = expr_normalize(expr);
283 ovs_assert(expr_is_normalized(expr));
290 expr_to_matches(expr, lookup_port_cb, &ports, &matches);
291 expr_matches_print(&matches, stdout);
292 expr_matches_destroy(&matches);
294 struct ds output = DS_EMPTY_INITIALIZER;
295 expr_format(expr, &output);
296 puts(ds_cstr(&output));
307 simap_destroy(&ports);
308 expr_symtab_destroy(&symtab);
309 shash_destroy(&symtab);
313 test_parse_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
315 test_parse_expr__(0);
319 test_annotate_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
321 test_parse_expr__(1);
325 test_simplify_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
327 test_parse_expr__(2);
331 test_normalize_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
333 test_parse_expr__(3);
337 test_expr_to_flows(struct ovs_cmdl_context *ctx OVS_UNUSED)
339 test_parse_expr__(4);
342 /* Evaluate an expression. */
344 static bool evaluate_expr(const struct expr *, unsigned int subst, int n_bits);
347 evaluate_andor_expr(const struct expr *expr, unsigned int subst, int n_bits,
350 const struct expr *sub;
352 LIST_FOR_EACH (sub, node, &expr->andor) {
353 if (evaluate_expr(sub, subst, n_bits) == short_circuit) {
354 return short_circuit;
357 return !short_circuit;
361 evaluate_cmp_expr(const struct expr *expr, unsigned int subst, int n_bits)
363 int var_idx = atoi(expr->cmp.symbol->name + 1);
364 if (expr->cmp.symbol->name[0] == 'n') {
365 unsigned var_mask = (1u << n_bits) - 1;
366 unsigned int arg1 = (subst >> (var_idx * n_bits)) & var_mask;
367 unsigned int arg2 = ntohll(expr->cmp.value.integer);
368 unsigned int mask = ntohll(expr->cmp.mask.integer);
370 ovs_assert(!(mask & ~var_mask));
371 ovs_assert(!(arg2 & ~var_mask));
372 ovs_assert(!(arg2 & ~mask));
375 switch (expr->cmp.relop) {
397 } else if (expr->cmp.symbol->name[0] == 's') {
398 unsigned int arg1 = (subst >> (test_nvars * n_bits + var_idx)) & 1;
399 unsigned int arg2 = atoi(expr->cmp.string);
406 /* Evaluates 'expr' and returns its Boolean result. 'subst' provides the value
407 * for the variables, which must be 'n_bits' bits each and be named "a", "b",
408 * "c", etc. The value of variable "a" is the least-significant 'n_bits' bits
409 * of 'subst', the value of "b" is the next 'n_bits' bits, and so on. */
411 evaluate_expr(const struct expr *expr, unsigned int subst, int n_bits)
413 switch (expr->type) {
415 return evaluate_cmp_expr(expr, subst, n_bits);
418 return evaluate_andor_expr(expr, subst, n_bits, false);
421 return evaluate_andor_expr(expr, subst, n_bits, true);
424 return expr->boolean;
432 test_evaluate_expr(struct ovs_cmdl_context *ctx)
434 int a = atoi(ctx->argv[1]);
435 int b = atoi(ctx->argv[2]);
436 int c = atoi(ctx->argv[3]);
437 unsigned int subst = a | (b << 3) || (c << 6);
442 expr_symtab_add_field(&symtab, "xreg0", MFF_XREG0, NULL, false);
443 expr_symtab_add_field(&symtab, "xreg1", MFF_XREG1, NULL, false);
444 expr_symtab_add_field(&symtab, "xreg2", MFF_XREG1, NULL, false);
445 expr_symtab_add_subfield(&symtab, "a", NULL, "xreg0[0..2]");
446 expr_symtab_add_subfield(&symtab, "b", NULL, "xreg1[0..2]");
447 expr_symtab_add_subfield(&symtab, "c", NULL, "xreg2[0..2]");
450 while (!ds_get_test_line(&input, stdin)) {
454 expr = expr_parse_string(ds_cstr(&input), &symtab, &error);
456 expr = expr_annotate(expr, &symtab, &error);
459 printf("%d\n", evaluate_expr(expr, subst, 3));
468 expr_symtab_destroy(&symtab);
469 shash_destroy(&symtab);
474 * The "compositions" of a positive integer N are all of the ways that one can
475 * add up positive integers to sum to N. For example, the compositions of 3
476 * are 3, 2+1, 1+2, and 1+1+1.
478 * We use compositions to find all the ways to break up N terms of a Boolean
479 * expression into subexpressions. Suppose we want to generate all expressions
480 * with 3 terms. The compositions of 3 (ignoring 3 itself) provide the
481 * possibilities (x && x) || x, x || (x && x), and x || x || x. (Of course one
482 * can exchange && for || in each case.) One must recursively compose the
483 * sub-expressions whose values are 3 or greater; that is what the "tree shape"
484 * concept later covers.
486 * To iterate through all compositions of, e.g., 5:
488 * unsigned int state;
492 * for (n = first_composition(ARRAY_SIZE(s), &state, s); n > 0;
493 * n = next_composition(&state, s, n)) {
494 * // Do something with composition 's' with 'n' elements.
497 * Algorithm from D. E. Knuth, _The Art of Computer Programming, Vol. 4A:
498 * Combinatorial Algorithms, Part 1_, section 7.2.1.1, answer to exercise
502 /* Begins iteration through the compositions of 'n'. Initializes 's' to the
503 * number of elements in the first composition of 'n' and returns that number
504 * of elements. The first composition in fact is always 'n' itself, so the
505 * return value will be 1.
507 * Initializes '*state' to some internal state information. The caller must
508 * maintain this state (and 's') for use by next_composition().
510 * 's' must have room for at least 'n' elements. */
512 first_composition(int n, unsigned int *state, int s[])
519 /* Advances 's', with 'sn' elements, to the next composition and returns the
520 * number of elements in this new composition, or 0 if no compositions are
521 * left. 'state' is the same internal state passed to first_composition(). */
523 next_composition(unsigned int *state, int s[], int sn)
554 test_composition(struct ovs_cmdl_context *ctx)
556 int n = atoi(ctx->argv[1]);
560 for (int sn = first_composition(n, &state, s); sn;
561 sn = next_composition(&state, s, sn)) {
562 for (int i = 0; i < sn; i++) {
563 printf("%d%c", s[i], i == sn - 1 ? '\n' : ' ');
570 * This code generates all possible Boolean expressions with a specified number
571 * of terms N (equivalent to the number of external nodes in a tree).
573 * See test_tree_shape() for a simple example. */
575 /* An array of these structures describes the shape of a tree.
577 * A single element of struct tree_shape describes a single node in the tree.
578 * The node has 'sn' direct children. From left to right, for i in 0...sn-1,
579 * s[i] is 1 if the child is a leaf node, otherwise the child is a subtree and
580 * s[i] is the number of leaf nodes within that subtree. In the latter case,
581 * the subtree is described by another struct tree_shape within the enclosing
582 * array. The tree_shapes are ordered in the array in in-order.
591 init_tree_shape__(struct tree_shape ts[], int n)
598 /* Skip the first composition intentionally. */
599 ts->sn = first_composition(n, &ts->state, ts->s);
600 ts->sn = next_composition(&ts->state, ts->s, ts->sn);
601 for (int i = 0; i < ts->sn; i++) {
602 n_tses += init_tree_shape__(&ts[n_tses], ts->s[i]);
607 /* Initializes 'ts[]' as the first in the set of all of possible shapes of
608 * trees with 'n' leaves. Returns the number of "struct tree_shape"s in the
609 * first tree shape. */
611 init_tree_shape(struct tree_shape ts[], int n)
624 return init_tree_shape__(ts, n);
628 /* Advances 'ts', which currently has 'n_tses' elements, to the next possible
629 * tree shape with the number of leaves passed to init_tree_shape(). Returns
630 * the number of "struct tree_shape"s in the next shape, or 0 if all tree
631 * shapes have been visited. */
633 next_tree_shape(struct tree_shape ts[], int n_tses)
635 if (n_tses == 1 && ts->sn == 2 && ts->s[0] == 1 && ts->s[1] == 1) {
639 struct tree_shape *p = &ts[n_tses - 1];
640 p->sn = p->sn > 1 ? next_composition(&p->state, p->s, p->sn) : 0;
642 for (int i = 0; i < p->sn; i++) {
643 n_tses += init_tree_shape__(&ts[n_tses], p->s[i]);
653 print_tree_shape(const struct tree_shape ts[], int n_tses)
655 for (int i = 0; i < n_tses; i++) {
659 for (int j = 0; j < ts[i].sn; j++) {
671 test_tree_shape(struct ovs_cmdl_context *ctx)
673 int n = atoi(ctx->argv[1]);
674 struct tree_shape ts[50];
677 for (n_tses = init_tree_shape(ts, n); n_tses;
678 n_tses = next_tree_shape(ts, n_tses)) {
679 print_tree_shape(ts, n_tses);
684 /* Iteration through all possible terminal expressions (e.g. EXPR_T_CMP and
685 * EXPR_T_BOOLEAN expressions).
687 * Given a tree shape, this allows the code to try all possible ways to plug in
692 * struct expr terminal;
693 * const struct expr_symbol *vars = ...;
697 * init_terminal(&terminal, vars[0]);
699 * // Something with 'terminal'.
700 * } while (next_terminal(&terminal, vars, n_vars, n_bits));
703 /* Sets 'expr' to the first possible terminal expression. 'var' should be the
704 * first variable in the ones to be tested. */
706 init_terminal(struct expr *expr, int phase,
707 const struct expr_symbol *nvars[], int n_nvars,
708 const struct expr_symbol *svars[], int n_svars)
710 if (phase < 1 && n_nvars) {
711 expr->type = EXPR_T_CMP;
712 expr->cmp.symbol = nvars[0];
713 expr->cmp.relop = rightmost_1bit_idx(test_relops);
714 memset(&expr->cmp.value, 0, sizeof expr->cmp.value);
715 memset(&expr->cmp.mask, 0, sizeof expr->cmp.mask);
716 expr->cmp.value.integer = htonll(0);
717 expr->cmp.mask.integer = htonll(1);
721 if (phase < 2 && n_svars) {
722 expr->type = EXPR_T_CMP;
723 expr->cmp.symbol = svars[0];
724 expr->cmp.relop = EXPR_R_EQ;
725 expr->cmp.string = xstrdup("0");
729 expr->type = EXPR_T_BOOLEAN;
730 expr->boolean = false;
733 /* Returns 'x' with the rightmost contiguous string of 1s changed to 0s,
734 * e.g. 01011100 => 01000000. See H. S. Warren, Jr., _Hacker's Delight_, 2nd
735 * ed., section 2-1. */
737 turn_off_rightmost_1s(unsigned int x)
739 return ((x & -x) + x) & x;
742 static const struct expr_symbol *
743 next_var(const struct expr_symbol *symbol,
744 const struct expr_symbol *vars[], int n_vars)
746 for (int i = 0; i < n_vars; i++) {
747 if (symbol == vars[i]) {
748 return i + 1 >= n_vars ? NULL : vars[i + 1];
754 static enum expr_relop
755 next_relop(enum expr_relop relop)
757 unsigned int remaining_relops = test_relops & ~((1u << (relop + 1)) - 1);
758 return (remaining_relops
759 ? rightmost_1bit_idx(remaining_relops)
760 : rightmost_1bit_idx(test_relops));
763 /* Advances 'expr' to the next possible terminal expression within the 'n_vars'
764 * variables of 'n_bits' bits each in 'vars[]'. */
766 next_terminal(struct expr *expr,
767 const struct expr_symbol *nvars[], int n_nvars, int n_bits,
768 const struct expr_symbol *svars[], int n_svars)
770 if (expr->type == EXPR_T_BOOLEAN) {
774 expr->boolean = true;
779 if (!expr->cmp.symbol->width) {
780 int next_value = atoi(expr->cmp.string) + 1;
781 free(expr->cmp.string);
782 if (next_value > 1) {
783 expr->cmp.symbol = next_var(expr->cmp.symbol, svars, n_svars);
784 if (!expr->cmp.symbol) {
785 init_terminal(expr, 2, nvars, n_nvars, svars, n_svars);
790 expr->cmp.string = xasprintf("%d", next_value);
796 next = (ntohll(expr->cmp.value.integer)
797 + (ntohll(expr->cmp.mask.integer) << n_bits));
800 unsigned m = next >> n_bits;
801 unsigned v = next & ((1u << n_bits) - 1);
802 if (next >= (1u << (2 * n_bits))) {
803 enum expr_relop old_relop = expr->cmp.relop;
804 expr->cmp.relop = next_relop(old_relop);
805 if (expr->cmp.relop <= old_relop) {
806 expr->cmp.symbol = next_var(expr->cmp.symbol, nvars, n_nvars);
807 if (!expr->cmp.symbol) {
808 init_terminal(expr, 1, nvars, n_nvars, svars, n_svars);
814 /* Skip: empty mask is pathological. */
816 /* Skip: 1-bits in value correspond to 0-bits in mask. */
817 } else if (turn_off_rightmost_1s(m)
818 && (expr->cmp.relop != EXPR_R_EQ &&
819 expr->cmp.relop != EXPR_R_NE)) {
820 /* Skip: can't have discontiguous mask for > >= < <=. */
822 expr->cmp.value.integer = htonll(v);
823 expr->cmp.mask.integer = htonll(m);
830 make_terminal(struct expr ***terminalp)
832 struct expr *e = expr_create_boolean(true);
839 build_simple_tree(enum expr_type type, int n, struct expr ***terminalp)
842 struct expr *e = expr_create_andor(type);
843 for (int i = 0; i < 2; i++) {
844 struct expr *sub = make_terminal(terminalp);
845 ovs_list_push_back(&e->andor, &sub->node);
849 return make_terminal(terminalp);
856 build_tree_shape(enum expr_type type, const struct tree_shape **tsp,
857 struct expr ***terminalp)
859 const struct tree_shape *ts = *tsp;
862 struct expr *e = expr_create_andor(type);
863 enum expr_type t = type == EXPR_T_AND ? EXPR_T_OR : EXPR_T_AND;
864 for (int i = 0; i < ts->sn; i++) {
865 struct expr *sub = (ts->s[i] > 2
866 ? build_tree_shape(t, tsp, terminalp)
867 : build_simple_tree(t, ts->s[i], terminalp));
868 ovs_list_push_back(&e->andor, &sub->node);
878 free_rule(struct test_rule *test_rule)
880 cls_rule_destroy(&test_rule->cr);
885 test_tree_shape_exhaustively(struct expr *expr, struct shash *symtab,
886 struct expr *terminals[], int n_terminals,
887 const struct expr_symbol *nvars[], int n_nvars,
889 const struct expr_symbol *svars[], int n_svars)
891 struct simap string_map = SIMAP_INITIALIZER(&string_map);
892 simap_put(&string_map, "0", 0);
893 simap_put(&string_map, "1", 1);
897 const unsigned int var_mask = (1u << n_bits) - 1;
898 for (int i = 0; i < n_terminals; i++) {
899 init_terminal(terminals[i], 0, nvars, n_nvars, svars, n_svars);
902 struct ds s = DS_EMPTY_INITIALIZER;
904 memset(&f, 0, sizeof f);
906 for (int i = n_terminals - 1; ; i--) {
909 simap_destroy(&string_map);
912 if (next_terminal(terminals[i], nvars, n_nvars, n_bits,
916 init_terminal(terminals[i], 0, nvars, n_nvars, svars, n_svars);
918 ovs_assert(expr_honors_invariants(expr));
922 struct expr *modified;
923 if (operation == OP_CONVERT) {
925 expr_format(expr, &s);
928 modified = expr_parse_string(ds_cstr(&s), symtab, &error);
930 fprintf(stderr, "%s fails to parse (%s)\n",
934 } else if (operation >= OP_SIMPLIFY) {
935 modified = expr_simplify(expr_clone(expr));
936 ovs_assert(expr_honors_invariants(modified));
938 if (operation >= OP_NORMALIZE) {
939 modified = expr_normalize(modified);
940 ovs_assert(expr_is_normalized(modified));
945 struct classifier cls;
946 if (operation >= OP_FLOW) {
947 struct expr_match *m;
948 struct test_rule *test_rule;
950 expr_to_matches(modified, lookup_port_cb, &string_map, &matches);
952 classifier_init(&cls, NULL);
953 HMAP_FOR_EACH (m, hmap_node, &matches) {
954 test_rule = xmalloc(sizeof *test_rule);
955 cls_rule_init(&test_rule->cr, &m->match, 0);
956 classifier_insert(&cls, &test_rule->cr, CLS_MIN_VERSION,
957 m->conjunctions, m->n);
960 for (int subst = 0; subst < 1 << (n_bits * n_nvars + n_svars);
962 bool expected = evaluate_expr(expr, subst, n_bits);
963 bool actual = evaluate_expr(modified, subst, n_bits);
964 if (actual != expected) {
965 struct ds expr_s, modified_s;
968 expr_format(expr, &expr_s);
970 ds_init(&modified_s);
971 expr_format(modified, &modified_s);
974 "%s evaluates to %d, but %s evaluates to %d, for",
975 ds_cstr(&expr_s), expected,
976 ds_cstr(&modified_s), actual);
977 for (int i = 0; i < n_nvars; i++) {
981 fprintf(stderr, " n%d = 0x%x", i,
982 (subst >> (n_bits * i)) & var_mask);
984 for (int i = 0; i < n_svars; i++) {
985 fprintf(stderr, ", s%d = \"%d\"", i,
986 (subst >> (n_bits * n_nvars + i)) & 1);
992 if (operation >= OP_FLOW) {
993 for (int i = 0; i < n_nvars; i++) {
994 f.regs[i] = (subst >> (i * n_bits)) & var_mask;
996 for (int i = 0; i < n_svars; i++) {
997 f.regs[n_nvars + i] = ((subst >> (n_nvars * n_bits + i))
1000 bool found = classifier_lookup(&cls, CLS_MIN_VERSION,
1002 if (expected != found) {
1003 struct ds expr_s, modified_s;
1006 expr_format(expr, &expr_s);
1008 ds_init(&modified_s);
1009 expr_format(modified, &modified_s);
1012 "%s and %s evaluate to %d, for",
1013 ds_cstr(&expr_s), ds_cstr(&modified_s), expected);
1014 for (int i = 0; i < n_nvars; i++) {
1018 fprintf(stderr, " n%d = 0x%x", i,
1019 (subst >> (n_bits * i)) & var_mask);
1021 for (int i = 0; i < n_svars; i++) {
1022 fprintf(stderr, ", s%d = \"%d\"", i,
1023 (subst >> (n_bits * n_nvars + i)) & 1);
1025 fputs(".\n", stderr);
1027 fprintf(stderr, "Converted to classifier:\n");
1028 expr_matches_print(&matches, stderr);
1030 "However, %s flow was found in the classifier.\n",
1031 found ? "a" : "no");
1036 if (operation >= OP_FLOW) {
1037 struct test_rule *test_rule;
1039 CLS_FOR_EACH (test_rule, cr, &cls) {
1040 classifier_remove(&cls, &test_rule->cr);
1041 ovsrcu_postpone(free_rule, test_rule);
1043 classifier_destroy(&cls);
1046 expr_matches_destroy(&matches);
1048 expr_destroy(modified);
1054 wait_pid(pid_t *pids, int *n)
1059 pid = waitpid(WAIT_ANY, &status, 0);
1061 ovs_fatal(errno, "waitpid failed");
1062 } else if (WIFEXITED(status)) {
1063 if (WEXITSTATUS(status)) {
1064 exit(WEXITSTATUS(status));
1066 } else if (WIFSIGNALED(status)) {
1067 raise(WTERMSIG(status));
1073 for (int i = 0; i < *n; i++) {
1074 if (pids[i] == pid) {
1075 pids[i] = pids[--*n];
1079 ovs_fatal(0, "waitpid returned unknown child");
1084 test_exhaustive(struct ovs_cmdl_context *ctx OVS_UNUSED)
1086 int n_terminals = atoi(ctx->argv[1]);
1087 struct tree_shape ts[50];
1090 struct shash symtab;
1091 const struct expr_symbol *nvars[4];
1092 const struct expr_symbol *svars[4];
1094 ovs_assert(test_nvars <= ARRAY_SIZE(nvars));
1095 ovs_assert(test_svars <= ARRAY_SIZE(svars));
1096 ovs_assert(test_nvars + test_svars <= FLOW_N_REGS);
1098 shash_init(&symtab);
1099 for (int i = 0; i < test_nvars; i++) {
1100 char *name = xasprintf("n%d", i);
1101 nvars[i] = expr_symtab_add_field(&symtab, name, MFF_REG0 + i, NULL,
1105 for (int i = 0; i < test_svars; i++) {
1106 char *name = xasprintf("s%d", i);
1107 svars[i] = expr_symtab_add_string(&symtab, name,
1108 MFF_REG0 + test_nvars + i, NULL);
1113 pid_t *children = xmalloc(test_parallel * sizeof *children);
1118 for (int i = 0; i < 2; i++) {
1119 enum expr_type base_type = i ? EXPR_T_OR : EXPR_T_AND;
1121 for (n_tses = init_tree_shape(ts, n_terminals); n_tses;
1122 n_tses = next_tree_shape(ts, n_tses)) {
1123 const struct tree_shape *tsp = ts;
1124 struct expr *terminals[50];
1125 struct expr **terminalp = terminals;
1126 struct expr *expr = build_tree_shape(base_type, &tsp, &terminalp);
1127 ovs_assert(terminalp == &terminals[n_terminals]);
1129 if (verbosity > 0) {
1130 print_tree_shape(ts, n_tses);
1132 struct ds s = DS_EMPTY_INITIALIZER;
1133 expr_format(expr, &s);
1139 if (test_parallel > 1) {
1140 pid_t pid = xfork();
1142 test_tree_shape_exhaustively(expr, &symtab,
1143 terminals, n_terminals,
1144 nvars, test_nvars, test_bits,
1149 if (n_children >= test_parallel) {
1150 wait_pid(children, &n_children);
1152 children[n_children++] = pid;
1157 n_tested += test_tree_shape_exhaustively(
1158 expr, &symtab, terminals, n_terminals,
1159 nvars, test_nvars, test_bits,
1166 while (n_children > 0) {
1167 wait_pid(children, &n_children);
1173 switch (operation) {
1175 printf("converting");
1178 printf("simplifying");
1181 printf("normalizing");
1184 printf("converting to flows");
1188 printf(" %d expressions of %d terminals", n_tested, n_terminals);
1190 printf(" all %d-terminal expressions", n_terminals);
1192 if (test_nvars || test_svars) {
1195 printf(" %d numeric vars (each %d bits) in terms of operators",
1196 test_nvars, test_bits);
1197 for (unsigned int relops = test_relops; relops;
1198 relops = zero_rightmost_1bit(relops)) {
1199 enum expr_relop r = rightmost_1bit_idx(relops);
1200 printf(" %s", expr_relop_to_string(r));
1203 if (test_nvars && test_svars) {
1207 printf(" %d string vars", test_svars);
1210 printf(" in terms of Boolean constants only");
1214 expr_symtab_destroy(&symtab);
1215 shash_destroy(&symtab);
1221 test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED)
1223 struct shash symtab;
1224 struct simap ports, ct_zones;
1227 create_symtab(&symtab);
1230 simap_put(&ports, "eth0", 5);
1231 simap_put(&ports, "eth1", 6);
1232 simap_put(&ports, "LOCAL", ofp_to_u16(OFPP_LOCAL));
1233 simap_init(&ct_zones);
1236 while (!ds_get_test_line(&input, stdin)) {
1237 struct ofpbuf ofpacts;
1238 struct expr *prereqs;
1241 ofpbuf_init(&ofpacts, 0);
1243 struct action_params ap = {
1245 .lookup_port = lookup_port_cb,
1247 .ct_zones = &ct_zones,
1252 .output_ptable = 64,
1255 error = actions_parse_string(ds_cstr(&input), &ap, &ofpacts, &prereqs);
1260 ds_put_cstr(&output, "actions=");
1261 ofpacts_format(ofpacts.data, ofpacts.size, &output);
1262 ds_put_cstr(&output, ", prereqs=");
1264 expr_format(prereqs, &output);
1266 ds_put_char(&output, '1');
1268 puts(ds_cstr(&output));
1269 ds_destroy(&output);
1275 expr_destroy(prereqs);
1276 ofpbuf_uninit(&ofpacts);
1280 simap_destroy(&ports);
1281 simap_destroy(&ct_zones);
1282 expr_symtab_destroy(&symtab);
1283 shash_destroy(&symtab);
1287 parse_relops(const char *s)
1289 unsigned int relops = 0;
1292 lexer_init(&lexer, s);
1295 enum expr_relop relop;
1297 if (expr_relop_from_token(lexer.token.type, &relop)) {
1298 relops |= 1u << relop;
1301 ovs_fatal(0, "%s: relational operator expected at `%.*s'",
1302 s, (int) (lexer.input - lexer.start), lexer.start);
1304 lexer_match(&lexer, LEX_T_COMMA);
1305 } while (lexer.token.type != LEX_T_END);
1306 lexer_destroy(&lexer);
1315 %s: OVN test utility\n\
1316 usage: test-ovn %s [OPTIONS] COMMAND [ARG...]\n\
1319 Lexically analyzes OVN input from stdin and print them back on stdout.\n\
1326 Parses OVN expressions from stdin and print them back on stdout after\n\
1327 differing degrees of analysis. Available fields are based on packet\n\
1330 evaluate-expr A B C\n\
1331 Parses OVN expressions from stdin, evaluate them with assigned values,\n\
1332 and print the results on stdout. Available fields are 'a', 'b', and 'c'\n\
1333 of 3 bits each. A, B, and C should be in the range 0 to 7.\n\
1336 Prints all the compositions of N on stdout.\n\
1339 Prints all the tree shapes with N terminals on stdout.\n\
1342 Tests that all possible Boolean expressions with N terminals are properly\n\
1343 simplified, normalized, and converted to flows. Available options:\n\
1345 --operation=OPERATION Operation to test, one of: convert, simplify,\n\
1346 normalize, flow. Default: flow. 'normalize' includes 'simplify',\n\
1347 'flow' includes 'simplify' and 'normalize'.\n\
1348 --parallel=N Number of processes to use in parallel, default 1.\n\
1350 --nvars=N Number of numeric vars to test, in range 0...4, default 2.\n\
1351 --bits=N Number of bits per variable, in range 1...3, default 3.\n\
1352 --relops=OPERATORS Test only the specified Boolean operators.\n\
1353 OPERATORS may include == != < <= > >=, space or\n\
1354 comma separated. Default is all operators.\n\
1356 --svars=N Number of string vars to test, in range 0...4, default 2.\n\
1359 Parses OVN actions from stdin and prints the equivalent OpenFlow actions\n\
1362 program_name, program_name);
1367 test_ovn_main(int argc, char *argv[])
1370 OPT_RELOPS = UCHAR_MAX + 1,
1377 static const struct option long_options[] = {
1378 {"relops", required_argument, NULL, OPT_RELOPS},
1379 {"nvars", required_argument, NULL, OPT_NVARS},
1380 {"svars", required_argument, NULL, OPT_SVARS},
1381 {"bits", required_argument, NULL, OPT_BITS},
1382 {"operation", required_argument, NULL, OPT_OPERATION},
1383 {"parallel", required_argument, NULL, OPT_PARALLEL},
1384 {"more", no_argument, NULL, 'm'},
1385 {"help", no_argument, NULL, 'h'},
1388 char *short_options = ovs_cmdl_long_options_to_short_options(long_options);
1390 set_program_name(argv[0]);
1392 test_relops = parse_relops("== != < <= > >=");
1394 int option_index = 0;
1395 int c = getopt_long (argc, argv, short_options, long_options,
1403 test_relops = parse_relops(optarg);
1407 test_nvars = atoi(optarg);
1408 if (test_nvars < 0 || test_nvars > 4) {
1409 ovs_fatal(0, "number of numeric variables must be "
1415 test_svars = atoi(optarg);
1416 if (test_svars < 0 || test_svars > 4) {
1417 ovs_fatal(0, "number of string variables must be "
1423 test_bits = atoi(optarg);
1424 if (test_bits < 1 || test_bits > 3) {
1425 ovs_fatal(0, "number of bits must be between 1 and 3");
1430 if (!strcmp(optarg, "convert")) {
1431 operation = OP_CONVERT;
1432 } else if (!strcmp(optarg, "simplify")) {
1433 operation = OP_SIMPLIFY;
1434 } else if (!strcmp(optarg, "normalize")) {
1435 operation = OP_NORMALIZE;
1436 } else if (!strcmp(optarg, "flow")) {
1437 operation = OP_FLOW;
1439 ovs_fatal(0, "%s: unknown operation", optarg);
1444 test_parallel = atoi(optarg);
1461 free(short_options);
1463 static const struct ovs_cmdl_command commands[] = {
1465 {"lex", NULL, 0, 0, test_lex},
1468 {"parse-expr", NULL, 0, 0, test_parse_expr},
1469 {"annotate-expr", NULL, 0, 0, test_annotate_expr},
1470 {"simplify-expr", NULL, 0, 0, test_simplify_expr},
1471 {"normalize-expr", NULL, 0, 0, test_normalize_expr},
1472 {"expr-to-flows", NULL, 0, 0, test_expr_to_flows},
1473 {"evaluate-expr", NULL, 1, 1, test_evaluate_expr},
1474 {"composition", NULL, 1, 1, test_composition},
1475 {"tree-shape", NULL, 1, 1, test_tree_shape},
1476 {"exhaustive", NULL, 1, 1, test_exhaustive},
1479 {"parse-actions", NULL, 0, 0, test_parse_actions},
1481 {NULL, NULL, 0, 0, NULL},
1483 struct ovs_cmdl_context ctx;
1484 ctx.argc = argc - optind;
1485 ctx.argv = argv + optind;
1486 ovs_cmdl_run_command(&ctx, commands);
1489 OVSTEST_REGISTER("test-ovn", test_ovn_main);