Hi Paulo, thanks for the series! Overall, I think this is a great
setup for ovn-ic. I looked through all the patches, but I'm only going
to comment on patches 1, 2, and 6. The reason is that the types of
comments I make on these patches apply more generally to other patches
in the series as well. I try to point this out when possible.

See my comments inline below.

On Mon, Feb 9, 2026 at 1:29 PM Paulo Guilherme Silva via dev
<[email protected]> wrote:
>
> 'struct ic_data' is used to hold the global state data for the
> incremental processing node 'en_ic' and 'struct ic_input' this will
> hold references to database tables and indexes. In order to achieve this,
> we refactor in the following way:
> * Move index and tables into the main 'ic' engine
> * Adjust inputs of function 'ovn_db_run()' inside the ic engine which
>   in turn ends up calling upon the functions that manage the main groups
>   of actions spreading the new structures:
>     gateway_run();
>     enumerate_datapaths();
>     ts_run();
>     tr_run();
>     port_binding_run();
>     route_run();
>     sync_service_monitor();
> * Refactor ovn-ic.c to use 'struct ic_data' and 'struct ic_input'
>   where applicable.
>
> Signed-off-by: Paulo Guilherme Silva <[email protected]>
> ---
>  ic/en-ic.c            | 168 ++++++++++-
>  ic/en-ic.h            |   2 +-
>  ic/inc-proc-ic.c      | 154 +++++++++-
>  ic/inc-proc-ic.h      |   8 +-
>  ic/ovn-ic.c           | 682 +++++++++++++++++++-----------------------
>  ic/ovn-ic.h           |  50 +++-
>  lib/stopwatch-names.h |   2 +
>  7 files changed, 657 insertions(+), 409 deletions(-)
>
> diff --git a/ic/en-ic.c b/ic/en-ic.c
> index 2db9d3b84..ce7d5de76 100644
> --- a/ic/en-ic.c
> +++ b/ic/en-ic.c
> @@ -18,33 +18,185 @@
>  #include <stdlib.h>
>  #include <stdio.h>
>
> +/* OVS includes. */
> +#include "openvswitch/vlog.h"
> +
> +/* OVN includes. */
> +#include "ovn-ic.h"
>  #include "en-ic.h"
>  #include "lib/inc-proc-eng.h"
> +#include "lib/ovn-util.h"
>  #include "lib/stopwatch-names.h"
> -#include "ovn-ic.h"
> -#include "openvswitch/vlog.h"
> +#include "coverage.h"
> +#include "stopwatch.h"
> +#include "stopwatch-names.h"
>
>  VLOG_DEFINE_THIS_MODULE(en_ic);
> +COVERAGE_DEFINE(ic_run);
> +
> +void ic_destroy(struct ic_data *data);
> +void ic_init(struct ic_data *data);
> +
> +static void
> +ic_get_input_data(struct engine_node *node,
> +                  struct ic_input *input_data)
> +{
> +    /* Table references */
> +    input_data->nbrec_nb_global_table =
> +        EN_OVSDB_GET(engine_get_input("NB_nb_global", node));
> +    input_data->nbrec_logical_switch_table =
> +        EN_OVSDB_GET(engine_get_input("NB_logical_switch", node));
> +    input_data->nbrec_logical_router_table =
> +        EN_OVSDB_GET(engine_get_input("NB_logical_router", node));
> +    input_data->sbrec_sb_global_table =
> +        EN_OVSDB_GET(engine_get_input("SB_sb_global", node));
> +    input_data->sbrec_chassis_table =
> +        EN_OVSDB_GET(engine_get_input("SB_chassis", node));
> +    input_data->icnbrec_ic_nb_global_table =
> +        EN_OVSDB_GET(engine_get_input("ICNB_ic_nb_global", node));
> +    input_data->icnbrec_transit_switch_table =
> +        EN_OVSDB_GET(engine_get_input("ICNB_transit_switch", node));
> +    input_data->icnbrec_transit_router_table =
> +        EN_OVSDB_GET(engine_get_input("ICNB_transit_router", node));
> +    input_data->icsbrec_ic_sb_global_table =
> +        EN_OVSDB_GET(engine_get_input("ICSB_ic_sb_global", node));
> +    input_data->icsbrec_availability_zone_table =
> +        EN_OVSDB_GET(engine_get_input("ICSB_availability_zone", node));
> +    input_data->icsbrec_encap_table =
> +        EN_OVSDB_GET(engine_get_input("ICSB_encap", node));
> +    input_data->icsbrec_gateway_table =
> +        EN_OVSDB_GET(engine_get_input("ICSB_gateway", node));
> +    input_data->icsbrec_datapath_binding_table =
> +        EN_OVSDB_GET(engine_get_input("ICSB_datapath_binding", node));
> +
> +    /* Indexes */
> +    input_data->nbrec_ls_by_name =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("NB_logical_switch", node),
> +            "nbrec_ls_by_name");
> +    input_data->nbrec_lr_by_name =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("NB_logical_router", node),
> +            "nbrec_lr_by_name");
> +    input_data->nbrec_lrp_by_name =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("NB_logical_router", node),
> +            "nbrec_lrp_by_name");
> +    input_data->nbrec_port_by_name =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("NB_logical_switch", node),
> +            "nbrec_port_by_name");
> +    input_data->sbrec_chassis_by_name =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("SB_chassis", node),
> +            "sbrec_chassis_by_name");
> +    input_data->sbrec_port_binding_by_name =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("SB_port_binding", node),
> +            "sbrec_port_binding_by_name");
> +    input_data->sbrec_service_monitor_by_remote_type =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("SB_service_monitor", node),
> +            "sbrec_service_monitor_by_remote_type");
> +    input_data->sbrec_service_monitor_by_ic_learned =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("SB_service_monitor", node),
> +            "sbrec_service_monitor_by_ic_learned");
> +    input_data->sbrec_service_monitor_by_remote_type_logical_port =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("SB_service_monitor", node),
> +            "sbrec_service_monitor_by_remote_type_logical_port");
> +    input_data->icnbrec_transit_switch_by_name =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("ICNB_transit_switch", node),
> +            "icnbrec_transit_switch_by_name");
> +    input_data->icsbrec_port_binding_by_az =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("ICSB_port_binding", node),
> +            "icsbrec_port_binding_by_az");
> +    input_data->icsbrec_port_binding_by_ts =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("ICSB_port_binding", node),
> +            "icsbrec_port_binding_by_ts");
> +    input_data->icsbrec_port_binding_by_ts_az =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("ICSB_port_binding", node),
> +            "icsbrec_port_binding_by_ts_az");
> +    input_data->icsbrec_route_by_az =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("ICSB_route", node),
> +            "icsbrec_route_by_az");
> +    input_data->icsbrec_route_by_ts =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("ICSB_route", node),
> +            "icsbrec_route_by_ts");
> +    input_data->icsbrec_route_by_ts_az =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("ICSB_route", node),
> +            "icsbrec_route_by_ts_az");
> +    input_data->icsbrec_service_monitor_by_source_az =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("ICSB_service_monitor", node),
> +            "icsbrec_service_monitor_by_source_az");
> +    input_data->icsbrec_service_monitor_by_target_az =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("ICSB_service_monitor", node),
> +            "icsbrec_service_monitor_by_target_az");
> +    input_data->icsbrec_service_monitor_by_target_az_logical_port =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("ICSB_service_monitor", node),
> +            "icsbrec_service_monitor_by_target_az_logical_port");
> +}
>
>  enum engine_node_state
> -en_ic_run(struct engine_node *node OVS_UNUSED, void *data OVS_UNUSED)
> +en_ic_run(struct engine_node *node, void *data)
>  {
>      const struct engine_context *eng_ctx = engine_get_context();
> -    struct ic_context *ctx = eng_ctx->client_ctx;
>
> -    ovn_db_run(ctx);
> +    struct ic_input input_data;
> +
> +    ic_destroy(data);
> +    ic_init(data);
>
> +    ic_get_input_data(node, &input_data);
> +    input_data.runned_az = eng_ctx->client_ctx;
> +
> +    COVERAGE_INC(ic_run);
> +    stopwatch_start(IC_OVN_DB_RUN_STOPWATCH_NAME, time_msec());

A recent change to the incremental engine made it so that all
incremental engine nodes have a built-in stopwatch for their run()
callbacks. Therefore, you don't need to add this stopwatch to the new
code. This same comment applies to patches 2, 3, 4, 5, 6, 7, and 8,
since they also add similar stopwatches.

> +    ovn_db_run(&input_data, data, (struct engine_context *) eng_ctx);
> +    stopwatch_stop(IC_OVN_DB_RUN_STOPWATCH_NAME, time_msec());
>      return EN_UPDATED;
>  }
>
>  void *
>  en_ic_init(struct engine_node *node OVS_UNUSED,
> -            struct engine_arg *arg OVS_UNUSED)
> +           struct engine_arg *arg OVS_UNUSED)
> +{
> +    struct ic_data *data = xzalloc(sizeof *data);
> +
> +    ic_init(data);
> +
> +    return data;
> +}
> +
> +void
> +en_ic_cleanup(void *data)
> +{
> +    ic_destroy(data);
> +}
> +
> +void
> +ic_destroy(struct ic_data *data)
>  {
> -    return NULL;
> +    ovn_destroy_tnlids(&data->dp_tnlids);
> +    shash_destroy(&data->isb_ts_dps);
> +    shash_destroy(&data->isb_tr_dps);
>  }
>
>  void
> -en_ic_cleanup(void *data OVS_UNUSED)
> +ic_init(struct ic_data *data)
>  {
> +    hmap_init(&data->dp_tnlids);
> +    shash_init(&data->isb_ts_dps);
> +    shash_init(&data->isb_tr_dps);
>  }
> diff --git a/ic/en-ic.h b/ic/en-ic.h
> index a4b75bb0e..ab1fbaf42 100644
> --- a/ic/en-ic.h
> +++ b/ic/en-ic.h
> @@ -12,7 +12,7 @@
>  enum engine_node_state en_ic_run(struct engine_node *node OVS_UNUSED,
>                                   void *data OVS_UNUSED);
>  void *en_ic_init(struct engine_node *node OVS_UNUSED,
> -                 struct engine_arg *arg);
> +                 struct engine_arg *arg OVS_UNUSED);
>  void en_ic_cleanup(void *data);
>
>  #endif /* EN_IC_H */
> diff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c
> index ba9fdeb9e..0160c3a3e 100644
> --- a/ic/inc-proc-ic.c
> +++ b/ic/inc-proc-ic.c
> @@ -157,12 +157,13 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_ic);
>
>  /* Define engine nodes for other nodes. They should be defined as static to
>   * avoid sparse errors. */
> -static ENGINE_NODE(ic);
> +static ENGINE_NODE(ic, SB_WRITE);
>
> -void inc_proc_ic_init(struct ovsdb_idl_loop *nb,
> -                      struct ovsdb_idl_loop *sb,
> -                      struct ovsdb_idl_loop *icnb,
> -                      struct ovsdb_idl_loop *icsb)
> +void
> +inc_proc_ic_init(struct ovsdb_idl_loop *nb,
> +                 struct ovsdb_idl_loop *sb,
> +                 struct ovsdb_idl_loop *icnb,
> +                 struct ovsdb_idl_loop *icsb)
>  {
>      /* Define relationships between nodes where first argument is dependent
>       * on the second argument */
> @@ -187,11 +188,11 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,
>      engine_add_input(&en_ic, &en_icnb_transit_router, NULL);
>      engine_add_input(&en_ic, &en_icnb_transit_router_port, NULL);
>
> +    engine_add_input(&en_ic, &en_icsb_ic_sb_global, NULL);
> +    engine_add_input(&en_ic, &en_icsb_availability_zone, NULL);
>      engine_add_input(&en_ic, &en_icsb_encap, NULL);
>      engine_add_input(&en_ic, &en_icsb_service_monitor, NULL);
> -    engine_add_input(&en_ic, &en_icsb_ic_sb_global, NULL);
>      engine_add_input(&en_ic, &en_icsb_port_binding, NULL);
> -    engine_add_input(&en_ic, &en_icsb_availability_zone, NULL);
>      engine_add_input(&en_ic, &en_icsb_gateway, NULL);
>      engine_add_input(&en_ic, &en_icsb_route, NULL);
>      engine_add_input(&en_ic, &en_icsb_datapath_binding, NULL);
> @@ -203,22 +204,149 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,
>          .icsb_idl = icsb->idl,
>      };
>
> +    /* create IDL indexes*/
> +    struct ovsdb_idl_index *nbrec_ls_by_name
> +        = ovsdb_idl_index_create1(nb->idl, &nbrec_logical_switch_col_name);
> +    struct ovsdb_idl_index *nbrec_lr_by_name
> +        = ovsdb_idl_index_create1(nb->idl, &nbrec_logical_router_col_name);
> +    struct ovsdb_idl_index *nbrec_lrp_by_name
> +        = ovsdb_idl_index_create1(nb->idl,
> +                                  &nbrec_logical_router_port_col_name);
> +    struct ovsdb_idl_index *nbrec_port_by_name
> +        = ovsdb_idl_index_create1(nb->idl,
> +                                  &nbrec_logical_switch_port_col_name);
> +    struct ovsdb_idl_index *sbrec_chassis_by_name
> +        = ovsdb_idl_index_create1(sb->idl, &sbrec_chassis_col_name);
> +    struct ovsdb_idl_index *sbrec_port_binding_by_name
> +        = ovsdb_idl_index_create1(sb->idl,
> +                                  &sbrec_port_binding_col_logical_port);
> +    struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type
> +        = ovsdb_idl_index_create1(sb->idl,
> +                                  &sbrec_service_monitor_col_remote);
> +    struct ovsdb_idl_index *sbrec_service_monitor_by_ic_learned
> +        = ovsdb_idl_index_create1(sb->idl,
> +                                  &sbrec_service_monitor_col_ic_learned);
> +    struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type_logical_port
> +        = ovsdb_idl_index_create2(sb->idl,
> +                                  &sbrec_service_monitor_col_remote,
> +                                  &sbrec_service_monitor_col_logical_port);
> +    struct ovsdb_idl_index *icnbrec_transit_switch_by_name
> +        = ovsdb_idl_index_create1(icnb->idl,
> +                                  &icnbrec_transit_switch_col_name);
> +    struct ovsdb_idl_index *icsbrec_port_binding_by_az
> +        = ovsdb_idl_index_create1(icsb->idl,
> +                                  
> &icsbrec_port_binding_col_availability_zone);
> +    struct ovsdb_idl_index *icsbrec_port_binding_by_ts
> +        = ovsdb_idl_index_create1(icsb->idl,
> +                                  &icsbrec_port_binding_col_transit_switch);
> +    struct ovsdb_idl_index *icsbrec_port_binding_by_ts_az
> +        = ovsdb_idl_index_create2(icsb->idl,
> +                                  &icsbrec_port_binding_col_transit_switch,
> +                                  
> &icsbrec_port_binding_col_availability_zone);
> +    struct ovsdb_idl_index *icsbrec_route_by_az
> +        = ovsdb_idl_index_create1(icsb->idl,
> +                                  &icsbrec_route_col_availability_zone);
> +    struct ovsdb_idl_index *icsbrec_route_by_ts
> +        = ovsdb_idl_index_create1(icsb->idl,
> +                                  &icsbrec_route_col_transit_switch);
> +    struct ovsdb_idl_index *icsbrec_route_by_ts_az
> +        = ovsdb_idl_index_create2(icsb->idl,
> +                                  &icsbrec_route_col_transit_switch,
> +                                  &icsbrec_route_col_availability_zone);
> +    struct ovsdb_idl_index *icsbrec_service_monitor_by_source_az
> +        = ovsdb_idl_index_create1(icsb->idl,
> +            &icsbrec_service_monitor_col_source_availability_zone);
> +    struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az
> +        = ovsdb_idl_index_create1(icsb->idl,
> +            &icsbrec_service_monitor_col_target_availability_zone);
> +    struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az_logical_port
> +        = ovsdb_idl_index_create2(icsb->idl,
> +            &icsbrec_service_monitor_col_target_availability_zone,
> +            &icsbrec_service_monitor_col_logical_port);
> +
>      engine_init(&en_ic, &engine_arg);
> +
> +    /* indexes */
> +    engine_ovsdb_node_add_index(&en_nb_logical_switch,
> +                                "nbrec_ls_by_name",
> +                                nbrec_ls_by_name);
> +    engine_ovsdb_node_add_index(&en_nb_logical_router,
> +                                "nbrec_lr_by_name",
> +                                nbrec_lr_by_name);
> +    engine_ovsdb_node_add_index(&en_nb_logical_router,
> +                                "nbrec_lrp_by_name",
> +                                nbrec_lrp_by_name);
> +    engine_ovsdb_node_add_index(&en_nb_logical_switch,
> +                                "nbrec_port_by_name",
> +                                nbrec_port_by_name);
> +    engine_ovsdb_node_add_index(&en_sb_chassis,
> +                                "sbrec_chassis_by_name",
> +                                sbrec_chassis_by_name);
> +    engine_ovsdb_node_add_index(&en_sb_port_binding,
> +                                "sbrec_port_binding_by_name",
> +                                sbrec_port_binding_by_name);
> +    engine_ovsdb_node_add_index(&en_sb_service_monitor,
> +                                "sbrec_service_monitor_by_remote_type",
> +                                sbrec_service_monitor_by_remote_type);
> +    engine_ovsdb_node_add_index(&en_sb_service_monitor,
> +                                "sbrec_service_monitor_by_ic_learned",
> +                                sbrec_service_monitor_by_ic_learned);
> +    engine_ovsdb_node_add_index(&en_sb_service_monitor,
> +        "sbrec_service_monitor_by_remote_type_logical_port",
> +        sbrec_service_monitor_by_remote_type_logical_port);
> +    engine_ovsdb_node_add_index(&en_icnb_transit_switch,
> +                                "icnbrec_transit_switch_by_name",
> +                                icnbrec_transit_switch_by_name);
> +    engine_ovsdb_node_add_index(&en_icsb_port_binding,
> +                                "icsbrec_port_binding_by_az",
> +                                icsbrec_port_binding_by_az);
> +    engine_ovsdb_node_add_index(&en_icsb_port_binding,
> +                                "icsbrec_port_binding_by_ts",
> +                                icsbrec_port_binding_by_ts);
> +    engine_ovsdb_node_add_index(&en_icsb_port_binding,
> +                                "icsbrec_port_binding_by_ts_az",
> +                                icsbrec_port_binding_by_ts_az);
> +    engine_ovsdb_node_add_index(&en_icsb_route,
> +                                "icsbrec_route_by_az",
> +                                icsbrec_route_by_az);
> +    engine_ovsdb_node_add_index(&en_icsb_route,
> +                                "icsbrec_route_by_ts",
> +                                icsbrec_route_by_ts);
> +    engine_ovsdb_node_add_index(&en_icsb_route,
> +                                "icsbrec_route_by_ts_az",
> +                                icsbrec_route_by_ts_az);
> +    engine_ovsdb_node_add_index(&en_icsb_service_monitor,
> +                                "icsbrec_service_monitor_by_source_az",
> +                                icsbrec_service_monitor_by_source_az);
> +    engine_ovsdb_node_add_index(&en_icsb_service_monitor,
> +                                "icsbrec_service_monitor_by_target_az",
> +                                icsbrec_service_monitor_by_target_az);
> +    engine_ovsdb_node_add_index(&en_icsb_service_monitor,
> +        "icsbrec_service_monitor_by_target_az_logical_port",
> +        icsbrec_service_monitor_by_target_az_logical_port);
>  }
>
>  /* Returns true if the incremental processing ended up updating nodes. */
>  bool
> -inc_proc_ic_run(struct ic_context *ctx,
> -                struct ic_engine_context *ic_eng_ctx)
> +inc_proc_ic_run(struct ovsdb_idl_txn *ovnnb_txn,
> +                struct ovsdb_idl_txn *ovnsb_txn,
> +                struct ovsdb_idl_txn *ovninb_txn,
> +                struct ovsdb_idl_txn *ovnisb_txn,
> +                struct ic_engine_context *ctx,
> +                const struct icsbrec_availability_zone *runned_az)
>  {
> -    ovs_assert(ctx->ovnnb_txn && ctx->ovnsb_txn &&
> -               ctx->ovninb_txn && ctx->ovnisb_txn);
> +    ovs_assert(ovnnb_txn && ovnsb_txn &&
> +               ovninb_txn && ovnisb_txn);
>
>      int64_t start = time_msec();
>      engine_init_run();
>
>      struct engine_context eng_ctx = {
> -        .client_ctx = ctx,
> +        .client_ctx = (void *) runned_az,
> +        .ovnnb_idl_txn = ovnnb_txn,
> +        .ovnsb_idl_txn = ovnsb_txn,
> +        .ovninb_idl_txn = ovninb_txn,
> +        .ovnisb_idl_txn = ovnisb_txn,
>      };
>
>      engine_set_context(&eng_ctx);
> @@ -241,7 +369,7 @@ inc_proc_ic_run(struct ic_context *ctx,
>      int64_t now = time_msec();
>      /* Postpone the next run by length of current run with maximum capped
>       * by "northd-backoff-interval-ms" interval. */
> -    ic_eng_ctx->next_run_ms = now + MIN(now - start, ic_eng_ctx->backoff_ms);
> +    ctx->next_run_ms = now + MIN(now - start, ctx->backoff_ms);
>
>      return engine_has_updated();
>  }
> diff --git a/ic/inc-proc-ic.h b/ic/inc-proc-ic.h
> index 9af147fb3..c50c1b02e 100644
> --- a/ic/inc-proc-ic.h
> +++ b/ic/inc-proc-ic.h
> @@ -21,8 +21,12 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,
>                        struct ovsdb_idl_loop *icnb,
>                        struct ovsdb_idl_loop *icsb);
>
> -bool inc_proc_ic_run(struct ic_context *ctx,
> -                     struct ic_engine_context *ic_eng_ctx);
> +bool inc_proc_ic_run(struct ovsdb_idl_txn *ovnnb_txn,
> +                     struct ovsdb_idl_txn *ovnsb_txn,
> +                     struct ovsdb_idl_txn *ovninb_txn,
> +                     struct ovsdb_idl_txn *ovnisb_txn,
> +                     struct ic_engine_context *ctx,
> +                     const struct icsbrec_availability_zone *runned_az);
>
>  void inc_proc_ic_cleanup(void);
>  bool inc_proc_ic_can_run(struct ic_engine_context *ctx);
> diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c
> index 41596d73a..8327054de 100644
> --- a/ic/ovn-ic.c
> +++ b/ic/ovn-ic.c
> @@ -48,6 +48,8 @@
>  #include "vec.h"
>  #include "inc-proc-ic.h"
>  #include "ovn-ic.h"
> +#include "stopwatch-names.h"
> +#include "stopwatch.h"
>
>  VLOG_DEFINE_THIS_MODULE(ovn_ic);
>
> @@ -99,11 +101,13 @@ Options:\n\
>      stream_usage("database", true, true, false);
>  }
>
> -static const struct icsbrec_availability_zone *
> -az_run(struct ic_context *ctx)
> +const struct icsbrec_availability_zone *
> +az_run(struct ovsdb_idl *ovnnb_idl,
> +       struct ovsdb_idl *ovnisb_idl,
> +       struct ovsdb_idl_txn *ovnisb_idl_txn)
>  {
>      const struct nbrec_nb_global *nb_global =
> -        nbrec_nb_global_first(ctx->ovnnb_idl);
> +        nbrec_nb_global_first(ovnnb_idl);
>
>      if (!nb_global) {
>          VLOG_INFO("NB Global not exist.");
> @@ -115,8 +119,8 @@ az_run(struct ic_context *ctx)
>       * "ovn-ic-sbctl destroy avail <az>". */
>      static char *az_name;
>      const struct icsbrec_availability_zone *az;
> -    if (ctx->ovnisb_txn && az_name && strcmp(az_name, nb_global->name)) {
> -        ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ctx->ovnisb_idl) {
> +    if (ovnisb_idl_txn && az_name && strcmp(az_name, nb_global->name)) {
> +        ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ovnisb_idl) {
>              /* AZ name update locally need to update az in ISB. */
>              if (nb_global->name[0] && !strcmp(az->name, az_name)) {
>                  icsbrec_availability_zone_set_name(az, nb_global->name);
> @@ -138,24 +142,22 @@ az_run(struct ic_context *ctx)
>          az_name = xstrdup(nb_global->name);
>      }
>
> -    if (ctx->ovnisb_txn) {
> -        ovsdb_idl_txn_add_comment(ctx->ovnisb_txn, "AZ %s", az_name);
> +    if (ovnisb_idl_txn) {
> +        ovsdb_idl_txn_add_comment(ovnisb_idl_txn, "AZ %s", az_name);
>      }
>
> -    ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ctx->ovnisb_idl) {
> +    ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ovnisb_idl) {
>          if (!strcmp(az->name, az_name)) {
> -            ctx->runned_az = az;
> -            return az;
> +            return (struct icsbrec_availability_zone *) az;

I'm not sure why az is being cast to a non-const type in this return.
The function is supposed to return a const struct
icsbrec_availability_zone pointer, and the only place that calls
az_run() assigns the returned value to a const pointer. I think this
cast should be removed.

>          }
>      }
>
>      /* Create AZ in ISB */
> -    if (ctx->ovnisb_txn) {
> +    if (ovnisb_idl_txn) {
>          VLOG_INFO("Register AZ %s to interconnection DB.", az_name);
> -        az = icsbrec_availability_zone_insert(ctx->ovnisb_txn);
> +        az = icsbrec_availability_zone_insert(ovnisb_idl_txn);
>          icsbrec_availability_zone_set_name(az, az_name);
> -        ctx->runned_az = az;
> -        return az;
> +        return (struct icsbrec_availability_zone *) az;

The same comment applies here.

>      }
>      return NULL;
>  }
> @@ -191,11 +193,14 @@ ic_pb_get_type(const struct icsbrec_port_binding 
> *isb_pb)
>  }
>
>  static void
> -enumerate_datapaths(struct ic_context *ctx, struct hmap *dp_tnlids,
> -                    struct shash *isb_ts_dps, struct shash *isb_tr_dps)
> +enumerate_datapaths(struct ic_input *ic,
> +                    struct hmap *dp_tnlids,
> +                    struct shash *isb_ts_dps,
> +                    struct shash *isb_tr_dps)
>  {
>      const struct icsbrec_datapath_binding *isb_dp;
> -    ICSBREC_DATAPATH_BINDING_FOR_EACH (isb_dp, ctx->ovnisb_idl) {
> +    ICSBREC_DATAPATH_BINDING_TABLE_FOR_EACH (isb_dp,
> +        ic->icsbrec_datapath_binding_table) {
>          ovn_add_tnlid(dp_tnlids, isb_dp->tunnel_key);
>
>          enum ic_datapath_type dp_type = ic_dp_get_type(isb_dp);
> @@ -210,18 +215,20 @@ enumerate_datapaths(struct ic_context *ctx, struct hmap 
> *dp_tnlids,
>  }
>
>  static void
> -ts_run(struct ic_context *ctx, struct hmap *dp_tnlids,
> +ts_run(struct engine_context *ctx,
> +       struct ic_input *ic,
> +       struct hmap *dp_tnlids,
>         struct shash *isb_ts_dps)
>  {
>      const struct icnbrec_transit_switch *ts;
>      bool dp_key_refresh = false;
>      bool vxlan_mode = false;
>      const struct icnbrec_ic_nb_global *ic_nb =
> -        icnbrec_ic_nb_global_first(ctx->ovninb_idl);
> +        icnbrec_ic_nb_global_table_first(ic->icnbrec_ic_nb_global_table);
>
>      if (ic_nb && smap_get_bool(&ic_nb->options, "vxlan_mode", false)) {
>          const struct icsbrec_encap *encap;
> -        ICSBREC_ENCAP_FOR_EACH (encap, ctx->ovnisb_idl) {
> +        ICSBREC_ENCAP_TABLE_FOR_EACH (encap, ic->icsbrec_encap_table) {
>              if (!strcmp(encap->type, "vxlan")) {
>                  vxlan_mode = true;
>                  break;
> @@ -230,12 +237,13 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids,
>      }
>
>      /* Sync INB TS to AZ NB */
> -    if (ctx->ovnnb_txn) {
> +    if (ctx->ovnnb_idl_txn) {
>          struct shash nb_tses = SHASH_INITIALIZER(&nb_tses);
>          const struct nbrec_logical_switch *ls;
>
>          /* Get current NB Logical_Switch with other_config:interconn-ts */
> -        NBREC_LOGICAL_SWITCH_FOR_EACH (ls, ctx->ovnnb_idl) {
> +        NBREC_LOGICAL_SWITCH_TABLE_FOR_EACH (ls,
> +                                             ic->nbrec_logical_switch_table) 
> {
>              const char *ts_name = smap_get(&ls->other_config, 
> "interconn-ts");
>              if (ts_name) {
>                  shash_add(&nb_tses, ts_name, ls);
> @@ -243,10 +251,11 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids,
>          }
>
>          /* Create/update NB Logical_Switch for each TS */
> -        ICNBREC_TRANSIT_SWITCH_FOR_EACH (ts, ctx->ovninb_idl) {
> +        ICNBREC_TRANSIT_SWITCH_TABLE_FOR_EACH (ts,
> +            ic->icnbrec_transit_switch_table) {
>              ls = shash_find_and_delete(&nb_tses, ts->name);
>              if (!ls) {
> -                ls = nbrec_logical_switch_insert(ctx->ovnnb_txn);
> +                ls = nbrec_logical_switch_insert(ctx->ovnnb_idl_txn);
>                  nbrec_logical_switch_set_name(ls, ts->name);
>                  nbrec_logical_switch_update_other_config_setkey(ls,
>                                                                  
> "interconn-ts",
> @@ -294,9 +303,10 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids,
>      /* Sync TS between INB and ISB.  This is performed after syncing with AZ
>       * SB, to avoid uncommitted ISB datapath tunnel key to be synced back to
>       * AZ. */
> -    if (ctx->ovnisb_txn) {
> +    if (ctx->ovnisb_idl_txn) {
>          /* Create ISB Datapath_Binding */
> -        ICNBREC_TRANSIT_SWITCH_FOR_EACH (ts, ctx->ovninb_idl) {
> +        ICNBREC_TRANSIT_SWITCH_TABLE_FOR_EACH (ts,
> +            ic->icnbrec_transit_switch_table) {
>              const struct icsbrec_datapath_binding *isb_dp =
>                  shash_find_and_delete(isb_ts_dps, ts->name);
>              if (!isb_dp) {
> @@ -307,7 +317,7 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids,
>                      continue;
>                  }
>
> -                isb_dp = icsbrec_datapath_binding_insert(ctx->ovnisb_txn);
> +                isb_dp = 
> icsbrec_datapath_binding_insert(ctx->ovnisb_idl_txn);
>                  icsbrec_datapath_binding_set_transit_switch(isb_dp, 
> ts->name);
>                  icsbrec_datapath_binding_set_tunnel_key(isb_dp, dp_key);
>              } else if (dp_key_refresh) {
> @@ -337,14 +347,17 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids,
>  }
>
>  static void
> -tr_run(struct ic_context *ctx, struct hmap *dp_tnlids,
> +tr_run(struct engine_context *ctx,
> +       struct ic_input *ic,
> +       struct hmap *dp_tnlids,
>         struct shash *isb_tr_dps)
>  {
>      const struct nbrec_logical_router *lr;
>
> -    if (ctx->ovnnb_txn) {
> +    if (ctx->ovnnb_idl_txn) {
>          struct shash nb_tres = SHASH_INITIALIZER(&nb_tres);
> -        NBREC_LOGICAL_ROUTER_FOR_EACH (lr, ctx->ovnnb_idl) {
> +        NBREC_LOGICAL_ROUTER_TABLE_FOR_EACH (lr,
> +                                             ic->nbrec_logical_router_table) 
> {
>              const char *tr_name = smap_get(&lr->options, "interconn-tr");
>              if (tr_name) {
>                  shash_add(&nb_tres, tr_name, lr);
> @@ -352,10 +365,11 @@ tr_run(struct ic_context *ctx, struct hmap *dp_tnlids,
>          }
>
>          const struct icnbrec_transit_router *tr;
> -        ICNBREC_TRANSIT_ROUTER_FOR_EACH (tr, ctx->ovninb_idl) {
> +        ICNBREC_TRANSIT_ROUTER_TABLE_FOR_EACH (tr,
> +            ic->icnbrec_transit_router_table) {
>              lr = shash_find_and_delete(&nb_tres, tr->name);
>              if (!lr) {
> -                lr = nbrec_logical_router_insert(ctx->ovnnb_txn);
> +                lr = nbrec_logical_router_insert(ctx->ovnnb_idl_txn);
>                  nbrec_logical_router_set_name(lr, tr->name);
>                  nbrec_logical_router_update_options_setkey(
>                      lr, "interconn-tr", tr->name);
> @@ -383,10 +397,11 @@ tr_run(struct ic_context *ctx, struct hmap *dp_tnlids,
>      /* Sync TR between INB and ISB.  This is performed after syncing with AZ
>       * SB, to avoid uncommitted ISB datapath tunnel key to be synced back to
>       * AZ. */
> -    if (ctx->ovnisb_txn) {
> +    if (ctx->ovnisb_idl_txn) {
>          /* Create ISB Datapath_Binding */
>          const struct icnbrec_transit_router *tr;
> -        ICNBREC_TRANSIT_ROUTER_FOR_EACH (tr, ctx->ovninb_idl) {
> +        ICNBREC_TRANSIT_ROUTER_TABLE_FOR_EACH (tr,
> +            ic->icnbrec_transit_router_table) {
>              char *uuid_str = uuid_to_string(&tr->header_.uuid);
>              struct icsbrec_datapath_binding *isb_dp =
>                  shash_find_and_delete(isb_tr_dps, uuid_str);
> @@ -399,7 +414,7 @@ tr_run(struct ic_context *ctx, struct hmap *dp_tnlids,
>                      continue;
>                  }
>
> -                isb_dp = icsbrec_datapath_binding_insert(ctx->ovnisb_txn);
> +                isb_dp = 
> icsbrec_datapath_binding_insert(ctx->ovnisb_idl_txn);
>                  icsbrec_datapath_binding_set_tunnel_key(isb_dp, dp_key);
>                  icsbrec_datapath_binding_set_nb_ic_uuid(isb_dp,
>                                                          &tr->header_.uuid, 
> 1);
> @@ -451,7 +466,7 @@ is_gateway_data_changed(const struct icsbrec_gateway *gw,
>  }
>
>  static void
> -sync_isb_gw_to_sb(struct ic_context *ctx,
> +sync_isb_gw_to_sb(struct engine_context *ctx,
>                    const struct icsbrec_gateway *gw,
>                    const struct sbrec_chassis *chassis)
>  {
> @@ -464,7 +479,7 @@ sync_isb_gw_to_sb(struct ic_context *ctx,
>      struct sbrec_encap **sb_encaps =
>          xmalloc(gw->n_encaps * sizeof *sb_encaps);
>      for (int i = 0; i < gw->n_encaps; i++) {
> -        sb_encap = sbrec_encap_insert(ctx->ovnsb_txn);
> +        sb_encap = sbrec_encap_insert(ctx->ovnsb_idl_txn);
>          sbrec_encap_set_chassis_name(sb_encap, gw->name);
>          sbrec_encap_set_ip(sb_encap, gw->encaps[i]->ip);
>          sbrec_encap_set_type(sb_encap, gw->encaps[i]->type);
> @@ -476,7 +491,7 @@ sync_isb_gw_to_sb(struct ic_context *ctx,
>  }
>
>  static void
> -sync_sb_gw_to_isb(struct ic_context *ctx,
> +sync_sb_gw_to_isb(struct engine_context *ctx,
>                    const struct sbrec_chassis *chassis,
>                    const struct icsbrec_gateway *gw)
>  {
> @@ -488,7 +503,7 @@ sync_sb_gw_to_isb(struct ic_context *ctx,
>      struct icsbrec_encap **isb_encaps =
>          xmalloc(chassis->n_encaps * sizeof *isb_encaps);
>      for (int i = 0; i < chassis->n_encaps; i++) {
> -        isb_encap = icsbrec_encap_insert(ctx->ovnisb_txn);
> +        isb_encap = icsbrec_encap_insert(ctx->ovnisb_idl_txn);
>          icsbrec_encap_set_gateway_name(isb_encap,
>                                        chassis->name);
>          icsbrec_encap_set_ip(isb_encap, chassis->encaps[i]->ip);
> @@ -504,17 +519,18 @@ sync_sb_gw_to_isb(struct ic_context *ctx,
>  }
>
>  static void
> -gateway_run(struct ic_context *ctx)
> +gateway_run(struct engine_context *ctx,
> +            struct ic_input *ic)
>  {
> -    if (!ctx->ovnisb_txn || !ctx->ovnsb_txn) {
> +    if (!ctx->ovnisb_idl_txn || !ctx->ovnsb_idl_txn) {
>          return;
>      }
>
>      struct shash local_gws = SHASH_INITIALIZER(&local_gws);
>      struct shash remote_gws = SHASH_INITIALIZER(&remote_gws);
>      const struct icsbrec_gateway *gw;
> -    ICSBREC_GATEWAY_FOR_EACH (gw, ctx->ovnisb_idl) {
> -        if (gw->availability_zone == ctx->runned_az) {
> +    ICSBREC_GATEWAY_TABLE_FOR_EACH (gw, ic->icsbrec_gateway_table) {
> +        if (gw->availability_zone == ic->runned_az) {
>              shash_add(&local_gws, gw->name, gw);
>          } else {
>              shash_add(&remote_gws, gw->name, gw);
> @@ -522,12 +538,12 @@ gateway_run(struct ic_context *ctx)
>      }
>
>      const struct sbrec_chassis *chassis;
> -    SBREC_CHASSIS_FOR_EACH (chassis, ctx->ovnsb_idl) {
> +    SBREC_CHASSIS_TABLE_FOR_EACH (chassis, ic->sbrec_chassis_table) {
>          if (smap_get_bool(&chassis->other_config, "is-interconn", false)) {
>              gw = shash_find_and_delete(&local_gws, chassis->name);
>              if (!gw) {
> -                gw = icsbrec_gateway_insert(ctx->ovnisb_txn);
> -                icsbrec_gateway_set_availability_zone(gw, ctx->runned_az);
> +                gw = icsbrec_gateway_insert(ctx->ovnisb_idl_txn);
> +                icsbrec_gateway_set_availability_zone(gw, ic->runned_az);
>                  icsbrec_gateway_set_name(gw, chassis->name);
>                  sync_sb_gw_to_isb(ctx, chassis, gw);
>              } else if (is_gateway_data_changed(gw, chassis)) {
> @@ -553,7 +569,7 @@ gateway_run(struct ic_context *ctx)
>      /* Create SB chassis for remote gateways in ISB */
>      SHASH_FOR_EACH (node, &remote_gws) {
>          gw = node->data;
> -        chassis = sbrec_chassis_insert(ctx->ovnsb_txn);
> +        chassis = sbrec_chassis_insert(ctx->ovnsb_idl_txn);
>          sbrec_chassis_set_name(chassis, gw->name);
>          sync_isb_gw_to_sb(ctx, gw, chassis);
>      }
> @@ -561,15 +577,15 @@ gateway_run(struct ic_context *ctx)
>  }
>
>  static const struct nbrec_logical_switch *
> -find_ts_in_nb(struct ic_context *ctx, char *ts_name)
> +find_ts_in_nb(struct ic_input *ic, char *ts_name)
>  {
>      const struct nbrec_logical_switch *key =
> -        nbrec_logical_switch_index_init_row(ctx->nbrec_ls_by_name);
> +        nbrec_logical_switch_index_init_row(ic->nbrec_ls_by_name);
>      nbrec_logical_switch_index_set_name(key, ts_name);
>
>      const struct nbrec_logical_switch *ls;
>      bool found = false;
> -    NBREC_LOGICAL_SWITCH_FOR_EACH_EQUAL (ls, key, ctx->nbrec_ls_by_name) {
> +    NBREC_LOGICAL_SWITCH_FOR_EACH_EQUAL (ls, key, ic->nbrec_ls_by_name) {
>          const char *ls_ts_name = smap_get(&ls->other_config, "interconn-ts");
>          if (ls_ts_name && !strcmp(ts_name, ls_ts_name)) {
>              found = true;
> @@ -585,15 +601,15 @@ find_ts_in_nb(struct ic_context *ctx, char *ts_name)
>  }
>
>  static const struct nbrec_logical_router *
> -find_tr_in_nb(struct ic_context *ctx, char *tr_name)
> +find_tr_in_nb(struct ic_input *ic, char *tr_name)
>  {
>      const struct nbrec_logical_router *key =
> -        nbrec_logical_router_index_init_row(ctx->nbrec_lr_by_name);
> +        nbrec_logical_router_index_init_row(ic->nbrec_lr_by_name);
>      nbrec_logical_router_index_set_name(key, tr_name);
>
>      const struct nbrec_logical_router *lr;
>      bool found = false;
> -    NBREC_LOGICAL_ROUTER_FOR_EACH_EQUAL (lr, key, ctx->nbrec_lr_by_name) {
> +    NBREC_LOGICAL_ROUTER_FOR_EACH_EQUAL (lr, key, ic->nbrec_lr_by_name) {
>          if (smap_get(&lr->options, "interconn-tr")) {
>              found = true;
>              break;
> @@ -624,7 +640,7 @@ find_sb_pb_by_name(struct ovsdb_idl_index 
> *sbrec_port_binding_by_name,
>  }
>
>  static const struct sbrec_port_binding *
> -find_peer_port(struct ic_context *ctx,
> +find_peer_port(struct ic_input *ic,
>                 const struct sbrec_port_binding *sb_pb)
>  {
>      const char *peer_name = smap_get(&sb_pb->options, "peer");
> @@ -632,61 +648,61 @@ find_peer_port(struct ic_context *ctx,
>          return NULL;
>      }
>
> -    return find_sb_pb_by_name(ctx->sbrec_port_binding_by_name, peer_name);
> +    return find_sb_pb_by_name(ic->sbrec_port_binding_by_name, peer_name);
>  }
>
>  static const struct sbrec_port_binding *
> -find_crp_from_lrp(struct ic_context *ctx,
> +find_crp_from_lrp(struct ic_input *ic,
>                    const struct sbrec_port_binding *lrp_pb)
>  {
>      char *crp_name = ovn_chassis_redirect_name(lrp_pb->logical_port);
>
>      const struct sbrec_port_binding *pb =
> -        find_sb_pb_by_name(ctx->sbrec_port_binding_by_name, crp_name);
> +        find_sb_pb_by_name(ic->sbrec_port_binding_by_name, crp_name);
>
>      free(crp_name);
>      return pb;
>  }
>
>  static const struct sbrec_port_binding *
> -find_crp_for_sb_pb(struct ic_context *ctx,
> +find_crp_for_sb_pb(struct ic_input *ic,
>                     const struct sbrec_port_binding *sb_pb)
>  {
> -    const struct sbrec_port_binding *peer = find_peer_port(ctx, sb_pb);
> +    const struct sbrec_port_binding *peer = find_peer_port(ic, sb_pb);
>      if (!peer) {
>          return NULL;
>      }
>
> -    return find_crp_from_lrp(ctx, peer);
> +    return find_crp_from_lrp(ic, peer);
>  }
>
>  static const struct nbrec_logical_switch_port *
> -get_lsp_by_ts_port_name(struct ic_context *ctx, const char *ts_port_name)
> +get_lsp_by_ts_port_name(struct ic_input *ic, const char *ts_port_name)
>  {
>      const struct nbrec_logical_switch_port *lsp, *key;
>
> -    key = nbrec_logical_switch_port_index_init_row(ctx->nbrec_port_by_name);
> +    key = nbrec_logical_switch_port_index_init_row(ic->nbrec_port_by_name);
>      nbrec_logical_switch_port_index_set_name(key, ts_port_name);
> -    lsp = nbrec_logical_switch_port_index_find(ctx->nbrec_port_by_name, key);
> +    lsp = nbrec_logical_switch_port_index_find(ic->nbrec_port_by_name, key);
>      nbrec_logical_switch_port_index_destroy_row(key);
>
>      return lsp;
>  }
>
>  static const char *
> -get_lp_address_for_sb_pb(struct ic_context *ctx,
> +get_lp_address_for_sb_pb(struct ic_input *ic,
>                           const struct sbrec_port_binding *sb_pb)
>  {
>      const struct nbrec_logical_switch_port *nb_lsp;
>
> -    nb_lsp = get_lsp_by_ts_port_name(ctx, sb_pb->logical_port);
> +    nb_lsp = get_lsp_by_ts_port_name(ic, sb_pb->logical_port);
>      if (!strcmp(nb_lsp->type, "switch")) {
>          /* Switches always have implicit "unknown" address, and IC-SB port
>           * binding can only have one address specified. */
>          return "unknown";
>      }
>
> -    const struct sbrec_port_binding *peer = find_peer_port(ctx, sb_pb);
> +    const struct sbrec_port_binding *peer = find_peer_port(ic, sb_pb);
>      if (!peer) {
>          return NULL;
>      }
> @@ -695,14 +711,14 @@ get_lp_address_for_sb_pb(struct ic_context *ctx,
>  }
>
>  static const struct sbrec_chassis *
> -find_sb_chassis(struct ic_context *ctx, const char *name)
> +find_sb_chassis(struct ic_input *ic, const char *name)
>  {
>      const struct sbrec_chassis *key =
> -        sbrec_chassis_index_init_row(ctx->sbrec_chassis_by_name);
> +        sbrec_chassis_index_init_row(ic->sbrec_chassis_by_name);
>      sbrec_chassis_index_set_name(key, name);
>
>      const struct sbrec_chassis *chassis =
> -        sbrec_chassis_index_find(ctx->sbrec_chassis_by_name, key);
> +        sbrec_chassis_index_find(ic->sbrec_chassis_by_name, key);
>      sbrec_chassis_index_destroy_row(key);
>
>      return chassis;
> @@ -741,11 +757,11 @@ sync_lrp_tnl_key(const struct nbrec_logical_router_port 
> *lrp,
>  }
>
>  static bool
> -get_router_uuid_by_sb_pb(struct ic_context *ctx,
> +get_router_uuid_by_sb_pb(struct ic_input *ic,
>                           const struct sbrec_port_binding *sb_pb,
>                           struct uuid *router_uuid)
>  {
> -    const struct sbrec_port_binding *router_pb = find_peer_port(ctx, sb_pb);
> +    const struct sbrec_port_binding *router_pb = find_peer_port(ic, sb_pb);
>      if (!router_pb || !router_pb->datapath) {
>          return NULL;
>      }
> @@ -754,12 +770,12 @@ get_router_uuid_by_sb_pb(struct ic_context *ctx,
>  }
>
>  static void
> -update_isb_pb_external_ids(struct ic_context *ctx,
> +update_isb_pb_external_ids(struct ic_input *ic,
>                             const struct sbrec_port_binding *sb_pb,
>                             const struct icsbrec_port_binding *isb_pb)
>  {
>      struct uuid lr_uuid;
> -    if (!get_router_uuid_by_sb_pb(ctx, sb_pb, &lr_uuid)) {
> +    if (!get_router_uuid_by_sb_pb(ic, sb_pb, &lr_uuid)) {
>          static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
>          VLOG_WARN_RL(&rl, "Can't get router uuid for transit switch port 
> %s.",
>                       isb_pb->logical_port);
> @@ -784,13 +800,13 @@ update_isb_pb_external_ids(struct ic_context *ctx,
>   *   - Sync tunnel key from ISB to NB.
>   */
>  static void
> -sync_local_port(struct ic_context *ctx,
> +sync_local_port(struct ic_input *ic,
>                  const struct icsbrec_port_binding *isb_pb,
>                  const struct sbrec_port_binding *sb_pb,
>                  const struct nbrec_logical_switch_port *lsp)
>  {
>      /* Sync address from NB to ISB */
> -    const char *address = get_lp_address_for_sb_pb(ctx, sb_pb);
> +    const char *address = get_lp_address_for_sb_pb(ic, sb_pb);
>      if (!address) {
>          VLOG_DBG("Can't get router/switch port address for logical"
>                   " switch port %s", sb_pb->logical_port);
> @@ -804,7 +820,7 @@ sync_local_port(struct ic_context *ctx,
>      }
>
>      /* Sync gateway from SB to ISB */
> -    const struct sbrec_port_binding *crp = find_crp_for_sb_pb(ctx, sb_pb);
> +    const struct sbrec_port_binding *crp = find_crp_for_sb_pb(ic, sb_pb);
>      if (crp && crp->chassis) {
>          if (strcmp(crp->chassis->name, isb_pb->gateway)) {
>              icsbrec_port_binding_set_gateway(isb_pb, crp->chassis->name);
> @@ -820,7 +836,7 @@ sync_local_port(struct ic_context *ctx,
>      }
>
>      /* Sync external_ids:router-id to ISB */
> -    update_isb_pb_external_ids(ctx, sb_pb, isb_pb);
> +    update_isb_pb_external_ids(ic, sb_pb, isb_pb);
>
>      /* Sync back tunnel key from ISB to NB */
>      sync_lsp_tnl_key(lsp, isb_pb->tunnel_key);
> @@ -831,7 +847,7 @@ sync_local_port(struct ic_context *ctx,
>   *   - Sync gateway from ISB to SB
>   */
>  static void
> -sync_remote_port(struct ic_context *ctx,
> +sync_remote_port(struct ic_input *ic,
>                   const struct icsbrec_port_binding *isb_pb,
>                   const struct nbrec_logical_switch_port *lsp,
>                   const struct sbrec_port_binding *sb_pb)
> @@ -861,7 +877,7 @@ sync_remote_port(struct ic_context *ctx,
>      if (isb_pb->gateway[0]) {
>          if (!sb_pb->chassis || strcmp(sb_pb->chassis->name, 
> isb_pb->gateway)) {
>              const struct sbrec_chassis *chassis =
> -                find_sb_chassis(ctx, isb_pb->gateway);
> +                find_sb_chassis(ic, isb_pb->gateway);
>              if (!chassis) {
>                  VLOG_DBG("Chassis %s is not found in SB, syncing from ISB "
>                           "to SB skipped for logical port %s.",
> @@ -924,12 +940,12 @@ sync_router_port(const struct icsbrec_port_binding 
> *isb_pb,
>  }
>
>  static void
> -create_nb_lsp(struct ic_context *ctx,
> +create_nb_lsp(struct engine_context *ctx,
>                const struct icsbrec_port_binding *isb_pb,
>                const struct nbrec_logical_switch *ls)
>  {
>      const struct nbrec_logical_switch_port *lsp =
> -        nbrec_logical_switch_port_insert(ctx->ovnnb_txn);
> +        nbrec_logical_switch_port_insert(ctx->ovnnb_idl_txn);
>      nbrec_logical_switch_port_set_name(lsp, isb_pb->logical_port);
>      nbrec_logical_switch_port_set_type(lsp, "remote");
>
> @@ -953,7 +969,7 @@ allocate_port_key(struct hmap *pb_tnlids)
>  }
>
>  static const struct icsbrec_port_binding *
> -create_isb_pb(struct ic_context *ctx, const char *logical_port,
> +create_isb_pb(struct engine_context *ctx, const char *logical_port,
>                const struct icsbrec_availability_zone *az, const char 
> *ts_name,
>                const struct uuid *nb_ic_uuid, const char *type,
>                struct hmap *pb_tnlids)
> @@ -964,7 +980,7 @@ create_isb_pb(struct ic_context *ctx, const char 
> *logical_port,
>      }
>
>      const struct icsbrec_port_binding *isb_pb =
> -        icsbrec_port_binding_insert(ctx->ovnisb_txn);
> +        icsbrec_port_binding_insert(ctx->ovnisb_idl_txn);
>      icsbrec_port_binding_set_availability_zone(isb_pb, az);
>      icsbrec_port_binding_set_transit_switch(isb_pb, ts_name);
>      icsbrec_port_binding_set_logical_port(isb_pb, logical_port);
> @@ -975,25 +991,25 @@ create_isb_pb(struct ic_context *ctx, const char 
> *logical_port,
>  }
>
>  static const struct nbrec_logical_router_port *
> -get_lrp_by_lrp_name(struct ic_context *ctx, const char *lrp_name)
> +get_lrp_by_lrp_name(struct ic_input *ic, const char *lrp_name)
>  {
>      const struct nbrec_logical_router_port *lrp;
>      const struct nbrec_logical_router_port *lrp_key =
> -        nbrec_logical_router_port_index_init_row(ctx->nbrec_lrp_by_name);
> +        nbrec_logical_router_port_index_init_row(ic->nbrec_lrp_by_name);
>      nbrec_logical_router_port_index_set_name(lrp_key, lrp_name);
>      lrp =
> -        nbrec_logical_router_port_index_find(ctx->nbrec_lrp_by_name, 
> lrp_key);
> +        nbrec_logical_router_port_index_find(ic->nbrec_lrp_by_name, lrp_key);
>      nbrec_logical_router_port_index_destroy_row(lrp_key);
>
>      return lrp;
>  }
>
>  static bool
> -trp_is_remote(struct ic_context *ctx, const char *chassis_name)
> +trp_is_remote(struct ic_input *ic, const char *chassis_name)
>  {
>      if (chassis_name) {
>          const struct sbrec_chassis *chassis =
> -            find_sb_chassis(ctx, chassis_name);
> +            find_sb_chassis(ic, chassis_name);
>          if (chassis) {
>              return smap_get_bool(&chassis->other_config, "is-remote", false);
>          } else {
> @@ -1005,11 +1021,11 @@ trp_is_remote(struct ic_context *ctx, const char 
> *chassis_name)
>  }
>
>  static struct nbrec_logical_router_port *
> -lrp_create(struct ic_context *ctx, const struct nbrec_logical_router *lr,
> +lrp_create(struct engine_context *ctx, const struct nbrec_logical_router *lr,
>             const struct icnbrec_transit_router_port *trp)
>  {
>      struct nbrec_logical_router_port *lrp =
> -        nbrec_logical_router_port_insert(ctx->ovnnb_txn);
> +        nbrec_logical_router_port_insert(ctx->ovnnb_idl_txn);
>      nbrec_logical_router_port_set_name(lrp, trp->name);
>
>      nbrec_logical_router_port_update_options_setkey(lrp, "interconn-tr",
> @@ -1019,20 +1035,20 @@ lrp_create(struct ic_context *ctx, const struct 
> nbrec_logical_router *lr,
>  }
>
>  static void
> -sync_ts_isb_pb(struct ic_context *ctx, const struct sbrec_port_binding 
> *sb_pb,
> +sync_ts_isb_pb(struct ic_input *ic, const struct sbrec_port_binding *sb_pb,
>                 const struct icsbrec_port_binding *isb_pb)
>  {
> -    const char *address = get_lp_address_for_sb_pb(ctx, sb_pb);
> +    const char *address = get_lp_address_for_sb_pb(ic, sb_pb);
>      if (address) {
>          icsbrec_port_binding_set_address(isb_pb, address);
>      }
>
> -    const struct sbrec_port_binding *crp = find_crp_for_sb_pb(ctx, sb_pb);
> +    const struct sbrec_port_binding *crp = find_crp_for_sb_pb(ic, sb_pb);
>      if (crp && crp->chassis) {
>          icsbrec_port_binding_set_gateway(isb_pb, crp->chassis->name);
>      }
>
> -    update_isb_pb_external_ids(ctx, sb_pb, isb_pb);
> +    update_isb_pb_external_ids(ic, sb_pb, isb_pb);
>
>      /* XXX: Sync encap so that multiple encaps can be used for the same
>       * gateway.  However, it is not needed for now, since we don't yet
> @@ -1043,16 +1059,18 @@ sync_ts_isb_pb(struct ic_context *ctx, const struct 
> sbrec_port_binding *sb_pb,
>  }
>
>  static const struct sbrec_port_binding *
> -find_lsp_in_sb(struct ic_context *ctx,
> +find_lsp_in_sb(struct ic_input *ic,
>                 const struct nbrec_logical_switch_port *lsp)
>  {
> -    return find_sb_pb_by_name(ctx->sbrec_port_binding_by_name, lsp->name);
> +    return find_sb_pb_by_name(ic->sbrec_port_binding_by_name, lsp->name);
>  }
>
>  static void
> -port_binding_run(struct ic_context *ctx)
> +port_binding_run(struct engine_context *ctx,
> +                 struct ic_input *ic)
>  {
> -    if (!ctx->ovnisb_txn || !ctx->ovnnb_txn || !ctx->ovnsb_txn) {
> +    if (!ctx->ovnisb_idl_txn || !ctx->ovnnb_idl_txn
> +        || !ctx->ovnsb_idl_txn) {
>          return;
>      }
>
> @@ -1065,12 +1083,12 @@ port_binding_run(struct ic_context *ctx)
>
>      const struct icsbrec_port_binding *isb_pb;
>      const struct icsbrec_port_binding *isb_pb_key =
> -        icsbrec_port_binding_index_init_row(ctx->icsbrec_port_binding_by_az);
> +        icsbrec_port_binding_index_init_row(ic->icsbrec_port_binding_by_az);
>      icsbrec_port_binding_index_set_availability_zone(isb_pb_key,
> -                                                     ctx->runned_az);
> +                                                     ic->runned_az);
>
>      ICSBREC_PORT_BINDING_FOR_EACH_EQUAL (isb_pb, isb_pb_key,
> -                                         ctx->icsbrec_port_binding_by_az) {
> +                                         ic->icsbrec_port_binding_by_az) {
>          ic_pb_get_type(isb_pb) != IC_ROUTER_PORT
>              ? shash_add(&switch_all_local_pbs, isb_pb->logical_port, isb_pb)
>              : shash_add(&router_all_local_pbs, isb_pb->logical_port, isb_pb);
> @@ -1081,8 +1099,9 @@ port_binding_run(struct ic_context *ctx)
>
>      const struct sbrec_port_binding *sb_pb;
>      const struct icnbrec_transit_switch *ts;
> -    ICNBREC_TRANSIT_SWITCH_FOR_EACH (ts, ctx->ovninb_idl) {
> -        const struct nbrec_logical_switch *ls = find_ts_in_nb(ctx, ts->name);
> +    ICNBREC_TRANSIT_SWITCH_TABLE_FOR_EACH (ts,
> +                                           ic->icnbrec_transit_switch_table) 
> {
> +        const struct nbrec_logical_switch *ls = find_ts_in_nb(ic, ts->name);
>          if (!ls) {
>              VLOG_DBG("Transit switch %s not found in NB.", ts->name);
>              continue;
> @@ -1091,12 +1110,12 @@ port_binding_run(struct ic_context *ctx)
>          struct shash remote_pbs = SHASH_INITIALIZER(&remote_pbs);
>
>          isb_pb_key = icsbrec_port_binding_index_init_row(
> -            ctx->icsbrec_port_binding_by_ts);
> +            ic->icsbrec_port_binding_by_ts);
>          icsbrec_port_binding_index_set_transit_switch(isb_pb_key, ts->name);
>
>          ICSBREC_PORT_BINDING_FOR_EACH_EQUAL (isb_pb, isb_pb_key,
> -                                             
> ctx->icsbrec_port_binding_by_ts) {
> -            if (isb_pb->availability_zone == ctx->runned_az) {
> +                                             ic->icsbrec_port_binding_by_ts) 
> {
> +            if (isb_pb->availability_zone == ic->runned_az) {
>                  shash_add(&local_pbs, isb_pb->logical_port, isb_pb);
>                  shash_find_and_delete(&switch_all_local_pbs,
>                                        isb_pb->logical_port);
> @@ -1113,18 +1132,18 @@ port_binding_run(struct ic_context *ctx)
>              if (!strcmp(lsp->type, "router")
>                  || !strcmp(lsp->type, "switch")) {
>                  /* The port is local. */
> -                sb_pb = find_lsp_in_sb(ctx, lsp);
> +                sb_pb = find_lsp_in_sb(ic, lsp);
>                  if (!sb_pb) {
>                      continue;
>                  }
>                  isb_pb = shash_find_and_delete(&local_pbs, lsp->name);
>                  if (!isb_pb) {
>                      isb_pb = create_isb_pb(
> -                        ctx, sb_pb->logical_port, ctx->runned_az, ts->name,
> +                        ctx, sb_pb->logical_port, ic->runned_az, ts->name,
>                          &ts->header_.uuid, "transit-switch-port", 
> &pb_tnlids);
> -                    sync_ts_isb_pb(ctx, sb_pb, isb_pb);
> +                    sync_ts_isb_pb(ic, sb_pb, isb_pb);
>                  } else {
> -                    sync_local_port(ctx, isb_pb, sb_pb, lsp);
> +                    sync_local_port(ic, isb_pb, sb_pb, lsp);
>                  }
>
>                  if (isb_pb->type) {
> @@ -1142,11 +1161,11 @@ port_binding_run(struct ic_context *ctx)
>                  if (!isb_pb) {
>                      nbrec_logical_switch_update_ports_delvalue(ls, lsp);
>                  } else {
> -                    sb_pb = find_lsp_in_sb(ctx, lsp);
> +                    sb_pb = find_lsp_in_sb(ic, lsp);
>                      if (!sb_pb) {
>                          continue;
>                      }
> -                    sync_remote_port(ctx, isb_pb, lsp, sb_pb);
> +                    sync_remote_port(ic, isb_pb, lsp, sb_pb);
>                  }
>              } else {
>                  VLOG_DBG("Ignore lsp %s on ts %s with type %s.",
> @@ -1174,8 +1193,9 @@ port_binding_run(struct ic_context *ctx)
>      shash_destroy(&switch_all_local_pbs);
>
>      const struct icnbrec_transit_router *tr;
> -    ICNBREC_TRANSIT_ROUTER_FOR_EACH (tr, ctx->ovninb_idl) {
> -        const struct nbrec_logical_router *lr = find_tr_in_nb(ctx, tr->name);
> +    ICNBREC_TRANSIT_ROUTER_TABLE_FOR_EACH (tr,
> +                                           ic->icnbrec_transit_router_table) 
> {
> +        const struct nbrec_logical_router *lr = find_tr_in_nb(ic, tr->name);
>          if (!lr) {
>              VLOG_DBG("Transit router %s not found in NB.", tr->name);
>              continue;
> @@ -1193,12 +1213,12 @@ port_binding_run(struct ic_context *ctx)
>          }
>
>          isb_pb_key = icsbrec_port_binding_index_init_row(
> -            ctx->icsbrec_port_binding_by_ts);
> +            ic->icsbrec_port_binding_by_ts);
>          icsbrec_port_binding_index_set_transit_switch(isb_pb_key, tr->name);
>
>          ICSBREC_PORT_BINDING_FOR_EACH_EQUAL (isb_pb, isb_pb_key,
> -                                             
> ctx->icsbrec_port_binding_by_ts) {
> -            if (isb_pb->availability_zone == ctx->runned_az) {
> +                                             ic->icsbrec_port_binding_by_ts) 
> {
> +            if (isb_pb->availability_zone == ic->runned_az) {
>                  shash_add(&local_pbs, isb_pb->logical_port, isb_pb);
>                  shash_find_and_delete(&router_all_local_pbs,
>                                        isb_pb->logical_port);
> @@ -1211,12 +1231,12 @@ port_binding_run(struct ic_context *ctx)
>          for (size_t i = 0; i < tr->n_ports; i++) {
>              const struct icnbrec_transit_router_port *trp = tr->ports[i];
>
> -            if (trp_is_remote(ctx, trp->chassis)) {
> +            if (trp_is_remote(ic, trp->chassis)) {
>                  isb_pb = shash_find_and_delete(&remote_pbs, trp->name);
>              } else {
>                  isb_pb = shash_find_and_delete(&local_pbs, trp->name);
>                  if (!isb_pb) {
> -                    isb_pb = create_isb_pb(ctx, trp->name, ctx->runned_az,
> +                    isb_pb = create_isb_pb(ctx, trp->name, ic->runned_az,
>                                             tr->name, &tr->header_.uuid,
>                                             "transit-router-port", 
> &pb_tnlids);
>                      icsbrec_port_binding_set_address(isb_pb, trp->mac);
> @@ -1548,8 +1568,8 @@ add_to_routes_ad(struct hmap *routes_ad, const struct 
> in6_addr prefix,
>
>      uint hash = ic_route_hash(&prefix, plen, &nexthop, origin, route_table);
>
> -    if (!ic_route_find(routes_ad, &prefix, plen, &nexthop, origin, 
> route_table,
> -                       hash)) {
> +    if (!ic_route_find(routes_ad, &prefix, plen, &nexthop, origin,
> +                       route_table, hash)) {
>          struct ic_route_info *ic_route = xzalloc(sizeof *ic_route);
>          ic_route->prefix = prefix;
>          ic_route->plen = plen;
> @@ -1921,11 +1941,11 @@ route_need_learn(const struct nbrec_logical_router 
> *lr,
>  }
>
>  static const char *
> -get_lrp_name_by_ts_port_name(struct ic_context *ctx, const char 
> *ts_port_name)
> +get_lrp_name_by_ts_port_name(struct ic_input *ic, const char *ts_port_name)
>  {
>      const struct nbrec_logical_switch_port *nb_lsp;
>
> -    nb_lsp = get_lsp_by_ts_port_name(ctx, ts_port_name);
> +    nb_lsp = get_lsp_by_ts_port_name(ic, ts_port_name);
>      if (!nb_lsp) {
>          return NULL;
>      }
> @@ -1934,12 +1954,12 @@ get_lrp_name_by_ts_port_name(struct ic_context *ctx, 
> const char *ts_port_name)
>  }
>
>  static const struct nbrec_logical_router_port *
> -find_lrp_of_nexthop(struct ic_context *ctx,
> +find_lrp_of_nexthop(struct ic_input *ic,
>                      const struct icsbrec_route *isb_route)
>  {
>      const struct nbrec_logical_router_port *lrp;
>      const struct nbrec_logical_switch *ls;
> -    ls = find_ts_in_nb(ctx, isb_route->transit_switch);
> +    ls = find_ts_in_nb(ic, isb_route->transit_switch);
>      if (!ls) {
>          return NULL;
>      }
> @@ -1951,13 +1971,13 @@ find_lrp_of_nexthop(struct ic_context *ctx,
>
>      for (size_t i = 0; i < ls->n_ports; i++) {
>          char *lsp_name = ls->ports[i]->name;
> -        const char *lrp_name = get_lrp_name_by_ts_port_name(ctx,
> +        const char *lrp_name = get_lrp_name_by_ts_port_name(ic,
>                                                              lsp_name);
>          if (!lrp_name) {
>              continue;
>          }
>
> -        lrp = get_lrp_by_lrp_name(ctx, lrp_name);
> +        lrp = get_lrp_by_lrp_name(ic, lrp_name);
>          if (!lrp) {
>              continue;
>          }
> @@ -1995,13 +2015,13 @@ find_lrp_of_nexthop(struct ic_context *ctx,
>  }
>
>  static bool
> -lrp_is_ts_port(struct ic_context *ctx, struct ic_router_info *ic_lr,
> +lrp_is_ts_port(struct ic_input *ic, struct ic_router_info *ic_lr,
>                 const char *lrp_name)
>  {
>      const struct icsbrec_port_binding *isb_pb;
>      const char *ts_lrp_name;
>      VECTOR_FOR_EACH (&ic_lr->isb_pbs, isb_pb) {
> -        ts_lrp_name = get_lrp_name_by_ts_port_name(ctx, 
> isb_pb->logical_port);
> +        ts_lrp_name = get_lrp_name_by_ts_port_name(ic, isb_pb->logical_port);
>          if (!strcmp(ts_lrp_name, lrp_name)) {
>              return true;
>          }
> @@ -2010,14 +2030,15 @@ lrp_is_ts_port(struct ic_context *ctx, struct 
> ic_router_info *ic_lr,
>  }
>
>  static void
> -sync_learned_routes(struct ic_context *ctx,
> +sync_learned_routes(struct engine_context *ctx,
> +                    struct ic_input *ic,
>                      struct ic_router_info *ic_lr)
>  {
> -    ovs_assert(ctx->ovnnb_txn);
> +    ovs_assert(ctx->ovnnb_idl_txn);
>      const struct icsbrec_route *isb_route, *isb_route_key;
>
>      const struct nbrec_nb_global *nb_global =
> -        nbrec_nb_global_first(ctx->ovnnb_idl);
> +        nbrec_nb_global_table_first(ic->nbrec_nb_global_table);
>      ovs_assert(nb_global);
>
>      const char *lrp_name, *ts_route_table, *route_filter_tag;
> @@ -2027,8 +2048,8 @@ sync_learned_routes(struct ic_context *ctx,
>          if (!strcmp(isb_pb->address, "")) {
>              continue;
>          }
> -        lrp_name = get_lrp_name_by_ts_port_name(ctx, isb_pb->logical_port);
> -        lrp = get_lrp_by_lrp_name(ctx, lrp_name);
> +        lrp_name = get_lrp_name_by_ts_port_name(ic, isb_pb->logical_port);
> +        lrp = get_lrp_by_lrp_name(ic, lrp_name);
>          if (lrp) {
>              ts_route_table = smap_get_def(&lrp->options, "route_table", "");
>              route_filter_tag = smap_get_def(&lrp->options,
> @@ -2038,12 +2059,12 @@ sync_learned_routes(struct ic_context *ctx,
>              route_filter_tag = "";
>          }
>
> -        isb_route_key = 
> icsbrec_route_index_init_row(ctx->icsbrec_route_by_ts);
> +        isb_route_key = 
> icsbrec_route_index_init_row(ic->icsbrec_route_by_ts);
>          icsbrec_route_index_set_transit_switch(isb_route_key,
>                                                 isb_pb->transit_switch);
>
>          ICSBREC_ROUTE_FOR_EACH_EQUAL (isb_route, isb_route_key,
> -                                      ctx->icsbrec_route_by_ts) {
> +                                      ic->icsbrec_route_by_ts) {
>              /* Filters ICSB routes, skipping those that either belong to
>               * current logical router or are legacy routes from the current
>               * availability zone (withoud lr-id).
> @@ -2055,7 +2076,7 @@ sync_learned_routes(struct ic_context *ctx,
>                      || uuid_equals(&ic_lr->lr->header_.uuid, &lr_uuid)) {
>                      continue;
>                  }
> -            } else if (isb_route->availability_zone == ctx->runned_az) {
> +            } else if (isb_route->availability_zone == ic->runned_az) {
>                  continue;
>              }
>
> @@ -2117,7 +2138,8 @@ sync_learned_routes(struct ic_context *ctx,
>              } else {
>                  /* Create the missing route in NB. */
>                  const struct nbrec_logical_router_static_route *nb_route =
> -                    nbrec_logical_router_static_route_insert(ctx->ovnnb_txn);
> +                    nbrec_logical_router_static_route_insert(
> +                        ctx->ovnnb_idl_txn);
>                  nbrec_logical_router_static_route_set_ip_prefix(nb_route,
>                      isb_route->ip_prefix);
>                  nbrec_logical_router_static_route_set_nexthop(nb_route,
> @@ -2190,20 +2212,21 @@ ad_route_sync_external_ids(const struct ic_route_info 
> *route_adv,
>
>  /* Sync routes from routes_ad to IC-SB. */
>  static void
> -advertise_routes(struct ic_context *ctx,
> +advertise_routes(struct engine_context *ctx,
> +                 struct ic_input *ic,
>                   const struct icsbrec_availability_zone *az,
>                   const char *ts_name,
>                   struct hmap *routes_ad)
>  {
> -    ovs_assert(ctx->ovnisb_txn);
> +    ovs_assert(ctx->ovnisb_idl_txn);
>      const struct icsbrec_route *isb_route;
>      const struct icsbrec_route *isb_route_key =
> -        icsbrec_route_index_init_row(ctx->icsbrec_route_by_ts_az);
> +        icsbrec_route_index_init_row(ic->icsbrec_route_by_ts_az);
>      icsbrec_route_index_set_transit_switch(isb_route_key, ts_name);
>      icsbrec_route_index_set_availability_zone(isb_route_key, az);
>
>      ICSBREC_ROUTE_FOR_EACH_EQUAL (isb_route, isb_route_key,
> -                                  ctx->icsbrec_route_by_ts_az) {
> +                                  ic->icsbrec_route_by_ts_az) {
>          struct in6_addr prefix, nexthop;
>          unsigned int plen;
>
> @@ -2237,7 +2260,7 @@ advertise_routes(struct ic_context *ctx,
>      /* Create the missing routes in IC-SB */
>      struct ic_route_info *route_adv;
>      HMAP_FOR_EACH_SAFE (route_adv, node, routes_ad) {
> -        isb_route = icsbrec_route_insert(ctx->ovnisb_txn);
> +        isb_route = icsbrec_route_insert(ctx->ovnisb_idl_txn);
>          icsbrec_route_set_transit_switch(isb_route, ts_name);
>          icsbrec_route_set_availability_zone(isb_route, az);
>
> @@ -2273,7 +2296,7 @@ advertise_routes(struct ic_context *ctx,
>  }
>
>  static void
> -build_ts_routes_to_adv(struct ic_context *ctx,
> +build_ts_routes_to_adv(struct ic_input *ic,
>                         struct ic_router_info *ic_lr,
>                         struct hmap *routes_ad,
>                         struct lport_addresses *ts_port_addrs,
> @@ -2310,7 +2333,7 @@ build_ts_routes_to_adv(struct ic_context *ctx,
>      /* Check directly-connected subnets of the LR */
>      for (int i = 0; i < lr->n_ports; i++) {
>          const struct nbrec_logical_router_port *lrp = lr->ports[i];
> -        if (!lrp_is_ts_port(ctx, ic_lr, lrp->name)) {
> +        if (!lrp_is_ts_port(ic, ic_lr, lrp->name)) {
>              for (int j = 0; j < lrp->n_networks; j++) {
>                  add_network_to_routes_ad(routes_ad, lrp->networks[j], lrp,
>                                           ts_port_addrs,
> @@ -2356,12 +2379,13 @@ build_ts_routes_to_adv(struct ic_context *ctx,
>  }
>
>  static void
> -collect_lr_routes(struct ic_context *ctx,
> +collect_lr_routes(struct ic_input *ic,
>                    struct ic_router_info *ic_lr,
>                    struct shash *routes_ad_by_ts)
>  {
>      const struct nbrec_nb_global *nb_global =
> -        nbrec_nb_global_first(ctx->ovnnb_idl);
> +        nbrec_nb_global_table_first(ic->nbrec_nb_global_table);
> +
>      ovs_assert(nb_global);
>
>      const struct icsbrec_port_binding *isb_pb;
> @@ -2374,10 +2398,10 @@ collect_lr_routes(struct ic_context *ctx,
>      const struct icnbrec_transit_switch *t_sw;
>      VECTOR_FOR_EACH (&ic_lr->isb_pbs, isb_pb) {
>          key = icnbrec_transit_switch_index_init_row(
> -            ctx->icnbrec_transit_switch_by_name);
> +            ic->icnbrec_transit_switch_by_name);
>          icnbrec_transit_switch_index_set_name(key, isb_pb->transit_switch);
>          t_sw = icnbrec_transit_switch_index_find(
> -             ctx->icnbrec_transit_switch_by_name, key);
> +             ic->icnbrec_transit_switch_by_name, key);
>          icnbrec_transit_switch_index_destroy_row(key);
>          if (!t_sw) {
>              continue;
> @@ -2398,8 +2422,8 @@ collect_lr_routes(struct ic_context *ctx,
>                           ic_lr->lr->name);
>              continue;
>          }
> -        lrp_name = get_lrp_name_by_ts_port_name(ctx, isb_pb->logical_port);
> -        lrp = get_lrp_by_lrp_name(ctx, lrp_name);
> +        lrp_name = get_lrp_name_by_ts_port_name(ic, isb_pb->logical_port);
> +        lrp = get_lrp_by_lrp_name(ic, lrp_name);
>          if (lrp) {
>              route_table = smap_get_def(&lrp->options, "route_table", "");
>              route_tag = smap_get_def(&lrp->options, "ic-route-tag", "");
> @@ -2407,34 +2431,34 @@ collect_lr_routes(struct ic_context *ctx,
>              route_table = "";
>              route_tag = "";
>          }
> -        build_ts_routes_to_adv(ctx, ic_lr, routes_ad, &ts_port_addrs,
> +        build_ts_routes_to_adv(ic, ic_lr, routes_ad, &ts_port_addrs,
>                                 nb_global, route_table, route_tag, lrp);
>          destroy_lport_addresses(&ts_port_addrs);
>      }
>  }
>
>  static void
> -delete_orphan_ic_routes(struct ic_context *ctx,
> -                         const struct icsbrec_availability_zone *az)
> +delete_orphan_ic_routes(struct ic_input *ic,
> +                        const struct icsbrec_availability_zone *az)
>  {
>      const struct icsbrec_route *isb_route, *isb_route_key =
> -        icsbrec_route_index_init_row(ctx->icsbrec_route_by_az);
> +        icsbrec_route_index_init_row(ic->icsbrec_route_by_az);
>      icsbrec_route_index_set_availability_zone(isb_route_key, az);
>
>      const struct icnbrec_transit_switch *t_sw, *t_sw_key;
>
>      ICSBREC_ROUTE_FOR_EACH_EQUAL (isb_route, isb_route_key,
> -                                  ctx->icsbrec_route_by_az)
> +                                  ic->icsbrec_route_by_az)
>      {
>          t_sw_key = icnbrec_transit_switch_index_init_row(
> -            ctx->icnbrec_transit_switch_by_name);
> +            ic->icnbrec_transit_switch_by_name);
>          icnbrec_transit_switch_index_set_name(t_sw_key,
>              isb_route->transit_switch);
>          t_sw = icnbrec_transit_switch_index_find(
> -            ctx->icnbrec_transit_switch_by_name, t_sw_key);
> +            ic->icnbrec_transit_switch_by_name, t_sw_key);
>          icnbrec_transit_switch_index_destroy_row(t_sw_key);
>
> -        if (!t_sw || !find_lrp_of_nexthop(ctx, isb_route)) {
> +        if (!t_sw || !find_lrp_of_nexthop(ic, isb_route)) {
>              static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
>              VLOG_INFO_RL(&rl, "Deleting orphan ICDB:Route: %s->%s (%s, 
> rtb:%s,"
>                           " transit switch: %s)", isb_route->ip_prefix,
> @@ -2447,34 +2471,35 @@ delete_orphan_ic_routes(struct ic_context *ctx,
>  }
>
>  static void
> -route_run(struct ic_context *ctx)
> +route_run(struct engine_context *ctx,
> +          struct ic_input *ic)
>  {
> -    if (!ctx->ovnisb_txn || !ctx->ovnnb_txn) {
> +    if (!ctx->ovnisb_idl_txn || !ctx->ovnnb_idl_txn) {
>          return;
>      }
>
> -    delete_orphan_ic_routes(ctx, ctx->runned_az);
> +    delete_orphan_ic_routes(ic, ic->runned_az);
>
>      struct hmap ic_lrs = HMAP_INITIALIZER(&ic_lrs);
>      const struct icsbrec_port_binding *isb_pb;
>      const struct icsbrec_port_binding *isb_pb_key =
> -        icsbrec_port_binding_index_init_row(ctx->icsbrec_port_binding_by_az);
> +        icsbrec_port_binding_index_init_row(ic->icsbrec_port_binding_by_az);
>      icsbrec_port_binding_index_set_availability_zone(isb_pb_key,
> -        ctx->runned_az);
> +                                                     ic->runned_az);
>
>      /* Each port on TS maps to a logical router, which is stored in the
>       * external_ids:router-id of the IC SB port_binding record.
>       * Here we build info for interconnected Logical Router:
>       * collect IC Port Binding to process routes sync later on. */
>      ICSBREC_PORT_BINDING_FOR_EACH_EQUAL (isb_pb, isb_pb_key,
> -                                         ctx->icsbrec_port_binding_by_az)
> +                                         ic->icsbrec_port_binding_by_az)
>      {
>          if (ic_pb_get_type(isb_pb) == IC_ROUTER_PORT) {
>              continue;
>          }
>          const struct nbrec_logical_switch_port *nb_lsp;
>
> -        nb_lsp = get_lsp_by_ts_port_name(ctx, isb_pb->logical_port);
> +        nb_lsp = get_lsp_by_ts_port_name(ic, isb_pb->logical_port);
>          if (!strcmp(nb_lsp->type, "switch")) {
>              VLOG_DBG("IC-SB Port_Binding '%s' on ts '%s' corresponds to a "
>                       "switch port, not considering for route collection.",
> @@ -2483,7 +2508,7 @@ route_run(struct ic_context *ctx)
>          }
>
>          const char *ts_lrp_name =
> -            get_lrp_name_by_ts_port_name(ctx, isb_pb->logical_port);
> +            get_lrp_name_by_ts_port_name(ic, isb_pb->logical_port);
>          if (!ts_lrp_name) {
>              static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
>              VLOG_WARN_RL(&rl, "Route sync ignores port %s on ts %s because "
> @@ -2501,7 +2526,8 @@ route_run(struct ic_context *ctx)
>          }
>
>          const struct nbrec_logical_router *lr
> -            = nbrec_logical_router_get_for_uuid(ctx->ovnnb_idl, &lr_uuid);
> +            = nbrec_logical_router_table_get_for_uuid(
> +                ic->nbrec_logical_router_table, &lr_uuid);
>          if (!lr) {
>              continue;
>          }
> @@ -2522,8 +2548,8 @@ route_run(struct ic_context *ctx)
>      struct ic_router_info *ic_lr;
>      struct shash routes_ad_by_ts = SHASH_INITIALIZER(&routes_ad_by_ts);
>      HMAP_FOR_EACH_SAFE (ic_lr, node, &ic_lrs) {
> -        collect_lr_routes(ctx, ic_lr, &routes_ad_by_ts);
> -        sync_learned_routes(ctx, ic_lr);
> +        collect_lr_routes(ic, ic_lr, &routes_ad_by_ts);
> +        sync_learned_routes(ctx, ic, ic_lr);
>          vector_destroy(&ic_lr->isb_pbs);
>          hmap_destroy(&ic_lr->routes_learned);
>          hmap_remove(&ic_lrs, &ic_lr->node);
> @@ -2531,7 +2557,7 @@ route_run(struct ic_context *ctx)
>      }
>      struct shash_node *node;
>      SHASH_FOR_EACH (node, &routes_ad_by_ts) {
> -        advertise_routes(ctx, ctx->runned_az, node->name, node->data);
> +        advertise_routes(ctx, ic, ic->runned_az, node->name, node->data);
>          hmap_destroy(node->data);
>      }
>      shash_destroy_free_data(&routes_ad_by_ts);
> @@ -2665,18 +2691,18 @@ remove_unused_sb_records(struct hmap 
> *local_sb_svcs_map)
>  }
>
>  static void
> -create_pushed_svcs_mon(struct ic_context *ctx,
> +create_pushed_svcs_mon(struct ic_input *ic,
>                         struct hmap *pushed_svcs_map)
>  {
>      struct sbrec_service_monitor *key =
>          sbrec_service_monitor_index_init_row(
> -            ctx->sbrec_service_monitor_by_remote_type);
> +            ic->sbrec_service_monitor_by_remote_type);
>
>      sbrec_service_monitor_index_set_remote(key, true);
>
>      const struct sbrec_service_monitor *sb_rec;
>      SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key,
> -        ctx->sbrec_service_monitor_by_remote_type) {
> +        ic->sbrec_service_monitor_by_remote_type) {
>          const char *target_az_name = smap_get(&sb_rec->options,
>                                                "az-name");
>          if (!target_az_name) {
> @@ -2684,7 +2710,7 @@ create_pushed_svcs_mon(struct ic_context *ctx,
>          }
>          create_service_monitor_info(pushed_svcs_map, sb_rec,
>                                      &sb_rec->header_.uuid,
> -                                    ctx->runned_az->name, target_az_name,
> +                                    ic->runned_az->name, target_az_name,
>                                      NULL, false);
>      }
>
> @@ -2692,22 +2718,22 @@ create_pushed_svcs_mon(struct ic_context *ctx,
>  }
>
>  static void
> -create_synced_svcs_mon(struct ic_context *ctx,
> +create_synced_svcs_mon(struct ic_input *ic,
>                         struct hmap *synced_svcs_map)
>  {
>      struct icsbrec_service_monitor *key =
>          icsbrec_service_monitor_index_init_row(
> -          ctx->icsbrec_service_monitor_by_target_az);
> +          ic->icsbrec_service_monitor_by_target_az);
>
>      icsbrec_service_monitor_index_set_target_availability_zone(
> -        key, ctx->runned_az->name);
> +        key, ic->runned_az->name);
>
>      const struct icsbrec_service_monitor *ic_rec;
>      ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key,
> -        ctx->icsbrec_service_monitor_by_target_az) {
> +        ic->icsbrec_service_monitor_by_target_az) {
>
>          const struct sbrec_port_binding *pb =
> -            find_sb_pb_by_name(ctx->sbrec_port_binding_by_name,
> +            find_sb_pb_by_name(ic->sbrec_port_binding_by_name,
>                                 ic_rec->logical_port);
>
>          if (!pb || !pb->up) {
> @@ -2717,7 +2743,7 @@ create_synced_svcs_mon(struct ic_context *ctx,
>          const char *chassis_name = pb->chassis ? pb->chassis->name : NULL;
>          create_service_monitor_info(synced_svcs_map, ic_rec,
>                                      &ic_rec->header_.uuid,
> -                                    ctx->runned_az->name,
> +                                    ic->runned_az->name,
>                                      NULL, chassis_name, true);
>      }
>
> @@ -2725,22 +2751,22 @@ create_synced_svcs_mon(struct ic_context *ctx,
>  }
>
>  static void
> -create_local_ic_svcs_map(struct ic_context *ctx,
> +create_local_ic_svcs_map(struct ic_input *ic,
>                           struct hmap *owned_svc_map)
>  {
>      struct icsbrec_service_monitor *key =
>          icsbrec_service_monitor_index_init_row(
> -          ctx->icsbrec_service_monitor_by_source_az);
> +            ic->icsbrec_service_monitor_by_source_az);
>
>      icsbrec_service_monitor_index_set_source_availability_zone(
> -        key, ctx->runned_az->name);
> +        key, ic->runned_az->name);
>
>      const struct icsbrec_service_monitor *ic_rec;
>      ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key,
> -        ctx->icsbrec_service_monitor_by_source_az) {
> +        ic->icsbrec_service_monitor_by_source_az) {
>          create_service_monitor_info(owned_svc_map, ic_rec,
>                                      &ic_rec->header_.uuid,
> -                                    ctx->runned_az->name, NULL,
> +                                    ic->runned_az->name, NULL,
>                                      NULL, true);
>      }
>
> @@ -2748,22 +2774,22 @@ create_local_ic_svcs_map(struct ic_context *ctx,
>  }
>
>  static void
> -create_local_sb_svcs_map(struct ic_context *ctx,
> +create_local_sb_svcs_map(struct ic_input *ic,
>                           struct hmap *owned_svc_map)
>  {
>      struct sbrec_service_monitor *key =
>          sbrec_service_monitor_index_init_row(
> -          ctx->sbrec_service_monitor_by_ic_learned);
> +          ic->sbrec_service_monitor_by_ic_learned);
>
>      sbrec_service_monitor_index_set_ic_learned(
>          key, true);
>
>      const struct sbrec_service_monitor *sb_rec;
>      SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key,
> -        ctx->sbrec_service_monitor_by_ic_learned) {
> +        ic->sbrec_service_monitor_by_ic_learned) {
>          create_service_monitor_info(owned_svc_map, sb_rec,
>                                      &sb_rec->header_.uuid,
> -                                    ctx->runned_az->name, NULL,
> +                                    ic->runned_az->name, NULL,
>                                      NULL, false);
>      }
>
> @@ -2771,21 +2797,21 @@ create_local_sb_svcs_map(struct ic_context *ctx,
>  }
>
>  static const struct sbrec_service_monitor *
> -lookup_sb_svc_rec(struct ic_context *ctx,
> +lookup_sb_svc_rec(struct ic_input *ic,
>                    const struct service_monitor_info *svc_mon)
>  {
>      const struct icsbrec_service_monitor *db_rec =
>          svc_mon->db_rec.ic_rec;
>      struct sbrec_service_monitor *key =
>          sbrec_service_monitor_index_init_row(
> -            ctx->sbrec_service_monitor_by_remote_type_logical_port);
> +            ic->sbrec_service_monitor_by_remote_type_logical_port);
>
>      sbrec_service_monitor_index_set_remote(key, false);
>      sbrec_service_monitor_index_set_logical_port(key, db_rec->logical_port);
>
>      const struct sbrec_service_monitor *sb_rec;
>      SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key,
> -        ctx->sbrec_service_monitor_by_remote_type_logical_port) {
> +        ic->sbrec_service_monitor_by_remote_type_logical_port) {
>          if (db_rec->port == sb_rec->port &&
>              ((db_rec->type && sb_rec->type &&
>                !strcmp(db_rec->type, sb_rec->type)) ||
> @@ -2804,14 +2830,14 @@ lookup_sb_svc_rec(struct ic_context *ctx,
>  }
>
>  static const struct icsbrec_service_monitor *
> -lookup_icsb_svc_rec(struct ic_context *ctx,
> +lookup_icsb_svc_rec(struct ic_input *ic,
>                      const struct service_monitor_info *svc_mon)
>  {
>      const struct sbrec_service_monitor *db_rec =
>         svc_mon->db_rec.sb_rec;
>      struct icsbrec_service_monitor *key =
>          icsbrec_service_monitor_index_init_row(
> -        ctx->icsbrec_service_monitor_by_target_az_logical_port);
> +        ic->icsbrec_service_monitor_by_target_az_logical_port);
>
>      ovs_assert(svc_mon->dst_az_name);
>      icsbrec_service_monitor_index_set_target_availability_zone(
> @@ -2822,7 +2848,7 @@ lookup_icsb_svc_rec(struct ic_context *ctx,
>
>      const struct icsbrec_service_monitor *ic_rec;
>      ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key,
> -        ctx->icsbrec_service_monitor_by_target_az_logical_port) {
> +        ic->icsbrec_service_monitor_by_target_az_logical_port) {
>          if (db_rec->port == ic_rec->port &&
>              ((db_rec->type && ic_rec->type &&
>                !strcmp(db_rec->type, ic_rec->type)) ||
> @@ -2842,11 +2868,11 @@ lookup_icsb_svc_rec(struct ic_context *ctx,
>  }
>
>  static void
> -create_service_monitor_data(struct ic_context *ctx,
> +create_service_monitor_data(struct ic_input *ic,
>                              struct sync_service_monitor_data *sync_data)
>  {
> -    const struct sbrec_sb_global *ic_sb = sbrec_sb_global_first(
> -                                                ctx->ovnsb_idl);
> +    const struct sbrec_sb_global *ic_sb =
> +        sbrec_sb_global_table_first(ic->sbrec_sb_global_table);
>      const char *svc_monitor_mac = smap_get(&ic_sb->options,
>                                             "svc_monitor_mac");
>
> @@ -2855,10 +2881,10 @@ create_service_monitor_data(struct ic_context *ctx,
>      }
>
>      sync_data->prpg_svc_monitor_mac = xstrdup(svc_monitor_mac);
> -    create_pushed_svcs_mon(ctx, &sync_data->pushed_svcs_map);
> -    create_synced_svcs_mon(ctx, &sync_data->synced_svcs_map);
> -    create_local_ic_svcs_map(ctx, &sync_data->local_ic_svcs_map);
> -    create_local_sb_svcs_map(ctx, &sync_data->local_sb_svcs_map);
> +    create_pushed_svcs_mon(ic, &sync_data->pushed_svcs_map);
> +    create_synced_svcs_mon(ic, &sync_data->synced_svcs_map);
> +    create_local_ic_svcs_map(ic, &sync_data->local_ic_svcs_map);
> +    create_local_sb_svcs_map(ic, &sync_data->local_sb_svcs_map);
>  }
>
>  static void
> @@ -2879,9 +2905,10 @@ destroy_service_monitor_data(struct 
> sync_service_monitor_data *sync_data)
>  }
>
>  static void
> -sync_service_monitor(struct ic_context *ctx)
> +sync_service_monitor(struct engine_context *ctx,
> +                     struct ic_input *ic)
>  {
> -    if (!ctx->ovnisb_txn || !ctx->ovnsb_txn) {
> +    if (!ctx->ovnisb_idl_txn || !ctx->ovnsb_idl_txn) {
>          return;
>      }
>
> @@ -2892,18 +2919,18 @@ sync_service_monitor(struct ic_context *ctx)
>      hmap_init(&sync_data.local_ic_svcs_map);
>      hmap_init(&sync_data.local_sb_svcs_map);
>
> -    create_service_monitor_data(ctx, &sync_data);
> +    create_service_monitor_data(ic, &sync_data);
>
>      struct service_monitor_info *svc_mon;
>      HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &sync_data.pushed_svcs_map) {
>          const struct sbrec_service_monitor *db_rec = svc_mon->db_rec.sb_rec;
>          const struct icsbrec_service_monitor *ic_rec =
> -            lookup_icsb_svc_rec(ctx, svc_mon);
> +            lookup_icsb_svc_rec(ic, svc_mon);
>
>          if (ic_rec) {
>              sbrec_service_monitor_set_status(db_rec, ic_rec->status);
>          } else {
> -            ic_rec = icsbrec_service_monitor_insert(ctx->ovnisb_txn);
> +            ic_rec = icsbrec_service_monitor_insert(ctx->ovnisb_idl_txn);
>              icsbrec_service_monitor_set_type(ic_rec, db_rec->type);
>              icsbrec_service_monitor_set_ip(ic_rec, db_rec->ip);
>              icsbrec_service_monitor_set_port(ic_rec, db_rec->port);
> @@ -2928,13 +2955,13 @@ sync_service_monitor(struct ic_context *ctx)
>          const struct icsbrec_service_monitor *db_rec =
>              svc_mon->db_rec.ic_rec;
>          const struct sbrec_service_monitor *sb_rec =
> -            lookup_sb_svc_rec(ctx, svc_mon);
> +            lookup_sb_svc_rec(ic, svc_mon);
>
>          if (sb_rec) {
>              icsbrec_service_monitor_set_status(svc_mon->db_rec.ic_rec,
>                                                 sb_rec->status);
>          } else {
> -            sb_rec = sbrec_service_monitor_insert(ctx->ovnsb_txn);
> +            sb_rec = sbrec_service_monitor_insert(ctx->ovnsb_idl_txn);
>              sbrec_service_monitor_set_type(sb_rec, db_rec->type);
>              sbrec_service_monitor_set_ip(sb_rec, db_rec->ip);
>              sbrec_service_monitor_set_port(sb_rec, db_rec->port);
> @@ -3002,55 +3029,60 @@ sync_service_monitor(struct ic_context *ctx)
>   *    INB:nb_ic_cfg and INB:sb_ic_cfg to INB:nb_ic_cfg.
>   */
>  static void
> -update_sequence_numbers(struct ic_context *ctx,
> -                        struct ovsdb_idl_loop *ic_sb_loop)
> -{
> -    if (!ctx->ovnisb_txn || !ctx->ovninb_txn) {
> +update_sequence_numbers(struct ovsdb_idl *ovninb_idl,
> +                        struct ovsdb_idl *ovnisb_idl,
> +                        struct ovsdb_idl_txn *ovninb_txn,
> +                        struct ovsdb_idl_txn *ovnisb_txn,
> +                        struct ovsdb_idl_loop *ic_sb_loop,
> +                        const struct icsbrec_availability_zone *az)
> +{
> +    if (!ovnisb_txn || !ovninb_txn) {
>          return;
>      }
>
>      const struct icnbrec_ic_nb_global *ic_nb = icnbrec_ic_nb_global_first(
> -                                               ctx->ovninb_idl);
> +                                               ovninb_idl);
>      if (!ic_nb) {
> -        ic_nb = icnbrec_ic_nb_global_insert(ctx->ovninb_txn);
> +        ic_nb = icnbrec_ic_nb_global_insert(ovninb_txn);
>      }
>      const struct icsbrec_ic_sb_global *ic_sb = icsbrec_ic_sb_global_first(
> -                                               ctx->ovnisb_idl);
> +                                               ovnisb_idl);
>      if (!ic_sb) {
> -        ic_sb = icsbrec_ic_sb_global_insert(ctx->ovnisb_txn);
> +        ic_sb = icsbrec_ic_sb_global_insert(ovnisb_txn);
>      }
>
>      if ((ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg) &&
> -                          (ic_nb->nb_ic_cfg != ctx->runned_az->nb_ic_cfg)) {
> +                          (ic_nb->nb_ic_cfg != az->nb_ic_cfg)) {
>          /* Deal with potential overflows. */
> -        if (ctx->runned_az->nb_ic_cfg == INT64_MAX) {
> -            icsbrec_availability_zone_set_nb_ic_cfg(ctx->runned_az, 0);
> +        if (az->nb_ic_cfg == INT64_MAX) {
> +            icsbrec_availability_zone_set_nb_ic_cfg(az, 0);
>          }
>          ic_sb_loop->next_cfg = ic_nb->nb_ic_cfg;
> -        ovsdb_idl_txn_increment(ctx->ovnisb_txn, &ctx->runned_az->header_,
> -            &icsbrec_availability_zone_col_nb_ic_cfg, true);
> +        ovsdb_idl_txn_increment(ovnisb_txn, &az->header_,
> +                                &icsbrec_availability_zone_col_nb_ic_cfg,
> +                                true);
>          return;
>      }
>
>      /* handle cases where accidentally AZ:ic_nb_cfg exceeds
>       * the INB:ic_nb_cfg.
>       */
> -    if (ctx->runned_az->nb_ic_cfg != ic_sb_loop->cur_cfg) {
> -        icsbrec_availability_zone_set_nb_ic_cfg(ctx->runned_az,
> +    if (az->nb_ic_cfg != ic_sb_loop->cur_cfg) {
> +        icsbrec_availability_zone_set_nb_ic_cfg(az,
>                                                  ic_sb_loop->cur_cfg);
>          return;
>      }
>
>      const struct icsbrec_availability_zone *other_az;
> -    ICSBREC_AVAILABILITY_ZONE_FOR_EACH (other_az, ctx->ovnisb_idl) {
> -        if (other_az->nb_ic_cfg != ctx->runned_az->nb_ic_cfg) {
> +    ICSBREC_AVAILABILITY_ZONE_FOR_EACH (other_az, ovnisb_idl) {
> +        if (other_az->nb_ic_cfg != az->nb_ic_cfg) {
>              return;
>          }
>      }
>      /* All the AZs are updated successfully, update SB/NB counter. */
>      if (ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg) {
> -        icsbrec_ic_sb_global_set_nb_ic_cfg(ic_sb, ctx->runned_az->nb_ic_cfg);
> -        icnbrec_ic_nb_global_set_sb_ic_cfg(ic_nb, ctx->runned_az->nb_ic_cfg);
> +        icsbrec_ic_sb_global_set_nb_ic_cfg(ic_sb, az->nb_ic_cfg);
> +        icnbrec_ic_nb_global_set_sb_ic_cfg(ic_nb, az->nb_ic_cfg);
>      }
>  }
>
> @@ -3077,23 +3109,18 @@ inc_proc_graph_dump(const char *end_node)
>  }
>
>  void
> -ovn_db_run(struct ic_context *ctx)
> -{
> -    struct hmap dp_tnlids = HMAP_INITIALIZER(&dp_tnlids);
> -    struct shash isb_ts_dps = SHASH_INITIALIZER(&isb_ts_dps);
> -    struct shash isb_tr_dps = SHASH_INITIALIZER(&isb_tr_dps);
> -
> -    gateway_run(ctx);
> -    enumerate_datapaths(ctx, &dp_tnlids, &isb_ts_dps, &isb_tr_dps);
> -    ts_run(ctx, &dp_tnlids, &isb_ts_dps);
> -    tr_run(ctx, &dp_tnlids, &isb_tr_dps);
> -    port_binding_run(ctx);
> -    route_run(ctx);
> -    sync_service_monitor(ctx);
> -
> -    ovn_destroy_tnlids(&dp_tnlids);
> -    shash_destroy(&isb_ts_dps);
> -    shash_destroy(&isb_tr_dps);
> +ovn_db_run(struct ic_input *input_data,
> +           struct ic_data *ic_data,
> +           struct engine_context *eng_ctx)
> +{
> +    gateway_run(eng_ctx, input_data);
> +    enumerate_datapaths(input_data, &ic_data->dp_tnlids,
> +                        &ic_data->isb_ts_dps, &ic_data->isb_tr_dps);
> +    ts_run(eng_ctx, input_data, &ic_data->dp_tnlids, &ic_data->isb_ts_dps);
> +    tr_run(eng_ctx, input_data, &ic_data->dp_tnlids, &ic_data->isb_tr_dps);
> +    port_binding_run(eng_ctx, input_data);
> +    route_run(eng_ctx, input_data);
> +    sync_service_monitor(eng_ctx, input_data);
>  }
>
>  static void
> @@ -3485,81 +3512,6 @@ main(int argc, char *argv[])
>      ovsdb_idl_track_add_column(ovnsb_idl_loop.idl,
>                                 &sbrec_service_monitor_col_options);
>
> -    /* Create IDL indexes */
> -    struct ovsdb_idl_index *nbrec_ls_by_name
> -        = ovsdb_idl_index_create1(ovnnb_idl_loop.idl,
> -                                  &nbrec_logical_switch_col_name);
> -    struct ovsdb_idl_index *nbrec_lr_by_name = ovsdb_idl_index_create1(
> -        ovnnb_idl_loop.idl, &nbrec_logical_router_col_name);
> -    struct ovsdb_idl_index *nbrec_port_by_name
> -        = ovsdb_idl_index_create1(ovnnb_idl_loop.idl,
> -                                  &nbrec_logical_switch_port_col_name);
> -    struct ovsdb_idl_index *nbrec_lrp_by_name
> -        = ovsdb_idl_index_create1(ovnnb_idl_loop.idl,
> -                                  &nbrec_logical_router_port_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_chassis_by_name
> -        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
> -                                  &sbrec_chassis_col_name);
> -
> -    struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type
> -        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
> -                                  &sbrec_service_monitor_col_remote);
> -
> -    struct ovsdb_idl_index *sbrec_service_monitor_by_ic_learned
> -        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
> -                                  &sbrec_service_monitor_col_ic_learned);
> -
> -    struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type_logical_port
> -        = ovsdb_idl_index_create2(ovnsb_idl_loop.idl,
> -                                  &sbrec_service_monitor_col_remote,
> -                                  &sbrec_service_monitor_col_logical_port);
> -
> -    struct ovsdb_idl_index *icnbrec_transit_switch_by_name
> -        = ovsdb_idl_index_create1(ovninb_idl_loop.idl,
> -                                  &icnbrec_transit_switch_col_name);
> -
> -    struct ovsdb_idl_index *icsbrec_port_binding_by_az
> -        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,
> -                                  
> &icsbrec_port_binding_col_availability_zone);
> -
> -    struct ovsdb_idl_index *icsbrec_port_binding_by_ts
> -        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,
> -                                  &icsbrec_port_binding_col_transit_switch);
> -
> -    struct ovsdb_idl_index *icsbrec_port_binding_by_ts_az
> -        = ovsdb_idl_index_create2(ovnisb_idl_loop.idl,
> -                                  &icsbrec_port_binding_col_transit_switch,
> -                                  
> &icsbrec_port_binding_col_availability_zone);
> -
> -    struct ovsdb_idl_index *icsbrec_route_by_az
> -        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,
> -                                  &icsbrec_route_col_availability_zone);
> -
> -    struct ovsdb_idl_index *icsbrec_route_by_ts
> -        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,
> -                                  &icsbrec_route_col_transit_switch);
> -
> -    struct ovsdb_idl_index *icsbrec_route_by_ts_az
> -        = ovsdb_idl_index_create2(ovnisb_idl_loop.idl,
> -                                  &icsbrec_route_col_transit_switch,
> -                                  &icsbrec_route_col_availability_zone);
> -
> -    struct ovsdb_idl_index *icsbrec_service_monitor_by_source_az
> -        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,
> -            &icsbrec_service_monitor_col_source_availability_zone);
> -
> -    struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az
> -        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,
> -            &icsbrec_service_monitor_col_target_availability_zone);
> -
> -    struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az_logical_port
> -        = ovsdb_idl_index_create2(ovnisb_idl_loop.idl,
> -            &icsbrec_service_monitor_col_target_availability_zone,
> -            &icsbrec_service_monitor_col_logical_port);
> -
>      unixctl_command_register("nb-connection-status", "", 0, 0,
>                               ovn_conn_show, ovnnb_idl_loop.idl);
>      unixctl_command_register("sb-connection-status", "", 0, 0,
> @@ -3569,6 +3521,8 @@ main(int argc, char *argv[])
>      unixctl_command_register("ic-sb-connection-status", "", 0, 0,
>                               ovn_conn_show, ovnisb_idl_loop.idl);
>
> +    stopwatch_create(IC_OVN_DB_RUN_STOPWATCH_NAME, SW_MS);
> +
>      /* Initialize incremental processing engine for ovn-northd */
>      inc_proc_ic_init(&ovnnb_idl_loop, &ovnsb_idl_loop,
>                       &ovninb_idl_loop, &ovnisb_idl_loop);
> @@ -3662,67 +3616,43 @@ main(int argc, char *argv[])
>                  ovnisb_cond_seqno = new_ovnisb_cond_seqno;
>              }
>
> -            struct ic_context ctx = {
> -                .ovnnb_idl = ovnnb_idl_loop.idl,
> -                .ovnnb_txn = ovnnb_txn,
> -                .ovnsb_idl = ovnsb_idl_loop.idl,
> -                .ovnsb_txn = ovnsb_txn,
> -                .ovninb_idl = ovninb_idl_loop.idl,
> -                .ovninb_txn = ovninb_txn,
> -                .ovnisb_idl = ovnisb_idl_loop.idl,
> -                .ovnisb_txn = ovnisb_txn,
> -                .nbrec_ls_by_name = nbrec_ls_by_name,
> -                .nbrec_lr_by_name = nbrec_lr_by_name,
> -                .nbrec_lrp_by_name = nbrec_lrp_by_name,
> -                .nbrec_port_by_name = nbrec_port_by_name,
> -                .sbrec_port_binding_by_name = sbrec_port_binding_by_name,
> -                .sbrec_chassis_by_name = sbrec_chassis_by_name,
> -                .sbrec_service_monitor_by_remote_type =
> -                    sbrec_service_monitor_by_remote_type,
> -                .sbrec_service_monitor_by_ic_learned =
> -                    sbrec_service_monitor_by_ic_learned,
> -                .sbrec_service_monitor_by_remote_type_logical_port =
> -                    sbrec_service_monitor_by_remote_type_logical_port,
> -                .icnbrec_transit_switch_by_name =
> -                    icnbrec_transit_switch_by_name,
> -                .icsbrec_port_binding_by_az = icsbrec_port_binding_by_az,
> -                .icsbrec_port_binding_by_ts = icsbrec_port_binding_by_ts,
> -                .icsbrec_port_binding_by_ts_az = 
> icsbrec_port_binding_by_ts_az,
> -                .icsbrec_route_by_az = icsbrec_route_by_az,
> -                .icsbrec_route_by_ts = icsbrec_route_by_ts,
> -                .icsbrec_route_by_ts_az = icsbrec_route_by_ts_az,
> -                .icsbrec_service_monitor_by_source_az =
> -                    icsbrec_service_monitor_by_source_az,
> -                .icsbrec_service_monitor_by_target_az =
> -                    icsbrec_service_monitor_by_target_az,
> -                .icsbrec_service_monitor_by_target_az_logical_port =
> -                    icsbrec_service_monitor_by_target_az_logical_port,
> -            };
> -
> -            if (!state.had_lock && ovsdb_idl_has_lock(ctx.ovnsb_idl)) {
> +            if (!state.had_lock && ovsdb_idl_has_lock(ovnsb_idl_loop.idl)) {
>                  VLOG_INFO("ovn-ic lock acquired. "
>                              "This ovn-ic instance is now active.");
>                  state.had_lock = true;
>              } else if (state.had_lock &&
> -                       !ovsdb_idl_has_lock(ctx.ovnsb_idl)) {
> +                       !ovsdb_idl_has_lock(ovnsb_idl_loop.idl)) {
>                  VLOG_INFO("ovn-ic lock lost. "
>                              "This ovn-ic instance is now on standby.");
>                  state.had_lock = false;
>              }
>
> -            if (ovsdb_idl_has_lock(ctx.ovnsb_idl) &&
> -                ovsdb_idl_has_ever_connected(ctx.ovnnb_idl) &&
> -                ovsdb_idl_has_ever_connected(ctx.ovnsb_idl) &&
> -                ovsdb_idl_has_ever_connected(ctx.ovninb_idl) &&
> -                ovsdb_idl_has_ever_connected(ctx.ovnisb_idl)) {
> -                if (ctx.ovnnb_txn && ctx.ovnsb_txn && ctx.ovninb_txn &&
> -                    ctx.ovnisb_txn && inc_proc_ic_can_run(&eng_ctx)) {
> -                    ctx.runned_az = az_run(&ctx);
> -                    VLOG_DBG("Availability zone: %s", ctx.runned_az ?
> -                             ctx.runned_az->name : "not created yet.");
> -                    if (ctx.runned_az) {
> -                        (void) inc_proc_ic_run(&ctx, &eng_ctx);
> -                        update_sequence_numbers(&ctx, &ovnisb_idl_loop);
> +            if (ovsdb_idl_has_lock(ovnsb_idl_loop.idl) &&
> +                ovsdb_idl_has_ever_connected(ovnnb_idl_loop.idl) &&
> +                ovsdb_idl_has_ever_connected(ovnsb_idl_loop.idl) &&
> +                ovsdb_idl_has_ever_connected(ovninb_idl_loop.idl) &&
> +                ovsdb_idl_has_ever_connected(ovnisb_idl_loop.idl)) {
> +                if (ovnnb_txn && ovnsb_txn && ovninb_txn &&
> +                    ovnisb_txn && inc_proc_ic_can_run(&eng_ctx)) {
> +                    const struct icsbrec_availability_zone *az =
> +                        az_run(ovnnb_idl_loop.idl,
> +                               ovnisb_idl_loop.idl,
> +                               ovnisb_txn);
> +                    VLOG_DBG("Availability zone: %s", az ?
> +                             az->name : "not created yet.");
> +                    if (az) {
> +                        (void) inc_proc_ic_run(ovnnb_txn,
> +                                               ovnsb_txn,
> +                                               ovninb_txn,
> +                                               ovnisb_txn,
> +                                               &eng_ctx,
> +                                               az);
> +                        update_sequence_numbers(ovninb_idl_loop.idl,
> +                                                ovnisb_idl_loop.idl,
> +                                                ovninb_txn,
> +                                                ovnisb_txn,
> +                                                &ovnisb_idl_loop,
> +                                                az);
>                      }
>                  } else if (!inc_proc_ic_get_force_recompute()) {
>                      clear_idl_track = false;
> @@ -3812,10 +3742,12 @@ main(int argc, char *argv[])
>              poll_immediate_wake();
>          }
>
> +        stopwatch_stop(NORTHD_LOOP_STOPWATCH_NAME, time_msec());
>          poll_block();
>          if (should_service_stop()) {
>              exiting = true;
>          }
> +        stopwatch_start(NORTHD_LOOP_STOPWATCH_NAME, time_msec());
>      }
>      inc_proc_ic_cleanup();
>
> @@ -3885,8 +3817,8 @@ ovn_ic_status(struct unixctl_conn *conn, int argc 
> OVS_UNUSED,
>      }
>
>      /*
> -     * Use a labelled formatted output so we can add more to the status 
> command
> -     * later without breaking any consuming scripts
> +     * Use a labelled formatted output so we can add more to the status
> +     * command later without breaking any consuming scripts
>       */
>      struct ds s = DS_EMPTY_INITIALIZER;
>      ds_put_format(&s, "Status: %s\n", status);
> diff --git a/ic/ovn-ic.h b/ic/ovn-ic.h
> index e8d7a970f..2c2efc046 100644
> --- a/ic/ovn-ic.h
> +++ b/ic/ovn-ic.h
> @@ -16,16 +16,33 @@
>
>  #include "ovsdb-idl.h"
>  #include "unixctl.h"
> +#include "lib/inc-proc-eng.h"
>
> -struct ic_context {
> -    struct ovsdb_idl *ovnnb_idl;
> -    struct ovsdb_idl *ovnsb_idl;
> -    struct ovsdb_idl *ovninb_idl;
> -    struct ovsdb_idl *ovnisb_idl;
> -    struct ovsdb_idl_txn *ovnnb_txn;
> -    struct ovsdb_idl_txn *ovnsb_txn;
> -    struct ovsdb_idl_txn *ovninb_txn;
> -    struct ovsdb_idl_txn *ovnisb_txn;
> +struct ic_input {
> +    /* Northbound table references */
> +    const struct nbrec_logical_switch_table *nbrec_logical_switch_table;
> +    const struct nbrec_logical_router_table *nbrec_logical_router_table;
> +    const struct nbrec_nb_global_table *nbrec_nb_global_table;
> +
> +    /* Southbound table references */
> +    const struct sbrec_chassis_table *sbrec_chassis_table;
> +    const struct sbrec_sb_global_table *sbrec_sb_global_table;
> +
> +    /* InterconnectNorthbound table references */
> +    const struct icnbrec_transit_switch_table *icnbrec_transit_switch_table;
> +    const struct icnbrec_ic_nb_global_table *icnbrec_ic_nb_global_table;
> +    const struct icnbrec_transit_router_table *icnbrec_transit_router_table;
> +
> +    /* InterconnectSouthbound table references */
> +    const struct icsbrec_encap_table *icsbrec_encap_table;
> +    const struct icsbrec_gateway_table *icsbrec_gateway_table;
> +    const struct icsbrec_ic_sb_global_table *icsbrec_ic_sb_global_table;
> +    const struct icsbrec_datapath_binding_table
> +        *icsbrec_datapath_binding_table;
> +    const struct icsbrec_availability_zone_table
> +        *icsbrec_availability_zone_table;
> +
> +    /* Indexes */
>      const struct icsbrec_availability_zone *runned_az;
>      struct ovsdb_idl_index *nbrec_ls_by_name;
>      struct ovsdb_idl_index *nbrec_lr_by_name;
> @@ -48,6 +65,12 @@ struct ic_context {
>      struct ovsdb_idl_index 
> *icsbrec_service_monitor_by_target_az_logical_port;
>  };
>
> +struct ic_data {
> +    /* Global state for 'en-ic'. */
> +    struct hmap dp_tnlids;
> +    struct shash isb_ts_dps;
> +    struct shash isb_tr_dps;
> +};
>  struct ic_state {
>      bool had_lock;
>      bool paused;
> @@ -56,6 +79,13 @@ struct ic_state {
>  enum ic_datapath_type { IC_SWITCH, IC_ROUTER, IC_DATAPATH_MAX };
>  enum ic_port_binding_type { IC_SWITCH_PORT, IC_ROUTER_PORT, IC_PORT_MAX };
>
> -void ovn_db_run(struct ic_context *ctx);
> +const struct icsbrec_availability_zone *
> +    az_run(struct ovsdb_idl *ovnnb_idl,
> +           struct ovsdb_idl *ovnisb_idl,
> +           struct ovsdb_idl_txn *ovnisb_idl_txn);
> +
> +void ovn_db_run(struct ic_input *input_data,
> +                struct ic_data *ic_data,
> +                struct engine_context *eng_ctx);
>
>  #endif /* OVN_IC_H */
> diff --git a/lib/stopwatch-names.h b/lib/stopwatch-names.h
> index b912e813c..e933213d8 100644
> --- a/lib/stopwatch-names.h
> +++ b/lib/stopwatch-names.h
> @@ -40,4 +40,6 @@
>  #define DYNAMIC_ROUTES_RUN_STOPWATCH_NAME "dynamic_routes"
>  #define GROUP_ECMP_ROUTE_RUN_STOPWATCH_NAME "group_ecmp_route"
>
> +#define IC_OVN_DB_RUN_STOPWATCH_NAME "ovn_db_run"
> +
>  #endif
> --
> 2.34.1
>
>
> --
>
>
>
>
> _'Esta mensagem é direcionada apenas para os endereços constantes no
> cabeçalho inicial. Se você não está listado nos endereços constantes no
> cabeçalho, pedimos-lhe que desconsidere completamente o conteúdo dessa
> mensagem e cuja cópia, encaminhamento e/ou execução das ações citadas estão
> imediatamente anuladas e proibidas'._
>
>
> * **'Apesar do Magazine Luiza tomar
> todas as precauções razoáveis para assegurar que nenhum vírus esteja
> presente nesse e-mail, a empresa não poderá aceitar a responsabilidade por
> quaisquer perdas ou danos causados por esse e-mail ou por seus anexos'.*

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

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

Reply via email to