diff mbox series

[ovs-dev,v0,1/9] ovn-ic: Introduce structs ic_data and ic_input.

Message ID 20260120114948.2289909-2-guilherme.paulo@luizalabs.com
State New
Headers show
Series Create multiple engines nodes for ovn-ic. | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed
ovsrobot/github-robot-_ovn-kubernetes success github build: passed

Commit Message

Paulo Guilherme \(MGC NETP SDN\) Jan. 20, 2026, 11:49 a.m. UTC
'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 <guilherme.paulo@luizalabs.com>
---
 ic/en-ic.c            | 168 ++++++++++-
 ic/en-ic.h            |   2 +-
 ic/inc-proc-ic.c      | 145 ++++++++-
 ic/inc-proc-ic.h      |   8 +-
 ic/ovn-ic.c           | 680 +++++++++++++++++++-----------------------
 ic/ovn-ic.h           |  50 +++-
 lib/stopwatch-names.h |   3 +
 7 files changed, 652 insertions(+), 404 deletions(-)

Comments

Mairtin O'Loingsigh Jan. 30, 2026, 3:34 p.m. UTC | #1
On Tue, Jan 20, 2026 at 08:49:40AM -0300, Paulo Guilherme Silva via dev 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 <guilherme.paulo@luizalabs.com>
> ---
>  ic/en-ic.c            | 168 ++++++++++-
>  ic/en-ic.h            |   2 +-
>  ic/inc-proc-ic.c      | 145 ++++++++-
>  ic/inc-proc-ic.h      |   8 +-
>  ic/ovn-ic.c           | 680 +++++++++++++++++++-----------------------
>  ic/ovn-ic.h           |  50 +++-
>  lib/stopwatch-names.h |   3 +
>  7 files changed, 652 insertions(+), 404 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());
> +    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..2f4579464 100644
> --- a/ic/inc-proc-ic.c
> +++ b/ic/inc-proc-ic.c
> @@ -157,7 +157,7 @@ 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,
nit: Function return type should be on seperate line
>                        struct ovsdb_idl_loop *sb,
> @@ -187,11 +187,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 +203,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 +368,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..f4a97fbca 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;
>          }
>      }
>  
>      /* 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;
>      }
>      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,
nit: incorrect paramater alignment
> -        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);
nit: incorrect alignment. This applies below also
> +          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,32 +3029,36 @@ 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_,
> +        ovsdb_idl_txn_increment(ovnisb_txn, &az->header_,
nit: incorrect alignment
>              &icsbrec_availability_zone_col_nb_ic_cfg, true);
>          return;
>      }
> @@ -3035,22 +3066,22 @@ update_sequence_numbers(struct ic_context *ctx,
>      /* 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 +3108,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 +3511,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 +3520,9 @@ main(int argc, char *argv[])
>      unixctl_command_register("ic-sb-connection-status", "", 0, 0,
>                               ovn_conn_show, ovnisb_idl_loop.idl);
>  
> +    stopwatch_create(OVN_IC_LOOP_STOPWATCH_NAME, SW_MS);
nit: OVN_IC_LOOP_STOPWATCH_NAME never used.
> +    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..5f1091155 100644
> --- a/lib/stopwatch-names.h
> +++ b/lib/stopwatch-names.h
> @@ -40,4 +40,7 @@
>  #define DYNAMIC_ROUTES_RUN_STOPWATCH_NAME "dynamic_routes"
>  #define GROUP_ECMP_ROUTE_RUN_STOPWATCH_NAME "group_ecmp_route"
>  
> +#define OVN_IC_LOOP_STOPWATCH_NAME "ovn-ic-loop"
> +#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
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> 

Just a few small nits

Acked-by: Mairtin O'Loingsigh <moloings@redhat.com>
Paulo Guilherme \(MGC NETP SDN\) Feb. 4, 2026, 11:17 p.m. UTC | #2
Hi Mairtin,

Thank you for review the patch. I have applied for most of your
observations, with the exception of this note. I would like to know what
your suggestion would be
before submitting for the next review.

ble=  /* 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));

These are used to extract data from the database tables (OVSDB) that have
been "registered" as dependencies of the en-ic node of the processing
engine.

Since we need to access several OVSDB reference tables throughout the
various functions within the en-ic engine, I chose to concentrate them all
in this
initialization structure along with their respective indexes. As future
engines are created, they will begin to migrate from the current engine to
the future ones.
Without this current definition, the source code compiles, but the ovn-ic
process fails drastically.

Thanks in advance,
Paulo

Em sex., 30 de jan. de 2026 às 12:34, Mairtin O'Loingsigh <
moloings@redhat.com> escreveu:

> On Tue, Jan 20, 2026 at 08:49:40AM -0300, Paulo Guilherme Silva via dev
> 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 <guilherme.paulo@luizalabs.com>
> > ---
> >  ic/en-ic.c            | 168 ++++++++++-
> >  ic/en-ic.h            |   2 +-
> >  ic/inc-proc-ic.c      | 145 ++++++++-
> >  ic/inc-proc-ic.h      |   8 +-
> >  ic/ovn-ic.c           | 680 +++++++++++++++++++-----------------------
> >  ic/ovn-ic.h           |  50 +++-
> >  lib/stopwatch-names.h |   3 +
> >  7 files changed, 652 insertions(+), 404 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());
> > +    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..2f4579464 100644
> > --- a/ic/inc-proc-ic.c
> > +++ b/ic/inc-proc-ic.c
> > @@ -157,7 +157,7 @@ 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,
> nit: Function return type should be on seperate line
> >                        struct ovsdb_idl_loop *sb,
> > @@ -187,11 +187,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 +203,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 +368,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..f4a97fbca 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;
> >          }
> >      }
> >
> >      /* 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;
> >      }
> >      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,
> nit: incorrect paramater alignment
> > -        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);
> nit: incorrect alignment. This applies below also
> > +          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,32 +3029,36 @@ 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_,
> > +        ovsdb_idl_txn_increment(ovnisb_txn, &az->header_,
> nit: incorrect alignment
> >              &icsbrec_availability_zone_col_nb_ic_cfg, true);
> >          return;
> >      }
> > @@ -3035,22 +3066,22 @@ update_sequence_numbers(struct ic_context *ctx,
> >      /* 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 +3108,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 +3511,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 +3520,9 @@ main(int argc, char *argv[])
> >      unixctl_command_register("ic-sb-connection-status", "", 0, 0,
> >                               ovn_conn_show, ovnisb_idl_loop.idl);
> >
> > +    stopwatch_create(OVN_IC_LOOP_STOPWATCH_NAME, SW_MS);
> nit: OVN_IC_LOOP_STOPWATCH_NAME never used.
> > +    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..5f1091155 100644
> > --- a/lib/stopwatch-names.h
> > +++ b/lib/stopwatch-names.h
> > @@ -40,4 +40,7 @@
> >  #define DYNAMIC_ROUTES_RUN_STOPWATCH_NAME "dynamic_routes"
> >  #define GROUP_ECMP_ROUTE_RUN_STOPWATCH_NAME "group_ecmp_route"
> >
> > +#define OVN_IC_LOOP_STOPWATCH_NAME "ovn-ic-loop"
> > +#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
> > dev@openvswitch.org
> > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> >
>
> Just a few small nits
>
> Acked-by: Mairtin O'Loingsigh <moloings@redhat.com>
>
>
Mairtin OLoingsigh via dev Feb. 5, 2026, 2:06 p.m. UTC | #3
On Wed, Feb 04, 2026 at 08:17:50PM -0300, Paulo Guilherme (MGC NETP SDN) wrote:
> Hi Mairtin,
> 
> Thank you for review the patch. I have applied for most of your
> observations, with the exception of this note. I would like to know what
> your suggestion would be
> before submitting for the next review.
> 
> ble=  /* 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));
> 
> These are used to extract data from the database tables (OVSDB) that have
> been "registered" as dependencies of the en-ic node of the processing
> engine.
> 
> Since we need to access several OVSDB reference tables throughout the
> various functions within the en-ic engine, I chose to concentrate them all
> in this
> initialization structure along with their respective indexes. As future
> engines are created, they will begin to migrate from the current engine to
> the future ones.
> Without this current definition, the source code compiles, but the ovn-ic
> process fails drastically.
> 
> Thanks in advance,
> Paulo
> 
> Em sex., 30 de jan. de 2026 às 12:34, Mairtin O'Loingsigh <
> moloings@redhat.com> escreveu:
> 
> > On Tue, Jan 20, 2026 at 08:49:40AM -0300, Paulo Guilherme Silva via dev
> > 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 <guilherme.paulo@luizalabs.com>
> > > ---
> > >  ic/en-ic.c            | 168 ++++++++++-
> > >  ic/en-ic.h            |   2 +-
> > >  ic/inc-proc-ic.c      | 145 ++++++++-
> > >  ic/inc-proc-ic.h      |   8 +-
> > >  ic/ovn-ic.c           | 680 +++++++++++++++++++-----------------------
> > >  ic/ovn-ic.h           |  50 +++-
> > >  lib/stopwatch-names.h |   3 +
> > >  7 files changed, 652 insertions(+), 404 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());
> > > +    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..2f4579464 100644
> > > --- a/ic/inc-proc-ic.c
> > > +++ b/ic/inc-proc-ic.c
> > > @@ -157,7 +157,7 @@ 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,
> > nit: Function return type should be on seperate line
> > >                        struct ovsdb_idl_loop *sb,
> > > @@ -187,11 +187,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 +203,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 +368,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..f4a97fbca 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;
> > >          }
> > >      }
> > >
> > >      /* 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;
> > >      }
> > >      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,
> > nit: incorrect paramater alignment
> > > -        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);
> > nit: incorrect alignment. This applies below also
> > > +          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,32 +3029,36 @@ 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_,
> > > +        ovsdb_idl_txn_increment(ovnisb_txn, &az->header_,
> > nit: incorrect alignment
> > >              &icsbrec_availability_zone_col_nb_ic_cfg, true);
> > >          return;
> > >      }
> > > @@ -3035,22 +3066,22 @@ update_sequence_numbers(struct ic_context *ctx,
> > >      /* 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 +3108,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 +3511,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 +3520,9 @@ main(int argc, char *argv[])
> > >      unixctl_command_register("ic-sb-connection-status", "", 0, 0,
> > >                               ovn_conn_show, ovnisb_idl_loop.idl);
> > >
> > > +    stopwatch_create(OVN_IC_LOOP_STOPWATCH_NAME, SW_MS);
> > nit: OVN_IC_LOOP_STOPWATCH_NAME never used.
> > > +    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..5f1091155 100644
> > > --- a/lib/stopwatch-names.h
> > > +++ b/lib/stopwatch-names.h
> > > @@ -40,4 +40,7 @@
> > >  #define DYNAMIC_ROUTES_RUN_STOPWATCH_NAME "dynamic_routes"
> > >  #define GROUP_ECMP_ROUTE_RUN_STOPWATCH_NAME "group_ecmp_route"
> > >
> > > +#define OVN_IC_LOOP_STOPWATCH_NAME "ovn-ic-loop"
> > > +#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
> > > dev@openvswitch.org
> > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> > >
> >
> > Just a few small nits
> >
> > Acked-by: Mairtin O'Loingsigh <moloings@redhat.com>
> >
> >
> 
> -- 
> 
> 
> 
> 
> _‘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’.*
> 
> 
> 
Hi, Paulo

If I understand your question, you are asking if group these is a good
idea? In this case I agree with you, I like haveing these calls grouped
together.

Mairtin
Paulo Guilherme \(MGC NETP SDN\) Feb. 6, 2026, 7:33 p.m. UTC | #4
Hi Mairtin,

Thank you for your review and feedback. I will submit the new revision.

Best regards
Paulo

Em qui., 5 de fev. de 2026 às 11:07, Mairtin OLoingsigh via dev <
ovs-dev@openvswitch.org> escreveu:

> On Wed, Feb 04, 2026 at 08:17:50PM -0300, Paulo Guilherme (MGC NETP SDN)
> wrote:
> > Hi Mairtin,
> >
> > Thank you for review the patch. I have applied for most of your
> > observations, with the exception of this note. I would like to know what
> > your suggestion would be
> > before submitting for the next review.
> >
> > ble=  /* 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));
> >
> > These are used to extract data from the database tables (OVSDB) that have
> > been "registered" as dependencies of the en-ic node of the processing
> > engine.
> >
> > Since we need to access several OVSDB reference tables throughout the
> > various functions within the en-ic engine, I chose to concentrate them
> all
> > in this
> > initialization structure along with their respective indexes. As future
> > engines are created, they will begin to migrate from the current engine
> to
> > the future ones.
> > Without this current definition, the source code compiles, but the ovn-ic
> > process fails drastically.
> >
> > Thanks in advance,
> > Paulo
> >
> > Em sex., 30 de jan. de 2026 às 12:34, Mairtin O'Loingsigh <
> > moloings@redhat.com> escreveu:
> >
> > > On Tue, Jan 20, 2026 at 08:49:40AM -0300, Paulo Guilherme Silva via dev
> > > 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 <guilherme.paulo@luizalabs.com>
> > > > ---
> > > >  ic/en-ic.c            | 168 ++++++++++-
> > > >  ic/en-ic.h            |   2 +-
> > > >  ic/inc-proc-ic.c      | 145 ++++++++-
> > > >  ic/inc-proc-ic.h      |   8 +-
> > > >  ic/ovn-ic.c           | 680
> +++++++++++++++++++-----------------------
> > > >  ic/ovn-ic.h           |  50 +++-
> > > >  lib/stopwatch-names.h |   3 +
> > > >  7 files changed, 652 insertions(+), 404 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());
> > > > +    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..2f4579464 100644
> > > > --- a/ic/inc-proc-ic.c
> > > > +++ b/ic/inc-proc-ic.c
> > > > @@ -157,7 +157,7 @@ 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,
> > > nit: Function return type should be on seperate line
> > > >                        struct ovsdb_idl_loop *sb,
> > > > @@ -187,11 +187,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 +203,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 +368,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..f4a97fbca 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;
> > > >          }
> > > >      }
> > > >
> > > >      /* 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;
> > > >      }
> > > >      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,
> > > nit: incorrect paramater alignment
> > > > -        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);
> > > nit: incorrect alignment. This applies below also
> > > > +          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,32 +3029,36 @@ 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_,
> > > > +        ovsdb_idl_txn_increment(ovnisb_txn, &az->header_,
> > > nit: incorrect alignment
> > > >              &icsbrec_availability_zone_col_nb_ic_cfg, true);
> > > >          return;
> > > >      }
> > > > @@ -3035,22 +3066,22 @@ update_sequence_numbers(struct ic_context
> *ctx,
> > > >      /* 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 +3108,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 +3511,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 +3520,9 @@ main(int argc, char *argv[])
> > > >      unixctl_command_register("ic-sb-connection-status", "", 0, 0,
> > > >                               ovn_conn_show, ovnisb_idl_loop.idl);
> > > >
> > > > +    stopwatch_create(OVN_IC_LOOP_STOPWATCH_NAME, SW_MS);
> > > nit: OVN_IC_LOOP_STOPWATCH_NAME never used.
> > > > +    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..5f1091155 100644
> > > > --- a/lib/stopwatch-names.h
> > > > +++ b/lib/stopwatch-names.h
> > > > @@ -40,4 +40,7 @@
> > > >  #define DYNAMIC_ROUTES_RUN_STOPWATCH_NAME "dynamic_routes"
> > > >  #define GROUP_ECMP_ROUTE_RUN_STOPWATCH_NAME "group_ecmp_route"
> > > >
> > > > +#define OVN_IC_LOOP_STOPWATCH_NAME "ovn-ic-loop"
> > > > +#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
> > > > dev@openvswitch.org
> > > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> > > >
> > >
> > > Just a few small nits
> > >
> > > Acked-by: Mairtin O'Loingsigh <moloings@redhat.com>
> > >
> > >
> >
> > --
> >
> >
> >
> >
> > _‘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’.*
> >
> >
> >
> Hi, Paulo
>
> If I understand your question, you are asking if group these is a good
> idea? In this case I agree with you, I like haveing these calls grouped
> together.
>
> Mairtin
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
diff mbox series

Patch

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());
+    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..2f4579464 100644
--- a/ic/inc-proc-ic.c
+++ b/ic/inc-proc-ic.c
@@ -157,7 +157,7 @@  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,
@@ -187,11 +187,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 +203,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 +368,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..f4a97fbca 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;
         }
     }
 
     /* 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;
     }
     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,32 +3029,36 @@  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_,
+        ovsdb_idl_txn_increment(ovnisb_txn, &az->header_,
             &icsbrec_availability_zone_col_nb_ic_cfg, true);
         return;
     }
@@ -3035,22 +3066,22 @@  update_sequence_numbers(struct ic_context *ctx,
     /* 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 +3108,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 +3511,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 +3520,9 @@  main(int argc, char *argv[])
     unixctl_command_register("ic-sb-connection-status", "", 0, 0,
                              ovn_conn_show, ovnisb_idl_loop.idl);
 
+    stopwatch_create(OVN_IC_LOOP_STOPWATCH_NAME, SW_MS);
+    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..5f1091155 100644
--- a/lib/stopwatch-names.h
+++ b/lib/stopwatch-names.h
@@ -40,4 +40,7 @@ 
 #define DYNAMIC_ROUTES_RUN_STOPWATCH_NAME "dynamic_routes"
 #define GROUP_ECMP_ROUTE_RUN_STOPWATCH_NAME "group_ecmp_route"
 
+#define OVN_IC_LOOP_STOPWATCH_NAME "ovn-ic-loop"
+#define IC_OVN_DB_RUN_STOPWATCH_NAME "ovn_db_run"
+
 #endif