get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2186655,
    "url": "http://patchwork.ozlabs.org/api/1.0/patches/2186655/?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-6-guilherme.paulo@luizalabs.com>",
    "date": "2026-01-20T11:49:44",
    "name": "[ovs-dev,v0,5/9] ovn-ic: Add a new engine-node 'gateway'.",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "ae6448b23380186fee96d666804fe98bbbceaf17",
    "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-6-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/2186655/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=LN9NlkAk;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=140.211.166.138; helo=smtp1.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)",
            "smtp1.osuosl.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key)\n header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256\n header.s=google header.b=LN9NlkAk",
            "smtp1.osuosl.org; dmarc=pass (p=quarantine dis=none)\n header.from=luizalabs.com"
        ],
        "Received": [
            "from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138])\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 4dwQd338Q1z1xsW\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 20 Jan 2026 22:50:47 +1100 (AEDT)",
            "from localhost (localhost [127.0.0.1])\n\tby smtp1.osuosl.org (Postfix) with ESMTP id B842D859B3;\n\tTue, 20 Jan 2026 11:50:45 +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 mbIpMf5QA35B; Tue, 20 Jan 2026 11:50:38 +0000 (UTC)",
            "from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])\n\tby smtp1.osuosl.org (Postfix) with ESMTPS id 0EEC58599B;\n\tTue, 20 Jan 2026 11:50:37 +0000 (UTC)",
            "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id E2321C02A6;\n\tTue, 20 Jan 2026 11:50:36 +0000 (UTC)",
            "from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 2D063C04FD\n for <dev@openvswitch.org>; Tue, 20 Jan 2026 11:50:34 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n by smtp1.osuosl.org (Postfix) with ESMTP id 8973C8598D\n for <dev@openvswitch.org>; Tue, 20 Jan 2026 11:50:28 +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 wmRD01RecnW5 for <dev@openvswitch.org>;\n Tue, 20 Jan 2026 11:50:27 +0000 (UTC)",
            "from mail-dl1-x122d.google.com (mail-dl1-x122d.google.com\n [IPv6:2607:f8b0:4864:20::122d])\n by smtp1.osuosl.org (Postfix) with ESMTPS id E82F985989\n for <dev@openvswitch.org>; Tue, 20 Jan 2026 11:50:26 +0000 (UTC)",
            "by mail-dl1-x122d.google.com with SMTP id\n a92af1059eb24-1233bc1117fso3249242c88.0\n for <dev@openvswitch.org>; Tue, 20 Jan 2026 03:50:26 -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.23\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 20 Jan 2026 03:50:24 -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 smtp1.osuosl.org 0EEC58599B",
            "OpenDKIM Filter v2.11.0 smtp1.osuosl.org E82F985989"
        ],
        "Received-SPF": "Pass (mailfrom) identity=mailfrom;\n client-ip=2607:f8b0:4864:20::122d; helo=mail-dl1-x122d.google.com;\n envelope-from=guilherme.paulo@luizalabs.com; receiver=<UNKNOWN>",
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 smtp1.osuosl.org E82F985989",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=luizalabs.com; s=google; t=1768909826; x=1769514626; 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=lYah72RmS/HB8CdT5/p+oEGuRfSUfHoOw11ak5n3ewM=;\n b=LN9NlkAkNN6xCF/gqRU7T+RoUJBCJPexsttf4ECcThVU0e5qGaae7n7K8+vElp162O\n gRNQeOVriYnRlpQ5Urt82xkn4glXecQosi6c7bPy8qlb6zwRDfF91pAbiwlRrHe80EHu\n Sam337HFhEIMRHw4PmmPU0SvKkBzMJgso58ms=",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1768909826; x=1769514626;\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=lYah72RmS/HB8CdT5/p+oEGuRfSUfHoOw11ak5n3ewM=;\n b=cwyqOTWxH9Uiqd3cRFg1iZKy5l30D4UUtARydG0Buw7wMDySkkFzsxl6Vqnll61ozl\n KlvURw5037h3B2eFuOndu/oLC26uCHwHuhgxTecmD5GWZe98LjyStxAhYkReWf75Xopd\n CMhAyboIZVAtIjs9mYdK1y2NuPzvD8zN/h80P4Nrjg6yulA5wjhmoa6LDaxR3qIMUeoo\n nBR262TwuAPVV4gDrirj5AfRIgaIOeUnsgHr+S4d0j3p+7azfP3OnVcoObqgs2D1BTRE\n y7t+Q0UXQNOm+ZKnerIH39c5m9pXgvvnKhOynux54IPma6urzNlua8TeomUc9S/sSwH4\n 8DzA==",
        "X-Gm-Message-State": "AOJu0YxMxxsyrtvAAdTkMUb2OAcf7UkHJLFbkxXy33qr3oQ/7l4saVjF\n jgTZY5ttHuXgF5vpwAOXow6xEdKBNGTZu2Xkedaxa8aVLDKez9ZI2mpKzWCklNl/BtzVdyGIB4h\n ShoJEMGPPR07bnxNFq5hz3f7Dyjk7+826YbU9De/sxIJ98e8YZVHKAUwgzdGX",
        "X-Gm-Gg": "AZuq6aKJUPeEyiHM/ItylzbM3L/xcBPf1uxCcXAzXXmgo+fbLs6Dubi0S3ITR0HCNEZ\n Re12eZtODLlEifSO2tVQk4B69XTcKvVML5I6DgS2EO9ITzAYkFROq9gNgSxNQMGsblEEVNf+xPx\n +zqoQixkGolpwkTmXaqi7hlC4LTkUmn2JdgIgaX6sYdQM1fsc+pweClNA9lkZUFQ+kYMGmnHfUX\n kJJcC0PSXkI27TenM27Y+NBwBi/CLolToKoBRygXBvwhoT5kR+fyLZly7KScEtnxbIrki1zpWs6\n lu3pMQGEsywsDk8nM5MBtpz236FHJ1qoBWd681jD+xb8SuyFl2q4gTsegch7VXoyAFQbo679GxC\n I8+IC4MX1Ecjqy1pfXevilZpE11qtYPVq0x/zM0SNXdGbZ/oqGJ6mTxAhdF85BoAdkXTL/wGN/i\n yzy2Rcd2hxIWqZF7CxeS+jn+p2y7xR8cVbkA61kQ==",
        "X-Received": "by 2002:a05:7300:fd02:b0:2ac:3383:357e with SMTP id\n 5a478bee46e88-2b66434d120mr12350719eec.19.1768909825252;\n Tue, 20 Jan 2026 03:50:25 -0800 (PST)",
        "To": "dev@openvswitch.org",
        "Date": "Tue, 20 Jan 2026 08:49:44 -0300",
        "Message-Id": "<20260120114948.2289909-6-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 5/9] ovn-ic: Add a new engine-node\n 'gateway'.",
        "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": "This new engine now maintains the gateway related data for ovn-ic\ndaemon which was earlier maintained by the ic engine node invoked\nthe gateway_run() function. The inputs to this engine node are:\n   en_icsb_gateway;\n   en_sb_chassis;\n\nIn order to achieve this, we refactor in the following way:\n* Introduce gateway_init() which initializes this data.\n* Introduce gateway_destroy() which clears this data for a new iteration.\n* Introduce gateway_run() which invokes the full recompute of the engine.\n\nThis engine node becomes an input to 'ic' node.\n\nSigned-off-by: Paulo Guilherme Silva <guilherme.paulo@luizalabs.com>\n---\n ic/automake.mk        |   2 +\n ic/en-gateway.c       | 268 ++++++++++++++++++++++++++++++++++++++++++\n ic/en-gateway.h       |  28 +++++\n ic/en-ic.c            |   2 -\n ic/inc-proc-ic.c      |   7 +-\n ic/ovn-ic.c           | 149 +----------------------\n ic/ovn-ic.h           |   1 -\n lib/stopwatch-names.h |   1 +\n 8 files changed, 306 insertions(+), 152 deletions(-)\n create mode 100644 ic/en-gateway.c\n create mode 100644 ic/en-gateway.h",
    "diff": "diff --git a/ic/automake.mk b/ic/automake.mk\nindex 24807a360..1fca1eb38 100644\n--- a/ic/automake.mk\n+++ b/ic/automake.mk\n@@ -4,6 +4,8 @@ ic_ovn_ic_SOURCES = ic/ovn-ic.c \\\n \tic/ovn-ic.h \\\n \tic/en-ic.c \\\n \tic/en-ic.h \\\n+\tic/en-gateway.c \\\n+\tic/en-gateway.h \\\n \tic/en-enum-datapaths.c \\\n \tic/en-enum-datapaths.h \\\n \tic/en-port-binding.c \\\ndiff --git a/ic/en-gateway.c b/ic/en-gateway.c\nnew file mode 100644\nindex 000000000..d0eb77564\n--- /dev/null\n+++ b/ic/en-gateway.c\n@@ -0,0 +1,268 @@\n+/*\n+ * Licensed under the Apache License, Version 2.0 (the \"License\");\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at:\n+ *\n+ *     http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+*/\n+\n+#include <config.h>\n+\n+#include <getopt.h>\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-gateway.h\"\n+#include \"inc-proc-ic.h\"\n+#include \"lib/inc-proc-eng.h\"\n+#include \"lib/ovn-sb-idl.h\"\n+#include \"lib/ovn-ic-sb-idl.h\"\n+#include \"lib/ovn-util.h\"\n+#include \"lib/stopwatch-names.h\"\n+#include \"coverage.h\"\n+#include \"stopwatch.h\"\n+#include \"stopwatch-names.h\"\n+\n+VLOG_DEFINE_THIS_MODULE(gateway);\n+COVERAGE_DEFINE(gateway_run);\n+\n+static void\n+gateway_run(const struct engine_context *eng_ctx,\n+            struct gateway_input *gateway_input,\n+            struct ed_type_gateway *gateway_data,\n+            const struct icsbrec_gateway_table *icsb_gateway_table,\n+            const struct sbrec_chassis_table *sb_chassis_table);\n+static void gateway_init(struct ed_type_gateway *data);\n+static void gateway_destroy(struct ed_type_gateway *data);\n+static void gateway_clear(struct ed_type_gateway *data);\n+static void\n+sync_sb_gw_to_isb(const struct engine_context *ctx,\n+                  const struct sbrec_chassis *chassis,\n+                  const struct icsbrec_gateway *gw);\n+static void\n+sync_isb_gw_to_sb(const struct engine_context *ctx,\n+                  const struct icsbrec_gateway *gw,\n+                  const struct sbrec_chassis *chassis);\n+static bool\n+is_gateway_data_changed(const struct icsbrec_gateway *gw,\n+                        const struct sbrec_chassis *chassis);\n+\n+enum engine_node_state\n+en_gateway_run(struct engine_node *node, void *data)\n+{\n+    const struct engine_context *eng_ctx = engine_get_context();\n+    struct ed_type_gateway *gateway_data = data;\n+    struct gateway_input gateway_input;\n+\n+    gateway_clear(gateway_data);\n+\n+    const struct icsbrec_gateway_table *icsb_gateway_table =\n+        EN_OVSDB_GET(engine_get_input(\"ICSB_gateway\", node));\n+    const struct sbrec_chassis_table *sb_chassis_table =\n+        EN_OVSDB_GET(engine_get_input(\"SB_chassis\", node));\n+\n+    gateway_input.runned_az = eng_ctx->client_ctx;\n+\n+    COVERAGE_INC(gateway_run);\n+    stopwatch_start(OVN_IC_GATEWAY_RUN_STOPWATCH_NAME, time_usec());\n+    gateway_run(eng_ctx, &gateway_input, gateway_data, icsb_gateway_table,\n+                sb_chassis_table);\n+    stopwatch_stop(OVN_IC_GATEWAY_RUN_STOPWATCH_NAME, time_usec());\n+\n+    return EN_UPDATED;\n+}\n+\n+void *\n+en_gateway_init(struct engine_node *node OVS_UNUSED,\n+                struct engine_arg *arg OVS_UNUSED)\n+{\n+    struct ed_type_gateway *data = xzalloc(sizeof *data);\n+    gateway_init(data);\n+    return data;\n+}\n+\n+void\n+en_gateway_cleanup(void *data)\n+{\n+    gateway_destroy(data);\n+}\n+\n+static void\n+gateway_init(struct ed_type_gateway *data)\n+{\n+    shash_init(&data->local_gws);\n+    shash_init(&data->remote_gws);\n+}\n+\n+static void\n+gateway_destroy(struct ed_type_gateway *data)\n+{\n+    gateway_clear(data);\n+\n+    shash_destroy(&data->local_gws);\n+    shash_destroy(&data->remote_gws);\n+}\n+\n+static void\n+gateway_clear(struct ed_type_gateway *data)\n+{\n+    shash_clear(&data->local_gws);\n+    shash_clear(&data->remote_gws);\n+}\n+\n+static void\n+gateway_run(const struct engine_context *eng_ctx,\n+            struct gateway_input *gw_input,\n+            struct ed_type_gateway *gw_data,\n+            const struct icsbrec_gateway_table *icsb_gateway_table,\n+            const struct sbrec_chassis_table *sb_chassis_table)\n+{\n+    if (!eng_ctx->ovnisb_idl_txn || !eng_ctx->ovnsb_idl_txn) {\n+        return;\n+    }\n+\n+    const struct icsbrec_gateway *gw;\n+    ICSBREC_GATEWAY_TABLE_FOR_EACH (gw, icsb_gateway_table) {\n+        if (gw->availability_zone == gw_input->runned_az) {\n+            shash_add(&gw_data->local_gws, gw->name, gw);\n+        } else {\n+            shash_add(&gw_data->remote_gws, gw->name, gw);\n+        }\n+    }\n+\n+    const struct sbrec_chassis *chassis;\n+    SBREC_CHASSIS_TABLE_FOR_EACH (chassis, sb_chassis_table) {\n+        if (smap_get_bool(&chassis->other_config, \"is-interconn\", false)) {\n+            gw = shash_find_and_delete(&gw_data->local_gws, chassis->name);\n+            if (!gw) {\n+                gw = icsbrec_gateway_insert(eng_ctx->ovnisb_idl_txn);\n+                icsbrec_gateway_set_availability_zone(gw, gw_input->runned_az);\n+                icsbrec_gateway_set_name(gw, chassis->name);\n+                sync_sb_gw_to_isb(eng_ctx, chassis, gw);\n+            } else if (is_gateway_data_changed(gw, chassis)) {\n+                sync_sb_gw_to_isb(eng_ctx, chassis, gw);\n+            }\n+        } else if (smap_get_bool(&chassis->other_config, \"is-remote\", false)) {\n+            gw = shash_find_and_delete(&gw_data->remote_gws, chassis->name);\n+            if (!gw) {\n+                sbrec_chassis_delete(chassis);\n+            } else if (is_gateway_data_changed(gw, chassis)) {\n+                sync_isb_gw_to_sb(eng_ctx, gw, chassis);\n+            }\n+        }\n+    }\n+\n+    /* Delete extra gateways from ISB for the local AZ */\n+    struct shash_node *node;\n+    SHASH_FOR_EACH (node, &gw_data->local_gws) {\n+        icsbrec_gateway_delete(node->data);\n+    }\n+\n+    /* Create SB chassis for remote gateways in ISB */\n+    SHASH_FOR_EACH (node, &gw_data->remote_gws) {\n+        gw = node->data;\n+        chassis = sbrec_chassis_insert(eng_ctx->ovnsb_idl_txn);\n+        sbrec_chassis_set_name(chassis, gw->name);\n+        sync_isb_gw_to_sb(eng_ctx, gw, chassis);\n+    }\n+}\n+\n+/* Returns true if any information in gw and chassis is different. */\n+static bool\n+is_gateway_data_changed(const struct icsbrec_gateway *gw,\n+                        const struct sbrec_chassis *chassis)\n+{\n+    if (strcmp(gw->hostname, chassis->hostname)) {\n+        return true;\n+    }\n+\n+    if (gw->n_encaps != chassis->n_encaps) {\n+        return true;\n+    }\n+\n+    for (int g = 0; g < gw->n_encaps; g++) {\n+\n+        bool found = false;\n+        const struct icsbrec_encap *gw_encap = gw->encaps[g];\n+        for (int s = 0; s < chassis->n_encaps; s++) {\n+            const struct sbrec_encap *chassis_encap = chassis->encaps[s];\n+            if (!strcmp(gw_encap->type, chassis_encap->type) &&\n+                !strcmp(gw_encap->ip, chassis_encap->ip)) {\n+                found = true;\n+                if (!smap_equal(&gw_encap->options, &chassis_encap->options)) {\n+                    return true;\n+                }\n+                break;\n+            }\n+        }\n+        if (!found) {\n+            return true;\n+        }\n+    }\n+\n+    return false;\n+}\n+\n+static void\n+sync_isb_gw_to_sb(const struct engine_context *ctx,\n+                  const struct icsbrec_gateway *gw,\n+                  const struct sbrec_chassis *chassis)\n+{\n+    sbrec_chassis_set_hostname(chassis, gw->hostname);\n+    sbrec_chassis_update_other_config_setkey(chassis, \"is-remote\", \"true\");\n+\n+    /* Sync encaps used by this gateway. */\n+    ovs_assert(gw->n_encaps);\n+    struct sbrec_encap *sb_encap;\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_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+        sbrec_encap_set_options(sb_encap, &gw->encaps[i]->options);\n+        sb_encaps[i] = sb_encap;\n+    }\n+    sbrec_chassis_set_encaps(chassis, sb_encaps, gw->n_encaps);\n+    free(sb_encaps);\n+}\n+\n+static void\n+sync_sb_gw_to_isb(const struct engine_context *ctx,\n+                  const struct sbrec_chassis *chassis,\n+                  const struct icsbrec_gateway *gw)\n+{\n+    icsbrec_gateway_set_hostname(gw, chassis->hostname);\n+\n+    /* Sync encaps used by this chassis. */\n+    ovs_assert(chassis->n_encaps);\n+    struct icsbrec_encap *isb_encap;\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_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+        icsbrec_encap_set_type(isb_encap,\n+                              chassis->encaps[i]->type);\n+        icsbrec_encap_set_options(isb_encap,\n+                                 &chassis->encaps[i]->options);\n+        isb_encaps[i] = isb_encap;\n+    }\n+    icsbrec_gateway_set_encaps(gw, isb_encaps,\n+                              chassis->n_encaps);\n+    free(isb_encaps);\n+}\ndiff --git a/ic/en-gateway.h b/ic/en-gateway.h\nnew file mode 100644\nindex 000000000..9010d27f4\n--- /dev/null\n+++ b/ic/en-gateway.h\n@@ -0,0 +1,28 @@\n+#ifndef EN_IC_GATEWAY_H\n+#define EN_IC_GATEWAY_H 1\n+\n+#include <config.h>\n+\n+#include <stdbool.h>\n+#include <getopt.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+\n+/* OVN includes. */\n+#include \"lib/inc-proc-eng.h\"\n+\n+struct ed_type_gateway {\n+    struct shash local_gws;\n+    struct shash remote_gws;\n+};\n+\n+struct gateway_input {\n+    /* Indexes */\n+    const struct icsbrec_availability_zone *runned_az;\n+};\n+\n+void *en_gateway_init(struct engine_node *, struct engine_arg *);\n+enum engine_node_state en_gateway_run(struct engine_node *, void *data);\n+void en_gateway_cleanup(void *data);\n+\n+#endif\ndiff --git a/ic/en-ic.c b/ic/en-ic.c\nindex e0956bdee..af240c20a 100644\n--- a/ic/en-ic.c\n+++ b/ic/en-ic.c\n@@ -64,8 +64,6 @@ ic_get_input_data(struct engine_node *node,\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 \ndiff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c\nindex 7399dbd57..dc625d759 100644\n--- a/ic/inc-proc-ic.c\n+++ b/ic/inc-proc-ic.c\n@@ -27,6 +27,7 @@\n #include \"openvswitch/vlog.h\"\n #include \"inc-proc-ic.h\"\n #include \"en-ic.h\"\n+#include \"en-gateway.h\"\n #include \"en-enum-datapaths.h\"\n #include \"en-port-binding.h\"\n #include \"en-route.h\"\n@@ -161,6 +162,7 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_ic);\n /* Define engine nodes for other nodes. They should be defined as static to\n  * avoid sparse errors. */\n static ENGINE_NODE(ic, SB_WRITE);\n+static ENGINE_NODE(gateway, SB_WRITE);\n static ENGINE_NODE(enum_datapaths);\n static ENGINE_NODE(port_binding, SB_WRITE);\n static ENGINE_NODE(route);\n@@ -172,6 +174,9 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,\n {\n     /* Define relationships between nodes where first argument is dependent\n      * on the second argument */\n+    engine_add_input(&en_gateway, &en_icsb_gateway, NULL);\n+    engine_add_input(&en_gateway, &en_sb_chassis, NULL);\n+\n     engine_add_input(&en_enum_datapaths, &en_icnb_transit_switch, NULL);\n     engine_add_input(&en_enum_datapaths, &en_icsb_datapath_binding, NULL);\n \n@@ -191,6 +196,7 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,\n     engine_add_input(&en_route, &en_icsb_route, NULL);\n     engine_add_input(&en_route, &en_nb_logical_router_static_route, NULL);\n \n+    engine_add_input(&en_ic, &en_gateway, NULL);\n     engine_add_input(&en_ic, &en_enum_datapaths, NULL);\n     engine_add_input(&en_ic, &en_port_binding, NULL);\n     engine_add_input(&en_ic, &en_route, NULL);\n@@ -219,7 +225,6 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,\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_gateway, NULL);\n     engine_add_input(&en_ic, &en_icsb_datapath_binding, NULL);\n \n     struct engine_arg engine_arg = {\ndiff --git a/ic/ovn-ic.c b/ic/ovn-ic.c\nindex c880244e2..ffd814846 100644\n--- a/ic/ovn-ic.c\n+++ b/ic/ovn-ic.c\n@@ -429,153 +429,6 @@ tr_run(struct engine_context *ctx,\n     }\n }\n \n-/* Returns true if any information in gw and chassis is different. */\n-static bool\n-is_gateway_data_changed(const struct icsbrec_gateway *gw,\n-                   const struct sbrec_chassis *chassis)\n-{\n-    if (strcmp(gw->hostname, chassis->hostname)) {\n-        return true;\n-    }\n-\n-    if (gw->n_encaps != chassis->n_encaps) {\n-        return true;\n-    }\n-\n-    for (int g = 0; g < gw->n_encaps; g++) {\n-\n-        bool found = false;\n-        const struct icsbrec_encap *gw_encap = gw->encaps[g];\n-        for (int s = 0; s < chassis->n_encaps; s++) {\n-            const struct sbrec_encap *chassis_encap = chassis->encaps[s];\n-            if (!strcmp(gw_encap->type, chassis_encap->type) &&\n-                !strcmp(gw_encap->ip, chassis_encap->ip)) {\n-                found = true;\n-                if (!smap_equal(&gw_encap->options, &chassis_encap->options)) {\n-                    return true;\n-                }\n-                break;\n-            }\n-        }\n-        if (!found) {\n-            return true;\n-        }\n-    }\n-\n-    return false;\n-}\n-\n-static void\n-sync_isb_gw_to_sb(struct engine_context *ctx,\n-                  const struct icsbrec_gateway *gw,\n-                  const struct sbrec_chassis *chassis)\n-{\n-    sbrec_chassis_set_hostname(chassis, gw->hostname);\n-    sbrec_chassis_update_other_config_setkey(chassis, \"is-remote\", \"true\");\n-\n-    /* Sync encaps used by this gateway. */\n-    ovs_assert(gw->n_encaps);\n-    struct sbrec_encap *sb_encap;\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_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-        sbrec_encap_set_options(sb_encap, &gw->encaps[i]->options);\n-        sb_encaps[i] = sb_encap;\n-    }\n-    sbrec_chassis_set_encaps(chassis, sb_encaps, gw->n_encaps);\n-    free(sb_encaps);\n-}\n-\n-static void\n-sync_sb_gw_to_isb(struct engine_context *ctx,\n-                  const struct sbrec_chassis *chassis,\n-                  const struct icsbrec_gateway *gw)\n-{\n-    icsbrec_gateway_set_hostname(gw, chassis->hostname);\n-\n-    /* Sync encaps used by this chassis. */\n-    ovs_assert(chassis->n_encaps);\n-    struct icsbrec_encap *isb_encap;\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_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-        icsbrec_encap_set_type(isb_encap,\n-                              chassis->encaps[i]->type);\n-        icsbrec_encap_set_options(isb_encap,\n-                                 &chassis->encaps[i]->options);\n-        isb_encaps[i] = isb_encap;\n-    }\n-    icsbrec_gateway_set_encaps(gw, isb_encaps,\n-                              chassis->n_encaps);\n-    free(isb_encaps);\n-}\n-\n-static void\n-gateway_run(struct engine_context *ctx,\n-            struct ic_input *ic)\n-{\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_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-        }\n-    }\n-\n-    const struct sbrec_chassis *chassis;\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_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-                sync_sb_gw_to_isb(ctx, chassis, gw);\n-            }\n-        } else if (smap_get_bool(&chassis->other_config, \"is-remote\", false)) {\n-            gw = shash_find_and_delete(&remote_gws, chassis->name);\n-            if (!gw) {\n-                sbrec_chassis_delete(chassis);\n-            } else if (is_gateway_data_changed(gw, chassis)) {\n-                sync_isb_gw_to_sb(ctx, gw, chassis);\n-            }\n-        }\n-    }\n-\n-    /* Delete extra gateways from ISB for the local AZ */\n-    struct shash_node *node;\n-    SHASH_FOR_EACH (node, &local_gws) {\n-        icsbrec_gateway_delete(node->data);\n-    }\n-    shash_destroy(&local_gws);\n-\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_idl_txn);\n-        sbrec_chassis_set_name(chassis, gw->name);\n-        sync_isb_gw_to_sb(ctx, gw, chassis);\n-    }\n-    shash_destroy(&remote_gws);\n-}\n-\n const struct nbrec_logical_router_port *\n get_lrp_by_lrp_name(struct ovsdb_idl_index *nbrec_lrp_by_name,\n                     const char *lrp_name)\n@@ -1192,7 +1045,6 @@ 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     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     sync_service_monitor(eng_ctx, input_data);\n@@ -1601,6 +1453,7 @@ main(int argc, char *argv[])\n     stopwatch_create(OVN_IC_ENUM_DATAPATHS_RUN_STOPWATCH_NAME, SW_MS);\n     stopwatch_create(OVN_IC_PORT_BINDING_RUN_STOPWATCH_NAME, SW_MS);\n     stopwatch_create(OVN_IC_ROUTE_RUN_STOPWATCH_NAME, SW_MS);\n+    stopwatch_create(OVN_IC_GATEWAY_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,\ndiff --git a/ic/ovn-ic.h b/ic/ovn-ic.h\nindex bc4a1e6e0..e6918c8d2 100644\n--- a/ic/ovn-ic.h\n+++ b/ic/ovn-ic.h\n@@ -34,7 +34,6 @@ struct ic_input {\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;\ndiff --git a/lib/stopwatch-names.h b/lib/stopwatch-names.h\nindex c277d4056..cd75376d9 100644\n--- a/lib/stopwatch-names.h\n+++ b/lib/stopwatch-names.h\n@@ -42,6 +42,7 @@\n \n #define OVN_IC_LOOP_STOPWATCH_NAME \"ovn-ic-loop\"\n #define IC_OVN_DB_RUN_STOPWATCH_NAME \"ovn_db_run\"\n+#define OVN_IC_GATEWAY_RUN_STOPWATCH_NAME \"gateway_run\"\n #define OVN_IC_ENUM_DATAPATHS_RUN_STOPWATCH_NAME \"enum_datapaths_run\"\n #define OVN_IC_PORT_BINDING_RUN_STOPWATCH_NAME \"port_binding_run\"\n #define OVN_IC_ROUTE_RUN_STOPWATCH_NAME \"route_run\"\n",
    "prefixes": [
        "ovs-dev",
        "v0",
        "5/9"
    ]
}