[ovs-dev] [PATCH ovn 1/5] Add new table Load_Balancer in Southbound database.
numans at ovn.org
numans at ovn.org
Wed Oct 21 08:22:22 UTC 2020
From: Numan Siddique <numans at ovn.org>
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 <numans at ovn.org>
---
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.
</column>
+ <column name="load_balancers">
+ <p>
+ Load balancers associated with the datapath.
+ </p>
+ </column>
+
<group title="OVN_Northbound Relationship">
<p>
Each row in <ref table="Datapath_Binding"/> is associated with some
@@ -4104,4 +4110,45 @@ tcp.flags = RST;
</column>
</group>
</table>
+
+ <table name="Load_Balancer">
+ <p>
+ Each row represents one load balancer and corresponds directly
+ with the <ref table="Load_Balancer"/> table in the
+ <ref db="OVN_Northbound"/> database.
+ </p>
+
+ <column name="name">
+ 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.
+ </column>
+
+ <column name="vips">
+ A map of virtual IP addresses (and an optional port number with
+ <code>:</code> as a separator) associated with this load balancer and
+ their corresponding endpoint IP addresses (and optional port numbers
+ with <code>:</code> as separators) separated by commas.
+ </column>
+
+ <column name="protocol">
+ <p>
+ Valid protocols are <code>tcp</code>, <code>udp</code>, or
+ <code>sctp</code>. This column is useful when a port number is
+ provided as part of the <code>vips</code> column. If this column is
+ empty and a port number is provided as part of <code>vips</code>
+ column, OVN assumes the protocol to be <code>tcp</code>.
+ </p>
+ </column>
+
+ <column name="datapaths">
+ Datapaths to which this load balancer applies to.
+ </column>
+
+ <group title="Common Columns">
+ <column name="external_ids">
+ See <em>External IDs</em> at the beginning of this document.
+ </column>
+ </group>
+ </table>
</database>
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},
};
--
2.26.2
More information about the dev
mailing list