This allows upcoming patches to initialize the I-P engine from different
places in ovn-controller.

Signed-off-by: Dumitru Ceara <[email protected]>
---
 controller/ovn-controller.c | 1097 ++++++++++++++++++-----------------
 1 file changed, 569 insertions(+), 528 deletions(-)

diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index f9f2172768..52fc69f31f 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -6581,260 +6581,612 @@ static ENGINE_NODE(evpn_vtep_binding, 
CLEAR_TRACKED_DATA);
 static ENGINE_NODE(evpn_fdb, CLEAR_TRACKED_DATA);
 static ENGINE_NODE(evpn_arp, CLEAR_TRACKED_DATA);
 
-/* Returns false if the northd internal version stored in SB_Global
- * and ovn-controller internal version don't match.
- */
-static bool
-check_northd_version(struct ovsdb_idl *ovs_idl, struct ovsdb_idl *ovnsb_idl,
-                     const char *version)
-{
-    static bool version_mismatch;
+static void
+inc_proc_ovn_controller_init(
+    struct ovsdb_idl_loop *sb_idl_loop, struct ovsdb_idl_loop *ovs_idl_loop,
+    struct ovsdb_idl_index *sbrec_chassis_by_name,
+    struct ovsdb_idl_index *sbrec_port_binding_by_name,
+    struct ovsdb_idl_index *sbrec_port_binding_by_key,
+    struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
+    struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip,
+    struct ovsdb_idl_index *ovsrec_flow_sample_collector_set_by_id,
+    struct ovsdb_idl_index *ovsrec_port_by_qos,
+    struct ovsdb_idl_index *ovsrec_interface_by_name,
+    struct ovsdb_idl_index *ovsrec_queue_by_external_ids)
+{
+    /* Define relationships between nodes where first argument is dependent
+     * on the second argument. */
 
-    const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(ovs_idl);
-    const struct ovsrec_open_vswitch_table *ovs_table =
-        ovsrec_open_vswitch_table_get(ovs_idl);
-    const char *chassis_id = get_ovs_chassis_id(ovs_table);
-    if (!cfg || !get_chassis_external_id_value_bool(
-                     &cfg->external_ids, chassis_id,
-                     "ovn-match-northd-version", false)) {
-        version_mismatch = false;
-        return true;
-    }
+    engine_add_input(&en_template_vars, &en_ovs_open_vswitch, NULL);
+    engine_add_input(&en_template_vars, &en_sb_chassis, NULL);
+    engine_add_input(&en_template_vars, &en_sb_chassis_template_var,
+                     template_vars_sb_chassis_template_var_handler);
 
-    const struct sbrec_sb_global *sb = sbrec_sb_global_first(ovnsb_idl);
-    if (!sb) {
-        version_mismatch = true;
-        return false;
-    }
+    engine_add_input(&en_lb_data, &en_sb_load_balancer,
+                     lb_data_sb_load_balancer_handler);
+    engine_add_input(&en_lb_data, &en_template_vars,
+                     lb_data_template_var_handler);
+    engine_add_input(&en_lb_data, &en_runtime_data,
+                     lb_data_runtime_data_handler);
 
-    const char *northd_version =
-        smap_get_def(&sb->options, "northd_internal_version", "");
+    engine_add_input(&en_route, &en_ovs_open_vswitch, NULL);
+    engine_add_input(&en_route, &en_sb_chassis, NULL);
+    engine_add_input(&en_route, &en_sb_port_binding,
+                     route_sb_port_binding_data_handler);
+    engine_add_input(&en_route, &en_runtime_data,
+                     route_runtime_data_handler);
+    engine_add_input(&en_route, &en_sb_advertised_route,
+                     route_sb_advertised_route_data_handler);
 
-    if (strcmp(northd_version, version)) {
-        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
-        VLOG_WARN_RL(&rl, "controller version - %s mismatch with northd "
-                     "version - %s", version, northd_version);
-        version_mismatch = true;
-        return false;
-    }
+    engine_add_input(&en_route_exchange, &en_route, NULL);
+    engine_add_input(&en_route_exchange, &en_sb_learned_route,
+                     engine_noop_handler);
+    engine_add_input(&en_route_exchange, &en_sb_port_binding,
+                     engine_noop_handler);
+    engine_add_input(&en_route_exchange, &en_route_table_notify, NULL);
+    engine_add_input(&en_route_exchange, &en_route_exchange_status, NULL);
+    engine_add_input(&en_route_exchange, &en_sb_ro,
+                     route_exchange_sb_ro_handler);
 
-    /* If there used to be a mismatch and ovn-northd got updated, force a
-     * full recompute.
+    engine_add_input(&en_addr_sets, &en_sb_address_set,
+                     addr_sets_sb_address_set_handler);
+    engine_add_input(&en_port_groups, &en_sb_port_group,
+                     port_groups_sb_port_group_handler);
+    /* port_groups computation requires runtime_data's lbinding_data for the
+     * locally bound ports. */
+    engine_add_input(&en_port_groups, &en_runtime_data,
+                     port_groups_runtime_data_handler);
+
+    engine_add_input(&en_non_vif_data, &en_ovs_open_vswitch, NULL);
+    engine_add_input(&en_non_vif_data, &en_ovs_bridge, NULL);
+    engine_add_input(&en_non_vif_data, &en_sb_chassis, NULL);
+    engine_add_input(&en_non_vif_data, &en_ovs_interface,
+                     non_vif_data_ovs_iface_handler);
+
+    engine_add_input(&en_if_status_mgr, &en_ovs_interface,
+                     if_status_mgr_ovs_interface_handler);
+    engine_add_input(&en_bfd_chassis, &en_ovs_open_vswitch, NULL);
+    engine_add_input(&en_bfd_chassis, &en_sb_chassis, NULL);
+    engine_add_input(&en_bfd_chassis, &en_sb_ha_chassis_group, NULL);
+
+    /* Note: The order of inputs is important, all OVS interface changes must
+     * be handled before any ct_zone changes.
      */
-    if (version_mismatch) {
-        engine_set_force_recompute();
-    }
-    version_mismatch = false;
-    return true;
-}
+    engine_add_input(&en_pflow_output, &en_non_vif_data,
+                     NULL);
+    engine_add_input(&en_pflow_output, &en_northd_options, NULL);
+    engine_add_input(&en_pflow_output, &en_ct_zones,
+                     pflow_output_ct_zones_handler);
+    engine_add_input(&en_pflow_output, &en_sb_chassis,
+                     pflow_lflow_output_sb_chassis_handler);
 
-static void
-br_int_remote_update(struct br_int_remote *remote,
-                     const struct ovsrec_bridge *br_int,
-                     const struct ovsrec_open_vswitch_table *ovs_table)
-{
-    if (!br_int) {
-        return;
-    }
+    engine_add_input(&en_pflow_output, &en_if_status_mgr,
+                     pflow_output_if_status_mgr_handler);
+    engine_add_input(&en_pflow_output, &en_sb_port_binding,
+                     pflow_output_sb_port_binding_handler);
+    engine_add_input(&en_pflow_output, &en_sb_multicast_group,
+                     pflow_output_sb_multicast_group_handler);
 
-    const struct ovsrec_open_vswitch *cfg =
-            ovsrec_open_vswitch_table_first(ovs_table);
+    /* pflow_output needs to access the SB datapath binding and hence a noop
+     * handler.
+     */
+    engine_add_input(&en_pflow_output, &en_sb_datapath_binding,
+                     engine_noop_handler);
+    engine_add_input(&en_pflow_output, &en_activated_ports,
+                     pflow_output_activated_ports_handler);
 
-    const char *ext_target =
-            smap_get(&cfg->external_ids, "ovn-bridge-remote");
-    char *target = ext_target
-            ? xstrdup(ext_target)
-            : xasprintf("unix:%s/%s.mgmt", ovs_rundir(), br_int->name);
+    engine_add_input(&en_pflow_output, &en_runtime_data,
+                     pflow_output_runtime_data_handler);
+    engine_add_input(&en_pflow_output, &en_sb_encap, NULL);
+    engine_add_input(&en_pflow_output, &en_mff_ovn_geneve, NULL);
+    engine_add_input(&en_pflow_output, &en_ovs_open_vswitch, NULL);
+    engine_add_input(&en_pflow_output, &en_ovs_bridge, NULL);
+    engine_add_input(&en_pflow_output, &en_ovs_flow_sample_collector_set,
+                     pflow_output_debug_handler);
+    engine_add_input(&en_pflow_output, &en_sb_sb_global,
+                     pflow_output_debug_handler);
 
-    if (!remote->target || strcmp(remote->target, target)) {
-        free(remote->target);
-        remote->target = target;
-    } else {
-        free(target);
-    }
+    engine_add_input(&en_northd_options, &en_sb_sb_global,
+                     en_northd_options_sb_sb_global_handler);
 
-    unsigned long long probe_interval =
-            smap_get_ullong(&cfg->external_ids,
-                            "ovn-bridge-remote-probe-interval", 0);
-    remote->probe_interval = MIN(probe_interval / 1000, INT_MAX);
-}
+    engine_add_input(&en_dhcp_options, &en_sb_dhcp_options, NULL);
+    engine_add_input(&en_dhcp_options, &en_sb_dhcpv6_options, NULL);
 
-static void
-ovsdb_idl_loop_next_cfg_inc(struct ovsdb_idl_loop *idl_loop)
-{
-    if (idl_loop->next_cfg == INT64_MAX) {
-        idl_loop->next_cfg = 0;
-    } else {
-        idl_loop->next_cfg++;
-    }
-}
+    engine_add_input(&en_lflow_output, &en_northd_options, NULL);
+    engine_add_input(&en_lflow_output, &en_dhcp_options, NULL);
 
-int
-main(int argc, char *argv[])
-{
-    struct unixctl_server *unixctl;
-    struct ovn_exit_args exit_args = {0};
-    struct br_int_remote br_int_remote = {0};
-    int retval;
+    /* Keep en_addr_sets before en_runtime_data because
+     * lflow_output_runtime_data_handler may *partially* reprocess a lflow when
+     * the lflow is attached to a DP group and a new DP in that DP group is
+     * added locally, i.e. reprocessing the lflow for the new DP only but not
+     * for the other DPs in the group. If we handle en_addr_sets after this,
+     * incrementally processing an updated address set for the added IPs may
+     * end up adding redundant flows/conjunctions for the lflow agaist the new
+     * DP because it has been processed on the DP already. */
+    engine_add_input(&en_lflow_output, &en_addr_sets,
+                     lflow_output_addr_sets_handler);
+    engine_add_input(&en_lflow_output, &en_port_groups,
+                     lflow_output_port_groups_handler);
+    engine_add_input(&en_lflow_output, &en_template_vars,
+                     lflow_output_template_vars_handler);
+    engine_add_input(&en_lflow_output, &en_runtime_data,
+                     lflow_output_runtime_data_handler);
+    engine_add_input(&en_lflow_output, &en_non_vif_data,
+                     NULL);
 
-    /* Read from system-id-override file once on startup. */
-    file_system_id = get_file_system_id();
+    engine_add_input(&en_lflow_output, &en_sb_multicast_group,
+                     lflow_output_sb_multicast_group_handler);
 
-    ovs_cmdl_proctitle_init(argc, argv);
-    ovn_set_program_name(argv[0]);
-    service_start(&argc, &argv);
-    char *ovs_remote = parse_options(argc, argv);
-    fatal_ignore_sigpipe();
+    engine_add_input(&en_lflow_output, &en_sb_chassis,
+                     pflow_lflow_output_sb_chassis_handler);
 
-    daemonize_start(true, false);
+    engine_add_input(&en_lflow_output, &en_sb_port_binding,
+                     lflow_output_sb_port_binding_handler);
 
-    char *abs_unixctl_path = get_abs_unix_ctl_path(unixctl_path);
-    retval = unixctl_server_create(abs_unixctl_path, &unixctl);
-    free(abs_unixctl_path);
-    if (retval) {
-        exit(EXIT_FAILURE);
-    }
-    unixctl_command_register("exit", "", 0, 1, ovn_exit_command_callback,
-                             &exit_args);
+    engine_add_input(&en_lflow_output, &en_ovs_open_vswitch, NULL);
+    engine_add_input(&en_lflow_output, &en_ovs_bridge, NULL);
+    engine_add_input(&en_lflow_output, &en_ovs_flow_sample_collector_set,
+                     lflow_output_flow_sample_collector_set_handler);
 
-    daemonize_complete();
+    engine_add_input(&en_lflow_output, &en_sb_mac_binding,
+                     lflow_output_sb_mac_binding_handler);
+    engine_add_input(&en_lflow_output, &en_sb_static_mac_binding,
+                     lflow_output_sb_static_mac_binding_handler);
+    engine_add_input(&en_lflow_output, &en_sb_logical_flow,
+                     lflow_output_sb_logical_flow_handler);
+    /* Using a noop handler since we don't really need any data from datapath
+     * groups or a full recompute.  Update of a datapath group will put
+     * logical flow into the tracked list, so the logical flow handler will
+     * process all changes. */
+    engine_add_input(&en_lflow_output, &en_sb_logical_dp_group,
+                     engine_noop_handler);
 
-    /* Register ofctrl seqno types. */
-    ofctrl_seq_type_nb_cfg = ofctrl_seqno_add_type();
+    engine_add_input(&en_lflow_output, &en_lb_data,
+                     lflow_output_lb_data_handler);
+    engine_add_input(&en_lflow_output, &en_sb_fdb,
+                     lflow_output_sb_fdb_handler);
+    engine_add_input(&en_lflow_output, &en_sb_meter,
+                     lflow_output_sb_meter_handler);
 
-    patch_init();
-    pinctrl_init();
-    lflow_init();
-    mirror_init();
-    vif_plug_provider_initialize();
-    statctrl_init();
-    dns_resolve_init(true);
+    engine_add_input(&en_ct_zones, &en_ovs_open_vswitch, NULL);
+    engine_add_input(&en_ct_zones, &en_ovs_bridge, NULL);
+    engine_add_input(&en_ct_zones, &en_sb_datapath_binding,
+                     ct_zones_datapath_binding_handler);
+    engine_add_input(&en_ct_zones, &en_runtime_data,
+                     ct_zones_runtime_data_handler);
 
-    /* Connect to OVS OVSDB instance. */
-    struct ovsdb_idl_loop ovs_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
-        ovsdb_idl_create(ovs_remote, &ovsrec_idl_class, false, true));
-    ctrl_register_ovs_idl(ovs_idl_loop.idl);
+    engine_add_input(&en_ovs_interface_shadow, &en_ovs_interface,
+                     ovs_interface_shadow_ovs_interface_handler);
 
-    struct ovsdb_idl_index *ovsrec_port_by_interfaces
-        = ovsdb_idl_index_create1(ovs_idl_loop.idl,
-                                  &ovsrec_port_col_interfaces);
-    struct ovsdb_idl_index *ovsrec_port_by_name
-        = ovsdb_idl_index_create1(ovs_idl_loop.idl,
-                                  &ovsrec_port_col_name);
-    struct ovsdb_idl_index *ovsrec_port_by_qos
-        = ovsdb_idl_index_create1(ovs_idl_loop.idl,
-                                  &ovsrec_port_col_qos);
-    struct ovsdb_idl_index *ovsrec_interface_by_name
-        = ovsdb_idl_index_create1(ovs_idl_loop.idl,
-                                  &ovsrec_interface_col_name);
-    struct ovsdb_idl_index *ovsrec_queue_by_external_ids
-        = ovsdb_idl_index_create1(ovs_idl_loop.idl,
-                                  &ovsrec_queue_col_external_ids);
-    struct ovsdb_idl_index *ovsrec_flow_sample_collector_set_by_id
-        = ovsdb_idl_index_create2(ovs_idl_loop.idl,
-                                  &ovsrec_flow_sample_collector_set_col_bridge,
-                                  &ovsrec_flow_sample_collector_set_col_id);
+    engine_add_input(&en_runtime_data, &en_ofctrl_is_connected, NULL);
 
-    ovsdb_idl_get_initial_snapshot(ovs_idl_loop.idl);
+    engine_add_input(&en_runtime_data, &en_ovs_open_vswitch, NULL);
+    engine_add_input(&en_runtime_data, &en_ovs_bridge, NULL);
+    engine_add_input(&en_runtime_data, &en_ovs_qos, NULL);
+    engine_add_input(&en_runtime_data, &en_ovs_queue, NULL);
 
-    /* Configure OVN SB database. */
-    struct ovsdb_idl_loop ovnsb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
-        ovsdb_idl_create_unconnected(&sbrec_idl_class, true));
-    ovsdb_idl_set_leader_only(ovnsb_idl_loop.idl, false);
+    engine_add_input(&en_runtime_data, &en_sb_chassis, NULL);
+    engine_add_input(&en_runtime_data, &en_sb_datapath_binding,
+                     runtime_data_sb_datapath_binding_handler);
+    engine_add_input(&en_runtime_data, &en_sb_port_binding,
+                     runtime_data_sb_port_binding_handler);
+    /* Reuse the same handler for any previously postponed ports. */
+    engine_add_input(&en_runtime_data, &en_postponed_ports,
+                     runtime_data_sb_port_binding_handler);
+    /* Run sb_ro_handler after port_binding_handler in case port get deleted */
+    engine_add_input(&en_runtime_data, &en_sb_ro, runtime_data_sb_ro_handler);
 
