This commit adds support for synchronizing load balancer health checks across interconnected availability zones via OVN-IC. Key features include:
1. Added new Service_Monitor table to ICSB database - Tracks service monitors across AZs with source/target zone info - Supports status propagation between zones 2. Implemented synchronization logic in ovn-ic: - Pushes local service monitors to remote AZs via ICSB - Pulls remote monitors into local SBDB as IC-learned - Handles status updates in both directions - Maintains consistency during configuration changes 3. Added comprehensive test casesю 4. Extended OVSDB indexes for efficient lookups. Signed-off-by: Alexandra Rukomoinikova <arukomoinikova@k2.cloud> --- ic/ovn-ic.c | 503 ++++++++++++++++++++++++++++++++++++++++++++ ovn-ic-sb.ovsschema | 32 ++- ovn-ic-sb.xml | 56 +++++ tests/ovn-ic.at | 380 +++++++++++++++++++++++++++++++++ 4 files changed, 968 insertions(+), 3 deletions(-) diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index 0d36b0bf5..52c4c8435 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -70,6 +70,9 @@ struct ic_context { struct ovsdb_idl_index *nbrec_port_by_name; struct ovsdb_idl_index *sbrec_chassis_by_name; struct ovsdb_idl_index *sbrec_port_binding_by_name; + struct ovsdb_idl_index *sbrec_service_monitor_by_local_type; + struct ovsdb_idl_index *sbrec_service_monitor_by_ic_learned; + struct ovsdb_idl_index *sbrec_service_monitor_by_local_type_logical_port; struct ovsdb_idl_index *icnbrec_transit_switch_by_name; struct ovsdb_idl_index *icsbrec_port_binding_by_az; struct ovsdb_idl_index *icsbrec_port_binding_by_ts; @@ -77,6 +80,9 @@ struct ic_context { struct ovsdb_idl_index *icsbrec_route_by_az; struct ovsdb_idl_index *icsbrec_route_by_ts; struct ovsdb_idl_index *icsbrec_route_by_ts_az; + struct ovsdb_idl_index *icsbrec_service_monitor_by_source_az; + struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az; + struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az_logical_port; }; struct ic_state { @@ -95,6 +101,9 @@ static const char *ssl_private_key_file; static const char *ssl_certificate_file; static const char *ssl_ca_cert_file; +static const struct sbrec_port_binding * find_sb_pb_by_name( + struct ovsdb_idl_index *sbrec_port_binding_by_name, const char *name); + static void usage(void) @@ -2182,6 +2191,428 @@ route_run(struct ic_context *ctx) hmap_destroy(&ic_lrs); } +/* + * Data structures and functions related to + * synchronize health checks for load balancers + * between availability zones. + */ +struct sync_service_monitor_data { + /* Map of service monitors to be pushed to other AZs. */ + struct hmap pushed_svcs_map; + /* Map of service monitors synced from other AZs to our. */ + struct hmap synced_svcs_map; + /* Map of local service monitors in the ICSBDB. */ + struct hmap local_ic_svcs_map; + /* Map of local service monitors in SBDB. */ + struct hmap local_sb_svcs_map; + /* MAC address used for service monitor. */ + char *prpg_svc_monitor_mac; +}; + +struct service_monitor_info { + struct hmap_node hmap_node; + union { + const struct sbrec_service_monitor *sb_rec; + const struct icsbrec_service_monitor *ic_rec; + } db_rec; + /* Destination availability zone name. */ + char *dst_az_name; + /* Source availability zone name. */ + char *src_az_name; + /* Chassis name associated with monitor logical port. */ + char *chassis_name; +}; + +static void +create_service_monitor_info(struct hmap *svc_map, + const void *db_rec, + const struct uuid *uuid, + const char *src_az_name, + const char *target_az_name, + const char *chassis_name, + bool ic_rec) +{ + struct service_monitor_info *svc_mon = xzalloc(sizeof(*svc_mon)); + size_t hash = uuid_hash(uuid); + + if (ic_rec) { + svc_mon->db_rec.ic_rec = + (const struct icsbrec_service_monitor *) db_rec; + } else { + svc_mon->db_rec.sb_rec = + (const struct sbrec_service_monitor *) db_rec; + } + + svc_mon->dst_az_name = target_az_name ? xstrdup(target_az_name) : NULL; + svc_mon->chassis_name = chassis_name ? xstrdup(chassis_name) : NULL; + svc_mon->src_az_name = xstrdup(src_az_name); + + hmap_insert(svc_map, &svc_mon->hmap_node, hash); +} + +static void +destroy_service_monitor_info(struct service_monitor_info *svc_mon) +{ + free(svc_mon->src_az_name); + free(svc_mon->dst_az_name); + free(svc_mon->chassis_name); + free(svc_mon); +} + +static void +refresh_sb_record_cache(struct hmap *svc_mon_map, + const struct sbrec_service_monitor *lookup_rec) +{ + size_t hash = uuid_hash(&lookup_rec->header_.uuid); + struct service_monitor_info *svc_mon; + + HMAP_FOR_EACH_WITH_HASH (svc_mon, hmap_node, hash, svc_mon_map) { + ovs_assert(svc_mon->db_rec.sb_rec); + if (svc_mon->db_rec.sb_rec == lookup_rec) { + hmap_remove(svc_mon_map, &svc_mon->hmap_node); + destroy_service_monitor_info(svc_mon); + return; + } + } +} + +static void +refresh_ic_record_cache(struct hmap *svc_mon_map, + const struct icsbrec_service_monitor *lookup_rec) +{ + size_t hash = uuid_hash(&lookup_rec->header_.uuid); + struct service_monitor_info *svc_mon; + + HMAP_FOR_EACH_WITH_HASH (svc_mon, hmap_node, hash, svc_mon_map) { + ovs_assert(svc_mon->db_rec.ic_rec); + if (svc_mon->db_rec.ic_rec == lookup_rec) { + hmap_remove(svc_mon_map, &svc_mon->hmap_node); + destroy_service_monitor_info(svc_mon); + return; + } + } +} + +static void +remove_unused_ic_records(struct hmap *local_ic_svcs_map) +{ + struct service_monitor_info *svc_mon; + HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, local_ic_svcs_map) { + icsbrec_service_monitor_delete(svc_mon->db_rec.ic_rec); + destroy_service_monitor_info(svc_mon); + } + + hmap_destroy(local_ic_svcs_map); +} + +static void +remove_unused_sb_records(struct hmap *local_sb_svcs_map) +{ + struct service_monitor_info *svc_mon; + HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, local_sb_svcs_map) { + sbrec_service_monitor_delete(svc_mon->db_rec.sb_rec); + destroy_service_monitor_info(svc_mon); + } + + hmap_destroy(local_sb_svcs_map); +} + +static void +create_pushed_svcs_mon(struct ic_context *ctx, + struct hmap *pushed_svcs_map) +{ + struct sbrec_service_monitor *key = + sbrec_service_monitor_index_init_row( + ctx->sbrec_service_monitor_by_local_type); + + sbrec_service_monitor_index_set_local(key, false); + + const struct sbrec_service_monitor *sb_rec; + SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key, + ctx->sbrec_service_monitor_by_local_type) { + const char *target_az_name = smap_get_def(&sb_rec->options, + "az-name", ""); + if (!target_az_name) { + continue; + } + create_service_monitor_info(pushed_svcs_map, sb_rec, + &sb_rec->header_.uuid, + ctx->runned_az->name, target_az_name, + NULL, false); + } + + sbrec_service_monitor_index_destroy_row(key); +} + +static void +create_synced_svcs_mon(struct ic_context *ctx, + struct hmap *synced_svcs_map) +{ + struct icsbrec_service_monitor *key = + icsbrec_service_monitor_index_init_row( + ctx->icsbrec_service_monitor_by_target_az); + + icsbrec_service_monitor_index_set_target_availability_zone( + key, ctx->runned_az->name); + + const struct icsbrec_service_monitor *ic_rec; + ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key, + ctx->icsbrec_service_monitor_by_target_az) { + + const struct sbrec_port_binding *pb = + find_sb_pb_by_name(ctx->sbrec_port_binding_by_name, + ic_rec->logical_port); + + if (!pb || !pb->up) { + continue; + } + + const char *chassis_name = pb->chassis ? pb->chassis->name : NULL; + create_service_monitor_info(synced_svcs_map, ic_rec, + &ic_rec->header_.uuid, + ctx->runned_az->name, + NULL, chassis_name, true); + } + + icsbrec_service_monitor_index_destroy_row(key); +} + +static void +create_local_ic_svcs_map(struct ic_context *ctx, + struct hmap *owned_svc_map) +{ + struct icsbrec_service_monitor *key = + icsbrec_service_monitor_index_init_row( + ctx->icsbrec_service_monitor_by_source_az); + + icsbrec_service_monitor_index_set_source_availability_zone( + key, ctx->runned_az->name); + + const struct icsbrec_service_monitor *ic_rec; + ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key, + ctx->icsbrec_service_monitor_by_source_az) { + create_service_monitor_info(owned_svc_map, ic_rec, + &ic_rec->header_.uuid, + ctx->runned_az->name, NULL, + NULL, true); + } + + icsbrec_service_monitor_index_destroy_row(key); +} + +static void +create_local_sb_svcs_map(struct ic_context *ctx, + struct hmap *owned_svc_map) +{ + struct sbrec_service_monitor *key = + sbrec_service_monitor_index_init_row( + ctx->sbrec_service_monitor_by_ic_learned); + + sbrec_service_monitor_index_set_ic_learned( + key, true); + + const struct sbrec_service_monitor *sb_rec; + SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key, + ctx->sbrec_service_monitor_by_ic_learned) { + create_service_monitor_info(owned_svc_map, sb_rec, + &sb_rec->header_.uuid, + ctx->runned_az->name, NULL, + NULL, false); + } + + sbrec_service_monitor_index_destroy_row(key); +} + +static const struct sbrec_service_monitor * +lookup_sb_svc_rec(struct ic_context *ctx, + const struct service_monitor_info *svc_mon) +{ + const struct icsbrec_service_monitor *db_rec = + svc_mon->db_rec.ic_rec; + struct sbrec_service_monitor *key = + sbrec_service_monitor_index_init_row( + ctx->sbrec_service_monitor_by_local_type_logical_port); + + sbrec_service_monitor_index_set_local(key, true); + sbrec_service_monitor_index_set_logical_port(key, db_rec->logical_port); + + const struct sbrec_service_monitor *sb_rec; + SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key, + ctx->sbrec_service_monitor_by_local_type_logical_port) { + if (db_rec->port == sb_rec->port && + !strcmp(db_rec->ip, sb_rec->ip) && + !strcmp(db_rec->src_ip, sb_rec->src_ip) && + !strcmp(db_rec->protocol, sb_rec->protocol)) { + sbrec_service_monitor_index_destroy_row(key); + return sb_rec; + } + } + + sbrec_service_monitor_index_destroy_row(key); + + return NULL; +} + +static const struct icsbrec_service_monitor * +lookup_icsb_svc_rec(struct ic_context *ctx, + const struct service_monitor_info *svc_mon) +{ + const struct sbrec_service_monitor *db_rec = + svc_mon->db_rec.sb_rec; + struct icsbrec_service_monitor *key = + icsbrec_service_monitor_index_init_row( + ctx->icsbrec_service_monitor_by_target_az_logical_port); + + ovs_assert(svc_mon->dst_az_name); + icsbrec_service_monitor_index_set_target_availability_zone( + key, svc_mon->dst_az_name); + + icsbrec_service_monitor_index_set_logical_port( + key, db_rec->logical_port); + + const struct icsbrec_service_monitor *ic_rec; + ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key, + ctx->icsbrec_service_monitor_by_target_az_logical_port) { + if (db_rec->port == ic_rec->port && + !strcmp(db_rec->ip, ic_rec->ip) && + !strcmp(db_rec->src_ip, ic_rec->src_ip) && + !strcmp(db_rec->protocol, ic_rec->protocol) && + !strcmp(db_rec->logical_port, ic_rec->logical_port)) { + icsbrec_service_monitor_index_destroy_row(key); + return ic_rec; + } + } + + icsbrec_service_monitor_index_destroy_row(key); + + return NULL; +} + +static void +create_service_monitor_data(struct ic_context *ctx, + struct sync_service_monitor_data *sync_data) +{ + const struct sbrec_sb_global *ic_sb = sbrec_sb_global_first( + ctx->ovnsb_idl); + const char *svc_monitor_mac = smap_get_def(&ic_sb->options, + "svc_monitor_mac", ""); + + if (svc_monitor_mac) { + sync_data->prpg_svc_monitor_mac = xstrdup(svc_monitor_mac); + } + + create_pushed_svcs_mon(ctx, &sync_data->pushed_svcs_map); + create_synced_svcs_mon(ctx, &sync_data->synced_svcs_map); + create_local_ic_svcs_map(ctx, &sync_data->local_ic_svcs_map); + create_local_sb_svcs_map(ctx, &sync_data->local_sb_svcs_map); +} + +static void +destroy_service_monitor_data(struct sync_service_monitor_data *sync_data) +{ + struct service_monitor_info *svc_mon; + HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &sync_data->pushed_svcs_map) { + destroy_service_monitor_info(svc_mon); + } + + HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &sync_data->synced_svcs_map) { + destroy_service_monitor_info(svc_mon); + } + + hmap_destroy(&sync_data->pushed_svcs_map); + hmap_destroy(&sync_data->synced_svcs_map); + free(sync_data->prpg_svc_monitor_mac); +} + +static void +sync_service_monitor(struct ic_context *ctx) +{ + if (!ctx->ovnisb_txn || !ctx->ovnsb_txn) { + return; + } + + struct sync_service_monitor_data sync_data; + memset(&sync_data, 0, sizeof(sync_data)); + hmap_init(&sync_data.pushed_svcs_map); + hmap_init(&sync_data.synced_svcs_map); + hmap_init(&sync_data.local_ic_svcs_map); + hmap_init(&sync_data.local_sb_svcs_map); + + create_service_monitor_data(ctx, &sync_data); + + struct service_monitor_info *svc_mon; + HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &sync_data.pushed_svcs_map) { + const struct sbrec_service_monitor *db_rec = svc_mon->db_rec.sb_rec; + const struct icsbrec_service_monitor *ic_rec = + lookup_icsb_svc_rec(ctx, svc_mon); + + if (ic_rec) { + sbrec_service_monitor_set_status(db_rec, ic_rec->status); + } else { + ic_rec = icsbrec_service_monitor_insert(ctx->ovnisb_txn); + icsbrec_service_monitor_set_ip(ic_rec, db_rec->ip); + icsbrec_service_monitor_set_port(ic_rec, db_rec->port); + icsbrec_service_monitor_set_src_ip(ic_rec, db_rec->src_ip); + icsbrec_service_monitor_set_src_mac(ic_rec, + sync_data.prpg_svc_monitor_mac); + icsbrec_service_monitor_set_protocol(ic_rec, db_rec->protocol); + icsbrec_service_monitor_set_logical_port(ic_rec, + db_rec->logical_port); + icsbrec_service_monitor_set_target_availability_zone(ic_rec, + svc_mon->dst_az_name); + icsbrec_service_monitor_set_source_availability_zone(ic_rec, + svc_mon->src_az_name); + } + + /* Always update options because they change from NB. */ + icsbrec_service_monitor_set_options(ic_rec, &db_rec->options); + refresh_ic_record_cache(&sync_data.local_ic_svcs_map, ic_rec); + } + + HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &sync_data.synced_svcs_map) { + const struct icsbrec_service_monitor *db_rec = + svc_mon->db_rec.ic_rec; + const struct sbrec_service_monitor *sb_rec = + lookup_sb_svc_rec(ctx, svc_mon); + + if (sb_rec) { + icsbrec_service_monitor_set_status(svc_mon->db_rec.ic_rec, + sb_rec->status); + } else { + sb_rec = sbrec_service_monitor_insert(ctx->ovnsb_txn); + sbrec_service_monitor_set_ip(sb_rec, db_rec->ip); + sbrec_service_monitor_set_port(sb_rec, db_rec->port); + sbrec_service_monitor_set_src_ip(sb_rec, db_rec->src_ip); + /* Set svc_monitor_mac from local SBDB. */ + sbrec_service_monitor_set_src_mac(sb_rec, + sync_data.prpg_svc_monitor_mac); + sbrec_service_monitor_set_protocol(sb_rec, + db_rec->protocol); + sbrec_service_monitor_set_logical_port(sb_rec, + db_rec->logical_port); + sbrec_service_monitor_set_local(sb_rec, true); + sbrec_service_monitor_set_ic_learned(sb_rec, true); + } + + /* Always update options since they may change via + * NB configuration. Also update chassis_name if + * the port has been reassigned to a different chassis. + */ + if (svc_mon->chassis_name) { + sbrec_service_monitor_set_chassis_name(sb_rec, + svc_mon->chassis_name); + } + sbrec_service_monitor_set_options(sb_rec, &db_rec->options); + refresh_sb_record_cache(&sync_data.local_sb_svcs_map, sb_rec); + } + + /* Delete local created records that are no longer used. */ + remove_unused_ic_records(&sync_data.local_ic_svcs_map); + remove_unused_sb_records(&sync_data.local_sb_svcs_map); + + destroy_service_monitor_data(&sync_data); +} + /* * This function implements a sequence number protocol that can be used by * the INB end user to verify that ISB is synced with all the changes that @@ -2274,6 +2705,7 @@ ovn_db_run(struct ic_context *ctx) ts_run(ctx); port_binding_run(ctx); route_run(ctx); + sync_service_monitor(ctx); } static void @@ -2570,6 +3002,9 @@ main(int argc, char *argv[]) struct ovsdb_idl_loop ovnsb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER( ovsdb_idl_create(ovnsb_db, &sbrec_idl_class, false, true)); + ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_sb_global); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_sb_global_col_options); + ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_chassis); ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_encaps); ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_name); @@ -2599,6 +3034,35 @@ main(int argc, char *argv[]) &sbrec_port_binding_col_external_ids); ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_port_binding_col_chassis); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_port_binding_col_up); + + ovsdb_idl_add_table(ovnsb_idl_loop.idl, + &sbrec_table_service_monitor); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_service_monitor_col_chassis_name); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_service_monitor_col_external_ids); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_service_monitor_col_ip); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_service_monitor_col_logical_port); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_service_monitor_col_port); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_service_monitor_col_protocol); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_service_monitor_col_src_ip); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_service_monitor_col_src_mac); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_service_monitor_col_local); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_service_monitor_col_ic_learned); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_service_monitor_col_status); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_service_monitor_col_options); /* Create IDL indexes */ struct ovsdb_idl_index *nbrec_ls_by_name @@ -2617,6 +3081,19 @@ main(int argc, char *argv[]) = ovsdb_idl_index_create1(ovnsb_idl_loop.idl, &sbrec_chassis_col_name); + struct ovsdb_idl_index *sbrec_service_monitor_by_local_type + = ovsdb_idl_index_create1(ovnsb_idl_loop.idl, + &sbrec_service_monitor_col_local); + + struct ovsdb_idl_index *sbrec_service_monitor_by_ic_learned + = ovsdb_idl_index_create1(ovnsb_idl_loop.idl, + &sbrec_service_monitor_col_ic_learned); + + struct ovsdb_idl_index *sbrec_service_monitor_by_local_type_logical_port + = ovsdb_idl_index_create2(ovnsb_idl_loop.idl, + &sbrec_service_monitor_col_local, + &sbrec_service_monitor_col_logical_port); + struct ovsdb_idl_index *icnbrec_transit_switch_by_name = ovsdb_idl_index_create1(ovninb_idl_loop.idl, &icnbrec_transit_switch_col_name); @@ -2647,6 +3124,19 @@ main(int argc, char *argv[]) &icsbrec_route_col_transit_switch, &icsbrec_route_col_availability_zone); + struct ovsdb_idl_index *icsbrec_service_monitor_by_source_az + = ovsdb_idl_index_create1(ovnisb_idl_loop.idl, + &icsbrec_service_monitor_col_source_availability_zone); + + struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az + = ovsdb_idl_index_create1(ovnisb_idl_loop.idl, + &icsbrec_service_monitor_col_target_availability_zone); + + struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az_logical_port + = ovsdb_idl_index_create2(ovnisb_idl_loop.idl, + &icsbrec_service_monitor_col_target_availability_zone, + &icsbrec_service_monitor_col_logical_port); + unixctl_command_register("nb-connection-status", "", 0, 0, ovn_conn_show, ovnnb_idl_loop.idl); unixctl_command_register("sb-connection-status", "", 0, 0, @@ -2698,6 +3188,12 @@ main(int argc, char *argv[]) .nbrec_port_by_name = nbrec_port_by_name, .sbrec_port_binding_by_name = sbrec_port_binding_by_name, .sbrec_chassis_by_name = sbrec_chassis_by_name, + .sbrec_service_monitor_by_local_type = + sbrec_service_monitor_by_local_type, + .sbrec_service_monitor_by_ic_learned = + sbrec_service_monitor_by_ic_learned, + .sbrec_service_monitor_by_local_type_logical_port = + sbrec_service_monitor_by_local_type_logical_port, .icnbrec_transit_switch_by_name = icnbrec_transit_switch_by_name, .icsbrec_port_binding_by_az = icsbrec_port_binding_by_az, @@ -2706,6 +3202,12 @@ main(int argc, char *argv[]) .icsbrec_route_by_az = icsbrec_route_by_az, .icsbrec_route_by_ts = icsbrec_route_by_ts, .icsbrec_route_by_ts_az = icsbrec_route_by_ts_az, + .icsbrec_service_monitor_by_source_az = + icsbrec_service_monitor_by_source_az, + .icsbrec_service_monitor_by_target_az = + icsbrec_service_monitor_by_target_az, + .icsbrec_service_monitor_by_target_az_logical_port = + icsbrec_service_monitor_by_target_az_logical_port, }; if (!state.had_lock && ovsdb_idl_has_lock(ovnsb_idl_loop.idl)) { @@ -2731,6 +3233,7 @@ main(int argc, char *argv[]) ovn_db_run(&ctx); update_sequence_numbers(&ctx, &ovnisb_idl_loop); } + } int rc1 = ovsdb_idl_loop_commit_and_wait(&ovnnb_idl_loop); diff --git a/ovn-ic-sb.ovsschema b/ovn-ic-sb.ovsschema index 22f75b06c..34b5457bb 100644 --- a/ovn-ic-sb.ovsschema +++ b/ovn-ic-sb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_IC_Southbound", - "version": "2.1.0", - "cksum": "1466425967 7126", + "version": "2.2.0", + "cksum": "2294868959 8438", "tables": { "IC_SB_Global": { "columns": { @@ -145,6 +145,32 @@ "value": "string", "min": 0, "max": "unlimited"}}}, - "maxRows": 1} + "maxRows": 1}, + "Service_Monitor": { + "columns": { + "ip": {"type": "string"}, + "protocol": { + "type": {"key": {"type": "string", + "enum": ["set", ["tcp", "udp"]]}, + "min": 0, "max": 1}}, + "port": {"type": {"key": {"type": "integer", + "minInteger": 0, + "maxInteger": 65535}}}, + "logical_port": {"type": "string"}, + "src_ip": {"type": "string"}, + "src_mac": {"type": "string"}, + "status": { + "type": {"key": {"type": "string", + "enum": ["set", ["online", "offline", "error"]]}, + "min": 0, "max": 1}}, + "target_availability_zone": {"type": "string"}, + "source_availability_zone": {"type": "string"}, + "options": { + "type": {"key": "string", "value": "string", + "min": 0, "max": "unlimited"}}, + "external_ids": { + "type": {"key": "string", "value": "string", + "min": 0, "max": "unlimited"}}}, + "isRoot": true} } } diff --git a/ovn-ic-sb.xml b/ovn-ic-sb.xml index 8f98c7ebb..35dc1f509 100644 --- a/ovn-ic-sb.xml +++ b/ovn-ic-sb.xml @@ -691,4 +691,60 @@ </group> </table> + <table name="Service_Monitor"> + <column name="ip"> + IP of the service to be monitored. Copy from SBDB record. + </column> + + <column name="protocol"> + The protocol of the service. + Copy from source Southbound Database record. + </column> + + <column name="port"> + The TCP or UDP port of the service. + Copy from source Southbound Database record. + </column> + + <column name="logical_port"> + The VIF of the logical port on which the service is running. The + <code>ovn-controller</code> that binds this <code>logical_port</code> + monitors the service by sending periodic monitor packets. + Copy from source Southbound Database record. + </column> + + <column name="src_ip"> + Source IPv4 or IPv6 address to use in the service monitor packet. + Copy from source Southbound Database record. + </column> + + <column name="src_mac"> + Source Ethernet address to use in the service monitor packet. + Copy from Southbound Database record. + </column> + + <column name="status"> + The health status of the service monitor, synchronized from target + Southbound Database. + </column> + + <column name="target_availability_zone"> + The Availability Zone where the monitored service endpoint is located. + </column> + + <column name="source_availability_zone"> + Availability Zone that initiated this monitor entry in ICSB and retains + ownership for lifecycle management. + </column> + + <column name="options"> + Same as in Table Service_Monitor in SBDB. + Copy from source SBDB record. + </column> + + <column name="external_ids"> + Same as in Table Service_Monitor in SBDB. + Copy from source SBDB record. + </column> + </table> </database> diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at index 49a409015..817efd090 100644 --- a/tests/ovn-ic.at +++ b/tests/ovn-ic.at @@ -3643,3 +3643,383 @@ OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep 2001 | OVN_CLEANUP_IC([az1], [az2]) AT_CLEANUP ]) + +AT_BANNER([OVN Interconnection Service Monitor synchronization]) +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ovn-ic -- Service Monitor synchronization]) + +ovn_init_ic_db +ovn_start az1 +ovn_start az2 +ovn_start az3 + +# ┌─────────────────────────────────────────────────────────────────────────────┐ +# │ Service Monitor Sync Check (Cross-AZ LB Setup) │ +# ├───────────────┬───────────────┬────────────────────────────────────────────-┤ +# │ AZ1 │ AZ2 │ AZ3 (Backends only) │ +# ├───────────────┼───────────────┼────────────────────────────────────────────-┤ +# │ ┌─────────┐ │ ┌─────────┐ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ +# │ │ LB1 │ │ │ LB2 │ │ │ lport5 │ │ lport6 │ │ lport7 │ │ +# │ ├─────────┤ │ ├─────────┤ │ │ (AZ3) │ │ (AZ3) │ │ (AZ3) │ │ +# │ │ - lport1├──┼──┤ - lport3│ │ └─────────┘ └─────────┘ └─────────┘ │ +# │ │ (AZ1) │ │ │ (AZ2) │ │ │ +# │ │ - lport3│ │ │ - lport1├──┼───────────────────┐ │ +# │ │ (AZ2) │ │ │ (AZ3) │ │ │ │ +# │ │ - lport5│ │ └─────────┘ │ │ │ +# │ │ (AZ3) │ │ │ │ │ +# │ └─────────┘ │ ┌─────────┐ │ │ │ +# │ │ │ LB3 │ │ │ │ +# │ │ ├─────────┤ │ │ │ +# │ │ │ - lport5├──┼───────────────────┘ │ +# │ │ │ (AZ3) │ │ │ +# │ │ │ - lport6│ │ │ +# │ │ │ (AZ3) │ │ │ +# │ │ │ - lport2├──┘ │ +# │ │ │ (AZ1) │ │ +# │ │ └─────────┘ │ +# └───────────────┴───────────────┴────────────────────────────────────────────-┘ +# +# Physical Backend Locations: +# - AZ1: lport1, lport2 +# - AZ2: lport3, lport4 +# - AZ3: lport5, lport6 , lport7 +# +# Load Balancer Configurations: +# - LB1 (AZ1): lport1(AZ1), lport3(AZ2), lport5(AZ3), lport4(az2) +# - LB2 (AZ2): lport3(AZ2), lport1(AZ3) +# - LB3 (AZ2): lport5(AZ3), lport6(AZ3), lport2(AZ1) + + +# AZ1 Configuration +ovn_as az1 +check ovn-nbctl ls-add az1_ls1 +check ovn-nbctl lsp-add az1_ls1 lport1_az1 +check ovn-nbctl lsp-add az1_ls1 lport2_az1 + +check ovn-nbctl lb-add az1_lb1 10.10.10.1:80 1.1.1.1:10880,5.5.5.1:10880,3.3.3.1:10880,4.4.4.1:10880 +check ovn-nbctl ls-lb-add az1_ls1 az1_lb1 +AT_CHECK([ovn-nbctl --wait=sb \ + -- --id=@hc create Load_Balancer_Health_Check vip="10.10.10.1\:80" \ + options:failure_count=100 \ + -- add Load_Balancer . health_check @hc | uuidfilt], [0], [<0> +]) + +check ovn-nbctl set load_balancer az1_lb1 ip_port_mappings:1.1.1.1=lport1_az1:1.1.1.9 +check ovn-nbctl set load_balancer az1_lb1 ip_port_mappings:3.3.3.1=lport3_az2:3.3.3.9:remote:az2 +check ovn-nbctl set load_balancer az1_lb1 ip_port_mappings:5.5.5.1=lport5_az3:5.5.5.9:remote:az3 +check ovn-nbctl set load_balancer az1_lb1 ip_port_mappings:4.4.4.1=lport4_az2:4.4.4.9:remote:az2 + +check_row_count sb:Service_Monitor 4 +check_row_count ic-sb:Service_Monitor 3 + +AT_CHECK([ovn-sbctl lflow-list az1_ls1 | grep arp | grep -c "1.1.1.9"], [0], [dnl +1 +]) + +AT_CHECK([ovn-sbctl lflow-list az1_ls1 | grep arp | grep -c "3.3.3.9"], [1], [dnl +0 +]) + +# AZ2 Configuration +ovn_as az2 +check ovn-nbctl ls-add az2_ls1 +check ovn-nbctl lsp-add az2_ls1 lport3_az2 +check ovn-nbctl lsp-add az2_ls1 lport4_az2 + +check ovn-nbctl lb-add az2_lb1 20.20.20.1:80 3.3.3.1:10880,1.1.1.1:10880 +check ovn-nbctl ls-lb-add az2_ls1 az2_lb1 +-nbctl ls-lb-add az2_ls1 az2_lb1 +AT_CHECK([ovn-nbctl --wait=sb \ + -- --id=@hc create Load_Balancer_Health_Check vip="20.20.20.1\:80" \ + options:failure_count=100 \ + -- add Load_Balancer . health_check @hc | uuidfilt], [0], [<0> +]) + +check ovn-nbctl set load_balancer az2_lb1 ip_port_mappings:3.3.3.1=lport3_az2:3.3.3.9 +check ovn-nbctl set load_balancer az2_lb1 ip_port_mappings:1.1.1.1=lport1_az1:1.1.1.9:remote:az1 + +check_row_count sb:Service_Monitor 3 +check_row_count ic-sb:Service_Monitor 4 + +ovn_as az1 +check_row_count sb:Service_Monitor 4 +check_column false sb:Service_Monitor ic_learned logical_port=lport1_az1 +check_column true sb:Service_Monitor local logical_port=lport1_az1 + +ovn_as az2 +check_column "3.3.3.1" sb:Service_Monitor ip logical_port=lport3_az2 +check_column 10880 sb:Service_Monitor port logical_port=lport3_az2 +check_column tcp sb:Service_Monitor protocol logical_port=lport3_az2 +check_column "3.3.3.9" sb:Service_Monitor src_ip logical_port=lport3_az2 +check_column true sb:Service_Monitor ic_learned logical_port=lport3_az2 +check_column true sb:Service_Monitor local logical_port=lport3_az2 + +check_column false sb:Service_Monitor ic_learned logical_port=lport1_az1 +check_column false sb:Service_Monitor local logical_port=lport1_az1 + +check_column true sb:Service_Monitor ic_learned logical_port=lport4_az2 +check_column true sb:Service_Monitor local logical_port=lport4_az2 + +# Check ICSB records +check_column "4.4.4.1" ic-sb:Service_Monitor ip logical_port=lport4_az2 +check_column 10880 ic-sb:Service_Monitor port logical_port=lport4_az2 +check_column tcp ic-sb:Service_Monitor protocol logical_port=lport4_az2 +check_column "4.4.4.9" ic-sb:Service_Monitor src_ip logical_port=lport4_az2 +check_column az2 ic-sb:Service_Monitor target_availability_zone logical_port=lport4_az2 +check_column az1 ic-sb:Service_Monitor source_availability_zone logical_port=lport4_az2 + +check_column az2 ic-sb:Service_Monitor target_availability_zone logical_port=lport3_az2 +check_column az1 ic-sb:Service_Monitor source_availability_zone logical_port=lport3_az2 + +check_column az1 ic-sb:Service_Monitor target_availability_zone logical_port=lport1_az1 +check_column az2 ic-sb:Service_Monitor source_availability_zone logical_port=lport1_az1 + +check_column az3 ic-sb:Service_Monitor target_availability_zone logical_port=lport5_az3 +check_column az1 ic-sb:Service_Monitor source_availability_zone logical_port=lport5_az3 + +# AZ3 Configuration +ovn_as az3 +check ovn-nbctl ls-add az3_ls1 + +# Check there no Service_Monitor when we have no ports. +check_row_count sb:Service_Monitor 0 +check_row_count nb:Load_Balancer 0 + +check ovn-nbctl lsp-add az3_ls1 lport5_az3 +check ovn-nbctl lsp-add az3_ls1 lport6_az3 +check ovn-nbctl lsp-add az3_ls1 lport7_az3 + +# Check there is one Service Monitor learned from az1. +check_row_count sb:Service_Monitor 1 + +check_column "5.5.5.1" sb:Service_Monitor ip logical_port=lport5_az3 +check_column 10880 sb:Service_Monitor port logical_port=lport5_az3 +check_column tcp sb:Service_Monitor protocol logical_port=lport5_az3 +check_column "5.5.5.9" sb:Service_Monitor src_ip logical_port=lport5_az3 +check_column true sb:Service_Monitor ic_learned logical_port=lport5_az3 +check_column true sb:Service_Monitor local logical_port=lport5_az3 + +AT_CHECK([ovn-sbctl lflow-list az3_ls1 | grep arp | grep -c "5.5.5.9"], [0], [dnl +1 +]) + +# Add more lb in AZ2, change port for one backend, check we will have one more +# records for this Service_Monitor +ovn_as az2 +check ovn-nbctl lb-add az2_lb2 20.20.20.2:80 2.2.2.1:10880,5.5.5.1:10881,6.6.6.1:10880 +check ovn-nbctl ls-lb-add az2_ls1 az2_lb2 +-nbctl ls-lb-add az2_ls1 az2_lb2 +AT_CHECK([ovn-nbctl --wait=sb \ + -- --id=@hc create Load_Balancer_Health_Check vip="20.20.20.2\:80" \ + options:failure_count=100 \ + -- add Load_Balancer az2_lb2 health_check @hc | uuidfilt], [0], [<0> +]) + +check ovn-nbctl set load_balancer az2_lb2 ip_port_mappings:2.2.2.1=lport2_az1:2.2.2.9:remote:az1 +check ovn-nbctl set load_balancer az2_lb2 ip_port_mappings:5.5.5.1=lport5_az3:5.5.5.9:remote:az3 +check ovn-nbctl set load_balancer az2_lb2 ip_port_mappings:6.6.6.1=lport6_az3:6.6.6.9:remote:az3 + +check_row_count sb:Service_Monitor 6 + +AT_CHECK([ovn-sbctl lflow-list az2_ls1 | grep arp | grep -c "6.6.6.9"], [1], [dnl +0 +]) + +AT_CHECK([ovn-sbctl lflow-list az2_ls1 | grep arp | grep -c "5.5.5.9"], [1], [dnl +0 +]) + +AT_CHECK([ovn-sbctl lflow-list az2_ls1 | grep arp | grep -c "2.2.2.9"], [1], [dnl +0 +]) + +AT_CHECK([ovn-sbctl lflow-list az2_ls1 | grep arp | grep -c "3.3.3.9"], [0], [dnl +1 +]) + +ovn_as az1 + +check_row_count sb:Service_Monitor 5 + +check_column true sb:Service_Monitor ic_learned logical_port=lport2_az1 +check_column true sb:Service_Monitor local logical_port=lport2_az1 + +ovn_as az3 + +check_row_count sb:Service_Monitor 3 + +AT_CHECK([ovn-sbctl lflow-list az3_ls1 | grep arp | wc -l], [0], [dnl +3 +]) + +AT_CHECK([ovn-sbctl lflow-list az3_ls1 | grep arp | grep -c "6.6.6.9"], [0], [dnl +1 +]) + +AT_CHECK([ovn-sbctl lflow-list az3_ls1 | grep arp | grep -c "5.5.5.9"], [0], [dnl +1 +]) + +# Check status propogation. + +ovn_as az1 +AT_CHECK([ovn-sbctl lflow-list az1_ls1 | grep ls_in_lb | grep backends | ovn_strip_lflows], [0], [dnl + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.10.10.1 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 10.10.10.1; reg2[[0..15]] = 80; ct_lb_mark(backends=1.1.1.1:10880,5.5.5.1:10880,3.3.3.1:10880,4.4.4.1:10880);) +]) + +ovn_as az2 +AT_CHECK([ovn-sbctl lflow-list az2_ls1 | grep ls_in_lb | grep backends | ovn_strip_lflows], [0], [dnl + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 20.20.20.1 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 20.20.20.1; reg2[[0..15]] = 80; ct_lb_mark(backends=3.3.3.1:10880,1.1.1.1:10880);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 20.20.20.2 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 20.20.20.2; reg2[[0..15]] = 80; ct_lb_mark(backends=2.2.2.1:10880,5.5.5.1:10881,6.6.6.1:10880);) +]) + +ovn_as az1 +svc_lport1_uuid=$(ovn-sbctl -d bare --no-headings --columns _uuid find Service_Monitor logical_port=lport1_az1) + +check ovn-sbctl set Service_Monitor $svc_lport1_uuid status="offline" + +check_column offline ic-sb:Service_Monitor status logical_port=lport1_az1 + +ovn_as az1 +AT_CHECK([ovn-sbctl lflow-list az1_ls1 | grep ls_in_lb | grep backends | ovn_strip_lflows], [0], [dnl + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.10.10.1 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 10.10.10.1; reg2[[0..15]] = 80; ct_lb_mark(backends=5.5.5.1:10880,3.3.3.1:10880,4.4.4.1:10880);) +]) + +ovn_as az2 +AT_CHECK([ovn-sbctl lflow-list az2_ls1 | grep ls_in_lb | grep backends | ovn_strip_lflows], [0], [dnl + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 20.20.20.1 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 20.20.20.1; reg2[[0..15]] = 80; ct_lb_mark(backends=3.3.3.1:10880);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 20.20.20.2 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 20.20.20.2; reg2[[0..15]] = 80; ct_lb_mark(backends=2.2.2.1:10880,5.5.5.1:10881,6.6.6.1:10880);) +]) + +ovn_as az3 +svc_lport6_uuid=$(ovn-sbctl -d bare --no-headings --columns _uuid find Service_Monitor logical_port=lport6_az3) + +check ovn-sbctl set Service_Monitor $svc_lport6_uuid status="offline" + +check_column offline ic-sb:Service_Monitor status logical_port=lport6_az3 + +ovn_as az2 +check_column offline sb:Service_Monitor status logical_port=lport6_az3 + +AT_CHECK([ovn-sbctl lflow-list az2_ls1 | grep ls_in_lb | grep backends | ovn_strip_lflows], [0], [dnl + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 20.20.20.1 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 20.20.20.1; reg2[[0..15]] = 80; ct_lb_mark(backends=3.3.3.1:10880);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 20.20.20.2 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 20.20.20.2; reg2[[0..15]] = 80; ct_lb_mark(backends=2.2.2.1:10880,5.5.5.1:10881);) +]) + +ovn_as az1 +svc_lport2_uuid=$(ovn-sbctl -d bare --no-headings --columns _uuid find Service_Monitor logical_port=lport2_az1) + +check ovn-sbctl set Service_Monitor $svc_lport2_uuid status="offline" + +check_column offline ic-sb:Service_Monitor status logical_port=lport2_az1 + +ovn_as az2 +AT_CHECK([ovn-sbctl lflow-list az2_ls1 | grep ls_in_lb | grep backends | ovn_strip_lflows], [0], [dnl + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 20.20.20.1 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 20.20.20.1; reg2[[0..15]] = 80; ct_lb_mark(backends=3.3.3.1:10880);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 20.20.20.2 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 20.20.20.2; reg2[[0..15]] = 80; ct_lb_mark(backends=5.5.5.1:10881);) +]) + +svc_lport4_uuid=$(ovn-sbctl -d bare --no-headings --columns _uuid find Service_Monitor logical_port=lport4_az2) + +check ovn-sbctl set Service_Monitor $svc_lport4_uuid status="offline" + +check_column offline ic-sb:Service_Monitor status logical_port=lport4_az2 + +ovn_as az1 +AT_CHECK([ovn-sbctl lflow-list az1_ls1 | grep ls_in_lb | grep backends | ovn_strip_lflows], [0], [dnl + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.10.10.1 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 10.10.10.1; reg2[[0..15]] = 80; ct_lb_mark(backends=5.5.5.1:10880,3.3.3.1:10880);) +]) + +ovn_as az2 +check_row_count sb:Service_Monitor 1 logical_port=lport4_az2 + +ovn_as az1 +az1_lb1_uuid=$(ovn-nbctl --bare --no-headings --columns=_uuid find Load_Balancer name=az1_lb1) + +check_row_count sb:Service_Monitor 5 + +check_row_count sb:Service_Monitor 1 logical_port=lport4_az2 + +check ovn-nbctl set Load_Balancer $az1_lb1_uuid vip='"10.10.10.1:80"="1.1.1.1:10880,5.5.5.1:10880,3.3.3.1:10880,2.2.2.1:10880"' +check ovn-nbctl set load_balancer az1_lb1 ip_port_mappings:2.2.2.1=lport2_az1:2.2.2.9 + +check_row_count sb:Service_Monitor 4 + +check_row_count sb:Service_Monitor 0 logical_port=lport4_az2 + +check_row_count ic-sb:Service_Monitor 0 logical_port=lport4_az2 + +ovn_as az3 +svc_lport6_uuid=$(ovn-sbctl -d bare --no-headings --columns _uuid find Service_Monitor logical_port=lport6_az3) + +check ovn-sbctl set Service_Monitor $svc_lport6_uuid status="online" + +check_column online ic-sb:Service_Monitor status logical_port=lport6_az3 + +ovn_as az2 +check_column online sb:Service_Monitor status logical_port=lport6_az3 + +ovn_as az2 +AT_CHECK([ovn-sbctl lflow-list az2_ls1 | grep ls_in_lb | grep backends | ovn_strip_lflows], [0], [dnl + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 20.20.20.1 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 20.20.20.1; reg2[[0..15]] = 80; ct_lb_mark(backends=3.3.3.1:10880);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 20.20.20.2 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 20.20.20.2; reg2[[0..15]] = 80; ct_lb_mark(backends=5.5.5.1:10881,6.6.6.1:10880);) +]) + +ovn_as az1 +svc_lport1_uuid=$(ovn-sbctl -d bare --no-headings --columns _uuid find Service_Monitor logical_port=lport1_az1) +lport1_uuid=$(ovn-sbctl -d bare --no-headings --columns _uuid find Port_Binding logical_port=lport1_az1) + +check ovn-sbctl set Port_Binding $lport1_uuid up=true + +check ovn-sbctl set Service_Monitor $svc_lport1_uuid status="online" + +check_column online ic-sb:Service_Monitor status logical_port=lport1_az1 + +ovn_as az2 +AT_CHECK([ovn-sbctl lflow-list az2_ls1 | grep ls_in_lb | grep backends | ovn_strip_lflows], [0], [dnl + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 20.20.20.1 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 20.20.20.1; reg2[[0..15]] = 80; ct_lb_mark(backends=3.3.3.1:10880,1.1.1.1:10880);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 20.20.20.2 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 20.20.20.2; reg2[[0..15]] = 80; ct_lb_mark(backends=5.5.5.1:10881,6.6.6.1:10880);) +]) + +ovn_as az1 +AT_CHECK([ovn-sbctl lflow-list az1_ls1 | grep ls_in_lb | grep backends | ovn_strip_lflows], [0], [dnl + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.10.10.1 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 10.10.10.1; reg2[[0..15]] = 80; ct_lb_mark(backends=1.1.1.1:10880,5.5.5.1:10880,3.3.3.1:10880);) +]) + +check ovn-nbctl lb-del az1_lb1 + +/* check ic_learned not deleted */ + +check_row_count sb:Service_Monitor 2 +check_row_count sb:Service_Monitor 1 logical_port=lport1_az1 +check_row_count sb:Service_Monitor 1 logical_port=lport2_az1 + +ovn_as az2 + +check_row_count sb:Service_Monitor 0 logical_port=lport4_az2 + +ovn-nbctl list load_balancer az2_lb2 + +check ovn-nbctl lb-del az2_lb2 +check_row_count sb:Service_Monitor 2 + +ovn_as az1 +check_row_count sb:Service_Monitor 1 + +ovn_as az3 +check_row_count sb:Service_Monitor 0 + +ovn_as az1 +check_row_count ic-sb:Service_Monitor 1 + +ovn_as az2 +check ovn-nbctl lb-del az2_lb1 +check_row_count sb:Service_Monitor 0 + +ovn_as az1 +check_row_count sb:Service_Monitor 0 +check_row_count ic-sb:Service_Monitor 0 + +OVN_CLEANUP_IC([az1], [az2], [az3]) +AT_CLEANUP +]) -- 2.48.1 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev