FYI: this patch is rebased on top of (patch below) which is not yet merged into ovs.
commit ee61acf6202c6575033ea050b63271af49936da5 Author: Terry Wilson <twil...@redhat.com> Date: Fri Jul 22 21:57:20 2016 -0500 JSON serialization via Python's json lib There is no particularly good reason to use our own Python JSON serialization implementation when serialization can be done faster with Python's built-in JSON library. A few tests were changed due to Python's default JSON library returning slightly more precise floating point numbers. Signed-off-by: Terry Wilson <twil...@redhat.com> On Mon, Jul 25, 2016 at 3:04 PM, Aaron Rosen <aaronoro...@gmail.com> wrote: > This patch is done to enable in tree building of the ovn-utils python > wrapper. This is similar to what was done in: > ee89ea7b477bb4fd05137de03b2e8443807ed9f4 > > Signed-off-by: Aaron Rosen <aaronoro...@gmail.com> > --- > include/automake.mk | 1 + > include/ovn/actions.h | 141 ++++++++++++ > include/ovn/automake.mk | 5 + > include/ovn/expr.h | 474 > ++++++++++++++++++++++++++++++++++++++++ > include/ovn/lex.h | 139 ++++++++++++ > ovn/controller/lflow.c | 4 +- > ovn/controller/ofctrl.c | 2 +- > ovn/controller/ovn-controller.c | 2 +- > ovn/controller/pinctrl.c | 2 +- > ovn/lib/actions.c | 6 +- > ovn/lib/actions.h | 141 ------------ > ovn/lib/automake.mk | 3 - > ovn/lib/expr.c | 4 +- > ovn/lib/expr.h | 474 > ---------------------------------------- > ovn/lib/lex.c | 2 +- > ovn/lib/lex.h | 139 ------------ > ovn/northd/ovn-northd.c | 2 +- > tests/test-ovn.c | 6 +- > 18 files changed, 775 insertions(+), 772 deletions(-) > create mode 100644 include/ovn/actions.h > create mode 100644 include/ovn/automake.mk > create mode 100644 include/ovn/expr.h > create mode 100644 include/ovn/lex.h > delete mode 100644 ovn/lib/actions.h > delete mode 100644 ovn/lib/expr.h > delete mode 100644 ovn/lib/lex.h > > diff --git a/include/automake.mk b/include/automake.mk > index 6a4cf86..37903fd 100644 > --- a/include/automake.mk > +++ b/include/automake.mk > @@ -6,6 +6,7 @@ include/odp-netlink.h: > datapath/linux/compat/include/linux/openvswitch.h \ > EXTRA_DIST += build-aux/extract-odp-netlink-h > CLEANFILES += include/odp-netlink.h > > +include include/ovn/automake.mk > include include/openflow/automake.mk > include include/openvswitch/automake.mk > include include/sparse/automake.mk > diff --git a/include/ovn/actions.h b/include/ovn/actions.h > new file mode 100644 > index 0000000..114c71e > --- /dev/null > +++ b/include/ovn/actions.h > @@ -0,0 +1,141 @@ > +/* > + * Copyright (c) 2015, 2016 Nicira, Inc. > + * > + * Licensed under the Apache License, Version 2.0 (the "License"); > + * you may not use this file except in compliance with the License. > + * You may obtain a copy of the License at: > + * > + * http://www.apache.org/licenses/LICENSE-2.0 > + * > + * Unless required by applicable law or agreed to in writing, software > + * distributed under the License is distributed on an "AS IS" BASIS, > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or > implied. > + * See the License for the specific language governing permissions and > + * limitations under the License. > + */ > + > +#ifndef OVN_ACTIONS_H > +#define OVN_ACTIONS_H 1 > + > +#include <stdbool.h> > +#include <stdint.h> > +#include "compiler.h" > +#include "openvswitch/hmap.h" > +#include "openvswitch/dynamic-string.h" > +#include "util.h" > + > +struct expr; > +struct lexer; > +struct ofpbuf; > +struct shash; > +struct simap; > + > +#define MAX_OVN_GROUPS 65535 > + > +struct group_table { > + unsigned long *group_ids; /* Used as a bitmap with value set > + * for allocated group ids in either > + * desired_groups or existing_groups. */ > + struct hmap desired_groups; > + struct hmap existing_groups; > +}; > + > +struct group_info { > + struct hmap_node hmap_node; > + struct ds group; > + uint32_t group_id; > +}; > + > +enum action_opcode { > + /* "arp { ...actions... }". > + * > + * The actions, in OpenFlow 1.3 format, follow the action_header. > + */ > + ACTION_OPCODE_ARP, > + > + /* "put_arp(port, ip, mac)" > + * > + * Arguments are passed through the packet metadata and data, as > follows: > + * > + * MFF_REG0 = ip > + * MFF_LOG_INPORT = port > + * MFF_ETH_SRC = mac > + */ > + ACTION_OPCODE_PUT_ARP, > + > + /* "result = put_dhcp_opts(offer_ip, option, ...)". > + * > + * Arguments follow the action_header, in this format: > + * - A 32-bit or 64-bit OXM header designating the result field. > + * - A 32-bit integer specifying a bit offset within the result > field. > + * - The 32-bit DHCP offer IP. > + * - Any number of DHCP options. > + */ > + ACTION_OPCODE_PUT_DHCP_OPTS, > + > + /* "na { ...actions... }". > + * > + * The actions, in OpenFlow 1.3 format, follow the action_header. > + */ > + ACTION_OPCODE_NA, > +}; > + > +/* Header. */ > +struct action_header { > + ovs_be32 opcode; /* One of ACTION_OPCODE_* */ > + uint8_t pad[4]; > +}; > +BUILD_ASSERT_DECL(sizeof(struct action_header) == 8); > + > +struct action_params { > + /* A table of "struct expr_symbol"s to support (as one would provide > to > + * expr_parse()). */ > + const struct shash *symtab; > + > + /* hmap of 'struct dhcp_opts_map' to support 'put_dhcp_opts' action > */ > + const struct hmap *dhcp_opts; > + > + /* Looks up logical port 'port_name'. If found, stores its port > number in > + * '*portp' and returns true; otherwise, returns false. */ > + bool (*lookup_port)(const void *aux, const char *port_name, > + unsigned int *portp); > + const void *aux; > + > + /* A map from a port name to its connection tracking zone. */ > + const struct simap *ct_zones; > + > + /* A struct to figure out the group_id for group actions. */ > + struct group_table *group_table; > + > + /* OVN maps each logical flow table (ltable), one-to-one, onto a > physical > + * OpenFlow flow table (ptable). A number of parameters describe this > + * mapping and data related to flow tables: > + * > + * - 'first_ptable' and 'n_tables' define the range of OpenFlow > tables > + * to which the logical "next" action should be able to jump. > + * Logical table 0 maps to OpenFlow table 'first_ptable', > logical > + * table 1 to 'first_ptable + 1', and so on. If 'n_tables' is > 0 > + * then "next" is disallowed entirely. > + * > + * - 'cur_ltable' is an offset from 'first_ptable' (e.g. 0 <= > + * cur_ltable < n_ptables) of the logical flow that contains the > + * actions. If cur_ltable + 1 < n_tables, then this defines the > + * default table that "next" will jump to. > + * > + * - 'output_ptable' should be the OpenFlow table to which the > logical > + * "output" action will resubmit. */ > + uint8_t n_tables; /* Number of flow tables. */ > + uint8_t first_ptable; /* First OpenFlow table. */ > + uint8_t cur_ltable; /* 0 <= cur_ltable < n_tables. */ > + uint8_t output_ptable; /* OpenFlow table for 'output' to > resubmit. */ > + uint8_t arp_ptable; /* OpenFlow table for 'get_arp' to > resubmit. */ > +}; > + > +char *actions_parse(struct lexer *, const struct action_params *, > + struct ofpbuf *ofpacts, struct expr **prereqsp) > + OVS_WARN_UNUSED_RESULT; > +char *actions_parse_string(const char *s, const struct action_params *, > + struct ofpbuf *ofpacts, struct expr **prereqsp) > + OVS_WARN_UNUSED_RESULT; > + > +#endif /* ovn/actions.h */ > diff --git a/include/ovn/automake.mk b/include/ovn/automake.mk > new file mode 100644 > index 0000000..d2924c2 > --- /dev/null > +++ b/include/ovn/automake.mk > @@ -0,0 +1,5 @@ > +ovnincludedir = $(includedir)/ovn > +ovninclude_HEADERS = \ > + include/ovn/actions.h \ > + include/ovn/expr.h \ > + include/ovn/lex.h > diff --git a/include/ovn/expr.h b/include/ovn/expr.h > new file mode 100644 > index 0000000..d790c49 > --- /dev/null > +++ b/include/ovn/expr.h > @@ -0,0 +1,474 @@ > +/* > + * Copyright (c) 2015, 2016 Nicira, Inc. > + * > + * Licensed under the Apache License, Version 2.0 (the "License"); > + * you may not use this file except in compliance with the License. > + * You may obtain a copy of the License at: > + * > + * http://www.apache.org/licenses/LICENSE-2.0 > + * > + * Unless required by applicable law or agreed to in writing, software > + * distributed under the License is distributed on an "AS IS" BASIS, > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or > implied. > + * See the License for the specific language governing permissions and > + * limitations under the License. > + */ > + > +#ifndef OVN_EXPR_H > +#define OVN_EXPR_H 1 > + > +/* OVN matching expression tree > + * ============================ > + * > + * The data structures here form an abstract expression tree for matching > + * expressions in OVN. > + * > + * The abstract syntax tree representation of a matching expression is > one of: > + * > + * - A Boolean literal ("true" or "false"). > + * > + * - A comparison of a field (or part of a field) against a constant > + * with one of the operators == != < <= > >=. > + * > + * - The logical AND or OR of two or more matching expressions. > + * > + * Literals and comparisons are called "terminal" nodes, logical AND and > OR > + * nodes are "nonterminal" nodes. > + * > + * The syntax for expressions includes a few other concepts that are not > part > + * of the abstract syntax tree. In these examples, x is a field, a, b, > and c > + * are constants, and e1 and e2 are arbitrary expressions: > + * > + * - Logical NOT. The parser implements NOT by inverting the sense of > the > + * operand: !(x == a) becomes x != a, !(e1 && e2) becomes !e1 || > !e2, and > + * so on. > + * > + * - Set membership. The parser translates x == {a, b, c} into > + * x == a || x == b || x == c. > + * > + * - Reversed comparisons. The parser translates a < x into x > a. > + * > + * - Range expressions. The parser translates a < x < b into > + * x > a && x < b. > + */ > + > +#include "classifier.h" > +#include "lex.h" > +#include "openvswitch/hmap.h" > +#include "openvswitch/list.h" > +#include "openvswitch/match.h" > +#include "openvswitch/meta-flow.h" > + > +struct ds; > +struct ofpbuf; > +struct shash; > +struct simap; > + > +/* "Measurement level" of a field. See "Level of Measurement" in the > large > + * comment on struct expr_symbol below for more information. */ > +enum expr_level { > + EXPR_L_NOMINAL, > + > + /* Boolean values are nominal, however because of their simple nature > OVN > + * can allow both equality and inequality tests on them. */ > + EXPR_L_BOOLEAN, > + > + /* Ordinal values can at least be ordered on a scale. OVN allows > equality > + * and inequality and relational tests on ordinal values. These are > the > + * fields on which OVS allows bitwise matching. */ > + EXPR_L_ORDINAL > +}; > + > +const char *expr_level_to_string(enum expr_level); > + > +/* A symbol. > + * > + * > + * Name > + * ==== > + * > + * Every symbol must have a name. To be useful, the name must satisfy the > + * lexer's syntax for an identifier. > + * > + * > + * Width > + * ===== > + * > + * Every symbol has a width. For integer symbols, this is the number of > bits > + * in the value; for string symbols, this is 0. > + * > + * > + * Types > + * ===== > + * > + * There are three kinds of symbols: > + * > + * Fields: > + * > + * One might, for example, define a field named "vlan.tci" to refer to > + * MFF_VLAN_TCI. For integer fields, 'field' specifies the referent; > for > + * string fields, 'field' is NULL. > + * > + * 'expansion' is NULL. > + * > + * Integer fields can be nominal or ordinal (see below). String > fields are > + * always nominal. > + * > + * Subfields: > + * > + * 'expansion' is a string that specifies a subfield of some larger > field, > + * e.g. "vlan.tci[0..11]" for a field that represents a VLAN VID. > + * > + * 'field' is NULL. > + * > + * Only ordinal fields (see below) may have subfields, and subfields > are > + * always ordinal. > + * > + * Predicates: > + * > + * A predicate is an arbitrary Boolean expression that can be used in > an > + * expression much like a 1-bit field. 'expansion' specifies the > Boolean > + * expression, e.g. "ip4" might expand to "eth.type == 0x800". The > + * expansion of a predicate might refer to other predicates, e.g. > "icmp4" > + * might expand to "ip4 && ip4.proto == 1". > + * > + * 'field' is NULL. > + * > + * A predicate whose expansion refers to any nominal field or > predicate > + * (see below) is nominal; other predicates have Boolean level of > + * measurement. > + * > + * > + * Level of Measurement > + * ==================== > + * > + * See http://en.wikipedia.org/wiki/Level_of_measurement for the > statistical > + * concept on which this classification is based. There are three levels: > + * > + * Ordinal: > + * > + * In statistics, ordinal values can be ordered on a scale. Here, we > + * consider a field (or subfield) to be ordinal if its bits can be > examined > + * individually. This is true for the OpenFlow fields that OpenFlow > or > + * Open vSwitch makes "maskable". > + * > + * OVN supports all the usual arithmetic relations (== != < <= > >=) > on > + * ordinal fields and their subfields, because all of these can be > + * implemented as collections of bitwise tests. > + * > + * Nominal: > + * > + * In statistics, nominal values cannot be usefully compared except > for > + * equality. This is true of OpenFlow port numbers, Ethernet types, > and IP > + * protocols are examples: all of these are just identifiers assigned > + * arbitrarily with no deeper meaning. In OpenFlow and Open vSwitch, > bits > + * in these fields generally aren't individually addressable. > + * > + * OVN only supports arithmetic tests for equality on nominal fields, > + * because OpenFlow and Open vSwitch provide no way for a flow to > + * efficiently implement other comparisons on them. (A test for > inequality > + * can be sort of built out of two flows with different priorities, > but OVN > + * matching expressions always generate flows with a single priority.) > + * > + * String fields are always nominal. > + * > + * Boolean: > + * > + * A nominal field that has only two values, 0 and 1, is somewhat > + * exceptional, since it is easy to support both equality and > inequality > + * tests on such a field: either one can be implemented as a test for > 0 or > + * 1. > + * > + * Only predicates (see above) have a Boolean level of measurement. > + * > + * This isn't a standard level of measurement. > + * > + * > + * Prerequisites > + * ============= > + * > + * Any symbol can have prerequisites, which are specified as a string > giving an > + * additional expression that must be true whenever the symbol is > referenced. > + * For example, the "icmp4.type" symbol might have prerequisite "icmp4", > which > + * would cause an expression "icmp4.type == 0" to be interpreted as > "icmp4.type > + * == 0 && icmp4", which would in turn expand to "icmp4.type == 0 && > eth.type > + * == 0x800 && ip4.proto == 1" (assuming "icmp4" is a predicate defined as > + * suggested under "Types" above). > + * > + * > + * Crossproducting > + * =============== > + * > + * Ordinarily OVN is willing to consider using any field as a dimension > in the > + * Open vSwitch "conjunctive match" extension (see ovs-ofctl(8)). > However, > + * some fields can't actually be used that way because they are necessary > as > + * prerequisites. For example, from an expression like "tcp.src == > {1,2,3} > + * && tcp.dst == {4,5,6}", OVN might naturally generate flows like this: > + * > + * conj_id=1,actions=... > + * ip,actions=conjunction(1,1/3) > + * ip6,actions=conjunction(1,1/3) > + * tp_src=1,actions=conjunction(1,2/3) > + * tp_src=2,actions=conjunction(1,2/3) > + * tp_src=3,actions=conjunction(1,2/3) > + * tp_dst=4,actions=conjunction(1,3/3) > + * tp_dst=5,actions=conjunction(1,3/3) > + * tp_dst=6,actions=conjunction(1,3/3) > + * > + * but that's not valid because any flow that matches on tp_src or tp_dst > must > + * also match on either ip or ip6. Thus, one would mark eth.type as "must > + * crossproduct", to force generating flows like this: > + * > + * conj_id=1,actions=... > + * ip,tp_src=1,actions=conjunction(1,1/2) > + * ip,tp_src=2,actions=conjunction(1,1/2) > + * ip,tp_src=3,actions=conjunction(1,1/2) > + * ip6,tp_src=1,actions=conjunction(1,1/2) > + * ip6,tp_src=2,actions=conjunction(1,1/2) > + * ip6,tp_src=3,actions=conjunction(1,1/2) > + * ip,tp_dst=4,actions=conjunction(1,2/2) > + * ip,tp_dst=5,actions=conjunction(1,2/2) > + * ip,tp_dst=6,actions=conjunction(1,2/2) > + * ip6,tp_dst=4,actions=conjunction(1,2/2) > + * ip6,tp_dst=5,actions=conjunction(1,2/2) > + * ip6,tp_dst=6,actions=conjunction(1,2/2) > + * > + * which are acceptable. > + */ > +struct expr_symbol { > + char *name; > + int width; > + > + const struct mf_field *field; > + char *expansion; > + > + enum expr_level level; > + > + char *prereqs; > + bool must_crossproduct; > +}; > + > +/* A reference to a symbol or a subfield of a symbol. > + * > + * For string fields, ofs and n_bits are 0. */ > +struct expr_field { > + const struct expr_symbol *symbol; /* The symbol. */ > + int ofs; /* Starting bit offset. */ > + int n_bits; /* Number of bits. */ > +}; > + > +struct expr_symbol *expr_symtab_add_field(struct shash *symtab, > + const char *name, enum > mf_field_id, > + const char *prereqs, > + bool must_crossproduct); > +struct expr_symbol *expr_symtab_add_subfield(struct shash *symtab, > + const char *name, > + const char *prereqs, > + const char *subfield); > +struct expr_symbol *expr_symtab_add_string(struct shash *symtab, > + const char *name, enum > mf_field_id, > + const char *prereqs); > +struct expr_symbol *expr_symtab_add_predicate(struct shash *symtab, > + const char *name, > + const char *expansion); > +void expr_symtab_destroy(struct shash *symtab); > + > +/* Expression type. */ > +enum expr_type { > + EXPR_T_CMP, /* Compare symbol with constant. */ > + EXPR_T_AND, /* Logical AND of 2 or more > subexpressions. */ > + EXPR_T_OR, /* Logical OR of 2 or more > subexpressions. */ > + EXPR_T_BOOLEAN, /* True or false constant. */ > +}; > + > +/* Relational operator. */ > +enum expr_relop { > + EXPR_R_EQ, /* == */ > + EXPR_R_NE, /* != */ > + EXPR_R_LT, /* < */ > + EXPR_R_LE, /* <= */ > + EXPR_R_GT, /* > */ > + EXPR_R_GE, /* >= */ > +}; > +const char *expr_relop_to_string(enum expr_relop); > +bool expr_relop_from_token(enum lex_type type, enum expr_relop *relop); > + > +/* An abstract syntax tree for a matching expression. > + * > + * The expression code maintains and relies on a few important invariants: > + * > + * - An EXPR_T_AND or EXPR_T_OR node never has a child of the same > type. > + * (Any such children could be merged into their parent.) A node > may > + * have grandchildren of its own type. > + * > + * As a consequence, every nonterminal node at the same distance > from the > + * root has the same type. > + * > + * - EXPR_T_AND and EXPR_T_OR nodes must have at least two children. > + * > + * - An EXPR_T_CMP node always has a nonzero mask, and never has a > 1-bit > + * in its value in a position where the mask is a 0-bit. > + * > + * The expr_honors_invariants() function can check invariants. */ > +struct expr { > + struct ovs_list node; /* In parent EXPR_T_AND or EXPR_T_OR if > any. */ > + enum expr_type type; /* Expression type. */ > + > + union { > + /* EXPR_T_CMP. > + * > + * The symbol is on the left, e.g. "field < constant". */ > + struct { > + const struct expr_symbol *symbol; > + enum expr_relop relop; > + > + union { > + char *string; > + struct { > + union mf_subvalue value; > + union mf_subvalue mask; > + }; > + }; > + } cmp; > + > + /* EXPR_T_AND, EXPR_T_OR. */ > + struct ovs_list andor; > + > + /* EXPR_T_BOOLEAN. */ > + bool boolean; > + }; > +}; > + > +struct expr *expr_create_boolean(bool b); > +struct expr *expr_create_andor(enum expr_type); > +struct expr *expr_combine(enum expr_type, struct expr *a, struct expr *b); > + > +static inline struct expr * > +expr_from_node(const struct ovs_list *node) > +{ > + return CONTAINER_OF(node, struct expr, node); > +} > + > +void expr_format(const struct expr *, struct ds *); > +void expr_print(const struct expr *); > +struct expr *expr_parse(struct lexer *, const struct shash *symtab, > + const struct shash *macros, > + char **errorp); > +struct expr *expr_parse_string(const char *, const struct shash *symtab, > + const struct shash *macros, > + char **errorp); > + > +struct expr *expr_clone(struct expr *); > +void expr_destroy(struct expr *); > + > +struct expr *expr_annotate(struct expr *, const struct shash *symtab, > + char **errorp); > +struct expr *expr_simplify(struct expr *); > +struct expr *expr_normalize(struct expr *); > + > +bool expr_honors_invariants(const struct expr *); > +bool expr_is_simplified(const struct expr *); > +bool expr_is_normalized(const struct expr *); > + > +/* Converting expressions to OpenFlow flows. */ > + > +/* An OpenFlow match generated from a Boolean expression. See > + * expr_to_matches() for more information. */ > +struct expr_match { > + struct hmap_node hmap_node; > + struct match match; > + struct cls_conjunction *conjunctions; > + size_t n, allocated; > +}; > + > +uint32_t expr_to_matches(const struct expr *, > + bool (*lookup_port)(const void *aux, > + const char *port_name, > + unsigned int *portp), > + const void *aux, > + struct hmap *matches); > +void expr_matches_destroy(struct hmap *matches); > +void expr_matches_print(const struct hmap *matches, FILE *); > + > +/* Action parsing helper. */ > + > +char *expr_parse_assignment(struct lexer *lexer, struct expr_field *dst, > + const struct shash *symtab, > + bool (*lookup_port)(const void *aux, > + const char *port_name, > + unsigned int *portp), > + const void *aux, > + struct ofpbuf *ofpacts, struct expr > **prereqsp) > + OVS_WARN_UNUSED_RESULT; > +char *expr_parse_exchange(struct lexer *lexer, struct expr_field *dst, > + const struct shash *symtab, > + bool (*lookup_port)(const void *aux, > + const char *port_name, > + unsigned int *portp), > + const void *aux, > + struct ofpbuf *ofpacts, struct expr **prereqsp) > + OVS_WARN_UNUSED_RESULT; > +char *expr_parse_field(struct lexer *lexer, const struct shash *symtab, > + struct expr_field *field) > + OVS_WARN_UNUSED_RESULT; > +char *expr_expand_field(struct lexer *lexer, const struct shash *symtab, > + const struct expr_field *orig_field, > + int n_bits, bool rw, > + struct mf_subfield *sf, struct expr **prereqsp) > + OVS_WARN_UNUSED_RESULT; > + > +/* Type of a "union expr_constant" or "struct expr_constant_set". */ > +enum expr_constant_type { > + EXPR_C_INTEGER, > + EXPR_C_STRING > +}; > + > +/* A string or integer constant (one must know which from context). */ > +union expr_constant { > + /* Integer constant. > + * > + * The width of a constant isn't always clear, e.g. if you write "1", > + * there's no way to tell whether you mean for that to be a 1-bit > constant > + * or a 128-bit constant or somewhere in between. */ > + struct { > + union mf_subvalue value; > + union mf_subvalue mask; /* Only initialized if 'masked'. */ > + bool masked; > + > + enum lex_format format; /* From the constant's lex_token. */ > + }; > + > + /* Null-terminated string constant. */ > + char *string; > +}; > + > +/* A collection of "union expr_constant"s of the same type. */ > +struct expr_constant_set { > + union expr_constant *values; /* Constants. */ > + size_t n_values; /* Number of constants. */ > + enum expr_constant_type type; /* Type of the constants. */ > + bool in_curlies; /* Whether the constants were in {}. */ > +}; > + > +char *expr_parse_constant_set(struct lexer *, const struct shash *symtab, > + struct expr_constant_set *cs) > + OVS_WARN_UNUSED_RESULT; > +void expr_constant_set_destroy(struct expr_constant_set *cs); > + > + > +/* Address sets, aka "macros". > + * > + * Instead of referring to a set of value as: > + * {addr1, addr2, ..., addrN} > + * You can register a set of values and refer to them as: > + * $name > + * The macros should all have integer/masked-integer values. > + * The values that don't qualify are ignored. > + */ > + > +void expr_macros_add(struct shash *macros, const char *name, > + const char * const *values, size_t n_values); > +void expr_macros_remove(struct shash *macros, const char *name); > +void expr_macros_destroy(struct shash *macros); > + > +#endif /* ovn/expr.h */ > diff --git a/include/ovn/lex.h b/include/ovn/lex.h > new file mode 100644 > index 0000000..4de48c7 > --- /dev/null > +++ b/include/ovn/lex.h > @@ -0,0 +1,139 @@ > +/* > + * Copyright (c) 2015, 2016 Nicira, Inc. > + * > + * Licensed under the Apache License, Version 2.0 (the "License"); > + * you may not use this file except in compliance with the License. > + * You may obtain a copy of the License at: > + * > + * http://www.apache.org/licenses/LICENSE-2.0 > + * > + * Unless required by applicable law or agreed to in writing, software > + * distributed under the License is distributed on an "AS IS" BASIS, > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or > implied. > + * See the License for the specific language governing permissions and > + * limitations under the License. > + */ > + > +#ifndef OVN_LEX_H > +#define OVN_LEX_H 1 > + > +/* OVN lexical analyzer > + * ==================== > + * > + * This is a simple lexical analyzer (or tokenizer) for OVN match > expressions > + * and ACLs. */ > + > +#include "openvswitch/meta-flow.h" > + > +struct ds; > + > +/* Token type. */ > +enum lex_type { > + LEX_T_END, /* end of input */ > + > + /* Tokens with auxiliary data. */ > + LEX_T_ID, /* foo */ > + LEX_T_STRING, /* "foo" */ > + LEX_T_INTEGER, /* 12345 or 1.2.3.4 or ::1 or > 01:02:03:04:05 */ > + LEX_T_MASKED_INTEGER, /* 12345/10 or 1.2.0.0/16 or ::2/127 > or... */ > + LEX_T_MACRO, /* $NAME */ > + LEX_T_ERROR, /* invalid input */ > + > + /* Bare tokens. */ > + LEX_T_LPAREN, /* ( */ > + LEX_T_RPAREN, /* ) */ > + LEX_T_LCURLY, /* { */ > + LEX_T_RCURLY, /* } */ > + LEX_T_LSQUARE, /* [ */ > + LEX_T_RSQUARE, /* ] */ > + LEX_T_EQ, /* == */ > + LEX_T_NE, /* != */ > + LEX_T_LT, /* < */ > + LEX_T_LE, /* <= */ > + LEX_T_GT, /* > */ > + LEX_T_GE, /* >= */ > + LEX_T_LOG_NOT, /* ! */ > + LEX_T_LOG_AND, /* && */ > + LEX_T_LOG_OR, /* || */ > + LEX_T_ELLIPSIS, /* .. */ > + LEX_T_COMMA, /* , */ > + LEX_T_SEMICOLON, /* ; */ > + LEX_T_EQUALS, /* = */ > + LEX_T_EXCHANGE, /* <-> */ > + LEX_T_DECREMENT, /* -- */ > + LEX_T_COLON, /* : */ > +}; > + > +/* Subtype for LEX_T_INTEGER and LEX_T_MASKED_INTEGER tokens. > + * > + * These do not change the semantics of a token; instead, they determine > the > + * format used when a token is serialized back to a text form. That's > + * important because 3232268289 is meaningless to a human whereas > 192.168.128.1 > + * has some actual significance. */ > +enum lex_format { > + LEX_F_DECIMAL, > + LEX_F_HEXADECIMAL, > + LEX_F_IPV4, > + LEX_F_IPV6, > + LEX_F_ETHERNET, > +}; > +const char *lex_format_to_string(enum lex_format); > + > +/* A token. */ > +struct lex_token { > + /* One of LEX_*. */ > + enum lex_type type; > + > + /* Meaningful for LEX_T_ID, LEX_T_STRING, LEX_T_ERROR, LEX_T_MACRO > only. > + * For these token types, 's' may point to 'buffer'; otherwise, it > points > + * to malloc()ed memory owned by the token. > + * > + * Must be NULL for other token types. > + * > + * For LEX_T_MACRO, 's' does not include the leading $. */ > + char *s; > + > + /* LEX_T_INTEGER, LEX_T_MASKED_INTEGER only. */ > + enum lex_format format; > + > + union { > + /* LEX_T_INTEGER, LEX_T_MASKED_INTEGER only. */ > + struct { > + union mf_subvalue value; /* LEX_T_INTEGER, > LEX_T_MASKED_INTEGER. */ > + union mf_subvalue mask; /* LEX_T_MASKED_INTEGER only. */ > + }; > + > + /* LEX_T_ID, LEX_T_STRING, LEX_T_ERROR, LEX_T_MACRO only. */ > + char buffer[256]; > + }; > +}; > + > +void lex_token_init(struct lex_token *); > +void lex_token_destroy(struct lex_token *); > +void lex_token_swap(struct lex_token *, struct lex_token *); > +void lex_token_strcpy(struct lex_token *, const char *s, size_t length); > +void lex_token_strset(struct lex_token *, char *s); > +void lex_token_vsprintf(struct lex_token *, const char *format, va_list > args); > + > +void lex_token_format(const struct lex_token *, struct ds *); > +const char *lex_token_parse(struct lex_token *, const char *input, > + const char **startp); > + > +/* A lexical analyzer. */ > +struct lexer { > + const char *input; /* Remaining input (not owned by lexer). > */ > + const char *start; /* Start of current token in 'input'. */ > + struct lex_token token; /* Current token (owned by lexer). */ > +}; > + > +void lexer_init(struct lexer *, const char *input); > +void lexer_destroy(struct lexer *); > + > +enum lex_type lexer_get(struct lexer *); > +enum lex_type lexer_lookahead(const struct lexer *); > +bool lexer_match(struct lexer *, enum lex_type); > +bool lexer_match_id(struct lexer *, const char *id); > +bool lexer_is_int(const struct lexer *); > +bool lexer_get_int(struct lexer *, int *value); > + > +#endif /* ovn/lex.h */ > diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c > index 42c9055..a4f3322 100644 > --- a/ovn/controller/lflow.c > +++ b/ovn/controller/lflow.c > @@ -22,8 +22,8 @@ > #include "openvswitch/ofpbuf.h" > #include "openvswitch/vlog.h" > #include "ovn-controller.h" > -#include "ovn/lib/actions.h" > -#include "ovn/lib/expr.h" > +#include "ovn/actions.h" > +#include "ovn/expr.h" > #include "ovn/lib/ovn-dhcp.h" > #include "ovn/lib/ovn-sb-idl.h" > #include "packets.h" > diff --git a/ovn/controller/ofctrl.c b/ovn/controller/ofctrl.c > index f0451b7..6274888 100644 > --- a/ovn/controller/ofctrl.c > +++ b/ovn/controller/ofctrl.c > @@ -34,7 +34,7 @@ > #include "openvswitch/ofpbuf.h" > #include "openvswitch/vlog.h" > #include "ovn-controller.h" > -#include "ovn/lib/actions.h" > +#include "ovn/actions.h" > #include "poll-loop.h" > #include "physical.h" > #include "rconn.h" > diff --git a/ovn/controller/ovn-controller.c > b/ovn/controller/ovn-controller.c > index 4d9490a..95d3ff3 100644 > --- a/ovn/controller/ovn-controller.c > +++ b/ovn/controller/ovn-controller.c > @@ -39,7 +39,7 @@ > #include "ofctrl.h" > #include "openvswitch/vconn.h" > #include "openvswitch/vlog.h" > -#include "ovn/lib/actions.h" > +#include "ovn/actions.h" > #include "ovn/lib/ovn-sb-idl.h" > #include "ovn/lib/ovn-util.h" > #include "patch.h" > diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c > index 0ae6501..416dad6 100644 > --- a/ovn/controller/pinctrl.c > +++ b/ovn/controller/pinctrl.c > @@ -35,7 +35,7 @@ > > #include "lib/dhcp.h" > #include "ovn-controller.h" > -#include "ovn/lib/actions.h" > +#include "ovn/actions.h" > #include "ovn/lib/logical-fields.h" > #include "ovn/lib/ovn-util.h" > #include "poll-loop.h" > diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c > index 6e2bf93..fd5a867 100644 > --- a/ovn/lib/actions.c > +++ b/ovn/lib/actions.c > @@ -17,20 +17,20 @@ > #include <config.h> > #include <stdarg.h> > #include <stdbool.h> > -#include "actions.h" > #include "bitmap.h" > #include "byte-order.h" > #include "compiler.h" > #include "ovn-dhcp.h" > -#include "expr.h" > #include "hash.h" > #include "openvswitch/hmap.h" > -#include "lex.h" > #include "logical-fields.h" > #include "nx-match.h" > #include "openvswitch/dynamic-string.h" > #include "openvswitch/ofp-actions.h" > #include "openvswitch/ofpbuf.h" > +#include "ovn/actions.h" > +#include "ovn/expr.h" > +#include "ovn/lex.h" > #include "packets.h" > #include "openvswitch/shash.h" > #include "simap.h" > diff --git a/ovn/lib/actions.h b/ovn/lib/actions.h > deleted file mode 100644 > index 114c71e..0000000 > --- a/ovn/lib/actions.h > +++ /dev/null > @@ -1,141 +0,0 @@ > -/* > - * Copyright (c) 2015, 2016 Nicira, Inc. > - * > - * Licensed under the Apache License, Version 2.0 (the "License"); > - * you may not use this file except in compliance with the License. > - * You may obtain a copy of the License at: > - * > - * http://www.apache.org/licenses/LICENSE-2.0 > - * > - * Unless required by applicable law or agreed to in writing, software > - * distributed under the License is distributed on an "AS IS" BASIS, > - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or > implied. > - * See the License for the specific language governing permissions and > - * limitations under the License. > - */ > - > -#ifndef OVN_ACTIONS_H > -#define OVN_ACTIONS_H 1 > - > -#include <stdbool.h> > -#include <stdint.h> > -#include "compiler.h" > -#include "openvswitch/hmap.h" > -#include "openvswitch/dynamic-string.h" > -#include "util.h" > - > -struct expr; > -struct lexer; > -struct ofpbuf; > -struct shash; > -struct simap; > - > -#define MAX_OVN_GROUPS 65535 > - > -struct group_table { > - unsigned long *group_ids; /* Used as a bitmap with value set > - * for allocated group ids in either > - * desired_groups or existing_groups. */ > - struct hmap desired_groups; > - struct hmap existing_groups; > -}; > - > -struct group_info { > - struct hmap_node hmap_node; > - struct ds group; > - uint32_t group_id; > -}; > - > -enum action_opcode { > - /* "arp { ...actions... }". > - * > - * The actions, in OpenFlow 1.3 format, follow the action_header. > - */ > - ACTION_OPCODE_ARP, > - > - /* "put_arp(port, ip, mac)" > - * > - * Arguments are passed through the packet metadata and data, as > follows: > - * > - * MFF_REG0 = ip > - * MFF_LOG_INPORT = port > - * MFF_ETH_SRC = mac > - */ > - ACTION_OPCODE_PUT_ARP, > - > - /* "result = put_dhcp_opts(offer_ip, option, ...)". > - * > - * Arguments follow the action_header, in this format: > - * - A 32-bit or 64-bit OXM header designating the result field. > - * - A 32-bit integer specifying a bit offset within the result > field. > - * - The 32-bit DHCP offer IP. > - * - Any number of DHCP options. > - */ > - ACTION_OPCODE_PUT_DHCP_OPTS, > - > - /* "na { ...actions... }". > - * > - * The actions, in OpenFlow 1.3 format, follow the action_header. > - */ > - ACTION_OPCODE_NA, > -}; > - > -/* Header. */ > -struct action_header { > - ovs_be32 opcode; /* One of ACTION_OPCODE_* */ > - uint8_t pad[4]; > -}; > -BUILD_ASSERT_DECL(sizeof(struct action_header) == 8); > - > -struct action_params { > - /* A table of "struct expr_symbol"s to support (as one would provide > to > - * expr_parse()). */ > - const struct shash *symtab; > - > - /* hmap of 'struct dhcp_opts_map' to support 'put_dhcp_opts' action > */ > - const struct hmap *dhcp_opts; > - > - /* Looks up logical port 'port_name'. If found, stores its port > number in > - * '*portp' and returns true; otherwise, returns false. */ > - bool (*lookup_port)(const void *aux, const char *port_name, > - unsigned int *portp); > - const void *aux; > - > - /* A map from a port name to its connection tracking zone. */ > - const struct simap *ct_zones; > - > - /* A struct to figure out the group_id for group actions. */ > - struct group_table *group_table; > - > - /* OVN maps each logical flow table (ltable), one-to-one, onto a > physical > - * OpenFlow flow table (ptable). A number of parameters describe this > - * mapping and data related to flow tables: > - * > - * - 'first_ptable' and 'n_tables' define the range of OpenFlow > tables > - * to which the logical "next" action should be able to jump. > - * Logical table 0 maps to OpenFlow table 'first_ptable', > logical > - * table 1 to 'first_ptable + 1', and so on. If 'n_tables' is > 0 > - * then "next" is disallowed entirely. > - * > - * - 'cur_ltable' is an offset from 'first_ptable' (e.g. 0 <= > - * cur_ltable < n_ptables) of the logical flow that contains the > - * actions. If cur_ltable + 1 < n_tables, then this defines the > - * default table that "next" will jump to. > - * > - * - 'output_ptable' should be the OpenFlow table to which the > logical > - * "output" action will resubmit. */ > - uint8_t n_tables; /* Number of flow tables. */ > - uint8_t first_ptable; /* First OpenFlow table. */ > - uint8_t cur_ltable; /* 0 <= cur_ltable < n_tables. */ > - uint8_t output_ptable; /* OpenFlow table for 'output' to > resubmit. */ > - uint8_t arp_ptable; /* OpenFlow table for 'get_arp' to > resubmit. */ > -}; > - > -char *actions_parse(struct lexer *, const struct action_params *, > - struct ofpbuf *ofpacts, struct expr **prereqsp) > - OVS_WARN_UNUSED_RESULT; > -char *actions_parse_string(const char *s, const struct action_params *, > - struct ofpbuf *ofpacts, struct expr **prereqsp) > - OVS_WARN_UNUSED_RESULT; > - > -#endif /* ovn/actions.h */ > diff --git a/ovn/lib/automake.mk b/ovn/lib/automake.mk > index 4f8cd05..4e9daf5 100644 > --- a/ovn/lib/automake.mk > +++ b/ovn/lib/automake.mk > @@ -5,11 +5,8 @@ ovn_lib_libovn_la_LDFLAGS = \ > $(AM_LDFLAGS) > ovn_lib_libovn_la_SOURCES = \ > ovn/lib/actions.c \ > - ovn/lib/actions.h \ > ovn/lib/expr.c \ > - ovn/lib/expr.h \ > ovn/lib/lex.c \ > - ovn/lib/lex.h \ > ovn/lib/ovn-dhcp.h \ > ovn/lib/ovn-util.c \ > ovn/lib/ovn-util.h \ > diff --git a/ovn/lib/expr.c b/ovn/lib/expr.c > index 1c38b99..288aae2 100644 > --- a/ovn/lib/expr.c > +++ b/ovn/lib/expr.c > @@ -16,15 +16,15 @@ > > #include <config.h> > #include "byte-order.h" > -#include "expr.h" > #include "openvswitch/json.h" > -#include "lex.h" > #include "logical-fields.h" > #include "openvswitch/dynamic-string.h" > #include "openvswitch/match.h" > #include "openvswitch/ofp-actions.h" > #include "openvswitch/vlog.h" > #include "openvswitch/shash.h" > +#include "ovn/expr.h" > +#include "ovn/lex.h" > #include "simap.h" > #include "sset.h" > #include "util.h" > diff --git a/ovn/lib/expr.h b/ovn/lib/expr.h > deleted file mode 100644 > index d790c49..0000000 > --- a/ovn/lib/expr.h > +++ /dev/null > @@ -1,474 +0,0 @@ > -/* > - * Copyright (c) 2015, 2016 Nicira, Inc. > - * > - * Licensed under the Apache License, Version 2.0 (the "License"); > - * you may not use this file except in compliance with the License. > - * You may obtain a copy of the License at: > - * > - * http://www.apache.org/licenses/LICENSE-2.0 > - * > - * Unless required by applicable law or agreed to in writing, software > - * distributed under the License is distributed on an "AS IS" BASIS, > - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or > implied. > - * See the License for the specific language governing permissions and > - * limitations under the License. > - */ > - > -#ifndef OVN_EXPR_H > -#define OVN_EXPR_H 1 > - > -/* OVN matching expression tree > - * ============================ > - * > - * The data structures here form an abstract expression tree for matching > - * expressions in OVN. > - * > - * The abstract syntax tree representation of a matching expression is > one of: > - * > - * - A Boolean literal ("true" or "false"). > - * > - * - A comparison of a field (or part of a field) against a constant > - * with one of the operators == != < <= > >=. > - * > - * - The logical AND or OR of two or more matching expressions. > - * > - * Literals and comparisons are called "terminal" nodes, logical AND and > OR > - * nodes are "nonterminal" nodes. > - * > - * The syntax for expressions includes a few other concepts that are not > part > - * of the abstract syntax tree. In these examples, x is a field, a, b, > and c > - * are constants, and e1 and e2 are arbitrary expressions: > - * > - * - Logical NOT. The parser implements NOT by inverting the sense of > the > - * operand: !(x == a) becomes x != a, !(e1 && e2) becomes !e1 || > !e2, and > - * so on. > - * > - * - Set membership. The parser translates x == {a, b, c} into > - * x == a || x == b || x == c. > - * > - * - Reversed comparisons. The parser translates a < x into x > a. > - * > - * - Range expressions. The parser translates a < x < b into > - * x > a && x < b. > - */ > - > -#include "classifier.h" > -#include "lex.h" > -#include "openvswitch/hmap.h" > -#include "openvswitch/list.h" > -#include "openvswitch/match.h" > -#include "openvswitch/meta-flow.h" > - > -struct ds; > -struct ofpbuf; > -struct shash; > -struct simap; > - > -/* "Measurement level" of a field. See "Level of Measurement" in the > large > - * comment on struct expr_symbol below for more information. */ > -enum expr_level { > - EXPR_L_NOMINAL, > - > - /* Boolean values are nominal, however because of their simple nature > OVN > - * can allow both equality and inequality tests on them. */ > - EXPR_L_BOOLEAN, > - > - /* Ordinal values can at least be ordered on a scale. OVN allows > equality > - * and inequality and relational tests on ordinal values. These are > the > - * fields on which OVS allows bitwise matching. */ > - EXPR_L_ORDINAL > -}; > - > -const char *expr_level_to_string(enum expr_level); > - > -/* A symbol. > - * > - * > - * Name > - * ==== > - * > - * Every symbol must have a name. To be useful, the name must satisfy the > - * lexer's syntax for an identifier. > - * > - * > - * Width > - * ===== > - * > - * Every symbol has a width. For integer symbols, this is the number of > bits > - * in the value; for string symbols, this is 0. > - * > - * > - * Types > - * ===== > - * > - * There are three kinds of symbols: > - * > - * Fields: > - * > - * One might, for example, define a field named "vlan.tci" to refer to > - * MFF_VLAN_TCI. For integer fields, 'field' specifies the referent; > for > - * string fields, 'field' is NULL. > - * > - * 'expansion' is NULL. > - * > - * Integer fields can be nominal or ordinal (see below). String > fields are > - * always nominal. > - * > - * Subfields: > - * > - * 'expansion' is a string that specifies a subfield of some larger > field, > - * e.g. "vlan.tci[0..11]" for a field that represents a VLAN VID. > - * > - * 'field' is NULL. > - * > - * Only ordinal fields (see below) may have subfields, and subfields > are > - * always ordinal. > - * > - * Predicates: > - * > - * A predicate is an arbitrary Boolean expression that can be used in > an > - * expression much like a 1-bit field. 'expansion' specifies the > Boolean > - * expression, e.g. "ip4" might expand to "eth.type == 0x800". The > - * expansion of a predicate might refer to other predicates, e.g. > "icmp4" > - * might expand to "ip4 && ip4.proto == 1". > - * > - * 'field' is NULL. > - * > - * A predicate whose expansion refers to any nominal field or > predicate > - * (see below) is nominal; other predicates have Boolean level of > - * measurement. > - * > - * > - * Level of Measurement > - * ==================== > - * > - * See http://en.wikipedia.org/wiki/Level_of_measurement for the > statistical > - * concept on which this classification is based. There are three levels: > - * > - * Ordinal: > - * > - * In statistics, ordinal values can be ordered on a scale. Here, we > - * consider a field (or subfield) to be ordinal if its bits can be > examined > - * individually. This is true for the OpenFlow fields that OpenFlow > or > - * Open vSwitch makes "maskable". > - * > - * OVN supports all the usual arithmetic relations (== != < <= > >=) > on > - * ordinal fields and their subfields, because all of these can be > - * implemented as collections of bitwise tests. > - * > - * Nominal: > - * > - * In statistics, nominal values cannot be usefully compared except > for > - * equality. This is true of OpenFlow port numbers, Ethernet types, > and IP > - * protocols are examples: all of these are just identifiers assigned > - * arbitrarily with no deeper meaning. In OpenFlow and Open vSwitch, > bits > - * in these fields generally aren't individually addressable. > - * > - * OVN only supports arithmetic tests for equality on nominal fields, > - * because OpenFlow and Open vSwitch provide no way for a flow to > - * efficiently implement other comparisons on them. (A test for > inequality > - * can be sort of built out of two flows with different priorities, > but OVN > - * matching expressions always generate flows with a single priority.) > - * > - * String fields are always nominal. > - * > - * Boolean: > - * > - * A nominal field that has only two values, 0 and 1, is somewhat > - * exceptional, since it is easy to support both equality and > inequality > - * tests on such a field: either one can be implemented as a test for > 0 or > - * 1. > - * > - * Only predicates (see above) have a Boolean level of measurement. > - * > - * This isn't a standard level of measurement. > - * > - * > - * Prerequisites > - * ============= > - * > - * Any symbol can have prerequisites, which are specified as a string > giving an > - * additional expression that must be true whenever the symbol is > referenced. > - * For example, the "icmp4.type" symbol might have prerequisite "icmp4", > which > - * would cause an expression "icmp4.type == 0" to be interpreted as > "icmp4.type > - * == 0 && icmp4", which would in turn expand to "icmp4.type == 0 && > eth.type > - * == 0x800 && ip4.proto == 1" (assuming "icmp4" is a predicate defined as > - * suggested under "Types" above). > - * > - * > - * Crossproducting > - * =============== > - * > - * Ordinarily OVN is willing to consider using any field as a dimension > in the > - * Open vSwitch "conjunctive match" extension (see ovs-ofctl(8)). > However, > - * some fields can't actually be used that way because they are necessary > as > - * prerequisites. For example, from an expression like "tcp.src == > {1,2,3} > - * && tcp.dst == {4,5,6}", OVN might naturally generate flows like this: > - * > - * conj_id=1,actions=... > - * ip,actions=conjunction(1,1/3) > - * ip6,actions=conjunction(1,1/3) > - * tp_src=1,actions=conjunction(1,2/3) > - * tp_src=2,actions=conjunction(1,2/3) > - * tp_src=3,actions=conjunction(1,2/3) > - * tp_dst=4,actions=conjunction(1,3/3) > - * tp_dst=5,actions=conjunction(1,3/3) > - * tp_dst=6,actions=conjunction(1,3/3) > - * > - * but that's not valid because any flow that matches on tp_src or tp_dst > must > - * also match on either ip or ip6. Thus, one would mark eth.type as "must > - * crossproduct", to force generating flows like this: > - * > - * conj_id=1,actions=... > - * ip,tp_src=1,actions=conjunction(1,1/2) > - * ip,tp_src=2,actions=conjunction(1,1/2) > - * ip,tp_src=3,actions=conjunction(1,1/2) > - * ip6,tp_src=1,actions=conjunction(1,1/2) > - * ip6,tp_src=2,actions=conjunction(1,1/2) > - * ip6,tp_src=3,actions=conjunction(1,1/2) > - * ip,tp_dst=4,actions=conjunction(1,2/2) > - * ip,tp_dst=5,actions=conjunction(1,2/2) > - * ip,tp_dst=6,actions=conjunction(1,2/2) > - * ip6,tp_dst=4,actions=conjunction(1,2/2) > - * ip6,tp_dst=5,actions=conjunction(1,2/2) > - * ip6,tp_dst=6,actions=conjunction(1,2/2) > - * > - * which are acceptable. > - */ > -struct expr_symbol { > - char *name; > - int width; > - > - const struct mf_field *field; > - char *expansion; > - > - enum expr_level level; > - > - char *prereqs; > - bool must_crossproduct; > -}; > - > -/* A reference to a symbol or a subfield of a symbol. > - * > - * For string fields, ofs and n_bits are 0. */ > -struct expr_field { > - const struct expr_symbol *symbol; /* The symbol. */ > - int ofs; /* Starting bit offset. */ > - int n_bits; /* Number of bits. */ > -}; > - > -struct expr_symbol *expr_symtab_add_field(struct shash *symtab, > - const char *name, enum > mf_field_id, > - const char *prereqs, > - bool must_crossproduct); > -struct expr_symbol *expr_symtab_add_subfield(struct shash *symtab, > - const char *name, > - const char *prereqs, > - const char *subfield); > -struct expr_symbol *expr_symtab_add_string(struct shash *symtab, > - const char *name, enum > mf_field_id, > - const char *prereqs); > -struct expr_symbol *expr_symtab_add_predicate(struct shash *symtab, > - const char *name, > - const char *expansion); > -void expr_symtab_destroy(struct shash *symtab); > - > -/* Expression type. */ > -enum expr_type { > - EXPR_T_CMP, /* Compare symbol with constant. */ > - EXPR_T_AND, /* Logical AND of 2 or more > subexpressions. */ > - EXPR_T_OR, /* Logical OR of 2 or more > subexpressions. */ > - EXPR_T_BOOLEAN, /* True or false constant. */ > -}; > - > -/* Relational operator. */ > -enum expr_relop { > - EXPR_R_EQ, /* == */ > - EXPR_R_NE, /* != */ > - EXPR_R_LT, /* < */ > - EXPR_R_LE, /* <= */ > - EXPR_R_GT, /* > */ > - EXPR_R_GE, /* >= */ > -}; > -const char *expr_relop_to_string(enum expr_relop); > -bool expr_relop_from_token(enum lex_type type, enum expr_relop *relop); > - > -/* An abstract syntax tree for a matching expression. > - * > - * The expression code maintains and relies on a few important invariants: > - * > - * - An EXPR_T_AND or EXPR_T_OR node never has a child of the same > type. > - * (Any such children could be merged into their parent.) A node > may > - * have grandchildren of its own type. > - * > - * As a consequence, every nonterminal node at the same distance > from the > - * root has the same type. > - * > - * - EXPR_T_AND and EXPR_T_OR nodes must have at least two children. > - * > - * - An EXPR_T_CMP node always has a nonzero mask, and never has a > 1-bit > - * in its value in a position where the mask is a 0-bit. > - * > - * The expr_honors_invariants() function can check invariants. */ > -struct expr { > - struct ovs_list node; /* In parent EXPR_T_AND or EXPR_T_OR if > any. */ > - enum expr_type type; /* Expression type. */ > - > - union { > - /* EXPR_T_CMP. > - * > - * The symbol is on the left, e.g. "field < constant". */ > - struct { > - const struct expr_symbol *symbol; > - enum expr_relop relop; > - > - union { > - char *string; > - struct { > - union mf_subvalue value; > - union mf_subvalue mask; > - }; > - }; > - } cmp; > - > - /* EXPR_T_AND, EXPR_T_OR. */ > - struct ovs_list andor; > - > - /* EXPR_T_BOOLEAN. */ > - bool boolean; > - }; > -}; > - > -struct expr *expr_create_boolean(bool b); > -struct expr *expr_create_andor(enum expr_type); > -struct expr *expr_combine(enum expr_type, struct expr *a, struct expr *b); > - > -static inline struct expr * > -expr_from_node(const struct ovs_list *node) > -{ > - return CONTAINER_OF(node, struct expr, node); > -} > - > -void expr_format(const struct expr *, struct ds *); > -void expr_print(const struct expr *); > -struct expr *expr_parse(struct lexer *, const struct shash *symtab, > - const struct shash *macros, > - char **errorp); > -struct expr *expr_parse_string(const char *, const struct shash *symtab, > - const struct shash *macros, > - char **errorp); > - > -struct expr *expr_clone(struct expr *); > -void expr_destroy(struct expr *); > - > -struct expr *expr_annotate(struct expr *, const struct shash *symtab, > - char **errorp); > -struct expr *expr_simplify(struct expr *); > -struct expr *expr_normalize(struct expr *); > - > -bool expr_honors_invariants(const struct expr *); > -bool expr_is_simplified(const struct expr *); > -bool expr_is_normalized(const struct expr *); > - > -/* Converting expressions to OpenFlow flows. */ > - > -/* An OpenFlow match generated from a Boolean expression. See > - * expr_to_matches() for more information. */ > -struct expr_match { > - struct hmap_node hmap_node; > - struct match match; > - struct cls_conjunction *conjunctions; > - size_t n, allocated; > -}; > - > -uint32_t expr_to_matches(const struct expr *, > - bool (*lookup_port)(const void *aux, > - const char *port_name, > - unsigned int *portp), > - const void *aux, > - struct hmap *matches); > -void expr_matches_destroy(struct hmap *matches); > -void expr_matches_print(const struct hmap *matches, FILE *); > - > -/* Action parsing helper. */ > - > -char *expr_parse_assignment(struct lexer *lexer, struct expr_field *dst, > - const struct shash *symtab, > - bool (*lookup_port)(const void *aux, > - const char *port_name, > - unsigned int *portp), > - const void *aux, > - struct ofpbuf *ofpacts, struct expr > **prereqsp) > - OVS_WARN_UNUSED_RESULT; > -char *expr_parse_exchange(struct lexer *lexer, struct expr_field *dst, > - const struct shash *symtab, > - bool (*lookup_port)(const void *aux, > - const char *port_name, > - unsigned int *portp), > - const void *aux, > - struct ofpbuf *ofpacts, struct expr **prereqsp) > - OVS_WARN_UNUSED_RESULT; > -char *expr_parse_field(struct lexer *lexer, const struct shash *symtab, > - struct expr_field *field) > - OVS_WARN_UNUSED_RESULT; > -char *expr_expand_field(struct lexer *lexer, const struct shash *symtab, > - const struct expr_field *orig_field, > - int n_bits, bool rw, > - struct mf_subfield *sf, struct expr **prereqsp) > - OVS_WARN_UNUSED_RESULT; > - > -/* Type of a "union expr_constant" or "struct expr_constant_set". */ > -enum expr_constant_type { > - EXPR_C_INTEGER, > - EXPR_C_STRING > -}; > - > -/* A string or integer constant (one must know which from context). */ > -union expr_constant { > - /* Integer constant. > - * > - * The width of a constant isn't always clear, e.g. if you write "1", > - * there's no way to tell whether you mean for that to be a 1-bit > constant > - * or a 128-bit constant or somewhere in between. */ > - struct { > - union mf_subvalue value; > - union mf_subvalue mask; /* Only initialized if 'masked'. */ > - bool masked; > - > - enum lex_format format; /* From the constant's lex_token. */ > - }; > - > - /* Null-terminated string constant. */ > - char *string; > -}; > - > -/* A collection of "union expr_constant"s of the same type. */ > -struct expr_constant_set { > - union expr_constant *values; /* Constants. */ > - size_t n_values; /* Number of constants. */ > - enum expr_constant_type type; /* Type of the constants. */ > - bool in_curlies; /* Whether the constants were in {}. */ > -}; > - > -char *expr_parse_constant_set(struct lexer *, const struct shash *symtab, > - struct expr_constant_set *cs) > - OVS_WARN_UNUSED_RESULT; > -void expr_constant_set_destroy(struct expr_constant_set *cs); > - > - > -/* Address sets, aka "macros". > - * > - * Instead of referring to a set of value as: > - * {addr1, addr2, ..., addrN} > - * You can register a set of values and refer to them as: > - * $name > - * The macros should all have integer/masked-integer values. > - * The values that don't qualify are ignored. > - */ > - > -void expr_macros_add(struct shash *macros, const char *name, > - const char * const *values, size_t n_values); > -void expr_macros_remove(struct shash *macros, const char *name); > -void expr_macros_destroy(struct shash *macros); > - > -#endif /* ovn/expr.h */ > diff --git a/ovn/lib/lex.c b/ovn/lib/lex.c > index 79aa221..95edeaf 100644 > --- a/ovn/lib/lex.c > +++ b/ovn/lib/lex.c > @@ -15,12 +15,12 @@ > */ > > #include <config.h> > -#include "lex.h" > #include <ctype.h> > #include <errno.h> > #include <stdarg.h> > #include "openvswitch/dynamic-string.h" > #include "openvswitch/json.h" > +#include "ovn/lex.h" > #include "packets.h" > #include "util.h" > > diff --git a/ovn/lib/lex.h b/ovn/lib/lex.h > deleted file mode 100644 > index 4de48c7..0000000 > --- a/ovn/lib/lex.h > +++ /dev/null > @@ -1,139 +0,0 @@ > -/* > - * Copyright (c) 2015, 2016 Nicira, Inc. > - * > - * Licensed under the Apache License, Version 2.0 (the "License"); > - * you may not use this file except in compliance with the License. > - * You may obtain a copy of the License at: > - * > - * http://www.apache.org/licenses/LICENSE-2.0 > - * > - * Unless required by applicable law or agreed to in writing, software > - * distributed under the License is distributed on an "AS IS" BASIS, > - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or > implied. > - * See the License for the specific language governing permissions and > - * limitations under the License. > - */ > - > -#ifndef OVN_LEX_H > -#define OVN_LEX_H 1 > - > -/* OVN lexical analyzer > - * ==================== > - * > - * This is a simple lexical analyzer (or tokenizer) for OVN match > expressions > - * and ACLs. */ > - > -#include "openvswitch/meta-flow.h" > - > -struct ds; > - > -/* Token type. */ > -enum lex_type { > - LEX_T_END, /* end of input */ > - > - /* Tokens with auxiliary data. */ > - LEX_T_ID, /* foo */ > - LEX_T_STRING, /* "foo" */ > - LEX_T_INTEGER, /* 12345 or 1.2.3.4 or ::1 or > 01:02:03:04:05 */ > - LEX_T_MASKED_INTEGER, /* 12345/10 or 1.2.0.0/16 or ::2/127 > or... */ > - LEX_T_MACRO, /* $NAME */ > - LEX_T_ERROR, /* invalid input */ > - > - /* Bare tokens. */ > - LEX_T_LPAREN, /* ( */ > - LEX_T_RPAREN, /* ) */ > - LEX_T_LCURLY, /* { */ > - LEX_T_RCURLY, /* } */ > - LEX_T_LSQUARE, /* [ */ > - LEX_T_RSQUARE, /* ] */ > - LEX_T_EQ, /* == */ > - LEX_T_NE, /* != */ > - LEX_T_LT, /* < */ > - LEX_T_LE, /* <= */ > - LEX_T_GT, /* > */ > - LEX_T_GE, /* >= */ > - LEX_T_LOG_NOT, /* ! */ > - LEX_T_LOG_AND, /* && */ > - LEX_T_LOG_OR, /* || */ > - LEX_T_ELLIPSIS, /* .. */ > - LEX_T_COMMA, /* , */ > - LEX_T_SEMICOLON, /* ; */ > - LEX_T_EQUALS, /* = */ > - LEX_T_EXCHANGE, /* <-> */ > - LEX_T_DECREMENT, /* -- */ > - LEX_T_COLON, /* : */ > -}; > - > -/* Subtype for LEX_T_INTEGER and LEX_T_MASKED_INTEGER tokens. > - * > - * These do not change the semantics of a token; instead, they determine > the > - * format used when a token is serialized back to a text form. That's > - * important because 3232268289 is meaningless to a human whereas > 192.168.128.1 > - * has some actual significance. */ > -enum lex_format { > - LEX_F_DECIMAL, > - LEX_F_HEXADECIMAL, > - LEX_F_IPV4, > - LEX_F_IPV6, > - LEX_F_ETHERNET, > -}; > -const char *lex_format_to_string(enum lex_format); > - > -/* A token. */ > -struct lex_token { > - /* One of LEX_*. */ > - enum lex_type type; > - > - /* Meaningful for LEX_T_ID, LEX_T_STRING, LEX_T_ERROR, LEX_T_MACRO > only. > - * For these token types, 's' may point to 'buffer'; otherwise, it > points > - * to malloc()ed memory owned by the token. > - * > - * Must be NULL for other token types. > - * > - * For LEX_T_MACRO, 's' does not include the leading $. */ > - char *s; > - > - /* LEX_T_INTEGER, LEX_T_MASKED_INTEGER only. */ > - enum lex_format format; > - > - union { > - /* LEX_T_INTEGER, LEX_T_MASKED_INTEGER only. */ > - struct { > - union mf_subvalue value; /* LEX_T_INTEGER, > LEX_T_MASKED_INTEGER. */ > - union mf_subvalue mask; /* LEX_T_MASKED_INTEGER only. */ > - }; > - > - /* LEX_T_ID, LEX_T_STRING, LEX_T_ERROR, LEX_T_MACRO only. */ > - char buffer[256]; > - }; > -}; > - > -void lex_token_init(struct lex_token *); > -void lex_token_destroy(struct lex_token *); > -void lex_token_swap(struct lex_token *, struct lex_token *); > -void lex_token_strcpy(struct lex_token *, const char *s, size_t length); > -void lex_token_strset(struct lex_token *, char *s); > -void lex_token_vsprintf(struct lex_token *, const char *format, va_list > args); > - > -void lex_token_format(const struct lex_token *, struct ds *); > -const char *lex_token_parse(struct lex_token *, const char *input, > - const char **startp); > - > -/* A lexical analyzer. */ > -struct lexer { > - const char *input; /* Remaining input (not owned by lexer). > */ > - const char *start; /* Start of current token in 'input'. */ > - struct lex_token token; /* Current token (owned by lexer). */ > -}; > - > -void lexer_init(struct lexer *, const char *input); > -void lexer_destroy(struct lexer *); > - > -enum lex_type lexer_get(struct lexer *); > -enum lex_type lexer_lookahead(const struct lexer *); > -bool lexer_match(struct lexer *, enum lex_type); > -bool lexer_match_id(struct lexer *, const char *id); > -bool lexer_is_int(const struct lexer *); > -bool lexer_get_int(struct lexer *, int *value); > - > -#endif /* ovn/lex.h */ > diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c > index a3d1672..b563586 100644 > --- a/ovn/northd/ovn-northd.c > +++ b/ovn/northd/ovn-northd.c > @@ -26,7 +26,7 @@ > #include "hash.h" > #include "openvswitch/hmap.h" > #include "openvswitch/json.h" > -#include "ovn/lib/lex.h" > +#include "ovn/lex.h" > #include "ovn/lib/ovn-nb-idl.h" > #include "ovn/lib/ovn-sb-idl.h" > #include "ovn/lib/ovn-util.h" > diff --git a/tests/test-ovn.c b/tests/test-ovn.c > index 26055bb..ffb4e50 100644 > --- a/tests/test-ovn.c > +++ b/tests/test-ovn.c > @@ -26,9 +26,9 @@ > #include "openvswitch/ofp-actions.h" > #include "openvswitch/ofpbuf.h" > #include "openvswitch/vlog.h" > -#include "ovn/lib/actions.h" > -#include "ovn/lib/expr.h" > -#include "ovn/lib/lex.h" > +#include "ovn/actions.h" > +#include "ovn/expr.h" > +#include "ovn/lex.h" > #include "ovn/lib/ovn-dhcp.h" > #include "ovs-thread.h" > #include "ovstest.h" > -- > 1.9.1 > > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev