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