-    unixctl_command_register("connection-status", "", 0, 0,
-                             ovn_conn_show, ovnsb_idl_loop.idl);
+    /* The OVS interface handler for runtime_data changes MUST be executed
+     * after the sb_port_binding_handler as port_binding deletes must be
+     * processed first.
+     *
+     * runtime_data needs to access the OVS Port data and hence a noop
+     * handler.
+     */
+    engine_add_input(&en_runtime_data, &en_ovs_port,
+                     engine_noop_handler);
+    engine_add_input(&en_runtime_data, &en_ovs_interface_shadow,
+                     runtime_data_ovs_interface_shadow_handler);
 
-    struct ovsdb_idl_index *sbrec_chassis_by_name
-        = chassis_index_create(ovnsb_idl_loop.idl);
-    struct ovsdb_idl_index *sbrec_chassis_private_by_name
-        = chassis_private_index_create(ovnsb_idl_loop.idl);
+    engine_add_input(&en_mac_cache, &en_runtime_data,
+                     mac_cache_runtime_data_handler);
+    engine_add_input(&en_mac_cache, &en_sb_mac_binding,
+                     mac_cache_sb_mac_binding_handler);
+    engine_add_input(&en_mac_cache, &en_sb_fdb,
+                     mac_cache_sb_fdb_handler);
+    engine_add_input(&en_mac_cache, &en_sb_datapath_binding,
+                     mac_cache_sb_datapath_binding_handler);
+    engine_add_input(&en_mac_cache, &en_sb_port_binding,
+                     engine_noop_handler);
+
+    engine_add_input(&en_dns_cache, &en_sb_dns,
+                     dns_cache_sb_dns_handler);
+
+    engine_add_input(&en_garp_rarp, &en_ovs_open_vswitch, NULL);
+    engine_add_input(&en_garp_rarp, &en_sb_chassis, NULL);
+    engine_add_input(&en_garp_rarp, &en_sb_port_binding,
+                     garp_rarp_sb_port_binding_handler);
+    engine_add_input(&en_garp_rarp, &en_sb_datapath_binding,
+                     garp_rarp_sb_datapath_binding_handler);
+    /* The mac_binding data is just used in an index to filter duplicates when
+     * inserting data to the southbound. */
+    engine_add_input(&en_garp_rarp, &en_sb_mac_binding, engine_noop_handler);
+    engine_add_input(&en_garp_rarp, &en_runtime_data,
+                     garp_rarp_runtime_data_handler);
+
+    engine_add_input(&en_neighbor, &en_ovs_open_vswitch, NULL);
+    engine_add_input(&en_neighbor, &en_sb_chassis, NULL);
+    engine_add_input(&en_neighbor, &en_sb_advertised_mac_binding, NULL);
+    engine_add_input(&en_neighbor, &en_runtime_data,
+                     neighbor_runtime_data_handler);
+    engine_add_input(&en_neighbor, &en_sb_datapath_binding,
+                     neighbor_sb_datapath_binding_handler);
+    engine_add_input(&en_neighbor, &en_sb_port_binding,
+                     neighbor_sb_port_binding_handler);
+    engine_add_input(&en_neighbor_exchange, &en_neighbor, NULL);
+    engine_add_input(&en_neighbor_exchange, &en_host_if_monitor, NULL);
+    engine_add_input(&en_neighbor_exchange, &en_neighbor_table_notify, NULL);
+    engine_add_input(&en_neighbor_exchange, &en_neighbor_exchange_status,
+                     NULL);
+
+    engine_add_input(&en_evpn_vtep_binding, &en_ovs_open_vswitch, NULL);
+    engine_add_input(&en_evpn_vtep_binding, &en_ovs_bridge, NULL);
+    engine_add_input(&en_evpn_vtep_binding, &en_neighbor_exchange, NULL);
+    /* The runtime_data are needed only for local datapaths, any update of
+     * local datapath will be reflected via en_neighbor_exchange. */
+    engine_add_input(&en_evpn_vtep_binding, &en_runtime_data,
+                     engine_noop_handler);
+    engine_add_input(&en_evpn_vtep_binding, &en_ovs_interface,
+                     evpn_vtep_binding_ovs_interface_handler);
+    engine_add_input(&en_evpn_vtep_binding, &en_sb_datapath_binding,
+                     evpn_vtep_binding_datapath_binding_handler);
+
+    engine_add_input(&en_evpn_fdb, &en_neighbor_exchange, NULL);
+    engine_add_input(&en_evpn_fdb, &en_evpn_vtep_binding,
+                     evpn_fdb_vtep_binding_handler);
+
+    engine_add_input(&en_evpn_arp, &en_neighbor_exchange, NULL);
+    engine_add_input(&en_evpn_arp, &en_evpn_vtep_binding,
+                     evpn_arp_vtep_binding_handler);
+
+    engine_add_input(&en_pflow_output, &en_evpn_vtep_binding,
+                     pflow_output_evpn_binding_handler);
+    engine_add_input(&en_pflow_output, &en_evpn_fdb,
+                     pflow_output_fdb_handler);
+    engine_add_input(&en_pflow_output, &en_evpn_arp,
+                     pflow_output_arp_handler);
+
+    engine_add_input(&en_controller_output, &en_dns_cache,
+                     NULL);
+    engine_add_input(&en_controller_output, &en_lflow_output,
+                     controller_output_lflow_output_handler);
+    engine_add_input(&en_controller_output, &en_pflow_output,
+                     controller_output_pflow_output_handler);
+    engine_add_input(&en_controller_output, &en_mac_cache,
+                     controller_output_mac_cache_handler);
+    engine_add_input(&en_controller_output, &en_bfd_chassis,
+                     controller_output_bfd_chassis_handler);
+    engine_add_input(&en_controller_output, &en_route_exchange,
+                     controller_output_route_exchange_handler);
+    engine_add_input(&en_controller_output, &en_garp_rarp,
+                     controller_output_garp_rarp_handler);
+
+    engine_add_input(&en_acl_id, &en_sb_acl_id, NULL);
+    engine_add_input(&en_controller_output, &en_acl_id,
+                     controller_output_acl_id_handler);
+
+    struct engine_arg engine_arg = {
+        .sb_idl = sb_idl_loop->idl,
+        .ovs_idl = ovs_idl_loop->idl,
+    };
+    engine_init(&en_controller_output, &engine_arg);
+
+    engine_ovsdb_node_add_index(&en_sb_chassis, "name", sbrec_chassis_by_name);
     struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath
