On Thu, Nov 27, 2025 at 06:20:33PM +0100, Dumitru Ceara via dev wrote:
> 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
> 

Looks good to me.

Acked-by: Mairtin O'Loingsigh <[email protected]>

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

Reply via email to