On Thu, Aug 10, 2023 at 2:44 PM Dumitru Ceara <dce...@redhat.com> wrote:

> It's actually a generic wrapper and will be useful for upcoming commits.
> This commit doesn't perform any functional changes but cleans up a bit
> the implementation unifying the sorted_array cleanup.  Before the change
> the caller had to track whether it should free the internal 'arr' field
> or not.  It's now taken care of inside the sorted_array_destroy() API
> which the user always has to call.
>
> Signed-off-by: Dumitru Ceara <dce...@redhat.com>
> ---
>  lib/ovn-util.h      |   78 +++++++++++++++++++++++++++
>  northd/en-sync-sb.c |  150
> +++++++++++++++++----------------------------------
>  2 files changed, 127 insertions(+), 101 deletions(-)
>
> diff --git a/lib/ovn-util.h b/lib/ovn-util.h
> index 5ebdd8adb0..2de7725132 100644
> --- a/lib/ovn-util.h
> +++ b/lib/ovn-util.h
> @@ -18,6 +18,8 @@
>
>  #include "ovsdb-idl.h"
>  #include "lib/packets.h"
> +#include "lib/sset.h"
> +#include "lib/svec.h"
>  #include "include/ovn/version.h"
>
>  #define ovn_set_program_name(name) \
> @@ -409,4 +411,80 @@ void flow_collector_ids_clear(struct
> flow_collector_ids *);
>   * The returned pointer has to be freed by caller. */
>  char *encode_fqdn_string(const char *fqdn, size_t *len);
>
> +/* A wrapper that holds sorted arrays of strings. */
> +struct sorted_array {
> +    const char **arr;
> +    bool owns_array;
> +    size_t n;
> +};
> +
> +static inline struct sorted_array
> +sorted_array_create(const char **sorted_data, size_t n, bool
> take_ownership)
> +{
> +    return (struct sorted_array) {
> +        .arr = sorted_data,
> +        .owns_array = take_ownership,
> +        .n = n,
> +    };
> +}
> +
> +static inline void
> +sorted_array_destroy(struct sorted_array *a)
> +{
> +    if (a->owns_array) {
> +        free(a->arr);
> +    }
> +}
> +
> +static inline struct sorted_array
> +sorted_array_from_svec(struct svec *v)
> +{
> +    svec_sort(v);
> +    return sorted_array_create((const char **) v->names, v->n, false);
> +}
> +
> +static inline struct sorted_array
> +sorted_array_from_sset(struct sset *s)
> +{
> +    return sorted_array_create(sset_sort(s), sset_count(s), true);
> +}
> +
> +/* DB set columns are already sorted, just wrap them into a sorted array.
> */
> +#define sorted_array_from_dbrec(dbrec, column)           \
> +    sorted_array_create((const char **) (dbrec)->column, \
> +                        (dbrec)->n_##column, false)
> +
> +static inline void
> +sorted_array_apply_diff(const struct sorted_array *a1,
> +                        const struct sorted_array *a2,
> +                        void (*apply_callback)(const void *arg,
> +                                               const char *item,
> +                                               bool add),
> +                        const void *arg)
> +{
> +    size_t idx1, idx2;
> +
> +    for (idx1 = idx2 = 0; idx1 < a1->n && idx2 < a2->n;) {
> +        int cmp = strcmp(a1->arr[idx1], a2->arr[idx2]);
> +        if (cmp < 0) {
> +            apply_callback(arg, a1->arr[idx1], true);
> +            idx1++;
> +        } else if (cmp > 0) {
> +            apply_callback(arg, a2->arr[idx2], false);
> +            idx2++;
> +        } else {
> +            idx1++;
> +            idx2++;
> +        }
> +    }
> +
> +    for (; idx1 < a1->n; idx1++) {
> +        apply_callback(arg, a1->arr[idx1], true);
> +    }
> +
> +    for (; idx2 < a2->n; idx2++) {
> +        apply_callback(arg, a2->arr[idx2], false);
> +    }
> +}
> +
>  #endif /* OVN_UTIL_H */
> diff --git a/northd/en-sync-sb.c b/northd/en-sync-sb.c
> index d7fea981f2..f97771b3b4 100644
> --- a/northd/en-sync-sb.c
> +++ b/northd/en-sync-sb.c
> @@ -33,15 +33,8 @@
>
>  VLOG_DEFINE_THIS_MODULE(en_sync_to_sb);
>
> -/* This is just a type wrapper to enforce that it has to be sorted. */
> -struct sorted_addresses {
> -    const char **arr;
> -    size_t n;
> -};
> -
> -
>  static void sync_addr_set(struct ovsdb_idl_txn *ovnsb_txn, const char
> *name,
> -                          struct sorted_addresses *addresses,
> +                          struct sorted_array *addresses,
>                            struct shash *sb_address_sets);
>  static void sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn,
>                             const struct nbrec_address_set_table *,
> @@ -50,17 +43,11 @@ static void sync_addr_sets(struct ovsdb_idl_txn
> *ovnsb_txn,
>                             const struct ovn_datapaths *lr_datapaths);
>  static const struct sbrec_address_set *sb_address_set_lookup_by_name(
>      struct ovsdb_idl_index *, const char *name);
> -static void update_sb_addr_set(struct sorted_addresses *,
> +static void update_sb_addr_set(struct sorted_array *,
>                                 const struct sbrec_address_set *);
>  static void build_port_group_address_set(const struct nbrec_port_group *,
>                                           struct svec *ipv4_addrs,
>                                           struct svec *ipv6_addrs);
> -static struct sorted_addresses
> -sorted_addresses_from_nbrec(const struct nbrec_address_set *nb_as);
> -static struct sorted_addresses
> -sorted_addresses_from_svec(struct svec *addresses);
> -static struct sorted_addresses
> -sorted_addresses_from_sset(struct sset *addresses);
>
>  void *
>  en_sync_to_sb_init(struct engine_node *node OVS_UNUSED,
> @@ -145,9 +132,10 @@ sync_to_sb_addr_set_nb_address_set_handler(struct
> engine_node *node,
>          if (!sb_addr_set) {
>              return false;
>          }
> -        struct sorted_addresses addrs =
> -                sorted_addresses_from_nbrec(nb_addr_set);
> +        struct sorted_array addrs =
> +            sorted_array_from_dbrec(nb_addr_set, addresses);
>          update_sb_addr_set(&addrs, sb_addr_set);
> +        sorted_array_destroy(&addrs);
>      }
>
>      return true;
> @@ -194,18 +182,20 @@ sync_to_sb_addr_set_nb_port_group_handler(struct
> engine_node *node,
>          struct svec ipv6_addrs = SVEC_EMPTY_INITIALIZER;
>          build_port_group_address_set(nb_pg, &ipv4_addrs, &ipv6_addrs);
>
> -        struct sorted_addresses ipv4_addrs_sorted =
> -                sorted_addresses_from_svec(&ipv4_addrs);
> -        struct sorted_addresses ipv6_addrs_sorted =
> -                sorted_addresses_from_svec(&ipv6_addrs);
> +        struct sorted_array ipv4_addrs_sorted =
> +                sorted_array_from_svec(&ipv4_addrs);
> +        struct sorted_array ipv6_addrs_sorted =
> +                sorted_array_from_svec(&ipv6_addrs);
>
>          update_sb_addr_set(&ipv4_addrs_sorted, sb_addr_set_v4);
>          update_sb_addr_set(&ipv6_addrs_sorted, sb_addr_set_v6);
>
> -        free(ipv4_addrs_name);
> -        free(ipv6_addrs_name);
> +        sorted_array_destroy(&ipv4_addrs_sorted);
> +        sorted_array_destroy(&ipv6_addrs_sorted);
>          svec_destroy(&ipv4_addrs);
>          svec_destroy(&ipv6_addrs);
> +        free(ipv4_addrs_name);
> +        free(ipv6_addrs_name);
>      }
>
>      return true;
> @@ -214,7 +204,7 @@ sync_to_sb_addr_set_nb_port_group_handler(struct
> engine_node *node,
>  /* static functions. */
>  static void
>  sync_addr_set(struct ovsdb_idl_txn *ovnsb_txn, const char *name,
> -              struct sorted_addresses *addresses,
> +              struct sorted_array *addresses,
>                struct shash *sb_address_sets)
>  {
>      const struct sbrec_address_set *sb_address_set;
> @@ -261,11 +251,9 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn,
>
>      /* Service monitor MAC. */
>      const char *svc_monitor_macp = northd_get_svc_monitor_mac();
> -    struct sorted_addresses svc = {
> -            .arr = &svc_monitor_macp,
> -            .n = 1,
> -    };
> +    struct sorted_array svc = sorted_array_create(&svc_monitor_macp, 1,
> false);
>      sync_addr_set(ovnsb_txn, "svc_monitor_mac", &svc, &sb_address_sets);
> +    sorted_array_destroy(&svc);
>
>      /* sync port group generated address sets first */
>      const struct nbrec_port_group *nb_port_group;
> @@ -277,19 +265,21 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn,
>          char *ipv4_addrs_name = xasprintf("%s_ip4", nb_port_group->name);
>          char *ipv6_addrs_name = xasprintf("%s_ip6", nb_port_group->name);
>
> -        struct sorted_addresses ipv4_addrs_sorted =
> -                sorted_addresses_from_svec(&ipv4_addrs);
> -        struct sorted_addresses ipv6_addrs_sorted =
> -                sorted_addresses_from_svec(&ipv6_addrs);
> +        struct sorted_array ipv4_addrs_sorted =
> +                sorted_array_from_svec(&ipv4_addrs);
> +        struct sorted_array ipv6_addrs_sorted =
> +                sorted_array_from_svec(&ipv6_addrs);
>
>          sync_addr_set(ovnsb_txn, ipv4_addrs_name,
>                        &ipv4_addrs_sorted, &sb_address_sets);
>          sync_addr_set(ovnsb_txn, ipv6_addrs_name,
>                        &ipv6_addrs_sorted, &sb_address_sets);
> -        free(ipv4_addrs_name);
> -        free(ipv6_addrs_name);
> +        sorted_array_destroy(&ipv4_addrs_sorted);
> +        sorted_array_destroy(&ipv6_addrs_sorted);
>          svec_destroy(&ipv4_addrs);
>          svec_destroy(&ipv6_addrs);
> +        free(ipv4_addrs_name);
> +        free(ipv6_addrs_name);
>      }
>
>      /* Sync router load balancer VIP generated address sets. */
> @@ -301,24 +291,24 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn,
>              char *ipv4_addrs_name = lr_lb_address_set_name(od->tunnel_key,
>                                                             AF_INET);
>
> -            struct sorted_addresses ipv4_addrs_sorted =
> -
> sorted_addresses_from_sset(&od->lb_ips->ips_v4_reachable);
> +            struct sorted_array ipv4_addrs_sorted =
> +                    sorted_array_from_sset(&od->lb_ips->ips_v4_reachable);
>
>              sync_addr_set(ovnsb_txn, ipv4_addrs_name,
>                            &ipv4_addrs_sorted, &sb_address_sets);
> -            free(ipv4_addrs_sorted.arr);
> +            sorted_array_destroy(&ipv4_addrs_sorted);
>              free(ipv4_addrs_name);
>          }
>
>          if (sset_count(&od->lb_ips->ips_v6_reachable)) {
>              char *ipv6_addrs_name = lr_lb_address_set_name(od->tunnel_key,
>                                                             AF_INET6);
> -            struct sorted_addresses ipv6_addrs_sorted =
> -
> sorted_addresses_from_sset(&od->lb_ips->ips_v6_reachable);
> +            struct sorted_array ipv6_addrs_sorted =
> +                    sorted_array_from_sset(&od->lb_ips->ips_v6_reachable);
>
>              sync_addr_set(ovnsb_txn, ipv6_addrs_name,
>                            &ipv6_addrs_sorted, &sb_address_sets);
> -            free(ipv6_addrs_sorted.arr);
> +            sorted_array_destroy(&ipv6_addrs_sorted);
>              free(ipv6_addrs_name);
>          }
>      }
> @@ -328,10 +318,11 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn,
>      const struct nbrec_address_set *nb_address_set;
>      NBREC_ADDRESS_SET_TABLE_FOR_EACH (nb_address_set,
>                                        nb_address_set_table) {
> -        struct sorted_addresses addrs =
> -                sorted_addresses_from_nbrec(nb_address_set);
> +        struct sorted_array addrs =
> +                sorted_array_from_dbrec(nb_address_set, addresses);
>          sync_addr_set(ovnsb_txn, nb_address_set->name,
>                        &addrs, &sb_address_sets);
> +        sorted_array_destroy(&addrs);
>      }
>
>      struct shash_node *node;
> @@ -343,39 +334,25 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn,
>  }
>
>  static void
> -update_sb_addr_set(struct sorted_addresses *nb_addresses,
> -                   const struct sbrec_address_set *sb_as)
> +sb_addr_set_apply_diff(const void *arg, const char *item, bool add)
>  {
> -    size_t nb_index, sb_index;
> -
> -    const char **nb_arr = nb_addresses->arr;
> -    char **sb_arr = sb_as->addresses;
> -    size_t nb_n = nb_addresses->n;
> -    size_t sb_n = sb_as->n_addresses;
> -
> -    for (nb_index = sb_index = 0; nb_index < nb_n && sb_index < sb_n;) {
> -        int cmp = strcmp(nb_arr[nb_index], sb_arr[sb_index]);
> -        if (cmp < 0) {
> -            sbrec_address_set_update_addresses_addvalue(sb_as,
> -                                                        nb_arr[nb_index]);
> -            nb_index++;
> -        } else if (cmp > 0) {
> -            sbrec_address_set_update_addresses_delvalue(sb_as,
> -                                                        sb_arr[sb_index]);
> -            sb_index++;
> -        } else {
> -            nb_index++;
> -            sb_index++;
> -        }
> -    }
> -
> -    for (; nb_index < nb_n; nb_index++) {
> -        sbrec_address_set_update_addresses_addvalue(sb_as,
> nb_arr[nb_index]);
> +    const struct sbrec_address_set *as = arg;
> +    if (add) {
> +        sbrec_address_set_update_addresses_addvalue(as, item);
> +    } else {
> +        sbrec_address_set_update_addresses_delvalue(as, item);
>      }
> +}
>
> -    for (; sb_index < sb_n; sb_index++) {
> -        sbrec_address_set_update_addresses_delvalue(sb_as,
> sb_arr[sb_index]);
> -    }
> +static void
> +update_sb_addr_set(struct sorted_array *nb_addresses,
> +                   const struct sbrec_address_set *sb_as)
> +{
> +    struct sorted_array sb_addresses =
> +        sorted_array_from_dbrec(sb_as, addresses);
> +    sorted_array_apply_diff(nb_addresses, &sb_addresses,
> +                            sb_addr_set_apply_diff, sb_as);
> +    sorted_array_destroy(&sb_addresses);
>  }
>
>  static void
> @@ -414,32 +391,3 @@ sb_address_set_lookup_by_name(struct ovsdb_idl_index
> *sbrec_addr_set_by_name,
>
>      return retval;
>  }
> -
> -static struct sorted_addresses
> -sorted_addresses_from_nbrec(const struct nbrec_address_set *nb_as)
> -{
> -    /* The DB is already sorted. */
> -    return (struct sorted_addresses) {
> -        .arr = (const char **) nb_as->addresses,
> -        .n = nb_as->n_addresses,
> -    };
> -}
> -
> -static struct sorted_addresses
> -sorted_addresses_from_svec(struct svec *addresses)
> -{
> -    svec_sort(addresses);
> -    return (struct sorted_addresses) {
> -        .arr = (const char **) addresses->names,
> -        .n = addresses->n,
> -    };
> -}
> -
> -static struct sorted_addresses
> -sorted_addresses_from_sset(struct sset *addresses)
> -{
> -    return (struct sorted_addresses) {
> -        .arr = sset_sort(addresses),
> -        .n = sset_count(addresses),
> -    };
> -}
>
>
Happy to see that it has other uses besides the address sets.

Acked-by: Ales Musil <amu...@redhat.com>
-- 

Ales Musil

Senior Software Engineer - OVN Core

Red Hat EMEA <https://www.redhat.com>

amu...@redhat.com
<https://red.ht/sig>
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to