Hi, I have a fairly conceptual question. I'm working on implementing service monitor synchronization between different OVN deployments. I've written some code (I sent the RFC above), but I ran into problems during implementation in northd, so I've left that part out for now. Here's my idea: Let's say we have two OVN deployments(az1 and az2). In one of them(in az1, for example), a load balancer is created with an ip_port_mapping: ip_port_mappings:10.10.10.1=lport1:10.10.10.99:remote:az2 Here, 10.10.10.1 is the IP, lport1 is a non-local port in another OVN deployment(az2 in this case), src_ip = 10.10.10.99, and remote:az2 means we want to propagate this service monitor to deployment az2. This service monitor is marked as non-local. The IC database picks it up and creates its own entry, tagging the src and dst AZs (src_az = az1 and dst_az = az2). The second deployment detects the dst_az and adds a record to its southbound DB. The relevant controller then handles health checks, updates the status in the southbound DB, the IC sees the update, adjusts its own records, and the status propagates back to the correct AZ(az1) and southbound DB. The main unresolved issue is adding logical flows for ARP requests to svc_mac and svc_src_ip. I can't add this to the load balancer node because the remote AZ might not have load balancers, and it doesn’t seem conceptually right anyway. I’d like to move away from the current abstractions for service monitors since, in my case, they aren’t created from the northbound DB. So, I have a few questions: 1) In my implementation, I’d like to move service monitors out of the LB node into a separate node dedicated to service monitors(both local and propogated), so we can incrementally process flows for both propogated and local service monitors. I’ve already written some code but wanted to ask your thoughts first—should I create a separate node just for propagated service monitors? or I can generally move the service monitors to a separate node? 2) I’m also concerned about incremental processing in the IC DB. I’d like to hear some ideas on this—maybe someone is already working on it. The main question is: Do you conceptually support this idea? And what do you think about my first question? Depending on your answer, I can finish the code in northd and submit a more detailed RFC. Numan, I saw that you did a LB node, what do you think?
On 17.04.2025 20:28, Alexandra Rukomoinikova wrote: --- controller/pinctrl.c | 2 +- ic/ovn-ic.c | 312 +++++++++++++++++++++++++++++++++++++++++++ northd/lb.c | 11 ++ northd/lb.h | 2 + northd/northd.c | 126 +++++++++++++---- northd/northd.h | 4 + ovn-ic-sb.ovsschema | 31 ++++- ovn-ic-sb.xml | 46 +++++++ ovn-sb.ovsschema | 6 +- ovn-sb.xml | 9 ++ 10 files changed, 515 insertions(+), 34 deletions(-) diff --git a/controller/pinctrl.c b/controller/pinctrl.c index bdb619b4d..d9e5919e8 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -7597,7 +7597,7 @@ sync_svc_monitors(struct ovsdb_idl_txn *ovnsb_idl_txn, const struct sbrec_port_binding *pb = lport_lookup_by_name(sbrec_port_binding_by_name, sb_svc_mon->logical_port); - if (!pb) { + if (!pb || !sb_svc_mon->local_backend) { continue; } diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index c8796680b..e7d904ec6 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -93,6 +93,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) @@ -404,6 +407,289 @@ sync_sb_gw_to_isb(struct ic_context *ctx, free(isb_encaps); } +struct ic_service_monitor_info { + struct hmap_node hmap_node; + const struct icsbrec_service_monitor *rec; + bool required; +}; + +struct sb_service_monitor_info { + struct hmap_node hmap_node; + const struct sbrec_service_monitor *rec; + bool required; +}; + +static void +init_svc_hashmap(struct hmap *svc_map, uint32_t port, + const char *ip, const char *logical_port, + void **mon_info_p, const void *rec, + bool is_ic) +{ + uint32_t hash = port; + hash = hash_string(ip, hash); + hash = hash_string(logical_port, hash); + + if (is_ic) { + struct ic_service_monitor_info *mon_info = xzalloc(sizeof(*mon_info)); + mon_info->rec = (const struct icsbrec_service_monitor *) rec; + mon_info->required = false; + hmap_insert(svc_map, &mon_info->hmap_node, hash); + *mon_info_p = mon_info; + } else { + struct sb_service_monitor_info *mon_info = xzalloc(sizeof(*mon_info)); + mon_info->rec = (const struct sbrec_service_monitor *) rec; + mon_info->required = false; + hmap_insert(svc_map, &mon_info->hmap_node, hash); + *mon_info_p = mon_info; + } +} + +static struct sb_service_monitor_info * +sb_find_svc_monitor(struct hmap *svc_table, const char *ip, uint32_t port, + const char *src_ip, const char *protocol, + const char *logical_port) +{ + uint32_t hash = port; + hash = hash_string(ip, hash); + hash = hash_string(logical_port, hash); + + struct sb_service_monitor_info *mon_info; + HMAP_FOR_EACH_WITH_HASH (mon_info, hmap_node, hash, svc_table) { + if (mon_info->rec->port == port && + !strcmp(mon_info->rec->ip, ip) && + !strcmp(mon_info->rec->src_ip, src_ip) && + !strcmp(mon_info->rec->protocol, protocol) && + !strcmp(mon_info->rec->logical_port, logical_port)) { + return mon_info; + } + } + + return NULL; +} + +static struct ic_service_monitor_info * +ic_find_svc_monitor(struct hmap *svc_table, const char *ip, uint32_t port, + const char *src_ip, const char *protocol, + const char *logical_port) +{ + uint32_t hash = port; + hash = hash_string(ip, hash); + hash = hash_string(logical_port, hash); + struct ic_service_monitor_info *mon_info; + HMAP_FOR_EACH_WITH_HASH (mon_info, hmap_node, hash, svc_table) { + if (mon_info->rec->port == port && + !strcmp(mon_info->rec->ip, ip) && + !strcmp(mon_info->rec->src_ip, src_ip) && + !strcmp(mon_info->rec->protocol, protocol) && + !strcmp(mon_info->rec->logical_port, logical_port)) { + return mon_info; + } + } + + return NULL; +} + +static bool +validate_propogeted_svc(struct ic_context *ctx, + const struct icsbrec_service_monitor *ic_rec) +{ + 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) { + return false; + } + + return true; +} + +static void +sync_sb_to_ic_base(struct ic_context *ctx, + const struct sbrec_service_monitor *svc_rec, + const struct icsbrec_availability_zone *az, + struct hmap *ic_svc_local, + struct hmap *ic_svc_remote) +{ + const char *az_name = smap_get_def(&svc_rec->external_ids, + "az-name", ""); + + if (!svc_rec->local_backend && strcmp(az_name, az->name)) { + struct ic_service_monitor_info *ic_mon_info = + ic_find_svc_monitor(ic_svc_local, + svc_rec->ip, + svc_rec->port, + svc_rec->src_ip, + svc_rec->protocol, + svc_rec->logical_port); + if (!ic_mon_info) { + const struct icsbrec_service_monitor *ic_svc = + icsbrec_service_monitor_insert(ctx->ovnisb_txn); + icsbrec_service_monitor_set_ip(ic_svc, svc_rec->ip); + icsbrec_service_monitor_set_port(ic_svc, svc_rec->port); + icsbrec_service_monitor_set_src_ip(ic_svc, svc_rec->src_ip); + icsbrec_service_monitor_set_protocol(ic_svc, svc_rec->protocol); + icsbrec_service_monitor_set_dst_availability_zone(ic_svc, + az_name); + icsbrec_service_monitor_set_src_availability_zone(ic_svc, + az->name); + icsbrec_service_monitor_set_logical_port(ic_svc, + svc_rec->logical_port); + icsbrec_service_monitor_set_options(ic_svc, &svc_rec->options); + init_svc_hashmap(ic_svc_local, svc_rec->port, + svc_rec->ip, svc_rec->logical_port, + (void **)&ic_mon_info, + ic_svc, true); + } + ic_mon_info->required = true; + } + + if (svc_rec->propogated) { + struct ic_service_monitor_info *ic_mon_info = + ic_find_svc_monitor(ic_svc_remote, + svc_rec->ip, + svc_rec->port, + svc_rec->src_ip, + svc_rec->protocol, + svc_rec->logical_port); + if (ic_mon_info) { + icsbrec_service_monitor_set_status(ic_mon_info->rec, + svc_rec->status); + } else { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + VLOG_WARN_RL(&rl, "Didn't find original service monitor recording " + "in SBIC DB for recording in SBDB "); + } + } +} + +static void +sync_ic_to_sb_base(struct ic_context *ctx, + const struct icsbrec_service_monitor *ic_svc_rec, + const struct icsbrec_availability_zone *az, + struct hmap *sb_svc_propagated, + struct hmap *sb_svc_non_local) +{ + struct sb_service_monitor_info *sb_svc_mon; + if (!strcmp(ic_svc_rec->dst_availability_zone, az->name)) { + sb_svc_mon = sb_find_svc_monitor(sb_svc_propagated, + ic_svc_rec->ip, + ic_svc_rec->port, + ic_svc_rec->src_ip, + ic_svc_rec->protocol, + ic_svc_rec->logical_port); + if (!sb_svc_mon && validate_propogeted_svc(ctx, ic_svc_rec)) { + const struct sbrec_service_monitor *sb_svc = + sbrec_service_monitor_insert(ctx->ovnsb_txn); + sbrec_service_monitor_set_propogated(sb_svc, true); + sbrec_service_monitor_set_ip(sb_svc, ic_svc_rec->ip); + sbrec_service_monitor_set_src_ip(sb_svc, ic_svc_rec->src_ip); + sbrec_service_monitor_set_local_backend(sb_svc, true); + sbrec_service_monitor_set_port(sb_svc, ic_svc_rec->port); + sbrec_service_monitor_set_protocol(sb_svc, ic_svc_rec->protocol); + sbrec_service_monitor_set_options(sb_svc, &ic_svc_rec->options); + sbrec_service_monitor_set_logical_port(sb_svc, + ic_svc_rec->logical_port); + init_svc_hashmap(sb_svc_propagated, ic_svc_rec->port, + ic_svc_rec->ip, ic_svc_rec->logical_port, + (void **)&sb_svc_mon, + sb_svc, true); + } + sb_svc_mon->required = true; + } else if (!strcmp(ic_svc_rec->src_availability_zone, az->name)) { + sb_svc_mon = sb_find_svc_monitor(sb_svc_non_local, + ic_svc_rec->ip, + ic_svc_rec->port, + ic_svc_rec->src_ip, + ic_svc_rec->protocol, + ic_svc_rec->logical_port); + if (sb_svc_mon) { + sbrec_service_monitor_set_status(sb_svc_mon->rec, + ic_svc_rec->status); + } else { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + VLOG_WARN_RL(&rl, "Didn't find original service monitor recording " + "in SBIC DB for recording in SBDB "); + } + } +} + +static void +sync_service_monitor(struct ic_context *ctx, + const struct icsbrec_availability_zone *az) +{ + if (!ctx->ovnisb_txn || !ctx->ovnsb_txn) { + return; + } + + struct hmap ic_svc_local = HMAP_INITIALIZER(&ic_svc_local); + struct hmap ic_svc_remote = HMAP_INITIALIZER(&ic_svc_remote); + struct hmap sb_svc_non_local = HMAP_INITIALIZER(&sb_svc_non_local); + struct hmap sb_svc_propagated = HMAP_INITIALIZER(&sb_svc_propagated); + + const struct icsbrec_service_monitor *ic_svc_rec; + ICSBREC_SERVICE_MONITOR_FOR_EACH (ic_svc_rec, ctx->ovnisb_idl) { + struct ic_service_monitor_info *ic_mon_info; + bool is_local = !strcmp(ic_svc_rec->src_availability_zone, az->name); + init_svc_hashmap(is_local ? &ic_svc_local : &ic_svc_remote, + ic_svc_rec->port, ic_svc_rec->ip, + ic_svc_rec->logical_port, + (void **)&ic_mon_info, + ic_svc_rec, true); + } + + const struct sbrec_service_monitor *sb_svc_rec; + SBREC_SERVICE_MONITOR_FOR_EACH (sb_svc_rec, ctx->ovnsb_idl) { + struct sb_service_monitor_info *sb_mon_info; + + if (sb_svc_rec->propogated) { + init_svc_hashmap(&sb_svc_propagated, sb_svc_rec->port, + sb_svc_rec->ip, sb_svc_rec->logical_port, + (void **)&sb_mon_info, + sb_svc_rec, false); + } else if (!sb_svc_rec->local_backend) { + init_svc_hashmap(&sb_svc_non_local, sb_svc_rec->port, + sb_svc_rec->ip, sb_svc_rec->logical_port, + (void **)&sb_mon_info, + sb_svc_rec, false); + } + } + + SBREC_SERVICE_MONITOR_FOR_EACH (sb_svc_rec, ctx->ovnsb_idl) { + sync_sb_to_ic_base(ctx, sb_svc_rec, az, + &ic_svc_local, + &ic_svc_remote); + } + + ICSBREC_SERVICE_MONITOR_FOR_EACH (ic_svc_rec, ctx->ovnisb_idl) { + sync_ic_to_sb_base(ctx, ic_svc_rec, az, + &sb_svc_propagated, + &sb_svc_non_local); + } + + struct ic_service_monitor_info *ic_mon_info; + HMAP_FOR_EACH_SAFE (ic_mon_info, hmap_node, &ic_svc_local) { + if (!ic_mon_info->required) { + icsbrec_service_monitor_delete(ic_mon_info->rec); + hmap_remove(&ic_svc_local, &ic_mon_info->hmap_node); + free(ic_mon_info); + } + } + + struct sb_service_monitor_info *sb_mon_info; + HMAP_FOR_EACH_SAFE (sb_mon_info, hmap_node, &sb_svc_propagated) { + if (!sb_mon_info->required) { + sbrec_service_monitor_delete(sb_mon_info->rec); + hmap_remove(&sb_svc_propagated, &sb_mon_info->hmap_node); + free(sb_mon_info); + } + } + + hmap_destroy(&ic_svc_local); + hmap_destroy(&ic_svc_remote); + hmap_destroy(&sb_svc_non_local); + hmap_destroy(&sb_svc_propagated); +} + static void gateway_run(struct ic_context *ctx, const struct icsbrec_availability_zone *az) { @@ -1976,6 +2262,7 @@ ovn_db_run(struct ic_context *ctx, ts_run(ctx); port_binding_run(ctx, az); route_run(ctx, az); + sync_service_monitor(ctx, az); } static void @@ -2285,6 +2572,31 @@ 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_local_backend); + 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_propogated); + 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_status); /* Create IDL indexes */ struct ovsdb_idl_index *nbrec_ls_by_name diff --git a/northd/lb.c b/northd/lb.c index af0c92954..59502e0e0 100644 --- a/northd/lb.c +++ b/northd/lb.c @@ -119,7 +119,14 @@ ovn_lb_vip_backends_health_check_init(const struct ovn_northd_lb *lb, } char *svc_mon_src_ip = NULL; + char *az_name = NULL; char *port_name = xstrdup(s); + char *remote = strstr(port_name, "remote"); + + if (remote) { + *(remote - 1) = 0; + az_name = remote + 7; + } char *p = strstr(port_name, ":"); if (p) { *p = 0; @@ -143,6 +150,10 @@ ovn_lb_vip_backends_health_check_init(const struct ovn_northd_lb *lb, backend_nb->health_check = true; backend_nb->logical_port = xstrdup(port_name); backend_nb->svc_mon_src_ip = svc_mon_src_ip; + backend_nb->local_backend = remote ? false : true; + if (remote) { + backend_nb->az_name = xstrdup(az_name); + } } free(port_name); } diff --git a/northd/lb.h b/northd/lb.h index aa6616af4..f4b92d617 100644 --- a/northd/lb.h +++ b/northd/lb.h @@ -85,8 +85,10 @@ struct ovn_northd_lb_vip { struct ovn_northd_lb_backend { bool health_check; + bool local_backend; /* Set to true if port locates in our ovn cluster. */ char *logical_port; /* Logical port to which the ip belong to. */ char *svc_mon_src_ip; /* Source IP to use for monitoring. */ + char *az_name; }; struct ovn_northd_lb *ovn_northd_lb_create(const struct nbrec_load_balancer *); diff --git a/northd/northd.c b/northd/northd.c index 880ec92ac..1c7a5e870 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -3599,8 +3599,9 @@ static struct service_monitor_info * create_or_get_service_mon(struct ovsdb_idl_txn *ovnsb_txn, struct hmap *monitor_map, const char *ip, const char *logical_port, - uint16_t service_port, const char *protocol, - const char *chassis_name) + uint16_t service_port, bool local_backend, + const char *protocol, const char *chassis_name, + const char *az_name) { struct service_monitor_info *mon_info = get_service_mon(monitor_map, ip, logical_port, service_port, @@ -3626,9 +3627,18 @@ create_or_get_service_mon(struct ovsdb_idl_txn *ovnsb_txn, sbrec_service_monitor_set_port(sbrec_mon, service_port); sbrec_service_monitor_set_logical_port(sbrec_mon, logical_port); sbrec_service_monitor_set_protocol(sbrec_mon, protocol); + sbrec_service_monitor_set_local_backend(sbrec_mon, local_backend); if (chassis_name) { sbrec_service_monitor_set_chassis_name(sbrec_mon, chassis_name); } + + if (az_name) { + struct smap options = SMAP_INITIALIZER(&options); + smap_add(&options, "az-name", az_name); + sbrec_service_monitor_set_external_ids(sbrec_mon, &options); + smap_destroy(&options); + } + mon_info = xzalloc(sizeof *mon_info); mon_info->sbrec_mon = sbrec_mon; hmap_insert(monitor_map, &mon_info->hmap_node, hash); @@ -3636,12 +3646,12 @@ create_or_get_service_mon(struct ovsdb_idl_txn *ovnsb_txn, } static void -ovn_lb_svc_create(struct ovsdb_idl_txn *ovnsb_txn, - const struct ovn_northd_lb *lb, - const char *svc_monitor_mac, - const struct eth_addr *svc_monitor_mac_ea, - struct hmap *monitor_map, struct hmap *ls_ports, - struct sset *svc_monitor_lsps) +ovn_lb_svc_create_local(struct ovsdb_idl_txn *ovnsb_txn, + const struct ovn_northd_lb *lb, + const char *svc_monitor_mac, + const struct eth_addr *svc_monitor_mac_ea, + struct hmap *monitor_map, struct hmap *ls_ports, + struct sset *svc_monitor_lsps) { if (lb->template) { return; @@ -3664,7 +3674,8 @@ ovn_lb_svc_create(struct ovsdb_idl_txn *ovnsb_txn, struct ovn_port *op = ovn_port_find(ls_ports, backend_nb->logical_port); - if (!op || !lsp_is_enabled(op->nbsp)) { + if (backend_nb->local_backend && + (!op || !lsp_is_enabled(op->nbsp))) { continue; } @@ -3674,7 +3685,7 @@ ovn_lb_svc_create(struct ovsdb_idl_txn *ovnsb_txn, } const char *chassis_name = NULL; - if (op->sb->chassis) { + if (backend_nb->local_backend && op->sb->chassis) { chassis_name = op->sb->chassis->name; } @@ -3683,8 +3694,9 @@ ovn_lb_svc_create(struct ovsdb_idl_txn *ovnsb_txn, backend->ip_str, backend_nb->logical_port, backend->port, - protocol, - chassis_name); + backend_nb->local_backend, + protocol, chassis_name, + backend_nb->az_name); ovs_assert(mon_info); sbrec_service_monitor_set_options( mon_info->sbrec_mon, &lb_vip_nb->lb_health_check->options); @@ -3704,11 +3716,13 @@ ovn_lb_svc_create(struct ovsdb_idl_txn *ovnsb_txn, backend_nb->svc_mon_src_ip); } - if ((!op->sb->n_up || !op->sb->up[0]) - && mon_info->sbrec_mon->status - && !strcmp(mon_info->sbrec_mon->status, "online")) { - sbrec_service_monitor_set_status(mon_info->sbrec_mon, - "offline"); + if (backend_nb->local_backend) { + if ((!op->sb->n_up || !op->sb->up[0]) + && mon_info->sbrec_mon->status + && !strcmp(mon_info->sbrec_mon->status, "online")) { + sbrec_service_monitor_set_status(mon_info->sbrec_mon, + "offline"); + } } mon_info->required = true; @@ -3924,20 +3938,22 @@ build_lb_svcs( const struct sbrec_service_monitor *sbrec_mon; SBREC_SERVICE_MONITOR_TABLE_FOR_EACH (sbrec_mon, sbrec_service_monitor_table) { - uint32_t hash = sbrec_mon->port; - hash = hash_string(sbrec_mon->ip, hash); - hash = hash_string(sbrec_mon->logical_port, hash); - struct service_monitor_info *mon_info = xzalloc(sizeof *mon_info); - mon_info->sbrec_mon = sbrec_mon; - mon_info->required = false; - hmap_insert(svc_monitor_map, &mon_info->hmap_node, hash); + if (!sbrec_mon->propogated) { + uint32_t hash = sbrec_mon->port; + hash = hash_string(sbrec_mon->ip, hash); + hash = hash_string(sbrec_mon->logical_port, hash); + struct service_monitor_info *mon_info = xzalloc(sizeof *mon_info); + mon_info->sbrec_mon = sbrec_mon; + mon_info->required = false; + hmap_insert(svc_monitor_map, &mon_info->hmap_node, hash); + } } struct ovn_lb_datapaths *lb_dps; HMAP_FOR_EACH (lb_dps, hmap_node, lb_dps_map) { - ovn_lb_svc_create(ovnsb_txn, lb_dps->lb, svc_monitor_mac, - svc_monitor_mac_ea, svc_monitor_map, ls_ports, - svc_monitor_lsps); + ovn_lb_svc_create_local(ovnsb_txn, lb_dps->lb, svc_monitor_mac, + svc_monitor_mac_ea, svc_monitor_map, ls_ports, + svc_monitor_lsps); } struct service_monitor_info *mon_info; @@ -10315,6 +10331,50 @@ build_lswitch_ip_unicast_lookup_for_nats( } } +static void +ovn_lb_svc_create_propagated(const struct sbrec_service_monitor *sbrec_mon, + const struct eth_addr *svc_monitor_mac_ea, + const char *svc_monitor_mac) +{ + struct eth_addr ea; + if (!sbrec_mon->src_mac || + !eth_addr_from_string(sbrec_mon->src_mac, &ea) || + !eth_addr_equals(ea, *svc_monitor_mac_ea)) { + sbrec_service_monitor_set_src_mac(sbrec_mon, + svc_monitor_mac); + } + + /* TODO: set port to svc_monitor_lsps */ +} + +static void +build_prgp_svc(struct lflow_input *input_data, + const struct eth_addr *svc_monitor_mac_ea, + const char *svc_monitor_mac, + const struct hmap *prgp_svc) +{ + + const struct sbrec_service_monitor *sbrec_mon; + SBREC_SERVICE_MONITOR_TABLE_FOR_EACH (sbrec_mon, + input_data->sbrec_svc_table) { + if (sbrec_mon->propogated) { + uint32_t hash = sbrec_mon->port; + hash = hash_string(sbrec_mon->ip, hash); + hash = hash_string(sbrec_mon->logical_port, hash); + struct service_monitor_info *mon_info = xzalloc(sizeof *mon_info); + mon_info->sbrec_mon = sbrec_mon; + mon_info->required = false; + hmap_insert(prgp_svc, &mon_info->hmap_node, hash); + } + } + + struct service_monitor_info *mon_info; + HMAP_FOR_EACH (mon_info, hmap_node, prgp_svc) { + ovn_lb_svc_create_propagated(mon_info->sbrec_mon, svc_monitor_mac_ea, + svc_monitor_mac); + } +} + struct bfd_entry { struct hmap_node hmap_node; @@ -17421,6 +17481,7 @@ struct lswitch_flow_build_info { const struct shash *meter_groups; const struct hmap *lb_dps_map; const struct hmap *svc_monitor_map; + const struct hmap *prgp_svc; const struct sset *bfd_ports; const struct chassis_features *features; char *svc_check_match; @@ -17788,6 +17849,7 @@ build_lswitch_and_lrouter_flows( const struct shash *meter_groups, const struct hmap *lb_dps_map, const struct hmap *svc_monitor_map, + const struct hmap *prgp_svc, const struct sset *bfd_ports, const struct chassis_features *features, const char *svc_monitor_mac, @@ -17828,6 +17890,7 @@ build_lswitch_and_lrouter_flows( lsiv[index].svc_check_match = svc_check_match; lsiv[index].thread_lflow_counter = 0; lsiv[index].svc_monitor_mac = svc_monitor_mac; + lsiv[index].prgp_svc = prgp_svc; lsiv[index].sampling_apps = sampling_apps; lsiv[index].route_data = route_data; lsiv[index].route_tables = route_tables; @@ -17871,6 +17934,7 @@ build_lswitch_and_lrouter_flows( .features = features, .svc_check_match = svc_check_match, .svc_monitor_mac = svc_monitor_mac, + .prgp_svc = prgp_svc, .sampling_apps = sampling_apps, .route_data = route_data, .route_tables = route_tables, @@ -18036,6 +18100,7 @@ void build_lflows(struct ovsdb_idl_txn *ovnsb_txn, input_data->meter_groups, input_data->lb_datapaths_map, input_data->svc_monitor_map, + input_data->prgp_svc, input_data->bfd_ports, input_data->features, input_data->svc_monitor_mac, @@ -18884,7 +18949,12 @@ northd_destroy(struct northd_data *data) HMAP_FOR_EACH_POP (mon_info, hmap_node, &data->svc_monitor_map) { free(mon_info); } - hmap_destroy(&data->svc_monitor_map); + hmap_destroy(&data->prgp_svc); + + HMAP_FOR_EACH_POP (mon_info, hmap_node, &data->prgp_svc) { + free(mon_info); + } + hmap_destroy(&data->prgp_svc); /* XXX Having to explicitly clean up macam here * is a bit strange. We don't explicitly initialize diff --git a/northd/northd.h b/northd/northd.h index 388bac6df..3c590a646 100644 --- a/northd/northd.h +++ b/northd/northd.h @@ -169,6 +169,7 @@ struct northd_data { struct ovs_list lr_list; struct sset svc_monitor_lsps; struct hmap svc_monitor_map; + struct hmap prgp_svc; /* Change tracking data. */ struct northd_tracked_data trk_data; @@ -218,6 +219,7 @@ struct lflow_input { const struct sbrec_logical_flow_table *sbrec_logical_flow_table; const struct sbrec_logical_dp_group_table *sbrec_logical_dp_group_table; const struct sbrec_acl_id_table *sbrec_acl_id_table; + const struct sbrec_service_monitor_table *sbrec_svc_table; /* Indexes */ struct ovsdb_idl_index *sbrec_mcast_group_by_name_dp; @@ -234,8 +236,10 @@ struct lflow_input { const struct sset *bfd_ports; const struct chassis_features *features; const struct hmap *svc_monitor_map; + const struct hmap *prgp_svc; bool ovn_internal_version_changed; const char *svc_monitor_mac; + struct eth_addr svc_monitor_mac_ea; const struct sampling_app_table *sampling_apps; struct group_ecmp_route_data *route_data; struct hmap *route_policies; diff --git a/ovn-ic-sb.ovsschema b/ovn-ic-sb.ovsschema index 459c3833e..2b732881e 100644 --- a/ovn-ic-sb.ovsschema +++ b/ovn-ic-sb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_IC_Southbound", - "version": "2.0.0", - "cksum": "197748428 7081", + "version": "2.1.0", + "cksum": "125433995 8340", "tables": { "IC_SB_Global": { "columns": { @@ -144,6 +144,31 @@ "value": "string", "min": 0, "max": "unlimited"}}}, - "maxRows": 1} + "maxRows": 1}, + "Service_Monitor": { + "columns": { + "src_availability_zone": {"type": "string"}, + "dst_availability_zone": {"type": "string"}, + "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"}, + "status": { + "type": {"key": {"type": "string", + "enum": ["set", ["online", "offline", "error"]]}, + "min": 0, "max": 1}}, + "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 5f0743dc3..7f2f38b3a 100644 --- a/ovn-ic-sb.xml +++ b/ovn-ic-sb.xml @@ -689,4 +689,50 @@ </group> </table> + <table name="Service_Monitor"> + + <column name="src_availability_zone"> + Availability zone in which a balancer with a backend and a service + monitor for a port in another ovn deployment is created. + </column> + + <column name="dst_availability_zone"> + Availability zone in which the port, for which the propogated record + was created in the Southbound Database is located. + </column> + + <column name="ip"> + IP of the service to be monitored. + </column> + + <column name="protocol"> + The protocol of the service. + </column> + + <column name="port"> + The TCP or UDP port of the service. + </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. + </column> + + <column name="src_ip"> + Source Ethernet address to use in the service monitor packet. + </column> + + <column name="status"> + Same as in Table Service_Monitor in SBDB. + </column> + + <column name="options"> + Same as in Table Service_Monitor in SBDB. + </column> + + <column name="external_ids"> + </column> + + </table> </database> diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema index d7cfeaa8f..81606ce7c 100644 --- a/ovn-sb.ovsschema +++ b/ovn-sb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Southbound", - "version": "21.0.0", - "cksum": "4028932437 34711", + "version": "21.1.0", + "cksum": "2798142836 34816", "tables": { "SB_Global": { "columns": { @@ -519,6 +519,8 @@ "type": {"key": {"type": "string", "enum": ["set", ["online", "offline", "error"]]}, "min": 0, "max": 1}}, + "local_backend": {"type": "boolean"}, + "propogated": {"type": "boolean"}, "options": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, diff --git a/ovn-sb.xml b/ovn-sb.xml index 4bcf44d04..2b26acbf8 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -4973,6 +4973,15 @@ tcp.flags = RST; The name of the chassis where the logical port is bound. </column> + <column name="local_backend"> + Set to true if backend locates on local ovn deployment. + </column> + + <column name="propogated"> + Set to true if service monitor was propogated from another ovn + deployment. + </column> + <column name="options" key="interval" type='{"type": "integer"}'> The interval, in seconds, between service monitor checks. </column> -- regards, Alexandra. _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev