This patch aims to extend Address_Set to Macros, make it more common to
accept variable set, not only address. And by that, we can skinny down ACLs,
if we use Macros to defines port name sets for ACL to use, since lots of ACL
entries are similar but only "inport" and "outport" fields are different.

Address_Set improves the performance of OVN control plane. But what more
important is, its implementation introduced a "$macros -- element_set"
mechanism, it's good way to do bunch jobs for ACLs, and even lflows.

How does Address_Set improve OVN performance?
 - it reduces the match part length for lflows, who has addresses to match.
 - indeed, it means less tokens in expression to parse, less constants, less
   combination symbols.
 - and for CMS integration component, for its DB sync job, a ACL entry has
   short match field is easier to compare.

What changes:
  Adderss_Set           -> Macros
  Adderss_Set.addresses -> Macros.elements
                           (addresses, or ports names)
                         + Macros.element_type
                           (only "address", "port_name" are valid now)
  ACL match field, for example:
    match : "outport == $ps1 && icmp4"

Will port set defined under Macros benefit in the same way as Address_Set
did? -- NO, it may be better.
 - it will not decrease ACL match field length, but the number of ACL entries.
   ACL entries who have similar match expressions, but with particular
   "inport" or "outport" can use port name set defined in Macros to combine
   into one ACL.
 - less ACL entries means less refers between ACL and Logical_Switch.acl.
 - less ACL entries, will help CMS integration component has less workload
   in DB sync job, comparing port name should be quicker then comparing whole
   ACL entry.
 - less ACL entries, means less lflows, means less match part in lflows to
   parse, less tokens to parse, make parsing work quicker.

Port name set defined under Macros will improve ovn-controller performance on
installation plenty of similar ACLs/lflows.
For port comes and leaves scenario, when there are no special ACL entries
assigned to ports, it will be the ones first come and last leave to update ACL
uuid refers in Logical_Switch.acl.

TODO:
 - go check how will ovn-northd use port sets defined under Macros.
 - find any other type need to support.

Signed-off-by: Zong Kai LI <zealo...@gmail.com>
---
 AUTHORS                   |   1 +
 include/ovn/expr.h        |   2 +-
 ovn/controller/lflow.c    | 173 ++++++++++++++++++++++++----------------------
 ovn/lib/expr.c            |  68 ++++++++++--------
 ovn/northd/ovn-northd.c   |  54 ++++++++-------
 ovn/ovn-nb.ovsschema      |  11 +--
 ovn/ovn-nb.xml            |  27 ++++++--
 ovn/ovn-sb.ovsschema      |  11 +--
 ovn/ovn-sb.xml            |   7 +-
 ovn/utilities/ovn-nbctl.c |   4 +-
 ovn/utilities/ovn-sbctl.c |   4 +-
 tests/ovn.at              |  14 ++--
 tests/test-ovn.c          |   6 +-
 13 files changed, 212 insertions(+), 170 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index b598f4b..e71571e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -459,6 +459,7 @@ ZHANG Zhiming           zhangzhim...@yunshan.net.cn
 Zhangguanghui           zhang.guang...@h3c.com
 Ziyou Wang              ziy...@vmware.com
 Zoltán Balogh           zoltan.bal...@ericsson.com
+Zong Kai, LI           zealo...@gmail.com
 ankur dwivedi           ankurengg2...@gmail.com
 chen zhang              3zhangchen9...@gmail.com
 james hopper            jameshop...@email.com
diff --git a/include/ovn/expr.h b/include/ovn/expr.h
index d790c49..5020ff4 100644
--- a/include/ovn/expr.h
+++ b/include/ovn/expr.h
@@ -466,7 +466,7 @@ void expr_constant_set_destroy(struct expr_constant_set 
*cs);
  * The values that don't qualify are ignored.
  */
 
