From: Zongkai LI <st...@ovn-dev-lzklibj1.ibm.biz> This patch aims to extend table Address_Set to Set, make it more common to accept variable set, not only address. And by that, we can skinny down ACLs, if we use Set to defines port name sets for ACL to use, since lots of ACL entries are similar but only "inport" and "outport" fields are different.
What changes: Adderss_Set -> Set Adderss_Set.addresses -> Set.members (like addresses, or ports names) + Set.type (only "address", "string" are valid now) ACL match field, for example: match : "outport == $ps1 && icmp4" For scenario most ACL entries only have "inport" and "outport" fields are different, by using Set to define port name set, CMS will have less ACL entries to maintain, like: - less ACL entries to compare when synchronizing CMS DB with OVN NB DB. - less ACL entries to scan to locate one, when CMS disables a certain ACL rule for all ports. - when port deletion happen, instead of to locate ACL entries related to port by scanning ACL table, CMS may just need remove port name from relevant port name set. Signed-off-by: Zongkai LI <zealo...@gmail.com> --- AUTHORS | 1 + include/ovn/expr.h | 8 ++- ovn/controller/lflow.c | 35 ++++----- ovn/lib/expr.c | 67 ++++++++++------- ovn/northd/ovn-northd.c | 49 +++++++------ ovn/ovn-nb.ovsschema | 13 ++-- ovn/ovn-nb.xml | 18 +++-- ovn/ovn-sb.ovsschema | 13 ++-- ovn/ovn-sb.xml | 14 ++-- ovn/utilities/ovn-nbctl.c | 4 +- ovn/utilities/ovn-sbctl.c | 4 +- ovn/utilities/ovn-trace.c | 20 +++--- tests/ovn.at | 179 ++++++++++++++++++++++++++++++++++++++++++++-- tests/test-ovn.c | 6 +- 14 files changed, 312 insertions(+), 119 deletions(-) diff --git a/AUTHORS b/AUTHORS index 371c683..cdac86c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -467,6 +467,7 @@ ZHANG Zhiming zhangzhim...@yunshan.net.cn Zhangguanghui zhang.guang...@h3c.com Ziyou Wang ziy...@vmware.com Zoltán Balogh zoltan.bal...@ericsson.com +Zongkai 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 371ba20..a5fc5c6 100644 --- a/include/ovn/expr.h +++ b/include/ovn/expr.h @@ -466,17 +466,19 @@ void expr_constant_set_format(const struct expr_constant_set *, struct ds *); void expr_constant_set_destroy(struct expr_constant_set *cs); -/* Address sets, aka "macros". +/* Sets, like address sets and port name 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 of macros should have the same type: + * all integer/masked-integer values for address sets, + * all string values for port name sets. * 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, const char *type, 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 4e67365..477caef 100644 --- a/ovn/controller/lflow.c +++ b/ovn/controller/lflow.c @@ -44,17 +44,18 @@ lflow_init(void) ovn_init_symtab(&symtab); } -/* Iterate address sets in the southbound database. Create and update the +/* Iterate sets in the southbound database. Create and update the * corresponding symtab entries as necessary. */ static void -update_address_sets(struct controller_ctx *ctx, - struct shash *expr_address_sets_p) +update_sets(struct controller_ctx *ctx, + struct shash *expr_sets_p) { - const struct sbrec_address_set *as; - SBREC_ADDRESS_SET_FOR_EACH (as, ctx->ovnsb_idl) { - expr_macros_add(expr_address_sets_p, as->name, - (const char *const *) as->addresses, as->n_addresses); + const struct sbrec_set *set_rec; + SBREC_SET_FOR_EACH (set_rec, ctx->ovnsb_idl) { + expr_macros_add(expr_sets_p, set_rec->name, set_rec->type, + (const char *const *) set_rec->members, + set_rec->n_members); } } @@ -75,7 +76,7 @@ static void consider_logical_flow(const struct lport_index *lports, struct hmap *dhcpv6_opts_p, uint32_t *conj_id_ofs_p, struct hmap *flow_table, - struct shash *expr_address_sets_p); + struct shash *expr_sets_p); static bool lookup_port_cb(const void *aux_, const char *port_name, unsigned int *portp) @@ -115,7 +116,7 @@ add_logical_flows(struct controller_ctx *ctx, const struct lport_index *lports, struct group_table *group_table, const struct simap *ct_zones, struct hmap *flow_table, - struct shash *expr_address_sets_p) + struct shash *expr_sets_p) { uint32_t conj_id_ofs = 1; const struct sbrec_logical_flow *lflow; @@ -139,7 +140,7 @@ add_logical_flows(struct controller_ctx *ctx, const struct lport_index *lports, consider_logical_flow(lports, mcgroups, lflow, local_datapaths, patched_datapaths, group_table, ct_zones, &dhcp_opts, &dhcpv6_opts, &conj_id_ofs, - flow_table, expr_address_sets_p); + flow_table, expr_sets_p); } dhcp_opts_destroy(&dhcp_opts); @@ -158,7 +159,7 @@ consider_logical_flow(const struct lport_index *lports, struct hmap *dhcpv6_opts_p, uint32_t *conj_id_ofs_p, struct hmap *flow_table, - struct shash *expr_address_sets_p) + struct shash *expr_sets_p) { /* Determine translation of logical table IDs to physical table IDs. */ bool ingress = !strcmp(lflow->pipeline, "ingress"); @@ -268,7 +269,7 @@ consider_logical_flow(const struct lport_index *lports, struct expr *expr; expr = expr_parse_string(lflow->match, &symtab, - expr_address_sets_p, &error); + expr_sets_p, &error); if (!error) { if (prereqs) { expr = expr_combine(EXPR_T_AND, expr, prereqs); @@ -415,16 +416,16 @@ lflow_run(struct controller_ctx *ctx, const struct lport_index *lports, const struct simap *ct_zones, struct hmap *flow_table) { - struct shash expr_address_sets = SHASH_INITIALIZER(&expr_address_sets); + struct shash expr_sets = SHASH_INITIALIZER(&expr_sets); - update_address_sets(ctx, &expr_address_sets); + update_sets(ctx, &expr_sets); add_logical_flows(ctx, lports, mcgroups, local_datapaths, patched_datapaths, group_table, ct_zones, flow_table, - &expr_address_sets); + &expr_sets); add_neighbor_flows(ctx, lports, flow_table); - expr_macros_destroy(&expr_address_sets); - shash_destroy(&expr_address_sets); + expr_macros_destroy(&expr_sets); + shash_destroy(&expr_sets); } void diff --git a/ovn/lib/expr.c b/ovn/lib/expr.c index 4ae6b0b..1328088 100644 --- a/ovn/lib/expr.c +++ b/ovn/lib/expr.c @@ -691,26 +691,33 @@ 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 = (ctx->macros ? shash_find_data(ctx->macros, ctx->lexer->token.s) : NULL); - if (!addr_set) { - lexer_syntax_error(ctx->lexer, "expecting address set name"); + if (!macros_set) { + lexer_syntax_error(ctx->lexer, "expecting 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; @@ -907,37 +914,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, const char *type, 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 { + if (!strcmp(type, "string")) { + cs->type = EXPR_C_STRING; + for (size_t i = 0; i < n_values; i++) { 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; + c->string = xstrdup(values[i]); + } + } else { + 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) { + 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; + } } + lexer_destroy(&lex); } - lexer_destroy(&lex); } shash_add(macros, name, cs); diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c index cdc5525..a5f860b 100644 --- a/ovn/northd/ovn-northd.c +++ b/ovn/northd/ovn-northd.c @@ -4194,41 +4194,40 @@ 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 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_Northbound, so that the expr sets used in Logical_Flows in * OVN_Southbound is checked against the proper set.*/ static void -sync_address_sets(struct northd_context *ctx) +sync_sets(struct northd_context *ctx) { - struct shash sb_address_sets = SHASH_INITIALIZER(&sb_address_sets); + struct shash sb_sets = SHASH_INITIALIZER(&sb_sets); - 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_set *sb_set; + SBREC_SET_FOR_EACH (sb_set, ctx->ovnsb_idl) { + shash_add(&sb_sets, sb_set->name, sb_set); } - 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_set *nb_set; + NBREC_SET_FOR_EACH (nb_set, ctx->ovnnb_idl) { + sb_set = shash_find_and_delete(&sb_sets, nb_set->name); + if (!sb_set) { + sb_set = sbrec_set_insert(ctx->ovnsb_txn); + sbrec_set_set_name(sb_set, nb_set->name); + sbrec_set_set_type(sb_set, nb_set->type); } - sbrec_address_set_set_addresses(sb_address_set, + sbrec_set_set_members(sb_set, /* "char **" is not compatible with "const char **" */ - (const char **) nb_address_set->addresses, - nb_address_set->n_addresses); + (const char **) nb_set->members, nb_set->n_members); } 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_sets) { + sbrec_set_delete(node->data); + shash_delete(&sb_sets, node); } - shash_destroy(&sb_address_sets); + shash_destroy(&sb_sets); } static void @@ -4243,7 +4242,7 @@ ovnnb_db_run(struct northd_context *ctx, struct ovsdb_idl_loop *sb_loop) build_ipam(&datapaths, &ports); build_lflows(ctx, &datapaths, &ports); - sync_address_sets(ctx); + sync_sets(ctx); struct ovn_datapath *dp, *next_dp; HMAP_FOR_EACH_SAFE (dp, next_dp, key_node, &datapaths) { @@ -4638,9 +4637,9 @@ main(int argc, char *argv[]) add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dhcpv6_options_col_code); add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dhcpv6_options_col_type); add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dhcpv6_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_set); + add_column_noalert(ovnsb_idl_loop.idl, &sbrec_set_col_name); + add_column_noalert(ovnsb_idl_loop.idl, &sbrec_set_col_members); 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 b7e70aa..090aa13 100644 --- a/ovn/ovn-nb.ovsschema +++ b/ovn/ovn-nb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Northbound", - "version": "5.3.3", - "cksum": "2442952958 9945", + "version": "5.4.0", + "cksum": "3245118019 9975", "tables": { "NB_Global": { "columns": { @@ -84,12 +84,13 @@ "min": 0, "max": "unlimited"}}}, "indexes": [["name"]], "isRoot": false}, - "Address_Set": { + "Set": { "columns": { "name": {"type": "string"}, - "addresses": {"type": {"key": "string", - "min": 0, - "max": "unlimited"}}, + "type": {"type": "string"}, + "members": {"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 c45a444..cc94291 100644 --- a/ovn/ovn-nb.xml +++ b/ovn/ovn-nb.xml @@ -631,9 +631,12 @@ </group> </table> - <table name="Address_Set" title="Address Sets"> + <table name="Set" title="Sets"> <p> - Each row in this table represents a named set of addresses. + Each row in this table represents a named set of variables sets. + A port name set may contain port names. Port name set may ultimately + be used in ACLs to compare against fields such as <code>inport</code> + or <code>outport</code>. An address set may contain Ethernet, IPv4, or IPv6 addresses with optional bitwise or CIDR masks. Address set may ultimately be used in ACLs to compare against @@ -657,11 +660,16 @@ </p> <column name="name"> - A name for the address set. This must be unique among all address sets. + A name for the set. This must be unique among all sets. </column> - <column name="addresses"> - The set of addresses in string form. + <column name="type"> + Type for the set, only "address" for address set, "string" for port name + set are supported now. Default is "address". + </column> + + <column name="members"> + The set of members in string form. </column> <group title="Common Columns"> diff --git a/ovn/ovn-sb.ovsschema b/ovn/ovn-sb.ovsschema index 8604b4e..d9db8aa 100644 --- a/ovn/ovn-sb.ovsschema +++ b/ovn/ovn-sb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Southbound", - "version": "1.8.0", - "cksum": "59582657 7376", + "version": "1.9.0", + "cksum": "246007021 7406", "tables": { "SB_Global": { "columns": { @@ -37,12 +37,13 @@ "min": 0, "max": "unlimited"}}, "ip": {"type": "string"}}}, - "Address_Set": { + "Set": { "columns": { "name": {"type": "string"}, - "addresses": {"type": {"key": "string", - "min": 0, - "max": "unlimited"}}}, + "type": {"type": "string"}, + "members": {"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 235c21c..40f7c89 100644 --- a/ovn/ovn-sb.xml +++ b/ovn/ovn-sb.xml @@ -339,15 +339,16 @@ </column> </table> - <table name="Address_Set" title="Address Sets"> + <table name="Set" title="Sets"> <p> - See the documentation for the <ref table="Address_Set" + See the documentation for the <ref table="Set" db="OVN_Northbound"/> table in the <ref db="OVN_Northbound"/> database for details. </p> <column name="name"/> - <column name="addresses"/> + <column name="type"/> + <column name="members"/> </table> <table name="Logical_Flow" title="Logical Network Flows"> @@ -723,10 +724,9 @@ <p> You may refer to a set of IPv4, IPv6, or MAC addresses stored in the - <ref table="Address_Set"/> table by its <ref column="name" - table="Address_Set"/>. An <ref table="Address_Set"/> with a name - of <code>set1</code> can be referred to as - <code>$set1</code>. + <ref table="Set"/> table by its <ref column="name" table="Set"/>. An + <ref table="Set"/> with a name of <code>set1</code> can be referred to + as <code>$set1</code>. </p> <p><em>Miscellaneous</em></p> diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c index 2148665..e78ff35 100644 --- a/ovn/utilities/ovn-nbctl.c +++ b/ovn/utilities/ovn-nbctl.c @@ -2154,8 +2154,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_set, + {{&nbrec_table_set, &nbrec_set_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 b894b8b..23d8420 100644 --- a/ovn/utilities/ovn-sbctl.c +++ b/ovn/utilities/ovn-sbctl.c @@ -774,8 +774,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_set, + {{&sbrec_table_set, &sbrec_set_col_name, NULL}, {NULL, NULL, NULL}}}, {NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}} diff --git a/ovn/utilities/ovn-trace.c b/ovn/utilities/ovn-trace.c index f5607df..62337e0 100644 --- a/ovn/utilities/ovn-trace.c +++ b/ovn/utilities/ovn-trace.c @@ -329,8 +329,8 @@ static struct shash ports; /* Symbol table for expressions and actions. */ static struct shash symtab; -/* Address sets. */ -static struct shash address_sets; +/* Sets of macros. */ +static struct shash expr_sets; static struct ovntrace_datapath * ovntrace_datapath_find_by_sb_uuid(const struct uuid *sb_uuid) @@ -542,13 +542,13 @@ read_mcgroups(void) static void read_address_sets(void) { - shash_init(&address_sets); + shash_init(&expr_sets); - const struct sbrec_address_set *sbas; - SBREC_ADDRESS_SET_FOR_EACH (sbas, ovnsb_idl) { - expr_macros_add(&address_sets, sbas->name, - (const char *const *) sbas->addresses, - sbas->n_addresses); + const struct sbrec_set *sbs; + SBREC_SET_FOR_EACH (sbs, ovnsb_idl) { + expr_macros_add(&expr_sets, sbs->name, sbs->type, + (const char *const *) sbs->members, + sbs->n_members); } } @@ -592,7 +592,7 @@ read_flows(void) char *error; struct expr *match; - match = expr_parse_string(sblf->match, &symtab, &address_sets, &error); + match = expr_parse_string(sblf->match, &symtab, &expr_sets, &error); if (error) { VLOG_WARN("%s: parsing expression failed (%s)", sblf->match, error); @@ -1348,7 +1348,7 @@ trace(const char *dp_s, const char *flow_s) } struct flow uflow; - char *error = expr_parse_microflow(flow_s, &symtab, &address_sets, + char *error = expr_parse_microflow(flow_s, &symtab, &expr_sets, ovntrace_lookup_port, dp, &uflow); if (error) { ovs_fatal(0, "error parsing flow: %s", error); diff --git a/tests/ovn.at b/tests/ovn.at index 677ab46..5b24f32 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -297,7 +297,7 @@ inport = "eth0" => Syntax error at `=' expecting relational operator. 123 == 123 => Syntax error at `123' expecting field name. -$name => Syntax error at `$name' expecting address set name. +$name => Syntax error at `$name' expecting set name. 123 == xyzzy => Syntax error at `xyzzy' expecting field name. xyzzy == 1 => Syntax error at `xyzzy' expecting field name. @@ -344,7 +344,7 @@ ip4.src == ::1 => 128-bit constant is not compatible with 32-bit field ip4.src. eth.dst[40] x => Syntax error at `x' expecting end of input. -ip4.src == {1.2.3.4, $set1, $unknownset} => Syntax error at `$unknownset' expecting address set name. +ip4.src == {1.2.3.4, $set1, $unknownset} => Syntax error at `$unknownset' expecting set name. eth.src == {$set3, badmac, 00:00:00:00:00:01} => Syntax error at `badmac' expecting constant. ]]) sed 's/ =>.*//' test-cases.txt > input.txt @@ -1004,7 +1004,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 Set name=set1 members=\"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 @@ -1261,7 +1261,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 == "lp1"' drop ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1236 && outport == "lp3"' drop -ovn-nbctl create Address_Set name=set1 addresses=\"f0:00:00:00:00:01\",\"f0:00:00:00:00:02\" +ovn-nbctl create Set name=set1 members=\"f0:00:00:00:00:01\",\"f0:00:00:00:00:02\" ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1237 && eth.src == $set1 && outport == "lp3"' drop ovn-nbctl --wait=sb sync @@ -4510,9 +4510,9 @@ 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 Set name=set1 members=\"1.1.1.1\"` +ovn-nbctl set Set $row name=set1 members=\"1.1.1.1,1.1.1.2\" +ovn-nbctl destroy Set $row sleep 1 @@ -5346,3 +5346,168 @@ OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port patch-br-int-to-ln_port" | wc OVN_CLEANUP([hv1],[hv2]) AT_CLEANUP + +# one hypervisor, one logical switch, 3 logical ports. +AT_SETUP([ovn -- port name set and address set for ACL]) +AT_KEYWORDS([ovn-set]) +AT_SKIP_IF([test $HAVE_PYTHON = no]) +ovn_start + +# Create hypervisors hv1. +# Add vif[123] to hv1. +# Add all of the vifs to a single logical switch lsw0. +# Turn of l2 and l3 port security on vifs. +ovn-nbctl ls-add lsw0 +net_add n1 +sim_add hv1 +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.233 + +for i in 1 2 3; do + ovs-vsctl add-port br-int vif$i -- set Interface vif$i external-ids:iface-id=lp$i options:tx_pcap=hv1/vif$i-tx.pcap options:rxq_pcap=hv1/vif$i-rx.pcap ofport-request=$i + ovn-nbctl lsp-add lsw0 lp$i + ovn-nbctl lsp-set-addresses lp$i "f0:00:00:00:00:0$i 192.168.0.$i" + ovn-nbctl lsp-set-port-security lp$i "f0:00:00:00:00:0$i 192.168.0.$i" +done + +# Pre-populate the hypervisors' ARP tables so that we don't lose any +# packets for ARP resolution (native tunneling doesn't queue packets +# for ARP resolution). +ovn_populate_arp + +# Allow some time for ovn-northd and ovn-controller to catch up. +# XXX This should be more systematic. +sleep 1 + +for i in 1 2 3; do + : > $i.expected +done + +trim_zeros() { + sed 's/\(00\)\{1,\}$//' +} + +reset_pcap_file() { + local iface=$1 + local pcap_file=$2 + ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \ +options:rxq_pcap=dummy-rx.pcap + rm -f ${pcap_file}*.pcap + ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \ +options:rxq_pcap=${pcap_file}-rx.pcap +} + +reset_all_pcap_file() { + for i in 1 2 3; do + reset_pcap_file vif$i hv1/vif$i + done +} + +remove_all_expected_file() { + for i in 1 2 3; do + rm $i.expected + done +} + +# test_ip INPORT OUTPORT +# +# This shell function causes an ip packet to be received on INPORT. +# The OUTPORTs (zero or more) list the VIFs on which the packet should +# be received. INPORT and the OUTPORTs are specified as logical switch +# port numbers, e.g. 1 for vif1. +test_ip() { + # This packet has bad checksums but logical L3 routing doesn't check. + local inport=$1 outport=$2 + if test $inport = $outport; then + return + fi + local src_mac=f0000000000${inport} + local dst_mac=f0000000000${outport} + local src_ip=c0a8000${inport} + local dst_ip=c0a8000${outport} + local packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 + shift; shift; shift; shift; shift + as hv1 ovs-appctl netdev-dummy/receive vif$inport $packet + echo $packet >> $outport.expected +} + +test_ip_all() { + for i in 1 2 3; do + for j in 1 2 3; do + test_ip $i $j + done + done +} + +# No ACL rules yet, vif packets can go and come without ACL drop. +test_ip_all +for i in 1 2 3; do + OVN_CHECK_PACKETS([hv1/vif$i-tx.pcap], [$i.expected]) +done + +# Add ACL rule to drop ip packets, vifs cannot receive ip packets now +ovn-nbctl acl-add lsw0 to-lport 1001 'ip' drop +sleep 1 +reset_all_pcap_file +test_ip_all +for i in 1 2 3; do + $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif$i-tx.pcap | trim_zeros > $i.packets + AT_CHECK([cat $i.packets], [0], []) +done + +# Add ACL rule to allow ip packets with ip4.src in address set, with outport is lp1 to pass. +ovn-nbctl create Set name="as1" members="192.168.0.1, 192.168.0.2, 192.168.0.3" +ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp1" && ip4 && ip4.src == $as1' allow +sleep 1 +rm 1.expected +test_ip 1 2 +test_ip 1 3 +test_ip 2 1 +test_ip 3 1 +OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [1.expected]) +for i in 2 3; do + $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif$i-tx.pcap | trim_zeros > $i.packets + AT_CHECK([cat $i.packets], [0], []) +done + +# Add ACL rule to allow ip packets with ip4.src is lp1 ip address, with outport in port name +# set to pass. +ovn-nbctl create Set name="ps1" type="string" members="lp1, lp2, lp3" +ovn-nbctl acl-add lsw0 to-lport 1002 'outport == $ps1 && ip4 && ip4.src == 192.168.0.1' allow +sleep 1 +reset_all_pcap_file +remove_all_expected_file +test_ip 1 2 +test_ip 1 3 +test_ip 2 1 +test_ip 3 1 +for i in 1 2 3; do + OVN_CHECK_PACKETS([hv1/vif$i-tx.pcap], [$i.expected]) +done + +# Remove previously added ACL rules, add new ACL rule with address set and port name set +# to allow ip packets pass. +ovn-nbctl acl-del lsw0 to-lport 1002 'outport == $ps1 && ip4 && ip4.src == 192.168.0.1' +ovn-nbctl acl-del lsw0 to-lport 1002 'outport == "lp1" && ip4 && ip4.src == $as1' +ovn-nbctl acl-add lsw0 to-lport 1002 'outport == $ps1 && ip4 && ip4.src == $as1' allow +sleep 1 +reset_all_pcap_file +remove_all_expected_file +test_ip_all +for i in 1 2 3; do + OVN_CHECK_PACKETS([hv1/vif$i-tx.pcap], [$i.expected]) +done + +#dump information +ovn-nbctl show +ovn-nbctl list set + +echo "------ hv1 dump ------" +as hv1 ovs-vsctl show +as hv1 ovs-ofctl -O OpenFlow13 show br-int +as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int + +OVN_CLEANUP([hv1]) + +AT_CLEANUP diff --git a/tests/test-ovn.c b/tests/test-ovn.c index 67543b1..22bcf81 100644 --- a/tests/test-ovn.c +++ b/tests/test-ovn.c @@ -202,9 +202,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", "address", addrs1, 3); + expr_macros_add(macros, "set2", "address", addrs2, 3); + expr_macros_add(macros, "set3", "address", addrs3, 3); } static bool -- 2.7.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev