diff mbox series

[ovs-dev,v1,5/8] northd: Handle load balancer changes for a logical switch.

Message ID 20230624064830.12126-1-numans@ovn.org
State Superseded
Headers show
Series northd: I-P for load balancer and lb groups | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed
ovsrobot/github-robot-_ovn-kubernetes fail github build: failed

Commit Message

Numan Siddique June 24, 2023, 6:48 a.m. UTC
From: Numan Siddique <numans@ovn.org>

Logical switch change handler of the 'northd' engine node
now also handles changes to load balancers.

Signed-off-by: Numan Siddique <numans@ovn.org>
---
 lib/lb.c            |  17 +++-
 lib/lb.h            |   2 +
 northd/northd.c     | 211 +++++++++++++++++++++++++++++++++-----------
 northd/northd.h     |   9 ++
 tests/ovn-northd.at |   8 +-
 5 files changed, 190 insertions(+), 57 deletions(-)
diff mbox series

Patch

diff --git a/lib/lb.c b/lib/lb.c
index a51fe225fa..b2b6473c1d 100644
--- a/lib/lb.c
+++ b/lib/lb.c
@@ -1091,7 +1091,22 @@  ovn_lb_datapaths_add_ls(struct ovn_lb_datapaths *lb_dps, size_t n,
                         struct ovn_datapath **ods)
 {
     for (size_t i = 0; i < n; i++) {
-        bitmap_set1(lb_dps->nb_ls_map, ods[i]->index);
+        if (!bitmap_is_set(lb_dps->nb_ls_map, ods[i]->index)) {
+            bitmap_set1(lb_dps->nb_ls_map, ods[i]->index);
+            lb_dps->n_nb_ls++;
+        }
+    }
+}
+
+void
+ovn_lb_datapaths_remove_ls(struct ovn_lb_datapaths *lb_dps, size_t n,
+                        struct ovn_datapath **ods)
+{
+    for (size_t i = 0; i < n; i++) {
+        if (bitmap_is_set(lb_dps->nb_ls_map, ods[i]->index)) {
+            bitmap_set0(lb_dps->nb_ls_map, ods[i]->index);
+            lb_dps->n_nb_ls--;
+        }
     }
 }
 
diff --git a/lib/lb.h b/lib/lb.h
index 74905c73b7..ac33333a7f 100644
--- a/lib/lb.h
+++ b/lib/lb.h
@@ -179,6 +179,8 @@  void ovn_lb_datapaths_add_lr(struct ovn_lb_datapaths *, size_t n,
                              struct ovn_datapath **);
 void ovn_lb_datapaths_add_ls(struct ovn_lb_datapaths *, size_t n,
                              struct ovn_datapath **);
+void ovn_lb_datapaths_remove_ls(struct ovn_lb_datapaths *, size_t n,
+                                struct ovn_datapath **);
 
 struct ovn_lb_group_datapaths {
     struct hmap_node hmap_node;
diff --git a/northd/northd.c b/northd/northd.c
index 572e8fc849..8309ca52e4 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -853,7 +853,8 @@  ovn_datapath_destroy(struct hmap *datapaths, struct ovn_datapath *od)
         ovn_ls_port_group_destroy(&od->nb_pgs);
         destroy_mcast_info_for_datapath(od);
         destroy_ports_for_datapath(od);
-
+        free(od->lb_uuids);
+        free(od->lb_group_uuids);
         free(od);
     }
 }
@@ -4036,6 +4037,48 @@  build_lb_vip_actions(const struct ovn_northd_lb *lb,
     return reject;
 }
 