-        = mcast_group_index_create(ovnsb_idl_loop.idl);
-    struct ovsdb_idl_index *sbrec_meter_by_name
-        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl, &sbrec_meter_col_name);
+        = mcast_group_index_create(sb_idl_loop->idl);
+    engine_ovsdb_node_add_index(&en_sb_multicast_group, "name_datapath",
+                                sbrec_multicast_group_by_name_datapath);
+
     struct ovsdb_idl_index *sbrec_logical_flow_by_logical_datapath
-        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
+        = ovsdb_idl_index_create1(sb_idl_loop->idl,
                                   &sbrec_logical_flow_col_logical_datapath);
+    engine_ovsdb_node_add_index(&en_sb_logical_flow, "logical_datapath",
+                                sbrec_logical_flow_by_logical_datapath);
+
     struct ovsdb_idl_index *sbrec_logical_flow_by_logical_dp_group
-        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
+        = ovsdb_idl_index_create1(sb_idl_loop->idl,
                                   &sbrec_logical_flow_col_logical_dp_group);
-    struct ovsdb_idl_index *sbrec_port_binding_by_name
-        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
-                                  &sbrec_port_binding_col_logical_port);
-    struct ovsdb_idl_index *sbrec_port_binding_by_key
-        = ovsdb_idl_index_create2(ovnsb_idl_loop.idl,
-                                  &sbrec_port_binding_col_tunnel_key,
-                                  &sbrec_port_binding_col_datapath);
+    engine_ovsdb_node_add_index(&en_sb_logical_flow, "logical_dp_group",
+                                sbrec_logical_flow_by_logical_dp_group);
+
+    engine_ovsdb_node_add_index(&en_sb_port_binding, "name",
+                                sbrec_port_binding_by_name);
+
+    engine_ovsdb_node_add_index(&en_sb_port_binding, "key",
+                                sbrec_port_binding_by_key);
+
     struct ovsdb_idl_index *sbrec_port_binding_by_datapath
