@@ -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 \
@@ -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);
}
new file mode 100644
@@ -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)
+{
+
+}
new file mode 100644
@@ -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 */
@@ -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,
@@ -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)
{
@@ -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 *);
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 <hzhou@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