From patchwork Wed Feb 9 06:37:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 1590210 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4Jtr5v5Wyvz9sCD for ; Wed, 9 Feb 2022 17:47:15 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 2E32683265; Wed, 9 Feb 2022 06:47:13 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Srs-_enXtb9V; Wed, 9 Feb 2022 06:47:09 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id 6E6BC8317B; Wed, 9 Feb 2022 06:47:08 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 7A16EC0072; Wed, 9 Feb 2022 06:47:06 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 97A79C000B for ; Wed, 9 Feb 2022 06:47:04 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 860E082BE5 for ; Wed, 9 Feb 2022 06:47:04 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id yIzNYprzL_jB for ; Wed, 9 Feb 2022 06:47:03 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from mslow1.mail.gandi.net (mslow1.mail.gandi.net [217.70.178.240]) by smtp1.osuosl.org (Postfix) with ESMTPS id C394082BC3 for ; Wed, 9 Feb 2022 06:47:02 +0000 (UTC) Received: from relay9-d.mail.gandi.net (unknown [IPv6:2001:4b98:dc4:8::229]) by mslow1.mail.gandi.net (Postfix) with ESMTP id C0689C58B4 for ; Wed, 9 Feb 2022 06:37:45 +0000 (UTC) Received: (Authenticated sender: hzhou@ovn.org) by mail.gandi.net (Postfix) with ESMTPSA id 54BA4FF805; Wed, 9 Feb 2022 06:37:40 +0000 (UTC) From: Han Zhou To: dev@openvswitch.org Date: Tue, 8 Feb 2022 22:37:18 -0800 Message-Id: <20220209063726.1134827-4-hzhou@ovn.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220209063726.1134827-1-hzhou@ovn.org> References: <20220209063726.1134827-1-hzhou@ovn.org> MIME-Version: 1.0 Subject: [ovs-dev] [PATCH ovn 03/11] ovn-controller: Track individual IP information of address set during lflow parsing. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" This patch tracks individual address information when parsing address sets from logical flows, and link to the corresponding desired flow resulted from the IP. Signed-off-by: Han Zhou --- controller/lflow.c | 19 ++++-- controller/ofctrl.c | 130 ++++++++++++++++++++++++++++++++++++++---- controller/ofctrl.h | 19 ++++-- controller/physical.c | 2 +- include/ovn/expr.h | 9 +++ lib/expr.c | 81 ++++++++++++++++++++------ 6 files changed, 224 insertions(+), 36 deletions(-) diff --git a/controller/lflow.c b/controller/lflow.c index b976c7d56..965e91cce 100644 --- a/controller/lflow.c +++ b/controller/lflow.c @@ -692,13 +692,23 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, } } } + + struct addrset_info as_info = { + .name = m->as_name, + .ip = m->as_ip, + .mask = m->as_mask + }; if (!m->n) { ofctrl_add_flow_metered(l_ctx_out->flow_table, ptable, lflow->priority, lflow->header_.uuid.parts[0], &m->match, &ofpacts, &lflow->header_.uuid, - ctrl_meter_id); + ctrl_meter_id, + as_info.name ? &as_info : NULL); } else { + if (m->n > 1) { + ovs_assert(!as_info.name); + } uint64_t conj_stubs[64 / 8]; struct ofpbuf conj; @@ -716,7 +726,8 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, ofctrl_add_or_append_flow(l_ctx_out->flow_table, ptable, lflow->priority, 0, &m->match, &conj, &lflow->header_.uuid, - ctrl_meter_id); + ctrl_meter_id, + as_info.name ? &as_info : NULL); ofpbuf_uninit(&conj); } } @@ -1524,7 +1535,7 @@ add_lb_ct_snat_hairpin_dp_flows(struct ovn_controller_lb *lb, ofctrl_add_or_append_flow(flow_table, OFTABLE_CT_SNAT_HAIRPIN, 200, lb->slb->header_.uuid.parts[0], &dp_match, &dp_acts, &lb->slb->header_.uuid, - NX_CTLR_NO_METER); + NX_CTLR_NO_METER, NULL); } ofpbuf_uninit(&dp_acts); @@ -1698,7 +1709,7 @@ add_lb_ct_snat_hairpin_vip_flow(struct ovn_controller_lb *lb, ofctrl_add_or_append_flow(flow_table, OFTABLE_CT_SNAT_HAIRPIN, priority, lb->slb->header_.uuid.parts[0], &match, &ofpacts, &lb->slb->header_.uuid, - NX_CTLR_NO_METER); + NX_CTLR_NO_METER, NULL); ofpbuf_uninit(&ofpacts); } diff --git a/controller/ofctrl.c b/controller/ofctrl.c index bcd6cea79..7671a3b7a 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -165,15 +165,35 @@ struct sb_to_flow { struct uuid sb_uuid; struct ovs_list flows; /* A list of struct sb_flow_ref nodes that are referenced by the sb_uuid. */ + struct ovs_list addrsets; /* A list of struct sb_addrset_ref. */ }; struct sb_flow_ref { struct ovs_list sb_list; /* List node in desired_flow.references. */ - struct ovs_list flow_list; /* List node in sb_to_flow.desired_flows. */ + struct ovs_list flow_list; /* List node in sb_to_flow.flows. */ + struct ovs_list as_ip_flow_list; /* List node in ip_to_flow_node.flows. */ struct desired_flow *flow; struct uuid sb_uuid; }; +struct sb_addrset_ref { + struct ovs_list list_node; /* List node in sb_to_flow.addrsets. */ + char *name; /* Name of the address set. */ + struct hmap ip_to_flow_map; /* map from IPs in the address set to flows. + Each node is struct ip_to_flow_node. */ +}; + +struct ip_to_flow_node { + struct hmap_node hmap_node; /* Node in sb_addrset_ref.ip_to_flow_map. */ + struct in6_addr as_ip; + struct in6_addr as_mask; + + /* A list of struct sb_flow_ref. A single IP in an address set can be + * used by multiple flows. e.g., in match: + * ip.src == $as1 && ip.dst == $as1. */ + struct ovs_list flows; +}; + /* An installed flow, in static variable installed_lflows/installed_pflows. * * Installed flows are updated in ofctrl_put for maintaining the flow @@ -1030,9 +1050,26 @@ sb_to_flow_find(struct hmap *uuid_flow_table, const struct uuid *sb_uuid) return NULL; } +static struct ip_to_flow_node * +ip_to_flow_find(struct hmap *ip_to_flow_map, const struct in6_addr *as_ip, + const struct in6_addr *as_mask) +{ + uint32_t hash = hash_bytes(as_ip, sizeof *as_ip, 0); + + struct ip_to_flow_node *itfn; + HMAP_FOR_EACH_WITH_HASH (itfn, hmap_node, hash, ip_to_flow_map) { + if (ipv6_addr_equals(&itfn->as_ip, as_ip) + && ipv6_addr_equals(&itfn->as_mask, as_mask)) { + return itfn; + } + } + return NULL; +} + static void link_flow_to_sb(struct ovn_desired_flow_table *flow_table, - struct desired_flow *f, const struct uuid *sb_uuid) + struct desired_flow *f, const struct uuid *sb_uuid, + const struct addrset_info *as_info) { struct sb_flow_ref *sfr = xmalloc(sizeof *sfr); mem_stats.sb_flow_ref_usage += sb_flow_ref_size(sfr); @@ -1046,10 +1083,48 @@ link_flow_to_sb(struct ovn_desired_flow_table *flow_table, mem_stats.sb_flow_ref_usage += sb_to_flow_size(stf); stf->sb_uuid = *sb_uuid; ovs_list_init(&stf->flows); + ovs_list_init(&stf->addrsets); hmap_insert(&flow_table->uuid_flow_table, &stf->hmap_node, uuid_hash(sb_uuid)); } ovs_list_insert(&stf->flows, &sfr->flow_list); + + if (!as_info) { + ovs_list_init(&sfr->as_ip_flow_list); + return; + } + + /* link flow to address_set + ip */ + struct sb_addrset_ref *sar; + bool found = false; + LIST_FOR_EACH (sar, list_node, &stf->addrsets) { + if (!strcmp(sar->name, as_info->name)) { + found = true; + break; + } + } + if (!found) { + sar = xmalloc(sizeof *sar); + mem_stats.sb_flow_ref_usage += sizeof *sar; + sar->name = xstrdup(as_info->name); + hmap_init(&sar->ip_to_flow_map); + ovs_list_insert(&stf->addrsets, &sar->list_node); + } + + struct ip_to_flow_node * itfn = ip_to_flow_find(&sar->ip_to_flow_map, + &as_info->ip, + &as_info->mask); + if (!itfn) { + itfn = xmalloc(sizeof *itfn); + mem_stats.sb_flow_ref_usage += sizeof *itfn; + itfn->as_ip = as_info->ip; + itfn->as_mask = as_info->mask; + ovs_list_init(&itfn->flows); + uint32_t hash = hash_bytes(&as_info->ip, sizeof as_info->ip, 0); + hmap_insert(&sar->ip_to_flow_map, &itfn->hmap_node, hash); + } + + ovs_list_insert(&itfn->flows, &sfr->as_ip_flow_list); } /* Flow table interfaces to the rest of ovn-controller. */ @@ -1068,13 +1143,17 @@ link_flow_to_sb(struct ovn_desired_flow_table *flow_table, void ofctrl_check_and_add_flow_metered(struct ovn_desired_flow_table *flow_table, uint8_t table_id, uint16_t priority, - uint64_t cookie, const struct match *match, + uint64_t cookie, + const struct match *match, const struct ofpbuf *actions, const struct uuid *sb_uuid, - uint32_t meter_id, bool log_duplicate_flow) + uint32_t meter_id, + const struct addrset_info *as_info, + bool log_duplicate_flow) { struct desired_flow *f = desired_flow_alloc(table_id, priority, cookie, - match, actions, meter_id); + match, actions, + meter_id); if (desired_flow_lookup_check_uuid(flow_table, &f->flow, sb_uuid)) { if (log_duplicate_flow) { @@ -1091,7 +1170,7 @@ ofctrl_check_and_add_flow_metered(struct ovn_desired_flow_table *flow_table, hmap_insert(&flow_table->match_flow_table, &f->match_hmap_node, f->flow.hash); - link_flow_to_sb(flow_table, f, sb_uuid); + link_flow_to_sb(flow_table, f, sb_uuid, as_info); track_flow_add_or_modify(flow_table, f); ovn_flow_log(&f->flow, "ofctrl_add_flow"); } @@ -1103,7 +1182,7 @@ ofctrl_add_flow(struct ovn_desired_flow_table *desired_flows, const struct uuid *sb_uuid) { ofctrl_add_flow_metered(desired_flows, table_id, priority, cookie, - match, actions, sb_uuid, NX_CTLR_NO_METER); + match, actions, sb_uuid, NX_CTLR_NO_METER, NULL); } void @@ -1111,11 +1190,12 @@ ofctrl_add_flow_metered(struct ovn_desired_flow_table *desired_flows, uint8_t table_id, uint16_t priority, uint64_t cookie, const struct match *match, const struct ofpbuf *actions, - const struct uuid *sb_uuid, uint32_t meter_id) + const struct uuid *sb_uuid, uint32_t meter_id, + const struct addrset_info *as_info) { ofctrl_check_and_add_flow_metered(desired_flows, table_id, priority, cookie, match, actions, sb_uuid, - meter_id, true); + meter_id, as_info, true); } /* Either add a new flow, or append actions on an existing flow. If the @@ -1127,7 +1207,8 @@ ofctrl_add_or_append_flow(struct ovn_desired_flow_table *desired_flows, const struct match *match, const struct ofpbuf *actions, const struct uuid *sb_uuid, - uint32_t meter_id) + uint32_t meter_id, + const struct addrset_info *as_info) { struct desired_flow *existing; struct desired_flow *f; @@ -1156,11 +1237,20 @@ ofctrl_add_or_append_flow(struct ovn_desired_flow_table *desired_flows, ofpbuf_uninit(&compound); desired_flow_destroy(f); f = existing; + + /* Remove as_info tracking for the existing flow. */ + struct sb_flow_ref *sfr; + LIST_FOR_EACH (sfr, sb_list, &f->references) { + ovs_list_remove(&sfr->as_ip_flow_list); + ovs_list_init(&sfr->as_ip_flow_list); + } + /* Link to sb but don't track the as_info. */ + link_flow_to_sb(desired_flows, f, sb_uuid, NULL); } else { hmap_insert(&desired_flows->match_flow_table, &f->match_hmap_node, f->flow.hash); + link_flow_to_sb(desired_flows, f, sb_uuid, as_info); } - link_flow_to_sb(desired_flows, f, sb_uuid); track_flow_add_or_modify(desired_flows, f); if (existing) { @@ -1269,6 +1359,7 @@ remove_flows_from_sb_to_flow(struct ovn_desired_flow_table *flow_table, LIST_FOR_EACH_SAFE (sfr, next, flow_list, &stf->flows) { ovs_list_remove(&sfr->sb_list); ovs_list_remove(&sfr->flow_list); + ovs_list_remove(&sfr->as_ip_flow_list); struct desired_flow *f = sfr->flow; mem_stats.sb_flow_ref_usage -= sb_flow_ref_size(sfr); free(sfr); @@ -1286,6 +1377,22 @@ remove_flows_from_sb_to_flow(struct ovn_desired_flow_table *flow_table, } } + struct sb_addrset_ref *sar, *next_sar; + LIST_FOR_EACH_SAFE (sar, next_sar, list_node, &stf->addrsets) { + ovs_list_remove(&sar->list_node); + struct ip_to_flow_node *itfn, *itfn_next; + HMAP_FOR_EACH_SAFE (itfn, itfn_next, hmap_node, &sar->ip_to_flow_map) { + hmap_remove(&sar->ip_to_flow_map, &itfn->hmap_node); + ovs_assert(ovs_list_is_empty(&itfn->flows)); + mem_stats.sb_flow_ref_usage -= sizeof *itfn; + free(itfn); + } + hmap_destroy(&sar->ip_to_flow_map); + mem_stats.sb_flow_ref_usage -= (sizeof *sar + strlen(sar->name) + 1); + free(sar->name); + free(sar); + } + hmap_remove(&flow_table->uuid_flow_table, &stf->hmap_node); mem_stats.sb_flow_ref_usage -= sb_to_flow_size(stf); free(stf); @@ -1300,6 +1407,7 @@ remove_flows_from_sb_to_flow(struct ovn_desired_flow_table *flow_table, ovs_assert(!ovs_list_is_empty(&f->references)); LIST_FOR_EACH (sfr, sb_list, &f->references) { ovs_list_remove(&sfr->flow_list); + ovs_list_remove(&sfr->as_ip_flow_list); } } LIST_FOR_EACH_SAFE (f, f_next, list_node, &to_be_removed) { diff --git a/controller/ofctrl.h b/controller/ofctrl.h index 014de210d..4ec328c24 100644 --- a/controller/ofctrl.h +++ b/controller/ofctrl.h @@ -71,24 +71,34 @@ char *ofctrl_inject_pkt(const struct ovsrec_bridge *br_int, const struct shash *port_groups); /* Flow table interfaces to the rest of ovn-controller. */ + +/* Information of IP of an address set used to track a flow that is generated + * from a logical flow referencing address set(s). */ +struct addrset_info { + const char *name; /* The address set's name. */ + struct in6_addr ip; /* An IP in the address set. */ + struct in6_addr mask; /* The mask of the IP. */ +}; void ofctrl_add_flow(struct ovn_desired_flow_table *, uint8_t table_id, uint16_t priority, uint64_t cookie, const struct match *, const struct ofpbuf *ofpacts, const struct uuid *); -void ofctrl_add_or_append_flow(struct ovn_desired_flow_table *desired_flows, +void ofctrl_add_or_append_flow(struct ovn_desired_flow_table *, uint8_t table_id, uint16_t priority, - uint64_t cookie, const struct match *match, + uint64_t cookie, const struct match *, const struct ofpbuf *actions, const struct uuid *sb_uuid, - uint32_t meter_id); + uint32_t meter_id, + const struct addrset_info *); void ofctrl_add_flow_metered(struct ovn_desired_flow_table *desired_flows, uint8_t table_id, uint16_t priority, uint64_t cookie, const struct match *match, const struct ofpbuf *actions, const struct uuid *sb_uuid, - uint32_t meter_id); + uint32_t meter_id, + const struct addrset_info *); /* Removes a bundles of flows from the flow table for a specific sb_uuid. The * flows are removed only if they are not referenced by any other sb_uuid(s). @@ -123,6 +133,7 @@ void ofctrl_check_and_add_flow_metered(struct ovn_desired_flow_table *, uint64_t cookie, const struct match *, const struct ofpbuf *ofpacts, const struct uuid *, uint32_t meter_id, + const struct addrset_info *, bool log_duplicate_flow); diff --git a/controller/physical.c b/controller/physical.c index 6bfa2304d..033828d57 100644 --- a/controller/physical.c +++ b/controller/physical.c @@ -835,7 +835,7 @@ put_local_common_flows(uint32_t dp_key, put_stack(MFF_IN_PORT, ofpact_put_STACK_POP(ofpacts_p)); ofctrl_check_and_add_flow_metered(flow_table, OFTABLE_SAVE_INPORT, 100, 0, &match, ofpacts_p, hc_uuid, - NX_CTLR_NO_METER, false); + NX_CTLR_NO_METER, NULL, false); } } diff --git a/include/ovn/expr.h b/include/ovn/expr.h index 3b5653f7b..5572a1071 100644 --- a/include/ovn/expr.h +++ b/include/ovn/expr.h @@ -367,6 +367,8 @@ bool expr_relop_from_token(enum lex_type type, enum expr_relop *relop); struct expr { struct ovs_list node; /* In parent EXPR_T_AND or EXPR_T_OR if any. */ enum expr_type type; /* Expression type. */ + char *as_name; /* Address set name. Null if it is not an + address set. */ union { /* EXPR_T_CMP. @@ -469,6 +471,11 @@ struct expr_match { struct match match; struct cls_conjunction *conjunctions; size_t n, allocated; + + /* Tracked address set information. */ + char *as_name; + struct in6_addr as_ip; + struct in6_addr as_mask; }; uint32_t expr_to_matches(const struct expr *, @@ -526,6 +533,8 @@ struct expr_constant_set { 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 *as_name; /* Name of an address set. It is NULL if not + an address set. */ }; bool expr_constant_set_parse(struct lexer *, struct expr_constant_set *); diff --git a/lib/expr.c b/lib/expr.c index 5fc6c1ce9..af083190f 100644 --- a/lib/expr.c +++ b/lib/expr.c @@ -160,7 +160,7 @@ expr_relop_test(enum expr_relop relop, int cmp) struct expr * expr_create_andor(enum expr_type type) { - struct expr *e = xmalloc(sizeof *e); + struct expr *e = xzalloc(sizeof *e); e->type = type; ovs_list_init(&e->andor); return e; @@ -190,9 +190,17 @@ expr_combine(enum expr_type type, struct expr *a, struct expr *b) } else { ovs_list_push_back(&a->andor, &b->node); } + if (a->as_name) { + free(a->as_name); + a->as_name = NULL; + } return a; } else if (b->type == type) { ovs_list_push_front(&b->andor, &a->node); + if (b->as_name) { + free(b->as_name); + b->as_name = NULL; + } return b; } else { struct expr *e = expr_create_andor(type); @@ -220,7 +228,7 @@ expr_insert_andor(struct expr *andor, struct expr *before, struct expr *new) struct expr * expr_create_boolean(bool b) { - struct expr *e = xmalloc(sizeof *e); + struct expr *e = xzalloc(sizeof *e); e->type = EXPR_T_BOOLEAN; e->boolean = b; return e; @@ -680,6 +688,10 @@ make_cmp(struct expr_context *ctx, e = expr_combine(r == EXPR_R_EQ ? EXPR_T_OR : EXPR_T_AND, e, make_cmp__(f, r, &cs->values[i])); } + /* Track address set */ + if (r == EXPR_R_EQ && e->type == EXPR_T_OR && cs->as_name) { + e->as_name = xstrdup(cs->as_name); + } exit: expr_constant_set_destroy(cs); return e; @@ -802,6 +814,10 @@ parse_addr_sets(struct expr_context *ctx, struct expr_constant_set *cs, return false; } + if (!cs->n_values) { + cs->as_name = xstrdup(ctx->lexer->token.s); + } + size_t n_values = cs->n_values + addr_sets->n_values; if (n_values >= *allocated_values) { cs->values = xrealloc(cs->values, n_values * sizeof *cs->values); @@ -875,6 +891,13 @@ parse_constant(struct expr_context *ctx, struct expr_constant_set *cs, sizeof *cs->values); } + if (cs->as_name) { + /* Combining other values to the constant set that is tracking an + * address set, so untrack it. */ + free(cs->as_name); + cs->as_name = NULL; + } + if (ctx->lexer->token.type == LEX_T_STRING) { if (!assign_constant_set_type(ctx, cs, EXPR_C_STRING)) { return false; @@ -1057,6 +1080,7 @@ expr_constant_set_destroy(struct expr_constant_set *cs) } } free(cs->values); + free(cs->as_name); } } @@ -1244,6 +1268,7 @@ expr_parse_primary(struct expr_context *ctx, bool *atomic) c.values = cst; c.n_values = 1; c.in_curlies = false; + c.as_name = NULL; return make_cmp(ctx, &f, EXPR_R_NE, &c); } else if (parse_relop(ctx, &r) && parse_constant_set(ctx, &c)) { return make_cmp(ctx, &f, r, &c); @@ -1709,6 +1734,7 @@ expr_symtab_destroy(struct shash *symtab) static struct expr * expr_clone_cmp(struct expr *expr) { + ovs_assert(!expr->as_name); struct expr *new = xmemdup(expr, sizeof *expr); if (!new->cmp.symbol->width) { new->cmp.string = xstrdup(new->cmp.string); @@ -1732,6 +1758,7 @@ expr_clone_andor(struct expr *expr) static struct expr * expr_clone_condition(struct expr *expr) { + ovs_assert(!expr->as_name); struct expr *new = xmemdup(expr, sizeof *expr); new->cond.string = xstrdup(new->cond.string); return new; @@ -1767,6 +1794,8 @@ expr_destroy(struct expr *expr) return; } + free(expr->as_name); + struct expr *sub, *next; switch (expr->type) { @@ -2373,7 +2402,7 @@ crush_and_string(struct expr *expr, const struct expr_symbol *symbol) const char *string; SSET_FOR_EACH (string, &result) { - sub = xmalloc(sizeof *sub); + sub = xzalloc(sizeof *sub); sub->type = EXPR_T_CMP; sub->cmp.relop = EXPR_R_EQ; sub->cmp.symbol = symbol; @@ -2432,7 +2461,7 @@ crush_and_numeric(struct expr *expr, const struct expr_symbol *symbol) return expr_create_boolean(true); } else { struct expr *cmp; - cmp = xmalloc(sizeof *cmp); + cmp = xzalloc(sizeof *cmp); cmp->type = EXPR_T_CMP; cmp->cmp.symbol = symbol; cmp->cmp.relop = EXPR_R_EQ; @@ -2447,7 +2476,7 @@ crush_and_numeric(struct expr *expr, const struct expr_symbol *symbol) struct expr *disjuncts = expr_from_node(ovs_list_pop_front(&expr->andor)); struct expr *or; - or = xmalloc(sizeof *or); + or = xzalloc(sizeof *or); or->type = EXPR_T_OR; ovs_list_init(&or->andor); @@ -2483,7 +2512,7 @@ crush_and_numeric(struct expr *expr, const struct expr_symbol *symbol) struct expr *new = NULL; struct expr *or; - or = xmalloc(sizeof *or); + or = xzalloc(sizeof *or); or->type = EXPR_T_OR; ovs_list_init(&or->andor); @@ -2502,7 +2531,7 @@ crush_and_numeric(struct expr *expr, const struct expr_symbol *symbol) LIST_FOR_EACH (b, node, &bs->andor) { ovs_assert(b->type == EXPR_T_CMP); if (!new) { - new = xmalloc(sizeof *new); + new = xzalloc(sizeof *new); new->type = EXPR_T_CMP; new->cmp.symbol = symbol; new->cmp.relop = EXPR_R_EQ; @@ -2608,6 +2637,9 @@ crush_or(struct expr *expr, const struct expr_symbol *symbol) ovs_list_push_back(&expr->andor, &b->node); } else { expr_destroy(b); + /* Member modified, so untrack address set. */ + free(expr->as_name); + expr->as_name = NULL; } } free(subs); @@ -2659,7 +2691,7 @@ expr_sort(struct expr *expr) ovs_assert(expr->type == EXPR_T_AND); size_t n = ovs_list_size(&expr->andor); - struct expr_sort *subs = xmalloc(n * sizeof *subs); + struct expr_sort *subs = xzalloc(n * sizeof *subs); struct expr *sub; size_t i; @@ -2884,7 +2916,7 @@ static struct expr_match * expr_match_new(const struct match *m, uint8_t clause, uint8_t n_clauses, uint32_t conj_id) { - struct expr_match *match = xmalloc(sizeof *match); + struct expr_match *match = xzalloc(sizeof *match); if (m) { match->match = *m; } else { @@ -2905,6 +2937,14 @@ expr_match_new(const struct match *m, uint8_t clause, uint8_t n_clauses, return match; } +static void +expr_match_destroy(struct expr_match *match) +{ + free(match->as_name); + free(match->conjunctions); + free(match); +} + /* Adds 'match' to hash table 'matches', which becomes the new owner of * 'match'. * @@ -2932,8 +2972,12 @@ expr_match_add(struct hmap *matches, struct expr_match *match) } m->conjunctions[m->n++] = match->conjunctions[0]; } - free(match->conjunctions); - free(match); + if (m->as_name) { + /* m is combined with match. so untracked the address set. */ + free(m->as_name); + m->as_name = NULL; + } + expr_match_destroy(match); return; } } @@ -2994,12 +3038,18 @@ add_disjunction(const struct expr *or, LIST_FOR_EACH (sub, node, &or->andor) { struct expr_match *match = expr_match_new(m, clause, n_clauses, conj_id); + if (or->as_name) { + ovs_assert(sub->type == EXPR_T_CMP); + ovs_assert(sub->cmp.symbol->width); + match->as_name = xstrdup(or->as_name); + match->as_ip = sub->cmp.value.ipv6; + match->as_mask = sub->cmp.mask.ipv6; + } if (constrain_match(sub, lookup_port, aux, &match->match)) { expr_match_add(matches, match); n++; } else { - free(match->conjunctions); - free(match); + expr_match_destroy(match); } } @@ -3082,7 +3132,7 @@ add_cmp_flow(const struct expr *cmp, if (constrain_match(cmp, lookup_port, aux, &m->match)) { expr_match_add(matches, m); } else { - free(m); + expr_match_destroy(m); } } @@ -3214,8 +3264,7 @@ expr_matches_destroy(struct hmap *matches) } HMAP_FOR_EACH_POP (m, hmap_node, matches) { - free(m->conjunctions); - free(m); + expr_match_destroy(m); } hmap_destroy(matches); }