-        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
+        = ovsdb_idl_index_create1(sb_idl_loop->idl,
                                   &sbrec_port_binding_col_datapath);
-    struct ovsdb_idl_index *sbrec_port_binding_by_type
-        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
-                                  &sbrec_port_binding_col_type);
-    struct ovsdb_idl_index *sbrec_port_binding_by_requested_chassis
-        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
-                                  &sbrec_port_binding_col_requested_chassis);
-    struct ovsdb_idl_index *sbrec_datapath_binding_by_key
-        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
-                                  &sbrec_datapath_binding_col_tunnel_key);
-    struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip
-        = mac_binding_by_lport_ip_index_create(ovnsb_idl_loop.idl);
-    struct ovsdb_idl_index *sbrec_ip_multicast
-        = ip_mcast_index_create(ovnsb_idl_loop.idl);
-    struct ovsdb_idl_index *sbrec_igmp_group
-        = igmp_group_index_create(ovnsb_idl_loop.idl);
+    engine_ovsdb_node_add_index(&en_sb_port_binding, "datapath",
+                                sbrec_port_binding_by_datapath);
+
+    engine_ovsdb_node_add_index(&en_sb_datapath_binding, "key",
+                                sbrec_datapath_binding_by_key);
+
     struct ovsdb_idl_index *sbrec_fdb_by_dp_key
-        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
-                                  &sbrec_fdb_col_dp_key);
-    struct ovsdb_idl_index *sbrec_fdb_by_dp_key_mac
-        = ovsdb_idl_index_create2(ovnsb_idl_loop.idl,
-                                  &sbrec_fdb_col_mac,
+        = ovsdb_idl_index_create1(sb_idl_loop->idl,
                                   &sbrec_fdb_col_dp_key);
+    engine_ovsdb_node_add_index(&en_sb_fdb, "dp_key",
+                                sbrec_fdb_by_dp_key);
+
     struct ovsdb_idl_index *sbrec_mac_binding_by_datapath
-        = mac_binding_by_datapath_index_create(ovnsb_idl_loop.idl);
+        = mac_binding_by_datapath_index_create(sb_idl_loop->idl);
+    engine_ovsdb_node_add_index(&en_sb_mac_binding, "datapath",
+                                sbrec_mac_binding_by_datapath);
+
     struct ovsdb_idl_index *sbrec_static_mac_binding_by_datapath
-        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
+        = ovsdb_idl_index_create1(sb_idl_loop->idl,
                                   &sbrec_static_mac_binding_col_datapath);
+    engine_ovsdb_node_add_index(&en_sb_static_mac_binding, "datapath",
+                                sbrec_static_mac_binding_by_datapath);
+
     struct ovsdb_idl_index *sbrec_chassis_template_var_index_by_chassis
-        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
+        = ovsdb_idl_index_create1(sb_idl_loop->idl,
                                   &sbrec_chassis_template_var_col_chassis);
+    engine_ovsdb_node_add_index(&en_sb_chassis_template_var, "chassis",
+                                sbrec_chassis_template_var_index_by_chassis);
+
     struct ovsdb_idl_index *sbrec_learned_route_index_by_datapath
-        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
+        = ovsdb_idl_index_create1(sb_idl_loop->idl,
                                   &sbrec_learned_route_col_datapath);
+    engine_ovsdb_node_add_index(&en_sb_learned_route, "datapath",
+                                sbrec_learned_route_index_by_datapath);
+
     struct ovsdb_idl_index *sbrec_advertised_mac_binding_index_by_dp
-        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
+        = ovsdb_idl_index_create1(sb_idl_loop->idl,
                                   &sbrec_advertised_mac_binding_col_datapath);
-    struct ovsdb_idl_index *sbrec_encaps_index_by_ip_and_type
-        = ovsdb_idl_index_create2(ovnsb_idl_loop.idl,
-                                  &sbrec_encap_col_type, &sbrec_encap_col_ip);
+    engine_ovsdb_node_add_index(&en_sb_advertised_mac_binding, "datapath",
+                                sbrec_advertised_mac_binding_index_by_dp);
 
-    ovsdb_idl_track_add_all(ovnsb_idl_loop.idl);
-    ovsdb_idl_omit_alert(ovnsb_idl_loop.idl,
-                         &sbrec_chassis_private_col_nb_cfg);
-    ovsdb_idl_omit_alert(ovnsb_idl_loop.idl,
-                         &sbrec_chassis_private_col_nb_cfg_timestamp);
-    /* Omit the timestamp columns of the MAC_Binding and FDB tables.
-     * ovn-controller doesn't need to react to changes in timestamp
-     * values (it does read them to implement aging).  Therefore we
-     * can disable change tracking and alerting for these columns. */
-    ovsdb_idl_omit_alert(ovnsb_idl_loop.idl, &sbrec_mac_binding_col_timestamp);
-    ovsdb_idl_omit_alert(ovnsb_idl_loop.idl, &sbrec_fdb_col_timestamp);
+    engine_ovsdb_node_add_index(&en_sb_mac_binding, "lport_ip",
+                                sbrec_mac_binding_by_lport_ip);
 
-    /* Omit the external_ids column of all the tables except for -
-     *  - DNS. pinctrl.c uses the external_ids column of DNS,
-     *    which it shouldn't. This should be removed.
-     *
-     *  - Datapath_binding - lflow.c is using this to check if the datapath
-     *                       is switch or not. This should be removed.
-     * */
+    engine_ovsdb_node_add_index(&en_ovs_flow_sample_collector_set, "id",
+                                ovsrec_flow_sample_collector_set_by_id);
+    engine_ovsdb_node_add_index(&en_ovs_port, "qos", ovsrec_port_by_qos);
+    engine_ovsdb_node_add_index(&en_ovs_interface, "name",
+                                ovsrec_interface_by_name);
+    engine_ovsdb_node_add_index(&en_ovs_queue, "external_ids",
+                                ovsrec_queue_by_external_ids);
+}
 