+static void
+associate_ls_lbs(struct ovn_datapath *ls_od, struct hmap *lb_datapaths_map)
+{
+    struct ovn_lb_datapaths *lb_dps;
+
+    free(ls_od->lb_uuids);
+    ls_od->lb_uuids = xcalloc(ls_od->nbs->n_load_balancer,
+                              sizeof *ls_od->lb_uuids);
+    ls_od->n_lb_uuids = ls_od->nbs->n_load_balancer;
+    for (size_t i = 0; i < ls_od->nbs->n_load_balancer; i++) {
+        const struct uuid *lb_uuid =
+            &ls_od->nbs->load_balancer[i]->header_.uuid;
+        lb_dps = ovn_lb_datapaths_find(lb_datapaths_map, lb_uuid);
+        ovs_assert(lb_dps);
+        ovn_lb_datapaths_add_ls(lb_dps, 1, &ls_od);
+        ls_od->lb_uuids[i] = *lb_uuid;
+    }
+}
+
+static void
+associate_ls_lb_groups(struct ovn_datapath *ls_od,
+                       struct hmap *lb_group_datapaths_map)
+{
+    const struct nbrec_load_balancer_group *nbrec_lb_group;
+    struct ovn_lb_group_datapaths *lb_group_dps;
+
+    free(ls_od->lb_group_uuids);
+    ls_od->lb_group_uuids = xcalloc(ls_od->nbs->n_load_balancer_group,
+                                    sizeof *ls_od->lb_group_uuids);
+    ls_od->n_lb_group_uuids = ls_od->nbs->n_load_balancer_group;
+    for (size_t i = 0; i < ls_od->nbs->n_load_balancer_group; i++) {
+        nbrec_lb_group = ls_od->nbs->load_balancer_group[i];
+        const struct uuid *lb_group_uuid = &nbrec_lb_group->header_.uuid;
+        lb_group_dps =
+            ovn_lb_group_datapaths_find(lb_group_datapaths_map,
+                                        lb_group_uuid);
+        ovs_assert(lb_group_dps);
+        ovn_lb_group_datapaths_add_ls(lb_group_dps, 1, &ls_od);
+        ls_od->lb_group_uuids[i] = *lb_group_uuid;
+    }
+}
+
 static void
 build_lb_datapaths(const struct hmap *lbs, const struct hmap *lb_groups,
                    struct ovn_datapaths *ls_datapaths,
@@ -4071,24 +4114,8 @@  build_lb_datapaths(const struct hmap *lbs, const struct hmap *lb_groups,
         if (!od->nbs) {
             continue;
         }
-
-        for (size_t i = 0; i < od->nbs->n_load_balancer; i++) {
-            const struct uuid *lb_uuid =
-                &od->nbs->load_balancer[i]->header_.uuid;
-            lb_dps = ovn_lb_datapaths_find(lb_datapaths_map, lb_uuid);
-            ovs_assert(lb_dps);
-            ovn_lb_datapaths_add_ls(lb_dps, 1, &od);
-        }
-
-        for (size_t i = 0; i < od->nbs->n_load_balancer_group; i++) {
-            nbrec_lb_group = od->nbs->load_balancer_group[i];
-            const struct uuid *lb_group_uuid = &nbrec_lb_group->header_.uuid;
-            lb_group_dps =
-                ovn_lb_group_datapaths_find(lb_group_datapaths_map,
-                                            lb_group_uuid);
-            ovs_assert(lb_group_dps);
-            ovn_lb_group_datapaths_add_ls(lb_group_dps, 1, &od);
-        }
+        associate_ls_lbs(od, lb_datapaths_map);
+        associate_ls_lb_groups(od, lb_group_datapaths_map);
     }
 
     HMAP_FOR_EACH (od, key_node, &lr_datapaths->datapaths) {
@@ -4847,23 +4874,29 @@  build_ports(struct ovsdb_idl_txn *ovnsb_txn,
     sset_destroy(&active_ha_chassis_grps);
 }
 
+static void
+destroy_tracked_ls_change(struct ls_change *ls_change)
+{
+    struct ovn_port *op;
+    LIST_FOR_EACH (op, list, &ls_change->added_ports) {
+        ovs_list_remove(&op->list);
+    }
+    LIST_FOR_EACH (op, list, &ls_change->updated_ports) {
+        ovs_list_remove(&op->list);
+    }
+    LIST_FOR_EACH_SAFE (op, list, &ls_change->deleted_ports) {
+        ovs_list_remove(&op->list);
+        ovn_port_destroy_orphan(op);
+    }
+}
+
 void
 destroy_northd_data_tracked_changes(struct northd_data *nd)
 {
     struct ls_change *ls_change;
     LIST_FOR_EACH_SAFE (ls_change, list_node,
                         &nd->tracked_ls_changes.updated) {
-        struct ovn_port *op;
-        LIST_FOR_EACH (op, list, &ls_change->added_ports) {
-            ovs_list_remove(&op->list);
-        }
-        LIST_FOR_EACH (op, list, &ls_change->updated_ports) {
-            ovs_list_remove(&op->list);
-        }
-        LIST_FOR_EACH_SAFE (op, list, &ls_change->deleted_ports) {
-            ovs_list_remove(&op->list);
-            ovn_port_destroy_orphan(op);
-        }
+        destroy_tracked_ls_change(ls_change);
         ovs_list_remove(&ls_change->list_node);
         free(ls_change);
     }
@@ -4980,6 +5013,7 @@  ls_port_create(struct ovsdb_idl_txn *ovnsb_txn, struct hmap *ls_ports,
  * incrementally handled.
  * Presently supports i-p for the below changes:
  *    - logical switch ports.
+ *    - load balancers.
  */
 static bool
 check_unsupported_inc_proc_for_ls_changes(
@@ -4988,8 +5022,11 @@  check_unsupported_inc_proc_for_ls_changes(
     /* Check if the columns are changed in this row. */
     enum nbrec_logical_switch_column_id col;
     for (col = 0; col < NBREC_LOGICAL_SWITCH_N_COLUMNS; col++) {
-        if (nbrec_logical_switch_is_updated(ls, col) &&
-            col != NBREC_LOGICAL_SWITCH_COL_PORTS) {
+        if (nbrec_logical_switch_is_updated(ls, col)) {
+            if (col == NBREC_LOGICAL_SWITCH_COL_PORTS ||
+                col == NBREC_LOGICAL_SWITCH_COL_LOAD_BALANCER) {
+                continue;
+            }
             return true;
         }
     }
@@ -5018,12 +5055,6 @@  check_unsupported_inc_proc_for_ls_changes(
             return true;
         }
     }
-    for (size_t i = 0; i < ls->n_load_balancer; i++) {
-        if (nbrec_load_balancer_row_get_seqno(ls->load_balancer[i],
-                                OVSDB_IDL_CHANGE_MODIFY) > 0) {
-            return true;
-        }
-    }
     for (size_t i = 0; i < ls->n_load_balancer_group; i++) {
         if (nbrec_load_balancer_group_row_get_seqno(ls->load_balancer_group[i],
                                 OVSDB_IDL_CHANGE_MODIFY) > 0) {
@@ -5082,7 +5113,9 @@  ls_check_and_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn,
                                 const struct nbrec_logical_switch *changed_ls,
                                 const struct northd_input *ni,
                                 struct northd_data *nd,
-                                struct ovn_datapath *od)
+                                struct ovn_datapath *od,
+                                struct ls_change *ls_change,
+                                bool *updated)
 {
     bool ls_ports_changed = false;
     if (!nbrec_logical_switch_is_updated(changed_ls,
@@ -5103,12 +5136,6 @@  ls_check_and_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn,
         return true;
     }
 
-    struct ls_change *ls_change = xzalloc(sizeof *ls_change);
-    ls_change->od = od;
-    ovs_list_init(&ls_change->added_ports);
-    ovs_list_init(&ls_change->deleted_ports);
-    ovs_list_init(&ls_change->updated_ports);
-
     struct ovn_port *op;
     HMAP_FOR_EACH (op, dp_node, &od->ports) {
         op->visited = false;
@@ -5195,19 +5222,66 @@  ls_check_and_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn,
     if (!ovs_list_is_empty(&ls_change->added_ports) ||
         !ovs_list_is_empty(&ls_change->updated_ports) ||
         !ovs_list_is_empty(&ls_change->deleted_ports)) {
-        ovs_list_push_back(&nd->tracked_ls_changes.updated,
-                            &ls_change->list_node);
-    } else {
-        free(ls_change);
+        *updated = true;
     }
 
     return true;
 
 fail:
-    free(ls_change);
+
+    LIST_FOR_EACH (op, list, &ls_change->added_ports) {
+        ovs_list_remove(&op->list);
+    }
+    LIST_FOR_EACH (op, list, &ls_change->updated_ports) {
+        ovs_list_remove(&op->list);
+    }
+    LIST_FOR_EACH_SAFE (op, list, &ls_change->deleted_ports) {
+        ovs_list_remove(&op->list);
+        ovn_port_destroy_orphan(op);
+    }
     return false;
 }
 
+static bool
+ls_check_and_handle_lb_changes(const struct nbrec_logical_switch *changed_ls,
+                               struct hmap *lb_datapaths_map,
+                               struct ovn_datapath *od,
+                               struct ls_change *ls_change,
+                               bool *updated)
+{
+
+    if (!nbrec_logical_switch_is_updated(changed_ls,
+                        NBREC_LOGICAL_SWITCH_COL_LOAD_BALANCER)) {
+        for (size_t i = 0; i < changed_ls->n_load_balancer; i++) {
+            if (nbrec_load_balancer_row_get_seqno(changed_ls->load_balancer[i],
+                                    OVSDB_IDL_CHANGE_MODIFY) > 0) {
+                ls_change->lbs_changed = true;
+                *updated = true;
+                /* Re-evaluate 'od->has_lb_vip' */
+                init_lb_for_datapath(od);
+                break;
+            }
+        }
+
+        return true;
+    }
+
+    struct ovn_lb_datapaths *lb_dps;
+    for (size_t i = 0; i < od->n_lb_uuids; i++) {
+        lb_dps = ovn_lb_datapaths_find(lb_datapaths_map, &od->lb_uuids[i]);
+        if (lb_dps) {
+            ovn_lb_datapaths_remove_ls(lb_dps, 1, &od);
+        }
+    }
+
+    associate_ls_lbs(od, lb_datapaths_map);
+    ls_change->lbs_changed = true;
+    *updated = true;
+    /* Re-evaluate 'od->has_lb_vip' */
+    init_lb_for_datapath(od);
+    return true;
+}
+
 
 /* Return true if changes are handled incrementally, false otherwise.
  * When there are any changes, try to track what's exactly changed and set
@@ -5238,20 +5312,47 @@  northd_handle_ls_changes(struct ovsdb_idl_txn *ovnsb_idl_txn,
             goto fail;
         }
 
-        /* Now only able to handle lsp changes. */
+        /* Now only able to handle lsp, load balancerload and
+         * load balancer group changes. */
         if (check_unsupported_inc_proc_for_ls_changes(changed_ls)) {
             goto fail;
         }
 
+        struct ls_change *ls_change = xzalloc(sizeof *ls_change);
+        ls_change->od = od;
+        ovs_list_init(&ls_change->added_ports);
+        ovs_list_init(&ls_change->deleted_ports);
+        ovs_list_init(&ls_change->updated_ports);
+
+        bool updated = false;
         if (!ls_check_and_handle_lsp_changes(ovnsb_idl_txn, changed_ls,
-                                             ni, nd, od)) {
+                                             ni, nd, od, ls_change,
+                                             &updated)) {
+            destroy_tracked_ls_change(ls_change);
+            free(ls_change);
             goto fail;
         }
+
+        if (!ls_check_and_handle_lb_changes(changed_ls,
+                                            &nd->lb_datapaths_map, od,
+                                            ls_change, &updated)) {
+            destroy_tracked_ls_change(ls_change);
+            free(ls_change);
+            goto fail;
+        }
+
+        if (updated) {
+            ovs_list_push_back(&nd->tracked_ls_changes.updated,
+                               &ls_change->list_node);
+        } else {
+            free(ls_change);
+        }
     }
 
     if (!ovs_list_is_empty(&nd->tracked_ls_changes.updated)) {
         nd->change_tracked = true;
     }
+
     return true;
 
 fail:
@@ -16422,6 +16523,12 @@  bool lflow_handle_northd_ls_changes(struct ovsdb_idl_txn *ovnsb_txn,
                                     struct hmap *lflows)
 {
     struct ls_change *ls_change;
+    LIST_FOR_EACH (ls_change, list_node, &ls_changes->updated) {
+        if (ls_change->lbs_changed) {
+            return false;
+        }
+    }
+
     LIST_FOR_EACH (ls_change, list_node, &ls_changes->updated) {
         ovs_list_init(&temp_lflow_list);
         add_lflow_to_temp_list = true;
diff --git a/northd/northd.h b/northd/northd.h
index 7d17921fa2..3afa4eaff2 100644
--- a/northd/northd.h
+++ b/northd/northd.h
@@ -94,6 +94,7 @@  struct ls_change {
     struct ovs_list added_ports;
     struct ovs_list deleted_ports;
     struct ovs_list updated_ports;
+    bool lbs_changed;
 };
 
 /* Track what's changed for logical switches.
@@ -318,6 +319,14 @@  struct ovn_datapath {
     /* Map of ovn_port objects belonging to this datapath.
      * This map doesn't include derived ports. */
     struct hmap ports;
+
+    /* LB uuids associated with this datapath. */
+    struct uuid *lb_uuids;
+    size_t n_lb_uuids;
+
+    /* LB group uuids associated with this datapath. */
+    struct uuid *lb_group_uuids;
+    size_t n_lb_group_uuids;
 };
 
 void ovnnb_db_run(struct northd_input *input_data,
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 9c78ac8eaf..f133a89263 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -9677,15 +9677,15 @@  check ovn-nbctl ls-add sw0
 check ovn-nbctl --wait=sb lr-add lr0
 check_engine_stats recompute recompute
 
-# Associate lb1 to sw0. There should be a full recompute of northd engine node
+# Associate lb1 to sw0. There should be no recompute of northd engine node
 check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
 check ovn-nbctl --wait=sb ls-lb-add sw0 lb1
-check_engine_stats recompute recompute
+check_engine_stats norecompute recompute
 
-# Disassociate lb1 from sw0. There should be a full recompute of northd engine node.
+# Disassociate lb1 from sw0. There should be a no recompute of northd engine node.
 check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
 check ovn-nbctl --wait=sb ls-lb-del sw0 lb1
-check_engine_stats recompute recompute
+check_engine_stats norecompute recompute
 
 # Test load balancer group now
 check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats