On 2/17/26 6:58 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]>
> ---
> v2 --> v3: fixed Dumitru's comments
> ---
Hi Alexandra,
> 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;
As discussed on the other thread this should be:
+ if (strcmp(sbrec_mon->src_ip, src_ip)) {
+ return false;
+ }
+
+ if (strcmp(sbrec_mon->ip, target_ip)) {
+ return false;
+ }
+
+ return true;
> +}
> +
> +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. */
Typo: liniar should be linear.
I fixed this and the "matches" function up and applied the patch to main.
Regards,
Dumitru
> + 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])
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev