The Southbound Load_Balancer table (like the Northbound one) doesn't
define an index (e.g., by name).  This essentially means that there can
be duplicate records in the database.  Moreover, the OVSDB RAFT
implementation ensures "at-least-once" consistency [0] making it
possible for such duplicates to "spontaneously" appear.

ovn-northd now cleans up such duplicates.

[0] 
https://github.com/openvswitch/ovs/blob/master/Documentation/ref/ovsdb.7.rst#understanding-cluster-consistency

Fixes: 42e694f03c18 ("Add new table Load_Balancer in Southbound database.")
Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2046274
Signed-off-by: Dumitru Ceara <dce...@redhat.com>
---
 northd/northd.c     | 16 +++++++++++++---
 tests/ovn-northd.at | 17 +++++++++++++++++
 2 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/northd/northd.c b/northd/northd.c
index c0ecf2346..fc7a64f99 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -3803,6 +3803,7 @@ build_ovn_lbs(struct northd_input *input_data,
     }
 
     /* Delete any stale SB load balancer rows. */
+    struct hmapx existing_lbs = HMAPX_INITIALIZER(&existing_lbs);
     const struct sbrec_load_balancer *sbrec_lb, *next;
     SBREC_LOAD_BALANCER_TABLE_FOR_EACH_SAFE (sbrec_lb, next,
                             input_data->sbrec_load_balancer_table) {
@@ -3813,13 +3814,22 @@ build_ovn_lbs(struct northd_input *input_data,
             continue;
         }
 
+        /* Delete any SB load balancer entries that refer to NB load balancers
+         * that don't exist anymore or are not applied to switches anymore.
+         *
+         * There is also a special case in which duplicate LBs might be created
+         * in the SB, e.g., due to the fact that OVSDB only ensures
+         * "at-least-once" consistency for clustered database tables that
+         * are not indexed in any way.
+         */
         lb = ovn_northd_lb_find(lbs, &lb_uuid);
-        if (lb && lb->n_nb_ls) {
-            lb->slb = sbrec_lb;
-        } else {
+        if (!lb || !lb->n_nb_ls || !hmapx_add(&existing_lbs, lb)) {
             sbrec_load_balancer_delete(sbrec_lb);
+        } else {
+            lb->slb = sbrec_lb;
         }
     }
+    hmapx_destroy(&existing_lbs);
 
     /* Create SB Load balancer records if not present and sync
      * the SB load balancer columns. */
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 652903761..84e52e701 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -5336,6 +5336,23 @@ AT_CHECK([grep "lr_out_snat" lr0flows | sed 
's/table=./table=?/' | sort], [0], [
 AT_CLEANUP
 ])
 
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([Load Balancer SB duplicates])
+ovn_start
+
+check ovn-nbctl ls-add ls -- lb-add lb1 10.0.0.1:80 10.0.0.2:80 -- ls-lb-add 
ls lb1
+check ovn-nbctl --wait=sb sync
+
+dps=$(fetch_column Load_Balancer datapaths)
+nlb=$(fetch_column nb:Load_Balancer _uuid)
+AT_CHECK([ovn-sbctl create Load_Balancer name=lb1 datapaths="$dps" 
external_ids="lb_id=$nlb"], [0], [ignore])
+
+check ovn-nbctl --wait=sb sync
+check_row_count Load_Balancer 1
+
+AT_CLEANUP
+])
+
 OVN_FOR_EACH_NORTHD([
 AT_SETUP([ovn -- Add tags to logical flows])
 ovn_start
-- 
2.27.0

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to