The ovnsb_db_run() handles changes from SB DB and then updates NB/SB
accordingly. These changes are not directly related to the rest part of
the "northd" node, so split as a new node from it. This node doesn't
maintain any data, but simply output to NB/SB DBs. It is similar to the
sync-to-sb node but the input is from the other direction. This enables
handling SB changes in different (more efficient) ways from each node.

Signed-off-by: Han Zhou <hz...@ovn.org>
---
 northd/automake.mk       |  2 +
 northd/en-northd.c       | 12 ++++--
 northd/en-sync-from-sb.c | 86 ++++++++++++++++++++++++++++++++++++++++
 northd/en-sync-from-sb.h | 11 +++++
 northd/inc-proc-northd.c |  9 +++++
 northd/northd.c          | 67 +++++++++++++------------------
 northd/northd.h          | 14 +++++--
 7 files changed, 154 insertions(+), 47 deletions(-)
 create mode 100644 northd/en-sync-from-sb.c
 create mode 100644 northd/en-sync-from-sb.h

diff --git a/northd/automake.mk b/northd/automake.mk
index 3c3719a24936..f8e61a1683e8 100644
--- a/northd/automake.mk
+++ b/northd/automake.mk
@@ -16,6 +16,8 @@ northd_ovn_northd_SOURCES = \
        northd/en-northd-output.h \
        northd/en-sync-sb.c \
        northd/en-sync-sb.h \
+       northd/en-sync-from-sb.c \
+       northd/en-sync-from-sb.h \
        northd/inc-proc-northd.c \
        northd/inc-proc-northd.h \
        northd/ipam.c \
diff --git a/northd/en-northd.c b/northd/en-northd.c
index f2bf98f774b1..785a592516c0 100644
--- a/northd/en-northd.c
+++ b/northd/en-northd.c
@@ -18,6 +18,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 
+#include "coverage.h"
 #include "en-northd.h"
 #include "lib/inc-proc-eng.h"
 #include "lib/ovn-nb-idl.h"
@@ -25,11 +26,14 @@
                                * lib/ovn-parallel-hmap.h should be updated
                                * to include this dependency itself */
 #include "lib/ovn-parallel-hmap.h"
+#include "stopwatch.h"
+#include "lib/stopwatch-names.h"
 #include "northd.h"
 #include "lib/util.h"
 #include "openvswitch/vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(en_northd);
+COVERAGE_DEFINE(northd_run);
 
 static void
 northd_get_input_data(struct engine_node *node,
@@ -128,9 +132,11 @@ en_northd_run(struct engine_node *node, void *data)
     northd_init(data);
 
     northd_get_input_data(node, &input_data);
-    northd_run(&input_data, data,
-               eng_ctx->ovnnb_idl_txn,
-               eng_ctx->ovnsb_idl_txn);
+    COVERAGE_INC(northd_run);
+    stopwatch_start(OVNNB_DB_RUN_STOPWATCH_NAME, time_msec());
+    ovnnb_db_run(&input_data, data, eng_ctx->ovnnb_idl_txn,
+                 eng_ctx->ovnsb_idl_txn);
+    stopwatch_stop(OVNNB_DB_RUN_STOPWATCH_NAME, time_msec());
     engine_set_node_state(node, EN_UPDATED);
 
 }
