From patchwork Wed Oct 21 07:25:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Numan Siddique X-Patchwork-Id: 1385725 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=whitealder.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 whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CGg6J71r9z9sRR for ; Thu, 22 Oct 2020 06:09:43 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 125CB874A4; Wed, 21 Oct 2020 19:09:41 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id JCGnEcXJHzhB; Wed, 21 Oct 2020 19:09:37 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by whitealder.osuosl.org (Postfix) with ESMTP id 7F6E086DBA; Wed, 21 Oct 2020 19:09:37 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 64BE9C088B; Wed, 21 Oct 2020 19:09:37 +0000 (UTC) X-Original-To: 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 43778C0051 for ; Wed, 21 Oct 2020 19:09:35 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id 29A082E40C for ; Wed, 21 Oct 2020 19:09:35 +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 NKm1ADUMnCMo for ; Wed, 21 Oct 2020 19:09:21 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by silver.osuosl.org (Postfix) with ESMTPS id 9842F2E50C for ; Wed, 21 Oct 2020 07:25:27 +0000 (UTC) X-Originating-IP: 27.7.140.208 Received: from nusiddiq.home.org.home.org (unknown [27.7.140.208]) (Authenticated sender: numans@ovn.org) by relay1-d.mail.gandi.net (Postfix) with ESMTPSA id E4BD424000D; Wed, 21 Oct 2020 07:25:22 +0000 (UTC) From: numans@ovn.org To: dev@openvswitch.org Date: Wed, 21 Oct 2020 12:55:13 +0530 Message-Id: <20201021072513.3750765-1-numans@ovn.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201021072447.3750661-1-numans@ovn.org> References: <20201021072447.3750661-1-numans@ovn.org> MIME-Version: 1.0 Subject: [ovs-dev] [PATCH ovn 1/5] Add new table Load_Balancer in Southbound database. 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" From: Numan Siddique This patch adds a new table 'Load_Balancer' in SB DB and syncs the Load_Balancer table rows from NB DB to SB DB. An upcoming patch will make use of this table for handling the load balancer hairpin traffic. Signed-off-by: Numan Siddique --- northd/ovn-northd.c | 141 ++++++++++++++++++++++++++++++++++++++++++ ovn-sb.ovsschema | 27 +++++++- ovn-sb.xml | 47 ++++++++++++++ tests/ovn-northd.at | 81 ++++++++++++++++++++++++ utilities/ovn-sbctl.c | 3 + 5 files changed, 297 insertions(+), 2 deletions(-) diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 5b76868dfb..ea771afda1 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -11896,6 +11896,136 @@ sync_dns_entries(struct northd_context *ctx, struct hmap *datapaths) } hmap_destroy(&dns_map); } + +/* + * struct 'sync_lb_info' is used to sync the load balancer records between + * OVN Northbound db and Southbound db. + */ +struct sync_lb_info { + struct hmap_node hmap_node; + const struct nbrec_load_balancer *nlb; /* LB record in the NB db. */ + const struct sbrec_load_balancer *slb; /* LB record in the SB db. */ + + /* Datapaths to which the LB entry is associated with it. */ + const struct sbrec_datapath_binding **sbs; + size_t n_sbs; +}; + +static inline struct sync_lb_info * +get_sync_lb_info_from_hmap(struct hmap *sync_lb_map, struct uuid *uuid) +{ + struct sync_lb_info *lb_info; + size_t hash = uuid_hash(uuid); + HMAP_FOR_EACH_WITH_HASH (lb_info, hmap_node, hash, sync_lb_map) { + if (uuid_equals(&lb_info->nlb->header_.uuid, uuid)) { + return lb_info; + } + } + + return NULL; +} + +static void +sync_lb_entries(struct northd_context *ctx, struct hmap *datapaths) +{ + struct hmap lb_map = HMAP_INITIALIZER(&lb_map); + struct ovn_datapath *od; + + HMAP_FOR_EACH (od, key_node, datapaths) { + if (!od->nbs || !od->nbs->n_load_balancer) { + continue; + } + + for (size_t i = 0; i < od->nbs->n_load_balancer; i++) { + struct sync_lb_info *lb_info = + get_sync_lb_info_from_hmap( + &lb_map, &od->nbs->load_balancer[i]->header_.uuid); + + if (!lb_info) { + size_t hash = uuid_hash( + &od->nbs->load_balancer[i]->header_.uuid); + lb_info = xzalloc(sizeof *lb_info);; + lb_info->nlb = od->nbs->load_balancer[i]; + hmap_insert(&lb_map, &lb_info->hmap_node, hash); + } + + lb_info->n_sbs++; + lb_info->sbs = xrealloc(lb_info->sbs, + lb_info->n_sbs * sizeof *lb_info->sbs); + lb_info->sbs[lb_info->n_sbs - 1] = od->sb; + } + } + + const struct sbrec_load_balancer *sbrec_lb, *next; + SBREC_LOAD_BALANCER_FOR_EACH_SAFE (sbrec_lb, next, ctx->ovnsb_idl) { + const char *nb_lb_uuid = smap_get(&sbrec_lb->external_ids, "lb_id"); + struct uuid lb_uuid; + if (!nb_lb_uuid || !uuid_from_string(&lb_uuid, nb_lb_uuid)) { + sbrec_load_balancer_delete(sbrec_lb); + continue; + } + + struct sync_lb_info *lb_info = + get_sync_lb_info_from_hmap(&lb_map, &lb_uuid); + if (lb_info) { + lb_info->slb = sbrec_lb; + } else { + sbrec_load_balancer_delete(sbrec_lb); + } + } + + struct sync_lb_info *lb_info; + HMAP_FOR_EACH (lb_info, hmap_node, &lb_map) { + if (!lb_info->slb) { + sbrec_lb = sbrec_load_balancer_insert(ctx->ovnsb_txn); + lb_info->slb = sbrec_lb; + char *lb_id = xasprintf( + UUID_FMT, UUID_ARGS(&lb_info->nlb->header_.uuid)); + const struct smap external_ids = + SMAP_CONST1(&external_ids, "lb_id", lb_id); + sbrec_load_balancer_set_external_ids(sbrec_lb, &external_ids); + free(lb_id); + } + + /* Set the datapaths and other columns. If nothing has changed, then + * this will be a no-op. + */ + sbrec_load_balancer_set_datapaths( + lb_info->slb, + (struct sbrec_datapath_binding **)lb_info->sbs, + lb_info->n_sbs); + + sbrec_load_balancer_set_name(lb_info->slb, lb_info->nlb->name); + sbrec_load_balancer_set_vips(lb_info->slb, &lb_info->nlb->vips); + sbrec_load_balancer_set_protocol(lb_info->slb, lb_info->nlb->protocol); + } + + HMAP_FOR_EACH (od, key_node, datapaths) { + if (!od->nbs || !od->nbs->n_load_balancer) { + continue; + } + + const struct sbrec_load_balancer **lbs = + xmalloc(od->nbs->n_load_balancer * sizeof *lbs); + for (size_t i = 0; i < od->nbs->n_load_balancer; i++) { + lb_info = get_sync_lb_info_from_hmap( + &lb_map, &od->nbs->load_balancer[i]->header_.uuid); + ovs_assert(lb_info); + lbs[i] = lb_info->slb; + } + + sbrec_datapath_binding_set_load_balancers( + od->sb, (struct sbrec_load_balancer **)lbs, + od->nbs->n_load_balancer); + free(lbs); + } + + HMAP_FOR_EACH_POP (lb_info, hmap_node, &lb_map) { + free(lb_info->sbs); + free(lb_info); + } + hmap_destroy(&lb_map); +} static void destroy_datapaths_and_ports(struct hmap *datapaths, struct hmap *ports, @@ -12263,6 +12393,7 @@ ovnnb_db_run(struct northd_context *ctx, sync_port_groups(ctx, &port_groups); sync_meters(ctx); sync_dns_entries(ctx, datapaths); + sync_lb_entries(ctx, datapaths); destroy_ovn_lbs(&lbs); hmap_destroy(&lbs); @@ -13022,6 +13153,8 @@ main(int argc, char *argv[]) ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_datapath_binding); add_column_noalert(ovnsb_idl_loop.idl, &sbrec_datapath_binding_col_tunnel_key); + add_column_noalert(ovnsb_idl_loop.idl, + &sbrec_datapath_binding_col_load_balancers); add_column_noalert(ovnsb_idl_loop.idl, &sbrec_datapath_binding_col_external_ids); @@ -13189,6 +13322,14 @@ main(int argc, char *argv[]) add_column_noalert(ovnsb_idl_loop.idl, &sbrec_service_monitor_col_external_ids); + ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_load_balancer); + add_column_noalert(ovnsb_idl_loop.idl, &sbrec_load_balancer_col_datapaths); + add_column_noalert(ovnsb_idl_loop.idl, &sbrec_load_balancer_col_name); + add_column_noalert(ovnsb_idl_loop.idl, &sbrec_load_balancer_col_vips); + add_column_noalert(ovnsb_idl_loop.idl, &sbrec_load_balancer_col_protocol); + add_column_noalert(ovnsb_idl_loop.idl, + &sbrec_load_balancer_col_external_ids); + struct ovsdb_idl_index *sbrec_chassis_by_name = chassis_index_create(ovnsb_idl_loop.idl); diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema index d1c506a22c..7db6c6a4dd 100644 --- a/ovn-sb.ovsschema +++ b/ovn-sb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Southbound", - "version": "2.10.0", - "cksum": "2548342632 22615", + "version": "2.11.0", + "cksum": "1470439925 23814", "tables": { "SB_Global": { "columns": { @@ -152,6 +152,11 @@ "type": {"key": {"type": "integer", "minInteger": 1, "maxInteger": 16777215}}}, + "load_balancers": {"type": {"key": {"type": "uuid", + "refTable": "Load_Balancer", + "refType": "weak"}, + "min": 0, + "max": "unlimited"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}, @@ -447,6 +452,24 @@ "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}, "indexes": [["logical_port", "ip", "port", "protocol"]], + "isRoot": true}, + "Load_Balancer": { + "columns": { + "name": {"type": "string"}, + "vips": { + "type": {"key": "string", "value": "string", + "min": 0, "max": "unlimited"}}, + "protocol": { + "type": {"key": {"type": "string", + "enum": ["set", ["tcp", "udp", "sctp"]]}, + "min": 0, "max": 1}}, + "datapaths": { + "type": {"key": {"type": "uuid", + "refTable": "Datapath_Binding"}, + "min": 1, "max": "unlimited"}}, + "external_ids": { + "type": {"key": "string", "value": "string", + "min": 0, "max": "unlimited"}}}, "isRoot": true} } } diff --git a/ovn-sb.xml b/ovn-sb.xml index 182ff0a8a2..8638fa7eb4 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -2497,6 +2497,12 @@ tcp.flags = RST; constructed for each supported encapsulation. + +

+ Load balancers associated with the datapath. +

+
+

Each row in is associated with some @@ -4104,4 +4110,45 @@ tcp.flags = RST; + + +

+ Each row represents one load balancer and corresponds directly + with the table in the + database. +

+ + + A name for the load balancer. This name has no special meaning or + purpose other than to provide convenience for human interaction with + the ovn-nb database. + + + + A map of virtual IP addresses (and an optional port number with + : as a separator) associated with this load balancer and + their corresponding endpoint IP addresses (and optional port numbers + with : as separators) separated by commas. + + + +

+ Valid protocols are tcp, udp, or + sctp. This column is useful when a port number is + provided as part of the vips column. If this column is + empty and a port number is provided as part of vips + column, OVN assumes the protocol to be tcp. +

+
+ + + Datapaths to which this load balancer applies to. + + + + + See External IDs at the beginning of this document. + + +
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 50457c291a..3dd1920b79 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -2130,3 +2130,84 @@ action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implici ]) AT_CLEANUP + +AT_SETUP([ovn -- NB to SB load balancer sync]) +ovn_start + +ovn-nbctl --wait=hv lb-add lb0 10.0.0.10:80 10.0.0.4:8080 + +AT_CHECK([ovn-nbctl --bare --columns _uuid list load_balancer | wc -l], [0], [dnl +1 +]) + +AT_CHECK([ovn-sbctl --bare --columns _uuid list load_balancer | wc -l], [0], [dnl +0 +]) + +ovn-nbctl ls-add sw0 +ovn-nbctl --wait=hv ls-lb-add sw0 lb0 +sw0_sb_uuid=$(ovn-sbctl --bare --columns _uuid list datapath sw0) +AT_CHECK([ovn-sbctl --bare --columns name,vips,protocol list load_balancer], [0], [dnl +lb0 +10.0.0.10:80=10.0.0.4:8080 +tcp +]) + +lb0_uuid=$(ovn-sbctl --bare --columns _uuid list load_balancer lb0) + +AT_CHECK([test $(ovn-sbctl --bare --columns datapaths list load_balancer) = $sw0_sb_uuid]) +AT_CHECK([test $(ovn-sbctl --bare --columns load_balancers list datapath sw0) = $lb0_uuid]) + +ovn-nbctl --wait=sb set load_balancer . vips:"10.0.0.20\:90"="20.0.0.4:8080,30.0.0.4:8080" +AT_CHECK([ovn-sbctl --bare --columns name,vips,protocol list load_balancer], [0], [dnl +lb0 +10.0.0.10:80=10.0.0.4:8080 10.0.0.20:90=20.0.0.4:8080,30.0.0.4:8080 +tcp +]) + +ovn-nbctl lr-add lr0 +ovn-nbctl --wait=sb lr-lb-add lr0 lb0 + +AT_CHECK([test $(ovn-sbctl --bare --columns datapaths list load_balancer) = $sw0_sb_uuid]) + +ovn-nbctl ls-add sw1 +ovn-nbctl --wait=sb ls-lb-add sw1 lb0 +sw1_sb_uuid=$(ovn-sbctl --bare --columns _uuid list datapath sw1) + +for i in $sw0_sb_uuid $sw1_sb_uuid; do echo $i >> dp_ids; done +for i in $(ovn-sbctl --bare --columns datapaths list load_balancer); do echo $i >> lb_dps; done + +cat dp_ids | sort > expout +AT_CHECK([cat lb_dps | sort], [0], [expout]) +AT_CHECK([test $(ovn-sbctl --bare --columns load_balancers list datapath sw1) = $lb0_uuid]) + +ovn-nbctl --wait=sb lb-add lb1 10.0.0.30:80 20.0.0.50:8080 udp + +AT_CHECK([ovn-sbctl --bare --columns _uuid list load_balancer | wc -l], [0], [dnl +1 +]) + +ovn-nbctl --wait=sb lr-lb-add lr0 lb1 +AT_CHECK([ovn-sbctl --bare --columns _uuid list load_balancer | wc -l], [0], [dnl +1 +]) + +ovn-nbctl --wait=sb ls-lb-add sw1 lb1 +AT_CHECK([ovn-sbctl --bare --columns name,vips,protocol list load_balancer lb1 ], [0], [dnl +lb1 +10.0.0.30:80=20.0.0.50:8080 +udp +]) + +lb1_uuid=$(ovn-sbctl --bare --columns _uuid list load_balancer lb1) + +for i in $lb0_uuid $lb1_uuid; do echo $i >> lb_ids; done +cat lb_ids | sort > expout + +for i in $(ovn-sbctl --bare --columns load_balancers list datapath_binding sw1); do echo $i >> sw1_lbs; done +AT_CHECK([cat sw1_lbs | sort], [0], [expout]) + +ovn-nbctl --wait=sb lb-del lb1 +AT_CHECK([test $(ovn-sbctl --bare --columns load_balancers list datapath_binding sw1) = $lb0_uuid]) + +AT_CLEANUP diff --git a/utilities/ovn-sbctl.c b/utilities/ovn-sbctl.c index d3eec91332..e92e9187a5 100644 --- a/utilities/ovn-sbctl.c +++ b/utilities/ovn-sbctl.c @@ -1415,6 +1415,9 @@ static const struct ctl_table_class tables[SBREC_N_TABLES] = { [SBREC_TABLE_HA_CHASSIS].row_ids[0] = {&sbrec_ha_chassis_col_chassis, NULL, NULL}, + + [SBREC_TABLE_LOAD_BALANCER].row_ids[0] + = {&sbrec_load_balancer_col_name, NULL, NULL}, };