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