-void expr_macros_add(struct shash *macros, const char *name,
+void expr_macros_add(struct shash *macros, const char *name, bool parse_value,
                      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);
diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c
index fda10eb..825dae7 100644
--- a/ovn/controller/lflow.c
+++ b/ovn/controller/lflow.c
@@ -38,8 +38,8 @@ VLOG_DEFINE_THIS_MODULE(lflow);
 /* Contains "struct expr_symbol"s for fields supported by OVN lflows. */
 static struct shash symtab;
 
-/* Contains an internal expr datastructure that represents an address set. */
-static struct shash expr_address_sets;
+/* Contains an internal expr datastructure that represents an macro. */
+static struct shash expr_macros;
 
 static bool full_flow_processing = false;
 static bool full_logical_flow_processing = false;
@@ -65,7 +65,7 @@ void
 lflow_init(void)
 {
     shash_init(&symtab);
-    shash_init(&expr_address_sets);
+    shash_init(&expr_macros);
 
     /* Reserve a pair of registers for the logical inport and outport.  A full
      * 32-bit register each is bigger than we need, but the expression code
@@ -187,149 +187,156 @@ lflow_init(void)
     expr_symtab_add_field(&symtab, "sctp.dst", MFF_SCTP_DST, "sctp", false);
 }
 
-/* Details of an address set currently in address_sets. We keep a cached
+/* Details of a macro currently in macros. We keep a cached
  * copy of sets still in their string form here to make it easier to compare
  * with the current values in the OVN_Southbound database. */
-struct address_set {
-    char **addresses;
-    size_t n_addresses;
+struct macro {
+    char **elements;
+    size_t n_elements;
 };
 
-/* struct address_set instances for address sets currently in the symtab,
- * hashed on the address set name. */
-static struct shash local_address_sets = 
SHASH_INITIALIZER(&local_address_sets);
+/* struct macro instances for address sets and port set currently in the
+ * symtab, hashed on the macro name. */
+static struct shash local_macros = SHASH_INITIALIZER(&local_macros);
 
 static int
-addr_cmp(const void *p1, const void *p2)
+macro_element_cmp(const void *p1, const void *p2)
 {
     const char *s1 = p1;
     const char *s2 = p2;
     return strcmp(s1, s2);
 }
 
-/* Return true if the address sets match, false otherwise. */
+/* Return true if the macro match, false otherwise. */
 static bool
-address_sets_match(const struct address_set *addr_set,
-                   const struct sbrec_address_set *addr_set_rec)
+macro_match(const struct macro *_macro,
+            const struct sbrec_macros *macros_rec)
 {
-    char **addrs1;
-    char **addrs2;
-
-    if (addr_set->n_addresses != addr_set_rec->n_addresses) {
+    if (_macro->n_elements != macros_rec->n_elements) {
         return false;
     }
-    size_t n_addresses = addr_set->n_addresses;
 
-    addrs1 = xmemdup(addr_set->addresses,
-                     n_addresses * sizeof addr_set->addresses[0]);
-    addrs2 = xmemdup(addr_set_rec->addresses,
-                     n_addresses * sizeof addr_set_rec->addresses[0]);
+    char **elements1;
+    char **elements2;
+    size_t n_elements = _macro->n_elements;
+
+    elements1 = xmemdup(_macro->elements,
+                        n_elements * sizeof _macro->elements[0]);
+    elements2 = xmemdup(macros_rec->elements,
+                        n_elements * sizeof macros_rec->elements[0]);
 
-    qsort(addrs1, n_addresses, sizeof *addrs1, addr_cmp);
-    qsort(addrs2, n_addresses, sizeof *addrs2, addr_cmp);
+    qsort(elements1, n_elements, sizeof *elements1, macro_element_cmp);
+    qsort(elements2, n_elements, sizeof *elements2, macro_element_cmp);
 
     bool res = true;
     size_t i;
-    for (i = 0; i <  n_addresses; i++) {
-        if (strcmp(addrs1[i], addrs2[i])) {
+    for (i = 0; i <  n_elements; i++) {
+        if (strcmp(elements1[i], elements2[i])) {
             res = false;
             break;
         }
     }
 
-    free(addrs1);
-    free(addrs2);
+    free(elements1);
+    free(elements2);
 
     return res;
 }
 
 static void
-address_set_destroy(struct address_set *addr_set)
+macro_destroy(struct macro *_macro)
 {
     size_t i;
-    for (i = 0; i < addr_set->n_addresses; i++) {
-        free(addr_set->addresses[i]);
+    for (i = 0; i < _macro->n_elements; i++) {
+        free(_macro->elements[i]);
     }
-    if (addr_set->n_addresses) {
-        free(addr_set->addresses);
+    if (_macro->n_elements) {
+        free(_macro->elements);
     }
-    free(addr_set);
+    free(_macro);
 }
 
 static void
-update_address_sets(struct controller_ctx *ctx)
+update_macros(struct controller_ctx *ctx)
 {
-    /* Remember the names of all address sets currently in expr_address_sets
-     * so we can detect address sets that have been deleted. */
-    struct sset cur_addr_set_names = SSET_INITIALIZER(&cur_addr_set_names);
+    /* Remember the names of all macros currently in expr_macors
+     * so we can detect macros that have been deleted. */
+    struct sset cur_macros_names = SSET_INITIALIZER(&cur_macros_names);
 
     struct shash_node *node;
-    SHASH_FOR_EACH (node, &local_address_sets) {
-        sset_add(&cur_addr_set_names, node->name);
+    SHASH_FOR_EACH (node, &local_macros) {
+        sset_add(&cur_macros_names, node->name);
     }
 
-    /* Iterate address sets in the southbound database.  Create and update the
-     * corresponding symtab entries as necessary. */
-    const struct sbrec_address_set *addr_set_rec;
-    SBREC_ADDRESS_SET_FOR_EACH (addr_set_rec, ctx->ovnsb_idl) {
-        struct address_set *addr_set =
-            shash_find_data(&local_address_sets, addr_set_rec->name);
+    /* Iterate macros (address sets and port sets) in the southbound database.
+     * Create and update the corresponding symtab entries as necessary. */
+    const struct sbrec_macros *macros_rec;
+    SBREC_MACROS_FOR_EACH (macros_rec, ctx->ovnsb_idl) {
+        if (!macros_rec->element_type) {
+            continue;
+        }
+        bool is_addr_set = !strcmp(macros_rec->element_type, "address");
+        bool is_port_set = !strcmp(macros_rec->element_type, "port_name");
+        if (!is_addr_set && !is_port_set) {
+            continue;
+        }
+        struct macro * _macro=
+            shash_find_data(&local_macros, macros_rec->name);
 
         bool create_set = false;
-        if (addr_set) {
-            /* This address set has already been added.  We must determine
+        if (_macro) {
+            /* This macro has already been added.  We must determine
              * if the symtab entry needs to be updated due to a change. */
-            sset_find_and_delete(&cur_addr_set_names, addr_set_rec->name);
-            if (!address_sets_match(addr_set, addr_set_rec)) {
-                shash_find_and_delete(&local_address_sets, addr_set_rec->name);
-                expr_macros_remove(&expr_address_sets, addr_set_rec->name);
-                address_set_destroy(addr_set);
-                addr_set = NULL;
+            sset_find_and_delete(&cur_macros_names, macros_rec->name);
+            if (!macro_match(_macro, macros_rec)) {
+                shash_find_and_delete(&local_macros, macros_rec->name);
+                expr_macros_remove(&expr_macros, macros_rec->name);
+                macro_destroy(_macro);
+                _macro = NULL;
                 create_set = true;
             }
         } else {
-            /* This address set is not yet in the symtab, so add it. */
+            /* This macro is not yet in the symtab, so add it. */
             create_set = true;
         }
 
         if (create_set) {
-            /* The address set is either new or has changed.  Create a symbol
-             * that resolves to the full set of addresses.  Store it in
-             * address_sets to remember that we created this symbol. */
-            addr_set = xzalloc(sizeof *addr_set);
-            addr_set->n_addresses = addr_set_rec->n_addresses;
-            if (addr_set_rec->n_addresses) {
-                addr_set->addresses = xmalloc(addr_set_rec->n_addresses
-                                              * sizeof addr_set->addresses[0]);
+            /* The macro is either new or has changed.  Create a symbol
+             * that resolves to its elements (set of addresses or ports).
+             * Store it in macro to remember that we created this symbol. */
+            _macro = xzalloc(sizeof *_macro);
+            _macro->n_elements = macros_rec->n_elements;
+            if (macros_rec->n_elements) {
+                _macro->elements = xmalloc(macros_rec->n_elements
+                                           * sizeof _macro->elements[0]);
                 size_t i;
-                for (i = 0; i < addr_set_rec->n_addresses; i++) {
-                    addr_set->addresses[i] = 
xstrdup(addr_set_rec->addresses[i]);
+                for (i = 0; i < macros_rec->n_elements; i++) {
+                    _macro->elements[i] = xstrdup(macros_rec->elements[i]);
                 }
             }
-            shash_add(&local_address_sets, addr_set_rec->name, addr_set);
-
-            expr_macros_add(&expr_address_sets, addr_set_rec->name,
-                            (const char * const *) addr_set->addresses,
-                            addr_set->n_addresses);
+            shash_add(&local_macros, macros_rec->name, _macro);
+            expr_macros_add(&expr_macros, macros_rec->name, is_addr_set,
+                            (const char * const *) _macro->elements,
+                            _macro->n_elements);
         }
     }
 
-    /* Anything remaining in cur_addr_set_names refers to an address set that
+    /* Anything remaining in cur_macros_names refers to an element set that
      * has been deleted from the southbound database.  We should delete
      * the corresponding symtab entry. */
     const char *cur_node, *next_node;
-    SSET_FOR_EACH_SAFE (cur_node, next_node, &cur_addr_set_names) {
-        expr_macros_remove(&expr_address_sets, cur_node);
+    SSET_FOR_EACH_SAFE (cur_node, next_node, &cur_macros_names) {
+        expr_macros_remove(&expr_macros, cur_node);
 
-        struct address_set *addr_set
-            = shash_find_and_delete(&local_address_sets, cur_node);
-        address_set_destroy(addr_set);
+        struct macro *_macro
+            = shash_find_and_delete(&local_macros, cur_node);
+        macro_destroy(_macro);
 
         struct sset_node *sset_node = SSET_NODE_FROM_NAME(cur_node);
-        sset_delete(&cur_addr_set_names, sset_node);
+        sset_delete(&cur_macros_names, sset_node);
     }
 
-    sset_destroy(&cur_addr_set_names);
+    sset_destroy(&cur_macros_names);
 }
 
 struct lookup_port_aux {
@@ -544,7 +551,7 @@ consider_logical_flow(const struct lport_index *lports,
     struct expr *expr;
 
     expr = expr_parse_string(lflow->match, &symtab,
-                             &expr_address_sets, &error);
+                             &expr_macros, &error);
     if (!error) {
         if (prereqs) {
             expr = expr_combine(EXPR_T_AND, expr, prereqs);
@@ -713,7 +720,7 @@ lflow_run(struct controller_ctx *ctx, const struct 
lport_index *lports,
           struct group_table *group_table,
           const struct simap *ct_zones)
 {
-    update_address_sets(ctx);
+    update_macros(ctx);
     add_logical_flows(ctx, lports, mcgroups, local_datapaths,
                       patched_datapaths, group_table, ct_zones);
     add_neighbor_flows(ctx, lports);
@@ -724,6 +731,6 @@ lflow_destroy(void)
 {
     expr_symtab_destroy(&symtab);
     shash_destroy(&symtab);
-    expr_macros_destroy(&expr_address_sets);
-    shash_destroy(&expr_address_sets);
+    expr_macros_destroy(&expr_macros);
+    shash_destroy(&expr_macros);
 }
diff --git a/ovn/lib/expr.c b/ovn/lib/expr.c
index 1649c05..6d55949 100644
--- a/ovn/lib/expr.c
+++ b/ovn/lib/expr.c
@@ -734,26 +734,32 @@ static bool
 parse_macros(struct expr_context *ctx, struct expr_constant_set *cs,
              size_t *allocated_values)
 {
-    struct expr_constant_set *addr_set
+    struct expr_constant_set *macros_set
         = shash_find_data(ctx->macros, ctx->lexer->token.s);
-    if (!addr_set) {
+    if (!macros_set) {
         expr_syntax_error(ctx, "expecting address set name.");
         return false;
     }
 
-    if (!assign_constant_set_type(ctx, cs, EXPR_C_INTEGER)) {
+    if (!assign_constant_set_type(ctx, cs, macros_set->type)) {
         return false;
     }
 
-    size_t n_values = cs->n_values + addr_set->n_values;
+    size_t n_values = cs->n_values + macros_set->n_values;
     if (n_values >= *allocated_values) {
         cs->values = xrealloc(cs->values, n_values * sizeof *cs->values);
         *allocated_values = n_values;
     }
-    for (size_t i = 0; i < addr_set->n_values; i++) {
-        cs->values[cs->n_values++] = addr_set->values[i];
+    if (macros_set->type == EXPR_C_INTEGER) {
+        for (size_t i = 0; i < macros_set->n_values; i++) {
+            cs->values[cs->n_values++] = macros_set->values[i];
+        }
+    } else {
+        for (size_t i = 0; i < macros_set->n_values; i++) {
+            cs->values[cs->n_values++].string = xstrdup(
+                macros_set->values[i].string);
+        }
     }
-
     return true;
 }
 
@@ -846,37 +852,45 @@ expr_constant_set_destroy(struct expr_constant_set *cs)
 /* Adds a macro named 'name' to 'macros', replacing any existing macro with the
  * given name. */
 void
-expr_macros_add(struct shash *macros, const char *name,
+expr_macros_add(struct shash *macros, const char *name, bool parse_value,
                 const char *const *values, size_t n_values)
 {
     /* Replace any existing entry for this name. */
     expr_macros_remove(macros, name);
 
     struct expr_constant_set *cs = xzalloc(sizeof *cs);
-    cs->type = EXPR_C_INTEGER;
     cs->in_curlies = true;
     cs->n_values = 0;
     cs->values = xmalloc(n_values * sizeof *cs->values);
-    for (size_t i = 0; i < n_values; i++) {
-        /* Use the lexer to convert each macro into the proper
-         * integer format. */
-        struct lexer lex;
-        lexer_init(&lex, values[i]);
-        lexer_get(&lex);
-        if (lex.token.type != LEX_T_INTEGER
-            && lex.token.type != LEX_T_MASKED_INTEGER) {
-            VLOG_WARN("Invalid address set entry: '%s', token type: %d",
-                      values[i], lex.token.type);
-        } else {
-            union expr_constant *c = &cs->values[cs->n_values++];
-            c->value = lex.token.value;
-            c->format = lex.token.format;
-            c->masked = lex.token.type == LEX_T_MASKED_INTEGER;
-            if (c->masked) {
-                c->mask = lex.token.mask;
+    if (parse_value) {
+        cs->type = EXPR_C_INTEGER;
+        for (size_t i = 0; i < n_values; i++) {
+            /* Use the lexer to convert each macro into the proper
+             * integer format. */
+            struct lexer lex;
+            lexer_init(&lex, values[i]);
+            lexer_get(&lex);
+            if (lex.token.type == LEX_T_INTEGER
+                || lex.token.type == LEX_T_MASKED_INTEGER) {
+                union expr_constant *c = &cs->values[cs->n_values++];
+                c->value = lex.token.value;
+                c->format = lex.token.format;
+                c->masked = lex.token.type == LEX_T_MASKED_INTEGER;
+                if (c->masked) {
+                    c->mask = lex.token.mask;
+                }
+            } else {
+                VLOG_WARN("Invalid macro set entry: '%s', token type: %d",
+                          values[i], lex.token.type);
             }
+            lexer_destroy(&lex);
+        }
+    } else {
+        cs->type = EXPR_C_STRING;
+        for (size_t i = 0; i < n_values; i++) {
+            union expr_constant *c = &cs->values[cs->n_values++];
+            c->string = xstrdup(values[i]);
         }
-        lexer_destroy(&lex);
     }
 
     shash_add(macros, name, cs);
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index d6c14cf..acbaea8 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -3781,41 +3781,42 @@ build_lflows(struct northd_context *ctx, struct hmap 
*datapaths,
     hmap_destroy(&mcgroups);
 }
 
-/* OVN_Northbound and OVN_Southbound have an identical Address_Set table.
+/* OVN_Northbound and OVN_Southbound have an identical Macros_Set table.
  * We always update OVN_Southbound to match the current data in
- * OVN_Northbound, so that the address sets used in Logical_Flows in
- * OVN_Southbound is checked against the proper set.*/
+ * OVN_Northbound, so that the address sets and ports set used in
+ * Logical_Flows in OVN_Southbound is checked against the proper set.*/
 static void
-sync_address_sets(struct northd_context *ctx)
+sync_macros_sets(struct northd_context *ctx)
 {
-    struct shash sb_address_sets = SHASH_INITIALIZER(&sb_address_sets);
+    struct shash sb_macros = SHASH_INITIALIZER(&sb_macros);
 
-    const struct sbrec_address_set *sb_address_set;
-    SBREC_ADDRESS_SET_FOR_EACH (sb_address_set, ctx->ovnsb_idl) {
-        shash_add(&sb_address_sets, sb_address_set->name, sb_address_set);
+    const struct sbrec_macros *sb_macros_rec;
+    SBREC_MACROS_FOR_EACH (sb_macros_rec, ctx->ovnsb_idl) {
+        shash_add(&sb_macros, sb_macros_rec->name, sb_macros_rec);
     }
 
-    const struct nbrec_address_set *nb_address_set;
-    NBREC_ADDRESS_SET_FOR_EACH (nb_address_set, ctx->ovnnb_idl) {
-        sb_address_set = shash_find_and_delete(&sb_address_sets,
-                                               nb_address_set->name);
-        if (!sb_address_set) {
-            sb_address_set = sbrec_address_set_insert(ctx->ovnsb_txn);
-            sbrec_address_set_set_name(sb_address_set, nb_address_set->name);
+    const struct nbrec_macros *nb_macros_rec;
+    NBREC_MACROS_FOR_EACH (nb_macros_rec, ctx->ovnnb_idl) {
+        sb_macros_rec = shash_find_and_delete(&sb_macros, nb_macros_rec->name);
+        if (!sb_macros_rec) {
+            sb_macros_rec = sbrec_macros_insert(ctx->ovnsb_txn);
+            sbrec_macros_set_name(sb_macros_rec, nb_macros_rec->name);
         }
 
-        sbrec_address_set_set_addresses(sb_address_set,
+        sbrec_macros_set_element_type(sb_macros_rec,
+                                      nb_macros_rec->element_type);
+        sbrec_macros_set_elements(sb_macros_rec,
                 /* "char **" is not compatible with "const char **" */
-                (const char **) nb_address_set->addresses,
-                nb_address_set->n_addresses);
+                (const char **) nb_macros_rec->elements,
+                nb_macros_rec->n_elements);
     }
 
     struct shash_node *node, *next;
-    SHASH_FOR_EACH_SAFE (node, next, &sb_address_sets) {
-        sbrec_address_set_delete(node->data);
-        shash_delete(&sb_address_sets, node);
+    SHASH_FOR_EACH_SAFE (node, next, &sb_macros) {
+        sbrec_macros_delete(node->data);
+        shash_delete(&sb_macros, node);
     }
-    shash_destroy(&sb_address_sets);
+    shash_destroy(&sb_macros);
 }
 
 static void
@@ -3830,7 +3831,7 @@ ovnnb_db_run(struct northd_context *ctx, struct 
ovsdb_idl_loop *sb_loop)
     build_ipam(ctx, &datapaths, &ports);
     build_lflows(ctx, &datapaths, &ports);
 
-    sync_address_sets(ctx);
+    sync_macros_sets(ctx);
 
     struct ovn_datapath *dp, *next_dp;
     HMAP_FOR_EACH_SAFE (dp, next_dp, key_node, &datapaths) {
@@ -4194,9 +4195,10 @@ main(int argc, char *argv[])
     add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dhcp_options_col_type);
     add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dhcp_options_col_name);
 
-    ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_address_set);
-    add_column_noalert(ovnsb_idl_loop.idl, &sbrec_address_set_col_name);
-    add_column_noalert(ovnsb_idl_loop.idl, &sbrec_address_set_col_addresses);
+    ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_macros);
+    add_column_noalert(ovnsb_idl_loop.idl, &sbrec_macros_col_name);
+    add_column_noalert(ovnsb_idl_loop.idl, &sbrec_macros_col_element_type);
+    add_column_noalert(ovnsb_idl_loop.idl, &sbrec_macros_col_elements);
 
     ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_chassis);
     ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_nb_cfg);
diff --git a/ovn/ovn-nb.ovsschema b/ovn/ovn-nb.ovsschema
index 660db76..02abcb1 100644
--- a/ovn/ovn-nb.ovsschema
+++ b/ovn/ovn-nb.ovsschema
@@ -1,7 +1,7 @@
 {
     "name": "OVN_Northbound",
     "version": "5.3.0",
-    "cksum": "1305504870 9051",
+    "cksum": "1577381784 9095",
     "tables": {
         "NB_Global": {
             "columns": {
@@ -74,12 +74,13 @@
                              "min": 0, "max": "unlimited"}}},
             "indexes": [["name"]],
             "isRoot": false},
-        "Address_Set": {
+        "Macros": {
             "columns": {
                 "name": {"type": "string"},
-                "addresses": {"type": {"key": "string",
-                                       "min": 0,
-                                       "max": "unlimited"}},
+                "element_type": {"type": "string"},
+                "elements": {"type": {"key": "string",
+                                      "min": 0,
+                                      "max": "unlimited"}},
                 "external_ids": {
                     "type": {"key": "string", "value": "string",
                              "min": 0, "max": "unlimited"}}},
diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml
index 4ce295a..7a56237 100644
--- a/ovn/ovn-nb.xml
+++ b/ovn/ovn-nb.xml
@@ -599,15 +599,21 @@
     </group>
   </table>
 
-  <table name="Address_Set" title="Address Sets">
+  <table name="Macros" title="Macros">
     <p>
-      Each row in this table represents a named set of addresses.
+      Each row in this table represents a named set of addresses,
+      or port names.
       An address set may contain Ethernet, IPv4, or IPv6 addresses
       with optional bitwise or CIDR masks.
+      An port name set contains name strings of Logical_Switch_Port.
       Address set may ultimately be used in ACLs to compare against
       fields such as <code>ip4.src</code> or <code>ip6.src</code>.
+      Port names sets may ultimately be used in ACLs to compare against
+      fileds such as <code>inport</code> or <code>outport</code>.
+      A set should only contain either addresses or port names.
       A single address set must contain addresses of the
-      same type. As an example, the following would create an address set
+      same type.
+      As an example, the following would create an address set
       with three IP addresses:
     </p>
 
@@ -616,7 +622,7 @@
     </pre>
 
     <p>
-      Address sets may be used in the <ref column="match" table="ACL"/> column
+      Macros may be used in the <ref column="match" table="ACL"/> column
       of the <ref table="ACL"/> table.  For syntax information, see the details
       of the expression language used for the <ref column="match"
       table="Logical_Flow" db="OVN_Southbound"/> column in the <ref
@@ -625,11 +631,18 @@
     </p>
 
     <column name="name">
-      A name for the address set.  This must be unique among all address sets.
+      A name for address set or port names set.
+      This must be unique among all macros entries.
     </column>
 
-    <column name="addresses">
-      The set of addresses in string form.
+    <column name="element_type">
+      Elements type in a macros entry, only "address" and "port_name" are
+      valid for now. "address" specifies address set, and "port_name" specifies
+      port name set.
+    </column>
+
+    <column name="elements">
+      The set of addresses or port names in string form.
     </column>
 
     <group title="Common Columns">
diff --git a/ovn/ovn-sb.ovsschema b/ovn/ovn-sb.ovsschema
index b1737f5..fb4936e 100644
--- a/ovn/ovn-sb.ovsschema
+++ b/ovn/ovn-sb.ovsschema
@@ -1,7 +1,7 @@
 {
     "name": "OVN_Southbound",
     "version": "1.7.0",
-    "cksum": "3677179333 6917",
+    "cksum": "3337458650 6943",
     "tables": {
         "SB_Global": {
             "columns": {
@@ -37,12 +37,13 @@
                                      "min": 0,
                                      "max": "unlimited"}},
                 "ip": {"type": "string"}}},
-        "Address_Set": {
+        "Macros": {
             "columns": {
                 "name": {"type": "string"},
-                "addresses": {"type": {"key": "string",
-                                       "min": 0,
-                                       "max": "unlimited"}}},
+                "element_type": {"type": "string"},
+                "elements": {"type": {"key": "string",
+                             "min": 0,
+                             "max": "unlimited"}}},
             "indexes": [["name"]],
             "isRoot": true},
         "Logical_Flow": {
diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml
index 13c9526..19250a7 100644
--- a/ovn/ovn-sb.xml
+++ b/ovn/ovn-sb.xml
@@ -283,15 +283,16 @@
     </column>
   </table>
 
-  <table name="Address_Set" title="Address Sets">
+  <table name="Macros" title="Macros">
     <p>
-      See the documentation for the <ref table="Address_Set"
+      See the documentation for the <ref table="Macros"
       db="OVN_Northbound"/> table in the <ref db="OVN_Northbound"/> database
       for details.
     </p>
 
     <column name="name"/>
-    <column name="addresses"/>
+    <column name="element_type"/>
+    <column name="elements"/>
   </table>
 
   <table name="Logical_Flow" title="Logical Network Flows">
diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c
index 03b6c2b..7b0d2ba 100644
--- a/ovn/utilities/ovn-nbctl.c
+++ b/ovn/utilities/ovn-nbctl.c
@@ -2142,8 +2142,8 @@ static const struct ctl_table_class tables[] = {
        NULL},
       {NULL, NULL, NULL}}},
 
-    {&nbrec_table_address_set,
-     {{&nbrec_table_address_set, &nbrec_address_set_col_name, NULL},
+    {&nbrec_table_macros,
+     {{&nbrec_table_macros, &nbrec_macros_col_name, NULL},
       {NULL, NULL, NULL}}},
 
     {&nbrec_table_dhcp_options,
diff --git a/ovn/utilities/ovn-sbctl.c b/ovn/utilities/ovn-sbctl.c
index 936915b..ff6be26 100644
--- a/ovn/utilities/ovn-sbctl.c
+++ b/ovn/utilities/ovn-sbctl.c
@@ -782,8 +782,8 @@ static const struct ctl_table_class tables[] = {
      {{&sbrec_table_mac_binding, &sbrec_mac_binding_col_logical_port, NULL},
       {NULL, NULL, NULL}}},
 
-    {&sbrec_table_address_set,
-     {{&sbrec_table_address_set, &sbrec_address_set_col_name, NULL},
+    {&sbrec_table_macros,
+     {{&sbrec_table_macros, &sbrec_macros_col_name, NULL},
       {NULL, NULL, NULL}}},
 
     {NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
diff --git a/tests/ovn.at b/tests/ovn.at
index 54fa8c5..b121132 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -760,7 +760,7 @@ done
 ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1234' drop
 ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1235 && inport == 
"lp11"' drop
 ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1236 && outport == "lp33"' 
drop
-ovn-nbctl create Address_Set name=set1 
addresses=\"f0:00:00:00:00:11\",\"f0:00:00:00:00:21\",\"f0:00:00:00:00:31\"
+ovn-nbctl create Macros name=set1 element_type="address" 
elements=\"f0:00:00:00:00:11\",\"f0:00:00:00:00:21\",\"f0:00:00:00:00:31\"
 ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1237 && eth.src == $set1 
&& outport == "lp33"' drop
 
 # Pre-populate the hypervisors' ARP tables so that we don't lose any
@@ -3667,10 +3667,11 @@ ovn-nbctl lsp-add lsw0 lp2
 ovn-nbctl lsp-set-addresses lp2 "fa:16:3e:a1:f9:ae 192.168.0.4 
fd81:ce49:a948:0:f816:3eff:fea1:f9ae"
 ovn-nbctl lsp-set-port-security lp2 "fa:16:3e:a1:f9:ae 192.168.0.4 
fd81:ce49:a948:0:f816:3eff:fea1:f9ae"
 
+# Add port names set for lp1 and lp2
+ovn-nbctl create Macros name=ps1 element_type="port_name" elements="lp1 lp2"
 # Add ACL rule for ICMPv6 on lsw0
 ovn-nbctl acl-add lsw0 from-lport 1002 'ip6 && icmp6'  allow-related
-ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp1" && ip6 && icmp6'  
allow-related
-ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp2" && ip6 && icmp6'  
allow-related
+ovn-nbctl acl-add lsw0 to-lport 1002 'outport == $ps1 && ip6 && icmp6'  
allow-related
 
 # Allow some time for ovn-northd and ovn-controller to catch up.
 # XXX This should be more systematic.
@@ -3718,12 +3719,13 @@ as hv1
 ovs-vsctl add-br br-phys
 ovn_attach n1 br-phys 192.168.0.1
 
-row=`ovn-nbctl create Address_Set name=set1 addresses=\"1.1.1.1\"`
-ovn-nbctl set Address_Set $row name=set1 addresses=\"1.1.1.1,1.1.1.2\"
-ovn-nbctl destroy Address_Set $row
+row=`ovn-nbctl create Macros name=set1 element_type="address" 
elements=\"1.1.1.1\"`
+ovn-nbctl set Macros $row name=set1 element_type="address" 
elements=\"1.1.1.1,1.1.1.2\"
+ovn-nbctl destroy Macros $row
 
 sleep 1
 
+# Address_Set is old name to Macros.
 # A bug previously existed in the address set support code
 # that caused ovn-controller to crash after an address set
 # was updated and then removed.  This test case ensures
diff --git a/tests/test-ovn.c b/tests/test-ovn.c
index acb6a99..af13e20 100644
--- a/tests/test-ovn.c
+++ b/tests/test-ovn.c
@@ -289,9 +289,9 @@ create_macros(struct shash *macros)
         "00:00:00:00:00:01", "00:00:00:00:00:02", "00:00:00:00:00:03",
     };
 
-    expr_macros_add(macros, "set1", addrs1, 3);
-    expr_macros_add(macros, "set2", addrs2, 3);
-    expr_macros_add(macros, "set3", addrs3, 3);
+    expr_macros_add(macros, "set1", true, addrs1, 3);
+    expr_macros_add(macros, "set2", true, addrs2, 3);
+    expr_macros_add(macros, "set3", true, addrs3, 3);
 }
 
 static bool
-- 
1.9.1

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to