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 "ovn/lib/ovn-dhcp.h"
33 #include "ovs-thread.h"
39 /* --relops: Bitmap of the relational operators to test, in exhaustive test. */
40 static unsigned int test_relops;
42 /* --nvars: Number of numeric variables to test, in exhaustive test. */
43 static int test_nvars = 2;
45 /* --svars: Number of string variables to test, in exhaustive test. */
46 static int test_svars = 2;
48 /* --bits: Number of bits per variable, in exhaustive test. */
49 static int test_bits = 3;
51 /* --operation: The operation to test, in exhaustive test. */
52 static enum { OP_CONVERT, OP_SIMPLIFY, OP_NORMALIZE, OP_FLOW } operation
55 /* --parallel: Number of parallel processes to use in test. */
56 static int test_parallel = 1;
58 /* -m, --more: Message verbosity */
62 compare_token(const struct lex_token *a, const struct lex_token *b)
64 if (a->type != b->type) {
65 fprintf(stderr, "type differs: %d -> %d\n", a->type, b->type);
69 if (!((a->s && b->s && !strcmp(a->s, b->s))
70 || (!a->s && !b->s))) {
71 fprintf(stderr, "string differs: %s -> %s\n",
72 a->s ? a->s : "(null)",
73 b->s ? b->s : "(null)");
77 if (a->type == LEX_T_INTEGER || a->type == LEX_T_MASKED_INTEGER) {
78 if (memcmp(&a->value, &b->value, sizeof a->value)) {
79 fprintf(stderr, "value differs\n");
83 if (a->type == LEX_T_MASKED_INTEGER
84 && memcmp(&a->mask, &b->mask, sizeof a->mask)) {
85 fprintf(stderr, "mask differs\n");
89 if (a->format != b->format
90 && !(a->format == LEX_F_HEXADECIMAL
91 && b->format == LEX_F_DECIMAL
92 && a->value.integer == 0)) {
93 fprintf(stderr, "format differs: %d -> %d\n",
94 a->format, b->format);
100 test_lex(struct ovs_cmdl_context *ctx OVS_UNUSED)
107 while (!ds_get_test_line(&input, stdin)) {
110 lexer_init(&lexer, ds_cstr(&input));
112 while (lexer_get(&lexer) != LEX_T_END) {
113 size_t len = output.length;
114 lex_token_format(&lexer.token, &output);
116 /* Check that the formatted version can really be parsed back
118 if (lexer.token.type != LEX_T_ERROR) {
119 const char *s = ds_cstr(&output) + len;
124 compare_token(&lexer.token, &l2.token);
127 ds_put_char(&output, ' ');
129 lexer_destroy(&lexer);
131 ds_chomp(&output, ' ');
132 puts(ds_cstr(&output));
139 create_symtab(struct shash *symtab)
143 /* Reserve a pair of registers for the logical inport and outport. A full
144 * 32-bit register each is bigger than we need, but the expression code
145 * doesn't yet support string fields that occupy less than a full OXM. */
146 expr_symtab_add_string(symtab, "inport", MFF_REG14, NULL);
147 expr_symtab_add_string(symtab, "outport", MFF_REG15, NULL);
149 expr_symtab_add_field(symtab, "xxreg0", MFF_XXREG0, NULL, false);
150 expr_symtab_add_field(symtab, "xxreg1", MFF_XXREG1, NULL, false);
152 expr_symtab_add_field(symtab, "xreg0", MFF_XREG0, NULL, false);
153 expr_symtab_add_field(symtab, "xreg1", MFF_XREG1, NULL, false);
154 expr_symtab_add_field(symtab, "xreg2", MFF_XREG2, NULL, false);
156 expr_symtab_add_subfield(symtab, "reg0", NULL, "xreg0[32..63]");
157 expr_symtab_add_subfield(symtab, "reg1", NULL, "xreg0[0..31]");
158 expr_symtab_add_subfield(symtab, "reg2", NULL, "xreg1[32..63]");
159 expr_symtab_add_subfield(symtab, "reg3", NULL, "xreg1[0..31]");
160 expr_symtab_add_subfield(symtab, "reg4", NULL, "xreg2[32..63]");
161 expr_symtab_add_subfield(symtab, "reg5", NULL, "xreg2[0..31]");
163 expr_symtab_add_field(symtab, "eth.src", MFF_ETH_SRC, NULL, false);
164 expr_symtab_add_field(symtab, "eth.dst", MFF_ETH_DST, NULL, false);
165 expr_symtab_add_field(symtab, "eth.type", MFF_ETH_TYPE, NULL, true);
167 expr_symtab_add_field(symtab, "vlan.tci", MFF_VLAN_TCI, NULL, false);
168 expr_symtab_add_predicate(symtab, "vlan.present", "vlan.tci[12]");
169 expr_symtab_add_subfield(symtab, "vlan.pcp", "vlan.present",
171 expr_symtab_add_subfield(symtab, "vlan.vid", "vlan.present",
174 expr_symtab_add_predicate(symtab, "ip4", "eth.type == 0x800");
175 expr_symtab_add_predicate(symtab, "ip6", "eth.type == 0x86dd");
176 expr_symtab_add_predicate(symtab, "ip", "ip4 || ip6");
177 expr_symtab_add_field(symtab, "ip.proto", MFF_IP_PROTO, "ip", true);
178 expr_symtab_add_field(symtab, "ip.dscp", MFF_IP_DSCP, "ip", false);
179 expr_symtab_add_field(symtab, "ip.ecn", MFF_IP_ECN, "ip", false);
180 expr_symtab_add_field(symtab, "ip.ttl", MFF_IP_TTL, "ip", false);
182 expr_symtab_add_field(symtab, "ip4.src", MFF_IPV4_SRC, "ip4", false);
183 expr_symtab_add_field(symtab, "ip4.dst", MFF_IPV4_DST, "ip4", false);
185 expr_symtab_add_predicate(symtab, "icmp4", "ip4 && ip.proto == 1");
186 expr_symtab_add_field(symtab, "icmp4.type", MFF_ICMPV4_TYPE, "icmp4",
188 expr_symtab_add_field(symtab, "icmp4.code", MFF_ICMPV4_CODE, "icmp4",
191 expr_symtab_add_field(symtab, "ip6.src", MFF_IPV6_SRC, "ip6", false);
192 expr_symtab_add_field(symtab, "ip6.dst", MFF_IPV6_DST, "ip6", false);
193 expr_symtab_add_field(symtab, "ip6.label", MFF_IPV6_LABEL, "ip6", false);
195 expr_symtab_add_predicate(symtab, "icmp6", "ip6 && ip.proto == 58");
196 expr_symtab_add_field(symtab, "icmp6.type", MFF_ICMPV6_TYPE, "icmp6",
198 expr_symtab_add_field(symtab, "icmp6.code", MFF_ICMPV6_CODE, "icmp6",
201 expr_symtab_add_predicate(symtab, "icmp", "icmp4 || icmp6");
203 expr_symtab_add_field(symtab, "ip.frag", MFF_IP_FRAG, "ip", false);
204 expr_symtab_add_predicate(symtab, "ip.is_frag", "ip.frag[0]");
205 expr_symtab_add_predicate(symtab, "ip.later_frag", "ip.frag[1]");
206 expr_symtab_add_predicate(symtab, "ip.first_frag", "ip.is_frag && !ip.later_frag");
208 expr_symtab_add_predicate(symtab, "arp", "eth.type == 0x806");
209 expr_symtab_add_field(symtab, "arp.op", MFF_ARP_OP, "arp", false);
210 expr_symtab_add_field(symtab, "arp.spa", MFF_ARP_SPA, "arp", false);
211 expr_symtab_add_field(symtab, "arp.sha", MFF_ARP_SHA, "arp", false);
212 expr_symtab_add_field(symtab, "arp.tpa", MFF_ARP_TPA, "arp", false);
213 expr_symtab_add_field(symtab, "arp.tha", MFF_ARP_THA, "arp", false);
215 expr_symtab_add_predicate(symtab, "nd", "icmp6.type == {135, 136} && icmp6.code == 0");
216 expr_symtab_add_field(symtab, "nd.target", MFF_ND_TARGET, "nd", false);
217 expr_symtab_add_field(symtab, "nd.sll", MFF_ND_SLL,
218 "nd && icmp6.type == 135", false);
219 expr_symtab_add_field(symtab, "nd.tll", MFF_ND_TLL,
220 "nd && icmp6.type == 136", false);
222 expr_symtab_add_predicate(symtab, "tcp", "ip.proto == 6");
223 expr_symtab_add_field(symtab, "tcp.src", MFF_TCP_SRC, "tcp", false);
224 expr_symtab_add_field(symtab, "tcp.dst", MFF_TCP_DST, "tcp", false);
225 expr_symtab_add_field(symtab, "tcp.flags", MFF_TCP_FLAGS, "tcp", false);
227 expr_symtab_add_predicate(symtab, "udp", "ip.proto == 17");
228 expr_symtab_add_field(symtab, "udp.src", MFF_UDP_SRC, "udp", false);
229 expr_symtab_add_field(symtab, "udp.dst", MFF_UDP_DST, "udp", false);
231 expr_symtab_add_predicate(symtab, "sctp", "ip.proto == 132");
232 expr_symtab_add_field(symtab, "sctp.src", MFF_SCTP_SRC, "sctp", false);
233 expr_symtab_add_field(symtab, "sctp.dst", MFF_SCTP_DST, "sctp", false);
235 /* For negative testing. */
236 expr_symtab_add_field(symtab, "bad_prereq", MFF_XREG0, "xyzzy", false);
237 expr_symtab_add_field(symtab, "self_recurse", MFF_XREG0,
238 "self_recurse != 0", false);
239 expr_symtab_add_field(symtab, "mutual_recurse_1", MFF_XREG0,
240 "mutual_recurse_2 != 0", false);
241 expr_symtab_add_field(symtab, "mutual_recurse_2", MFF_XREG0,
242 "mutual_recurse_1 != 0", false);
243 expr_symtab_add_string(symtab, "big_string", MFF_XREG0, NULL);
247 create_dhcp_opts(struct hmap *dhcp_opts)
249 hmap_init(dhcp_opts);
250 dhcp_opt_add(dhcp_opts, "offerip", 0, "ipv4");
251 dhcp_opt_add(dhcp_opts, "netmask", 1, "ipv4");
252 dhcp_opt_add(dhcp_opts, "router", 3, "ipv4");
253 dhcp_opt_add(dhcp_opts, "dns_server", 6, "ipv4");
254 dhcp_opt_add(dhcp_opts, "log_server", 7, "ipv4");
255 dhcp_opt_add(dhcp_opts, "lpr_server", 9, "ipv4");
256 dhcp_opt_add(dhcp_opts, "domain", 15, "str");
257 dhcp_opt_add(dhcp_opts, "swap_server", 16, "ipv4");
258 dhcp_opt_add(dhcp_opts, "policy_filter", 21, "ipv4");
259 dhcp_opt_add(dhcp_opts, "router_solicitation", 32, "ipv4");
260 dhcp_opt_add(dhcp_opts, "nis_server", 41, "ipv4");
261 dhcp_opt_add(dhcp_opts, "ntp_server", 42, "ipv4");
262 dhcp_opt_add(dhcp_opts, "server_id", 54, "ipv4");
263 dhcp_opt_add(dhcp_opts, "tftp_server", 66, "ipv4");
264 dhcp_opt_add(dhcp_opts, "classless_static_route", 121, "static_routes");
265 dhcp_opt_add(dhcp_opts, "ip_forward_enable", 19, "bool");
266 dhcp_opt_add(dhcp_opts, "router_discovery", 31, "bool");
267 dhcp_opt_add(dhcp_opts, "ethernet_encap", 36, "bool");
268 dhcp_opt_add(dhcp_opts, "default_ttl", 23, "uint8");
269 dhcp_opt_add(dhcp_opts, "tcp_ttl", 37, "uint8");
270 dhcp_opt_add(dhcp_opts, "mtu", 26, "uint16");
271 dhcp_opt_add(dhcp_opts, "lease_time", 51, "uint32");
275 create_macros(struct shash *macros)
279 static const char *const addrs1[] = {
280 "10.0.0.1", "10.0.0.2", "10.0.0.3",
282 static const char *const addrs2[] = {
285 static const char *const addrs3[] = {
286 "00:00:00:00:00:01", "00:00:00:00:00:02", "00:00:00:00:00:03",
289 expr_macros_add(macros, "set1", addrs1, 3);
290 expr_macros_add(macros, "set2", addrs2, 3);
291 expr_macros_add(macros, "set3", addrs3, 3);
295 lookup_port_cb(const void *ports_, const char *port_name, unsigned int *portp)
297 const struct simap *ports = ports_;
298 const struct simap_node *node = simap_find(ports, port_name);
307 test_parse_expr__(int steps)
314 create_symtab(&symtab);
315 create_macros(¯os);
318 simap_put(&ports, "eth0", 5);
319 simap_put(&ports, "eth1", 6);
320 simap_put(&ports, "LOCAL", ofp_to_u16(OFPP_LOCAL));
323 while (!ds_get_test_line(&input, stdin)) {
327 expr = expr_parse_string(ds_cstr(&input), &symtab, ¯os, &error);
328 if (!error && steps > 0) {
329 expr = expr_annotate(expr, &symtab, &error);
333 expr = expr_simplify(expr);
336 expr = expr_normalize(expr);
337 ovs_assert(expr_is_normalized(expr));
344 expr_to_matches(expr, lookup_port_cb, &ports, &matches);
345 expr_matches_print(&matches, stdout);
346 expr_matches_destroy(&matches);
348 struct ds output = DS_EMPTY_INITIALIZER;
349 expr_format(expr, &output);
350 puts(ds_cstr(&output));
361 simap_destroy(&ports);
362 expr_symtab_destroy(&symtab);
363 shash_destroy(&symtab);
364 expr_macros_destroy(¯os);
365 shash_destroy(¯os);
369 test_parse_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
371 test_parse_expr__(0);
375 test_annotate_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
377 test_parse_expr__(1);
381 test_simplify_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
383 test_parse_expr__(2);
387 test_normalize_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
389 test_parse_expr__(3);
393 test_expr_to_flows(struct ovs_cmdl_context *ctx OVS_UNUSED)
395 test_parse_expr__(4);
398 /* Evaluate an expression. */
400 static bool evaluate_expr(const struct expr *, unsigned int subst, int n_bits);
403 evaluate_andor_expr(const struct expr *expr, unsigned int subst, int n_bits,
406 const struct expr *sub;
408 LIST_FOR_EACH (sub, node, &expr->andor) {
409 if (evaluate_expr(sub, subst, n_bits) == short_circuit) {
410 return short_circuit;
413 return !short_circuit;
417 evaluate_cmp_expr(const struct expr *expr, unsigned int subst, int n_bits)
419 int var_idx = atoi(expr->cmp.symbol->name + 1);
420 if (expr->cmp.symbol->name[0] == 'n') {
421 unsigned var_mask = (1u << n_bits) - 1;
422 unsigned int arg1 = (subst >> (var_idx * n_bits)) & var_mask;
423 unsigned int arg2 = ntohll(expr->cmp.value.integer);
424 unsigned int mask = ntohll(expr->cmp.mask.integer);
426 ovs_assert(!(mask & ~var_mask));
427 ovs_assert(!(arg2 & ~var_mask));
428 ovs_assert(!(arg2 & ~mask));
431 switch (expr->cmp.relop) {
453 } else if (expr->cmp.symbol->name[0] == 's') {
454 unsigned int arg1 = (subst >> (test_nvars * n_bits + var_idx)) & 1;
455 unsigned int arg2 = atoi(expr->cmp.string);
462 /* Evaluates 'expr' and returns its Boolean result. 'subst' provides the value
463 * for the variables, which must be 'n_bits' bits each and be named "a", "b",
464 * "c", etc. The value of variable "a" is the least-significant 'n_bits' bits
465 * of 'subst', the value of "b" is the next 'n_bits' bits, and so on. */
467 evaluate_expr(const struct expr *expr, unsigned int subst, int n_bits)
469 switch (expr->type) {
471 return evaluate_cmp_expr(expr, subst, n_bits);
474 return evaluate_andor_expr(expr, subst, n_bits, false);
477 return evaluate_andor_expr(expr, subst, n_bits, true);
480 return expr->boolean;
488 test_evaluate_expr(struct ovs_cmdl_context *ctx)
490 int a = atoi(ctx->argv[1]);
491 int b = atoi(ctx->argv[2]);
492 int c = atoi(ctx->argv[3]);
493 unsigned int subst = a | (b << 3) || (c << 6);
498 expr_symtab_add_field(&symtab, "xreg0", MFF_XREG0, NULL, false);
499 expr_symtab_add_field(&symtab, "xreg1", MFF_XREG1, NULL, false);
500 expr_symtab_add_field(&symtab, "xreg2", MFF_XREG1, NULL, false);
501 expr_symtab_add_subfield(&symtab, "a", NULL, "xreg0[0..2]");
502 expr_symtab_add_subfield(&symtab, "b", NULL, "xreg1[0..2]");
503 expr_symtab_add_subfield(&symtab, "c", NULL, "xreg2[0..2]");
506 while (!ds_get_test_line(&input, stdin)) {
510 expr = expr_parse_string(ds_cstr(&input), &symtab, NULL, &error);
512 expr = expr_annotate(expr, &symtab, &error);
515 printf("%d\n", evaluate_expr(expr, subst, 3));
524 expr_symtab_destroy(&symtab);
525 shash_destroy(&symtab);
530 * The "compositions" of a positive integer N are all of the ways that one can
531 * add up positive integers to sum to N. For example, the compositions of 3
532 * are 3, 2+1, 1+2, and 1+1+1.
534 * We use compositions to find all the ways to break up N terms of a Boolean
535 * expression into subexpressions. Suppose we want to generate all expressions
536 * with 3 terms. The compositions of 3 (ignoring 3 itself) provide the
537 * possibilities (x && x) || x, x || (x && x), and x || x || x. (Of course one
538 * can exchange && for || in each case.) One must recursively compose the
539 * sub-expressions whose values are 3 or greater; that is what the "tree shape"
540 * concept later covers.
542 * To iterate through all compositions of, e.g., 5:
544 * unsigned int state;
548 * for (n = first_composition(ARRAY_SIZE(s), &state, s); n > 0;
549 * n = next_composition(&state, s, n)) {
550 * // Do something with composition 's' with 'n' elements.
553 * Algorithm from D. E. Knuth, _The Art of Computer Programming, Vol. 4A:
554 * Combinatorial Algorithms, Part 1_, section 7.2.1.1, answer to exercise
558 /* Begins iteration through the compositions of 'n'. Initializes 's' to the
559 * number of elements in the first composition of 'n' and returns that number
560 * of elements. The first composition in fact is always 'n' itself, so the
561 * return value will be 1.
563 * Initializes '*state' to some internal state information. The caller must
564 * maintain this state (and 's') for use by next_composition().
566 * 's' must have room for at least 'n' elements. */
568 first_composition(int n, unsigned int *state, int s[])
575 /* Advances 's', with 'sn' elements, to the next composition and returns the
576 * number of elements in this new composition, or 0 if no compositions are
577 * left. 'state' is the same internal state passed to first_composition(). */
579 next_composition(unsigned int *state, int s[], int sn)
610 test_composition(struct ovs_cmdl_context *ctx)
612 int n = atoi(ctx->argv[1]);
616 for (int sn = first_composition(n, &state, s); sn;
617 sn = next_composition(&state, s, sn)) {
618 for (int i = 0; i < sn; i++) {
619 printf("%d%c", s[i], i == sn - 1 ? '\n' : ' ');
626 * This code generates all possible Boolean expressions with a specified number
627 * of terms N (equivalent to the number of external nodes in a tree).
629 * See test_tree_shape() for a simple example. */
631 /* An array of these structures describes the shape of a tree.
633 * A single element of struct tree_shape describes a single node in the tree.
634 * The node has 'sn' direct children. From left to right, for i in 0...sn-1,
635 * s[i] is 1 if the child is a leaf node, otherwise the child is a subtree and
636 * s[i] is the number of leaf nodes within that subtree. In the latter case,
637 * the subtree is described by another struct tree_shape within the enclosing
638 * array. The tree_shapes are ordered in the array in in-order.
647 init_tree_shape__(struct tree_shape ts[], int n)
654 /* Skip the first composition intentionally. */
655 ts->sn = first_composition(n, &ts->state, ts->s);
656 ts->sn = next_composition(&ts->state, ts->s, ts->sn);
657 for (int i = 0; i < ts->sn; i++) {
658 n_tses += init_tree_shape__(&ts[n_tses], ts->s[i]);
663 /* Initializes 'ts[]' as the first in the set of all of possible shapes of
664 * trees with 'n' leaves. Returns the number of "struct tree_shape"s in the
665 * first tree shape. */
667 init_tree_shape(struct tree_shape ts[], int n)
680 return init_tree_shape__(ts, n);
684 /* Advances 'ts', which currently has 'n_tses' elements, to the next possible
685 * tree shape with the number of leaves passed to init_tree_shape(). Returns
686 * the number of "struct tree_shape"s in the next shape, or 0 if all tree
687 * shapes have been visited. */
689 next_tree_shape(struct tree_shape ts[], int n_tses)
691 if (n_tses == 1 && ts->sn == 2 && ts->s[0] == 1 && ts->s[1] == 1) {
695 struct tree_shape *p = &ts[n_tses - 1];
696 p->sn = p->sn > 1 ? next_composition(&p->state, p->s, p->sn) : 0;
698 for (int i = 0; i < p->sn; i++) {
699 n_tses += init_tree_shape__(&ts[n_tses], p->s[i]);
709 print_tree_shape(const struct tree_shape ts[], int n_tses)
711 for (int i = 0; i < n_tses; i++) {
715 for (int j = 0; j < ts[i].sn; j++) {
727 test_tree_shape(struct ovs_cmdl_context *ctx)
729 int n = atoi(ctx->argv[1]);
730 struct tree_shape ts[50];
733 for (n_tses = init_tree_shape(ts, n); n_tses;
734 n_tses = next_tree_shape(ts, n_tses)) {
735 print_tree_shape(ts, n_tses);
740 /* Iteration through all possible terminal expressions (e.g. EXPR_T_CMP and
741 * EXPR_T_BOOLEAN expressions).
743 * Given a tree shape, this allows the code to try all possible ways to plug in
748 * struct expr terminal;
749 * const struct expr_symbol *vars = ...;
753 * init_terminal(&terminal, vars[0]);
755 * // Something with 'terminal'.
756 * } while (next_terminal(&terminal, vars, n_vars, n_bits));
759 /* Sets 'expr' to the first possible terminal expression. 'var' should be the
760 * first variable in the ones to be tested. */
762 init_terminal(struct expr *expr, int phase,
763 const struct expr_symbol *nvars[], int n_nvars,
764 const struct expr_symbol *svars[], int n_svars)
766 if (phase < 1 && n_nvars) {
767 expr->type = EXPR_T_CMP;
768 expr->cmp.symbol = nvars[0];
769 expr->cmp.relop = rightmost_1bit_idx(test_relops);
770 memset(&expr->cmp.value, 0, sizeof expr->cmp.value);
771 memset(&expr->cmp.mask, 0, sizeof expr->cmp.mask);
772 expr->cmp.value.integer = htonll(0);
773 expr->cmp.mask.integer = htonll(1);
777 if (phase < 2 && n_svars) {
778 expr->type = EXPR_T_CMP;
779 expr->cmp.symbol = svars[0];
780 expr->cmp.relop = EXPR_R_EQ;
781 expr->cmp.string = xstrdup("0");
785 expr->type = EXPR_T_BOOLEAN;
786 expr->boolean = false;
789 /* Returns 'x' with the rightmost contiguous string of 1s changed to 0s,
790 * e.g. 01011100 => 01000000. See H. S. Warren, Jr., _Hacker's Delight_, 2nd
791 * ed., section 2-1. */
793 turn_off_rightmost_1s(unsigned int x)
795 return ((x & -x) + x) & x;
798 static const struct expr_symbol *
799 next_var(const struct expr_symbol *symbol,
800 const struct expr_symbol *vars[], int n_vars)
802 for (int i = 0; i < n_vars; i++) {
803 if (symbol == vars[i]) {
804 return i + 1 >= n_vars ? NULL : vars[i + 1];
810 static enum expr_relop
811 next_relop(enum expr_relop relop)
813 unsigned int remaining_relops = test_relops & ~((1u << (relop + 1)) - 1);
814 return (remaining_relops
815 ? rightmost_1bit_idx(remaining_relops)
816 : rightmost_1bit_idx(test_relops));
819 /* Advances 'expr' to the next possible terminal expression within the 'n_vars'
820 * variables of 'n_bits' bits each in 'vars[]'. */
822 next_terminal(struct expr *expr,
823 const struct expr_symbol *nvars[], int n_nvars, int n_bits,
824 const struct expr_symbol *svars[], int n_svars)
826 if (expr->type == EXPR_T_BOOLEAN) {
830 expr->boolean = true;
835 if (!expr->cmp.symbol->width) {
836 int next_value = atoi(expr->cmp.string) + 1;
837 free(expr->cmp.string);
838 if (next_value > 1) {
839 expr->cmp.symbol = next_var(expr->cmp.symbol, svars, n_svars);
840 if (!expr->cmp.symbol) {
841 init_terminal(expr, 2, nvars, n_nvars, svars, n_svars);
846 expr->cmp.string = xasprintf("%d", next_value);
852 next = (ntohll(expr->cmp.value.integer)
853 + (ntohll(expr->cmp.mask.integer) << n_bits));
856 unsigned m = next >> n_bits;
857 unsigned v = next & ((1u << n_bits) - 1);
858 if (next >= (1u << (2 * n_bits))) {
859 enum expr_relop old_relop = expr->cmp.relop;
860 expr->cmp.relop = next_relop(old_relop);
861 if (expr->cmp.relop <= old_relop) {
862 expr->cmp.symbol = next_var(expr->cmp.symbol, nvars, n_nvars);
863 if (!expr->cmp.symbol) {
864 init_terminal(expr, 1, nvars, n_nvars, svars, n_svars);
870 /* Skip: empty mask is pathological. */
872 /* Skip: 1-bits in value correspond to 0-bits in mask. */
873 } else if (turn_off_rightmost_1s(m)
874 && (expr->cmp.relop != EXPR_R_EQ &&
875 expr->cmp.relop != EXPR_R_NE)) {
876 /* Skip: can't have discontiguous mask for > >= < <=. */
878 expr->cmp.value.integer = htonll(v);
879 expr->cmp.mask.integer = htonll(m);
886 make_terminal(struct expr ***terminalp)
888 struct expr *e = expr_create_boolean(true);
895 build_simple_tree(enum expr_type type, int n, struct expr ***terminalp)
898 struct expr *e = expr_create_andor(type);
899 for (int i = 0; i < 2; i++) {
900 struct expr *sub = make_terminal(terminalp);
901 ovs_list_push_back(&e->andor, &sub->node);
905 return make_terminal(terminalp);
912 build_tree_shape(enum expr_type type, const struct tree_shape **tsp,
913 struct expr ***terminalp)
915 const struct tree_shape *ts = *tsp;
918 struct expr *e = expr_create_andor(type);
919 enum expr_type t = type == EXPR_T_AND ? EXPR_T_OR : EXPR_T_AND;
920 for (int i = 0; i < ts->sn; i++) {
921 struct expr *sub = (ts->s[i] > 2
922 ? build_tree_shape(t, tsp, terminalp)
923 : build_simple_tree(t, ts->s[i], terminalp));
924 ovs_list_push_back(&e->andor, &sub->node);
934 free_rule(struct test_rule *test_rule)
936 cls_rule_destroy(&test_rule->cr);
941 test_tree_shape_exhaustively(struct expr *expr, struct shash *symtab,
942 struct expr *terminals[], int n_terminals,
943 const struct expr_symbol *nvars[], int n_nvars,
945 const struct expr_symbol *svars[], int n_svars)
947 struct simap string_map = SIMAP_INITIALIZER(&string_map);
948 simap_put(&string_map, "0", 0);
949 simap_put(&string_map, "1", 1);
953 const unsigned int var_mask = (1u << n_bits) - 1;
954 for (int i = 0; i < n_terminals; i++) {
955 init_terminal(terminals[i], 0, nvars, n_nvars, svars, n_svars);
958 struct ds s = DS_EMPTY_INITIALIZER;
960 memset(&f, 0, sizeof f);
962 for (int i = n_terminals - 1; ; i--) {
965 simap_destroy(&string_map);
968 if (next_terminal(terminals[i], nvars, n_nvars, n_bits,
972 init_terminal(terminals[i], 0, nvars, n_nvars, svars, n_svars);
974 ovs_assert(expr_honors_invariants(expr));
978 struct expr *modified;
979 if (operation == OP_CONVERT) {
981 expr_format(expr, &s);
984 modified = expr_parse_string(ds_cstr(&s), symtab, NULL, &error);
986 fprintf(stderr, "%s fails to parse (%s)\n",
990 } else if (operation >= OP_SIMPLIFY) {
991 modified = expr_simplify(expr_clone(expr));
992 ovs_assert(expr_honors_invariants(modified));
994 if (operation >= OP_NORMALIZE) {
995 modified = expr_normalize(modified);
996 ovs_assert(expr_is_normalized(modified));
1000 struct hmap matches;
1001 struct classifier cls;
1002 if (operation >= OP_FLOW) {
1003 struct expr_match *m;
1004 struct test_rule *test_rule;
1006 expr_to_matches(modified, lookup_port_cb, &string_map, &matches);
1008 classifier_init(&cls, NULL);
1009 HMAP_FOR_EACH (m, hmap_node, &matches) {
1010 test_rule = xmalloc(sizeof *test_rule);
1011 cls_rule_init(&test_rule->cr, &m->match, 0);
1012 classifier_insert(&cls, &test_rule->cr, CLS_MIN_VERSION,
1013 m->conjunctions, m->n);
1016 for (int subst = 0; subst < 1 << (n_bits * n_nvars + n_svars);
1018 bool expected = evaluate_expr(expr, subst, n_bits);
1019 bool actual = evaluate_expr(modified, subst, n_bits);
1020 if (actual != expected) {
1021 struct ds expr_s, modified_s;
1024 expr_format(expr, &expr_s);
1026 ds_init(&modified_s);
1027 expr_format(modified, &modified_s);
1030 "%s evaluates to %d, but %s evaluates to %d, for",
1031 ds_cstr(&expr_s), expected,
1032 ds_cstr(&modified_s), actual);
1033 for (int i = 0; i < n_nvars; i++) {
1037 fprintf(stderr, " n%d = 0x%x", i,
1038 (subst >> (n_bits * i)) & var_mask);
1040 for (int i = 0; i < n_svars; i++) {
1041 fprintf(stderr, ", s%d = \"%d\"", i,
1042 (subst >> (n_bits * n_nvars + i)) & 1);
1048 if (operation >= OP_FLOW) {
1049 for (int i = 0; i < n_nvars; i++) {
1050 f.regs[i] = (subst >> (i * n_bits)) & var_mask;
1052 for (int i = 0; i < n_svars; i++) {
1053 f.regs[n_nvars + i] = ((subst >> (n_nvars * n_bits + i))
1056 bool found = classifier_lookup(&cls, CLS_MIN_VERSION,
1058 if (expected != found) {
1059 struct ds expr_s, modified_s;
1062 expr_format(expr, &expr_s);
1064 ds_init(&modified_s);
1065 expr_format(modified, &modified_s);
1068 "%s and %s evaluate to %d, for",
1069 ds_cstr(&expr_s), ds_cstr(&modified_s), expected);
1070 for (int i = 0; i < n_nvars; i++) {
1074 fprintf(stderr, " n%d = 0x%x", i,
1075 (subst >> (n_bits * i)) & var_mask);
1077 for (int i = 0; i < n_svars; i++) {
1078 fprintf(stderr, ", s%d = \"%d\"", i,
1079 (subst >> (n_bits * n_nvars + i)) & 1);
1081 fputs(".\n", stderr);
1083 fprintf(stderr, "Converted to classifier:\n");
1084 expr_matches_print(&matches, stderr);
1086 "However, %s flow was found in the classifier.\n",
1087 found ? "a" : "no");
1092 if (operation >= OP_FLOW) {
1093 struct test_rule *test_rule;
1095 CLS_FOR_EACH (test_rule, cr, &cls) {
1096 classifier_remove(&cls, &test_rule->cr);
1097 ovsrcu_postpone(free_rule, test_rule);
1099 classifier_destroy(&cls);
1102 expr_matches_destroy(&matches);
1104 expr_destroy(modified);
1110 wait_pid(pid_t *pids, int *n)
1115 pid = waitpid(WAIT_ANY, &status, 0);
1117 ovs_fatal(errno, "waitpid failed");
1118 } else if (WIFEXITED(status)) {
1119 if (WEXITSTATUS(status)) {
1120 exit(WEXITSTATUS(status));
1122 } else if (WIFSIGNALED(status)) {
1123 raise(WTERMSIG(status));
1129 for (int i = 0; i < *n; i++) {
1130 if (pids[i] == pid) {
1131 pids[i] = pids[--*n];
1135 ovs_fatal(0, "waitpid returned unknown child");
1140 test_exhaustive(struct ovs_cmdl_context *ctx OVS_UNUSED)
1142 int n_terminals = atoi(ctx->argv[1]);
1143 struct tree_shape ts[50];
1146 struct shash symtab;
1147 const struct expr_symbol *nvars[4];
1148 const struct expr_symbol *svars[4];
1150 ovs_assert(test_nvars <= ARRAY_SIZE(nvars));
1151 ovs_assert(test_svars <= ARRAY_SIZE(svars));
1152 ovs_assert(test_nvars + test_svars <= FLOW_N_REGS);
1154 shash_init(&symtab);
1155 for (int i = 0; i < test_nvars; i++) {
1156 char *name = xasprintf("n%d", i);
1157 nvars[i] = expr_symtab_add_field(&symtab, name, MFF_REG0 + i, NULL,
1161 for (int i = 0; i < test_svars; i++) {
1162 char *name = xasprintf("s%d", i);
1163 svars[i] = expr_symtab_add_string(&symtab, name,
1164 MFF_REG0 + test_nvars + i, NULL);
1169 pid_t *children = xmalloc(test_parallel * sizeof *children);
1174 for (int i = 0; i < 2; i++) {
1175 enum expr_type base_type = i ? EXPR_T_OR : EXPR_T_AND;
1177 for (n_tses = init_tree_shape(ts, n_terminals); n_tses;
1178 n_tses = next_tree_shape(ts, n_tses)) {
1179 const struct tree_shape *tsp = ts;
1180 struct expr *terminals[50];
1181 struct expr **terminalp = terminals;
1182 struct expr *expr = build_tree_shape(base_type, &tsp, &terminalp);
1183 ovs_assert(terminalp == &terminals[n_terminals]);
1185 if (verbosity > 0) {
1186 print_tree_shape(ts, n_tses);
1188 struct ds s = DS_EMPTY_INITIALIZER;
1189 expr_format(expr, &s);
1195 if (test_parallel > 1) {
1196 pid_t pid = xfork();
1198 test_tree_shape_exhaustively(expr, &symtab,
1199 terminals, n_terminals,
1200 nvars, test_nvars, test_bits,
1205 if (n_children >= test_parallel) {
1206 wait_pid(children, &n_children);
1208 children[n_children++] = pid;
1213 n_tested += test_tree_shape_exhaustively(
1214 expr, &symtab, terminals, n_terminals,
1215 nvars, test_nvars, test_bits,
1222 while (n_children > 0) {
1223 wait_pid(children, &n_children);
1229 switch (operation) {
1231 printf("converting");
1234 printf("simplifying");
1237 printf("normalizing");
1240 printf("converting to flows");
1244 printf(" %d expressions of %d terminals", n_tested, n_terminals);
1246 printf(" all %d-terminal expressions", n_terminals);
1248 if (test_nvars || test_svars) {
1251 printf(" %d numeric vars (each %d bits) in terms of operators",
1252 test_nvars, test_bits);
1253 for (unsigned int relops = test_relops; relops;
1254 relops = zero_rightmost_1bit(relops)) {
1255 enum expr_relop r = rightmost_1bit_idx(relops);
1256 printf(" %s", expr_relop_to_string(r));
1259 if (test_nvars && test_svars) {
1263 printf(" %d string vars", test_svars);
1266 printf(" in terms of Boolean constants only");
1270 expr_symtab_destroy(&symtab);
1271 shash_destroy(&symtab);
1277 test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED)
1279 struct shash symtab;
1280 struct hmap dhcp_opts;
1281 struct simap ports, ct_zones;
1284 create_symtab(&symtab);
1285 create_dhcp_opts(&dhcp_opts);
1287 /* Initialize group ids. */
1288 struct group_table group_table;
1289 group_table.group_ids = bitmap_allocate(MAX_OVN_GROUPS);
1290 bitmap_set1(group_table.group_ids, 0); /* Group id 0 is invalid. */
1291 hmap_init(&group_table.desired_groups);
1292 hmap_init(&group_table.existing_groups);
1295 simap_put(&ports, "eth0", 5);
1296 simap_put(&ports, "eth1", 6);
1297 simap_put(&ports, "LOCAL", ofp_to_u16(OFPP_LOCAL));
1298 simap_init(&ct_zones);
1301 while (!ds_get_test_line(&input, stdin)) {
1302 struct ofpbuf ofpacts;
1303 struct expr *prereqs;
1306 ofpbuf_init(&ofpacts, 0);
1308 struct action_params ap = {
1310 .dhcp_opts = &dhcp_opts,
1311 .lookup_port = lookup_port_cb,
1313 .ct_zones = &ct_zones,
1314 .group_table = &group_table,
1319 .output_ptable = 64,
1322 error = actions_parse_string(ds_cstr(&input), &ap, &ofpacts, &prereqs);
1327 ds_put_cstr(&output, "actions=");
1328 ofpacts_format(ofpacts.data, ofpacts.size, &output);
1329 ds_put_cstr(&output, ", prereqs=");
1331 expr_format(prereqs, &output);
1333 ds_put_char(&output, '1');
1335 puts(ds_cstr(&output));
1336 ds_destroy(&output);
1342 expr_destroy(prereqs);
1343 ofpbuf_uninit(&ofpacts);
1347 simap_destroy(&ports);
1348 simap_destroy(&ct_zones);
1349 expr_symtab_destroy(&symtab);
1350 shash_destroy(&symtab);
1354 parse_relops(const char *s)
1356 unsigned int relops = 0;
1359 lexer_init(&lexer, s);
1362 enum expr_relop relop;
1364 if (expr_relop_from_token(lexer.token.type, &relop)) {
1365 relops |= 1u << relop;
1368 ovs_fatal(0, "%s: relational operator expected at `%.*s'",
1369 s, (int) (lexer.input - lexer.start), lexer.start);
1371 lexer_match(&lexer, LEX_T_COMMA);
1372 } while (lexer.token.type != LEX_T_END);
1373 lexer_destroy(&lexer);
1382 %s: OVN test utility\n\
1383 usage: test-ovn %s [OPTIONS] COMMAND [ARG...]\n\
1386 Lexically analyzes OVN input from stdin and print them back on stdout.\n\
1393 Parses OVN expressions from stdin and print them back on stdout after\n\
1394 differing degrees of analysis. Available fields are based on packet\n\
1397 evaluate-expr A B C\n\
1398 Parses OVN expressions from stdin, evaluate them with assigned values,\n\
1399 and print the results on stdout. Available fields are 'a', 'b', and 'c'\n\
1400 of 3 bits each. A, B, and C should be in the range 0 to 7.\n\
1403 Prints all the compositions of N on stdout.\n\
1406 Prints all the tree shapes with N terminals on stdout.\n\
1409 Tests that all possible Boolean expressions with N terminals are properly\n\
1410 simplified, normalized, and converted to flows. Available options:\n\
1412 --operation=OPERATION Operation to test, one of: convert, simplify,\n\
1413 normalize, flow. Default: flow. 'normalize' includes 'simplify',\n\
1414 'flow' includes 'simplify' and 'normalize'.\n\
1415 --parallel=N Number of processes to use in parallel, default 1.\n\
1417 --nvars=N Number of numeric vars to test, in range 0...4, default 2.\n\
1418 --bits=N Number of bits per variable, in range 1...3, default 3.\n\
1419 --relops=OPERATORS Test only the specified Boolean operators.\n\
1420 OPERATORS may include == != < <= > >=, space or\n\
1421 comma separated. Default is all operators.\n\
1423 --svars=N Number of string vars to test, in range 0...4, default 2.\n\
1426 Parses OVN actions from stdin and prints the equivalent OpenFlow actions\n\
1429 program_name, program_name);
1434 test_ovn_main(int argc, char *argv[])
1437 OPT_RELOPS = UCHAR_MAX + 1,
1444 static const struct option long_options[] = {
1445 {"relops", required_argument, NULL, OPT_RELOPS},
1446 {"nvars", required_argument, NULL, OPT_NVARS},
1447 {"svars", required_argument, NULL, OPT_SVARS},
1448 {"bits", required_argument, NULL, OPT_BITS},
1449 {"operation", required_argument, NULL, OPT_OPERATION},
1450 {"parallel", required_argument, NULL, OPT_PARALLEL},
1451 {"more", no_argument, NULL, 'm'},
1452 {"help", no_argument, NULL, 'h'},
1455 char *short_options = ovs_cmdl_long_options_to_short_options(long_options);
1457 set_program_name(argv[0]);
1459 test_relops = parse_relops("== != < <= > >=");
1461 int option_index = 0;
1462 int c = getopt_long (argc, argv, short_options, long_options,
1470 test_relops = parse_relops(optarg);
1474 test_nvars = atoi(optarg);
1475 if (test_nvars < 0 || test_nvars > 4) {
1476 ovs_fatal(0, "number of numeric variables must be "
1482 test_svars = atoi(optarg);
1483 if (test_svars < 0 || test_svars > 4) {
1484 ovs_fatal(0, "number of string variables must be "
1490 test_bits = atoi(optarg);
1491 if (test_bits < 1 || test_bits > 3) {
1492 ovs_fatal(0, "number of bits must be between 1 and 3");
1497 if (!strcmp(optarg, "convert")) {
1498 operation = OP_CONVERT;
1499 } else if (!strcmp(optarg, "simplify")) {
1500 operation = OP_SIMPLIFY;
1501 } else if (!strcmp(optarg, "normalize")) {
1502 operation = OP_NORMALIZE;
1503 } else if (!strcmp(optarg, "flow")) {
1504 operation = OP_FLOW;
1506 ovs_fatal(0, "%s: unknown operation", optarg);
1511 test_parallel = atoi(optarg);
1528 free(short_options);
1530 static const struct ovs_cmdl_command commands[] = {
1532 {"lex", NULL, 0, 0, test_lex},
1535 {"parse-expr", NULL, 0, 0, test_parse_expr},
1536 {"annotate-expr", NULL, 0, 0, test_annotate_expr},
1537 {"simplify-expr", NULL, 0, 0, test_simplify_expr},
1538 {"normalize-expr", NULL, 0, 0, test_normalize_expr},
1539 {"expr-to-flows", NULL, 0, 0, test_expr_to_flows},
1540 {"evaluate-expr", NULL, 1, 1, test_evaluate_expr},
1541 {"composition", NULL, 1, 1, test_composition},
1542 {"tree-shape", NULL, 1, 1, test_tree_shape},
1543 {"exhaustive", NULL, 1, 1, test_exhaustive},
1546 {"parse-actions", NULL, 0, 0, test_parse_actions},
1548 {NULL, NULL, 0, 0, NULL},
1550 struct ovs_cmdl_context ctx;
1551 ctx.argc = argc - optind;
1552 ctx.argv = argv + optind;
1553 ovs_cmdl_run_command(&ctx, commands);
1556 OVSTEST_REGISTER("test-ovn", test_ovn_main);