On Thu, Apr 17, 2025 at 1:35 PM Rukomoinikova Aleksandra <ARukomoinikova@k2.cloud> wrote: > > 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? >
What do you mean by LB node here ? Is it in the northd context or in ovn-controller context ? I didn't get the chance to look at this RFC. Let me take a look and come back. Numan > > 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