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

Reply via email to