[ovs-dev] [PATCH v4 ovn 3/3] controller: add memory accounting for local_datapath

Dumitru Ceara dceara at redhat.com
Mon Oct 18 11:36:47 UTC 2021


On 10/14/21 5:17 PM, Lorenzo Bianconi wrote:
> Similar to if-status-mgr, track memory allocated for local_datapath.
> 
> Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi at redhat.com>
> ---
>  controller/binding.c        |  6 ++--
>  controller/local_data.c     | 66 +++++++++++++++++++++++++++++++++++++
>  controller/local_data.h     |  7 ++++
>  controller/ovn-controller.c |  1 +
>  4 files changed, 77 insertions(+), 3 deletions(-)
> 
> diff --git a/controller/binding.c b/controller/binding.c
> index c037b2352..329d0d12b 100644
> --- a/controller/binding.c
> +++ b/controller/binding.c
> @@ -374,8 +374,8 @@ update_ld_external_ports(const struct sbrec_port_binding *binding_rec,
>      struct local_datapath *ld = get_local_datapath(
>          local_datapaths, binding_rec->datapath->tunnel_key);
>      if (ld) {
> -        shash_replace(&ld->external_ports, binding_rec->logical_port,
> -                      binding_rec);
> +        add_local_datapath_external_port(ld, binding_rec->logical_port,
> +                                         binding_rec);
>      }
>  }
>  
> @@ -1756,7 +1756,7 @@ remove_pb_from_local_datapath(const struct sbrec_port_binding *pb,
>              ld->localnet_port = NULL;
>          }
>      } else if (!strcmp(pb->type, "external")) {
> -        shash_find_and_delete(&ld->external_ports, pb->logical_port);
> +        remove_local_datapath_external_port(ld, pb->logical_port);
>      }
>  }
>  
> diff --git a/controller/local_data.c b/controller/local_data.c
> index 6efed2de0..48e6958b7 100644
> --- a/controller/local_data.c
> +++ b/controller/local_data.c
> @@ -47,6 +47,30 @@ static struct tracked_datapath *tracked_datapath_create(
>      enum en_tracked_resource_type tracked_type,
>      struct hmap *tracked_datapaths);
>  
> +static uint64_t local_datapath_usage;
> +
> +static void
> +local_datapath_peer_ports_mem_add(struct local_datapath *ld,
> +                                  size_t n_peer_ports)
> +{
> +    /* memory accounting - peer_ports. */
> +    local_datapath_usage +=
> +        (ld->n_allocated_peer_ports - n_peer_ports) * sizeof *ld->peer_ports;
> +}
> +
> +static void
> +local_datapath_ext_port_mem_update(struct local_datapath *ld, const char *name,
> +                                   bool erase)
> +{
> +    struct shash_node *node = shash_find(&ld->external_ports, name);
> +
> +    if (!node && !erase) { /* add a new element */
> +        local_datapath_usage += (sizeof *node + strlen(name));
> +    } else if (node && erase) { /* remove an element */
> +        local_datapath_usage -= (sizeof *node + strlen(name));
> +    }
> +}
> +
>  struct local_datapath *
>  get_local_datapath(const struct hmap *local_datapaths, uint32_t tunnel_key)
>  {
> @@ -63,6 +87,9 @@ local_datapath_alloc(const struct sbrec_datapath_binding *dp)
>      ld->datapath = dp;
>      ld->is_switch = datapath_is_switch(dp);
>      shash_init(&ld->external_ports);
> +    /* memory accounting - common part. */
> +    local_datapath_usage += sizeof *ld;
> +
>      return ld;
>  }
>  
> @@ -80,6 +107,16 @@ local_datapaths_destroy(struct hmap *local_datapaths)
>  void
>  local_datapath_destroy(struct local_datapath *ld)
>  {
> +    /* memory accounting. */
> +    struct shash_node *node;
> +    SHASH_FOR_EACH (node, &ld->external_ports) {
> +        local_datapath_usage -= strlen(node->name);
> +    }
> +    local_datapath_usage -= shash_count(&ld->external_ports) * sizeof *node;
> +    local_datapath_usage -= sizeof *ld;
> +    local_datapath_usage -=
> +        ld->n_allocated_peer_ports * sizeof *ld->peer_ports;
> +
>      free(ld->peer_ports);
>      shash_destroy(&ld->external_ports);
>      free(ld);
> @@ -175,10 +212,12 @@ add_local_datapath_peer_port(
>      if (!present) {
>          ld->n_peer_ports++;
>          if (ld->n_peer_ports > ld->n_allocated_peer_ports) {
> +            size_t n_peer_ports = ld->n_allocated_peer_ports;
>              ld->peer_ports =
>                  x2nrealloc(ld->peer_ports,
>                             &ld->n_allocated_peer_ports,
>                             sizeof *ld->peer_ports);
> +            local_datapath_peer_ports_mem_add(ld, n_peer_ports);
>          }
>          ld->peer_ports[ld->n_peer_ports - 1].local = pb;
>          ld->peer_ports[ld->n_peer_ports - 1].remote = peer;
> @@ -204,10 +243,12 @@ add_local_datapath_peer_port(
>  
>      peer_ld->n_peer_ports++;
>      if (peer_ld->n_peer_ports > peer_ld->n_allocated_peer_ports) {
> +        size_t n_peer_ports = peer_ld->n_allocated_peer_ports;
>          peer_ld->peer_ports =
>              x2nrealloc(peer_ld->peer_ports,
>                          &peer_ld->n_allocated_peer_ports,
>                          sizeof *peer_ld->peer_ports);
> +            local_datapath_peer_ports_mem_add(peer_ld, n_peer_ports);
>      }
>      peer_ld->peer_ports[peer_ld->n_peer_ports - 1].local = peer;
>      peer_ld->peer_ports[peer_ld->n_peer_ports - 1].remote = pb;
> @@ -248,6 +289,22 @@ remove_local_datapath_peer_port(const struct sbrec_port_binding *pb,
>      }
>  }
>  
> +void
> +add_local_datapath_external_port(struct local_datapath *ld,
> +                                 char *logical_port, const void *data)
> +{
> +    local_datapath_ext_port_mem_update(ld, logical_port, false);
> +    shash_replace(&ld->external_ports, logical_port, data);


We can simplify this and remove local_datapath_ext_port_mem_update()
if we rewrite it like:

if (!shash_replace(&ld->external_ports, logical_port, data)) {
    local_datapath_usage += sizeof(struct shash_node) + strlen(logical_port);
}

> +}
> +
> +void
> +remove_local_datapath_external_port(struct local_datapath *ld,
> +                                    char *logical_port)
> +{
> +    local_datapath_ext_port_mem_update(ld, logical_port, true);
> +    shash_find_and_delete(&ld->external_ports, logical_port);

Here too:

if (shash_find_and_delete(&ld->external_ports, logical_port)) {
    local_datapath_usage -= sizeof(struct shash_node) + strlen(logical_port);
}

> +}
> +
>  /* track datapath functions. */
>  struct tracked_datapath *
>  tracked_datapath_add(const struct sbrec_datapath_binding *dp,
> @@ -537,10 +594,12 @@ add_local_datapath__(struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
>                      }
>                      ld->n_peer_ports++;
>                      if (ld->n_peer_ports > ld->n_allocated_peer_ports) {
> +                        size_t n_peer_ports = ld->n_allocated_peer_ports;
>                          ld->peer_ports =
>                              x2nrealloc(ld->peer_ports,
>                                         &ld->n_allocated_peer_ports,
>                                         sizeof *ld->peer_ports);
> +                        local_datapath_peer_ports_mem_add(ld, n_peer_ports);

There's quite some code duplication when adding a new datapath peer port
(3 different places), we can probably refactor it and also include
memory accounting directly in there if we add a new function:

static void
local_datapath_peer_port_add(struct local_datapath *ld,
                             const struct sbrec_port_binding *local,
                             const struct sbrec_port_binding *remote)
{
    ld->n_peer_ports++;
    if (ld->n_peer_ports > ld->n_allocated_peer_ports) {
        size_t old_n_ports = ld->n_allocated_peer_ports;
        ld->peer_ports =
            x2nrealloc(ld->peer_ports,
                       &ld->n_allocated_peer_ports,
                       sizeof *ld->peer_ports);
        local_datapath_usage +=
            (ld->n_allocated_peer_ports - old_n_ports) *
            sizeof *ld->peer_ports;
    }
    ld->peer_ports[ld->n_peer_ports - 1].local = local;
    ld->peer_ports[ld->n_peer_ports - 1].remote = remote;
}

What do you think?

Thanks,
Dumitru



More information about the dev mailing list