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