diff --git a/northd/en-sync-from-sb.c b/northd/en-sync-from-sb.c
new file mode 100644
index 000000000000..55ece2d1627c
--- /dev/null
+++ b/northd/en-sync-from-sb.c
@@ -0,0 +1,86 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "openvswitch/util.h"
+
+#include "en-sync-from-sb.h"
+#include "include/ovn/expr.h"
+#include "lib/inc-proc-eng.h"
+#include "lib/lb.h"
+#include "lib/ovn-nb-idl.h"
+#include "lib/ovn-sb-idl.h"
+#include "lib/ovn-util.h"
+#include "stopwatch.h"
+#include "lib/stopwatch-names.h"
+#include "timeval.h"
+#include "northd.h"
+
+#include "openvswitch/vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(en_sync_from_sb);
+
+void *
+en_sync_from_sb_init(struct engine_node *node OVS_UNUSED,
+                     struct engine_arg *arg OVS_UNUSED)
+{
+    return NULL;
+}
+
+void
+en_sync_from_sb_run(struct engine_node *node, void *data OVS_UNUSED)
+{
+    const struct engine_context *eng_ctx = engine_get_context();
+    struct northd_data *nd = engine_get_input_data("northd", node);
+
+    const struct sbrec_port_binding_table *sb_pb_table =
+        EN_OVSDB_GET(engine_get_input("SB_port_binding", node));
+    const struct sbrec_ha_chassis_group_table *sb_ha_ch_grp_table =
+        EN_OVSDB_GET(engine_get_input("SB_ha_chassis_group", node));
+    struct ovsdb_idl_index *sb_ha_ch_grp_by_name =
+        engine_ovsdb_node_get_index(
+            engine_get_input("SB_ha_chassis_group", node),
+            "sbrec_ha_chassis_grp_by_name");
+    stopwatch_start(OVNSB_DB_RUN_STOPWATCH_NAME, time_msec());
+    ovnsb_db_run(eng_ctx->ovnnb_idl_txn, eng_ctx->ovnsb_idl_txn,
+                 sb_pb_table, sb_ha_ch_grp_table, sb_ha_ch_grp_by_name,
+                 &nd->ls_ports);
+    stopwatch_stop(OVNSB_DB_RUN_STOPWATCH_NAME, time_msec());
+}
+
+bool
+sync_from_sb_northd_handler(struct engine_node *node,
+                            void *data OVS_UNUSED)
+{
+    struct northd_data *nd = engine_get_input_data("northd", node);
+    if (nd->change_tracked) {
+        /* There are only NB LSP related changes and the only field this node
+         * cares about is the "up" column, which is considered write-only to
+         * this node, so it is safe to ignore the change. (The real change
+         * matters to this node is always from the SB DB.) */
+        return true;
+    }
+    return false;
+}
+
+void
+en_sync_from_sb_cleanup(void *data OVS_UNUSED)
+{
+
+}
diff --git a/northd/en-sync-from-sb.h b/northd/en-sync-from-sb.h
new file mode 100644
index 000000000000..1f0cfd2cdbc2
--- /dev/null
+++ b/northd/en-sync-from-sb.h
@@ -0,0 +1,11 @@
+#ifndef EN_SYNC_FROM_SB_H
+#define EN_SYNC_FROM_SB_H 1
+
+#include "lib/inc-proc-eng.h"
+
+void *en_sync_from_sb_init(struct engine_node *, struct engine_arg *);
+void en_sync_from_sb_run(struct engine_node *, void *data);
+void en_sync_from_sb_cleanup(void *data);
+bool sync_from_sb_northd_handler(struct engine_node *, void *data OVS_UNUSED);
+
+#endif /* end of EN_SYNC_FROM_SB_H */
diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
index f6ceb8280624..0642c9514b7c 100644
--- a/northd/inc-proc-northd.c
+++ b/northd/inc-proc-northd.c
@@ -34,6 +34,7 @@
 #include "en-lflow.h"
 #include "en-northd-output.h"
 #include "en-sync-sb.h"
+#include "en-sync-from-sb.h"
 #include "unixctl.h"
 #include "util.h"
 
