From patchwork Sat Nov 14 07:56:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilya Maximets X-Patchwork-Id: 1400237 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.137; helo=fraxinus.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ovn.org Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CY73f0W9tz9sRK for ; Sat, 14 Nov 2020 18:57:34 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 5EADE8767C; Sat, 14 Nov 2020 07:57:32 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id rnXomhlkZ65A; Sat, 14 Nov 2020 07:57:25 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by fraxinus.osuosl.org (Postfix) with ESMTP id 490D087650; Sat, 14 Nov 2020 07:57:25 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1B49CC1DAA; Sat, 14 Nov 2020 07:57:25 +0000 (UTC) X-Original-To: ovs-dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 6E43EC0800 for ; Sat, 14 Nov 2020 07:57:23 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id 51E562E2EA for ; Sat, 14 Nov 2020 07:57:23 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from silver.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id pGNhwrh0b8lP for ; Sat, 14 Nov 2020 07:57:12 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by silver.osuosl.org (Postfix) with ESMTPS id 6735E204E9 for ; Sat, 14 Nov 2020 07:57:07 +0000 (UTC) X-Originating-IP: 78.45.89.65 Received: from im-t490s.redhat.com (ip-78-45-89-65.net.upcbroadband.cz [78.45.89.65]) (Authenticated sender: i.maximets@ovn.org) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 10708FF805; Sat, 14 Nov 2020 07:57:04 +0000 (UTC) From: Ilya Maximets To: ovs-dev@openvswitch.org Date: Sat, 14 Nov 2020 08:56:50 +0100 Message-Id: <20201114075653.9142-4-i.maximets@ovn.org> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20201114075653.9142-1-i.maximets@ovn.org> References: <20201114075653.9142-1-i.maximets@ovn.org> MIME-Version: 1.0 Cc: Ilya Maximets Subject: [ovs-dev] [PATCH ovn 3/6] northd: Add support for Logical Datapath Groups. 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" Signed-off-by: Ilya Maximets --- lib/ovn-util.c | 14 +--- lib/ovn-util.h | 3 +- northd/ovn-northd.c | 166 ++++++++++++++++++++++++++++++++++---------- 3 files changed, 133 insertions(+), 50 deletions(-) diff --git a/lib/ovn-util.c b/lib/ovn-util.c index 18aac8da3..a7fdd431d 100644 --- a/lib/ovn-util.c +++ b/lib/ovn-util.c @@ -504,24 +504,16 @@ ovn_is_known_nb_lsp_type(const char *type) uint32_t sbrec_logical_flow_hash(const struct sbrec_logical_flow *lf) { - const struct sbrec_datapath_binding *ld = lf->logical_datapath; - if (!ld) { - return 0; - } - - return ovn_logical_flow_hash(&ld->header_.uuid, - lf->table_id, lf->pipeline, + return ovn_logical_flow_hash(lf->table_id, lf->pipeline, lf->priority, lf->match, lf->actions); } uint32_t -ovn_logical_flow_hash(const struct uuid *logical_datapath, - uint8_t table_id, const char *pipeline, +ovn_logical_flow_hash(uint8_t table_id, const char *pipeline, uint16_t priority, const char *match, const char *actions) { - size_t hash = uuid_hash(logical_datapath); - hash = hash_2words((table_id << 16) | priority, hash); + size_t hash = hash_2words((table_id << 16) | priority, 0); hash = hash_string(pipeline, hash); hash = hash_string(match, hash); return hash_string(actions, hash); diff --git a/lib/ovn-util.h b/lib/ovn-util.h index 3496673b2..9262b05e4 100644 --- a/lib/ovn-util.h +++ b/lib/ovn-util.h @@ -102,8 +102,7 @@ const char *db_table_usage(struct ds *tables, bool ovn_is_known_nb_lsp_type(const char *type); uint32_t sbrec_logical_flow_hash(const struct sbrec_logical_flow *); -uint32_t ovn_logical_flow_hash(const struct uuid *logical_datapath, - uint8_t table_id, const char *pipeline, +uint32_t ovn_logical_flow_hash(uint8_t table_id, const char *pipeline, uint16_t priority, const char *match, const char *actions); bool datapath_is_switch(const struct sbrec_datapath_binding *); diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 4d4190cb9..782a539dc 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -25,6 +25,7 @@ #include "openvswitch/dynamic-string.h" #include "fatal-signal.h" #include "hash.h" +#include "hmapx.h" #include "openvswitch/hmap.h" #include "openvswitch/json.h" #include "ovn/lex.h" @@ -4174,7 +4175,7 @@ ovn_igmp_group_destroy(struct hmap *igmp_groups, struct ovn_lflow { struct hmap_node hmap_node; - struct ovn_datapath *od; + struct hmapx od; /* Hash map of 'struct ovn_datapath *'. */ enum ovn_stage stage; uint16_t priority; char *match; @@ -4186,8 +4187,7 @@ struct ovn_lflow { static size_t ovn_lflow_hash(const struct ovn_lflow *lflow) { - return ovn_logical_flow_hash(&lflow->od->sb->header_.uuid, - ovn_stage_get_table(lflow->stage), + return ovn_logical_flow_hash(ovn_stage_get_table(lflow->stage), ovn_stage_get_pipeline_name(lflow->stage), lflow->priority, lflow->match, lflow->actions); @@ -4205,20 +4205,19 @@ ovn_lflow_hint(const struct ovsdb_idl_row *row) static bool ovn_lflow_equal(const struct ovn_lflow *a, const struct ovn_lflow *b) { - return (a->od == b->od - && a->stage == b->stage + return (a->stage == b->stage && a->priority == b->priority && !strcmp(a->match, b->match) && !strcmp(a->actions, b->actions)); } static void -ovn_lflow_init(struct ovn_lflow *lflow, struct ovn_datapath *od, +ovn_lflow_init(struct ovn_lflow *lflow, enum ovn_stage stage, uint16_t priority, char *match, char *actions, char *stage_hint, const char *where) { - lflow->od = od; + hmapx_init(&lflow->od); lflow->stage = stage; lflow->priority = priority; lflow->match = match; @@ -4227,6 +4226,34 @@ ovn_lflow_init(struct ovn_lflow *lflow, struct ovn_datapath *od, lflow->where = where; } +static void +ovn_lflow_destroy(struct hmap *lflows, struct ovn_lflow *lflow) +{ + if (lflow) { + if (lflows) { + hmap_remove(lflows, &lflow->hmap_node); + } + hmapx_destroy(&lflow->od); + free(lflow->match); + free(lflow->actions); + free(lflow->stage_hint); + free(lflow); + } +} + +static struct ovn_lflow * +ovn_lflow_find_by_lflow(const struct hmap *lflows, + const struct ovn_lflow *target, size_t hash) +{ + struct ovn_lflow *lflow; + HMAP_FOR_EACH_WITH_HASH (lflow, hmap_node, hash, lflows) { + if (ovn_lflow_equal(lflow, target)) { + return lflow; + } + } + return NULL; +} + /* Adds a row with the specified contents to the Logical_Flow table. */ static void ovn_lflow_add_at(struct hmap *lflow_map, struct ovn_datapath *od, @@ -4236,11 +4263,23 @@ ovn_lflow_add_at(struct hmap *lflow_map, struct ovn_datapath *od, { ovs_assert(ovn_stage_to_datapath_type(stage) == ovn_datapath_get_type(od)); - struct ovn_lflow *lflow = xmalloc(sizeof *lflow); - ovn_lflow_init(lflow, od, stage, priority, + struct ovn_lflow *old_lflow, *lflow; + size_t hash; + + lflow = xmalloc(sizeof *lflow); + ovn_lflow_init(lflow, stage, priority, xstrdup(match), xstrdup(actions), ovn_lflow_hint(stage_hint), where); - hmap_insert(lflow_map, &lflow->hmap_node, ovn_lflow_hash(lflow)); + + hash = ovn_lflow_hash(lflow); + old_lflow = ovn_lflow_find_by_lflow(lflow_map, lflow, hash); + if (old_lflow) { + ovn_lflow_destroy(NULL, lflow); + hmapx_add(&old_lflow->od, od); + } else { + hmapx_add(&lflow->od, od); + hmap_insert(lflow_map, &lflow->hmap_node, hash); + } } /* Adds a row with the specified contents to the Logical_Flow table. */ @@ -4254,34 +4293,16 @@ ovn_lflow_add_at(struct hmap *lflow_map, struct ovn_datapath *od, ACTIONS, NULL) static struct ovn_lflow * -ovn_lflow_find(struct hmap *lflows, struct ovn_datapath *od, +ovn_lflow_find(struct hmap *lflows, enum ovn_stage stage, uint16_t priority, const char *match, const char *actions, uint32_t hash) { struct ovn_lflow target; - ovn_lflow_init(&target, od, stage, priority, + ovn_lflow_init(&target, stage, priority, CONST_CAST(char *, match), CONST_CAST(char *, actions), NULL, NULL); - struct ovn_lflow *lflow; - HMAP_FOR_EACH_WITH_HASH (lflow, hmap_node, hash, lflows) { - if (ovn_lflow_equal(lflow, &target)) { - return lflow; - } - } - return NULL; -} - -static void -ovn_lflow_destroy(struct hmap *lflows, struct ovn_lflow *lflow) -{ - if (lflow) { - hmap_remove(lflows, &lflow->hmap_node); - free(lflow->match); - free(lflow->actions); - free(lflow->stage_hint); - free(lflow); - } + return ovn_lflow_find_by_lflow(lflows, &target, hash); } /* Appends port security constraints on L2 address field 'eth_addr_field' @@ -11295,6 +11316,28 @@ build_lswitch_and_lrouter_flows(struct hmap *datapaths, struct hmap *ports, } +static void +ovn_sb_set_lflow_logical_datapath_group( + struct northd_context *ctx, + const struct sbrec_logical_flow *sbflow, + const struct hmapx *od) +{ + struct sbrec_logical_datapath_group *dp_group; + const struct sbrec_datapath_binding **sb; + const struct hmapx_node *node; + int n = 0; + + sb = xmalloc(hmapx_count(od) * sizeof *sb); + HMAPX_FOR_EACH (node, od) { + sb[n++] = ((struct ovn_datapath *) node->data)->sb; + } + dp_group = sbrec_logical_datapath_group_insert(ctx->ovnsb_txn); + sbrec_logical_datapath_group_set_datapaths( + dp_group, (struct sbrec_datapath_binding **) sb, n); + free(sb); + sbrec_logical_flow_set_logical_datapath_group(sbflow, dp_group); +} + /* Updates the Logical_Flow and Multicast_Group tables in the OVN_SB database, * constructing their contents based on the OVN_NB database. */ static void @@ -11313,25 +11356,67 @@ build_lflows(struct northd_context *ctx, struct hmap *datapaths, /* Push changes to the Logical_Flow table to database. */ const struct sbrec_logical_flow *sbflow, *next_sbflow; SBREC_LOGICAL_FLOW_FOR_EACH_SAFE (sbflow, next_sbflow, ctx->ovnsb_idl) { - struct ovn_datapath *od - = ovn_datapath_from_sbrec(datapaths, sbflow->logical_datapath); + struct sbrec_logical_datapath_group *dp_group + = sbflow->logical_datapath_group; + struct ovn_datapath **od = xmalloc(dp_group->n_datapaths * sizeof *od); + enum ovn_datapath_type dp_type; + int n_valid_datapaths = 0; + size_t i; + + /* Check all logical datapaths from the group. */ + for (i = 0; i < dp_group->n_datapaths; i++) { + od[i] = ovn_datapath_from_sbrec(datapaths, dp_group->datapaths[i]); + if (!od[i] || ovn_datapath_is_stale(od[i])) { + od[i] = NULL; + continue; + } + n_valid_datapaths++; + dp_type = od[i]->nbs ? DP_SWITCH : DP_ROUTER; + } - if (!od || ovn_datapath_is_stale(od)) { + if (!n_valid_datapaths) { + /* This lflow has no valid logical datapaths. */ + sbrec_logical_datapath_group_delete(dp_group); sbrec_logical_flow_delete(sbflow); + free(od); continue; } - enum ovn_datapath_type dp_type = od->nbs ? DP_SWITCH : DP_ROUTER; enum ovn_pipeline pipeline = !strcmp(sbflow->pipeline, "ingress") ? P_IN : P_OUT; struct ovn_lflow *lflow = ovn_lflow_find( - &lflows, od, ovn_stage_build(dp_type, pipeline, sbflow->table_id), + &lflows, ovn_stage_build(dp_type, pipeline, sbflow->table_id), sbflow->priority, sbflow->match, sbflow->actions, sbflow->hash); + if (lflow) { + /* This is a valid lflow. Checking if the datapath group needs + * updates. */ + bool update_datapath_group = false; + + if (dp_group->n_datapaths != hmapx_count(&lflow->od)) { + update_datapath_group = true; + } else { + for (i = 0; i < dp_group->n_datapaths; i++) { + if (od[i] && !hmapx_contains(&lflow->od, od[i])) { + update_datapath_group = true; + break; + } + } + } + + if (update_datapath_group) { + /* Re-creating datapath group since there are changes. */ + sbrec_logical_datapath_group_delete(dp_group); + ovn_sb_set_lflow_logical_datapath_group(ctx, + sbflow, &lflow->od); + } + /* This lflow updated. Not needed anymore. */ ovn_lflow_destroy(&lflows, lflow); } else { + sbrec_logical_datapath_group_delete(dp_group); sbrec_logical_flow_delete(sbflow); } + free(od); } struct ovn_lflow *lflow, *next_lflow; HMAP_FOR_EACH_SAFE (lflow, next_lflow, hmap_node, &lflows) { @@ -11339,7 +11424,7 @@ build_lflows(struct northd_context *ctx, struct hmap *datapaths, uint8_t table = ovn_stage_get_table(lflow->stage); sbflow = sbrec_logical_flow_insert(ctx->ovnsb_txn); - sbrec_logical_flow_set_logical_datapath(sbflow, lflow->od->sb); + ovn_sb_set_lflow_logical_datapath_group(ctx, sbflow, &lflow->od); sbrec_logical_flow_set_pipeline(sbflow, pipeline); sbrec_logical_flow_set_table_id(sbflow, table); sbrec_logical_flow_set_priority(sbflow, lflow->priority); @@ -12914,12 +12999,19 @@ main(int argc, char *argv[]) ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_logical_flow); add_column_noalert(ovnsb_idl_loop.idl, &sbrec_logical_flow_col_logical_datapath); + add_column_noalert(ovnsb_idl_loop.idl, + &sbrec_logical_flow_col_logical_datapath_group); add_column_noalert(ovnsb_idl_loop.idl, &sbrec_logical_flow_col_pipeline); add_column_noalert(ovnsb_idl_loop.idl, &sbrec_logical_flow_col_table_id); add_column_noalert(ovnsb_idl_loop.idl, &sbrec_logical_flow_col_priority); add_column_noalert(ovnsb_idl_loop.idl, &sbrec_logical_flow_col_match); add_column_noalert(ovnsb_idl_loop.idl, &sbrec_logical_flow_col_actions); + ovsdb_idl_add_table(ovnsb_idl_loop.idl, + &sbrec_table_logical_datapath_group); + add_column_noalert(ovnsb_idl_loop.idl, + &sbrec_logical_datapath_group_col_datapaths); + ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_multicast_group); add_column_noalert(ovnsb_idl_loop.idl, &sbrec_multicast_group_col_datapath);