On 2/7/26 10:48 PM, Alexandra Rukomoinikova wrote:
> 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]>
> ---

Hi Alexandra,

Thanks for the patch!

> v1 --> v2: added DOC
> ---
>  northd/en-sync-from-sb.c         |  4 ++
>  northd/en-sync-from-sb.h         |  3 ++
>  northd/inc-proc-northd.c         |  8 +++
>  northd/northd.c                  | 83 ++++++++++++++++++++++++++++++++
>  ovn-nb.ovsschema                 |  8 ++-
>  ovn-nb.xml                       |  8 +++
>  tests/ovn-inc-proc-graph-dump.at |  1 +
>  tests/system-ovn.at              |  6 +++
>  8 files changed, 119 insertions(+), 2 deletions(-)
> 
> diff --git a/northd/en-sync-from-sb.c b/northd/en-sync-from-sb.c
> index 6d4ff3e39..11f3886dc 100644
> --- a/northd/en-sync-from-sb.c
> +++ b/northd/en-sync-from-sb.c
> @@ -52,6 +52,10 @@ en_sync_from_sb_get_input_data(struct engine_node *node,
>          EN_OVSDB_GET(engine_get_input("SB_port_binding", node));
>      data->sb_ha_ch_grp_table =
>          EN_OVSDB_GET(engine_get_input("SB_ha_chassis_group", node));
> +    data->sbrec_service_monitor_by_service_type =
> +        engine_ovsdb_node_get_index(
> +            engine_get_input("SB_service_monitor", node),
> +            "sbrec_service_monitor_by_service_type");
>  }
>  
>  enum engine_node_state
> diff --git a/northd/en-sync-from-sb.h b/northd/en-sync-from-sb.h
> index bea248c45..177d75de0 100644
> --- a/northd/en-sync-from-sb.h
> +++ b/northd/en-sync-from-sb.h
> @@ -7,6 +7,9 @@ struct en_sync_from_sb_data {
>      /* Southbound table references */
>      const struct sbrec_port_binding_table *sb_pb_table;
>      const struct sbrec_ha_chassis_group_table *sb_ha_ch_grp_table;
> +
> +    /* Indexes */
> +    struct ovsdb_idl_index *sbrec_service_monitor_by_service_type;
>  };
>  
>  void *en_sync_from_sb_init(struct engine_node *, struct engine_arg *);
> diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
> index 732066638..8f6f491fb 100644
> --- a/northd/inc-proc-northd.c
> +++ b/northd/inc-proc-northd.c
> @@ -478,6 +478,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
>                       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_ha_chassis_group, NULL);
> +    engine_add_input(&en_sync_from_sb, &en_sb_service_monitor, NULL);
>  
>      engine_add_input(&en_northd_output, &en_acl_id, NULL);
>      engine_add_input(&en_northd_output, &en_sync_from_sb, 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 1904b162b..b11a57ca9 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -21089,6 +21089,85 @@ handle_port_binding_changes(
>      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;
> +    }

I think there's a slight error here.  You want to return true if
"mon->src_ip == src_ip AND mon->ip == target_ip" right?

> +
> +    return false;
> +}
> +
> +static void
> +handle_service_monitor_changes(
> +        struct ovsdb_idl_index *sbrec_service_monitor_by_service_type,
> +        const struct hmap *ls_ports)

Nit: these two should be 4 spaces to the left.

> +{
> +    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,
> @@ -21106,6 +21185,10 @@ ovnsb_db_run(struct ovsdb_idl_txn *ovnsb_txn,
>                                  &northd_data->lr_ports,
>                                  &ha_ref_chassis_map);
>  
> +    handle_service_monitor_changes(
> +        sync_from_sb_data->sbrec_service_monitor_by_service_type,
> +        &northd_data->ls_ports);
> +
>      update_sb_ha_group_ref_chassis(sync_from_sb_data->sb_ha_ch_grp_table,
>                                     &ha_ref_chassis_map);
>  
> diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema
> index 538b37456..6892713dc 100644
> --- a/ovn-nb.ovsschema
> +++ b/ovn-nb.ovsschema
> @@ -1,7 +1,7 @@
>  {
>      "name": "OVN_Northbound",
> -    "version": "7.16.0",
> -    "cksum": "3492890733 44939",
> +    "version": "7.17.0",
> +    "cksum": "4065801885 45152",
>      "tables": {
>          "NB_Global": {
>              "columns": {
> @@ -264,6 +264,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 e60edbd8d..e71d33b2a 100644
> --- a/ovn-nb.xml
> +++ b/ovn-nb.xml
> @@ -2225,6 +2225,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..0122a6a4f 100644
> --- a/tests/ovn-inc-proc-graph-dump.at
> +++ b/tests/ovn-inc-proc-graph-dump.at
> @@ -99,6 +99,7 @@ digraph "Incremental-Processing-Engine" {
>       northd -> sync_from_sb [[label="sync_from_sb_northd_handler"]];
>       SB_port_binding -> sync_from_sb [[label=""]];
>       SB_ha_chassis_group -> sync_from_sb [[label=""]];
> +     SB_service_monitor -> sync_from_sb [[label=""]];
>       lr_nat [[style=filled, shape=box, fillcolor=white, label="lr_nat"]];
>       northd -> lr_nat [[label="lr_nat_northd_handler"]];
>       lr_stateful [[style=filled, shape=box, fillcolor=white, 
> label="lr_stateful"]];
> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> index 14c0996a0..3ac4f2442 100644
> --- a/tests/system-ovn.at
> +++ b/tests/system-ovn.at
> @@ -21033,6 +21033,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.255 4041 192.168.0.10
>  
> @@ -21043,12 +21044,14 @@ 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.255 4042 192.168.0.10
>  
>  NETNS_DAEMONIZE([lport], [nc -ulp 4042], [lport_udp.pid])
>  
>  # Wait until the services are set to online.
> +wait_row_count nb:Logical_Switch_Port_Health_Check 1 status=online 
> protocol=udp
>  wait_row_count Service_Monitor 3 status=online
>  
>  check ovn-nbctl lsp-hc-del lport
> @@ -21059,6 +21062,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
> @@ -21070,6 +21074,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
> @@ -21080,6 +21085,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
>  
>  killall nc 2>/dev/null || true
>  

Regards,
Dumitru

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

Reply via email to