From patchwork Fri Dec 23 10:31:23 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mickey Spiegel X-Patchwork-Id: 708408 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3tlPpb4vZfz9snk for ; Fri, 23 Dec 2016 21:32:23 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="JG53yag8"; dkim-atps=neutral Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id AA696B38; Fri, 23 Dec 2016 10:31:46 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 0A14295E for ; Fri, 23 Dec 2016 10:31:45 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f66.google.com (mail-pg0-f66.google.com [74.125.83.66]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id E1F3990 for ; Fri, 23 Dec 2016 10:31:43 +0000 (UTC) Received: by mail-pg0-f66.google.com with SMTP id i5so126781pgh.2 for ; Fri, 23 Dec 2016 02:31:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+BWkbNPNohfpTzvXbr+si8KHVglnITkhZ7TQEySqHkw=; b=JG53yag8l4KdAvuBNNF6qkZfvD9zJqr8nmLW3KIBRoHBjActXIl72LmZGEGc8as8r8 zjMg6E1iyzaP6scDFyYGO4MRT0abxENwk+6/GmSAJCK+x86vfVMlRvftyg3NXHow5d7n 6X7pwWHELa192QyCr91MVJ8+rnk7J7RhEbEzJPAqI3aLjNIbek0imwmPplNKOmiYXgfO rXuYkhMLbIxHTPmqT7yBNbO9OQivvKqfZ6rZjXfWePCKCTUfdbYW3KJk/rEewP4sSVLA qkEBFlEDGtCS26H6jLpVDsozdb1hSpRVwehlUIt/y4TQHO8orp9HCHUFkXtDqB5eLTjb KB0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=+BWkbNPNohfpTzvXbr+si8KHVglnITkhZ7TQEySqHkw=; b=ev7mK1zI2mcinQBI2cZg0tgIq+1G3s9sD3cIiGHMV8n/cWsUF/Uc3X4yu2R+/8mQsS nod59cfRSigP1ULI+USNKqSbg3wOxtta9CtAjzr3KmXfwxqCoJ2u3+DWnLPYttSnM+9w mP+07eMbeeg7a61fcqcgd27xSQl6nFdmxfTy9SKPAs3AXqgXfl4nDGAl/ZVVPbr4GxcH VeuO474DHrvg5ryTL8jr5HBvfPn3bbKgyLNcFRWvlrqtKdNuWy4VD7B+ZNk5yL1Gwj8a jkOqcCj4KVspsnPTIJRvCAM6mvX9coysPd2XjaFirQWQ5fZ5FgBydhb9bw8MKnMkk48F QU6g== X-Gm-Message-State: AIkVDXI00G4QFf0mo5kU+htKfmk3gekkGB9M7hrxDCq8U2PefipVlzrpqbcWDCtKxLfHRQ== X-Received: by 10.84.217.18 with SMTP id o18mr28401959pli.45.1482489103090; Fri, 23 Dec 2016 02:31:43 -0800 (PST) Received: from localhost.localdomain (c-73-202-53-195.hsd1.ca.comcast.net. [73.202.53.195]) by smtp.gmail.com with ESMTPSA id s3sm28905935pfg.14.2016.12.23.02.31.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 23 Dec 2016 02:31:42 -0800 (PST) From: Mickey Spiegel To: dev@openvswitch.org Date: Fri, 23 Dec 2016 02:31:23 -0800 Message-Id: <1482489088-13043-2-git-send-email-mickeys.dev@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1482489088-13043-1-git-send-email-mickeys.dev@gmail.com> References: <1482489088-13043-1-git-send-email-mickeys.dev@gmail.com> X-Spam-Status: No, score=-1.5 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH 1/6] ovn: add is_chassis_resident match expression component X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org This patch introduces a new match expression component is_chassis_resident(). Unlike match expression comparisons, is_chassis_resident is not pushed down to OpenFlow. It is a conditional that is evaluated in the controller during expr_simplify(), when it is replaced by a boolean expression. The is_chassis_resident conditional evaluates to "true" when the specified string identifies a port name that is resident on this controller chassis, i.e., the corresponding southbound database Port_Binding has a chassis column that matches this chassis. Otherwise it evaluates to "false". This allows higher level features to specify flows that are only installed on some chassis rather than on all chassis with the corresponding datapath. Suggested-by: Ben Pfaff Signed-off-by: Mickey Spiegel --- include/ovn/expr.h | 22 +++++- ovn/controller/lflow.c | 39 ++++++++-- ovn/controller/lflow.h | 5 +- ovn/controller/ovn-controller.c | 5 +- ovn/lib/expr.c | 155 ++++++++++++++++++++++++++++++++++++++-- ovn/utilities/ovn-trace.c | 21 +++++- tests/ovn.at | 14 ++++ tests/test-ovn.c | 15 +++- 8 files changed, 260 insertions(+), 16 deletions(-) diff --git a/include/ovn/expr.h b/include/ovn/expr.h index 371ba20..d3749fa 100644 --- a/include/ovn/expr.h +++ b/include/ovn/expr.h @@ -292,6 +292,15 @@ enum expr_type { 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. */ + EXPR_T_CONDITION, /* Conditional to be evaluated in the + * controller during expr_simplify(), + * prior to constructing OpenFlow matches. */ +}; + +/* Expression condition type. */ +enum expr_cond_type { + EXPR_COND_CHASSIS_RESIDENT, /* Check if specified logical port name is + * resident on the controller chassis. */ }; /* Relational operator. */ @@ -349,6 +358,14 @@ struct expr { /* EXPR_T_BOOLEAN. */ bool boolean; + + /* EXPR_T_CONDITION. */ + struct { + enum expr_cond_type type; + bool not; + /* XXX Should arguments for conditions be generic? */ + char *string; + } cond; }; }; @@ -375,7 +392,10 @@ 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_simplify(struct expr *, + bool (*is_chassis_resident)(const void *c_aux, + const char *port_name), + const void *c_aux); struct expr *expr_normalize(struct expr *); bool expr_honors_invariants(const struct expr *); diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c index d913998..0384c8d 100644 --- a/ovn/controller/lflow.c +++ b/ovn/controller/lflow.c @@ -64,12 +64,18 @@ struct lookup_port_aux { const struct sbrec_datapath_binding *dp; }; +struct condition_aux { + const struct lport_index *lports; + const struct sbrec_chassis *chassis; +}; + static void consider_logical_flow(const struct lport_index *lports, const struct mcgroup_index *mcgroups, const struct sbrec_logical_flow *lflow, const struct hmap *local_datapaths, struct group_table *group_table, const struct simap *ct_zones, + const struct sbrec_chassis *chassis, struct hmap *dhcp_opts_p, struct hmap *dhcpv6_opts_p, uint32_t *conj_id_ofs_p, @@ -99,6 +105,20 @@ lookup_port_cb(const void *aux_, const char *port_name, unsigned int *portp) } static bool +is_chassis_resident_cb(const void *c_aux_, const char *port_name) +{ + const struct condition_aux *c_aux = c_aux_; + + const struct sbrec_port_binding *pb + = lport_lookup_by_name(c_aux->lports, port_name); + if (pb && pb->chassis && pb->chassis == c_aux->chassis) { + return true; + } + + return false; +} + +static bool is_switch(const struct sbrec_datapath_binding *ldp) { return smap_get(&ldp->external_ids, "logical-switch") != NULL; @@ -112,6 +132,7 @@ add_logical_flows(struct controller_ctx *ctx, const struct lport_index *lports, const struct hmap *local_datapaths, struct group_table *group_table, const struct simap *ct_zones, + const struct sbrec_chassis *chassis, struct hmap *flow_table, struct shash *expr_address_sets_p) { @@ -135,7 +156,7 @@ add_logical_flows(struct controller_ctx *ctx, const struct lport_index *lports, SBREC_LOGICAL_FLOW_FOR_EACH (lflow, ctx->ovnsb_idl) { consider_logical_flow(lports, mcgroups, lflow, local_datapaths, - group_table, ct_zones, + group_table, ct_zones, chassis, &dhcp_opts, &dhcpv6_opts, &conj_id_ofs, flow_table, expr_address_sets_p); } @@ -151,6 +172,7 @@ consider_logical_flow(const struct lport_index *lports, const struct hmap *local_datapaths, struct group_table *group_table, const struct simap *ct_zones, + const struct sbrec_chassis *chassis, struct hmap *dhcp_opts_p, struct hmap *dhcpv6_opts_p, uint32_t *conj_id_ofs_p, @@ -231,6 +253,11 @@ consider_logical_flow(const struct lport_index *lports, struct hmap matches; struct expr *expr; + struct condition_aux cond_aux = { + .lports = lports, + .chassis = chassis + }; + expr = expr_parse_string(lflow->match, &symtab, expr_address_sets_p, &error); if (!error) { @@ -250,7 +277,7 @@ consider_logical_flow(const struct lport_index *lports, return; } - expr = expr_simplify(expr); + expr = expr_simplify(expr, is_chassis_resident_cb, &cond_aux); expr = expr_normalize(expr); uint32_t n_conjs = expr_to_matches(expr, lookup_port_cb, &aux, &matches); @@ -371,7 +398,9 @@ add_neighbor_flows(struct controller_ctx *ctx, /* Translates logical flows in the Logical_Flow table in the OVN_SB database * into OpenFlow flows. See ovn-architecture(7) for more information. */ void -lflow_run(struct controller_ctx *ctx, const struct lport_index *lports, +lflow_run(struct controller_ctx *ctx, + const struct sbrec_chassis *chassis, + const struct lport_index *lports, const struct mcgroup_index *mcgroups, const struct hmap *local_datapaths, struct group_table *group_table, @@ -381,8 +410,8 @@ lflow_run(struct controller_ctx *ctx, const struct lport_index *lports, struct shash expr_address_sets = SHASH_INITIALIZER(&expr_address_sets); update_address_sets(ctx, &expr_address_sets); - add_logical_flows(ctx, lports, mcgroups, local_datapaths, - group_table, ct_zones, flow_table, &expr_address_sets); + add_logical_flows(ctx, lports, mcgroups, local_datapaths, group_table, + ct_zones, chassis, flow_table, &expr_address_sets); add_neighbor_flows(ctx, lports, flow_table); expr_macros_destroy(&expr_address_sets); diff --git a/ovn/controller/lflow.h b/ovn/controller/lflow.h index 6305ce0..2ddf55d 100644 --- a/ovn/controller/lflow.h +++ b/ovn/controller/lflow.h @@ -40,6 +40,7 @@ struct group_table; struct hmap; struct lport_index; struct mcgroup_index; +struct sbrec_chassis; struct simap; struct uuid; @@ -61,7 +62,9 @@ struct uuid; #define LOG_PIPELINE_LEN 16 void lflow_init(void); -void lflow_run(struct controller_ctx *, const struct lport_index *, +void lflow_run(struct controller_ctx *, + const struct sbrec_chassis *chassis, + const struct lport_index *, const struct mcgroup_index *, const struct hmap *local_datapaths, struct group_table *group_table, diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 368ccc9..5bddcf3 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -592,8 +592,9 @@ main(int argc, char *argv[]) commit_ct_zones(br_int, &pending_ct_zones); struct hmap flow_table = HMAP_INITIALIZER(&flow_table); - lflow_run(&ctx, &lports, &mcgroups, &local_datapaths, - &group_table, &ct_zones, &flow_table); + lflow_run(&ctx, chassis, &lports, &mcgroups, + &local_datapaths, &group_table, &ct_zones, + &flow_table); physical_run(&ctx, mff_ovn_geneve, br_int, chassis, &ct_zones, &lports, diff --git a/ovn/lib/expr.c b/ovn/lib/expr.c index 5399985..3034456 100644 --- a/ovn/lib/expr.c +++ b/ovn/lib/expr.c @@ -233,6 +233,11 @@ expr_not(struct expr *expr) case EXPR_T_BOOLEAN: expr->boolean = !expr->boolean; break; + + case EXPR_T_CONDITION: + expr->cond.not = !expr->cond.not; + break; + default: OVS_NOT_REACHED(); } @@ -290,6 +295,9 @@ expr_fix(struct expr *expr) case EXPR_T_BOOLEAN: return expr; + case EXPR_T_CONDITION: + return expr; + default: OVS_NOT_REACHED(); } @@ -394,6 +402,21 @@ expr_format_andor(const struct expr *e, const char *op, struct ds *s) } } +static void +expr_format_condition(const struct expr *e, struct ds *s) +{ + if (e->cond.not) { + ds_put_char(s, '!'); + } + switch (e->cond.type) { + case EXPR_COND_CHASSIS_RESIDENT: + ds_put_format(s, "is_chassis_resident("); + json_string_escape(e->cond.string, s); + ds_put_char(s, ')'); + break; + } +} + /* Appends a string form of 'e' to 's'. The string form is acceptable for * parsing back into an equivalent expression. */ void @@ -415,6 +438,10 @@ expr_format(const struct expr *e, struct ds *s) case EXPR_T_BOOLEAN: ds_put_char(s, e->boolean ? '1' : '0'); break; + + case EXPR_T_CONDITION: + expr_format_condition(e, s); + break; } } @@ -973,6 +1000,32 @@ expr_macros_destroy(struct shash *macros) } static struct expr * +parse_chassis_resident(struct expr_context *ctx) +{ + if (!lexer_force_match(ctx->lexer, LEX_T_LPAREN)) { + return NULL; + } + if (ctx->lexer->token.type != LEX_T_STRING) { + lexer_syntax_error(ctx->lexer, "expecting string"); + return NULL; + } + + struct expr *e = xzalloc(sizeof *e); + e->type = EXPR_T_CONDITION; + e->cond.type = EXPR_COND_CHASSIS_RESIDENT; + e->cond.not = false; + e->cond.string = xstrdup(ctx->lexer->token.s); + + lexer_get(ctx->lexer); + if (!lexer_force_match(ctx->lexer, LEX_T_RPAREN)) { + expr_destroy(e); + return NULL; + } + + return e; +} + +static struct expr * expr_parse_primary(struct expr_context *ctx, bool *atomic) { *atomic = false; @@ -991,6 +1044,11 @@ expr_parse_primary(struct expr_context *ctx, bool *atomic) enum expr_relop r; struct expr_constant_set c; + if (lexer_match_id(ctx->lexer, "is_chassis_resident")) { + *atomic = true; + return parse_chassis_resident(ctx); + } + if (!parse_field(ctx, &f)) { return NULL; } @@ -1383,6 +1441,7 @@ expr_get_level(const struct expr *expr) return level; case EXPR_T_BOOLEAN: + case EXPR_T_CONDITION: return EXPR_L_BOOLEAN; default: @@ -1465,6 +1524,14 @@ expr_clone_andor(struct expr *expr) return new; } +static struct expr * +expr_clone_condition(struct expr *expr) +{ + struct expr *new = xmemdup(expr, sizeof *expr); + new->cond.string = xstrdup(new->cond.string); + return new; +} + /* Returns a clone of 'expr'. This is a "deep copy": neither the returned * expression nor any of its substructure will be shared with 'expr'. */ struct expr * @@ -1480,6 +1547,9 @@ expr_clone(struct expr *expr) case EXPR_T_BOOLEAN: return expr_create_boolean(expr->boolean); + + case EXPR_T_CONDITION: + return expr_clone_condition(expr); } OVS_NOT_REACHED(); } @@ -1511,6 +1581,10 @@ expr_destroy(struct expr *expr) case EXPR_T_BOOLEAN: break; + + case EXPR_T_CONDITION: + free(expr->cond.string); + break; } free(expr); } @@ -1639,6 +1713,7 @@ expr_annotate__(struct expr *expr, const struct shash *symtab, } case EXPR_T_BOOLEAN: + case EXPR_T_CONDITION: *errorp = NULL; return expr; @@ -1781,10 +1856,42 @@ expr_simplify_relational(struct expr *expr) return new ? new : expr_create_boolean(false); } +/* Resolves condition and replaces the expression with a boolean. */ +static struct expr * +expr_simplify_condition(struct expr *expr, + bool (*is_chassis_resident)(const void *c_aux, + const char *port_name), + const void *c_aux) +{ + bool cond_initial_result; + switch (expr->cond.type) { + case EXPR_COND_CHASSIS_RESIDENT: + if (!is_chassis_resident || !c_aux) { + /* For test cases where chassis is not considered. */ + cond_initial_result = true; + } else { + cond_initial_result = + is_chassis_resident(c_aux, expr->cond.string); + } + break; + + default: + OVS_NOT_REACHED(); + } + if (expr->cond.not) { + cond_initial_result = !cond_initial_result; + } + expr_destroy(expr); + return expr_create_boolean(cond_initial_result); +} + /* Takes ownership of 'expr' and returns an equivalent expression whose * EXPR_T_CMP nodes use only tests for equality (EXPR_R_EQ). */ struct expr * -expr_simplify(struct expr *expr) +expr_simplify(struct expr *expr, + bool (*is_chassis_resident)(const void *c_aux, + const char *port_name), + const void *c_aux) { struct expr *sub, *next; @@ -1799,12 +1906,16 @@ expr_simplify(struct expr *expr) case EXPR_T_OR: LIST_FOR_EACH_SAFE (sub, next, node, &expr->andor) { ovs_list_remove(&sub->node); - expr_insert_andor(expr, next, expr_simplify(sub)); + expr_insert_andor(expr, next, + expr_simplify(sub, is_chassis_resident, c_aux)); } return expr_fix(expr); case EXPR_T_BOOLEAN: return expr; + + case EXPR_T_CONDITION: + return expr_simplify_condition(expr, is_chassis_resident, c_aux); } OVS_NOT_REACHED(); } @@ -1832,6 +1943,7 @@ expr_is_cmp(const struct expr *expr) } case EXPR_T_BOOLEAN: + case EXPR_T_CONDITION: return NULL; default: @@ -1928,6 +2040,8 @@ crush_and_string(struct expr *expr, const struct expr_symbol *symbol) } free(new); break; + case EXPR_T_CONDITION: + OVS_NOT_REACHED(); } } @@ -2022,6 +2136,8 @@ crush_and_numeric(struct expr *expr, const struct expr_symbol *symbol) } expr_destroy(new); break; + case EXPR_T_CONDITION: + OVS_NOT_REACHED(); } } if (ovs_list_is_empty(&expr->andor)) { @@ -2234,6 +2350,10 @@ crush_cmps(struct expr *expr, const struct expr_symbol *symbol) case EXPR_T_BOOLEAN: return expr; + /* Should not hit expression type condition, since crush_cmps is only + * called during expr_normalize, after expr_simplify which resolves + * all conditions. */ + case EXPR_T_CONDITION: default: OVS_NOT_REACHED(); } @@ -2441,8 +2561,13 @@ expr_normalize(struct expr *expr) case EXPR_T_BOOLEAN: return expr; + + /* Should not hit expression type condition, since expr_normalize is + * only called after expr_simplify, which resolves all conditions. */ + case EXPR_T_CONDITION: + default: + OVS_NOT_REACHED(); } - OVS_NOT_REACHED(); } /* Creates, initializes, and returns a new 'struct expr_match'. If 'm' is @@ -2609,6 +2734,8 @@ add_conjunction(const struct expr *and, break; case EXPR_T_AND: case EXPR_T_BOOLEAN: + case EXPR_T_CONDITION: + default: OVS_NOT_REACHED(); } } @@ -2740,6 +2867,12 @@ expr_to_matches(const struct expr *expr, /* No match. */ } break; + + /* Should not hit expression type condition, since expr_to_matches is + * only called after expr_simplify, which resolves all conditions. */ + case EXPR_T_CONDITION: + default: + OVS_NOT_REACHED(); } return n_conjs; } @@ -2816,6 +2949,7 @@ expr_honors_invariants(const struct expr *expr) return true; case EXPR_T_BOOLEAN: + case EXPR_T_CONDITION: return true; default: @@ -2864,6 +2998,9 @@ expr_is_normalized(const struct expr *expr) case EXPR_T_BOOLEAN: return true; + case EXPR_T_CONDITION: + return false; + default: OVS_NOT_REACHED(); } @@ -2956,6 +3093,11 @@ expr_evaluate(const struct expr *e, const struct flow *uflow, case EXPR_T_BOOLEAN: return e->boolean; + case EXPR_T_CONDITION: + /* Assume tests calling expr_evaluate are not chassis specific, so + * is_chassis_resident evaluates as true. */ + return (e->cond.not ? false : true); + default: OVS_NOT_REACHED(); } @@ -3029,7 +3171,9 @@ expr_parse_microflow__(struct lexer *lexer, struct ds annotated = DS_EMPTY_INITIALIZER; expr_format(e, &annotated); - e = expr_simplify(e); + /* Assume tests calling expr_parse_microflow are not chassis specific, so + * is_chassis_resident need not be supplied and should return true. */ + e = expr_simplify(e, NULL, NULL); e = expr_normalize(e); struct match m = MATCH_CATCHALL_INITIALIZER; @@ -3065,6 +3209,9 @@ expr_parse_microflow__(struct lexer *lexer, } break; + /* Should not hit expression type condition, since + * expr_simplify was called above. */ + case EXPR_T_CONDITION: default: OVS_NOT_REACHED(); } diff --git a/ovn/utilities/ovn-trace.c b/ovn/utilities/ovn-trace.c index 6d8e514..b5100ba 100644 --- a/ovn/utilities/ovn-trace.c +++ b/ovn/utilities/ovn-trace.c @@ -563,6 +563,25 @@ read_address_sets(void) } } +static bool +ovntrace_is_chassis_resident(const void *ports_ OVS_UNUSED, + const char *port_name) +{ + if (port_name[0] == '\0') { + return true; + } + + const struct ovntrace_port *port = shash_find_data(&ports, port_name); + if (port) { + /* Since ovntrace is not chassis specific, assume any port + * that exists is resident. */ + return true; + } + + VLOG_WARN("%s: unknown logical port\n", port_name); + return false; +} + static int compare_flow(const void *a_, const void *b_) { @@ -640,7 +659,7 @@ read_flows(void) continue; } if (match) { - match = expr_simplify(match); + match = expr_simplify(match, ovntrace_is_chassis_resident, &ports); } struct ovntrace_flow *flow = xzalloc(sizeof *flow); diff --git a/tests/ovn.at b/tests/ovn.at index 557b2ca..55b7e9a 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -453,6 +453,20 @@ AT_CHECK([simplify 'tcp.dst < 65535'], [0], ]]) AT_CLEANUP +AT_SETUP([ovn -- is_chassis_resident simplification]) +simplify() { + echo "$1" | ovstest test-ovn simplify-expr +} +AT_CHECK([simplify 'is_chassis_resident("eth1")'], [0], [1 +]) +AT_CHECK([simplify 'is_chassis_resident("eth2")'], [0], [0 +]) +AT_CHECK([simplify '!is_chassis_resident("eth1")'], [0], [0 +]) +AT_CHECK([simplify '!is_chassis_resident("eth2")'], [0], [1 +]) +AT_CLEANUP + AT_SETUP([ovn -- 4-term numeric expression normalization]) AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=3 --svars=0 --bits=1 4], [0], [Tested normalizing 1874026 expressions of 4 terminals with 3 numeric vars (each 1 bits) in terms of operators == != < <= > >=. diff --git a/tests/test-ovn.c b/tests/test-ovn.c index 2e82a6f..3d80954 100644 --- a/tests/test-ovn.c +++ b/tests/test-ovn.c @@ -219,6 +219,17 @@ lookup_port_cb(const void *ports_, const char *port_name, unsigned int *portp) return true; } +static bool +is_chassis_resident_cb(const void *ports_, const char *port_name) +{ + const struct simap *ports = ports_; + const struct simap_node *node = simap_find(ports, port_name); + if (node) { + return true; + } + return false; +} + static void test_parse_expr__(int steps) { @@ -246,7 +257,7 @@ test_parse_expr__(int steps) } if (!error) { if (steps > 1) { - expr = expr_simplify(expr); + expr = expr_simplify(expr, is_chassis_resident_cb, &ports); } if (steps > 2) { expr = expr_normalize(expr); @@ -837,7 +848,7 @@ test_tree_shape_exhaustively(struct expr *expr, struct shash *symtab, exit(EXIT_FAILURE); } } else if (operation >= OP_SIMPLIFY) { - modified = expr_simplify(expr_clone(expr)); + modified = expr_simplify(expr_clone(expr), NULL, NULL); ovs_assert(expr_honors_invariants(modified)); if (operation >= OP_NORMALIZE) {