{"id":2186658,"url":"http://patchwork.ozlabs.org/api/1.0/patches/2186658/?format=json","project":{"id":68,"url":"http://patchwork.ozlabs.org/api/1.0/projects/68/?format=json","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-8-guilherme.paulo@luizalabs.com>","date":"2026-01-20T11:49:46","name":"[ovs-dev,v0,7/9] ovn-ic: Add a new engine-node 'transit-switch'.","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"8516c8837235a6303c2ed5e41568b82bbdad9fd6","submitter":{"id":90256,"url":"http://patchwork.ozlabs.org/api/1.0/people/90256/?format=json","name":"Paulo Guilherme Silva","email":"guilherme.paulo@luizalabs.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/ovn/patch/20260120114948.2289909-8-guilherme.paulo@luizalabs.com/mbox/","series":[{"id":489037,"url":"http://patchwork.ozlabs.org/api/1.0/series/489037/?format=json","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/2186658/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=L6Zfv4l1;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)","smtp2.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=L6Zfv4l1","smtp2.osuosl.org; dmarc=pass (p=quarantine dis=none)\n header.from=luizalabs.com"],"Received":["from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133])\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 4dwQdf4cvrz1xsW\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 20 Jan 2026 22:51:18 +1100 (AEDT)","from localhost (localhost [127.0.0.1])\n\tby smtp2.osuosl.org (Postfix) with ESMTP id BAD1F43051;\n\tTue, 20 Jan 2026 11:51:10 +0000 (UTC)","from smtp2.osuosl.org ([127.0.0.1])\n by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id yYDP9tXURnwu; Tue, 20 Jan 2026 11:50:59 +0000 (UTC)","from lists.linuxfoundation.org (lf-lists.osuosl.org\n [IPv6:2605:bc80:3010:104::8cd3:938])\n\tby smtp2.osuosl.org (Postfix) with ESMTPS id CCF6842F73;\n\tTue, 20 Jan 2026 11:50:59 +0000 (UTC)","from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id AEAA5C04FD;\n\tTue, 20 Jan 2026 11:50:59 +0000 (UTC)","from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 51B0AC02A5\n for <dev@openvswitch.org>; Tue, 20 Jan 2026 11:50:58 +0000 (UTC)","from localhost (localhost [127.0.0.1])\n by smtp2.osuosl.org (Postfix) with ESMTP id D475842F7F\n for <dev@openvswitch.org>; Tue, 20 Jan 2026 11:50:34 +0000 (UTC)","from smtp2.osuosl.org ([127.0.0.1])\n by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id nqOclRA9jyCs for <dev@openvswitch.org>;\n Tue, 20 Jan 2026 11:50:32 +0000 (UTC)","from mail-dy1-x1329.google.com (mail-dy1-x1329.google.com\n [IPv6:2607:f8b0:4864:20::1329])\n by smtp2.osuosl.org (Postfix) with ESMTPS id 49CE742FB7\n for <dev@openvswitch.org>; Tue, 20 Jan 2026 11:50:32 +0000 (UTC)","by mail-dy1-x1329.google.com with SMTP id\n 5a478bee46e88-2ae255ac8bdso9489249eec.0\n for <dev@openvswitch.org>; Tue, 20 Jan 2026 03:50:32 -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.28\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 20 Jan 2026 03:50:30 -0800 (PST)"],"X-Virus-Scanned":["amavis at osuosl.org","amavis at osuosl.org"],"X-Comment":"SPF check N/A for local connections -\n client-ip=2605:bc80:3010:104::8cd3:938; helo=lists.linuxfoundation.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN> ","DKIM-Filter":["OpenDKIM Filter v2.11.0 smtp2.osuosl.org CCF6842F73","OpenDKIM Filter v2.11.0 smtp2.osuosl.org 49CE742FB7"],"Received-SPF":"Pass (mailfrom) identity=mailfrom;\n client-ip=2607:f8b0:4864:20::1329; helo=mail-dy1-x1329.google.com;\n envelope-from=guilherme.paulo@luizalabs.com; receiver=<UNKNOWN>","DMARC-Filter":"OpenDMARC Filter v1.4.2 smtp2.osuosl.org 49CE742FB7","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=luizalabs.com; s=google; t=1768909831; x=1769514631; 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=yHF1VNwLFhU+ByRxeO7pYqhEJJg1Rj27OY7zv1vHzwo=;\n b=L6Zfv4l1dUT1/nx0KKhNiSWa0vRYTKdtFl+5iZmkOzlS1S4XHWjkxC8F3eIVuhW2UG\n aqbQLAVMOq1YGG3n1eFIII77uOFuJypU1dRBfIQ/FDNtN9/GoovCv/LGkSz3Eg24sSe8\n OA5pvrrnXVYfBWD247HcOwOWQ2cdpNSBV0Oi4=","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1768909831; x=1769514631;\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=yHF1VNwLFhU+ByRxeO7pYqhEJJg1Rj27OY7zv1vHzwo=;\n b=KwVI5DMKwj+oOyWHRW/PNYBnTRLfcCP8/8G2X8PZpXENOyDgILLYYXM/jFYuu3s7Q+\n gU9F/9/+onqPu48TMtFubH2fRadq2lFlUWIoKtxstYyIgZ8UEhWszbF0ChDI2F0xLioC\n UN4S4pQ1S0NKPm8hW57doY+Jdj3iIXStkCnzArXGQkLky3tC+vwm7KVXgRL3+ByQcutY\n PavMCCGHa5rwuFm/dKYLdryDCVHtlPyDdqWfU/nWoWJwfvhpH2IFT0wxFs3sqe0YaVYL\n lKpP1+tsFRwf2/8QIvaawaVYDK441e5pRDilsnziWro0n2MUB7SG1bvT/u83UbTUm5PS\n WyDg==","X-Gm-Message-State":"AOJu0YxwWsjwb9gi7xX5KLYMRM5w4N2Ssk6EpBhNsgAstIL52DFjQGtN\n IQmyKynrRejvrhBg/3iYnTPie3XF/xDvEIr4WAb+3aw8lXIg6zcuxixkHcAn2ZDkdWYHKwn8Cl4\n 4clPRnR1E+a650Mmr0tKS6fOcPQIzOlipOyY28Pbd6r2DyCPbd4CdoeUZjEKe","X-Gm-Gg":"AZuq6aKYDzHRTTJjn0d+AV6F+MtdkF04d7DwRXdadXz6Oi91OSxxrcbxQ81ijz3cK/L\n 44zJVn63TanrqOdRYqPf6GhrEvJQMCENHev+E+MM2JW1mjazrFvqQf9wMjQJVxLxvbh+6MN+ErV\n wZ0jVVp5Y1ulDTEARPIb9uQOW0nFaA65XYYD+vREzI1VlwIIbrSYFzH2sBFcbIbgh7YZXcG4QGy\n eh7Ce2KJvUVrhTZcOZfyR+Wvhj/pH+vA8HWi7lWe34zOF1L9Pn5dc2HB0054LAG3gumqxZFWgmL\n uqULhmKx9uMmwzDwe8ypRf2TTMzlCCtBItQQKNt3iISNvCyVMqtEkCPRkv4mzk+gF67v94bNGou\n gk2p3NP0zJVyajDXvBhG+uhoj1Se4evUVMHfdB6kbGjvWentsqq/8PI9tXEqZu2htLzVJB3P++w\n lKzIrFGi+scu1TGammoLvXSXUWl3Ji2OSM9d/PgQ==","X-Received":"by 2002:a05:7300:dc85:b0:2ac:2480:f0ac with SMTP id\n 5a478bee46e88-2b6b40d991cmr8880952eec.23.1768909830482;\n Tue, 20 Jan 2026 03:50:30 -0800 (PST)","To":"dev@openvswitch.org","Date":"Tue, 20 Jan 2026 08:49:46 -0300","Message-Id":"<20260120114948.2289909-8-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 7/9] ovn-ic: Add a new engine-node\n 'transit-switch'.","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 transit-switch related data for ovn-ic\ndaemon which was earlier maintained by the ic engine node invoked the\nts_run() function. The inputs to this engine node are:\n   en_enum_datapaths;\n   en_icsb_datapath_binding;\n   en_nb_logical_switch;\n   en_icnb_ic_nb_global;\n   en_icnb_transit_switch;\n   en_icsb_encap;\n\nIn order to achieve this, we refactor in the following way:\n* Introduce ts_init() which initializes this data.\n* Introduce ts_destroy() which clears this data for a new iteration.\n* Introduce ts_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-ic.c            |  16 +--\n ic/en-ts.c            | 282 ++++++++++++++++++++++++++++++++++++++++++\n ic/en-ts.h            |  23 ++++\n ic/inc-proc-ic.c      |  16 ++-\n ic/ovn-ic.c           | 171 +------------------------\n ic/ovn-ic.h           |   1 -\n lib/stopwatch-names.h |   1 +\n 8 files changed, 322 insertions(+), 190 deletions(-)\n create mode 100644 ic/en-ts.c\n create mode 100644 ic/en-ts.h","diff":"diff --git a/ic/automake.mk b/ic/automake.mk\nindex 180fcb252..84a487dc1 100644\n--- a/ic/automake.mk\n+++ b/ic/automake.mk\n@@ -8,6 +8,8 @@ ic_ovn_ic_SOURCES = ic/ovn-ic.c \\\n \tic/en-gateway.h \\\n \tic/en-enum-datapaths.c \\\n \tic/en-enum-datapaths.h \\\n+\tic/en-ts.c \\\n+\tic/en-ts.h \\\n \tic/en-tr.c \\\n \tic/en-tr.h \\\n \tic/en-port-binding.c \\\ndiff --git a/ic/en-ic.c b/ic/en-ic.c\nindex e9450a290..14c5c29cb 100644\n--- a/ic/en-ic.c\n+++ b/ic/en-ic.c\n@@ -48,22 +48,14 @@ ic_get_input_data(struct engine_node *node,\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->sbrec_sb_global_table =\n+        EN_OVSDB_GET(engine_get_input(\"SB_sb_global\", 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_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@@ -102,10 +94,6 @@ ic_get_input_data(struct engine_node *node,\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_service_monitor_by_source_az =\n         engine_ovsdb_node_get_index(\n             engine_get_input(\"ICSB_service_monitor\", node),\ndiff --git a/ic/en-ts.c b/ic/en-ts.c\nnew file mode 100644\nindex 000000000..4f9322326\n--- /dev/null\n+++ b/ic/en-ts.c\n@@ -0,0 +1,282 @@\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-ts.h\"\n+#include \"en-enum-datapaths.h\"\n+#include \"inc-proc-ic.h\"\n+#include \"lib/inc-proc-eng.h\"\n+#include \"lib/ovn-nb-idl.h\"\n+#include \"lib/ovn-ic-nb-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(en_transit_switch);\n+COVERAGE_DEFINE(ts_run);\n+\n+static void\n+ts_run(const struct engine_context *eng_ctx,\n+       struct ed_type_transit_switch *ts_data,\n+       struct ed_type_enum_datapaths *dp_node_data,\n+       const struct nbrec_logical_switch_table *nbrec_ls_table,\n+       const struct icnbrec_ic_nb_global_table *icnbrec_nb_global_table,\n+       const struct icnbrec_transit_switch_table *icnbrec_ts_table,\n+       const struct icsbrec_encap_table *icsbrec_encap_table,\n+       const struct icsbrec_datapath_binding_table *icsbrec_dp_table);\n+static void ts_init(struct ed_type_transit_switch *data);\n+static void ts_destroy(struct ed_type_transit_switch *data);\n+\n+enum engine_node_state\n+en_ts_run(struct engine_node *node, void *data)\n+{\n+    const struct engine_context *eng_ctx = engine_get_context();\n+    struct ed_type_transit_switch *ts_data = data;\n+\n+    struct ed_type_enum_datapaths *dp_node_data =\n+        engine_get_input_data(\"enum_datapaths\", node);\n+\n+    const struct nbrec_logical_switch_table *nbrec_ls_table =\n+        EN_OVSDB_GET(engine_get_input(\"NB_logical_switch\", node));\n+    const struct icnbrec_ic_nb_global_table *icnbrec_nb_global_table =\n+        EN_OVSDB_GET(engine_get_input(\"ICNB_ic_nb_global\", node));\n+    const struct icnbrec_transit_switch_table *icnbrec_ts_table =\n+        EN_OVSDB_GET(engine_get_input(\"ICNB_transit_switch\", node));\n+    const struct icsbrec_encap_table *icsbrec_encap_table =\n+        EN_OVSDB_GET(engine_get_input(\"ICSB_encap\", node));\n+    const struct icsbrec_datapath_binding_table *icsbrec_dp_table =\n+        EN_OVSDB_GET(engine_get_input(\"ICSB_datapath_binding\", node));\n+\n+    COVERAGE_INC(ts_run);\n+    stopwatch_start(OVN_IC_TRANSIT_SWITCH_RUN_STOPWATCH_NAME, time_usec());\n+    ts_run(eng_ctx, ts_data, dp_node_data, nbrec_ls_table,\n+           icnbrec_nb_global_table, icnbrec_ts_table, icsbrec_encap_table,\n+           icsbrec_dp_table);\n+    stopwatch_stop(OVN_IC_TRANSIT_SWITCH_RUN_STOPWATCH_NAME, time_usec());\n+\n+    return EN_UPDATED;\n+}\n+\n+void *\n+en_ts_init(struct engine_node *node OVS_UNUSED,\n+           struct engine_arg *arg OVS_UNUSED)\n+{\n+    struct ed_type_transit_switch *data = xzalloc(sizeof *data);\n+    ts_init(data);\n+    return data;\n+}\n+\n+void\n+en_ts_cleanup(void *data)\n+{\n+    ts_destroy(data);\n+}\n+\n+static void\n+ts_init(struct ed_type_transit_switch *data)\n+{\n+    shash_init(&data->isb_ts_dps);\n+    hmap_init(&data->dp_tnlids);\n+}\n+\n+static void\n+ts_destroy(struct ed_type_transit_switch *data)\n+{\n+    shash_destroy(&data->isb_ts_dps);\n+    ovn_destroy_tnlids(&data->dp_tnlids);\n+}\n+\n+static void\n+ts_run(const struct engine_context *eng_ctx,\n+       struct ed_type_transit_switch *ts_data OVS_UNUSED,\n+       struct ed_type_enum_datapaths *dp_node_data,\n+       const struct nbrec_logical_switch_table *nbrec_ls_table,\n+       const struct icnbrec_ic_nb_global_table *icnbrec_nb_global_table,\n+       const struct icnbrec_transit_switch_table *icnbrec_ts_table,\n+       const struct icsbrec_encap_table *icsbrec_encap_table,\n+       const struct icsbrec_datapath_binding_table *icsbrec_dp_table)\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_table_first(icnbrec_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_TABLE_FOR_EACH (encap, icsbrec_encap_table) {\n+            if (!strcmp(encap->type, \"vxlan\")) {\n+                vxlan_mode = true;\n+                break;\n+            }\n+        }\n+    }\n+\n+    /* Sync INB TS to AZ NB */\n+    if (eng_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_TABLE_FOR_EACH (ls, nbrec_ls_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+            }\n+        }\n+\n+        /* Create/update NB Logical_Switch for each TS */\n+        ICNBREC_TRANSIT_SWITCH_TABLE_FOR_EACH (ts, icnbrec_ts_table) {\n+            ls = shash_find_and_delete(&nb_tses, ts->name);\n+            if (!ls) {\n+                ls = nbrec_logical_switch_insert(eng_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+                                                                ts->name);\n+                nbrec_logical_switch_update_other_config_setkey(\n+                        ls, \"ic-vxlan_mode\", vxlan_mode ? \"true\" : \"false\");\n+            } else {\n+                bool _vxlan_mode = smap_get_bool(&ls->other_config,\n+                                                 \"ic-vxlan_mode\", false);\n+                if (_vxlan_mode != vxlan_mode) {\n+                    dp_key_refresh = true;\n+                    nbrec_logical_switch_update_other_config_setkey(\n+                            ls, \"ic-vxlan_mode\",\n+                            vxlan_mode ? \"true\" : \"false\");\n+                }\n+            }\n+\n+            const struct icsbrec_datapath_binding *isb_dp;\n+            isb_dp = shash_find_data(&dp_node_data->isb_ts_dps, ts->name);\n+            if (!isb_dp) {\n+                const struct icsbrec_datapath_binding *raw;\n+                ICSBREC_DATAPATH_BINDING_TABLE_FOR_EACH (raw,\n+                                                         icsbrec_dp_table) {\n+                    if (raw->transit_switch && !strcmp(raw->transit_switch,\n+                                                       ts->name)) {\n+                        isb_dp = raw;\n+                        break;\n+                    }\n+                }\n+            } else {\n+                int64_t nb_tnl_key = smap_get_int(&ls->other_config,\n+                                                  \"requested-tnl-key\",\n+                                                  0);\n+                if (nb_tnl_key != isb_dp->tunnel_key) {\n+                    VLOG_DBG(\"Set other_config:requested-tnl-key %\"PRId64\n+                             \" for transit switch %s in NB.\",\n+                             isb_dp->tunnel_key, ts->name);\n+                    char *tnl_key_str = xasprintf(\"%\"PRId64,\n+                                                  isb_dp->tunnel_key);\n+                    nbrec_logical_switch_update_other_config_setkey(\n+                        ls, \"requested-tnl-key\", tnl_key_str);\n+                    free(tnl_key_str);\n+                }\n+            }\n+        }\n+\n+        /* Delete extra NB Logical_Switch with other_config:interconn-ts */\n+        struct shash_node *node;\n+        SHASH_FOR_EACH (node, &nb_tses) {\n+            nbrec_logical_switch_delete(node->data);\n+        }\n+        shash_destroy(&nb_tses);\n+    }\n+\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 (eng_ctx->ovnisb_idl_txn) {\n+        /* Create ISB Datapath_Binding */\n+        ICNBREC_TRANSIT_SWITCH_TABLE_FOR_EACH (ts, icnbrec_ts_table) {\n+            const struct icsbrec_datapath_binding *isb_dp =\n+                shash_find_and_delete(&dp_node_data->isb_ts_dps, ts->name);\n+\n+            if (!isb_dp) {\n+                const struct icsbrec_datapath_binding *raw_isb;\n+                ICSBREC_DATAPATH_BINDING_TABLE_FOR_EACH (raw_isb,\n+                                                         icsbrec_dp_table) {\n+                    if (raw_isb->n_nb_ic_uuid > 0 &&\n+                        uuid_equals(&raw_isb->nb_ic_uuid[0],\n+                                    &ts->header_.uuid)) {\n+                        isb_dp = raw_isb;\n+                        if (isb_dp->transit_switch) {\n+                            shash_find_and_delete(&dp_node_data->isb_ts_dps,\n+                                                  isb_dp->transit_switch);\n+                        }\n+                        break;\n+                    }\n+                }\n+            }\n+\n+            if (!isb_dp) {\n+                /* Allocate tunnel key */\n+                int64_t dp_key = allocate_dp_key(&dp_node_data->dp_tnlids,\n+                                                 vxlan_mode,\n+                                                 \"transit switch datapath\");\n+                if (!dp_key) {\n+                    continue;\n+                }\n+\n+                isb_dp =\n+                    icsbrec_datapath_binding_insert(eng_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+                icsbrec_datapath_binding_set_nb_ic_uuid(isb_dp,\n+                                                        &ts->header_.uuid, 1);\n+                icsbrec_datapath_binding_set_type(isb_dp, \"transit-switch\");\n+            } else if (dp_key_refresh) {\n+                /* Refresh tunnel key since encap mode has changed. */\n+                int64_t dp_key = allocate_dp_key(&dp_node_data->dp_tnlids,\n+                                                 vxlan_mode,\n+                                                 \"transit switch datapath\");\n+                if (dp_key) {\n+                    icsbrec_datapath_binding_set_tunnel_key(isb_dp, dp_key);\n+                }\n+            }\n+\n+            if (!isb_dp->type) {\n+                icsbrec_datapath_binding_set_type(isb_dp, \"transit-switch\");\n+            }\n+\n+            if (!isb_dp->nb_ic_uuid) {\n+                icsbrec_datapath_binding_set_nb_ic_uuid(isb_dp,\n+                                                        &ts->header_.uuid, 1);\n+            }\n+        }\n+\n+        struct shash_node *node, *next;\n+        SHASH_FOR_EACH_SAFE (node, next, &dp_node_data->isb_ts_dps) {\n+            struct icsbrec_datapath_binding *isb_dp_to_del = node->data;\n+            if (isb_dp_to_del->n_nb_ic_uuid > 0) {\n+                icsbrec_datapath_binding_delete(isb_dp_to_del);\n+            }\n+            shash_delete(&dp_node_data->isb_ts_dps, node);\n+        }\n+    }\n+}\ndiff --git a/ic/en-ts.h b/ic/en-ts.h\nnew file mode 100644\nindex 000000000..c63c1aef7\n--- /dev/null\n+++ b/ic/en-ts.h\n@@ -0,0 +1,23 @@\n+#ifndef EN_IC_TS_RUN_H\n+#define EN_IC_TS_RUN_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_transit_switch {\n+    struct hmap dp_tnlids;\n+    struct shash isb_ts_dps;\n+};\n+\n+void *en_ts_init(struct engine_node *, struct engine_arg *);\n+enum engine_node_state en_ts_run(struct engine_node *, void *data);\n+void en_ts_cleanup(void *data);\n+\n+#endif\ndiff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c\nindex 6ac60c677..af282fad6 100644\n--- a/ic/inc-proc-ic.c\n+++ b/ic/inc-proc-ic.c\n@@ -29,6 +29,7 @@\n #include \"en-ic.h\"\n #include \"en-gateway.h\"\n #include \"en-enum-datapaths.h\"\n+#include \"en-ts.h\"\n #include \"en-tr.h\"\n #include \"en-port-binding.h\"\n #include \"en-route.h\"\n@@ -166,6 +167,7 @@ static ENGINE_NODE(ic, SB_WRITE);\n static ENGINE_NODE(gateway, SB_WRITE);\n static ENGINE_NODE(enum_datapaths);\n static ENGINE_NODE(tr);\n+static ENGINE_NODE(ts, SB_WRITE);\n static ENGINE_NODE(port_binding, SB_WRITE);\n static ENGINE_NODE(route);\n \n@@ -182,6 +184,13 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,\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+    engine_add_input(&en_ts, &en_enum_datapaths, NULL);\n+    engine_add_input(&en_ts, &en_icsb_datapath_binding, NULL);\n+    engine_add_input(&en_ts, &en_nb_logical_switch, NULL);\n+    engine_add_input(&en_ts, &en_icnb_ic_nb_global, NULL);\n+    engine_add_input(&en_ts, &en_icnb_transit_switch, NULL);\n+    engine_add_input(&en_ts, &en_icsb_encap, NULL);\n+\n     engine_add_input(&en_tr, &en_enum_datapaths, NULL);\n     engine_add_input(&en_tr, &en_icsb_datapath_binding, NULL);\n     engine_add_input(&en_tr, &en_nb_logical_router, NULL);\n@@ -206,6 +215,7 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,\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_ts, NULL);\n     engine_add_input(&en_ic, &en_tr, NULL);\n     engine_add_input(&en_ic, &en_port_binding, NULL);\n     engine_add_input(&en_ic, &en_route, NULL);\n@@ -224,15 +234,9 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,\n     engine_add_input(&en_ic, &en_sb_port_binding, NULL);\n     engine_add_input(&en_ic, &en_sb_service_monitor, NULL);\n \n-    engine_add_input(&en_ic, &en_icnb_ic_nb_global, NULL);\n-    engine_add_input(&en_ic, &en_icnb_transit_switch, NULL);\n-\n-    engine_add_input(&en_ic, &en_icsb_port_binding, NULL);\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_datapath_binding, NULL);\n \n     struct engine_arg engine_arg = {\n         .nb_idl = nb->idl,\ndiff --git a/ic/ovn-ic.c b/ic/ovn-ic.c\nindex 08241337d..301b54fb2 100644\n--- a/ic/ovn-ic.c\n+++ b/ic/ovn-ic.c\n@@ -179,173 +179,6 @@ ic_pb_get_type(const struct icsbrec_port_binding *isb_pb)\n     return IC_SWITCH_PORT;\n }\n \n-static void\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_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_TABLE_FOR_EACH (encap, ic->icsbrec_encap_table) {\n-            if (!strcmp(encap->type, \"vxlan\")) {\n-                vxlan_mode = true;\n-                break;\n-            }\n-        }\n-    }\n-\n-    /* Sync INB TS to AZ NB */\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_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-            }\n-        }\n-\n-        /* Create/update NB Logical_Switch for each TS */\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_idl_txn);\n-                nbrec_logical_switch_set_name(ls, ts->name);\n-                nbrec_logical_switch_update_other_config_setkey(ls,\n-                                                                \"interconn-ts\",\n-                                                                ts->name);\n-                nbrec_logical_switch_update_other_config_setkey(\n-                        ls, \"ic-vxlan_mode\", vxlan_mode ? \"true\" : \"false\");\n-            } else {\n-                bool _vxlan_mode = smap_get_bool(&ls->other_config,\n-                                                 \"ic-vxlan_mode\", false);\n-                if (_vxlan_mode != vxlan_mode) {\n-                    dp_key_refresh = true;\n-                    nbrec_logical_switch_update_other_config_setkey(\n-                            ls, \"ic-vxlan_mode\",\n-                            vxlan_mode ? \"true\" : \"false\");\n-                }\n-            }\n-\n-            const struct icsbrec_datapath_binding *isb_dp;\n-            isb_dp = shash_find_data(isb_ts_dps, ts->name);\n-            if (!isb_dp) {\n-                const struct icsbrec_datapath_binding *raw;\n-                ICSBREC_DATAPATH_BINDING_TABLE_FOR_EACH (raw,\n-                    ic->icsbrec_datapath_binding_table) {\n-                    if (raw->transit_switch && !strcmp(raw->transit_switch,\n-                                                       ts->name)) {\n-                        isb_dp = raw;\n-                        break;\n-                    }\n-                }\n-            } else {\n-                int64_t nb_tnl_key = smap_get_int(&ls->other_config,\n-                                                  \"requested-tnl-key\",\n-                                                  0);\n-                if (nb_tnl_key != isb_dp->tunnel_key) {\n-                    VLOG_DBG(\"Set other_config:requested-tnl-key %\"PRId64\n-                             \" for transit switch %s in NB.\",\n-                             isb_dp->tunnel_key, ts->name);\n-                    char *tnl_key_str = xasprintf(\"%\"PRId64,\n-                                                  isb_dp->tunnel_key);\n-                    nbrec_logical_switch_update_other_config_setkey(\n-                        ls, \"requested-tnl-key\", tnl_key_str);\n-                    free(tnl_key_str);\n-                }\n-            }\n-        }\n-\n-        /* Delete extra NB Logical_Switch with other_config:interconn-ts */\n-        struct shash_node *node;\n-        SHASH_FOR_EACH (node, &nb_tses) {\n-            nbrec_logical_switch_delete(node->data);\n-        }\n-        shash_destroy(&nb_tses);\n-    }\n-\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_idl_txn) {\n-        /* Create ISB Datapath_Binding */\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-\n-            if (!isb_dp) {\n-                const struct icsbrec_datapath_binding *raw_isb;\n-                ICSBREC_DATAPATH_BINDING_TABLE_FOR_EACH (raw_isb,\n-                    ic->icsbrec_datapath_binding_table) {\n-                    if (raw_isb->n_nb_ic_uuid > 0 &&\n-                        uuid_equals(&raw_isb->nb_ic_uuid[0],\n-                                    &ts->header_.uuid)) {\n-                        isb_dp = raw_isb;\n-                        if (isb_dp->transit_switch) {\n-                            shash_find_and_delete(isb_ts_dps,\n-                                                  isb_dp->transit_switch);\n-                        }\n-                        break;\n-                    }\n-                }\n-            }\n-\n-            if (!isb_dp) {\n-                /* Allocate tunnel key */\n-                int64_t dp_key = allocate_dp_key(dp_tnlids, vxlan_mode,\n-                                                 \"transit switch datapath\");\n-                if (!dp_key) {\n-                    continue;\n-                }\n-\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-                icsbrec_datapath_binding_set_nb_ic_uuid(isb_dp,\n-                                                        &ts->header_.uuid, 1);\n-                icsbrec_datapath_binding_set_type(isb_dp, \"transit-switch\");\n-            } else if (dp_key_refresh) {\n-                /* Refresh tunnel key since encap mode has changed. */\n-                int64_t dp_key = allocate_dp_key(dp_tnlids, vxlan_mode,\n-                                                 \"transit switch datapath\");\n-                if (dp_key) {\n-                    icsbrec_datapath_binding_set_tunnel_key(isb_dp, dp_key);\n-                }\n-            }\n-\n-            if (!isb_dp->type) {\n-                icsbrec_datapath_binding_set_type(isb_dp, \"transit-switch\");\n-            }\n-\n-            if (!isb_dp->nb_ic_uuid) {\n-                icsbrec_datapath_binding_set_nb_ic_uuid(isb_dp,\n-                                                        &ts->header_.uuid, 1);\n-            }\n-        }\n-\n-        struct shash_node *node, *next;\n-        SHASH_FOR_EACH_SAFE (node, next, isb_ts_dps) {\n-            struct icsbrec_datapath_binding *isb_dp_to_del = node->data;\n-            if (isb_dp_to_del->n_nb_ic_uuid > 0) {\n-                icsbrec_datapath_binding_delete(isb_dp_to_del);\n-            }\n-            shash_delete(isb_ts_dps, node);\n-        }\n-    }\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@@ -959,10 +792,9 @@ inc_proc_graph_dump(const char *end_node)\n \n void\n ovn_db_run(struct ic_input *input_data,\n-           struct ic_data *ic_data,\n+           struct ic_data *ic_data OVS_UNUSED,\n            struct engine_context *eng_ctx)\n {\n-    ts_run(eng_ctx, input_data, ic_data->dp_tnlids, ic_data->isb_ts_dps);\n     sync_service_monitor(eng_ctx, input_data);\n }\n \f\n@@ -1371,6 +1203,7 @@ main(int argc, char *argv[])\n     stopwatch_create(OVN_IC_ROUTE_RUN_STOPWATCH_NAME, SW_MS);\n     stopwatch_create(OVN_IC_GATEWAY_RUN_STOPWATCH_NAME, SW_MS);\n     stopwatch_create(OVN_IC_TRANSIT_ROUTER_RUN_STOPWATCH_NAME, SW_MS);\n+    stopwatch_create(OVN_IC_TRANSIT_SWITCH_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 225dc73f5..7e057cc1b 100644\n--- a/ic/ovn-ic.h\n+++ b/ic/ovn-ic.h\n@@ -29,7 +29,6 @@ struct ic_input {\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 \n     /* InterconnectSouthbound table references */\n     const struct icsbrec_encap_table *icsbrec_encap_table;\ndiff --git a/lib/stopwatch-names.h b/lib/stopwatch-names.h\nindex f6e1bc023..c9fe2e639 100644\n--- a/lib/stopwatch-names.h\n+++ b/lib/stopwatch-names.h\n@@ -44,6 +44,7 @@\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_TRANSIT_SWITCH_RUN_STOPWATCH_NAME \"transit_switch_run\"\n #define OVN_IC_TRANSIT_ROUTER_RUN_STOPWATCH_NAME \"transit_router_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","7/9"]}