-    ovsdb_idl_omit(ovnsb_idl_loop.idl, &sbrec_sb_global_col_external_ids);
-    ovsdb_idl_omit(ovnsb_idl_loop.idl, &sbrec_logical_flow_col_external_ids);
-    ovsdb_idl_omit(ovnsb_idl_loop.idl, &sbrec_port_binding_col_external_ids);
-    ovsdb_idl_omit(ovnsb_idl_loop.idl, &sbrec_ssl_col_external_ids);
-    ovsdb_idl_omit(ovnsb_idl_loop.idl,
-                   &sbrec_gateway_chassis_col_external_ids);
+/* Returns false if the northd internal version stored in SB_Global
+ * and ovn-controller internal version don't match.
+ */
+static bool
+check_northd_version(struct ovsdb_idl *ovs_idl, struct ovsdb_idl *ovnsb_idl,
+                     const char *version)
+{
+    static bool version_mismatch;
+
+    const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(ovs_idl);
+    const struct ovsrec_open_vswitch_table *ovs_table =
+        ovsrec_open_vswitch_table_get(ovs_idl);
+    const char *chassis_id = get_ovs_chassis_id(ovs_table);
+    if (!cfg || !get_chassis_external_id_value_bool(
+                     &cfg->external_ids, chassis_id,
+                     "ovn-match-northd-version", false)) {
+        version_mismatch = false;
+        return true;
+    }
+
+    const struct sbrec_sb_global *sb = sbrec_sb_global_first(ovnsb_idl);
+    if (!sb) {
+        version_mismatch = true;
+        return false;
+    }
+
+    const char *northd_version =
+        smap_get_def(&sb->options, "northd_internal_version", "");
+
+    if (strcmp(northd_version, version)) {
+        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+        VLOG_WARN_RL(&rl, "controller version - %s mismatch with northd "
+                     "version - %s", version, northd_version);
+        version_mismatch = true;
+        return false;
+    }
+
+    /* If there used to be a mismatch and ovn-northd got updated, force a
+     * full recompute.
+     */
+    if (version_mismatch) {
+        engine_set_force_recompute();
+    }
+    version_mismatch = false;
+    return true;
+}
+
+static void
+br_int_remote_update(struct br_int_remote *remote,
+                     const struct ovsrec_bridge *br_int,
+                     const struct ovsrec_open_vswitch_table *ovs_table)
+{
+    if (!br_int) {
+        return;
+    }
+
+    const struct ovsrec_open_vswitch *cfg =
+            ovsrec_open_vswitch_table_first(ovs_table);
+
+    const char *ext_target =
+            smap_get(&cfg->external_ids, "ovn-bridge-remote");
+    char *target = ext_target
+            ? xstrdup(ext_target)
+            : xasprintf("unix:%s/%s.mgmt", ovs_rundir(), br_int->name);
+
+    if (!remote->target || strcmp(remote->target, target)) {
+        free(remote->target);
+        remote->target = target;
+    } else {
+        free(target);
+    }
+
+    unsigned long long probe_interval =
+            smap_get_ullong(&cfg->external_ids,
+                            "ovn-bridge-remote-probe-interval", 0);
+    remote->probe_interval = MIN(probe_interval / 1000, INT_MAX);
+}
+
+static void
+ovsdb_idl_loop_next_cfg_inc(struct ovsdb_idl_loop *idl_loop)
+{
+    if (idl_loop->next_cfg == INT64_MAX) {
+        idl_loop->next_cfg = 0;
+    } else {
+        idl_loop->next_cfg++;
+    }
+}
+
+int
+main(int argc, char *argv[])
+{
+    struct unixctl_server *unixctl;
+    struct ovn_exit_args exit_args = {0};
+    struct br_int_remote br_int_remote = {0};
+    int retval;
+
+    /* Read from system-id-override file once on startup. */
+    file_system_id = get_file_system_id();
+
+    ovs_cmdl_proctitle_init(argc, argv);
+    ovn_set_program_name(argv[0]);
+    service_start(&argc, &argv);
+    char *ovs_remote = parse_options(argc, argv);
+    fatal_ignore_sigpipe();
+
+    daemonize_start(true, false);
+
+    char *abs_unixctl_path = get_abs_unix_ctl_path(unixctl_path);
+    retval = unixctl_server_create(abs_unixctl_path, &unixctl);
+    free(abs_unixctl_path);
+    if (retval) {
+        exit(EXIT_FAILURE);
+    }
+    unixctl_command_register("exit", "", 0, 1, ovn_exit_command_callback,
+                             &exit_args);
+
+    daemonize_complete();
+
+    /* Register ofctrl seqno types. */
+    ofctrl_seq_type_nb_cfg = ofctrl_seqno_add_type();
+
+    patch_init();
+    pinctrl_init();
+    lflow_init();
+    mirror_init();
+    vif_plug_provider_initialize();
+    statctrl_init();
+    dns_resolve_init(true);
+
+    /* Connect to OVS OVSDB instance. */
+    struct ovsdb_idl_loop ovs_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
+        ovsdb_idl_create(ovs_remote, &ovsrec_idl_class, false, true));
+    ctrl_register_ovs_idl(ovs_idl_loop.idl);
+
+    struct ovsdb_idl_index *ovsrec_port_by_interfaces
+        = ovsdb_idl_index_create1(ovs_idl_loop.idl,
+                                  &ovsrec_port_col_interfaces);
+    struct ovsdb_idl_index *ovsrec_port_by_name
+        = ovsdb_idl_index_create1(ovs_idl_loop.idl,
+                                  &ovsrec_port_col_name);
+    struct ovsdb_idl_index *ovsrec_port_by_qos
+        = ovsdb_idl_index_create1(ovs_idl_loop.idl,
+                                  &ovsrec_port_col_qos);
+    struct ovsdb_idl_index *ovsrec_interface_by_name
+        = ovsdb_idl_index_create1(ovs_idl_loop.idl,
+                                  &ovsrec_interface_col_name);
+    struct ovsdb_idl_index *ovsrec_flow_sample_collector_set_by_id
+        = ovsdb_idl_index_create2(ovs_idl_loop.idl,
+                                  &ovsrec_flow_sample_collector_set_col_bridge,
+                                  &ovsrec_flow_sample_collector_set_col_id);
+    struct ovsdb_idl_index *ovsrec_queue_by_external_ids
+        = ovsdb_idl_index_create1(ovs_idl_loop.idl,
+                                  &ovsrec_queue_col_external_ids);
+
+    ovsdb_idl_get_initial_snapshot(ovs_idl_loop.idl);
+
+    /* Configure OVN SB database. */
+    struct ovsdb_idl_loop ovnsb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
+        ovsdb_idl_create_unconnected(&sbrec_idl_class, true));
+    ovsdb_idl_set_leader_only(ovnsb_idl_loop.idl, false);
+
+    unixctl_command_register("connection-status", "", 0, 0,
+                             ovn_conn_show, ovnsb_idl_loop.idl);
+
+    struct ovsdb_idl_index *sbrec_chassis_by_name
+        = chassis_index_create(ovnsb_idl_loop.idl);
+    struct ovsdb_idl_index *sbrec_chassis_private_by_name
+        = chassis_private_index_create(ovnsb_idl_loop.idl);
+    struct ovsdb_idl_index *sbrec_meter_by_name
+        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl, &sbrec_meter_col_name);
+    struct ovsdb_idl_index *sbrec_port_binding_by_name
+        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
+                                  &sbrec_port_binding_col_logical_port);
+    struct ovsdb_idl_index *sbrec_port_binding_by_key
+        = ovsdb_idl_index_create2(ovnsb_idl_loop.idl,
+                                  &sbrec_port_binding_col_tunnel_key,
+                                  &sbrec_port_binding_col_datapath);
+    struct ovsdb_idl_index *sbrec_port_binding_by_type
+        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
+                                  &sbrec_port_binding_col_type);
+    struct ovsdb_idl_index *sbrec_port_binding_by_requested_chassis
+        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
+                                  &sbrec_port_binding_col_requested_chassis);
+    struct ovsdb_idl_index *sbrec_datapath_binding_by_key
+        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
+                                  &sbrec_datapath_binding_col_tunnel_key);
+    struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip
+        = mac_binding_by_lport_ip_index_create(ovnsb_idl_loop.idl);
+    struct ovsdb_idl_index *sbrec_ip_multicast
+        = ip_mcast_index_create(ovnsb_idl_loop.idl);
+    struct ovsdb_idl_index *sbrec_igmp_group
+        = igmp_group_index_create(ovnsb_idl_loop.idl);
+    struct ovsdb_idl_index *sbrec_fdb_by_dp_key_mac
+        = ovsdb_idl_index_create2(ovnsb_idl_loop.idl,
+                                  &sbrec_fdb_col_mac,
+                                  &sbrec_fdb_col_dp_key);
+    struct ovsdb_idl_index *sbrec_encaps_index_by_ip_and_type
+        = ovsdb_idl_index_create2(ovnsb_idl_loop.idl,
+                                  &sbrec_encap_col_type, &sbrec_encap_col_ip);
+
+    ovsdb_idl_track_add_all(ovnsb_idl_loop.idl);
+    ovsdb_idl_omit_alert(ovnsb_idl_loop.idl,
+                         &sbrec_chassis_private_col_nb_cfg);
+    ovsdb_idl_omit_alert(ovnsb_idl_loop.idl,
+                         &sbrec_chassis_private_col_nb_cfg_timestamp);
+    /* Omit the timestamp columns of the MAC_Binding and FDB tables.
+     * ovn-controller doesn't need to react to changes in timestamp
+     * values (it does read them to implement aging).  Therefore we
+     * can disable change tracking and alerting for these columns. */
+    ovsdb_idl_omit_alert(ovnsb_idl_loop.idl, &sbrec_mac_binding_col_timestamp);
+    ovsdb_idl_omit_alert(ovnsb_idl_loop.idl, &sbrec_fdb_col_timestamp);
+
+    /* Omit the external_ids column of all the tables except for -
+     *  - DNS. pinctrl.c uses the external_ids column of DNS,
+     *    which it shouldn't. This should be removed.
+     *
+     *  - Datapath_binding - lflow.c is using this to check if the datapath
+     *                       is switch or not. This should be removed.
+     * */
+
+    ovsdb_idl_omit(ovnsb_idl_loop.idl, &sbrec_sb_global_col_external_ids);
+    ovsdb_idl_omit(ovnsb_idl_loop.idl, &sbrec_logical_flow_col_external_ids);
+    ovsdb_idl_omit(ovnsb_idl_loop.idl, &sbrec_port_binding_col_external_ids);
+    ovsdb_idl_omit(ovnsb_idl_loop.idl, &sbrec_ssl_col_external_ids);
+    ovsdb_idl_omit(ovnsb_idl_loop.idl,
+                   &sbrec_gateway_chassis_col_external_ids);
     ovsdb_idl_omit(ovnsb_idl_loop.idl, &sbrec_ha_chassis_col_external_ids);
     ovsdb_idl_omit(ovnsb_idl_loop.idl,
                    &sbrec_ha_chassis_group_col_external_ids);
