get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.0/patches/2186651/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2186651,
    "url": "http://patchwork.ozlabs.org/api/1.0/patches/2186651/?format=api",
    "project": {
        "id": 68,
        "url": "http://patchwork.ozlabs.org/api/1.0/projects/68/?format=api",
        "name": "Open Virtual Network development",
        "link_name": "ovn",
        "list_id": "ovs-dev.openvswitch.org",
        "list_email": "ovs-dev@openvswitch.org",
        "web_url": "http://openvswitch.org/",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20260120114948.2289909-2-guilherme.paulo@luizalabs.com>",
    "date": "2026-01-20T11:49:40",
    "name": "[ovs-dev,v0,1/9] ovn-ic: Introduce structs ic_data and ic_input.",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "06d5184d491be984b2846b4ca9e8e26f033f23ee",
    "submitter": {
        "id": 90256,
        "url": "http://patchwork.ozlabs.org/api/1.0/people/90256/?format=api",
        "name": "Paulo Guilherme Silva",
        "email": "guilherme.paulo@luizalabs.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/ovn/patch/20260120114948.2289909-2-guilherme.paulo@luizalabs.com/mbox/",
    "series": [
        {
            "id": 489037,
            "url": "http://patchwork.ozlabs.org/api/1.0/series/489037/?format=api",
            "date": "2026-01-20T11:49:40",
            "name": "Create multiple engines nodes for ovn-ic.",
            "version": 0,
            "mbox": "http://patchwork.ozlabs.org/series/489037/mbox/"
        }
    ],
    "check": "success",
    "checks": "http://patchwork.ozlabs.org/api/patches/2186651/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<ovs-dev-bounces@openvswitch.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "dev@openvswitch.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@legolas.ozlabs.org",
            "ovs-dev@lists.linuxfoundation.org"
        ],
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=luizalabs.com header.i=@luizalabs.com\n header.a=rsa-sha256 header.s=google header.b=YcZkYC3m;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=2605:bc80:3010::137; helo=smtp4.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)",
            "smtp4.osuosl.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key,\n unprotected) header.d=luizalabs.com header.i=@luizalabs.com\n header.a=rsa-sha256 header.s=google header.b=YcZkYC3m",
            "smtp1.osuosl.org; dmarc=pass (p=quarantine dis=none)\n header.from=luizalabs.com",
            "smtp1.osuosl.org; dkim=pass (1024-bit key,\n unprotected) header.d=luizalabs.com header.i=@luizalabs.com\n header.a=rsa-sha256 header.s=google header.b=YcZkYC3m"
        ],
        "Received": [
            "from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4dwQcf4XTNz1xsW\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 20 Jan 2026 22:50:25 +1100 (AEDT)",
            "from localhost (localhost [127.0.0.1])\n\tby smtp4.osuosl.org (Postfix) with ESMTP id 9D3774EF81;\n\tTue, 20 Jan 2026 11:50:22 +0000 (UTC)",
            "from smtp4.osuosl.org ([127.0.0.1])\n by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id ANcgXxrH74VF; Tue, 20 Jan 2026 11:50:20 +0000 (UTC)",
            "from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])\n\tby smtp4.osuosl.org (Postfix) with ESMTPS id 28DE24EF50;\n\tTue, 20 Jan 2026 11:50:20 +0000 (UTC)",
            "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id 110D4C02A6;\n\tTue, 20 Jan 2026 11:50:20 +0000 (UTC)",
            "from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 40DFFC02A5\n for <dev@openvswitch.org>; Tue, 20 Jan 2026 11:50:18 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n by smtp1.osuosl.org (Postfix) with ESMTP id 30652848CF\n for <dev@openvswitch.org>; Tue, 20 Jan 2026 11:50:18 +0000 (UTC)",
            "from smtp1.osuosl.org ([127.0.0.1])\n by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id PGB4V2riAyHI for <dev@openvswitch.org>;\n Tue, 20 Jan 2026 11:50:16 +0000 (UTC)",
            "from mail-dy1-x132d.google.com (mail-dy1-x132d.google.com\n [IPv6:2607:f8b0:4864:20::132d])\n by smtp1.osuosl.org (Postfix) with ESMTPS id 369B9848C2\n for <dev@openvswitch.org>; Tue, 20 Jan 2026 11:50:15 +0000 (UTC)",
            "by mail-dy1-x132d.google.com with SMTP id\n 5a478bee46e88-2b6f85470b6so1528217eec.1\n for <dev@openvswitch.org>; Tue, 20 Jan 2026 03:50:15 -0800 (PST)",
            "from WNLEC-CW22RF4.. ([177.75.155.81])\n by smtp.gmail.com with ESMTPSA id\n 5a478bee46e88-2b6b367cbc9sm18630559eec.32.2026.01.20.03.50.12\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 20 Jan 2026 03:50:13 -0800 (PST)"
        ],
        "X-Virus-Scanned": [
            "amavis at osuosl.org",
            "amavis at osuosl.org"
        ],
        "X-Comment": "SPF check N/A for local connections - client-ip=140.211.9.56;\n helo=lists.linuxfoundation.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN> ",
        "DKIM-Filter": [
            "OpenDKIM Filter v2.11.0 smtp4.osuosl.org 28DE24EF50",
            "OpenDKIM Filter v2.11.0 smtp1.osuosl.org 369B9848C2"
        ],
        "Received-SPF": "Pass (mailfrom) identity=mailfrom;\n client-ip=2607:f8b0:4864:20::132d; helo=mail-dy1-x132d.google.com;\n envelope-from=guilherme.paulo@luizalabs.com; receiver=<UNKNOWN>",
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 smtp1.osuosl.org 369B9848C2",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=luizalabs.com; s=google; t=1768909815; x=1769514615; darn=openvswitch.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=vScRdp3ajD2kND1vB64s8v91fDI+7+OoTX9ZYRE7dvk=;\n b=YcZkYC3mDkotHhFT57rMdfoERAFpL3HwtMUkyWbPqimnLLJraXogtP8BgnLy2+vMki\n qMHn3w3lvM+BacADiwuey+icgR4uBcZM9ym6eVR8n+CQw6/c8PtaB1W7GUlWFY5RSAsh\n yVcyK2lodyfDD/I1fbG9NcDfsDRXTG2MRjFdk=",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1768909815; x=1769514615;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=vScRdp3ajD2kND1vB64s8v91fDI+7+OoTX9ZYRE7dvk=;\n b=OVGrK6n52YG176jFwsuxPTznwmzFPxxa00NaNGUCWAubH/qYfH3MWc3zkylEUn/H9x\n 6Vff6O3EH8A27/GxWZ5ExtkO2WQfABPJsheFInixGYRrJ5Tn43O9jyLk01PlcNSd4hmR\n 8wQvyfIZrCBo6iRUY44s1j4lLAQIyZKV+4aqEJkMVc8NUryPuEPEl+SKR0CrMF6qOG4P\n rTrX34Eq7daO5a4A+WrGh382cEJo4TEHFJDfCnrNJOdqrgElsn/N8xNEtnezrb3IAc3l\n Gsqca4DJGxCb7et8Xy0k7sssjtaX/IeBjYtUmyQKqm/tN37AfZQByaSQpTjTwM1THMkl\n CgSA==",
        "X-Gm-Message-State": "AOJu0Yy3nSVmwcU2iO88ebBMiTxnE9bz+AoIEjUF0NnKCkYBC2Ma/fMD\n hhKcA9fvV8IbmJUWt/OlVvQCQ4qVsyMGFl1atGCme5u5KtSXldRhJYv1qG9/rjQZ3058ycMmvY2\n HHq2tPJtuKeWJnb9EGVix9VEDd56nO6qRsra7gcOtns3J/dTPLXxnMb3WwYV3",
        "X-Gm-Gg": "AZuq6aIsgJz/0cK6U1azV1tmyADh8RkQufGaJxXUC8/J4FdRZajrk/v1mvk0UhCdZQ6\n P+kGbkJnCCG1C+2pxJeUXQF5mh8DGAWjz8RZgdXwEAWGb88uQkOh4jQio7yCfMep4kd5Nvxt7Kw\n j8CAASgiloro0vIG0Sjo3J11ZBG/XNJCJSYqpd7JDvkqioH6GVMC0gXzhvNaB3gqjxG9whGbxfE\n Kxz37HVDsGj0xxGRw3trSm2KjusRa6kU6NjfISpt4lLa9ButOsU8nXXwgDwUzMNtiRv//6mSpo0\n PLLj1XzaZkyXRer2bb3Cob8xPiYjdahlMh3advFfWYY4BaTdErDcc075brJgK0/FU/XpCQQjpLU\n SdYG1qyISQ5uHu7iiI2yKHqgfxaPY/orLlwTiEVeorzgHreRgDQrn8KNX8IskQysR+vJr2aPTpO\n wmRJodBwdohnGK1kw62kUPNdZi8ec=",
        "X-Received": "by 2002:a05:7300:ad06:b0:2ae:59dd:cfd1 with SMTP id\n 5a478bee46e88-2b6fdc7bfeemr953407eec.22.1768909814033;\n Tue, 20 Jan 2026 03:50:14 -0800 (PST)",
        "To": "dev@openvswitch.org",
        "Date": "Tue, 20 Jan 2026 08:49:40 -0300",
        "Message-Id": "<20260120114948.2289909-2-guilherme.paulo@luizalabs.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20260120114948.2289909-1-guilherme.paulo@luizalabs.com>",
        "References": "<20260120114948.2289909-1-guilherme.paulo@luizalabs.com>",
        "MIME-Version": "1.0",
        "Subject": "[ovs-dev] [PATCH ovn v0 1/9] ovn-ic: Introduce structs ic_data and\n ic_input.",
        "X-BeenThere": "ovs-dev@openvswitch.org",
        "X-Mailman-Version": "2.1.30",
        "Precedence": "list",
        "List-Id": "<ovs-dev.openvswitch.org>",
        "List-Unsubscribe": "<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>",
        "List-Archive": "<http://mail.openvswitch.org/pipermail/ovs-dev/>",
        "List-Post": "<mailto:ovs-dev@openvswitch.org>",
        "List-Help": "<mailto:ovs-dev-request@openvswitch.org?subject=help>",
        "List-Subscribe": "<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=subscribe>",
        "From": "Paulo Guilherme Silva via dev <ovs-dev@openvswitch.org>",
        "Reply-To": "Paulo Guilherme Silva <guilherme.paulo@luizalabs.com>",
        "Content-Type": "text/plain; charset=\"iso-8859-1\"",
        "Content-Transfer-Encoding": "quoted-printable",
        "Errors-To": "ovs-dev-bounces@openvswitch.org",
        "Sender": "\"dev\" <ovs-dev-bounces@openvswitch.org>"
    },
    "content": "'struct ic_data' is used to hold the global state data for the\nincremental processing node 'en_ic' and 'struct ic_input' this will\nhold references to database tables and indexes. In order to achieve this,\nwe refactor in the following way:\n* Move index and tables into the main 'ic' engine\n* Adjust inputs of function 'ovn_db_run()' inside the ic engine which\n  in turn ends up calling upon the functions that manage the main groups\n  of actions spreading the new structures:\n    gateway_run();\n    enumerate_datapaths();\n    ts_run();\n    tr_run();\n    port_binding_run();\n    route_run();\n    sync_service_monitor();\n* Refactor ovn-ic.c to use 'struct ic_data' and 'struct ic_input'\n  where applicable.\n\nSigned-off-by: Paulo Guilherme Silva <guilherme.paulo@luizalabs.com>\n---\n ic/en-ic.c            | 168 ++++++++++-\n ic/en-ic.h            |   2 +-\n ic/inc-proc-ic.c      | 145 ++++++++-\n ic/inc-proc-ic.h      |   8 +-\n ic/ovn-ic.c           | 680 +++++++++++++++++++-----------------------\n ic/ovn-ic.h           |  50 +++-\n lib/stopwatch-names.h |   3 +\n 7 files changed, 652 insertions(+), 404 deletions(-)",
    "diff": "diff --git a/ic/en-ic.c b/ic/en-ic.c\nindex 2db9d3b84..ce7d5de76 100644\n--- a/ic/en-ic.c\n+++ b/ic/en-ic.c\n@@ -18,33 +18,185 @@\n #include <stdlib.h>\n #include <stdio.h>\n \n+/* OVS includes. */\n+#include \"openvswitch/vlog.h\"\n+\n+/* OVN includes. */\n+#include \"ovn-ic.h\"\n #include \"en-ic.h\"\n #include \"lib/inc-proc-eng.h\"\n+#include \"lib/ovn-util.h\"\n #include \"lib/stopwatch-names.h\"\n-#include \"ovn-ic.h\"\n-#include \"openvswitch/vlog.h\"\n+#include \"coverage.h\"\n+#include \"stopwatch.h\"\n+#include \"stopwatch-names.h\"\n \n VLOG_DEFINE_THIS_MODULE(en_ic);\n+COVERAGE_DEFINE(ic_run);\n+\n+void ic_destroy(struct ic_data *data);\n+void ic_init(struct ic_data *data);\n+\n+static void\n+ic_get_input_data(struct engine_node *node,\n+                  struct ic_input *input_data)\n+{\n+    /* Table references */\n+    input_data->nbrec_nb_global_table =\n+        EN_OVSDB_GET(engine_get_input(\"NB_nb_global\", node));\n+    input_data->nbrec_logical_switch_table =\n+        EN_OVSDB_GET(engine_get_input(\"NB_logical_switch\", node));\n+    input_data->nbrec_logical_router_table =\n+        EN_OVSDB_GET(engine_get_input(\"NB_logical_router\", node));\n+    input_data->sbrec_sb_global_table =\n+        EN_OVSDB_GET(engine_get_input(\"SB_sb_global\", node));\n+    input_data->sbrec_chassis_table =\n+        EN_OVSDB_GET(engine_get_input(\"SB_chassis\", node));\n+    input_data->icnbrec_ic_nb_global_table =\n+        EN_OVSDB_GET(engine_get_input(\"ICNB_ic_nb_global\", node));\n+    input_data->icnbrec_transit_switch_table =\n+        EN_OVSDB_GET(engine_get_input(\"ICNB_transit_switch\", node));\n+    input_data->icnbrec_transit_router_table =\n+        EN_OVSDB_GET(engine_get_input(\"ICNB_transit_router\", node));\n+    input_data->icsbrec_ic_sb_global_table =\n+        EN_OVSDB_GET(engine_get_input(\"ICSB_ic_sb_global\", node));\n+    input_data->icsbrec_availability_zone_table =\n+        EN_OVSDB_GET(engine_get_input(\"ICSB_availability_zone\", node));\n+    input_data->icsbrec_encap_table =\n+        EN_OVSDB_GET(engine_get_input(\"ICSB_encap\", node));\n+    input_data->icsbrec_gateway_table =\n+        EN_OVSDB_GET(engine_get_input(\"ICSB_gateway\", node));\n+    input_data->icsbrec_datapath_binding_table =\n+        EN_OVSDB_GET(engine_get_input(\"ICSB_datapath_binding\", node));\n+\n+    /* Indexes */\n+    input_data->nbrec_ls_by_name =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"NB_logical_switch\", node),\n+            \"nbrec_ls_by_name\");\n+    input_data->nbrec_lr_by_name =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"NB_logical_router\", node),\n+            \"nbrec_lr_by_name\");\n+    input_data->nbrec_lrp_by_name =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"NB_logical_router\", node),\n+            \"nbrec_lrp_by_name\");\n+    input_data->nbrec_port_by_name =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"NB_logical_switch\", node),\n+            \"nbrec_port_by_name\");\n+    input_data->sbrec_chassis_by_name =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"SB_chassis\", node),\n+            \"sbrec_chassis_by_name\");\n+    input_data->sbrec_port_binding_by_name =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"SB_port_binding\", node),\n+            \"sbrec_port_binding_by_name\");\n+    input_data->sbrec_service_monitor_by_remote_type =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"SB_service_monitor\", node),\n+            \"sbrec_service_monitor_by_remote_type\");\n+    input_data->sbrec_service_monitor_by_ic_learned =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"SB_service_monitor\", node),\n+            \"sbrec_service_monitor_by_ic_learned\");\n+    input_data->sbrec_service_monitor_by_remote_type_logical_port =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"SB_service_monitor\", node),\n+            \"sbrec_service_monitor_by_remote_type_logical_port\");\n+    input_data->icnbrec_transit_switch_by_name =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"ICNB_transit_switch\", node),\n+            \"icnbrec_transit_switch_by_name\");\n+    input_data->icsbrec_port_binding_by_az =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"ICSB_port_binding\", node),\n+            \"icsbrec_port_binding_by_az\");\n+    input_data->icsbrec_port_binding_by_ts =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"ICSB_port_binding\", node),\n+            \"icsbrec_port_binding_by_ts\");\n+    input_data->icsbrec_port_binding_by_ts_az =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"ICSB_port_binding\", node),\n+            \"icsbrec_port_binding_by_ts_az\");\n+    input_data->icsbrec_route_by_az =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"ICSB_route\", node),\n+            \"icsbrec_route_by_az\");\n+    input_data->icsbrec_route_by_ts =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"ICSB_route\", node),\n+            \"icsbrec_route_by_ts\");\n+    input_data->icsbrec_route_by_ts_az =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"ICSB_route\", node),\n+            \"icsbrec_route_by_ts_az\");\n+    input_data->icsbrec_service_monitor_by_source_az =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"ICSB_service_monitor\", node),\n+            \"icsbrec_service_monitor_by_source_az\");\n+    input_data->icsbrec_service_monitor_by_target_az =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"ICSB_service_monitor\", node),\n+            \"icsbrec_service_monitor_by_target_az\");\n+    input_data->icsbrec_service_monitor_by_target_az_logical_port =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"ICSB_service_monitor\", node),\n+            \"icsbrec_service_monitor_by_target_az_logical_port\");\n+}\n \n enum engine_node_state\n-en_ic_run(struct engine_node *node OVS_UNUSED, void *data OVS_UNUSED)\n+en_ic_run(struct engine_node *node, void *data)\n {\n     const struct engine_context *eng_ctx = engine_get_context();\n-    struct ic_context *ctx = eng_ctx->client_ctx;\n \n-    ovn_db_run(ctx);\n+    struct ic_input input_data;\n+\n+    ic_destroy(data);\n+    ic_init(data);\n \n+    ic_get_input_data(node, &input_data);\n+    input_data.runned_az = eng_ctx->client_ctx;\n+\n+    COVERAGE_INC(ic_run);\n+    stopwatch_start(IC_OVN_DB_RUN_STOPWATCH_NAME, time_msec());\n+    ovn_db_run(&input_data, data, (struct engine_context *) eng_ctx);\n+    stopwatch_stop(IC_OVN_DB_RUN_STOPWATCH_NAME, time_msec());\n     return EN_UPDATED;\n }\n \n void *\n en_ic_init(struct engine_node *node OVS_UNUSED,\n-            struct engine_arg *arg OVS_UNUSED)\n+           struct engine_arg *arg OVS_UNUSED)\n+{\n+    struct ic_data *data = xzalloc(sizeof *data);\n+\n+    ic_init(data);\n+\n+    return data;\n+}\n+\n+void\n+en_ic_cleanup(void *data)\n+{\n+    ic_destroy(data);\n+}\n+\n+void\n+ic_destroy(struct ic_data *data)\n {\n-    return NULL;\n+    ovn_destroy_tnlids(&data->dp_tnlids);\n+    shash_destroy(&data->isb_ts_dps);\n+    shash_destroy(&data->isb_tr_dps);\n }\n \n void\n-en_ic_cleanup(void *data OVS_UNUSED)\n+ic_init(struct ic_data *data)\n {\n+    hmap_init(&data->dp_tnlids);\n+    shash_init(&data->isb_ts_dps);\n+    shash_init(&data->isb_tr_dps);\n }\ndiff --git a/ic/en-ic.h b/ic/en-ic.h\nindex a4b75bb0e..ab1fbaf42 100644\n--- a/ic/en-ic.h\n+++ b/ic/en-ic.h\n@@ -12,7 +12,7 @@\n enum engine_node_state en_ic_run(struct engine_node *node OVS_UNUSED,\n                                  void *data OVS_UNUSED);\n void *en_ic_init(struct engine_node *node OVS_UNUSED,\n-                 struct engine_arg *arg);\n+                 struct engine_arg *arg OVS_UNUSED);\n void en_ic_cleanup(void *data);\n \n #endif /* EN_IC_H */\ndiff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c\nindex ba9fdeb9e..2f4579464 100644\n--- a/ic/inc-proc-ic.c\n+++ b/ic/inc-proc-ic.c\n@@ -157,7 +157,7 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_ic);\n \n /* Define engine nodes for other nodes. They should be defined as static to\n  * avoid sparse errors. */\n-static ENGINE_NODE(ic);\n+static ENGINE_NODE(ic, SB_WRITE);\n \n void inc_proc_ic_init(struct ovsdb_idl_loop *nb,\n                       struct ovsdb_idl_loop *sb,\n@@ -187,11 +187,11 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,\n     engine_add_input(&en_ic, &en_icnb_transit_router, NULL);\n     engine_add_input(&en_ic, &en_icnb_transit_router_port, NULL);\n \n+    engine_add_input(&en_ic, &en_icsb_ic_sb_global, NULL);\n+    engine_add_input(&en_ic, &en_icsb_availability_zone, NULL);\n     engine_add_input(&en_ic, &en_icsb_encap, NULL);\n     engine_add_input(&en_ic, &en_icsb_service_monitor, NULL);\n-    engine_add_input(&en_ic, &en_icsb_ic_sb_global, NULL);\n     engine_add_input(&en_ic, &en_icsb_port_binding, NULL);\n-    engine_add_input(&en_ic, &en_icsb_availability_zone, NULL);\n     engine_add_input(&en_ic, &en_icsb_gateway, NULL);\n     engine_add_input(&en_ic, &en_icsb_route, NULL);\n     engine_add_input(&en_ic, &en_icsb_datapath_binding, NULL);\n@@ -203,22 +203,149 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,\n         .icsb_idl = icsb->idl,\n     };\n \n+    /* create IDL indexes*/\n+    struct ovsdb_idl_index *nbrec_ls_by_name\n+        = ovsdb_idl_index_create1(nb->idl, &nbrec_logical_switch_col_name);\n+    struct ovsdb_idl_index *nbrec_lr_by_name\n+        = ovsdb_idl_index_create1(nb->idl, &nbrec_logical_router_col_name);\n+    struct ovsdb_idl_index *nbrec_lrp_by_name\n+        = ovsdb_idl_index_create1(nb->idl,\n+                                  &nbrec_logical_router_port_col_name);\n+    struct ovsdb_idl_index *nbrec_port_by_name\n+        = ovsdb_idl_index_create1(nb->idl,\n+                                  &nbrec_logical_switch_port_col_name);\n+    struct ovsdb_idl_index *sbrec_chassis_by_name\n+        = ovsdb_idl_index_create1(sb->idl, &sbrec_chassis_col_name);\n+    struct ovsdb_idl_index *sbrec_port_binding_by_name\n+        = ovsdb_idl_index_create1(sb->idl,\n+                                  &sbrec_port_binding_col_logical_port);\n+    struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type\n+        = ovsdb_idl_index_create1(sb->idl,\n+                                  &sbrec_service_monitor_col_remote);\n+    struct ovsdb_idl_index *sbrec_service_monitor_by_ic_learned\n+        = ovsdb_idl_index_create1(sb->idl,\n+                                  &sbrec_service_monitor_col_ic_learned);\n+    struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type_logical_port\n+        = ovsdb_idl_index_create2(sb->idl,\n+                                  &sbrec_service_monitor_col_remote,\n+                                  &sbrec_service_monitor_col_logical_port);\n+    struct ovsdb_idl_index *icnbrec_transit_switch_by_name\n+        = ovsdb_idl_index_create1(icnb->idl,\n+                                  &icnbrec_transit_switch_col_name);\n+    struct ovsdb_idl_index *icsbrec_port_binding_by_az\n+        = ovsdb_idl_index_create1(icsb->idl,\n+                                  &icsbrec_port_binding_col_availability_zone);\n+    struct ovsdb_idl_index *icsbrec_port_binding_by_ts\n+        = ovsdb_idl_index_create1(icsb->idl,\n+                                  &icsbrec_port_binding_col_transit_switch);\n+    struct ovsdb_idl_index *icsbrec_port_binding_by_ts_az\n+        = ovsdb_idl_index_create2(icsb->idl,\n+                                  &icsbrec_port_binding_col_transit_switch,\n+                                  &icsbrec_port_binding_col_availability_zone);\n+    struct ovsdb_idl_index *icsbrec_route_by_az\n+        = ovsdb_idl_index_create1(icsb->idl,\n+                                  &icsbrec_route_col_availability_zone);\n+    struct ovsdb_idl_index *icsbrec_route_by_ts\n+        = ovsdb_idl_index_create1(icsb->idl,\n+                                  &icsbrec_route_col_transit_switch);\n+    struct ovsdb_idl_index *icsbrec_route_by_ts_az\n+        = ovsdb_idl_index_create2(icsb->idl,\n+                                  &icsbrec_route_col_transit_switch,\n+                                  &icsbrec_route_col_availability_zone);\n+    struct ovsdb_idl_index *icsbrec_service_monitor_by_source_az\n+        = ovsdb_idl_index_create1(icsb->idl,\n+            &icsbrec_service_monitor_col_source_availability_zone);\n+    struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az\n+        = ovsdb_idl_index_create1(icsb->idl,\n+            &icsbrec_service_monitor_col_target_availability_zone);\n+    struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az_logical_port\n+        = ovsdb_idl_index_create2(icsb->idl,\n+            &icsbrec_service_monitor_col_target_availability_zone,\n+            &icsbrec_service_monitor_col_logical_port);\n+\n     engine_init(&en_ic, &engine_arg);\n+\n+    /* indexes */\n+    engine_ovsdb_node_add_index(&en_nb_logical_switch,\n+                                \"nbrec_ls_by_name\",\n+                                nbrec_ls_by_name);\n+    engine_ovsdb_node_add_index(&en_nb_logical_router,\n+                                \"nbrec_lr_by_name\",\n+                                nbrec_lr_by_name);\n+    engine_ovsdb_node_add_index(&en_nb_logical_router,\n+                                \"nbrec_lrp_by_name\",\n+                                nbrec_lrp_by_name);\n+    engine_ovsdb_node_add_index(&en_nb_logical_switch,\n+                                \"nbrec_port_by_name\",\n+                                nbrec_port_by_name);\n+    engine_ovsdb_node_add_index(&en_sb_chassis,\n+                                \"sbrec_chassis_by_name\",\n+                                sbrec_chassis_by_name);\n+    engine_ovsdb_node_add_index(&en_sb_port_binding,\n+                                \"sbrec_port_binding_by_name\",\n+                                sbrec_port_binding_by_name);\n+    engine_ovsdb_node_add_index(&en_sb_service_monitor,\n+                                \"sbrec_service_monitor_by_remote_type\",\n+                                sbrec_service_monitor_by_remote_type);\n+    engine_ovsdb_node_add_index(&en_sb_service_monitor,\n+                                \"sbrec_service_monitor_by_ic_learned\",\n+                                sbrec_service_monitor_by_ic_learned);\n+    engine_ovsdb_node_add_index(&en_sb_service_monitor,\n+        \"sbrec_service_monitor_by_remote_type_logical_port\",\n+        sbrec_service_monitor_by_remote_type_logical_port);\n+    engine_ovsdb_node_add_index(&en_icnb_transit_switch,\n+                                \"icnbrec_transit_switch_by_name\",\n+                                icnbrec_transit_switch_by_name);\n+    engine_ovsdb_node_add_index(&en_icsb_port_binding,\n+                                \"icsbrec_port_binding_by_az\",\n+                                icsbrec_port_binding_by_az);\n+    engine_ovsdb_node_add_index(&en_icsb_port_binding,\n+                                \"icsbrec_port_binding_by_ts\",\n+                                icsbrec_port_binding_by_ts);\n+    engine_ovsdb_node_add_index(&en_icsb_port_binding,\n+                                \"icsbrec_port_binding_by_ts_az\",\n+                                icsbrec_port_binding_by_ts_az);\n+    engine_ovsdb_node_add_index(&en_icsb_route,\n+                                \"icsbrec_route_by_az\",\n+                                icsbrec_route_by_az);\n+    engine_ovsdb_node_add_index(&en_icsb_route,\n+                                \"icsbrec_route_by_ts\",\n+                                icsbrec_route_by_ts);\n+    engine_ovsdb_node_add_index(&en_icsb_route,\n+                                \"icsbrec_route_by_ts_az\",\n+                                icsbrec_route_by_ts_az);\n+    engine_ovsdb_node_add_index(&en_icsb_service_monitor,\n+                                \"icsbrec_service_monitor_by_source_az\",\n+                                icsbrec_service_monitor_by_source_az);\n+    engine_ovsdb_node_add_index(&en_icsb_service_monitor,\n+                                \"icsbrec_service_monitor_by_target_az\",\n+                                icsbrec_service_monitor_by_target_az);\n+    engine_ovsdb_node_add_index(&en_icsb_service_monitor,\n+        \"icsbrec_service_monitor_by_target_az_logical_port\",\n+        icsbrec_service_monitor_by_target_az_logical_port);\n }\n \n /* Returns true if the incremental processing ended up updating nodes. */\n bool\n-inc_proc_ic_run(struct ic_context *ctx,\n-                struct ic_engine_context *ic_eng_ctx)\n+inc_proc_ic_run(struct ovsdb_idl_txn *ovnnb_txn,\n+                struct ovsdb_idl_txn *ovnsb_txn,\n+                struct ovsdb_idl_txn *ovninb_txn,\n+                struct ovsdb_idl_txn *ovnisb_txn,\n+                struct ic_engine_context *ctx,\n+                const struct icsbrec_availability_zone *runned_az)\n {\n-    ovs_assert(ctx->ovnnb_txn && ctx->ovnsb_txn &&\n-               ctx->ovninb_txn && ctx->ovnisb_txn);\n+    ovs_assert(ovnnb_txn && ovnsb_txn &&\n+               ovninb_txn && ovnisb_txn);\n \n     int64_t start = time_msec();\n     engine_init_run();\n \n     struct engine_context eng_ctx = {\n-        .client_ctx = ctx,\n+        .client_ctx = (void *) runned_az,\n+        .ovnnb_idl_txn = ovnnb_txn,\n+        .ovnsb_idl_txn = ovnsb_txn,\n+        .ovninb_idl_txn = ovninb_txn,\n+        .ovnisb_idl_txn = ovnisb_txn,\n     };\n \n     engine_set_context(&eng_ctx);\n@@ -241,7 +368,7 @@ inc_proc_ic_run(struct ic_context *ctx,\n     int64_t now = time_msec();\n     /* Postpone the next run by length of current run with maximum capped\n      * by \"northd-backoff-interval-ms\" interval. */\n-    ic_eng_ctx->next_run_ms = now + MIN(now - start, ic_eng_ctx->backoff_ms);\n+    ctx->next_run_ms = now + MIN(now - start, ctx->backoff_ms);\n \n     return engine_has_updated();\n }\ndiff --git a/ic/inc-proc-ic.h b/ic/inc-proc-ic.h\nindex 9af147fb3..c50c1b02e 100644\n--- a/ic/inc-proc-ic.h\n+++ b/ic/inc-proc-ic.h\n@@ -21,8 +21,12 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,\n                       struct ovsdb_idl_loop *icnb,\n                       struct ovsdb_idl_loop *icsb);\n \n-bool inc_proc_ic_run(struct ic_context *ctx,\n-                     struct ic_engine_context *ic_eng_ctx);\n+bool inc_proc_ic_run(struct ovsdb_idl_txn *ovnnb_txn,\n+                     struct ovsdb_idl_txn *ovnsb_txn,\n+                     struct ovsdb_idl_txn *ovninb_txn,\n+                     struct ovsdb_idl_txn *ovnisb_txn,\n+                     struct ic_engine_context *ctx,\n+                     const struct icsbrec_availability_zone *runned_az);\n \n void inc_proc_ic_cleanup(void);\n bool inc_proc_ic_can_run(struct ic_engine_context *ctx);\ndiff --git a/ic/ovn-ic.c b/ic/ovn-ic.c\nindex 41596d73a..f4a97fbca 100644\n--- a/ic/ovn-ic.c\n+++ b/ic/ovn-ic.c\n@@ -48,6 +48,8 @@\n #include \"vec.h\"\n #include \"inc-proc-ic.h\"\n #include \"ovn-ic.h\"\n+#include \"stopwatch-names.h\"\n+#include \"stopwatch.h\"\n \n VLOG_DEFINE_THIS_MODULE(ovn_ic);\n \n@@ -99,11 +101,13 @@ Options:\\n\\\n     stream_usage(\"database\", true, true, false);\n }\n \f\n-static const struct icsbrec_availability_zone *\n-az_run(struct ic_context *ctx)\n+const struct icsbrec_availability_zone *\n+az_run(struct ovsdb_idl *ovnnb_idl,\n+       struct ovsdb_idl *ovnisb_idl,\n+       struct ovsdb_idl_txn *ovnisb_idl_txn)\n {\n     const struct nbrec_nb_global *nb_global =\n-        nbrec_nb_global_first(ctx->ovnnb_idl);\n+        nbrec_nb_global_first(ovnnb_idl);\n \n     if (!nb_global) {\n         VLOG_INFO(\"NB Global not exist.\");\n@@ -115,8 +119,8 @@ az_run(struct ic_context *ctx)\n      * \"ovn-ic-sbctl destroy avail <az>\". */\n     static char *az_name;\n     const struct icsbrec_availability_zone *az;\n-    if (ctx->ovnisb_txn && az_name && strcmp(az_name, nb_global->name)) {\n-        ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ctx->ovnisb_idl) {\n+    if (ovnisb_idl_txn && az_name && strcmp(az_name, nb_global->name)) {\n+        ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ovnisb_idl) {\n             /* AZ name update locally need to update az in ISB. */\n             if (nb_global->name[0] && !strcmp(az->name, az_name)) {\n                 icsbrec_availability_zone_set_name(az, nb_global->name);\n@@ -138,24 +142,22 @@ az_run(struct ic_context *ctx)\n         az_name = xstrdup(nb_global->name);\n     }\n \n-    if (ctx->ovnisb_txn) {\n-        ovsdb_idl_txn_add_comment(ctx->ovnisb_txn, \"AZ %s\", az_name);\n+    if (ovnisb_idl_txn) {\n+        ovsdb_idl_txn_add_comment(ovnisb_idl_txn, \"AZ %s\", az_name);\n     }\n \n-    ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ctx->ovnisb_idl) {\n+    ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ovnisb_idl) {\n         if (!strcmp(az->name, az_name)) {\n-            ctx->runned_az = az;\n-            return az;\n+            return (struct icsbrec_availability_zone *) az;\n         }\n     }\n \n     /* Create AZ in ISB */\n-    if (ctx->ovnisb_txn) {\n+    if (ovnisb_idl_txn) {\n         VLOG_INFO(\"Register AZ %s to interconnection DB.\", az_name);\n-        az = icsbrec_availability_zone_insert(ctx->ovnisb_txn);\n+        az = icsbrec_availability_zone_insert(ovnisb_idl_txn);\n         icsbrec_availability_zone_set_name(az, az_name);\n-        ctx->runned_az = az;\n-        return az;\n+        return (struct icsbrec_availability_zone *) az;\n     }\n     return NULL;\n }\n@@ -191,11 +193,14 @@ ic_pb_get_type(const struct icsbrec_port_binding *isb_pb)\n }\n \n static void\n-enumerate_datapaths(struct ic_context *ctx, struct hmap *dp_tnlids,\n-                    struct shash *isb_ts_dps, struct shash *isb_tr_dps)\n+enumerate_datapaths(struct ic_input *ic,\n+                    struct hmap *dp_tnlids,\n+                    struct shash *isb_ts_dps,\n+                    struct shash *isb_tr_dps)\n {\n     const struct icsbrec_datapath_binding *isb_dp;\n-    ICSBREC_DATAPATH_BINDING_FOR_EACH (isb_dp, ctx->ovnisb_idl) {\n+    ICSBREC_DATAPATH_BINDING_TABLE_FOR_EACH (isb_dp,\n+        ic->icsbrec_datapath_binding_table) {\n         ovn_add_tnlid(dp_tnlids, isb_dp->tunnel_key);\n \n         enum ic_datapath_type dp_type = ic_dp_get_type(isb_dp);\n@@ -210,18 +215,20 @@ enumerate_datapaths(struct ic_context *ctx, struct hmap *dp_tnlids,\n }\n \n static void\n-ts_run(struct ic_context *ctx, struct hmap *dp_tnlids,\n+ts_run(struct engine_context *ctx,\n+       struct ic_input *ic,\n+       struct hmap *dp_tnlids,\n        struct shash *isb_ts_dps)\n {\n     const struct icnbrec_transit_switch *ts;\n     bool dp_key_refresh = false;\n     bool vxlan_mode = false;\n     const struct icnbrec_ic_nb_global *ic_nb =\n-        icnbrec_ic_nb_global_first(ctx->ovninb_idl);\n+        icnbrec_ic_nb_global_table_first(ic->icnbrec_ic_nb_global_table);\n \n     if (ic_nb && smap_get_bool(&ic_nb->options, \"vxlan_mode\", false)) {\n         const struct icsbrec_encap *encap;\n-        ICSBREC_ENCAP_FOR_EACH (encap, ctx->ovnisb_idl) {\n+        ICSBREC_ENCAP_TABLE_FOR_EACH (encap, ic->icsbrec_encap_table) {\n             if (!strcmp(encap->type, \"vxlan\")) {\n                 vxlan_mode = true;\n                 break;\n@@ -230,12 +237,13 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids,\n     }\n \n     /* Sync INB TS to AZ NB */\n-    if (ctx->ovnnb_txn) {\n+    if (ctx->ovnnb_idl_txn) {\n         struct shash nb_tses = SHASH_INITIALIZER(&nb_tses);\n         const struct nbrec_logical_switch *ls;\n \n         /* Get current NB Logical_Switch with other_config:interconn-ts */\n-        NBREC_LOGICAL_SWITCH_FOR_EACH (ls, ctx->ovnnb_idl) {\n+        NBREC_LOGICAL_SWITCH_TABLE_FOR_EACH (ls,\n+                                             ic->nbrec_logical_switch_table) {\n             const char *ts_name = smap_get(&ls->other_config, \"interconn-ts\");\n             if (ts_name) {\n                 shash_add(&nb_tses, ts_name, ls);\n@@ -243,10 +251,11 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids,\n         }\n \n         /* Create/update NB Logical_Switch for each TS */\n-        ICNBREC_TRANSIT_SWITCH_FOR_EACH (ts, ctx->ovninb_idl) {\n+        ICNBREC_TRANSIT_SWITCH_TABLE_FOR_EACH (ts,\n+            ic->icnbrec_transit_switch_table) {\n             ls = shash_find_and_delete(&nb_tses, ts->name);\n             if (!ls) {\n-                ls = nbrec_logical_switch_insert(ctx->ovnnb_txn);\n+                ls = nbrec_logical_switch_insert(ctx->ovnnb_idl_txn);\n                 nbrec_logical_switch_set_name(ls, ts->name);\n                 nbrec_logical_switch_update_other_config_setkey(ls,\n                                                                 \"interconn-ts\",\n@@ -294,9 +303,10 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids,\n     /* Sync TS between INB and ISB.  This is performed after syncing with AZ\n      * SB, to avoid uncommitted ISB datapath tunnel key to be synced back to\n      * AZ. */\n-    if (ctx->ovnisb_txn) {\n+    if (ctx->ovnisb_idl_txn) {\n         /* Create ISB Datapath_Binding */\n-        ICNBREC_TRANSIT_SWITCH_FOR_EACH (ts, ctx->ovninb_idl) {\n+        ICNBREC_TRANSIT_SWITCH_TABLE_FOR_EACH (ts,\n+            ic->icnbrec_transit_switch_table) {\n             const struct icsbrec_datapath_binding *isb_dp =\n                 shash_find_and_delete(isb_ts_dps, ts->name);\n             if (!isb_dp) {\n@@ -307,7 +317,7 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids,\n                     continue;\n                 }\n \n-                isb_dp = icsbrec_datapath_binding_insert(ctx->ovnisb_txn);\n+                isb_dp = icsbrec_datapath_binding_insert(ctx->ovnisb_idl_txn);\n                 icsbrec_datapath_binding_set_transit_switch(isb_dp, ts->name);\n                 icsbrec_datapath_binding_set_tunnel_key(isb_dp, dp_key);\n             } else if (dp_key_refresh) {\n@@ -337,14 +347,17 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids,\n }\n \n static void\n-tr_run(struct ic_context *ctx, struct hmap *dp_tnlids,\n+tr_run(struct engine_context *ctx,\n+       struct ic_input *ic,\n+       struct hmap *dp_tnlids,\n        struct shash *isb_tr_dps)\n {\n     const struct nbrec_logical_router *lr;\n \n-    if (ctx->ovnnb_txn) {\n+    if (ctx->ovnnb_idl_txn) {\n         struct shash nb_tres = SHASH_INITIALIZER(&nb_tres);\n-        NBREC_LOGICAL_ROUTER_FOR_EACH (lr, ctx->ovnnb_idl) {\n+        NBREC_LOGICAL_ROUTER_TABLE_FOR_EACH (lr,\n+                                             ic->nbrec_logical_router_table) {\n             const char *tr_name = smap_get(&lr->options, \"interconn-tr\");\n             if (tr_name) {\n                 shash_add(&nb_tres, tr_name, lr);\n@@ -352,10 +365,11 @@ tr_run(struct ic_context *ctx, struct hmap *dp_tnlids,\n         }\n \n         const struct icnbrec_transit_router *tr;\n-        ICNBREC_TRANSIT_ROUTER_FOR_EACH (tr, ctx->ovninb_idl) {\n+        ICNBREC_TRANSIT_ROUTER_TABLE_FOR_EACH (tr,\n+            ic->icnbrec_transit_router_table) {\n             lr = shash_find_and_delete(&nb_tres, tr->name);\n             if (!lr) {\n-                lr = nbrec_logical_router_insert(ctx->ovnnb_txn);\n+                lr = nbrec_logical_router_insert(ctx->ovnnb_idl_txn);\n                 nbrec_logical_router_set_name(lr, tr->name);\n                 nbrec_logical_router_update_options_setkey(\n                     lr, \"interconn-tr\", tr->name);\n@@ -383,10 +397,11 @@ tr_run(struct ic_context *ctx, struct hmap *dp_tnlids,\n     /* Sync TR between INB and ISB.  This is performed after syncing with AZ\n      * SB, to avoid uncommitted ISB datapath tunnel key to be synced back to\n      * AZ. */\n-    if (ctx->ovnisb_txn) {\n+    if (ctx->ovnisb_idl_txn) {\n         /* Create ISB Datapath_Binding */\n         const struct icnbrec_transit_router *tr;\n-        ICNBREC_TRANSIT_ROUTER_FOR_EACH (tr, ctx->ovninb_idl) {\n+        ICNBREC_TRANSIT_ROUTER_TABLE_FOR_EACH (tr,\n+            ic->icnbrec_transit_router_table) {\n             char *uuid_str = uuid_to_string(&tr->header_.uuid);\n             struct icsbrec_datapath_binding *isb_dp =\n                 shash_find_and_delete(isb_tr_dps, uuid_str);\n@@ -399,7 +414,7 @@ tr_run(struct ic_context *ctx, struct hmap *dp_tnlids,\n                     continue;\n                 }\n \n-                isb_dp = icsbrec_datapath_binding_insert(ctx->ovnisb_txn);\n+                isb_dp = icsbrec_datapath_binding_insert(ctx->ovnisb_idl_txn);\n                 icsbrec_datapath_binding_set_tunnel_key(isb_dp, dp_key);\n                 icsbrec_datapath_binding_set_nb_ic_uuid(isb_dp,\n                                                         &tr->header_.uuid, 1);\n@@ -451,7 +466,7 @@ is_gateway_data_changed(const struct icsbrec_gateway *gw,\n }\n \n static void\n-sync_isb_gw_to_sb(struct ic_context *ctx,\n+sync_isb_gw_to_sb(struct engine_context *ctx,\n                   const struct icsbrec_gateway *gw,\n                   const struct sbrec_chassis *chassis)\n {\n@@ -464,7 +479,7 @@ sync_isb_gw_to_sb(struct ic_context *ctx,\n     struct sbrec_encap **sb_encaps =\n         xmalloc(gw->n_encaps * sizeof *sb_encaps);\n     for (int i = 0; i < gw->n_encaps; i++) {\n-        sb_encap = sbrec_encap_insert(ctx->ovnsb_txn);\n+        sb_encap = sbrec_encap_insert(ctx->ovnsb_idl_txn);\n         sbrec_encap_set_chassis_name(sb_encap, gw->name);\n         sbrec_encap_set_ip(sb_encap, gw->encaps[i]->ip);\n         sbrec_encap_set_type(sb_encap, gw->encaps[i]->type);\n@@ -476,7 +491,7 @@ sync_isb_gw_to_sb(struct ic_context *ctx,\n }\n \n static void\n-sync_sb_gw_to_isb(struct ic_context *ctx,\n+sync_sb_gw_to_isb(struct engine_context *ctx,\n                   const struct sbrec_chassis *chassis,\n                   const struct icsbrec_gateway *gw)\n {\n@@ -488,7 +503,7 @@ sync_sb_gw_to_isb(struct ic_context *ctx,\n     struct icsbrec_encap **isb_encaps =\n         xmalloc(chassis->n_encaps * sizeof *isb_encaps);\n     for (int i = 0; i < chassis->n_encaps; i++) {\n-        isb_encap = icsbrec_encap_insert(ctx->ovnisb_txn);\n+        isb_encap = icsbrec_encap_insert(ctx->ovnisb_idl_txn);\n         icsbrec_encap_set_gateway_name(isb_encap,\n                                       chassis->name);\n         icsbrec_encap_set_ip(isb_encap, chassis->encaps[i]->ip);\n@@ -504,17 +519,18 @@ sync_sb_gw_to_isb(struct ic_context *ctx,\n }\n \n static void\n-gateway_run(struct ic_context *ctx)\n+gateway_run(struct engine_context *ctx,\n+            struct ic_input *ic)\n {\n-    if (!ctx->ovnisb_txn || !ctx->ovnsb_txn) {\n+    if (!ctx->ovnisb_idl_txn || !ctx->ovnsb_idl_txn) {\n         return;\n     }\n \n     struct shash local_gws = SHASH_INITIALIZER(&local_gws);\n     struct shash remote_gws = SHASH_INITIALIZER(&remote_gws);\n     const struct icsbrec_gateway *gw;\n-    ICSBREC_GATEWAY_FOR_EACH (gw, ctx->ovnisb_idl) {\n-        if (gw->availability_zone == ctx->runned_az) {\n+    ICSBREC_GATEWAY_TABLE_FOR_EACH (gw, ic->icsbrec_gateway_table) {\n+        if (gw->availability_zone == ic->runned_az) {\n             shash_add(&local_gws, gw->name, gw);\n         } else {\n             shash_add(&remote_gws, gw->name, gw);\n@@ -522,12 +538,12 @@ gateway_run(struct ic_context *ctx)\n     }\n \n     const struct sbrec_chassis *chassis;\n-    SBREC_CHASSIS_FOR_EACH (chassis, ctx->ovnsb_idl) {\n+    SBREC_CHASSIS_TABLE_FOR_EACH (chassis, ic->sbrec_chassis_table) {\n         if (smap_get_bool(&chassis->other_config, \"is-interconn\", false)) {\n             gw = shash_find_and_delete(&local_gws, chassis->name);\n             if (!gw) {\n-                gw = icsbrec_gateway_insert(ctx->ovnisb_txn);\n-                icsbrec_gateway_set_availability_zone(gw, ctx->runned_az);\n+                gw = icsbrec_gateway_insert(ctx->ovnisb_idl_txn);\n+                icsbrec_gateway_set_availability_zone(gw, ic->runned_az);\n                 icsbrec_gateway_set_name(gw, chassis->name);\n                 sync_sb_gw_to_isb(ctx, chassis, gw);\n             } else if (is_gateway_data_changed(gw, chassis)) {\n@@ -553,7 +569,7 @@ gateway_run(struct ic_context *ctx)\n     /* Create SB chassis for remote gateways in ISB */\n     SHASH_FOR_EACH (node, &remote_gws) {\n         gw = node->data;\n-        chassis = sbrec_chassis_insert(ctx->ovnsb_txn);\n+        chassis = sbrec_chassis_insert(ctx->ovnsb_idl_txn);\n         sbrec_chassis_set_name(chassis, gw->name);\n         sync_isb_gw_to_sb(ctx, gw, chassis);\n     }\n@@ -561,15 +577,15 @@ gateway_run(struct ic_context *ctx)\n }\n \n static const struct nbrec_logical_switch *\n-find_ts_in_nb(struct ic_context *ctx, char *ts_name)\n+find_ts_in_nb(struct ic_input *ic, char *ts_name)\n {\n     const struct nbrec_logical_switch *key =\n-        nbrec_logical_switch_index_init_row(ctx->nbrec_ls_by_name);\n+        nbrec_logical_switch_index_init_row(ic->nbrec_ls_by_name);\n     nbrec_logical_switch_index_set_name(key, ts_name);\n \n     const struct nbrec_logical_switch *ls;\n     bool found = false;\n-    NBREC_LOGICAL_SWITCH_FOR_EACH_EQUAL (ls, key, ctx->nbrec_ls_by_name) {\n+    NBREC_LOGICAL_SWITCH_FOR_EACH_EQUAL (ls, key, ic->nbrec_ls_by_name) {\n         const char *ls_ts_name = smap_get(&ls->other_config, \"interconn-ts\");\n         if (ls_ts_name && !strcmp(ts_name, ls_ts_name)) {\n             found = true;\n@@ -585,15 +601,15 @@ find_ts_in_nb(struct ic_context *ctx, char *ts_name)\n }\n \n static const struct nbrec_logical_router *\n-find_tr_in_nb(struct ic_context *ctx, char *tr_name)\n+find_tr_in_nb(struct ic_input *ic, char *tr_name)\n {\n     const struct nbrec_logical_router *key =\n-        nbrec_logical_router_index_init_row(ctx->nbrec_lr_by_name);\n+        nbrec_logical_router_index_init_row(ic->nbrec_lr_by_name);\n     nbrec_logical_router_index_set_name(key, tr_name);\n \n     const struct nbrec_logical_router *lr;\n     bool found = false;\n-    NBREC_LOGICAL_ROUTER_FOR_EACH_EQUAL (lr, key, ctx->nbrec_lr_by_name) {\n+    NBREC_LOGICAL_ROUTER_FOR_EACH_EQUAL (lr, key, ic->nbrec_lr_by_name) {\n         if (smap_get(&lr->options, \"interconn-tr\")) {\n             found = true;\n             break;\n@@ -624,7 +640,7 @@ find_sb_pb_by_name(struct ovsdb_idl_index *sbrec_port_binding_by_name,\n }\n \n static const struct sbrec_port_binding *\n-find_peer_port(struct ic_context *ctx,\n+find_peer_port(struct ic_input *ic,\n                const struct sbrec_port_binding *sb_pb)\n {\n     const char *peer_name = smap_get(&sb_pb->options, \"peer\");\n@@ -632,61 +648,61 @@ find_peer_port(struct ic_context *ctx,\n         return NULL;\n     }\n \n-    return find_sb_pb_by_name(ctx->sbrec_port_binding_by_name, peer_name);\n+    return find_sb_pb_by_name(ic->sbrec_port_binding_by_name, peer_name);\n }\n \n static const struct sbrec_port_binding *\n-find_crp_from_lrp(struct ic_context *ctx,\n+find_crp_from_lrp(struct ic_input *ic,\n                   const struct sbrec_port_binding *lrp_pb)\n {\n     char *crp_name = ovn_chassis_redirect_name(lrp_pb->logical_port);\n \n     const struct sbrec_port_binding *pb =\n-        find_sb_pb_by_name(ctx->sbrec_port_binding_by_name, crp_name);\n+        find_sb_pb_by_name(ic->sbrec_port_binding_by_name, crp_name);\n \n     free(crp_name);\n     return pb;\n }\n \n static const struct sbrec_port_binding *\n-find_crp_for_sb_pb(struct ic_context *ctx,\n+find_crp_for_sb_pb(struct ic_input *ic,\n                    const struct sbrec_port_binding *sb_pb)\n {\n-    const struct sbrec_port_binding *peer = find_peer_port(ctx, sb_pb);\n+    const struct sbrec_port_binding *peer = find_peer_port(ic, sb_pb);\n     if (!peer) {\n         return NULL;\n     }\n \n-    return find_crp_from_lrp(ctx, peer);\n+    return find_crp_from_lrp(ic, peer);\n }\n \n static const struct nbrec_logical_switch_port *\n-get_lsp_by_ts_port_name(struct ic_context *ctx, const char *ts_port_name)\n+get_lsp_by_ts_port_name(struct ic_input *ic, const char *ts_port_name)\n {\n     const struct nbrec_logical_switch_port *lsp, *key;\n \n-    key = nbrec_logical_switch_port_index_init_row(ctx->nbrec_port_by_name);\n+    key = nbrec_logical_switch_port_index_init_row(ic->nbrec_port_by_name);\n     nbrec_logical_switch_port_index_set_name(key, ts_port_name);\n-    lsp = nbrec_logical_switch_port_index_find(ctx->nbrec_port_by_name, key);\n+    lsp = nbrec_logical_switch_port_index_find(ic->nbrec_port_by_name, key);\n     nbrec_logical_switch_port_index_destroy_row(key);\n \n     return lsp;\n }\n \n static const char *\n-get_lp_address_for_sb_pb(struct ic_context *ctx,\n+get_lp_address_for_sb_pb(struct ic_input *ic,\n                          const struct sbrec_port_binding *sb_pb)\n {\n     const struct nbrec_logical_switch_port *nb_lsp;\n \n-    nb_lsp = get_lsp_by_ts_port_name(ctx, sb_pb->logical_port);\n+    nb_lsp = get_lsp_by_ts_port_name(ic, sb_pb->logical_port);\n     if (!strcmp(nb_lsp->type, \"switch\")) {\n         /* Switches always have implicit \"unknown\" address, and IC-SB port\n          * binding can only have one address specified. */\n         return \"unknown\";\n     }\n \n-    const struct sbrec_port_binding *peer = find_peer_port(ctx, sb_pb);\n+    const struct sbrec_port_binding *peer = find_peer_port(ic, sb_pb);\n     if (!peer) {\n         return NULL;\n     }\n@@ -695,14 +711,14 @@ get_lp_address_for_sb_pb(struct ic_context *ctx,\n }\n \n static const struct sbrec_chassis *\n-find_sb_chassis(struct ic_context *ctx, const char *name)\n+find_sb_chassis(struct ic_input *ic, const char *name)\n {\n     const struct sbrec_chassis *key =\n-        sbrec_chassis_index_init_row(ctx->sbrec_chassis_by_name);\n+        sbrec_chassis_index_init_row(ic->sbrec_chassis_by_name);\n     sbrec_chassis_index_set_name(key, name);\n \n     const struct sbrec_chassis *chassis =\n-        sbrec_chassis_index_find(ctx->sbrec_chassis_by_name, key);\n+        sbrec_chassis_index_find(ic->sbrec_chassis_by_name, key);\n     sbrec_chassis_index_destroy_row(key);\n \n     return chassis;\n@@ -741,11 +757,11 @@ sync_lrp_tnl_key(const struct nbrec_logical_router_port *lrp,\n }\n \n static bool\n-get_router_uuid_by_sb_pb(struct ic_context *ctx,\n+get_router_uuid_by_sb_pb(struct ic_input *ic,\n                          const struct sbrec_port_binding *sb_pb,\n                          struct uuid *router_uuid)\n {\n-    const struct sbrec_port_binding *router_pb = find_peer_port(ctx, sb_pb);\n+    const struct sbrec_port_binding *router_pb = find_peer_port(ic, sb_pb);\n     if (!router_pb || !router_pb->datapath) {\n         return NULL;\n     }\n@@ -754,12 +770,12 @@ get_router_uuid_by_sb_pb(struct ic_context *ctx,\n }\n \n static void\n-update_isb_pb_external_ids(struct ic_context *ctx,\n+update_isb_pb_external_ids(struct ic_input *ic,\n                            const struct sbrec_port_binding *sb_pb,\n                            const struct icsbrec_port_binding *isb_pb)\n {\n     struct uuid lr_uuid;\n-    if (!get_router_uuid_by_sb_pb(ctx, sb_pb, &lr_uuid)) {\n+    if (!get_router_uuid_by_sb_pb(ic, sb_pb, &lr_uuid)) {\n         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);\n         VLOG_WARN_RL(&rl, \"Can't get router uuid for transit switch port %s.\",\n                      isb_pb->logical_port);\n@@ -784,13 +800,13 @@ update_isb_pb_external_ids(struct ic_context *ctx,\n  *   - Sync tunnel key from ISB to NB.\n  */\n static void\n-sync_local_port(struct ic_context *ctx,\n+sync_local_port(struct ic_input *ic,\n                 const struct icsbrec_port_binding *isb_pb,\n                 const struct sbrec_port_binding *sb_pb,\n                 const struct nbrec_logical_switch_port *lsp)\n {\n     /* Sync address from NB to ISB */\n-    const char *address = get_lp_address_for_sb_pb(ctx, sb_pb);\n+    const char *address = get_lp_address_for_sb_pb(ic, sb_pb);\n     if (!address) {\n         VLOG_DBG(\"Can't get router/switch port address for logical\"\n                  \" switch port %s\", sb_pb->logical_port);\n@@ -804,7 +820,7 @@ sync_local_port(struct ic_context *ctx,\n     }\n \n     /* Sync gateway from SB to ISB */\n-    const struct sbrec_port_binding *crp = find_crp_for_sb_pb(ctx, sb_pb);\n+    const struct sbrec_port_binding *crp = find_crp_for_sb_pb(ic, sb_pb);\n     if (crp && crp->chassis) {\n         if (strcmp(crp->chassis->name, isb_pb->gateway)) {\n             icsbrec_port_binding_set_gateway(isb_pb, crp->chassis->name);\n@@ -820,7 +836,7 @@ sync_local_port(struct ic_context *ctx,\n     }\n \n     /* Sync external_ids:router-id to ISB */\n-    update_isb_pb_external_ids(ctx, sb_pb, isb_pb);\n+    update_isb_pb_external_ids(ic, sb_pb, isb_pb);\n \n     /* Sync back tunnel key from ISB to NB */\n     sync_lsp_tnl_key(lsp, isb_pb->tunnel_key);\n@@ -831,7 +847,7 @@ sync_local_port(struct ic_context *ctx,\n  *   - Sync gateway from ISB to SB\n  */\n static void\n-sync_remote_port(struct ic_context *ctx,\n+sync_remote_port(struct ic_input *ic,\n                  const struct icsbrec_port_binding *isb_pb,\n                  const struct nbrec_logical_switch_port *lsp,\n                  const struct sbrec_port_binding *sb_pb)\n@@ -861,7 +877,7 @@ sync_remote_port(struct ic_context *ctx,\n     if (isb_pb->gateway[0]) {\n         if (!sb_pb->chassis || strcmp(sb_pb->chassis->name, isb_pb->gateway)) {\n             const struct sbrec_chassis *chassis =\n-                find_sb_chassis(ctx, isb_pb->gateway);\n+                find_sb_chassis(ic, isb_pb->gateway);\n             if (!chassis) {\n                 VLOG_DBG(\"Chassis %s is not found in SB, syncing from ISB \"\n                          \"to SB skipped for logical port %s.\",\n@@ -924,12 +940,12 @@ sync_router_port(const struct icsbrec_port_binding *isb_pb,\n }\n \n static void\n-create_nb_lsp(struct ic_context *ctx,\n+create_nb_lsp(struct engine_context *ctx,\n               const struct icsbrec_port_binding *isb_pb,\n               const struct nbrec_logical_switch *ls)\n {\n     const struct nbrec_logical_switch_port *lsp =\n-        nbrec_logical_switch_port_insert(ctx->ovnnb_txn);\n+        nbrec_logical_switch_port_insert(ctx->ovnnb_idl_txn);\n     nbrec_logical_switch_port_set_name(lsp, isb_pb->logical_port);\n     nbrec_logical_switch_port_set_type(lsp, \"remote\");\n \n@@ -953,7 +969,7 @@ allocate_port_key(struct hmap *pb_tnlids)\n }\n \n static const struct icsbrec_port_binding *\n-create_isb_pb(struct ic_context *ctx, const char *logical_port,\n+create_isb_pb(struct engine_context *ctx, const char *logical_port,\n               const struct icsbrec_availability_zone *az, const char *ts_name,\n               const struct uuid *nb_ic_uuid, const char *type,\n               struct hmap *pb_tnlids)\n@@ -964,7 +980,7 @@ create_isb_pb(struct ic_context *ctx, const char *logical_port,\n     }\n \n     const struct icsbrec_port_binding *isb_pb =\n-        icsbrec_port_binding_insert(ctx->ovnisb_txn);\n+        icsbrec_port_binding_insert(ctx->ovnisb_idl_txn);\n     icsbrec_port_binding_set_availability_zone(isb_pb, az);\n     icsbrec_port_binding_set_transit_switch(isb_pb, ts_name);\n     icsbrec_port_binding_set_logical_port(isb_pb, logical_port);\n@@ -975,25 +991,25 @@ create_isb_pb(struct ic_context *ctx, const char *logical_port,\n }\n \n static const struct nbrec_logical_router_port *\n-get_lrp_by_lrp_name(struct ic_context *ctx, const char *lrp_name)\n+get_lrp_by_lrp_name(struct ic_input *ic, const char *lrp_name)\n {\n     const struct nbrec_logical_router_port *lrp;\n     const struct nbrec_logical_router_port *lrp_key =\n-        nbrec_logical_router_port_index_init_row(ctx->nbrec_lrp_by_name);\n+        nbrec_logical_router_port_index_init_row(ic->nbrec_lrp_by_name);\n     nbrec_logical_router_port_index_set_name(lrp_key, lrp_name);\n     lrp =\n-        nbrec_logical_router_port_index_find(ctx->nbrec_lrp_by_name, lrp_key);\n+        nbrec_logical_router_port_index_find(ic->nbrec_lrp_by_name, lrp_key);\n     nbrec_logical_router_port_index_destroy_row(lrp_key);\n \n     return lrp;\n }\n \n static bool\n-trp_is_remote(struct ic_context *ctx, const char *chassis_name)\n+trp_is_remote(struct ic_input *ic, const char *chassis_name)\n {\n     if (chassis_name) {\n         const struct sbrec_chassis *chassis =\n-            find_sb_chassis(ctx, chassis_name);\n+            find_sb_chassis(ic, chassis_name);\n         if (chassis) {\n             return smap_get_bool(&chassis->other_config, \"is-remote\", false);\n         } else {\n@@ -1005,11 +1021,11 @@ trp_is_remote(struct ic_context *ctx, const char *chassis_name)\n }\n \n static struct nbrec_logical_router_port *\n-lrp_create(struct ic_context *ctx, const struct nbrec_logical_router *lr,\n+lrp_create(struct engine_context *ctx, const struct nbrec_logical_router *lr,\n            const struct icnbrec_transit_router_port *trp)\n {\n     struct nbrec_logical_router_port *lrp =\n-        nbrec_logical_router_port_insert(ctx->ovnnb_txn);\n+        nbrec_logical_router_port_insert(ctx->ovnnb_idl_txn);\n     nbrec_logical_router_port_set_name(lrp, trp->name);\n \n     nbrec_logical_router_port_update_options_setkey(lrp, \"interconn-tr\",\n@@ -1019,20 +1035,20 @@ lrp_create(struct ic_context *ctx, const struct nbrec_logical_router *lr,\n }\n \n static void\n-sync_ts_isb_pb(struct ic_context *ctx, const struct sbrec_port_binding *sb_pb,\n+sync_ts_isb_pb(struct ic_input *ic, const struct sbrec_port_binding *sb_pb,\n                const struct icsbrec_port_binding *isb_pb)\n {\n-    const char *address = get_lp_address_for_sb_pb(ctx, sb_pb);\n+    const char *address = get_lp_address_for_sb_pb(ic, sb_pb);\n     if (address) {\n         icsbrec_port_binding_set_address(isb_pb, address);\n     }\n \n-    const struct sbrec_port_binding *crp = find_crp_for_sb_pb(ctx, sb_pb);\n+    const struct sbrec_port_binding *crp = find_crp_for_sb_pb(ic, sb_pb);\n     if (crp && crp->chassis) {\n         icsbrec_port_binding_set_gateway(isb_pb, crp->chassis->name);\n     }\n \n-    update_isb_pb_external_ids(ctx, sb_pb, isb_pb);\n+    update_isb_pb_external_ids(ic, sb_pb, isb_pb);\n \n     /* XXX: Sync encap so that multiple encaps can be used for the same\n      * gateway.  However, it is not needed for now, since we don't yet\n@@ -1043,16 +1059,18 @@ sync_ts_isb_pb(struct ic_context *ctx, const struct sbrec_port_binding *sb_pb,\n }\n \n static const struct sbrec_port_binding *\n-find_lsp_in_sb(struct ic_context *ctx,\n+find_lsp_in_sb(struct ic_input *ic,\n                const struct nbrec_logical_switch_port *lsp)\n {\n-    return find_sb_pb_by_name(ctx->sbrec_port_binding_by_name, lsp->name);\n+    return find_sb_pb_by_name(ic->sbrec_port_binding_by_name, lsp->name);\n }\n \n static void\n-port_binding_run(struct ic_context *ctx)\n+port_binding_run(struct engine_context *ctx,\n+                 struct ic_input *ic)\n {\n-    if (!ctx->ovnisb_txn || !ctx->ovnnb_txn || !ctx->ovnsb_txn) {\n+    if (!ctx->ovnisb_idl_txn || !ctx->ovnnb_idl_txn\n+        || !ctx->ovnsb_idl_txn) {\n         return;\n     }\n \n@@ -1065,12 +1083,12 @@ port_binding_run(struct ic_context *ctx)\n \n     const struct icsbrec_port_binding *isb_pb;\n     const struct icsbrec_port_binding *isb_pb_key =\n-        icsbrec_port_binding_index_init_row(ctx->icsbrec_port_binding_by_az);\n+        icsbrec_port_binding_index_init_row(ic->icsbrec_port_binding_by_az);\n     icsbrec_port_binding_index_set_availability_zone(isb_pb_key,\n-                                                     ctx->runned_az);\n+                                                     ic->runned_az);\n \n     ICSBREC_PORT_BINDING_FOR_EACH_EQUAL (isb_pb, isb_pb_key,\n-                                         ctx->icsbrec_port_binding_by_az) {\n+                                         ic->icsbrec_port_binding_by_az) {\n         ic_pb_get_type(isb_pb) != IC_ROUTER_PORT\n             ? shash_add(&switch_all_local_pbs, isb_pb->logical_port, isb_pb)\n             : shash_add(&router_all_local_pbs, isb_pb->logical_port, isb_pb);\n@@ -1081,8 +1099,9 @@ port_binding_run(struct ic_context *ctx)\n \n     const struct sbrec_port_binding *sb_pb;\n     const struct icnbrec_transit_switch *ts;\n-    ICNBREC_TRANSIT_SWITCH_FOR_EACH (ts, ctx->ovninb_idl) {\n-        const struct nbrec_logical_switch *ls = find_ts_in_nb(ctx, ts->name);\n+    ICNBREC_TRANSIT_SWITCH_TABLE_FOR_EACH (ts,\n+                                           ic->icnbrec_transit_switch_table) {\n+        const struct nbrec_logical_switch *ls = find_ts_in_nb(ic, ts->name);\n         if (!ls) {\n             VLOG_DBG(\"Transit switch %s not found in NB.\", ts->name);\n             continue;\n@@ -1091,12 +1110,12 @@ port_binding_run(struct ic_context *ctx)\n         struct shash remote_pbs = SHASH_INITIALIZER(&remote_pbs);\n \n         isb_pb_key = icsbrec_port_binding_index_init_row(\n-            ctx->icsbrec_port_binding_by_ts);\n+            ic->icsbrec_port_binding_by_ts);\n         icsbrec_port_binding_index_set_transit_switch(isb_pb_key, ts->name);\n \n         ICSBREC_PORT_BINDING_FOR_EACH_EQUAL (isb_pb, isb_pb_key,\n-                                             ctx->icsbrec_port_binding_by_ts) {\n-            if (isb_pb->availability_zone == ctx->runned_az) {\n+                                             ic->icsbrec_port_binding_by_ts) {\n+            if (isb_pb->availability_zone == ic->runned_az) {\n                 shash_add(&local_pbs, isb_pb->logical_port, isb_pb);\n                 shash_find_and_delete(&switch_all_local_pbs,\n                                       isb_pb->logical_port);\n@@ -1113,18 +1132,18 @@ port_binding_run(struct ic_context *ctx)\n             if (!strcmp(lsp->type, \"router\")\n                 || !strcmp(lsp->type, \"switch\")) {\n                 /* The port is local. */\n-                sb_pb = find_lsp_in_sb(ctx, lsp);\n+                sb_pb = find_lsp_in_sb(ic, lsp);\n                 if (!sb_pb) {\n                     continue;\n                 }\n                 isb_pb = shash_find_and_delete(&local_pbs, lsp->name);\n                 if (!isb_pb) {\n                     isb_pb = create_isb_pb(\n-                        ctx, sb_pb->logical_port, ctx->runned_az, ts->name,\n+                        ctx, sb_pb->logical_port, ic->runned_az, ts->name,\n                         &ts->header_.uuid, \"transit-switch-port\", &pb_tnlids);\n-                    sync_ts_isb_pb(ctx, sb_pb, isb_pb);\n+                    sync_ts_isb_pb(ic, sb_pb, isb_pb);\n                 } else {\n-                    sync_local_port(ctx, isb_pb, sb_pb, lsp);\n+                    sync_local_port(ic, isb_pb, sb_pb, lsp);\n                 }\n \n                 if (isb_pb->type) {\n@@ -1142,11 +1161,11 @@ port_binding_run(struct ic_context *ctx)\n                 if (!isb_pb) {\n                     nbrec_logical_switch_update_ports_delvalue(ls, lsp);\n                 } else {\n-                    sb_pb = find_lsp_in_sb(ctx, lsp);\n+                    sb_pb = find_lsp_in_sb(ic, lsp);\n                     if (!sb_pb) {\n                         continue;\n                     }\n-                    sync_remote_port(ctx, isb_pb, lsp, sb_pb);\n+                    sync_remote_port(ic, isb_pb, lsp, sb_pb);\n                 }\n             } else {\n                 VLOG_DBG(\"Ignore lsp %s on ts %s with type %s.\",\n@@ -1174,8 +1193,9 @@ port_binding_run(struct ic_context *ctx)\n     shash_destroy(&switch_all_local_pbs);\n \n     const struct icnbrec_transit_router *tr;\n-    ICNBREC_TRANSIT_ROUTER_FOR_EACH (tr, ctx->ovninb_idl) {\n-        const struct nbrec_logical_router *lr = find_tr_in_nb(ctx, tr->name);\n+    ICNBREC_TRANSIT_ROUTER_TABLE_FOR_EACH (tr,\n+                                           ic->icnbrec_transit_router_table) {\n+        const struct nbrec_logical_router *lr = find_tr_in_nb(ic, tr->name);\n         if (!lr) {\n             VLOG_DBG(\"Transit router %s not found in NB.\", tr->name);\n             continue;\n@@ -1193,12 +1213,12 @@ port_binding_run(struct ic_context *ctx)\n         }\n \n         isb_pb_key = icsbrec_port_binding_index_init_row(\n-            ctx->icsbrec_port_binding_by_ts);\n+            ic->icsbrec_port_binding_by_ts);\n         icsbrec_port_binding_index_set_transit_switch(isb_pb_key, tr->name);\n \n         ICSBREC_PORT_BINDING_FOR_EACH_EQUAL (isb_pb, isb_pb_key,\n-                                             ctx->icsbrec_port_binding_by_ts) {\n-            if (isb_pb->availability_zone == ctx->runned_az) {\n+                                             ic->icsbrec_port_binding_by_ts) {\n+            if (isb_pb->availability_zone == ic->runned_az) {\n                 shash_add(&local_pbs, isb_pb->logical_port, isb_pb);\n                 shash_find_and_delete(&router_all_local_pbs,\n                                       isb_pb->logical_port);\n@@ -1211,12 +1231,12 @@ port_binding_run(struct ic_context *ctx)\n         for (size_t i = 0; i < tr->n_ports; i++) {\n             const struct icnbrec_transit_router_port *trp = tr->ports[i];\n \n-            if (trp_is_remote(ctx, trp->chassis)) {\n+            if (trp_is_remote(ic, trp->chassis)) {\n                 isb_pb = shash_find_and_delete(&remote_pbs, trp->name);\n             } else {\n                 isb_pb = shash_find_and_delete(&local_pbs, trp->name);\n                 if (!isb_pb) {\n-                    isb_pb = create_isb_pb(ctx, trp->name, ctx->runned_az,\n+                    isb_pb = create_isb_pb(ctx, trp->name, ic->runned_az,\n                                            tr->name, &tr->header_.uuid,\n                                            \"transit-router-port\", &pb_tnlids);\n                     icsbrec_port_binding_set_address(isb_pb, trp->mac);\n@@ -1548,8 +1568,8 @@ add_to_routes_ad(struct hmap *routes_ad, const struct in6_addr prefix,\n \n     uint hash = ic_route_hash(&prefix, plen, &nexthop, origin, route_table);\n \n-    if (!ic_route_find(routes_ad, &prefix, plen, &nexthop, origin, route_table,\n-                       hash)) {\n+    if (!ic_route_find(routes_ad, &prefix, plen, &nexthop, origin,\n+                       route_table, hash)) {\n         struct ic_route_info *ic_route = xzalloc(sizeof *ic_route);\n         ic_route->prefix = prefix;\n         ic_route->plen = plen;\n@@ -1921,11 +1941,11 @@ route_need_learn(const struct nbrec_logical_router *lr,\n }\n \n static const char *\n-get_lrp_name_by_ts_port_name(struct ic_context *ctx, const char *ts_port_name)\n+get_lrp_name_by_ts_port_name(struct ic_input *ic, const char *ts_port_name)\n {\n     const struct nbrec_logical_switch_port *nb_lsp;\n \n-    nb_lsp = get_lsp_by_ts_port_name(ctx, ts_port_name);\n+    nb_lsp = get_lsp_by_ts_port_name(ic, ts_port_name);\n     if (!nb_lsp) {\n         return NULL;\n     }\n@@ -1934,12 +1954,12 @@ get_lrp_name_by_ts_port_name(struct ic_context *ctx, const char *ts_port_name)\n }\n \n static const struct nbrec_logical_router_port *\n-find_lrp_of_nexthop(struct ic_context *ctx,\n+find_lrp_of_nexthop(struct ic_input *ic,\n                     const struct icsbrec_route *isb_route)\n {\n     const struct nbrec_logical_router_port *lrp;\n     const struct nbrec_logical_switch *ls;\n-    ls = find_ts_in_nb(ctx, isb_route->transit_switch);\n+    ls = find_ts_in_nb(ic, isb_route->transit_switch);\n     if (!ls) {\n         return NULL;\n     }\n@@ -1951,13 +1971,13 @@ find_lrp_of_nexthop(struct ic_context *ctx,\n \n     for (size_t i = 0; i < ls->n_ports; i++) {\n         char *lsp_name = ls->ports[i]->name;\n-        const char *lrp_name = get_lrp_name_by_ts_port_name(ctx,\n+        const char *lrp_name = get_lrp_name_by_ts_port_name(ic,\n                                                             lsp_name);\n         if (!lrp_name) {\n             continue;\n         }\n \n-        lrp = get_lrp_by_lrp_name(ctx, lrp_name);\n+        lrp = get_lrp_by_lrp_name(ic, lrp_name);\n         if (!lrp) {\n             continue;\n         }\n@@ -1995,13 +2015,13 @@ find_lrp_of_nexthop(struct ic_context *ctx,\n }\n \n static bool\n-lrp_is_ts_port(struct ic_context *ctx, struct ic_router_info *ic_lr,\n+lrp_is_ts_port(struct ic_input *ic, struct ic_router_info *ic_lr,\n                const char *lrp_name)\n {\n     const struct icsbrec_port_binding *isb_pb;\n     const char *ts_lrp_name;\n     VECTOR_FOR_EACH (&ic_lr->isb_pbs, isb_pb) {\n-        ts_lrp_name = get_lrp_name_by_ts_port_name(ctx, isb_pb->logical_port);\n+        ts_lrp_name = get_lrp_name_by_ts_port_name(ic, isb_pb->logical_port);\n         if (!strcmp(ts_lrp_name, lrp_name)) {\n             return true;\n         }\n@@ -2010,14 +2030,15 @@ lrp_is_ts_port(struct ic_context *ctx, struct ic_router_info *ic_lr,\n }\n \n static void\n-sync_learned_routes(struct ic_context *ctx,\n+sync_learned_routes(struct engine_context *ctx,\n+                    struct ic_input *ic,\n                     struct ic_router_info *ic_lr)\n {\n-    ovs_assert(ctx->ovnnb_txn);\n+    ovs_assert(ctx->ovnnb_idl_txn);\n     const struct icsbrec_route *isb_route, *isb_route_key;\n \n     const struct nbrec_nb_global *nb_global =\n-        nbrec_nb_global_first(ctx->ovnnb_idl);\n+        nbrec_nb_global_table_first(ic->nbrec_nb_global_table);\n     ovs_assert(nb_global);\n \n     const char *lrp_name, *ts_route_table, *route_filter_tag;\n@@ -2027,8 +2048,8 @@ sync_learned_routes(struct ic_context *ctx,\n         if (!strcmp(isb_pb->address, \"\")) {\n             continue;\n         }\n-        lrp_name = get_lrp_name_by_ts_port_name(ctx, isb_pb->logical_port);\n-        lrp = get_lrp_by_lrp_name(ctx, lrp_name);\n+        lrp_name = get_lrp_name_by_ts_port_name(ic, isb_pb->logical_port);\n+        lrp = get_lrp_by_lrp_name(ic, lrp_name);\n         if (lrp) {\n             ts_route_table = smap_get_def(&lrp->options, \"route_table\", \"\");\n             route_filter_tag = smap_get_def(&lrp->options,\n@@ -2038,12 +2059,12 @@ sync_learned_routes(struct ic_context *ctx,\n             route_filter_tag = \"\";\n         }\n \n-        isb_route_key = icsbrec_route_index_init_row(ctx->icsbrec_route_by_ts);\n+        isb_route_key = icsbrec_route_index_init_row(ic->icsbrec_route_by_ts);\n         icsbrec_route_index_set_transit_switch(isb_route_key,\n                                                isb_pb->transit_switch);\n \n         ICSBREC_ROUTE_FOR_EACH_EQUAL (isb_route, isb_route_key,\n-                                      ctx->icsbrec_route_by_ts) {\n+                                      ic->icsbrec_route_by_ts) {\n             /* Filters ICSB routes, skipping those that either belong to\n              * current logical router or are legacy routes from the current\n              * availability zone (withoud lr-id).\n@@ -2055,7 +2076,7 @@ sync_learned_routes(struct ic_context *ctx,\n                     || uuid_equals(&ic_lr->lr->header_.uuid, &lr_uuid)) {\n                     continue;\n                 }\n-            } else if (isb_route->availability_zone == ctx->runned_az) {\n+            } else if (isb_route->availability_zone == ic->runned_az) {\n                 continue;\n             }\n \n@@ -2117,7 +2138,8 @@ sync_learned_routes(struct ic_context *ctx,\n             } else {\n                 /* Create the missing route in NB. */\n                 const struct nbrec_logical_router_static_route *nb_route =\n-                    nbrec_logical_router_static_route_insert(ctx->ovnnb_txn);\n+                    nbrec_logical_router_static_route_insert(\n+                        ctx->ovnnb_idl_txn);\n                 nbrec_logical_router_static_route_set_ip_prefix(nb_route,\n                     isb_route->ip_prefix);\n                 nbrec_logical_router_static_route_set_nexthop(nb_route,\n@@ -2190,20 +2212,21 @@ ad_route_sync_external_ids(const struct ic_route_info *route_adv,\n \n /* Sync routes from routes_ad to IC-SB. */\n static void\n-advertise_routes(struct ic_context *ctx,\n+advertise_routes(struct engine_context *ctx,\n+                 struct ic_input *ic,\n                  const struct icsbrec_availability_zone *az,\n                  const char *ts_name,\n                  struct hmap *routes_ad)\n {\n-    ovs_assert(ctx->ovnisb_txn);\n+    ovs_assert(ctx->ovnisb_idl_txn);\n     const struct icsbrec_route *isb_route;\n     const struct icsbrec_route *isb_route_key =\n-        icsbrec_route_index_init_row(ctx->icsbrec_route_by_ts_az);\n+        icsbrec_route_index_init_row(ic->icsbrec_route_by_ts_az);\n     icsbrec_route_index_set_transit_switch(isb_route_key, ts_name);\n     icsbrec_route_index_set_availability_zone(isb_route_key, az);\n \n     ICSBREC_ROUTE_FOR_EACH_EQUAL (isb_route, isb_route_key,\n-                                  ctx->icsbrec_route_by_ts_az) {\n+                                  ic->icsbrec_route_by_ts_az) {\n         struct in6_addr prefix, nexthop;\n         unsigned int plen;\n \n@@ -2237,7 +2260,7 @@ advertise_routes(struct ic_context *ctx,\n     /* Create the missing routes in IC-SB */\n     struct ic_route_info *route_adv;\n     HMAP_FOR_EACH_SAFE (route_adv, node, routes_ad) {\n-        isb_route = icsbrec_route_insert(ctx->ovnisb_txn);\n+        isb_route = icsbrec_route_insert(ctx->ovnisb_idl_txn);\n         icsbrec_route_set_transit_switch(isb_route, ts_name);\n         icsbrec_route_set_availability_zone(isb_route, az);\n \n@@ -2273,7 +2296,7 @@ advertise_routes(struct ic_context *ctx,\n }\n \n static void\n-build_ts_routes_to_adv(struct ic_context *ctx,\n+build_ts_routes_to_adv(struct ic_input *ic,\n                        struct ic_router_info *ic_lr,\n                        struct hmap *routes_ad,\n                        struct lport_addresses *ts_port_addrs,\n@@ -2310,7 +2333,7 @@ build_ts_routes_to_adv(struct ic_context *ctx,\n     /* Check directly-connected subnets of the LR */\n     for (int i = 0; i < lr->n_ports; i++) {\n         const struct nbrec_logical_router_port *lrp = lr->ports[i];\n-        if (!lrp_is_ts_port(ctx, ic_lr, lrp->name)) {\n+        if (!lrp_is_ts_port(ic, ic_lr, lrp->name)) {\n             for (int j = 0; j < lrp->n_networks; j++) {\n                 add_network_to_routes_ad(routes_ad, lrp->networks[j], lrp,\n                                          ts_port_addrs,\n@@ -2356,12 +2379,13 @@ build_ts_routes_to_adv(struct ic_context *ctx,\n }\n \n static void\n-collect_lr_routes(struct ic_context *ctx,\n+collect_lr_routes(struct ic_input *ic,\n                   struct ic_router_info *ic_lr,\n                   struct shash *routes_ad_by_ts)\n {\n     const struct nbrec_nb_global *nb_global =\n-        nbrec_nb_global_first(ctx->ovnnb_idl);\n+        nbrec_nb_global_table_first(ic->nbrec_nb_global_table);\n+\n     ovs_assert(nb_global);\n \n     const struct icsbrec_port_binding *isb_pb;\n@@ -2374,10 +2398,10 @@ collect_lr_routes(struct ic_context *ctx,\n     const struct icnbrec_transit_switch *t_sw;\n     VECTOR_FOR_EACH (&ic_lr->isb_pbs, isb_pb) {\n         key = icnbrec_transit_switch_index_init_row(\n-            ctx->icnbrec_transit_switch_by_name);\n+            ic->icnbrec_transit_switch_by_name);\n         icnbrec_transit_switch_index_set_name(key, isb_pb->transit_switch);\n         t_sw = icnbrec_transit_switch_index_find(\n-             ctx->icnbrec_transit_switch_by_name, key);\n+             ic->icnbrec_transit_switch_by_name, key);\n         icnbrec_transit_switch_index_destroy_row(key);\n         if (!t_sw) {\n             continue;\n@@ -2398,8 +2422,8 @@ collect_lr_routes(struct ic_context *ctx,\n                          ic_lr->lr->name);\n             continue;\n         }\n-        lrp_name = get_lrp_name_by_ts_port_name(ctx, isb_pb->logical_port);\n-        lrp = get_lrp_by_lrp_name(ctx, lrp_name);\n+        lrp_name = get_lrp_name_by_ts_port_name(ic, isb_pb->logical_port);\n+        lrp = get_lrp_by_lrp_name(ic, lrp_name);\n         if (lrp) {\n             route_table = smap_get_def(&lrp->options, \"route_table\", \"\");\n             route_tag = smap_get_def(&lrp->options, \"ic-route-tag\", \"\");\n@@ -2407,34 +2431,34 @@ collect_lr_routes(struct ic_context *ctx,\n             route_table = \"\";\n             route_tag = \"\";\n         }\n-        build_ts_routes_to_adv(ctx, ic_lr, routes_ad, &ts_port_addrs,\n+        build_ts_routes_to_adv(ic, ic_lr, routes_ad, &ts_port_addrs,\n                                nb_global, route_table, route_tag, lrp);\n         destroy_lport_addresses(&ts_port_addrs);\n     }\n }\n \n static void\n-delete_orphan_ic_routes(struct ic_context *ctx,\n-                         const struct icsbrec_availability_zone *az)\n+delete_orphan_ic_routes(struct ic_input *ic,\n+                        const struct icsbrec_availability_zone *az)\n {\n     const struct icsbrec_route *isb_route, *isb_route_key =\n-        icsbrec_route_index_init_row(ctx->icsbrec_route_by_az);\n+        icsbrec_route_index_init_row(ic->icsbrec_route_by_az);\n     icsbrec_route_index_set_availability_zone(isb_route_key, az);\n \n     const struct icnbrec_transit_switch *t_sw, *t_sw_key;\n \n     ICSBREC_ROUTE_FOR_EACH_EQUAL (isb_route, isb_route_key,\n-                                  ctx->icsbrec_route_by_az)\n+                                  ic->icsbrec_route_by_az)\n     {\n         t_sw_key = icnbrec_transit_switch_index_init_row(\n-            ctx->icnbrec_transit_switch_by_name);\n+            ic->icnbrec_transit_switch_by_name);\n         icnbrec_transit_switch_index_set_name(t_sw_key,\n             isb_route->transit_switch);\n         t_sw = icnbrec_transit_switch_index_find(\n-            ctx->icnbrec_transit_switch_by_name, t_sw_key);\n+            ic->icnbrec_transit_switch_by_name, t_sw_key);\n         icnbrec_transit_switch_index_destroy_row(t_sw_key);\n \n-        if (!t_sw || !find_lrp_of_nexthop(ctx, isb_route)) {\n+        if (!t_sw || !find_lrp_of_nexthop(ic, isb_route)) {\n             static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);\n             VLOG_INFO_RL(&rl, \"Deleting orphan ICDB:Route: %s->%s (%s, rtb:%s,\"\n                          \" transit switch: %s)\", isb_route->ip_prefix,\n@@ -2447,34 +2471,35 @@ delete_orphan_ic_routes(struct ic_context *ctx,\n }\n \n static void\n-route_run(struct ic_context *ctx)\n+route_run(struct engine_context *ctx,\n+          struct ic_input *ic)\n {\n-    if (!ctx->ovnisb_txn || !ctx->ovnnb_txn) {\n+    if (!ctx->ovnisb_idl_txn || !ctx->ovnnb_idl_txn) {\n         return;\n     }\n \n-    delete_orphan_ic_routes(ctx, ctx->runned_az);\n+    delete_orphan_ic_routes(ic, ic->runned_az);\n \n     struct hmap ic_lrs = HMAP_INITIALIZER(&ic_lrs);\n     const struct icsbrec_port_binding *isb_pb;\n     const struct icsbrec_port_binding *isb_pb_key =\n-        icsbrec_port_binding_index_init_row(ctx->icsbrec_port_binding_by_az);\n+        icsbrec_port_binding_index_init_row(ic->icsbrec_port_binding_by_az);\n     icsbrec_port_binding_index_set_availability_zone(isb_pb_key,\n-        ctx->runned_az);\n+        ic->runned_az);\n \n     /* Each port on TS maps to a logical router, which is stored in the\n      * external_ids:router-id of the IC SB port_binding record.\n      * Here we build info for interconnected Logical Router:\n      * collect IC Port Binding to process routes sync later on. */\n     ICSBREC_PORT_BINDING_FOR_EACH_EQUAL (isb_pb, isb_pb_key,\n-                                         ctx->icsbrec_port_binding_by_az)\n+                                         ic->icsbrec_port_binding_by_az)\n     {\n         if (ic_pb_get_type(isb_pb) == IC_ROUTER_PORT) {\n             continue;\n         }\n         const struct nbrec_logical_switch_port *nb_lsp;\n \n-        nb_lsp = get_lsp_by_ts_port_name(ctx, isb_pb->logical_port);\n+        nb_lsp = get_lsp_by_ts_port_name(ic, isb_pb->logical_port);\n         if (!strcmp(nb_lsp->type, \"switch\")) {\n             VLOG_DBG(\"IC-SB Port_Binding '%s' on ts '%s' corresponds to a \"\n                      \"switch port, not considering for route collection.\",\n@@ -2483,7 +2508,7 @@ route_run(struct ic_context *ctx)\n         }\n \n         const char *ts_lrp_name =\n-            get_lrp_name_by_ts_port_name(ctx, isb_pb->logical_port);\n+            get_lrp_name_by_ts_port_name(ic, isb_pb->logical_port);\n         if (!ts_lrp_name) {\n             static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);\n             VLOG_WARN_RL(&rl, \"Route sync ignores port %s on ts %s because \"\n@@ -2501,7 +2526,8 @@ route_run(struct ic_context *ctx)\n         }\n \n         const struct nbrec_logical_router *lr\n-            = nbrec_logical_router_get_for_uuid(ctx->ovnnb_idl, &lr_uuid);\n+            = nbrec_logical_router_table_get_for_uuid(\n+                ic->nbrec_logical_router_table, &lr_uuid);\n         if (!lr) {\n             continue;\n         }\n@@ -2522,8 +2548,8 @@ route_run(struct ic_context *ctx)\n     struct ic_router_info *ic_lr;\n     struct shash routes_ad_by_ts = SHASH_INITIALIZER(&routes_ad_by_ts);\n     HMAP_FOR_EACH_SAFE (ic_lr, node, &ic_lrs) {\n-        collect_lr_routes(ctx, ic_lr, &routes_ad_by_ts);\n-        sync_learned_routes(ctx, ic_lr);\n+        collect_lr_routes(ic, ic_lr, &routes_ad_by_ts);\n+        sync_learned_routes(ctx, ic, ic_lr);\n         vector_destroy(&ic_lr->isb_pbs);\n         hmap_destroy(&ic_lr->routes_learned);\n         hmap_remove(&ic_lrs, &ic_lr->node);\n@@ -2531,7 +2557,7 @@ route_run(struct ic_context *ctx)\n     }\n     struct shash_node *node;\n     SHASH_FOR_EACH (node, &routes_ad_by_ts) {\n-        advertise_routes(ctx, ctx->runned_az, node->name, node->data);\n+        advertise_routes(ctx, ic, ic->runned_az, node->name, node->data);\n         hmap_destroy(node->data);\n     }\n     shash_destroy_free_data(&routes_ad_by_ts);\n@@ -2665,18 +2691,18 @@ remove_unused_sb_records(struct hmap *local_sb_svcs_map)\n }\n \n static void\n-create_pushed_svcs_mon(struct ic_context *ctx,\n+create_pushed_svcs_mon(struct ic_input *ic,\n                        struct hmap *pushed_svcs_map)\n {\n     struct sbrec_service_monitor *key =\n         sbrec_service_monitor_index_init_row(\n-            ctx->sbrec_service_monitor_by_remote_type);\n+            ic->sbrec_service_monitor_by_remote_type);\n \n     sbrec_service_monitor_index_set_remote(key, true);\n \n     const struct sbrec_service_monitor *sb_rec;\n     SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key,\n-        ctx->sbrec_service_monitor_by_remote_type) {\n+        ic->sbrec_service_monitor_by_remote_type) {\n         const char *target_az_name = smap_get(&sb_rec->options,\n                                               \"az-name\");\n         if (!target_az_name) {\n@@ -2684,7 +2710,7 @@ create_pushed_svcs_mon(struct ic_context *ctx,\n         }\n         create_service_monitor_info(pushed_svcs_map, sb_rec,\n                                     &sb_rec->header_.uuid,\n-                                    ctx->runned_az->name, target_az_name,\n+                                    ic->runned_az->name, target_az_name,\n                                     NULL, false);\n     }\n \n@@ -2692,22 +2718,22 @@ create_pushed_svcs_mon(struct ic_context *ctx,\n }\n \n static void\n-create_synced_svcs_mon(struct ic_context *ctx,\n+create_synced_svcs_mon(struct ic_input *ic,\n                        struct hmap *synced_svcs_map)\n {\n     struct icsbrec_service_monitor *key =\n         icsbrec_service_monitor_index_init_row(\n-          ctx->icsbrec_service_monitor_by_target_az);\n+          ic->icsbrec_service_monitor_by_target_az);\n \n     icsbrec_service_monitor_index_set_target_availability_zone(\n-        key, ctx->runned_az->name);\n+        key, ic->runned_az->name);\n \n     const struct icsbrec_service_monitor *ic_rec;\n     ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key,\n-        ctx->icsbrec_service_monitor_by_target_az) {\n+        ic->icsbrec_service_monitor_by_target_az) {\n \n         const struct sbrec_port_binding *pb =\n-            find_sb_pb_by_name(ctx->sbrec_port_binding_by_name,\n+            find_sb_pb_by_name(ic->sbrec_port_binding_by_name,\n                                ic_rec->logical_port);\n \n         if (!pb || !pb->up) {\n@@ -2717,7 +2743,7 @@ create_synced_svcs_mon(struct ic_context *ctx,\n         const char *chassis_name = pb->chassis ? pb->chassis->name : NULL;\n         create_service_monitor_info(synced_svcs_map, ic_rec,\n                                     &ic_rec->header_.uuid,\n-                                    ctx->runned_az->name,\n+                                    ic->runned_az->name,\n                                     NULL, chassis_name, true);\n     }\n \n@@ -2725,22 +2751,22 @@ create_synced_svcs_mon(struct ic_context *ctx,\n }\n \n static void\n-create_local_ic_svcs_map(struct ic_context *ctx,\n+create_local_ic_svcs_map(struct ic_input *ic,\n                          struct hmap *owned_svc_map)\n {\n     struct icsbrec_service_monitor *key =\n         icsbrec_service_monitor_index_init_row(\n-          ctx->icsbrec_service_monitor_by_source_az);\n+          ic->icsbrec_service_monitor_by_source_az);\n \n     icsbrec_service_monitor_index_set_source_availability_zone(\n-        key, ctx->runned_az->name);\n+        key, ic->runned_az->name);\n \n     const struct icsbrec_service_monitor *ic_rec;\n     ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key,\n-        ctx->icsbrec_service_monitor_by_source_az) {\n+        ic->icsbrec_service_monitor_by_source_az) {\n         create_service_monitor_info(owned_svc_map, ic_rec,\n                                     &ic_rec->header_.uuid,\n-                                    ctx->runned_az->name, NULL,\n+                                    ic->runned_az->name, NULL,\n                                     NULL, true);\n     }\n \n@@ -2748,22 +2774,22 @@ create_local_ic_svcs_map(struct ic_context *ctx,\n }\n \n static void\n-create_local_sb_svcs_map(struct ic_context *ctx,\n+create_local_sb_svcs_map(struct ic_input *ic,\n                          struct hmap *owned_svc_map)\n {\n     struct sbrec_service_monitor *key =\n         sbrec_service_monitor_index_init_row(\n-          ctx->sbrec_service_monitor_by_ic_learned);\n+          ic->sbrec_service_monitor_by_ic_learned);\n \n     sbrec_service_monitor_index_set_ic_learned(\n         key, true);\n \n     const struct sbrec_service_monitor *sb_rec;\n     SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key,\n-        ctx->sbrec_service_monitor_by_ic_learned) {\n+        ic->sbrec_service_monitor_by_ic_learned) {\n         create_service_monitor_info(owned_svc_map, sb_rec,\n                                     &sb_rec->header_.uuid,\n-                                    ctx->runned_az->name, NULL,\n+                                    ic->runned_az->name, NULL,\n                                     NULL, false);\n     }\n \n@@ -2771,21 +2797,21 @@ create_local_sb_svcs_map(struct ic_context *ctx,\n }\n \n static const struct sbrec_service_monitor *\n-lookup_sb_svc_rec(struct ic_context *ctx,\n+lookup_sb_svc_rec(struct ic_input *ic,\n                   const struct service_monitor_info *svc_mon)\n {\n     const struct icsbrec_service_monitor *db_rec =\n         svc_mon->db_rec.ic_rec;\n     struct sbrec_service_monitor *key =\n         sbrec_service_monitor_index_init_row(\n-            ctx->sbrec_service_monitor_by_remote_type_logical_port);\n+            ic->sbrec_service_monitor_by_remote_type_logical_port);\n \n     sbrec_service_monitor_index_set_remote(key, false);\n     sbrec_service_monitor_index_set_logical_port(key, db_rec->logical_port);\n \n     const struct sbrec_service_monitor *sb_rec;\n     SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key,\n-        ctx->sbrec_service_monitor_by_remote_type_logical_port) {\n+        ic->sbrec_service_monitor_by_remote_type_logical_port) {\n         if (db_rec->port == sb_rec->port &&\n             ((db_rec->type && sb_rec->type &&\n               !strcmp(db_rec->type, sb_rec->type)) ||\n@@ -2804,14 +2830,14 @@ lookup_sb_svc_rec(struct ic_context *ctx,\n }\n \n static const struct icsbrec_service_monitor *\n-lookup_icsb_svc_rec(struct ic_context *ctx,\n+lookup_icsb_svc_rec(struct ic_input *ic,\n                     const struct service_monitor_info *svc_mon)\n {\n     const struct sbrec_service_monitor *db_rec =\n        svc_mon->db_rec.sb_rec;\n     struct icsbrec_service_monitor *key =\n         icsbrec_service_monitor_index_init_row(\n-        ctx->icsbrec_service_monitor_by_target_az_logical_port);\n+        ic->icsbrec_service_monitor_by_target_az_logical_port);\n \n     ovs_assert(svc_mon->dst_az_name);\n     icsbrec_service_monitor_index_set_target_availability_zone(\n@@ -2822,7 +2848,7 @@ lookup_icsb_svc_rec(struct ic_context *ctx,\n \n     const struct icsbrec_service_monitor *ic_rec;\n     ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key,\n-        ctx->icsbrec_service_monitor_by_target_az_logical_port) {\n+        ic->icsbrec_service_monitor_by_target_az_logical_port) {\n         if (db_rec->port == ic_rec->port &&\n             ((db_rec->type && ic_rec->type &&\n               !strcmp(db_rec->type, ic_rec->type)) ||\n@@ -2842,11 +2868,11 @@ lookup_icsb_svc_rec(struct ic_context *ctx,\n }\n \n static void\n-create_service_monitor_data(struct ic_context *ctx,\n+create_service_monitor_data(struct ic_input *ic,\n                             struct sync_service_monitor_data *sync_data)\n {\n-    const struct sbrec_sb_global *ic_sb = sbrec_sb_global_first(\n-                                                ctx->ovnsb_idl);\n+    const struct sbrec_sb_global *ic_sb =\n+        sbrec_sb_global_table_first(ic->sbrec_sb_global_table);\n     const char *svc_monitor_mac = smap_get(&ic_sb->options,\n                                            \"svc_monitor_mac\");\n \n@@ -2855,10 +2881,10 @@ create_service_monitor_data(struct ic_context *ctx,\n     }\n \n     sync_data->prpg_svc_monitor_mac = xstrdup(svc_monitor_mac);\n-    create_pushed_svcs_mon(ctx, &sync_data->pushed_svcs_map);\n-    create_synced_svcs_mon(ctx, &sync_data->synced_svcs_map);\n-    create_local_ic_svcs_map(ctx, &sync_data->local_ic_svcs_map);\n-    create_local_sb_svcs_map(ctx, &sync_data->local_sb_svcs_map);\n+    create_pushed_svcs_mon(ic, &sync_data->pushed_svcs_map);\n+    create_synced_svcs_mon(ic, &sync_data->synced_svcs_map);\n+    create_local_ic_svcs_map(ic, &sync_data->local_ic_svcs_map);\n+    create_local_sb_svcs_map(ic, &sync_data->local_sb_svcs_map);\n }\n \n static void\n@@ -2879,9 +2905,10 @@ destroy_service_monitor_data(struct sync_service_monitor_data *sync_data)\n }\n \n static void\n-sync_service_monitor(struct ic_context *ctx)\n+sync_service_monitor(struct engine_context *ctx,\n+                     struct ic_input *ic)\n {\n-    if (!ctx->ovnisb_txn || !ctx->ovnsb_txn) {\n+    if (!ctx->ovnisb_idl_txn || !ctx->ovnsb_idl_txn) {\n         return;\n     }\n \n@@ -2892,18 +2919,18 @@ sync_service_monitor(struct ic_context *ctx)\n     hmap_init(&sync_data.local_ic_svcs_map);\n     hmap_init(&sync_data.local_sb_svcs_map);\n \n-    create_service_monitor_data(ctx, &sync_data);\n+    create_service_monitor_data(ic, &sync_data);\n \n     struct service_monitor_info *svc_mon;\n     HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &sync_data.pushed_svcs_map) {\n         const struct sbrec_service_monitor *db_rec = svc_mon->db_rec.sb_rec;\n         const struct icsbrec_service_monitor *ic_rec =\n-            lookup_icsb_svc_rec(ctx, svc_mon);\n+            lookup_icsb_svc_rec(ic, svc_mon);\n \n         if (ic_rec) {\n             sbrec_service_monitor_set_status(db_rec, ic_rec->status);\n         } else {\n-            ic_rec = icsbrec_service_monitor_insert(ctx->ovnisb_txn);\n+            ic_rec = icsbrec_service_monitor_insert(ctx->ovnisb_idl_txn);\n             icsbrec_service_monitor_set_type(ic_rec, db_rec->type);\n             icsbrec_service_monitor_set_ip(ic_rec, db_rec->ip);\n             icsbrec_service_monitor_set_port(ic_rec, db_rec->port);\n@@ -2928,13 +2955,13 @@ sync_service_monitor(struct ic_context *ctx)\n         const struct icsbrec_service_monitor *db_rec =\n             svc_mon->db_rec.ic_rec;\n         const struct sbrec_service_monitor *sb_rec =\n-            lookup_sb_svc_rec(ctx, svc_mon);\n+            lookup_sb_svc_rec(ic, svc_mon);\n \n         if (sb_rec) {\n             icsbrec_service_monitor_set_status(svc_mon->db_rec.ic_rec,\n                                                sb_rec->status);\n         } else {\n-            sb_rec = sbrec_service_monitor_insert(ctx->ovnsb_txn);\n+            sb_rec = sbrec_service_monitor_insert(ctx->ovnsb_idl_txn);\n             sbrec_service_monitor_set_type(sb_rec, db_rec->type);\n             sbrec_service_monitor_set_ip(sb_rec, db_rec->ip);\n             sbrec_service_monitor_set_port(sb_rec, db_rec->port);\n@@ -3002,32 +3029,36 @@ sync_service_monitor(struct ic_context *ctx)\n  *    INB:nb_ic_cfg and INB:sb_ic_cfg to INB:nb_ic_cfg.\n  */\n static void\n-update_sequence_numbers(struct ic_context *ctx,\n-                        struct ovsdb_idl_loop *ic_sb_loop)\n-{\n-    if (!ctx->ovnisb_txn || !ctx->ovninb_txn) {\n+update_sequence_numbers(struct ovsdb_idl *ovninb_idl,\n+                        struct ovsdb_idl *ovnisb_idl,\n+                        struct ovsdb_idl_txn *ovninb_txn,\n+                        struct ovsdb_idl_txn *ovnisb_txn,\n+                        struct ovsdb_idl_loop *ic_sb_loop,\n+                        const struct icsbrec_availability_zone *az)\n+{\n+    if (!ovnisb_txn || !ovninb_txn) {\n         return;\n     }\n \n     const struct icnbrec_ic_nb_global *ic_nb = icnbrec_ic_nb_global_first(\n-                                               ctx->ovninb_idl);\n+                                               ovninb_idl);\n     if (!ic_nb) {\n-        ic_nb = icnbrec_ic_nb_global_insert(ctx->ovninb_txn);\n+        ic_nb = icnbrec_ic_nb_global_insert(ovninb_txn);\n     }\n     const struct icsbrec_ic_sb_global *ic_sb = icsbrec_ic_sb_global_first(\n-                                               ctx->ovnisb_idl);\n+                                               ovnisb_idl);\n     if (!ic_sb) {\n-        ic_sb = icsbrec_ic_sb_global_insert(ctx->ovnisb_txn);\n+        ic_sb = icsbrec_ic_sb_global_insert(ovnisb_txn);\n     }\n \n     if ((ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg) &&\n-                          (ic_nb->nb_ic_cfg != ctx->runned_az->nb_ic_cfg)) {\n+                          (ic_nb->nb_ic_cfg != az->nb_ic_cfg)) {\n         /* Deal with potential overflows. */\n-        if (ctx->runned_az->nb_ic_cfg == INT64_MAX) {\n-            icsbrec_availability_zone_set_nb_ic_cfg(ctx->runned_az, 0);\n+        if (az->nb_ic_cfg == INT64_MAX) {\n+            icsbrec_availability_zone_set_nb_ic_cfg(az, 0);\n         }\n         ic_sb_loop->next_cfg = ic_nb->nb_ic_cfg;\n-        ovsdb_idl_txn_increment(ctx->ovnisb_txn, &ctx->runned_az->header_,\n+        ovsdb_idl_txn_increment(ovnisb_txn, &az->header_,\n             &icsbrec_availability_zone_col_nb_ic_cfg, true);\n         return;\n     }\n@@ -3035,22 +3066,22 @@ update_sequence_numbers(struct ic_context *ctx,\n     /* handle cases where accidentally AZ:ic_nb_cfg exceeds\n      * the INB:ic_nb_cfg.\n      */\n-    if (ctx->runned_az->nb_ic_cfg != ic_sb_loop->cur_cfg) {\n-        icsbrec_availability_zone_set_nb_ic_cfg(ctx->runned_az,\n+    if (az->nb_ic_cfg != ic_sb_loop->cur_cfg) {\n+        icsbrec_availability_zone_set_nb_ic_cfg(az,\n                                                 ic_sb_loop->cur_cfg);\n         return;\n     }\n \n     const struct icsbrec_availability_zone *other_az;\n-    ICSBREC_AVAILABILITY_ZONE_FOR_EACH (other_az, ctx->ovnisb_idl) {\n-        if (other_az->nb_ic_cfg != ctx->runned_az->nb_ic_cfg) {\n+    ICSBREC_AVAILABILITY_ZONE_FOR_EACH (other_az, ovnisb_idl) {\n+        if (other_az->nb_ic_cfg != az->nb_ic_cfg) {\n             return;\n         }\n     }\n     /* All the AZs are updated successfully, update SB/NB counter. */\n     if (ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg) {\n-        icsbrec_ic_sb_global_set_nb_ic_cfg(ic_sb, ctx->runned_az->nb_ic_cfg);\n-        icnbrec_ic_nb_global_set_sb_ic_cfg(ic_nb, ctx->runned_az->nb_ic_cfg);\n+        icsbrec_ic_sb_global_set_nb_ic_cfg(ic_sb, az->nb_ic_cfg);\n+        icnbrec_ic_nb_global_set_sb_ic_cfg(ic_nb, az->nb_ic_cfg);\n     }\n }\n \n@@ -3077,23 +3108,18 @@ inc_proc_graph_dump(const char *end_node)\n }\n \n void\n-ovn_db_run(struct ic_context *ctx)\n-{\n-    struct hmap dp_tnlids = HMAP_INITIALIZER(&dp_tnlids);\n-    struct shash isb_ts_dps = SHASH_INITIALIZER(&isb_ts_dps);\n-    struct shash isb_tr_dps = SHASH_INITIALIZER(&isb_tr_dps);\n-\n-    gateway_run(ctx);\n-    enumerate_datapaths(ctx, &dp_tnlids, &isb_ts_dps, &isb_tr_dps);\n-    ts_run(ctx, &dp_tnlids, &isb_ts_dps);\n-    tr_run(ctx, &dp_tnlids, &isb_tr_dps);\n-    port_binding_run(ctx);\n-    route_run(ctx);\n-    sync_service_monitor(ctx);\n-\n-    ovn_destroy_tnlids(&dp_tnlids);\n-    shash_destroy(&isb_ts_dps);\n-    shash_destroy(&isb_tr_dps);\n+ovn_db_run(struct ic_input *input_data,\n+           struct ic_data *ic_data,\n+           struct engine_context *eng_ctx)\n+{\n+    gateway_run(eng_ctx, input_data);\n+    enumerate_datapaths(input_data, &ic_data->dp_tnlids,\n+                        &ic_data->isb_ts_dps, &ic_data->isb_tr_dps);\n+    ts_run(eng_ctx, input_data, &ic_data->dp_tnlids, &ic_data->isb_ts_dps);\n+    tr_run(eng_ctx, input_data, &ic_data->dp_tnlids, &ic_data->isb_tr_dps);\n+    port_binding_run(eng_ctx, input_data);\n+    route_run(eng_ctx, input_data);\n+    sync_service_monitor(eng_ctx, input_data);\n }\n \f\n static void\n@@ -3485,81 +3511,6 @@ main(int argc, char *argv[])\n     ovsdb_idl_track_add_column(ovnsb_idl_loop.idl,\n                                &sbrec_service_monitor_col_options);\n \n-    /* Create IDL indexes */\n-    struct ovsdb_idl_index *nbrec_ls_by_name\n-        = ovsdb_idl_index_create1(ovnnb_idl_loop.idl,\n-                                  &nbrec_logical_switch_col_name);\n-    struct ovsdb_idl_index *nbrec_lr_by_name = ovsdb_idl_index_create1(\n-        ovnnb_idl_loop.idl, &nbrec_logical_router_col_name);\n-    struct ovsdb_idl_index *nbrec_port_by_name\n-        = ovsdb_idl_index_create1(ovnnb_idl_loop.idl,\n-                                  &nbrec_logical_switch_port_col_name);\n-    struct ovsdb_idl_index *nbrec_lrp_by_name\n-        = ovsdb_idl_index_create1(ovnnb_idl_loop.idl,\n-                                  &nbrec_logical_router_port_col_name);\n-    struct ovsdb_idl_index *sbrec_port_binding_by_name\n-        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,\n-                                  &sbrec_port_binding_col_logical_port);\n-    struct ovsdb_idl_index *sbrec_chassis_by_name\n-        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,\n-                                  &sbrec_chassis_col_name);\n-\n-    struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type\n-        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,\n-                                  &sbrec_service_monitor_col_remote);\n-\n-    struct ovsdb_idl_index *sbrec_service_monitor_by_ic_learned\n-        = ovsdb_idl_index_create1(ovnsb_idl_loop.idl,\n-                                  &sbrec_service_monitor_col_ic_learned);\n-\n-    struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type_logical_port\n-        = ovsdb_idl_index_create2(ovnsb_idl_loop.idl,\n-                                  &sbrec_service_monitor_col_remote,\n-                                  &sbrec_service_monitor_col_logical_port);\n-\n-    struct ovsdb_idl_index *icnbrec_transit_switch_by_name\n-        = ovsdb_idl_index_create1(ovninb_idl_loop.idl,\n-                                  &icnbrec_transit_switch_col_name);\n-\n-    struct ovsdb_idl_index *icsbrec_port_binding_by_az\n-        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,\n-                                  &icsbrec_port_binding_col_availability_zone);\n-\n-    struct ovsdb_idl_index *icsbrec_port_binding_by_ts\n-        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,\n-                                  &icsbrec_port_binding_col_transit_switch);\n-\n-    struct ovsdb_idl_index *icsbrec_port_binding_by_ts_az\n-        = ovsdb_idl_index_create2(ovnisb_idl_loop.idl,\n-                                  &icsbrec_port_binding_col_transit_switch,\n-                                  &icsbrec_port_binding_col_availability_zone);\n-\n-    struct ovsdb_idl_index *icsbrec_route_by_az\n-        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,\n-                                  &icsbrec_route_col_availability_zone);\n-\n-    struct ovsdb_idl_index *icsbrec_route_by_ts\n-        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,\n-                                  &icsbrec_route_col_transit_switch);\n-\n-    struct ovsdb_idl_index *icsbrec_route_by_ts_az\n-        = ovsdb_idl_index_create2(ovnisb_idl_loop.idl,\n-                                  &icsbrec_route_col_transit_switch,\n-                                  &icsbrec_route_col_availability_zone);\n-\n-    struct ovsdb_idl_index *icsbrec_service_monitor_by_source_az\n-        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,\n-            &icsbrec_service_monitor_col_source_availability_zone);\n-\n-    struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az\n-        = ovsdb_idl_index_create1(ovnisb_idl_loop.idl,\n-            &icsbrec_service_monitor_col_target_availability_zone);\n-\n-    struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az_logical_port\n-        = ovsdb_idl_index_create2(ovnisb_idl_loop.idl,\n-            &icsbrec_service_monitor_col_target_availability_zone,\n-            &icsbrec_service_monitor_col_logical_port);\n-\n     unixctl_command_register(\"nb-connection-status\", \"\", 0, 0,\n                              ovn_conn_show, ovnnb_idl_loop.idl);\n     unixctl_command_register(\"sb-connection-status\", \"\", 0, 0,\n@@ -3569,6 +3520,9 @@ main(int argc, char *argv[])\n     unixctl_command_register(\"ic-sb-connection-status\", \"\", 0, 0,\n                              ovn_conn_show, ovnisb_idl_loop.idl);\n \n+    stopwatch_create(OVN_IC_LOOP_STOPWATCH_NAME, SW_MS);\n+    stopwatch_create(IC_OVN_DB_RUN_STOPWATCH_NAME, SW_MS);\n+\n     /* Initialize incremental processing engine for ovn-northd */\n     inc_proc_ic_init(&ovnnb_idl_loop, &ovnsb_idl_loop,\n                      &ovninb_idl_loop, &ovnisb_idl_loop);\n@@ -3662,67 +3616,43 @@ main(int argc, char *argv[])\n                 ovnisb_cond_seqno = new_ovnisb_cond_seqno;\n             }\n \n-            struct ic_context ctx = {\n-                .ovnnb_idl = ovnnb_idl_loop.idl,\n-                .ovnnb_txn = ovnnb_txn,\n-                .ovnsb_idl = ovnsb_idl_loop.idl,\n-                .ovnsb_txn = ovnsb_txn,\n-                .ovninb_idl = ovninb_idl_loop.idl,\n-                .ovninb_txn = ovninb_txn,\n-                .ovnisb_idl = ovnisb_idl_loop.idl,\n-                .ovnisb_txn = ovnisb_txn,\n-                .nbrec_ls_by_name = nbrec_ls_by_name,\n-                .nbrec_lr_by_name = nbrec_lr_by_name,\n-                .nbrec_lrp_by_name = nbrec_lrp_by_name,\n-                .nbrec_port_by_name = nbrec_port_by_name,\n-                .sbrec_port_binding_by_name = sbrec_port_binding_by_name,\n-                .sbrec_chassis_by_name = sbrec_chassis_by_name,\n-                .sbrec_service_monitor_by_remote_type =\n-                    sbrec_service_monitor_by_remote_type,\n-                .sbrec_service_monitor_by_ic_learned =\n-                    sbrec_service_monitor_by_ic_learned,\n-                .sbrec_service_monitor_by_remote_type_logical_port =\n-                    sbrec_service_monitor_by_remote_type_logical_port,\n-                .icnbrec_transit_switch_by_name =\n-                    icnbrec_transit_switch_by_name,\n-                .icsbrec_port_binding_by_az = icsbrec_port_binding_by_az,\n-                .icsbrec_port_binding_by_ts = icsbrec_port_binding_by_ts,\n-                .icsbrec_port_binding_by_ts_az = icsbrec_port_binding_by_ts_az,\n-                .icsbrec_route_by_az = icsbrec_route_by_az,\n-                .icsbrec_route_by_ts = icsbrec_route_by_ts,\n-                .icsbrec_route_by_ts_az = icsbrec_route_by_ts_az,\n-                .icsbrec_service_monitor_by_source_az =\n-                    icsbrec_service_monitor_by_source_az,\n-                .icsbrec_service_monitor_by_target_az =\n-                    icsbrec_service_monitor_by_target_az,\n-                .icsbrec_service_monitor_by_target_az_logical_port =\n-                    icsbrec_service_monitor_by_target_az_logical_port,\n-            };\n-\n-            if (!state.had_lock && ovsdb_idl_has_lock(ctx.ovnsb_idl)) {\n+            if (!state.had_lock && ovsdb_idl_has_lock(ovnsb_idl_loop.idl)) {\n                 VLOG_INFO(\"ovn-ic lock acquired. \"\n                             \"This ovn-ic instance is now active.\");\n                 state.had_lock = true;\n             } else if (state.had_lock &&\n-                       !ovsdb_idl_has_lock(ctx.ovnsb_idl)) {\n+                       !ovsdb_idl_has_lock(ovnsb_idl_loop.idl)) {\n                 VLOG_INFO(\"ovn-ic lock lost. \"\n                             \"This ovn-ic instance is now on standby.\");\n                 state.had_lock = false;\n             }\n \n-            if (ovsdb_idl_has_lock(ctx.ovnsb_idl) &&\n-                ovsdb_idl_has_ever_connected(ctx.ovnnb_idl) &&\n-                ovsdb_idl_has_ever_connected(ctx.ovnsb_idl) &&\n-                ovsdb_idl_has_ever_connected(ctx.ovninb_idl) &&\n-                ovsdb_idl_has_ever_connected(ctx.ovnisb_idl)) {\n-                if (ctx.ovnnb_txn && ctx.ovnsb_txn && ctx.ovninb_txn &&\n-                    ctx.ovnisb_txn && inc_proc_ic_can_run(&eng_ctx)) {\n-                    ctx.runned_az = az_run(&ctx);\n-                    VLOG_DBG(\"Availability zone: %s\", ctx.runned_az ?\n-                             ctx.runned_az->name : \"not created yet.\");\n-                    if (ctx.runned_az) {\n-                        (void) inc_proc_ic_run(&ctx, &eng_ctx);\n-                        update_sequence_numbers(&ctx, &ovnisb_idl_loop);\n+            if (ovsdb_idl_has_lock(ovnsb_idl_loop.idl) &&\n+                ovsdb_idl_has_ever_connected(ovnnb_idl_loop.idl) &&\n+                ovsdb_idl_has_ever_connected(ovnsb_idl_loop.idl) &&\n+                ovsdb_idl_has_ever_connected(ovninb_idl_loop.idl) &&\n+                ovsdb_idl_has_ever_connected(ovnisb_idl_loop.idl)) {\n+                if (ovnnb_txn && ovnsb_txn && ovninb_txn &&\n+                    ovnisb_txn && inc_proc_ic_can_run(&eng_ctx)) {\n+                    const struct icsbrec_availability_zone *az =\n+                        az_run(ovnnb_idl_loop.idl,\n+                               ovnisb_idl_loop.idl,\n+                               ovnisb_txn);\n+                    VLOG_DBG(\"Availability zone: %s\", az ?\n+                             az->name : \"not created yet.\");\n+                    if (az) {\n+                        (void) inc_proc_ic_run(ovnnb_txn,\n+                                               ovnsb_txn,\n+                                               ovninb_txn,\n+                                               ovnisb_txn,\n+                                               &eng_ctx,\n+                                               az);\n+                        update_sequence_numbers(ovninb_idl_loop.idl,\n+                                                ovnisb_idl_loop.idl,\n+                                                ovninb_txn,\n+                                                ovnisb_txn,\n+                                                &ovnisb_idl_loop,\n+                                                az);\n                     }\n                 } else if (!inc_proc_ic_get_force_recompute()) {\n                     clear_idl_track = false;\n@@ -3812,10 +3742,12 @@ main(int argc, char *argv[])\n             poll_immediate_wake();\n         }\n \n+        stopwatch_stop(NORTHD_LOOP_STOPWATCH_NAME, time_msec());\n         poll_block();\n         if (should_service_stop()) {\n             exiting = true;\n         }\n+        stopwatch_start(NORTHD_LOOP_STOPWATCH_NAME, time_msec());\n     }\n     inc_proc_ic_cleanup();\n \n@@ -3885,8 +3817,8 @@ ovn_ic_status(struct unixctl_conn *conn, int argc OVS_UNUSED,\n     }\n \n     /*\n-     * Use a labelled formatted output so we can add more to the status command\n-     * later without breaking any consuming scripts\n+     * Use a labelled formatted output so we can add more to the status\n+     * command later without breaking any consuming scripts\n      */\n     struct ds s = DS_EMPTY_INITIALIZER;\n     ds_put_format(&s, \"Status: %s\\n\", status);\ndiff --git a/ic/ovn-ic.h b/ic/ovn-ic.h\nindex e8d7a970f..2c2efc046 100644\n--- a/ic/ovn-ic.h\n+++ b/ic/ovn-ic.h\n@@ -16,16 +16,33 @@\n \n #include \"ovsdb-idl.h\"\n #include \"unixctl.h\"\n+#include \"lib/inc-proc-eng.h\"\n \n-struct ic_context {\n-    struct ovsdb_idl *ovnnb_idl;\n-    struct ovsdb_idl *ovnsb_idl;\n-    struct ovsdb_idl *ovninb_idl;\n-    struct ovsdb_idl *ovnisb_idl;\n-    struct ovsdb_idl_txn *ovnnb_txn;\n-    struct ovsdb_idl_txn *ovnsb_txn;\n-    struct ovsdb_idl_txn *ovninb_txn;\n-    struct ovsdb_idl_txn *ovnisb_txn;\n+struct ic_input {\n+    /* Northbound table references */\n+    const struct nbrec_logical_switch_table *nbrec_logical_switch_table;\n+    const struct nbrec_logical_router_table *nbrec_logical_router_table;\n+    const struct nbrec_nb_global_table *nbrec_nb_global_table;\n+\n+    /* Southbound table references */\n+    const struct sbrec_chassis_table *sbrec_chassis_table;\n+    const struct sbrec_sb_global_table *sbrec_sb_global_table;\n+\n+    /* InterconnectNorthbound table references */\n+    const struct icnbrec_transit_switch_table *icnbrec_transit_switch_table;\n+    const struct icnbrec_ic_nb_global_table *icnbrec_ic_nb_global_table;\n+    const struct icnbrec_transit_router_table *icnbrec_transit_router_table;\n+\n+    /* InterconnectSouthbound table references */\n+    const struct icsbrec_encap_table *icsbrec_encap_table;\n+    const struct icsbrec_gateway_table *icsbrec_gateway_table;\n+    const struct icsbrec_ic_sb_global_table *icsbrec_ic_sb_global_table;\n+    const struct icsbrec_datapath_binding_table\n+        *icsbrec_datapath_binding_table;\n+    const struct icsbrec_availability_zone_table\n+        *icsbrec_availability_zone_table;\n+\n+    /* Indexes */\n     const struct icsbrec_availability_zone *runned_az;\n     struct ovsdb_idl_index *nbrec_ls_by_name;\n     struct ovsdb_idl_index *nbrec_lr_by_name;\n@@ -48,6 +65,12 @@ struct ic_context {\n     struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az_logical_port;\n };\n \n+struct ic_data {\n+    /* Global state for 'en-ic'. */\n+    struct hmap dp_tnlids;\n+    struct shash isb_ts_dps;\n+    struct shash isb_tr_dps;\n+};\n struct ic_state {\n     bool had_lock;\n     bool paused;\n@@ -56,6 +79,13 @@ struct ic_state {\n enum ic_datapath_type { IC_SWITCH, IC_ROUTER, IC_DATAPATH_MAX };\n enum ic_port_binding_type { IC_SWITCH_PORT, IC_ROUTER_PORT, IC_PORT_MAX };\n \n-void ovn_db_run(struct ic_context *ctx);\n+const struct icsbrec_availability_zone *\n+    az_run(struct ovsdb_idl *ovnnb_idl,\n+           struct ovsdb_idl *ovnisb_idl,\n+           struct ovsdb_idl_txn *ovnisb_idl_txn);\n+\n+void ovn_db_run(struct ic_input *input_data,\n+                struct ic_data *ic_data,\n+                struct engine_context *eng_ctx);\n \n #endif /* OVN_IC_H */\ndiff --git a/lib/stopwatch-names.h b/lib/stopwatch-names.h\nindex b912e813c..5f1091155 100644\n--- a/lib/stopwatch-names.h\n+++ b/lib/stopwatch-names.h\n@@ -40,4 +40,7 @@\n #define DYNAMIC_ROUTES_RUN_STOPWATCH_NAME \"dynamic_routes\"\n #define GROUP_ECMP_ROUTE_RUN_STOPWATCH_NAME \"group_ecmp_route\"\n \n+#define OVN_IC_LOOP_STOPWATCH_NAME \"ovn-ic-loop\"\n+#define IC_OVN_DB_RUN_STOPWATCH_NAME \"ovn_db_run\"\n+\n #endif\n",
    "prefixes": [
        "ovs-dev",
        "v0",
        "1/9"
    ]
}