get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2194255,
    "url": "http://patchwork.ozlabs.org/api/patches/2194255/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/ovn/patch/20260207214852.86991-5-arukomoinikova@k2.cloud/",
    "project": {
        "id": 68,
        "url": "http://patchwork.ozlabs.org/api/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": "<20260207214852.86991-5-arukomoinikova@k2.cloud>",
    "list_archive_url": null,
    "date": "2026-02-07T21:48:46",
    "name": "[ovs-dev,5/8,v2] northd: Sync LSP service monitor status to NB for CMS visibility.",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": false,
    "hash": "044c18bf94f4d0648dd6087c92c409d05f546615",
    "submitter": {
        "id": 89461,
        "url": "http://patchwork.ozlabs.org/api/people/89461/?format=api",
        "name": "Rukomoinikova Aleksandra",
        "email": "ARukomoinikova@k2.cloud"
    },
    "delegate": {
        "id": 94943,
        "url": "http://patchwork.ozlabs.org/api/users/94943/?format=api",
        "username": "dceara",
        "first_name": "Dumitru",
        "last_name": "Ceara",
        "email": "dceara@redhat.com"
    },
    "mbox": "http://patchwork.ozlabs.org/project/ovn/patch/20260207214852.86991-5-arukomoinikova@k2.cloud/mbox/",
    "series": [
        {
            "id": 491397,
            "url": "http://patchwork.ozlabs.org/api/series/491397/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/ovn/list/?series=491397",
            "date": "2026-02-07T21:48:46",
            "name": "[ovs-dev,1/8,v2] ovn-nb, ovn-nbctl: Add Logical Switch Port Health Check support.",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/491397/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2194255/comments/",
    "check": "success",
    "checks": "http://patchwork.ozlabs.org/api/patches/2194255/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=k2.cloud header.i=@k2.cloud header.a=rsa-sha256\n header.s=cloudmail header.b=kG3B/vEw;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=2605:bc80:3010::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 header.d=k2.cloud header.i=@k2.cloud header.a=rsa-sha256 header.s=cloudmail\n header.b=kG3B/vEw",
            "smtp3.osuosl.org;\n dmarc=pass (p=none dis=none) header.from=k2.cloud"
        ],
        "Received": [
            "from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::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 4f7l363YS5z1xvW\n\tfor <incoming@patchwork.ozlabs.org>; Sun, 08 Feb 2026 08:49:06 +1100 (AEDT)",
            "from localhost (localhost [127.0.0.1])\n\tby smtp3.osuosl.org (Postfix) with ESMTP id BE3F861256;\n\tSat,  7 Feb 2026 21:49:04 +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 TU_VFcT08s8s; Sat,  7 Feb 2026 21:49:03 +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 A37DA60744;\n\tSat,  7 Feb 2026 21:49:03 +0000 (UTC)",
            "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id 4E3FBC0781;\n\tSat,  7 Feb 2026 21:49:03 +0000 (UTC)",
            "from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n by lists.linuxfoundation.org (Postfix) with ESMTP id E355CC077E\n for <dev@openvswitch.org>; Sat,  7 Feb 2026 21:49:00 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n by smtp3.osuosl.org (Postfix) with ESMTP id BBB9F6078A\n for <dev@openvswitch.org>; Sat,  7 Feb 2026 21:49:00 +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 jZ60368Cihij for <dev@openvswitch.org>;\n Sat,  7 Feb 2026 21:48:59 +0000 (UTC)",
            "from mail1.k2.cloud (mail1.k2.cloud [109.73.14.252])\n by smtp3.osuosl.org (Postfix) with ESMTPS id DDA2C60744\n for <dev@openvswitch.org>; Sat,  7 Feb 2026 21:48:58 +0000 (UTC)"
        ],
        "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 A37DA60744",
            "OpenDKIM Filter v2.11.0 smtp3.osuosl.org DDA2C60744"
        ],
        "Received-SPF": "Pass (mailfrom) identity=mailfrom; client-ip=109.73.14.252;\n helo=mail1.k2.cloud; envelope-from=arukomoinikova@k2.cloud;\n receiver=<UNKNOWN>",
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 smtp3.osuosl.org DDA2C60744",
        "From": "Alexandra Rukomoinikova <arukomoinikova@k2.cloud>",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=k2.cloud;\n s=cloudmail; t=1770500936;\n bh=Naze1e6Q623e4rvWyNBn9tBZtxNMSaZYOs2LgHM1dYY=;\n h=From:To:Cc:Subject:Date:In-Reply-To:References;\n b=kG3B/vEwnXgEbpKmo88hafyceZyxQ6GjS/+SVETFodJtxiZ1oNIal9IheLME0K7N+\n iPxZXwzOnjvy8CHLseBWqRzVkEK10aLLTc++YmOid2llqRNtTUlOSZHu5avGQDdwk0\n ZSXBq5zaV32QdhFBgFzmnz6/b4l8PD7E9I2Pack8=",
        "To": "dev@openvswitch.org",
        "Cc": "Alexandra Rukomoinikova <arukomoinikova@k2.cloud>",
        "Date": "Sun,  8 Feb 2026 00:48:46 +0300",
        "Message-Id": "<20260207214852.86991-5-arukomoinikova@k2.cloud>",
        "In-Reply-To": "<20260207214852.86991-1-arukomoinikova@k2.cloud>",
        "References": "<20260207214852.86991-1-arukomoinikova@k2.cloud>",
        "MIME-Version": "1.0",
        "Subject": "[ovs-dev] [PATCH ovn 5/8 v2] northd: Sync LSP service monitor\n status to NB for CMS visibility.",
        "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>",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Errors-To": "ovs-dev-bounces@openvswitch.org",
        "Sender": "\"dev\" <ovs-dev-bounces@openvswitch.org>"
    },
    "content": "Propagate health status from SB Service_Monitor to NB\nLogical_Switch_Port_Health_Check table.\n\nThis synchronization enables CMS (Cloud Management System) to make\ninformed decisions about virtual machine availability, routing, and\nfailover based on the current health status of monitored service\n\nSigned-off-by: Alexandra Rukomoinikova <arukomoinikova@k2.cloud>\n---\nv1 --> v2: added DOC\n---\n northd/en-sync-from-sb.c         |  4 ++\n northd/en-sync-from-sb.h         |  3 ++\n northd/inc-proc-northd.c         |  8 +++\n northd/northd.c                  | 83 ++++++++++++++++++++++++++++++++\n ovn-nb.ovsschema                 |  8 ++-\n ovn-nb.xml                       |  8 +++\n tests/ovn-inc-proc-graph-dump.at |  1 +\n tests/system-ovn.at              |  6 +++\n 8 files changed, 119 insertions(+), 2 deletions(-)",
    "diff": "diff --git a/northd/en-sync-from-sb.c b/northd/en-sync-from-sb.c\nindex 6d4ff3e39..11f3886dc 100644\n--- a/northd/en-sync-from-sb.c\n+++ b/northd/en-sync-from-sb.c\n@@ -52,6 +52,10 @@ en_sync_from_sb_get_input_data(struct engine_node *node,\n         EN_OVSDB_GET(engine_get_input(\"SB_port_binding\", node));\n     data->sb_ha_ch_grp_table =\n         EN_OVSDB_GET(engine_get_input(\"SB_ha_chassis_group\", node));\n+    data->sbrec_service_monitor_by_service_type =\n+        engine_ovsdb_node_get_index(\n+            engine_get_input(\"SB_service_monitor\", node),\n+            \"sbrec_service_monitor_by_service_type\");\n }\n \n enum engine_node_state\ndiff --git a/northd/en-sync-from-sb.h b/northd/en-sync-from-sb.h\nindex bea248c45..177d75de0 100644\n--- a/northd/en-sync-from-sb.h\n+++ b/northd/en-sync-from-sb.h\n@@ -7,6 +7,9 @@ struct en_sync_from_sb_data {\n     /* Southbound table references */\n     const struct sbrec_port_binding_table *sb_pb_table;\n     const struct sbrec_ha_chassis_group_table *sb_ha_ch_grp_table;\n+\n+    /* Indexes */\n+    struct ovsdb_idl_index *sbrec_service_monitor_by_service_type;\n };\n \n void *en_sync_from_sb_init(struct engine_node *, struct engine_arg *);\ndiff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c\nindex 732066638..8f6f491fb 100644\n--- a/northd/inc-proc-northd.c\n+++ b/northd/inc-proc-northd.c\n@@ -478,6 +478,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,\n                      sync_from_sb_northd_handler);\n     engine_add_input(&en_sync_from_sb, &en_sb_port_binding, NULL);\n     engine_add_input(&en_sync_from_sb, &en_sb_ha_chassis_group, NULL);\n+    engine_add_input(&en_sync_from_sb, &en_sb_service_monitor, NULL);\n \n     engine_add_input(&en_northd_output, &en_acl_id, NULL);\n     engine_add_input(&en_northd_output, &en_sync_from_sb, NULL);\n@@ -593,6 +594,13 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,\n                                 \"sbrec_service_monitor_by_learned_type\",\n                                 sbrec_service_monitor_by_learned_type);\n \n+    struct ovsdb_idl_index *sbrec_service_monitor_by_service_type\n+        = ovsdb_idl_index_create1(sb->idl,\n+                                  &sbrec_service_monitor_col_type);\n+    engine_ovsdb_node_add_index(&en_sb_service_monitor,\n+                                \"sbrec_service_monitor_by_service_type\",\n+                                sbrec_service_monitor_by_service_type);\n+\n     struct ed_type_global_config *global_config =\n         engine_get_internal_data(&en_global_config);\n     unixctl_command_register(\"debug/chassis-features-list\", \"\", 0, 0,\ndiff --git a/northd/northd.c b/northd/northd.c\nindex 1904b162b..b11a57ca9 100644\n--- a/northd/northd.c\n+++ b/northd/northd.c\n@@ -21089,6 +21089,85 @@ handle_port_binding_changes(\n     hmapx_destroy(&lr_groups);\n }\n \n+static bool\n+svc_monitor_matches_health_check(const struct sbrec_service_monitor *sbrec_mon,\n+                                 const char *protocol,\n+                                 const char *src_ip,\n+                                 const char *target_ip,\n+                                 uint16_t destination_port)\n+{\n+    if (strcmp(sbrec_mon->protocol, protocol) != 0) {\n+        return false;\n+    }\n+\n+    if (!strcmp(protocol, \"tcp\") || !strcmp(protocol, \"udp\")) {\n+        if (sbrec_mon->port != destination_port) {\n+            return false;\n+        }\n+    }\n+\n+    if (!strcmp(sbrec_mon->src_ip, src_ip)) {\n+        return true;\n+    }\n+\n+    if (!strcmp(sbrec_mon->ip, target_ip)) {\n+        return true;\n+    }\n+\n+    return false;\n+}\n+\n+static void\n+handle_service_monitor_changes(\n+        struct ovsdb_idl_index *sbrec_service_monitor_by_service_type,\n+        const struct hmap *ls_ports)\n+{\n+    const struct sbrec_service_monitor *sbrec_mon;\n+    struct sbrec_service_monitor *key =\n+        sbrec_service_monitor_index_init_row(\n+            sbrec_service_monitor_by_service_type);\n+\n+    sbrec_service_monitor_set_type(key, \"logical-switch-port\");\n+\n+    SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sbrec_mon, key,\n+            sbrec_service_monitor_by_service_type) {\n+\n+        struct ovn_port *op = ovn_port_find(ls_ports,\n+                                            sbrec_mon->logical_port);\n+        if (!op) {\n+            continue;\n+        }\n+\n+        ovs_assert(op->nbsp && op->nbsp->n_health_checks);\n+\n+        /* There shouldn't be many health checks on port,\n+         * liniar check shouldn't be heavy. */\n+        for (size_t i = 0; i < op->nbsp->n_health_checks; i++) {\n+            const struct nbrec_logical_switch_port_health_check *lsp_hc =\n+                op->nbsp->health_checks[i];\n+\n+            if (!svc_monitor_matches_health_check(sbrec_mon,\n+                                                  lsp_hc->protocol,\n+                                                  lsp_hc->src_ip,\n+                                                  lsp_hc->address,\n+                                                  lsp_hc->port)) {\n+                continue;\n+            }\n+\n+            const char *desired_status = sbrec_mon->status;\n+            if (desired_status) {\n+                if (!lsp_hc->status ||\n+                    strcmp(lsp_hc->status, desired_status)) {\n+                    nbrec_logical_switch_port_health_check_set_status(\n+                        lsp_hc, sbrec_mon->status);\n+                }\n+            }\n+        }\n+    }\n+\n+    sbrec_service_monitor_index_destroy_row(key);\n+}\n+\n /* Handle a fairly small set of changes in the southbound database. */\n void\n ovnsb_db_run(struct ovsdb_idl_txn *ovnsb_txn,\n@@ -21106,6 +21185,10 @@ ovnsb_db_run(struct ovsdb_idl_txn *ovnsb_txn,\n                                 &northd_data->lr_ports,\n                                 &ha_ref_chassis_map);\n \n+    handle_service_monitor_changes(\n+        sync_from_sb_data->sbrec_service_monitor_by_service_type,\n+        &northd_data->ls_ports);\n+\n     update_sb_ha_group_ref_chassis(sync_from_sb_data->sb_ha_ch_grp_table,\n                                    &ha_ref_chassis_map);\n \ndiff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema\nindex 538b37456..6892713dc 100644\n--- a/ovn-nb.ovsschema\n+++ b/ovn-nb.ovsschema\n@@ -1,7 +1,7 @@\n {\n     \"name\": \"OVN_Northbound\",\n-    \"version\": \"7.16.0\",\n-    \"cksum\": \"3492890733 44939\",\n+    \"version\": \"7.17.0\",\n+    \"cksum\": \"4065801885 45152\",\n     \"tables\": {\n         \"NB_Global\": {\n             \"columns\": {\n@@ -264,6 +264,10 @@\n                 \"address\": {\"type\": {\"key\": \"string\",\n                                        \"min\": 0,\n                                        \"max\": 1}},\n+                \"status\": {\n+                    \"type\": {\"key\": {\"type\": \"string\",\n+                             \"enum\": [\"set\", [\"online\", \"offline\", \"error\"]]},\n+                             \"min\": 0, \"max\": 1}},\n                 \"options\": {\n                      \"type\": {\"key\": \"string\",\n                               \"value\": \"string\",\ndiff --git a/ovn-nb.xml b/ovn-nb.xml\nindex e60edbd8d..e71d33b2a 100644\n--- a/ovn-nb.xml\n+++ b/ovn-nb.xml\n@@ -2225,6 +2225,14 @@\n       IP address to monitor for the health check.\n     </column>\n \n+    <column name=\"status\">\n+      Health status synchronized from the <code>status</code> field of\n+      corresponding service monitor in the SBDB. This status indicates\n+      the current availability of logical switch port for the CMS to\n+      determine service virtual machine health and make routing or\n+      failover decisions.\n+    </column>\n+\n     <column name=\"options\" key=\"interval\" type='{\"type\": \"integer\"}'>\n       The interval, in seconds, between service monitor checks.\n     </column>\ndiff --git a/tests/ovn-inc-proc-graph-dump.at b/tests/ovn-inc-proc-graph-dump.at\nindex ff2c8c0c7..0122a6a4f 100644\n--- a/tests/ovn-inc-proc-graph-dump.at\n+++ b/tests/ovn-inc-proc-graph-dump.at\n@@ -99,6 +99,7 @@ digraph \"Incremental-Processing-Engine\" {\n \tnorthd -> sync_from_sb [[label=\"sync_from_sb_northd_handler\"]];\n \tSB_port_binding -> sync_from_sb [[label=\"\"]];\n \tSB_ha_chassis_group -> sync_from_sb [[label=\"\"]];\n+\tSB_service_monitor -> sync_from_sb [[label=\"\"]];\n \tlr_nat [[style=filled, shape=box, fillcolor=white, label=\"lr_nat\"]];\n \tnorthd -> lr_nat [[label=\"lr_nat_northd_handler\"]];\n \tlr_stateful [[style=filled, shape=box, fillcolor=white, label=\"lr_stateful\"]];\ndiff --git a/tests/system-ovn.at b/tests/system-ovn.at\nindex 14c0996a0..3ac4f2442 100644\n--- a/tests/system-ovn.at\n+++ b/tests/system-ovn.at\n@@ -21033,6 +21033,7 @@ check_row_count sb:Service_Monitor 1\n \n # Wait until the services are set to online.\n wait_row_count Service_Monitor 1 status=online\n+wait_row_count nb:Logical_Switch_Port_Health_Check 1 status=online protocol=icmp\n \n check ovn-nbctl lsp-hc-add lport tcp 192.168.0.255 4041 192.168.0.10\n \n@@ -21043,12 +21044,14 @@ NETNS_DAEMONIZE([lport], [nc -l -k 192.168.0.10 4041], [lport_tcp.pid])\n \n # Wait until the services are set to online.\n wait_row_count Service_Monitor 2 status=online\n+wait_row_count nb:Logical_Switch_Port_Health_Check 1 status=online protocol=tcp\n \n check ovn-nbctl lsp-hc-add lport udp 192.168.0.255 4042 192.168.0.10\n \n NETNS_DAEMONIZE([lport], [nc -ulp 4042], [lport_udp.pid])\n \n # Wait until the services are set to online.\n+wait_row_count nb:Logical_Switch_Port_Health_Check 1 status=online protocol=udp\n wait_row_count Service_Monitor 3 status=online\n \n check ovn-nbctl lsp-hc-del lport\n@@ -21059,6 +21062,7 @@ check_row_count sb:Service_Monitor 1\n \n # Wait until the services are set to online.\n wait_row_count Service_Monitor 1 status=online\n+wait_row_count nb:Logical_Switch_Port_Health_Check 1 status=online protocol=icmp\n \n # IPv6 TCP health check\n check ovn-nbctl lsp-hc-add lport tcp 2001:db8::ff 4043 2001:db8::10\n@@ -21070,6 +21074,7 @@ NETNS_DAEMONIZE([lport], [nc -6 -l -k 2001:db8::10 4043], [lport_ipv6_tcp.pid])\n \n # Wait until the services are set to online.\n wait_row_count Service_Monitor 2 status=online\n+wait_row_count nb:Logical_Switch_Port_Health_Check 1 status=online protocol=tcp\n \n # IPv6 UDP health check\n check ovn-nbctl lsp-hc-add lport udp 2001:db8::ff 4044 2001:db8::10\n@@ -21080,6 +21085,7 @@ NETNS_DAEMONIZE([lport], [nc -6 -u -l 2001:db8::10 4044], [lport_ipv6_udp.pid])\n \n # Wait until the services are set to online.\n wait_row_count Service_Monitor 3 status=online\n+wait_row_count nb:Logical_Switch_Port_Health_Check 1 status=online protocol=udp\n \n killall nc 2>/dev/null || true\n \n",
    "prefixes": [
        "ovs-dev",
        "5/8",
        "v2"
    ]
}