Propagate health status from SB Service_Monitor to NB
Logical_Switch_Port_Health_Check table.

This synchronization enables CMS (Cloud Management System) to make
informed decisions about virtual machine availability, routing, and
failover based on the current health status of monitored service

Signed-off-by: Alexandra Rukomoinikova <[email protected]>
---
v2 --> v3: fixed Dumitru's comments
---
 northd/en-sync-from-sb.c         |  6 +++
 northd/inc-proc-northd.c         |  8 ++++
 northd/northd.c                  | 82 ++++++++++++++++++++++++++++++++
 northd/northd.h                  |  1 +
 ovn-nb.ovsschema                 |  8 +++-
 ovn-nb.xml                       |  8 ++++
 tests/ovn-inc-proc-graph-dump.at |  1 +
 tests/system-ovn.at              |  6 +++
 8 files changed, 118 insertions(+), 2 deletions(-)

diff --git a/northd/en-sync-from-sb.c b/northd/en-sync-from-sb.c
index de822115d..bb61638a5 100644
--- a/northd/en-sync-from-sb.c
+++ b/northd/en-sync-from-sb.c
@@ -50,8 +50,14 @@ en_sync_from_sb_run(struct engine_node *node, void *data 
OVS_UNUSED)
         EN_OVSDB_GET(engine_get_input("SB_port_binding", node));
     const struct sbrec_ha_chassis_group_table *sb_ha_ch_grp_table =
         EN_OVSDB_GET(engine_get_input("SB_ha_chassis_group", node));
+    struct ovsdb_idl_index *sbrec_service_monitor_by_service_type =
+        engine_ovsdb_node_get_index(
+            engine_get_input("SB_service_monitor", node),
+            "sbrec_service_monitor_by_service_type");
+
     ovnsb_db_run(eng_ctx->ovnsb_idl_txn,
                  sb_pb_table, sb_ha_ch_grp_table,
+                 sbrec_service_monitor_by_service_type,
                  &nd->ls_ports, &nd->lr_ports);
 
     return EN_UNCHANGED;
diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
index 732066638..b79272324 100644
--- a/northd/inc-proc-northd.c
+++ b/northd/inc-proc-northd.c
@@ -477,6 +477,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
     engine_add_input(&en_sync_from_sb, &en_northd,
                      sync_from_sb_northd_handler);
     engine_add_input(&en_sync_from_sb, &en_sb_port_binding, NULL);
+    engine_add_input(&en_sync_from_sb, &en_sb_service_monitor, NULL);
     engine_add_input(&en_sync_from_sb, &en_sb_ha_chassis_group, NULL);
 
     engine_add_input(&en_northd_output, &en_acl_id, NULL);
@@ -593,6 +594,13 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
                                 "sbrec_service_monitor_by_learned_type",
                                 sbrec_service_monitor_by_learned_type);
 
