On Tue, Jan 14, 2025 at 2:03 AM Ales Musil <[email protected]> wrote:
>
>
>
> On Mon, Jan 13, 2025 at 7:35 PM <[email protected]> wrote:
>>
>> From: Numan Siddique <[email protected]>
>>
>> Its possible for pinctrl handling for DNS packets to be blocked
>> if the ovn-controller main thread has acquired the dns cache
>> mutex during the recompute.  This patch improves the DNS packet
>> handling by using cmap instead of hmap to maintain the dns cache.
>> With this, there is no need to maintain a mutex.
>>
>> Since cmaps use OVSRCU_TYPE, in order to safely free the cmap data,
>> we need to manage the quiesce state for both the main ovn-controller
>> thread and pinctrl thread.  ovsrcu_quiesce_start() is called before
>> calling poll_block() and ovsrcu_quiesce_end() is called at the
>> start of the while for both these threads.
>>
>> Suggested-by: Ales Musil <[email protected]>
>> Signed-off-by: Numan Siddique <[email protected]>
>> ---
>>  controller/ovn-controller.c |   3 +
>>  controller/ovn-dns.c        | 144 +++++++++++++++---------------------
>>  controller/pinctrl.c        |   4 +
>>  3 files changed, 67 insertions(+), 84 deletions(-)
>>
>> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
>> index d875ecc1e6..890c8f988b 100644
>> --- a/controller/ovn-controller.c
>> +++ b/controller/ovn-controller.c
>> @@ -5458,6 +5458,8 @@ main(int argc, char *argv[])
>>      /* Main loop. */
>>      bool sb_monitor_all = false;
>>      while (!exit_args.exiting) {
>> +        ovsrcu_quiesce_end();
>> +
>>          memory_run();
>>          if (memory_should_report()) {
>>              struct simap usage = SIMAP_INITIALIZER(&usage);
>> @@ -5951,6 +5953,7 @@ main(int argc, char *argv[])
>>
>>  loop_done:
>>          memory_wait();
>> +        ovsrcu_quiesce_start();
>>          poll_block();
>>          if (should_service_stop()) {
>>              exit_args.exiting = true;
>> diff --git a/controller/ovn-dns.c b/controller/ovn-dns.c
>> index 026d9bc647..bfeef5a747 100644
>> --- a/controller/ovn-dns.c
>> +++ b/controller/ovn-dns.c
>> @@ -18,6 +18,7 @@
>>  /* OVS includes */
>>  #include "include/openvswitch/shash.h"
>>  #include "include/openvswitch/thread.h"
>> +#include "lib/cmap.h"
>>  #include "openvswitch/vlog.h"
>>
>>  /* OVN includes. */
>> @@ -28,7 +29,7 @@ VLOG_DEFINE_THIS_MODULE(ovndns);
>>
>>  /* Internal DNS cache entry for each SB DNS record. */
>>  struct dns_data {
>> -    struct hmap_node hmap_node;
>> +    struct cmap_node cmap_node;
>>      struct uuid uuid;
>>      uint64_t *dps;
>>      size_t n_dps;
>> @@ -38,114 +39,87 @@ struct dns_data {
>>  };
>>
>>  /* shash of 'struct dns_data'. */
>> -static struct hmap dns_cache_ = HMAP_INITIALIZER(&dns_cache_);
>> -
>> -/* Mutex to protect dns_cache_. */
>> -static struct ovs_mutex dns_cache_mutex = OVS_MUTEX_INITIALIZER;
>> +static struct cmap dns_cache_;
>>
>>  static void update_cache_with_dns_rec(const struct sbrec_dns *,
>>                                        struct dns_data *,
>>                                        const struct uuid *uuid,
>> -                                      struct hmap *dns_cache);
>> -static struct dns_data *dns_data_find(const struct uuid *uuid);
>> +                                      struct cmap *dns_cache);
>> +static struct dns_data *dns_data_find(const struct uuid *uuid,
>> +                                      const struct cmap *);
>>  static struct dns_data *dns_data_alloc(struct uuid uuid);
>>  static void dns_data_destroy(struct dns_data *dns_data);
>> +static void destroy_dns_cache(struct cmap *dns_cache);
>>
>>  void
>>  ovn_dns_cache_init(void)
>>  {
>> +    cmap_init(&dns_cache_);
>>  }
>>
>>  void
>>  ovn_dns_cache_destroy(void)
>>  {
>> -    ovs_mutex_lock(&dns_cache_mutex);
>> -    struct dns_data *dns_data;
>> -    HMAP_FOR_EACH_POP (dns_data, hmap_node, &dns_cache_) {
>> -        dns_data_destroy(dns_data);
>> -    }
>> -    hmap_destroy(&dns_cache_);
>> -    ovs_mutex_unlock(&dns_cache_mutex);
>> +    destroy_dns_cache(&dns_cache_);
>> +    cmap_destroy(&dns_cache_);
>>  }
>>
>>  void
>>  ovn_dns_sync_cache(const struct sbrec_dns_table *dns_table)
>>  {
>> -    ovs_mutex_lock(&dns_cache_mutex);
>> -    struct dns_data *dns_data;
>> -    HMAP_FOR_EACH (dns_data, hmap_node, &dns_cache_) {
>> -        dns_data->delete = true;
>> +    const struct sbrec_dns *sbrec_dns;
>> +    struct dns_data *existing;
>> +
>> +    CMAP_FOR_EACH (existing, cmap_node, &dns_cache_) {
>> +        existing->delete = true;
>>      }
>>
>> -    const struct sbrec_dns *sbrec_dns;
>>      SBREC_DNS_TABLE_FOR_EACH (sbrec_dns, dns_table) {
>>          const struct uuid *uuid = &sbrec_dns->header_.uuid;
>> -        dns_data = dns_data_find(uuid);
>> -        if (!dns_data) {
>> -            dns_data = dns_data_alloc(*uuid);
>> -            hmap_insert(&dns_cache_, &dns_data->hmap_node, uuid_hash(uuid));
>> -        } else {
>> -            free(dns_data->dps);
>> -        }
>> -
>> -        dns_data->delete = false;
>> -
>> -        if (!smap_equal(&dns_data->records, &sbrec_dns->records)) {
>> -            smap_destroy(&dns_data->records);
>> -            smap_clone(&dns_data->records, &sbrec_dns->records);
>> -        }
>> -
>> -        if (!smap_equal(&dns_data->options, &sbrec_dns->options)) {
>> -            smap_destroy(&dns_data->options);
>> -            smap_clone(&dns_data->options, &sbrec_dns->options);
>> -        }
>> -
>> -        dns_data->n_dps = sbrec_dns->n_datapaths;
>> -        dns_data->dps = xcalloc(dns_data->n_dps, sizeof(uint64_t));
>> -        for (size_t i = 0; i < sbrec_dns->n_datapaths; i++) {
>> -            dns_data->dps[i] = sbrec_dns->datapaths[i]->tunnel_key;
>> -        }
>> +        existing = dns_data_find(uuid, &dns_cache_);
>> +        update_cache_with_dns_rec(sbrec_dns, existing, uuid,
>> +                                  &dns_cache_);
>>      }
>>
>> -    HMAP_FOR_EACH_SAFE (dns_data, hmap_node, &dns_cache_) {
>> -        if (dns_data->delete) {
>> -            hmap_remove(&dns_cache_, &dns_data->hmap_node);
>> -            dns_data_destroy(dns_data);
>> +    CMAP_FOR_EACH (existing, cmap_node, &dns_cache_) {
>> +        if (existing->delete) {
>> +            cmap_remove(&dns_cache_, &existing->cmap_node,
>> +                        uuid_hash(&existing->uuid));
>> +            ovsrcu_postpone(dns_data_destroy, existing);
>>          }
>>      }
>> -    ovs_mutex_unlock(&dns_cache_mutex);
>>  }
>>
>>  void
>>  ovn_dns_update_cache(const struct sbrec_dns_table *dns_table)
>>  {
>> -    ovs_mutex_lock(&dns_cache_mutex);
>> -
>>      const struct sbrec_dns *sbrec_dns;
>> +    struct dns_data *existing;
>> +
>>      SBREC_DNS_TABLE_FOR_EACH_TRACKED (sbrec_dns, dns_table) {
>>          const struct uuid *uuid = &sbrec_dns->header_.uuid;
>> -        struct dns_data *dns_data = dns_data_find(uuid);
>>
>> -        if (sbrec_dns_is_deleted(sbrec_dns) && dns_data) {
>> -            hmap_remove(&dns_cache_, &dns_data->hmap_node);
>> -            dns_data_destroy(dns_data);
>> +        existing = dns_data_find(uuid, &dns_cache_);
>> +        if (sbrec_dns_is_deleted(sbrec_dns) && existing) {
>> +            cmap_remove(&dns_cache_, &existing->cmap_node,
>> +                        uuid_hash(&existing->uuid));
>> +            ovsrcu_postpone(dns_data_destroy, existing);
>>          } else {
>> -            update_cache_with_dns_rec(sbrec_dns, dns_data, uuid, 
>> &dns_cache_);
>> +            update_cache_with_dns_rec(sbrec_dns, existing, uuid,
>> +                                      &dns_cache_);
>>          }
>>      }
>> -
>> -    ovs_mutex_unlock(&dns_cache_mutex);
>>  }
>>
>>  const char *
>>  ovn_dns_lookup(const char *query_name, uint64_t dp_key, bool *ovn_owned)
>>  {
>> -    ovs_mutex_lock(&dns_cache_mutex);
>> +    const char *answer_data = NULL;
>> +    struct dns_data *dns_data;
>>
>>      *ovn_owned = false;
>> -    struct dns_data *dns_data;
>> -    const char *answer_data = NULL;
>> -    HMAP_FOR_EACH (dns_data, hmap_node, &dns_cache_) {
>> +
>> +    CMAP_FOR_EACH (dns_data, cmap_node, &dns_cache_) {
>>          for (size_t i = 0; i < dns_data->n_dps; i++) {
>>              if (dns_data->dps[i] == dp_key) {
>>                  /* DNS records in SBDB are stored in lowercase. Convert to
>> @@ -167,8 +141,6 @@ ovn_dns_lookup(const char *query_name, uint64_t dp_key, 
>> bool *ovn_owned)
>>          }
>>      }
>>
>> -    ovs_mutex_unlock(&dns_cache_mutex);
>> -
>>      return answer_data;
>>  }
>>
>> @@ -176,40 +148,35 @@ ovn_dns_lookup(const char *query_name, uint64_t 
>> dp_key, bool *ovn_owned)
>>  /* Static functions. */
>>  static void
>>  update_cache_with_dns_rec(const struct sbrec_dns *sbrec_dns,
>> -                          struct dns_data *dns_data,
>> +                          struct dns_data *existing,
>>                            const struct uuid *uuid,
>> -                          struct hmap *dns_cache)
>> +                          struct cmap *dns_cache)
>>  {
>> -    if (!dns_data) {
>> -        dns_data = dns_data_alloc(*uuid);
>> -        hmap_insert(dns_cache, &dns_data->hmap_node, uuid_hash(uuid));
>> -    } else {
>> -        free(dns_data->dps);
>> -    }
>> -
>> -    if (!smap_equal(&dns_data->records, &sbrec_dns->records)) {
>> -        smap_destroy(&dns_data->records);
>> -        smap_clone(&dns_data->records, &sbrec_dns->records);
>> -    }
>> -
>> -    if (!smap_equal(&dns_data->options, &sbrec_dns->options)) {
>> -        smap_destroy(&dns_data->options);
>> -        smap_clone(&dns_data->options, &sbrec_dns->options);
>> -    }
>> +    struct dns_data *dns_data = dns_data_alloc(*uuid);
>> +    smap_clone(&dns_data->records, &sbrec_dns->records);
>> +    smap_clone(&dns_data->options, &sbrec_dns->options);
>>
>>      dns_data->n_dps = sbrec_dns->n_datapaths;
>>      dns_data->dps = xcalloc(dns_data->n_dps, sizeof(uint64_t));
>>      for (size_t i = 0; i < sbrec_dns->n_datapaths; i++) {
>>          dns_data->dps[i] = sbrec_dns->datapaths[i]->tunnel_key;
>>      }
>> +
>> +    if (!existing) {
>> +        cmap_insert(dns_cache, &dns_data->cmap_node, uuid_hash(uuid));
>> +    } else {
>> +        cmap_replace(dns_cache, &existing->cmap_node, &dns_data->cmap_node,
>> +                     uuid_hash(uuid));
>> +        ovsrcu_postpone(dns_data_destroy, existing);
>> +    }
>>  }
>>
>>  static struct dns_data *
>> -dns_data_find(const struct uuid *uuid)
>> +dns_data_find(const struct uuid *uuid, const struct cmap *dns_cache)
>>  {
>>      struct dns_data *dns_data;
>>      size_t hash = uuid_hash(uuid);
>> -    HMAP_FOR_EACH_WITH_HASH (dns_data, hmap_node, hash, &dns_cache_) {
>> +    CMAP_FOR_EACH_WITH_HASH (dns_data, cmap_node, hash, dns_cache) {
>>          if (uuid_equals(&dns_data->uuid, uuid)) {
>>              return dns_data;
>>          }
>> @@ -240,3 +207,12 @@ dns_data_destroy(struct dns_data *dns_data)
>>      free(dns_data->dps);
>>      free(dns_data);
>>  }
>> +
>> +static void
>> +destroy_dns_cache(struct cmap *dns_cache)
>> +{
>> +    struct dns_data *dns_data;
>> +    CMAP_FOR_EACH (dns_data, cmap_node, dns_cache) {
>> +        ovsrcu_postpone(dns_data_destroy, dns_data);
>> +    }
>> +}
>> diff --git a/controller/pinctrl.c b/controller/pinctrl.c
>> index e1bae61515..eaa0985021 100644
>> --- a/controller/pinctrl.c
>> +++ b/controller/pinctrl.c
>> @@ -3902,6 +3902,8 @@ pinctrl_handler(void *arg_)
>>      static long long int send_prefixd_time = LLONG_MAX;
>>
>>      while (!latch_is_set(&pctrl->pinctrl_thread_exit)) {
>> +        ovsrcu_quiesce_end();
>> +
>>          long long int bfd_time = LLONG_MAX;
>>          bool lock_failed = false;
>>
>> @@ -3975,6 +3977,8 @@ pinctrl_handler(void *arg_)
>>
>>              latch_wait(&pctrl->pinctrl_thread_exit);
>>          }
>> +
>> +        ovsrcu_quiesce_start();
>>          poll_block();
>>      }
>>
>> --
>> 2.47.1
>>
>
> Looks good to me, thanks.
>
> Acked-by: Ales Musil <[email protected]>


Thanks Ales for the review.  I applied this patch series to main and
also backported to branch-24.09.
I also had to backport the below 2 prereq patches:

817d4e53e8 ("ovn-controller: Add a separate dns cache module and I-P
for SB DNS.")
1270d71762 ("northd: Use the same UUID for SB representation of DNS.").

Numan
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to