get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2223309,
    "url": "http://patchwork.ozlabs.org/api/1.2/patches/2223309/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/ovn/patch/20260415012252.219220-1-tiago.reis@luizalabs.com/",
    "project": {
        "id": 68,
        "url": "http://patchwork.ozlabs.org/api/1.2/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": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260415012252.219220-1-tiago.reis@luizalabs.com>",
    "list_archive_url": null,
    "date": "2026-04-15T01:22:52",
    "name": "[ovs-dev,v5] ovn-ic: Use dual IC-SB connections to prevent constraint violations.",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "d2274f674c9b1309d892402a9a323f73447baf45",
    "submitter": {
        "id": 92676,
        "url": "http://patchwork.ozlabs.org/api/1.2/people/92676/?format=api",
        "name": "Tiago Matos",
        "email": "tiago.reis@luizalabs.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/ovn/patch/20260415012252.219220-1-tiago.reis@luizalabs.com/mbox/",
    "series": [
        {
            "id": 499902,
            "url": "http://patchwork.ozlabs.org/api/1.2/series/499902/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/ovn/list/?series=499902",
            "date": "2026-04-15T01:22:52",
            "name": "[ovs-dev,v5] ovn-ic: Use dual IC-SB connections to prevent constraint violations.",
            "version": 5,
            "mbox": "http://patchwork.ozlabs.org/series/499902/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2223309/comments/",
    "check": "success",
    "checks": "http://patchwork.ozlabs.org/api/patches/2223309/checks/",
    "tags": {},
    "related": [],
    "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=kAYN5LGq;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=140.211.166.136; helo=smtp3.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)",
            "smtp3.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=kAYN5LGq",
            "smtp2.osuosl.org; dmarc=pass (p=quarantine dis=none)\n header.from=luizalabs.com",
            "smtp2.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=kAYN5LGq"
        ],
        "Received": [
            "from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136])\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 4fwNgp0D6wz1yHM\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 15 Apr 2026 11:23:15 +1000 (AEST)",
            "from localhost (localhost [127.0.0.1])\n\tby smtp3.osuosl.org (Postfix) with ESMTP id 5E24A6F5E9;\n\tWed, 15 Apr 2026 01:23:13 +0000 (UTC)",
            "from smtp3.osuosl.org ([127.0.0.1])\n by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id wXRGdh2l5ykQ; Wed, 15 Apr 2026 01:23:11 +0000 (UTC)",
            "from lists.linuxfoundation.org (lf-lists.osuosl.org\n [IPv6:2605:bc80:3010:104::8cd3:938])\n\tby smtp3.osuosl.org (Postfix) with ESMTPS id 4A9C76F5DF;\n\tWed, 15 Apr 2026 01:23:11 +0000 (UTC)",
            "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id 2359DC054A;\n\tWed, 15 Apr 2026 01:23:11 +0000 (UTC)",
            "from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 4A02EC0549\n for <dev@openvswitch.org>; Wed, 15 Apr 2026 01:23:10 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n by smtp2.osuosl.org (Postfix) with ESMTP id 2A3AE4228C\n for <dev@openvswitch.org>; Wed, 15 Apr 2026 01:23: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 Nv6RP5sPDmD2 for <dev@openvswitch.org>;\n Wed, 15 Apr 2026 01:23:09 +0000 (UTC)",
            "from mail-vk1-xa42.google.com (mail-vk1-xa42.google.com\n [IPv6:2607:f8b0:4864:20::a42])\n by smtp2.osuosl.org (Postfix) with ESMTPS id 99C2F40232\n for <dev@openvswitch.org>; Wed, 15 Apr 2026 01:23:08 +0000 (UTC)",
            "by mail-vk1-xa42.google.com with SMTP id\n 71dfb90a1353d-56efdc96b05so4083557e0c.1\n for <dev@openvswitch.org>; Tue, 14 Apr 2026 18:23:08 -0700 (PDT)",
            "from state ([2804:10dc:d35d:f00:3256:fff:fe0d:5e27])\n by smtp.gmail.com with ESMTPSA id\n 71dfb90a1353d-56f89fe1776sm250075e0c.14.2026.04.14.18.23.04\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 14 Apr 2026 18:23:06 -0700 (PDT)"
        ],
        "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 smtp3.osuosl.org 4A9C76F5DF",
            "OpenDKIM Filter v2.11.0 smtp2.osuosl.org 99C2F40232"
        ],
        "Received-SPF": "Pass (mailfrom) identity=mailfrom;\n client-ip=2607:f8b0:4864:20::a42; helo=mail-vk1-xa42.google.com;\n envelope-from=tiago.reis@luizalabs.com; receiver=<UNKNOWN>",
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 smtp2.osuosl.org 99C2F40232",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=luizalabs.com; s=google; t=1776216187; x=1776820987; darn=openvswitch.org;\n h=content-transfer-encoding:mime-version:message-id:date:subject:cc\n :to:from:from:to:cc:subject:date:message-id:reply-to;\n bh=vQc+3bZA1jhYBMc5frzdZ7pWCold1POZA9OuxIvdUBE=;\n b=kAYN5LGqPVIqxZWYhX5rqgoY6yWGUQ+63FckduwAqUuxipkvze6rPy6w1pHxaTo9/+\n QzgQe/ztEVLEmH3kjkckO1CE3KS8gKtymfwuQG1lfNCG4uZsiQvsk9p+CeTXr/WhKou/\n kpUC45+pAAwzsAEy3kZhe8Fj+6UFe/r3N4Vgg=",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776216187; x=1776820987;\n h=content-transfer-encoding:mime-version:message-id:date:subject:cc\n :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date\n :message-id:reply-to;\n bh=vQc+3bZA1jhYBMc5frzdZ7pWCold1POZA9OuxIvdUBE=;\n b=i9ac94bd/X4hvBsK9kxFlMBMoQexZjnS4dgOy0nx6bwp43uuPJcilrTU/UKVXs3usA\n Vq/hAFO0n3hloqG5LA22/VhI2vyigYKbe+sAHZQN/Gl/6D9kdwh57KaPwgiGmH0R7okx\n /Z9BuzeLiwFpiYp6/KxPV32AuZBTKNlt3vD7zJK2U1o4gEjeK2nYchbqyf6ZDl/6MelY\n F3g8g0UHAs+DjP9Rk1aAbB/DdNfq0CqAcHfM87STv0Hvbw7Wk1JOQlqldURuojSPqIBJ\n YpXjcFNLj4FAqLuYIo16Qj1gQXrgm+cWpiOxt+gWvyeMIiS+BF0imNUcxhiZJo9M5U9+\n Lr4w==",
        "X-Gm-Message-State": "AOJu0Yz1kofSjU8M8hbCf4I7W+R4PhOKtFHBUGShI+worAaMzuSgFw3N\n Hm/aWdmOEzWhhc+D7FJhyIoX2DeKb01CXZE322qQX0j18U7b2f0Ssl+qYbp1+W/eFId66NnNoAh\n Snbu2Xm6Iz4B3SPEAGKJ5MbMLWA+dLk2FaZfKlOeNoXyYur3AJpyygP37HvugSIeVAGnB",
        "X-Gm-Gg": "AeBDietPHGfPaUFkRxaf3ckPyavQGQloElXjXk/GBe15KEqgVqJHYy439Ufv3aEHEm/\n qf8D9T3SkjG5qv/JD/+DQFoJ78hvTTw4YQgIEkZbrr0WM0cQmqcrFTGao/+cGlnaRE/Lid3c3PO\n qIxVCGb6GasBWTUGNQWfB9gcuaZazbwB58Yjmdza3CMKp+bv1yipeuzmibM+B6yIs5aqMq16glX\n ao3e08IyBnF5oqfwHxbVnScVc+UJkVfFJs5JHLxCDoIDwx3U2hUKunfd9SWkjyPDtYSnEZvWq2c\n 1uiO6RYit1U6MWO/c+ZUnTwGqFT0Kv3FHYoZlv9nMjK7iy/LJ1IxjRIilgkiNRhe4b1VazekcPb\n 00WSIWa1NIIUZvt3nz+ye0rAZAPwEkJzSbErf3aJh6LWsVtW/PG0TLwHZjpBChEbrTcO93+6F2O\n uTn3gqSNu09ubSeigB8jzhJrE=",
        "X-Received": "by 2002:a05:6122:6587:b0:56d:9def:20c8 with SMTP id\n 71dfb90a1353d-56f3bb97c97mr9695926e0c.6.1776216186875;\n Tue, 14 Apr 2026 18:23:06 -0700 (PDT)",
        "To": "dev@openvswitch.org",
        "Date": "Tue, 14 Apr 2026 22:22:52 -0300",
        "Message-ID": "<20260415012252.219220-1-tiago.reis@luizalabs.com>",
        "X-Mailer": "git-send-email 2.53.0",
        "MIME-Version": "1.0",
        "Subject": "[ovs-dev] [PATCH ovn v5] ovn-ic: Use dual IC-SB connections to\n prevent constraint violations.",
        "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": "Tiago Matos via dev <ovs-dev@openvswitch.org>",
        "Reply-To": "Tiago Matos <tiago.reis@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": "When multiple Availability Zones (AZs) are connected via OVN-IC,\ncertain events trigger all AZs to attempt writing the same data to the\nIC-SB simultaneously. This race condition leads to constraint\nviolations, causing transaction failures and forcing expensive full\nrecomputes.\n\nTo mitigate this, this patch introduces a write-segregation mechanism\nemploying two distinct connections to IC-SB:\n1. Locked Connection: Acquires a lock to handle data that only a\n   single AZ should write (e.g., creating a new datapath_binding for a\n   transit switch/router).\n\n2. Lockless Connections: Used for data that multiple AZs can safely\n   insert concurrently (e.g., creating a new port_binding).\n\nSigned-off-by: Tiago Matos <tiago.reis@luizalabs.com>\n---\n ic/inc-proc-ic.c |   6 +-\n ic/inc-proc-ic.h |   1 +\n ic/ovn-ic.c      | 199 +++++++++++++++++++++++++++++++++++------------\n ic/ovn-ic.h      |   2 +\n tests/ovn-ic.at  |  44 +++++++++++\n 5 files changed, 201 insertions(+), 51 deletions(-)",
    "diff": "diff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c\nindex 995f23433..2c0420292 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 \"ovn-util.h\"\n #include \"unixctl.h\"\n #include \"util.h\"\n \n@@ -214,7 +215,7 @@ inc_proc_ic_run(struct ic_context *ctx,\n                 struct ic_engine_context *ic_eng_ctx)\n {\n     ovs_assert(ctx->ovnnb_txn && ctx->ovnsb_txn &&\n-               ctx->ovninb_txn && ctx->ovnisb_txn);\n+               ctx->ovninb_txn && ctx->ovnisb_unlocked_txn);\n \n     int64_t start = time_msec();\n     engine_init_run();\n@@ -262,7 +263,8 @@ inc_proc_ic_can_run(struct ic_engine_context *ctx)\n         ctx->nb_idl_duration_ms >= IDL_LOOP_MAX_DURATION_MS ||\n         ctx->sb_idl_duration_ms >= IDL_LOOP_MAX_DURATION_MS ||\n         ctx->inb_idl_duration_ms >= IDL_LOOP_MAX_DURATION_MS ||\n-        ctx->isb_idl_duration_ms >= IDL_LOOP_MAX_DURATION_MS) {\n+        ctx->isb_idl_duration_ms >= IDL_LOOP_MAX_DURATION_MS ||\n+        ctx->isb_unlock_idl_duration_ms >= IDL_LOOP_MAX_DURATION_MS) {\n         return true;\n     }\n \ndiff --git a/ic/inc-proc-ic.h b/ic/inc-proc-ic.h\nindex 9af147fb3..36464564d 100644\n--- a/ic/inc-proc-ic.h\n+++ b/ic/inc-proc-ic.h\n@@ -13,6 +13,7 @@ struct ic_engine_context {\n     uint64_t sb_idl_duration_ms;\n     uint64_t inb_idl_duration_ms;\n     uint64_t isb_idl_duration_ms;\n+    uint64_t isb_unlock_idl_duration_ms;\n     uint32_t backoff_ms;\n };\n \ndiff --git a/ic/ovn-ic.c b/ic/ovn-ic.c\nindex 17feeb4af..ba9490658 100644\n--- a/ic/ovn-ic.c\n+++ b/ic/ovn-ic.c\n@@ -115,8 +115,9 @@ 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 (ctx->ovnisb_unlocked_txn && az_name\n+        && strcmp(az_name, nb_global->name)) {\n+        ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ctx->ovnisb_unlocked_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,11 +139,11 @@ 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 (ctx->ovnisb_unlocked_txn) {\n+        ovsdb_idl_txn_add_comment(ctx->ovnisb_unlocked_txn, \"AZ %s\", az_name);\n     }\n \n-    ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ctx->ovnisb_idl) {\n+    ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ctx->ovnisb_unlocked_idl) {\n         if (!strcmp(az->name, az_name)) {\n             ctx->runned_az = az;\n             return az;\n@@ -150,9 +151,9 @@ az_run(struct ic_context *ctx)\n     }\n \n     /* Create AZ in ISB */\n-    if (ctx->ovnisb_txn) {\n+    if (ctx->ovnisb_unlocked_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(ctx->ovnisb_unlocked_txn);\n         icsbrec_availability_zone_set_name(az, az_name);\n         ctx->runned_az = az;\n         return az;\n@@ -195,7 +196,7 @@ enumerate_datapaths(struct ic_context *ctx, struct hmap *dp_tnlids,\n                     struct shash *isb_ts_dps, 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_FOR_EACH (isb_dp, ctx->ovnisb_unlocked_idl) {\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@@ -209,6 +210,16 @@ enumerate_datapaths(struct ic_context *ctx, struct hmap *dp_tnlids,\n     }\n }\n \n+/*\n+ * Check if the AZ is the leader by checking the lock.\n+ */\n+static bool\n+is_az_leader(struct ovsdb_idl_txn *txn)\n+{\n+    struct ovsdb_idl *idl = ovsdb_idl_txn_get_idl(txn);\n+    return idl && ovsdb_idl_has_lock(idl);\n+}\n+\n static void\n ts_run(struct ic_context *ctx, struct hmap *dp_tnlids,\n        struct shash *isb_ts_dps)\n@@ -219,9 +230,14 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids,\n     const struct icnbrec_ic_nb_global *ic_nb =\n         icnbrec_ic_nb_global_first(ctx->ovninb_idl);\n \n+    /*\n+     * Warning: ovnisb_unlocked should not be used to insert data on IC_SB\n+     * which can cause a constraint violation, as an example, inserting data to\n+     * IC-SB datapath_binding.\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_FOR_EACH (encap, ctx->ovnisb_unlocked_idl) {\n             if (!strcmp(encap->type, \"vxlan\")) {\n                 vxlan_mode = true;\n                 break;\n@@ -294,7 +310,8 @@ 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_txn &&\n+        is_az_leader(ctx->ovnisb_txn)) {\n         /* Create ISB Datapath_Binding */\n         ICNBREC_TRANSIT_SWITCH_FOR_EACH (ts, ctx->ovninb_idl) {\n             const struct icsbrec_datapath_binding *isb_dp =\n@@ -340,6 +357,11 @@ static void\n tr_run(struct ic_context *ctx, struct hmap *dp_tnlids,\n        struct shash *isb_tr_dps)\n {\n+    /*\n+     * Warning: ovnisb_unlocked should not be used to insert data on IC_SB\n+     * which can cause a constraint violation, as an example, inserting data to\n+     * IC-SB datapath_binding.\n+     */\n     const struct nbrec_logical_router *lr;\n \n     if (ctx->ovnnb_txn) {\n@@ -383,7 +405,8 @@ 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_txn &&\n+        is_az_leader(ctx->ovnisb_txn)) {\n         /* Create ISB Datapath_Binding */\n         const struct icnbrec_transit_router *tr;\n         ICNBREC_TRANSIT_ROUTER_FOR_EACH (tr, ctx->ovninb_idl) {\n@@ -488,7 +511,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_unlocked_txn);\n         icsbrec_encap_set_gateway_name(isb_encap,\n                                       chassis->name);\n         icsbrec_encap_set_ip(isb_encap, chassis->encaps[i]->ip);\n@@ -506,14 +529,14 @@ sync_sb_gw_to_isb(struct ic_context *ctx,\n static void\n gateway_run(struct ic_context *ctx)\n {\n-    if (!ctx->ovnisb_txn || !ctx->ovnsb_txn) {\n+    if (!ctx->ovnisb_unlocked_txn || !ctx->ovnsb_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+    ICSBREC_GATEWAY_FOR_EACH (gw, ctx->ovnisb_unlocked_idl) {\n         if (gw->availability_zone == ctx->runned_az) {\n             shash_add(&local_gws, gw->name, gw);\n         } else {\n@@ -526,7 +549,7 @@ gateway_run(struct ic_context *ctx)\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+                gw = icsbrec_gateway_insert(ctx->ovnisb_unlocked_txn);\n                 icsbrec_gateway_set_availability_zone(gw, ctx->runned_az);\n                 icsbrec_gateway_set_name(gw, chassis->name);\n                 sync_sb_gw_to_isb(ctx, chassis, gw);\n@@ -980,7 +1003,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_unlocked_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@@ -1068,7 +1091,7 @@ find_lsp_in_sb(struct ic_context *ctx,\n static void\n port_binding_run(struct ic_context *ctx)\n {\n-    if (!ctx->ovnisb_txn || !ctx->ovnnb_txn || !ctx->ovnsb_txn) {\n+    if (!ctx->ovnisb_unlocked_txn || !ctx->ovnnb_txn || !ctx->ovnsb_txn) {\n         return;\n     }\n \n@@ -2256,7 +2279,7 @@ advertise_routes(struct ic_context *ctx,\n                  const char *ts_name,\n                  struct hmap *routes_ad)\n {\n-    ovs_assert(ctx->ovnisb_txn);\n+    ovs_assert(ctx->ovnisb_unlocked_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@@ -2298,7 +2321,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_unlocked_txn);\n         icsbrec_route_set_transit_switch(isb_route, ts_name);\n         icsbrec_route_set_availability_zone(isb_route, az);\n \n@@ -2531,7 +2554,7 @@ delete_orphan_ic_routes(struct ic_context *ctx,\n static void\n route_run(struct ic_context *ctx)\n {\n-    if (!ctx->ovnisb_txn || !ctx->ovnnb_txn || !ctx->ovnsb_txn) {\n+    if (!ctx->ovnisb_unlocked_txn || !ctx->ovnnb_txn || !ctx->ovnsb_txn) {\n         return;\n     }\n \n@@ -2963,7 +2986,7 @@ destroy_service_monitor_data(struct sync_service_monitor_data *sync_data)\n static void\n sync_service_monitor(struct ic_context *ctx)\n {\n-    if (!ctx->ovnisb_txn || !ctx->ovnsb_txn) {\n+    if (!ctx->ovnisb_unlocked_txn || !ctx->ovnsb_txn) {\n         return;\n     }\n \n@@ -2985,7 +3008,7 @@ sync_service_monitor(struct ic_context *ctx)\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_unlocked_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@@ -3090,7 +3113,7 @@ 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+    if (!ctx->ovnisb_unlocked_txn || !ctx->ovninb_txn) {\n         return;\n     }\n \n@@ -3100,9 +3123,9 @@ update_sequence_numbers(struct ic_context *ctx,\n         ic_nb = icnbrec_ic_nb_global_insert(ctx->ovninb_txn);\n     }\n     const struct icsbrec_ic_sb_global *ic_sb = icsbrec_ic_sb_global_first(\n-                                               ctx->ovnisb_idl);\n+                                               ctx->ovnisb_unlocked_idl);\n     if (!ic_sb) {\n-        ic_sb = icsbrec_ic_sb_global_insert(ctx->ovnisb_txn);\n+        ic_sb = icsbrec_ic_sb_global_insert(ctx->ovnisb_unlocked_txn);\n     }\n \n     if ((ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg) &&\n@@ -3112,7 +3135,8 @@ update_sequence_numbers(struct ic_context *ctx,\n             icsbrec_availability_zone_set_nb_ic_cfg(ctx->runned_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(ctx->ovnisb_unlocked_txn,\n+                                &ctx->runned_az->header_,\n             &icsbrec_availability_zone_col_nb_ic_cfg, true);\n         return;\n     }\n@@ -3127,7 +3151,7 @@ update_sequence_numbers(struct ic_context *ctx,\n     }\n \n     const struct icsbrec_availability_zone *other_az;\n-    ICSBREC_AVAILABILITY_ZONE_FOR_EACH (other_az, ctx->ovnisb_idl) {\n+    ICSBREC_AVAILABILITY_ZONE_FOR_EACH (other_az, ctx->ovnisb_unlocked_idl) {\n         if (other_az->nb_ic_cfg != ctx->runned_az->nb_ic_cfg) {\n             return;\n         }\n@@ -3336,6 +3360,7 @@ static void\n update_idl_probe_interval(struct ovsdb_idl *ovn_sb_idl,\n                           struct ovsdb_idl *ovn_nb_idl,\n                           struct ovsdb_idl *ovn_icsb_idl,\n+                          struct ovsdb_idl *ovn_icsb_unlocked_idl,\n                           struct ovsdb_idl *ovn_icnb_idl)\n {\n     const struct nbrec_nb_global *nb = nbrec_nb_global_first(ovn_nb_idl);\n@@ -3354,6 +3379,7 @@ update_idl_probe_interval(struct ovsdb_idl *ovn_sb_idl,\n                                    ic_interval);\n     }\n     set_idl_probe_interval(ovn_icsb_idl, ovn_ic_sb_db, ic_interval);\n+    set_idl_probe_interval(ovn_icsb_unlocked_idl, ovn_ic_sb_db, ic_interval);\n     set_idl_probe_interval(ovn_icnb_idl, ovn_ic_nb_db, ic_interval);\n }\n \n@@ -3394,7 +3420,27 @@ main(int argc, char *argv[])\n         ovsdb_idl_create(ovn_ic_nb_db, &icnbrec_idl_class, true, true));\n     ovsdb_idl_track_add_all(ovninb_idl_loop.idl);\n \n-    /* ovn-ic-sb db. */\n+    /*\n+     * Each ovn-ic instance maintains two connections to the IC-SB database:\n+     * 1. Locked Connection: Competes for a global lock on IC-SB. Used for\n+     * writes that must be performed by only one active instance\n+     * (e.g., inserting a datapath_binding for a transit switch/router).\n+     *\n+     * 2. Unlocked Connection: Does not hold a lock. Used for writes that\n+     * can be safely performed by multiple instances simultaneously\n+     * (e.g., inserting a port_binding).\n+     *\n+     * This segregation prevents constraint violations and a full recompute\n+     * when writing to IC-SB.\n+     */\n+    /* ovn-ic-sb db without lock. */\n+    struct ovsdb_idl_loop ovnisb_unlocked_idl_loop =\n+        OVSDB_IDL_LOOP_INITIALIZER(ovsdb_idl_create(ovn_ic_sb_db,\n+                                                    &icsbrec_idl_class,\n+                                                    true, true));\n+    ovsdb_idl_track_add_all(ovnisb_unlocked_idl_loop.idl);\n+\n+    /* ovn-ic-sb db with lock. */\n     struct ovsdb_idl_loop ovnisb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(\n         ovsdb_idl_create(ovn_ic_sb_db, &icsbrec_idl_class, true, true));\n     ovsdb_idl_track_add_all(ovnisb_idl_loop.idl);\n@@ -3619,41 +3665,41 @@ main(int argc, char *argv[])\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+        = ovsdb_idl_index_create1(ovnisb_unlocked_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+        = ovsdb_idl_index_create1(ovnisb_unlocked_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+        = ovsdb_idl_index_create2(ovnisb_unlocked_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+        = ovsdb_idl_index_create1(ovnisb_unlocked_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+        = ovsdb_idl_index_create1(ovnisb_unlocked_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+        = ovsdb_idl_index_create2(ovnisb_unlocked_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+        = ovsdb_idl_index_create1(ovnisb_unlocked_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+        = ovsdb_idl_index_create1(ovnisb_unlocked_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+        = ovsdb_idl_index_create2(ovnisb_unlocked_idl_loop.idl,\n             &icsbrec_service_monitor_col_target_availability_zone,\n             &icsbrec_service_monitor_col_logical_port);\n \n@@ -3668,12 +3714,13 @@ main(int argc, char *argv[])\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+                     &ovninb_idl_loop, &ovnisb_unlocked_idl_loop);\n \n     unsigned int ovnnb_cond_seqno = UINT_MAX;\n     unsigned int ovnsb_cond_seqno = UINT_MAX;\n     unsigned int ovninb_cond_seqno = UINT_MAX;\n     unsigned int ovnisb_cond_seqno = UINT_MAX;\n+    unsigned int ovnisb_unlocked_cond_seqno = UINT_MAX;\n \n     /* Main loop. */\n     struct ic_engine_context  eng_ctx = {0};\n@@ -3685,7 +3732,9 @@ main(int argc, char *argv[])\n     while (!exiting) {\n         update_ssl_config();\n         update_idl_probe_interval(ovnsb_idl_loop.idl, ovnnb_idl_loop.idl,\n-                                  ovnisb_idl_loop.idl, ovninb_idl_loop.idl);\n+                                  ovnisb_idl_loop.idl,\n+                                  ovnisb_unlocked_idl_loop.idl,\n+                                  ovninb_idl_loop.idl);\n         memory_run();\n         if (memory_should_report()) {\n             struct simap usage = SIMAP_INITIALIZER(&usage);\n@@ -3707,6 +3756,17 @@ main(int argc, char *argv[])\n                 ovsdb_idl_set_lock(ovnsb_idl_loop.idl, \"ovn_ic\");\n             }\n \n+            if (!ovsdb_idl_has_lock(ovnisb_idl_loop.idl) &&\n+                !ovsdb_idl_is_lock_contended(ovnisb_idl_loop.idl)) {\n+                /*\n+                 * Ensure that only a single ovn-ic has the permission to\n+                 * write to IC-SB.\n+                 */\n+                VLOG_INFO(\"OVN ISB lock acquired. \"\n+                          \"This ovn-ic instance is now active.\");\n+                ovsdb_idl_set_lock(ovnisb_idl_loop.idl, \"ovn_ic_sb\");\n+            }\n+\n             struct ovsdb_idl_txn *ovnnb_txn =\n                 run_idl_loop(&ovnnb_idl_loop, \"OVN_Northbound\",\n                              &eng_ctx.nb_idl_duration_ms);\n@@ -3759,6 +3819,20 @@ main(int argc, char *argv[])\n                 ovnisb_cond_seqno = new_ovnisb_cond_seqno;\n             }\n \n+            struct ovsdb_idl_txn *ovnisb_unlocked_txn =\n+                run_idl_loop(&ovnisb_unlocked_idl_loop, \"OVN_IC_Southbound\",\n+                             &eng_ctx.isb_unlock_idl_duration_ms);\n+            unsigned int new_ovnisb_unlocked_cond_seqno =\n+                ovsdb_idl_get_condition_seqno(ovnisb_unlocked_idl_loop.idl);\n+            if (new_ovnisb_unlocked_cond_seqno != ovnisb_unlocked_cond_seqno) {\n+                if (!new_ovnisb_unlocked_cond_seqno) {\n+                    VLOG_INFO(\"OVN ISB IDL Unlocked reconnected, \"\n+                              \"force recompute.\");\n+                    inc_proc_ic_force_recompute();\n+                }\n+                ovnisb_unlocked_cond_seqno = new_ovnisb_unlocked_cond_seqno;\n+            }\n+\n             struct ic_context ctx = {\n                 .ovnnb_idl = ovnnb_idl_loop.idl,\n                 .ovnnb_txn = ovnnb_txn,\n@@ -3768,6 +3842,8 @@ main(int argc, char *argv[])\n                 .ovninb_txn = ovninb_txn,\n                 .ovnisb_idl = ovnisb_idl_loop.idl,\n                 .ovnisb_txn = ovnisb_txn,\n+                .ovnisb_unlocked_idl = ovnisb_unlocked_idl_loop.idl,\n+                .ovnisb_unlocked_txn = ovnisb_unlocked_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@@ -3815,15 +3891,17 @@ main(int argc, char *argv[])\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+                ovsdb_idl_has_ever_connected(ctx.ovnisb_idl) &&\n+                ovsdb_idl_has_ever_connected(ctx.ovnisb_unlocked_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.ovnisb_unlocked_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+                        update_sequence_numbers(&ctx,\n+                                                &ovnisb_unlocked_idl_loop);\n                     }\n                 } else if (!inc_proc_ic_get_force_recompute()) {\n                     clear_idl_track = false;\n@@ -3847,10 +3925,21 @@ main(int argc, char *argv[])\n                                 \"force recompute next time.\");\n                     inc_proc_ic_force_recompute_immediate();\n                 }\n+                if (!ovsdb_idl_loop_commit_and_wait(\n+                                          &ovnisb_unlocked_idl_loop)) {\n+                    VLOG_INFO(\"OVNISB Unlocked commit failed, \"\n+                                \"force recompute next time.\");\n+                    inc_proc_ic_force_recompute_immediate();\n+                }\n \n-                if (!ovsdb_idl_loop_commit_and_wait(&ovnisb_idl_loop)) {\n+                /*\n+                 * ovn-ic will only try to recompute a failed transaction from\n+                 * the locked connection IF the AZ has the lock.\n+                 */\n+                if (!ovsdb_idl_loop_commit_and_wait(&ovnisb_idl_loop) &&\n+                    ovsdb_idl_has_lock(ovnisb_idl_loop.idl)) {\n                     VLOG_INFO(\"OVNISB commit failed, \"\n-                                \"force recompute next time.\");\n+                              \"force recompute next time.\");\n                     inc_proc_ic_force_recompute_immediate();\n                 }\n             } else {\n@@ -3859,10 +3948,13 @@ main(int argc, char *argv[])\n                 int rc2 = ovsdb_idl_loop_commit_and_wait(&ovnsb_idl_loop);\n                 int rc3 = ovsdb_idl_loop_commit_and_wait(&ovninb_idl_loop);\n                 int rc4 = ovsdb_idl_loop_commit_and_wait(&ovnisb_idl_loop);\n-                if (!rc1 || !rc2 || !rc3 || !rc4) {\n-                    VLOG_DBG(\" a transaction failed in: %s %s %s %s\",\n+                int rc5 =\n+                    ovsdb_idl_loop_commit_and_wait(&ovnisb_unlocked_idl_loop);\n+                if (!rc1 || !rc2 || !rc3 || !rc4 || !rc5) {\n+                    VLOG_DBG(\" a transaction failed in: %s %s %s %s %s\",\n                             !rc1 ? \"nb\" : \"\", !rc2 ? \"sb\" : \"\",\n-                            !rc3 ? \"ic_nb\" : \"\", !rc4 ? \"ic_sb\" : \"\");\n+                             !rc3 ? \"ic_nb\" : \"\", !rc4 ? \"ic_sb\" : \"\",\n+                             !rc5 ? \"ic_sb_unlocked\" : \"\");\n                     /* A transaction failed. Wake up immediately to give\n                     * opportunity to send the proper transaction\n                     */\n@@ -3877,9 +3969,14 @@ main(int argc, char *argv[])\n              *      copy will be out of sync.\n              *    - but we don't want to create any txns.\n              * */\n+            if (ovsdb_idl_has_lock(ovnisb_idl_loop.idl)) {\n+                VLOG_INFO(\"This ovn-ic instance is now paused. \"\n+                          \"Removing IC-SB lock.\");\n+                ovsdb_idl_set_lock(ovnisb_idl_loop.idl, NULL);\n+            }\n+\n             if (ovsdb_idl_has_lock(ovnsb_idl_loop.idl) ||\n-                ovsdb_idl_is_lock_contended(ovnsb_idl_loop.idl))\n-            {\n+                ovsdb_idl_is_lock_contended(ovnsb_idl_loop.idl)) {\n                 /* make sure we don't hold the lock while paused */\n                 VLOG_INFO(\"This ovn-ic instance is now paused.\");\n                 ovsdb_idl_set_lock(ovnsb_idl_loop.idl, NULL);\n@@ -3890,10 +3987,12 @@ main(int argc, char *argv[])\n             ovsdb_idl_run(ovnsb_idl_loop.idl);\n             ovsdb_idl_run(ovninb_idl_loop.idl);\n             ovsdb_idl_run(ovnisb_idl_loop.idl);\n+            ovsdb_idl_run(ovnisb_unlocked_idl_loop.idl);\n             ovsdb_idl_wait(ovnnb_idl_loop.idl);\n             ovsdb_idl_wait(ovnsb_idl_loop.idl);\n             ovsdb_idl_wait(ovninb_idl_loop.idl);\n             ovsdb_idl_wait(ovnisb_idl_loop.idl);\n+            ovsdb_idl_wait(ovnisb_unlocked_idl_loop.idl);\n \n             /* Force a full recompute next time we become active. */\n             inc_proc_ic_force_recompute_immediate();\n@@ -3904,6 +4003,7 @@ main(int argc, char *argv[])\n             ovsdb_idl_track_clear(ovnsb_idl_loop.idl);\n             ovsdb_idl_track_clear(ovninb_idl_loop.idl);\n             ovsdb_idl_track_clear(ovnisb_idl_loop.idl);\n+            ovsdb_idl_track_clear(ovnisb_unlocked_idl_loop.idl);\n         }\n \n         unixctl_server_run(unixctl);\n@@ -3925,6 +4025,7 @@ main(int argc, char *argv[])\n     ovsdb_idl_loop_destroy(&ovnsb_idl_loop);\n     ovsdb_idl_loop_destroy(&ovninb_idl_loop);\n     ovsdb_idl_loop_destroy(&ovnisb_idl_loop);\n+    ovsdb_idl_loop_destroy(&ovnisb_unlocked_idl_loop);\n     service_stop();\n \n     exit(res);\ndiff --git a/ic/ovn-ic.h b/ic/ovn-ic.h\nindex 7391a19d4..9f52bb0f9 100644\n--- a/ic/ovn-ic.h\n+++ b/ic/ovn-ic.h\n@@ -22,10 +22,12 @@ struct ic_context {\n     struct ovsdb_idl *ovnsb_idl;\n     struct ovsdb_idl *ovninb_idl;\n     struct ovsdb_idl *ovnisb_idl;\n+    struct ovsdb_idl *ovnisb_unlocked_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 ovsdb_idl_txn *ovnisb_unlocked_txn;\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;\ndiff --git a/tests/ovn-ic.at b/tests/ovn-ic.at\nindex 50270fdda..68adc480c 100644\n--- a/tests/ovn-ic.at\n+++ b/tests/ovn-ic.at\n@@ -4793,3 +4793,47 @@ OVN_CLEANUP_IC([az1], [az2])\n \n AT_CLEANUP\n ])\n+\n+OVN_FOR_EACH_NORTHD([\n+AT_SETUP([ovn-ic - IC-SB lock acquisition and transit switch creation])\n+\n+ovn_init_ic_db\n+ovn_start az1\n+ovn_start az2\n+\n+wait_row_count ic-sb:Availability_Zone 2\n+\n+ovn_as az1\n+check ovn-ic-nbctl ts-add ts1\n+\n+wait_row_count ic-sb:Datapath_Binding 1 transit_switch=ts1\n+as az1 check ovn-appctl -t ic/ovn-ic pause\n+\n+ovn_as az2\n+check ovn-ic-nbctl ts-add ts2\n+wait_row_count ic-sb:Datapath_Binding 1 transit_switch=ts2\n+\n+check_row_count ic-sb:Datapath_Binding 2\n+check_column \"ts1 ts2\" ic-sb:Datapath_Binding transit_switch\n+\n+as az1 check ovn-appctl -t ic/ovn-ic resume\n+\n+as az2 check ovn-appctl -t ic/ovn-ic pause\n+\n+ovn_as az1\n+check ovn-ic-nbctl ts-add ts3\n+\n+wait_row_count ic-sb:Datapath_Binding 1 transit_switch=ts3\n+check_row_count ic-sb:Datapath_Binding 3\n+check_column \"ts1 ts2 ts3\" ic-sb:Datapath_Binding transit_switch\n+\n+as az2 check ovn-appctl -t ic/ovn-ic resume\n+\n+for i in 1 2; do\n+    az=az$i\n+    ovn_as $az\n+    OVN_CLEANUP_AZ([$az])\n+done\n+\n+AT_CLEANUP\n+])\n\\ No newline at end of file\n",
    "prefixes": [
        "ovs-dev",
        "v5"
    ]
}