+    struct ovsdb_idl_index *sbrec_service_monitor_by_service_type
+        = ovsdb_idl_index_create1(sb->idl,
+                                  &sbrec_service_monitor_col_type);
+    engine_ovsdb_node_add_index(&en_sb_service_monitor,
+                                "sbrec_service_monitor_by_service_type",
+                                sbrec_service_monitor_by_service_type);
+
     struct ed_type_global_config *global_config =
         engine_get_internal_data(&en_global_config);
     unixctl_command_register("debug/chassis-features-list", "", 0, 0,
diff --git a/northd/northd.c b/northd/northd.c
index 90d8edfe9..98f97af26 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -21245,11 +21245,91 @@ handle_port_binding_changes(const struct 
sbrec_port_binding_table *sb_pb_table,
     hmapx_destroy(&lr_groups);
 }
 
+static bool
+svc_monitor_matches_health_check(const struct sbrec_service_monitor *sbrec_mon,
+                                 const char *protocol,
+                                 const char *src_ip,
+                                 const char *target_ip,
+                                 uint16_t destination_port)
+{
+    if (strcmp(sbrec_mon->protocol, protocol) != 0) {
+        return false;
+    }
+
+    if (!strcmp(protocol, "tcp") || !strcmp(protocol, "udp")) {
+        if (sbrec_mon->port != destination_port) {
+            return false;
+        }
+    }
+
+    if (!strcmp(sbrec_mon->src_ip, src_ip)) {
+        return true;
+    }
+
+    if (!strcmp(sbrec_mon->ip, target_ip)) {
+        return true;
+    }
+
+    return false;
+}
+
+static void
+handle_service_monitor_changes(
+    struct ovsdb_idl_index *sbrec_service_monitor_by_service_type,
+    const struct hmap *ls_ports)
+{
+    const struct sbrec_service_monitor *sbrec_mon;
+    struct sbrec_service_monitor *key =
+        sbrec_service_monitor_index_init_row(
+            sbrec_service_monitor_by_service_type);
+
+    sbrec_service_monitor_set_type(key, "logical-switch-port");
+
+    SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sbrec_mon, key,
+            sbrec_service_monitor_by_service_type) {
+
+        struct ovn_port *op = ovn_port_find(ls_ports,
+                                            sbrec_mon->logical_port);
+        if (!op) {
+            continue;
+        }
+
+        ovs_assert(op->nbsp && op->nbsp->n_health_checks);
+
+        /* There shouldn't be many health checks on port,
+         * liniar check shouldn't be heavy. */
+        for (size_t i = 0; i < op->nbsp->n_health_checks; i++) {
+            const struct nbrec_logical_switch_port_health_check *lsp_hc =
+                op->nbsp->health_checks[i];
+
+            if (!svc_monitor_matches_health_check(sbrec_mon,
+                                                  lsp_hc->protocol,
+                                                  lsp_hc->src_ip,
+                                                  lsp_hc->address,
+                                                  lsp_hc->port)) {
+                continue;
+            }
+
+            const char *desired_status = sbrec_mon->status;
+            if (desired_status) {
+                if (!lsp_hc->status ||
+                    strcmp(lsp_hc->status, desired_status)) {
+                    nbrec_logical_switch_port_health_check_set_status(
+                        lsp_hc, sbrec_mon->status);
+                }
+            }
+        }
+    }
+
+    sbrec_service_monitor_index_destroy_row(key);
+}
+
 /* Handle a fairly small set of changes in the southbound database. */
 void
 ovnsb_db_run(struct ovsdb_idl_txn *ovnsb_txn,
              const struct sbrec_port_binding_table *sb_pb_table,
              const struct sbrec_ha_chassis_group_table *sb_ha_ch_grp_table,
+             struct ovsdb_idl_index *sbrec_service_monitor_by_service_type,
              struct hmap *ls_ports,
              struct hmap *lr_ports)
 {
@@ -21260,6 +21340,8 @@ ovnsb_db_run(struct ovsdb_idl_txn *ovnsb_txn,
     struct shash ha_ref_chassis_map = SHASH_INITIALIZER(&ha_ref_chassis_map);
     handle_port_binding_changes(sb_pb_table, sb_ha_ch_grp_table,
                                 ls_ports, lr_ports, &ha_ref_chassis_map);
+    handle_service_monitor_changes(sbrec_service_monitor_by_service_type,
+                                   ls_ports);
     update_sb_ha_group_ref_chassis(sb_ha_ch_grp_table, &ha_ref_chassis_map);
 
     shash_destroy(&ha_ref_chassis_map);
diff --git a/northd/northd.h b/northd/northd.h
index c2571fb30..cc05c3b1f 100644
--- a/northd/northd.h
+++ b/northd/northd.h
@@ -905,6 +905,7 @@ void ovnnb_db_run(struct northd_input *input_data,
 void ovnsb_db_run(struct ovsdb_idl_txn *ovnsb_txn,
                   const struct sbrec_port_binding_table *,
                   const struct sbrec_ha_chassis_group_table *,
+                  struct ovsdb_idl_index *,
                   struct hmap *ls_ports,
                   struct hmap *lr_ports);
 bool northd_handle_ls_changes(struct ovsdb_idl_txn *,
diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema
index fea4cd130..07ad1f467 100644
--- a/ovn-nb.ovsschema
+++ b/ovn-nb.ovsschema
@@ -1,7 +1,7 @@
 {
     "name": "OVN_Northbound",
-    "version": "7.17.0",
-    "cksum": "2579043495 45129",
+    "version": "7.18.0",
+    "cksum": "3798579343 45342",
     "tables": {
         "NB_Global": {
             "columns": {
@@ -268,6 +268,10 @@
                 "address": {"type": {"key": "string",
                                      "min": 0,
                                      "max": 1}},
+                "status": {
+                    "type": {"key": {"type": "string",
+                             "enum": ["set", ["online", "offline", "error"]]},
+                             "min": 0, "max": 1}},
                 "options": {
                      "type": {"key": "string",
                               "value": "string",
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 627394cc4..eb52f8c7c 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -2280,6 +2280,14 @@
       IP address to monitor for the health check.
     </column>
 
+    <column name="status">
+      Health status synchronized from the <code>status</code> field of
+      corresponding service monitor in the SBDB. This status indicates
+      the current availability of logical switch port for the CMS to
+      determine service virtual machine health and make routing or
+      failover decisions.
+    </column>
+
     <column name="options" key="interval" type='{"type": "integer"}'>
       The interval, in seconds, between service monitor checks.
     </column>
diff --git a/tests/ovn-inc-proc-graph-dump.at b/tests/ovn-inc-proc-graph-dump.at
index ff2c8c0c7..a31aad6e7 100644
--- a/tests/ovn-inc-proc-graph-dump.at
+++ b/tests/ovn-inc-proc-graph-dump.at
@@ -98,6 +98,7 @@ digraph "Incremental-Processing-Engine" {
        sync_from_sb [[style=filled, shape=box, fillcolor=white, 
label="sync_from_sb"]];
        northd -> sync_from_sb [[label="sync_from_sb_northd_handler"]];
        SB_port_binding -> sync_from_sb [[label=""]];
+       SB_service_monitor -> sync_from_sb [[label=""]];
        SB_ha_chassis_group -> sync_from_sb [[label=""]];
        lr_nat [[style=filled, shape=box, fillcolor=white, label="lr_nat"]];
        northd -> lr_nat [[label="lr_nat_northd_handler"]];
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
index b88455dea..d90843220 100644
--- a/tests/system-ovn.at
+++ b/tests/system-ovn.at
@@ -21037,6 +21037,7 @@ check_row_count sb:Service_Monitor 1
 
 # Wait until the services are set to online.
 wait_row_count Service_Monitor 1 status=online
+wait_row_count nb:Logical_Switch_Port_Health_Check 1 status=online 
protocol=icmp
 
 check ovn-nbctl lsp-hc-add lport tcp 192.168.0.250 4041 192.168.0.10
 
@@ -21047,6 +21048,7 @@ NETNS_DAEMONIZE([lport], [nc -l -k 192.168.0.10 4041], 
[lport_tcp.pid])
 
 # Wait until the services are set to online.
 wait_row_count Service_Monitor 2 status=online
+wait_row_count nb:Logical_Switch_Port_Health_Check 1 status=online protocol=tcp
 
 check ovn-nbctl lsp-hc-add lport udp 192.168.0.250 4042 192.168.0.10
 
@@ -21054,6 +21056,7 @@ NETNS_DAEMONIZE([lport], [nc -ulp 4042], 
[lport_udp.pid])
 
 # Wait until the services are set to online.
 wait_row_count Service_Monitor 3 status=online
+wait_row_count nb:Logical_Switch_Port_Health_Check 1 status=online protocol=udp
 
 check ovn-nbctl lsp-hc-del lport
 
@@ -21063,6 +21066,7 @@ check_row_count sb:Service_Monitor 1
 
 # Wait until the services are set to online.
 wait_row_count Service_Monitor 1 status=online
+wait_row_count nb:Logical_Switch_Port_Health_Check 1 status=online 
protocol=icmp
 
 # IPv6 TCP health check
 check ovn-nbctl lsp-hc-add lport tcp 2001:db8::ff 4043 2001:db8::10
@@ -21074,6 +21078,7 @@ NETNS_DAEMONIZE([lport], [nc -6 -l -k 2001:db8::10 
4043], [lport_ipv6_tcp.pid])
 
 # Wait until the services are set to online.
 wait_row_count Service_Monitor 2 status=online
+wait_row_count nb:Logical_Switch_Port_Health_Check 1 status=online protocol=tcp
 
 # IPv6 UDP health check
 check ovn-nbctl lsp-hc-add lport udp 2001:db8::ff 4044 2001:db8::10
@@ -21084,6 +21089,7 @@ NETNS_DAEMONIZE([lport], [nc -6 -u -l 2001:db8::10 
4044], [lport_ipv6_udp.pid])
 
 # Wait until the services are set to online.
 wait_row_count Service_Monitor 3 status=online
+wait_row_count nb:Logical_Switch_Port_Health_Check 1 status=online protocol=udp
 
 OVN_CLEANUP_CONTROLLER([hv1])
 
-- 
2.48.1

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to