@@ -129,6 +130,7 @@ enum sb_engine_node {
 /* Define engine nodes for other nodes. They should be defined as static to
  * avoid sparse errors. */
 static ENGINE_NODE_WITH_CLEAR_TRACK_DATA(northd, "northd");
+static ENGINE_NODE(sync_from_sb, "sync_from_sb");
 static ENGINE_NODE(lflow, "lflow");
 static ENGINE_NODE(mac_binding_aging, "mac_binding_aging");
 static ENGINE_NODE(mac_binding_aging_waker, "mac_binding_aging_waker");
@@ -196,6 +198,13 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
      * Right now this engine only syncs the SB Address_Set table.
      */
     engine_add_input(&en_sync_to_sb, &en_sync_to_sb_addr_set, NULL);
+
+    engine_add_input(&en_sync_from_sb, &en_northd,
+                     sync_from_sb_northd_handler);
+    engine_add_input(&en_sync_from_sb, &en_sb_port_binding, NULL);
+    engine_add_input(&en_sync_from_sb, &en_sb_ha_chassis_group, NULL);
+
+    engine_add_input(&en_northd_output, &en_sync_from_sb, NULL);
     engine_add_input(&en_northd_output, &en_sync_to_sb,
                      northd_output_sync_to_sb_handler);
     engine_add_input(&en_northd_output, &en_lflow,
diff --git a/northd/northd.c b/northd/northd.c
index 32c18ab3c932..f65b69848a09 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -60,8 +60,6 @@
 
 VLOG_DEFINE_THIS_MODULE(northd);
 
-COVERAGE_DEFINE(northd_run);
-
 static bool controller_event_en;
 static bool lflow_hash_lock_initialized = false;
 
@@ -17116,7 +17114,7 @@ northd_destroy(struct northd_data *data)
     sset_destroy(&data->svc_monitor_lsps);
 }
 
-static void
+void
 ovnnb_db_run(struct northd_input *input_data,
              struct northd_data *data,
              struct ovsdb_idl_txn *ovnnb_txn,
@@ -17331,16 +17329,16 @@ struct ha_chassis_group_node {
 };
 
 static void
-update_sb_ha_group_ref_chassis(struct northd_input *input_data,
-                               struct shash *ha_ref_chassis_map)
+update_sb_ha_group_ref_chassis(
+    const struct sbrec_ha_chassis_group_table *sb_ha_ch_grp_table,
+    struct shash *ha_ref_chassis_map)
 {
     struct hmap ha_ch_grps = HMAP_INITIALIZER(&ha_ch_grps);
     struct ha_chassis_group_node *ha_ch_grp_node;
 
     /* Initialize a set of all ha_chassis_groups in SB. */
     const struct sbrec_ha_chassis_group *ha_ch_grp;
-    SBREC_HA_CHASSIS_GROUP_TABLE_FOR_EACH (ha_ch_grp,
-                                    input_data->sbrec_ha_chassis_group_table) {
+    SBREC_HA_CHASSIS_GROUP_TABLE_FOR_EACH (ha_ch_grp, sb_ha_ch_grp_table) {
         ha_ch_grp_node = xzalloc(sizeof *ha_ch_grp_node);
         ha_ch_grp_node->ha_ch_grp = ha_ch_grp;
         hmap_insert(&ha_ch_grps, &ha_ch_grp_node->hmap_node,
@@ -17402,7 +17400,7 @@ update_sb_ha_group_ref_chassis(struct northd_input 
*input_data,
  *  - 'ref_chassis' of hagrp1.
  */
 static void
-build_ha_chassis_group_ref_chassis(struct northd_input *input_data,
+build_ha_chassis_group_ref_chassis(struct ovsdb_idl_index *ha_ch_grp_by_name,
                                    const struct sbrec_port_binding *sb,
                                    struct ovn_port *op,
                                    struct shash *ha_ref_chassis_map)
@@ -17428,7 +17426,7 @@ build_ha_chassis_group_ref_chassis(struct northd_input 
*input_data,
     SSET_FOR_EACH (ha_group_name, &lr_group->ha_chassis_groups) {
         const struct sbrec_ha_chassis_group *sb_ha_chassis_grp;
         sb_ha_chassis_grp = ha_chassis_group_lookup_by_name(
-            input_data->sbrec_ha_chassis_grp_by_name, ha_group_name);
+            ha_ch_grp_by_name, ha_group_name);
 
         if (sb_ha_chassis_grp) {
             struct ha_ref_chassis_info *ref_ch_info =
@@ -17443,17 +17441,18 @@ build_ha_chassis_group_ref_chassis(struct 
northd_input *input_data,
  * this column is not empty, it means we need to set the corresponding logical
  * port as 'up' in the northbound DB. */
 static void
-handle_port_binding_changes(struct northd_input *input_data,
-                            struct ovsdb_idl_txn *ovnsb_txn,
-                            struct hmap *ports,
-                            struct shash *ha_ref_chassis_map)
+handle_port_binding_changes(struct ovsdb_idl_txn *ovnsb_txn,
+                const struct sbrec_port_binding_table *sb_pb_table,
+                const struct sbrec_ha_chassis_group_table *sb_ha_ch_grp_table,
+                struct ovsdb_idl_index *sb_ha_ch_grp_by_name,
+                struct hmap *ls_ports,
+                struct shash *ha_ref_chassis_map)
 {
     const struct sbrec_port_binding *sb;
     bool build_ha_chassis_ref = false;
     if (ovnsb_txn) {
         const struct sbrec_ha_chassis_group *ha_ch_grp;
-        SBREC_HA_CHASSIS_GROUP_TABLE_FOR_EACH (ha_ch_grp,
-                                    input_data->sbrec_ha_chassis_group_table) {
+        SBREC_HA_CHASSIS_GROUP_TABLE_FOR_EACH (ha_ch_grp, sb_ha_ch_grp_table) {
             if (ha_ch_grp->n_ha_chassis > 1) {
                 struct ha_ref_chassis_info *ref_ch_info =
                     xzalloc(sizeof *ref_ch_info);
@@ -17464,9 +17463,8 @@ handle_port_binding_changes(struct northd_input 
*input_data,
         }
     }
 
-    SBREC_PORT_BINDING_TABLE_FOR_EACH (sb,
-                                       input_data->sbrec_port_binding_table) {
-        struct ovn_port *op = ovn_port_find(ports, sb->logical_port);
+    SBREC_PORT_BINDING_TABLE_FOR_EACH (sb, sb_pb_table) {
+        struct ovn_port *op = ovn_port_find(ls_ports, sb->logical_port);
 
         if (!op || !op->nbsp) {
             /* The logical port doesn't exist for this port binding.  This can
@@ -17493,18 +17491,20 @@ handle_port_binding_changes(struct northd_input 
*input_data,
         if (build_ha_chassis_ref && ovnsb_txn && sb->chassis) {
             /* Check and add the chassis which has claimed this 'sb'
              * to the ha chassis group's ref_chassis if required. */
-            build_ha_chassis_group_ref_chassis(input_data, sb, op,
+            build_ha_chassis_group_ref_chassis(sb_ha_ch_grp_by_name, sb, op,
                                                ha_ref_chassis_map);
         }
     }
 }
 
 /* Handle a fairly small set of changes in the southbound database. */
-static void
-ovnsb_db_run(struct northd_input *input_data,
-             struct ovsdb_idl_txn *ovnnb_txn,
+void
+ovnsb_db_run(struct ovsdb_idl_txn *ovnnb_txn,
              struct ovsdb_idl_txn *ovnsb_txn,
-             struct hmap *ports)
+             const struct sbrec_port_binding_table *sb_pb_table,
+             const struct sbrec_ha_chassis_group_table *sb_ha_ch_grp_table,
+             struct ovsdb_idl_index *sb_ha_ch_grp_by_name,
+             struct hmap *ls_ports)
 {
     if (!ovnnb_txn ||
         !ovsdb_idl_has_ever_connected(ovsdb_idl_txn_get_idl(ovnsb_txn))) {
@@ -17512,29 +17512,16 @@ ovnsb_db_run(struct northd_input *input_data,
     }
 
     struct shash ha_ref_chassis_map = SHASH_INITIALIZER(&ha_ref_chassis_map);
-    handle_port_binding_changes(input_data,
-                                ovnsb_txn, ports, &ha_ref_chassis_map);
+    handle_port_binding_changes(ovnsb_txn, sb_pb_table, sb_ha_ch_grp_table,
+                                sb_ha_ch_grp_by_name, ls_ports,
+                                &ha_ref_chassis_map);
     if (ovnsb_txn) {
-        update_sb_ha_group_ref_chassis(input_data,
+        update_sb_ha_group_ref_chassis(sb_ha_ch_grp_table,
                                        &ha_ref_chassis_map);
     }
     shash_destroy(&ha_ref_chassis_map);
 }
 
-void northd_run(struct northd_input *input_data,
-                struct northd_data *data,
-                struct ovsdb_idl_txn *ovnnb_txn,
-                struct ovsdb_idl_txn *ovnsb_txn)
-{
-    COVERAGE_INC(northd_run);
-    stopwatch_start(OVNNB_DB_RUN_STOPWATCH_NAME, time_msec());
-    ovnnb_db_run(input_data, data, ovnnb_txn, ovnsb_txn);
-    stopwatch_stop(OVNNB_DB_RUN_STOPWATCH_NAME, time_msec());
-    stopwatch_start(OVNSB_DB_RUN_STOPWATCH_NAME, time_msec());
-    ovnsb_db_run(input_data, ovnnb_txn, ovnsb_txn, &data->ls_ports);
-    stopwatch_stop(OVNSB_DB_RUN_STOPWATCH_NAME, time_msec());
-}
-
 const char *
 northd_get_svc_monitor_mac(void)
 {
diff --git a/northd/northd.h b/northd/northd.h
index 8be504811921..c77b6b3685bc 100644
--- a/northd/northd.h
+++ b/northd/northd.h
@@ -315,10 +315,16 @@ struct ovn_datapath {
     struct hmap ports;
 };
 
-void northd_run(struct northd_input *input_data,
-                struct northd_data *data,
-                struct ovsdb_idl_txn *ovnnb_txn,
-                struct ovsdb_idl_txn *ovnsb_txn);
+void ovnnb_db_run(struct northd_input *input_data,
+                  struct northd_data *data,
+                  struct ovsdb_idl_txn *ovnnb_txn,
+                  struct ovsdb_idl_txn *ovnsb_txn);
+void ovnsb_db_run(struct ovsdb_idl_txn *ovnnb_txn,
+                  struct ovsdb_idl_txn *ovnsb_txn,
+                  const struct sbrec_port_binding_table *,
+                  const struct sbrec_ha_chassis_group_table *,
+                  struct ovsdb_idl_index *sb_ha_ch_grp_by_name,
+                  struct hmap *ls_ports);
 bool northd_handle_ls_changes(struct ovsdb_idl_txn *,
                               const struct northd_input *,
                               struct northd_data *);
-- 
2.30.2

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

Reply via email to