@@ -6879,327 +7231,16 @@ main(int argc, char *argv[])
     stopwatch_create(BFD_RUN_STOPWATCH_NAME, SW_MS);
     stopwatch_create(VIF_PLUG_RUN_STOPWATCH_NAME, SW_MS);
 
-    /* Add dependencies between inc-proc-engine nodes. */
-    engine_add_input(&en_template_vars, &en_ovs_open_vswitch, NULL);
-    engine_add_input(&en_template_vars, &en_sb_chassis, NULL);
-    engine_add_input(&en_template_vars, &en_sb_chassis_template_var,
-                     template_vars_sb_chassis_template_var_handler);
-
-    engine_add_input(&en_lb_data, &en_sb_load_balancer,
-                     lb_data_sb_load_balancer_handler);
-    engine_add_input(&en_lb_data, &en_template_vars,
-                     lb_data_template_var_handler);
-    engine_add_input(&en_lb_data, &en_runtime_data,
-                     lb_data_runtime_data_handler);
-
-    engine_add_input(&en_route, &en_ovs_open_vswitch, NULL);
-    engine_add_input(&en_route, &en_sb_chassis, NULL);
-    engine_add_input(&en_route, &en_sb_port_binding,
-                     route_sb_port_binding_data_handler);
-    engine_add_input(&en_route, &en_runtime_data,
-                     route_runtime_data_handler);
-    engine_add_input(&en_route, &en_sb_advertised_route,
-                     route_sb_advertised_route_data_handler);
-
-    engine_add_input(&en_route_exchange, &en_route, NULL);
-    engine_add_input(&en_route_exchange, &en_sb_learned_route,
-                     engine_noop_handler);
-    engine_add_input(&en_route_exchange, &en_sb_port_binding,
-                     engine_noop_handler);
-    engine_add_input(&en_route_exchange, &en_route_table_notify, NULL);
-    engine_add_input(&en_route_exchange, &en_route_exchange_status, NULL);
-    engine_add_input(&en_route_exchange, &en_sb_ro,
-                     route_exchange_sb_ro_handler);
-
-    engine_add_input(&en_addr_sets, &en_sb_address_set,
-                     addr_sets_sb_address_set_handler);
-    engine_add_input(&en_port_groups, &en_sb_port_group,
-                     port_groups_sb_port_group_handler);
-    /* port_groups computation requires runtime_data's lbinding_data for the
-     * locally bound ports. */
-    engine_add_input(&en_port_groups, &en_runtime_data,
-                     port_groups_runtime_data_handler);
-
-    engine_add_input(&en_non_vif_data, &en_ovs_open_vswitch, NULL);
-    engine_add_input(&en_non_vif_data, &en_ovs_bridge, NULL);
-    engine_add_input(&en_non_vif_data, &en_sb_chassis, NULL);
-    engine_add_input(&en_non_vif_data, &en_ovs_interface,
-                     non_vif_data_ovs_iface_handler);
-
-    engine_add_input(&en_if_status_mgr, &en_ovs_interface,
-                     if_status_mgr_ovs_interface_handler);
-    engine_add_input(&en_bfd_chassis, &en_ovs_open_vswitch, NULL);
-    engine_add_input(&en_bfd_chassis, &en_sb_chassis, NULL);
-    engine_add_input(&en_bfd_chassis, &en_sb_ha_chassis_group, NULL);
-
-    /* Note: The order of inputs is important, all OVS interface changes must
-     * be handled before any ct_zone changes.
-     */
-    engine_add_input(&en_pflow_output, &en_non_vif_data,
-                     NULL);
-    engine_add_input(&en_pflow_output, &en_northd_options, NULL);
-    engine_add_input(&en_pflow_output, &en_ct_zones,
-                     pflow_output_ct_zones_handler);
-    engine_add_input(&en_pflow_output, &en_sb_chassis,
-                     pflow_lflow_output_sb_chassis_handler);
-
-    engine_add_input(&en_pflow_output, &en_if_status_mgr,
-                     pflow_output_if_status_mgr_handler);
-    engine_add_input(&en_pflow_output, &en_sb_port_binding,
-                     pflow_output_sb_port_binding_handler);
-    engine_add_input(&en_pflow_output, &en_sb_multicast_group,
-                     pflow_output_sb_multicast_group_handler);
-
-    /* pflow_output needs to access the SB datapath binding and hence a noop
-     * handler.
-     */
-    engine_add_input(&en_pflow_output, &en_sb_datapath_binding,
-                     engine_noop_handler);
-    engine_add_input(&en_pflow_output, &en_activated_ports,
-                     pflow_output_activated_ports_handler);
-
-    engine_add_input(&en_pflow_output, &en_runtime_data,
-                     pflow_output_runtime_data_handler);
-    engine_add_input(&en_pflow_output, &en_sb_encap, NULL);
-    engine_add_input(&en_pflow_output, &en_mff_ovn_geneve, NULL);
-    engine_add_input(&en_pflow_output, &en_ovs_open_vswitch, NULL);
-    engine_add_input(&en_pflow_output, &en_ovs_bridge, NULL);
-    engine_add_input(&en_pflow_output, &en_ovs_flow_sample_collector_set,
-                     pflow_output_debug_handler);
-    engine_add_input(&en_pflow_output, &en_sb_sb_global,
-                     pflow_output_debug_handler);
-
-    engine_add_input(&en_northd_options, &en_sb_sb_global,
-                     en_northd_options_sb_sb_global_handler);
-
-    engine_add_input(&en_dhcp_options, &en_sb_dhcp_options, NULL);
-    engine_add_input(&en_dhcp_options, &en_sb_dhcpv6_options, NULL);
-
-    engine_add_input(&en_lflow_output, &en_northd_options, NULL);
-    engine_add_input(&en_lflow_output, &en_dhcp_options, NULL);
-
-    /* Keep en_addr_sets before en_runtime_data because
-     * lflow_output_runtime_data_handler may *partially* reprocess a lflow when
-     * the lflow is attached to a DP group and a new DP in that DP group is
-     * added locally, i.e. reprocessing the lflow for the new DP only but not
-     * for the other DPs in the group. If we handle en_addr_sets after this,
-     * incrementally processing an updated address set for the added IPs may
-     * end up adding redundant flows/conjunctions for the lflow agaist the new
-     * DP because it has been processed on the DP already. */
-    engine_add_input(&en_lflow_output, &en_addr_sets,
-                     lflow_output_addr_sets_handler);
-    engine_add_input(&en_lflow_output, &en_port_groups,
-                     lflow_output_port_groups_handler);
-    engine_add_input(&en_lflow_output, &en_template_vars,
-                     lflow_output_template_vars_handler);
-    engine_add_input(&en_lflow_output, &en_runtime_data,
-                     lflow_output_runtime_data_handler);
-    engine_add_input(&en_lflow_output, &en_non_vif_data,
-                     NULL);
-
-    engine_add_input(&en_lflow_output, &en_sb_multicast_group,
-                     lflow_output_sb_multicast_group_handler);
-
-    engine_add_input(&en_lflow_output, &en_sb_chassis,
-                     pflow_lflow_output_sb_chassis_handler);
-
-    engine_add_input(&en_lflow_output, &en_sb_port_binding,
-                     lflow_output_sb_port_binding_handler);
-
-    engine_add_input(&en_lflow_output, &en_ovs_open_vswitch, NULL);
-    engine_add_input(&en_lflow_output, &en_ovs_bridge, NULL);
-    engine_add_input(&en_lflow_output, &en_ovs_flow_sample_collector_set,
-                     lflow_output_flow_sample_collector_set_handler);
-
-    engine_add_input(&en_lflow_output, &en_sb_mac_binding,
-                     lflow_output_sb_mac_binding_handler);
-    engine_add_input(&en_lflow_output, &en_sb_static_mac_binding,
-                     lflow_output_sb_static_mac_binding_handler);
-    engine_add_input(&en_lflow_output, &en_sb_logical_flow,
-                     lflow_output_sb_logical_flow_handler);
-    /* Using a noop handler since we don't really need any data from datapath
-     * groups or a full recompute.  Update of a datapath group will put
-     * logical flow into the tracked list, so the logical flow handler will
-     * process all changes. */
-    engine_add_input(&en_lflow_output, &en_sb_logical_dp_group,
-                     engine_noop_handler);
-
-    engine_add_input(&en_lflow_output, &en_lb_data,
-                     lflow_output_lb_data_handler);
-    engine_add_input(&en_lflow_output, &en_sb_fdb,
-                     lflow_output_sb_fdb_handler);
-    engine_add_input(&en_lflow_output, &en_sb_meter,
-                     lflow_output_sb_meter_handler);
-
-    engine_add_input(&en_ct_zones, &en_ovs_open_vswitch, NULL);
-    engine_add_input(&en_ct_zones, &en_ovs_bridge, NULL);
-    engine_add_input(&en_ct_zones, &en_sb_datapath_binding,
-                     ct_zones_datapath_binding_handler);
-    engine_add_input(&en_ct_zones, &en_runtime_data,
-                     ct_zones_runtime_data_handler);
-
-    engine_add_input(&en_ovs_interface_shadow, &en_ovs_interface,
-                     ovs_interface_shadow_ovs_interface_handler);
-
-    engine_add_input(&en_runtime_data, &en_ofctrl_is_connected, NULL);
-
-    engine_add_input(&en_runtime_data, &en_ovs_open_vswitch, NULL);
-    engine_add_input(&en_runtime_data, &en_ovs_bridge, NULL);
-    engine_add_input(&en_runtime_data, &en_ovs_qos, NULL);
-    engine_add_input(&en_runtime_data, &en_ovs_queue, NULL);
-
-    engine_add_input(&en_runtime_data, &en_sb_chassis, NULL);
-    engine_add_input(&en_runtime_data, &en_sb_datapath_binding,
-                     runtime_data_sb_datapath_binding_handler);
-    engine_add_input(&en_runtime_data, &en_sb_port_binding,
-                     runtime_data_sb_port_binding_handler);
-    /* Reuse the same handler for any previously postponed ports. */
-    engine_add_input(&en_runtime_data, &en_postponed_ports,
-                     runtime_data_sb_port_binding_handler);
-    /* Run sb_ro_handler after port_binding_handler in case port get deleted */
-    engine_add_input(&en_runtime_data, &en_sb_ro, runtime_data_sb_ro_handler);
-
-    /* The OVS interface handler for runtime_data changes MUST be executed
-     * after the sb_port_binding_handler as port_binding deletes must be
-     * processed first.
-     *
-     * runtime_data needs to access the OVS Port data and hence a noop
-     * handler.
-     */
-    engine_add_input(&en_runtime_data, &en_ovs_port,
-                     engine_noop_handler);
-    engine_add_input(&en_runtime_data, &en_ovs_interface_shadow,
-                     runtime_data_ovs_interface_shadow_handler);
-
-    engine_add_input(&en_mac_cache, &en_runtime_data,
-                     mac_cache_runtime_data_handler);
-    engine_add_input(&en_mac_cache, &en_sb_mac_binding,
-                     mac_cache_sb_mac_binding_handler);
-    engine_add_input(&en_mac_cache, &en_sb_fdb,
-                     mac_cache_sb_fdb_handler);
-    engine_add_input(&en_mac_cache, &en_sb_datapath_binding,
-                     mac_cache_sb_datapath_binding_handler);
-    engine_add_input(&en_mac_cache, &en_sb_port_binding,
-                     engine_noop_handler);
-
-    engine_add_input(&en_dns_cache, &en_sb_dns,
-                     dns_cache_sb_dns_handler);
-
-    engine_add_input(&en_garp_rarp, &en_ovs_open_vswitch, NULL);
-    engine_add_input(&en_garp_rarp, &en_sb_chassis, NULL);
-    engine_add_input(&en_garp_rarp, &en_sb_port_binding,
-                     garp_rarp_sb_port_binding_handler);
-    engine_add_input(&en_garp_rarp, &en_sb_datapath_binding,
-                     garp_rarp_sb_datapath_binding_handler);
-    /* The mac_binding data is just used in an index to filter duplicates when
-     * inserting data to the southbound. */
-    engine_add_input(&en_garp_rarp, &en_sb_mac_binding, engine_noop_handler);
-    engine_add_input(&en_garp_rarp, &en_runtime_data,
-                     garp_rarp_runtime_data_handler);
-
-    engine_add_input(&en_neighbor, &en_ovs_open_vswitch, NULL);
-    engine_add_input(&en_neighbor, &en_sb_chassis, NULL);
-    engine_add_input(&en_neighbor, &en_sb_advertised_mac_binding, NULL);
-    engine_add_input(&en_neighbor, &en_runtime_data,
-                     neighbor_runtime_data_handler);
-    engine_add_input(&en_neighbor, &en_sb_datapath_binding,
-                     neighbor_sb_datapath_binding_handler);
-    engine_add_input(&en_neighbor, &en_sb_port_binding,
-                     neighbor_sb_port_binding_handler);
-    engine_add_input(&en_neighbor_exchange, &en_neighbor, NULL);
-    engine_add_input(&en_neighbor_exchange, &en_host_if_monitor, NULL);
-    engine_add_input(&en_neighbor_exchange, &en_neighbor_table_notify, NULL);
-    engine_add_input(&en_neighbor_exchange, &en_neighbor_exchange_status,
-                     NULL);
-
-    engine_add_input(&en_evpn_vtep_binding, &en_ovs_open_vswitch, NULL);
-    engine_add_input(&en_evpn_vtep_binding, &en_ovs_bridge, NULL);
-    engine_add_input(&en_evpn_vtep_binding, &en_neighbor_exchange, NULL);
-    /* The runtime_data are needed only for local datapaths, any update of
-     * local datapath will be reflected via en_neighbor_exchange. */
-    engine_add_input(&en_evpn_vtep_binding, &en_runtime_data,
-                     engine_noop_handler);
-    engine_add_input(&en_evpn_vtep_binding, &en_ovs_interface,
-                     evpn_vtep_binding_ovs_interface_handler);
-    engine_add_input(&en_evpn_vtep_binding, &en_sb_datapath_binding,
-                     evpn_vtep_binding_datapath_binding_handler);
-
-    engine_add_input(&en_evpn_fdb, &en_neighbor_exchange, NULL);
-    engine_add_input(&en_evpn_fdb, &en_evpn_vtep_binding,
-                     evpn_fdb_vtep_binding_handler);
-
-    engine_add_input(&en_evpn_arp, &en_neighbor_exchange, NULL);
-    engine_add_input(&en_evpn_arp, &en_evpn_vtep_binding,
-                     evpn_arp_vtep_binding_handler);
-
-    engine_add_input(&en_pflow_output, &en_evpn_vtep_binding,
-                     pflow_output_evpn_binding_handler);
-    engine_add_input(&en_pflow_output, &en_evpn_fdb,
-                     pflow_output_fdb_handler);
-    engine_add_input(&en_pflow_output, &en_evpn_arp,
-                     pflow_output_arp_handler);
-
-    engine_add_input(&en_controller_output, &en_dns_cache,
-                     NULL);
-    engine_add_input(&en_controller_output, &en_lflow_output,
-                     controller_output_lflow_output_handler);
-    engine_add_input(&en_controller_output, &en_pflow_output,
-                     controller_output_pflow_output_handler);
-    engine_add_input(&en_controller_output, &en_mac_cache,
-                     controller_output_mac_cache_handler);
-    engine_add_input(&en_controller_output, &en_bfd_chassis,
-                     controller_output_bfd_chassis_handler);
-    engine_add_input(&en_controller_output, &en_route_exchange,
-                     controller_output_route_exchange_handler);
-    engine_add_input(&en_controller_output, &en_garp_rarp,
-                     controller_output_garp_rarp_handler);
-
-    engine_add_input(&en_acl_id, &en_sb_acl_id, NULL);
-    engine_add_input(&en_controller_output, &en_acl_id,
-                     controller_output_acl_id_handler);
-
-    struct engine_arg engine_arg = {
-        .sb_idl = ovnsb_idl_loop.idl,
-        .ovs_idl = ovs_idl_loop.idl,
-    };
-    engine_init(&en_controller_output, &engine_arg);
-
-    engine_ovsdb_node_add_index(&en_sb_chassis, "name", sbrec_chassis_by_name);
-    engine_ovsdb_node_add_index(&en_sb_multicast_group, "name_datapath",
-                                sbrec_multicast_group_by_name_datapath);
-    engine_ovsdb_node_add_index(&en_sb_logical_flow, "logical_datapath",
-                                sbrec_logical_flow_by_logical_datapath);
-    engine_ovsdb_node_add_index(&en_sb_logical_flow, "logical_dp_group",
-                                sbrec_logical_flow_by_logical_dp_group);
-    engine_ovsdb_node_add_index(&en_sb_port_binding, "name",
-                                sbrec_port_binding_by_name);
-    engine_ovsdb_node_add_index(&en_sb_port_binding, "key",
-                                sbrec_port_binding_by_key);
-    engine_ovsdb_node_add_index(&en_sb_port_binding, "datapath",
-                                sbrec_port_binding_by_datapath);
-    engine_ovsdb_node_add_index(&en_sb_datapath_binding, "key",
-                                sbrec_datapath_binding_by_key);
-    engine_ovsdb_node_add_index(&en_sb_fdb, "dp_key",
-                                sbrec_fdb_by_dp_key);
-    engine_ovsdb_node_add_index(&en_sb_mac_binding, "datapath",
-                                sbrec_mac_binding_by_datapath);
-    engine_ovsdb_node_add_index(&en_sb_static_mac_binding, "datapath",
-                                sbrec_static_mac_binding_by_datapath);
-    engine_ovsdb_node_add_index(&en_sb_chassis_template_var, "chassis",
-                                sbrec_chassis_template_var_index_by_chassis);
-    engine_ovsdb_node_add_index(&en_sb_learned_route, "datapath",
-                                sbrec_learned_route_index_by_datapath);
-    engine_ovsdb_node_add_index(&en_sb_advertised_mac_binding, "datapath",
-                                sbrec_advertised_mac_binding_index_by_dp);
-    engine_ovsdb_node_add_index(&en_sb_mac_binding, "lport_ip",
-                                sbrec_mac_binding_by_lport_ip);
-    engine_ovsdb_node_add_index(&en_ovs_flow_sample_collector_set, "id",
-                                ovsrec_flow_sample_collector_set_by_id);
-    engine_ovsdb_node_add_index(&en_ovs_port, "qos", ovsrec_port_by_qos);
-    engine_ovsdb_node_add_index(&en_ovs_interface, "name",
-                                ovsrec_interface_by_name);
-    engine_ovsdb_node_add_index(&en_ovs_queue, "external_ids",
-                                ovsrec_queue_by_external_ids);
+    inc_proc_ovn_controller_init(&ovnsb_idl_loop, &ovs_idl_loop,
+                                 sbrec_chassis_by_name,
+                                 sbrec_port_binding_by_name,
+                                 sbrec_port_binding_by_key,
+                                 sbrec_datapath_binding_by_key,
+                                 sbrec_mac_binding_by_lport_ip,
+                                 ovsrec_flow_sample_collector_set_by_id,
+                                 ovsrec_port_by_qos,
+                                 ovsrec_interface_by_name,
+                                 ovsrec_queue_by_external_ids);
 
     struct ed_type_lflow_output *lflow_output_data =
         engine_get_internal_data(&en_lflow_output);
-- 
2.51.1

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to