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 maintaining 2 hmaps for dns cache and acquiring the
lock in the main thread only to swap the active cache to the
latest one.

Signed-off-by: Numan Siddique <[email protected]>
---
 controller/ovn-dns.c | 94 +++++++++++++++++++++++---------------------
 1 file changed, 50 insertions(+), 44 deletions(-)

diff --git a/controller/ovn-dns.c b/controller/ovn-dns.c
index 026d9bc64..cf384b043 100644
--- a/controller/ovn-dns.c
+++ b/controller/ovn-dns.c
@@ -38,7 +38,9 @@ struct dns_data {
 };
 
 /* shash of 'struct dns_data'. */
-static struct hmap dns_cache_ = HMAP_INITIALIZER(&dns_cache_);
+static struct hmap dns_caches[2];
+static struct hmap *active_dns_cache_;
+static uint8_t active_dns_cache_idx;
 
 /* Mutex to protect dns_cache_. */
 static struct ovs_mutex dns_cache_mutex = OVS_MUTEX_INITIALIZER;
@@ -47,58 +49,49 @@ 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);
+static struct dns_data *dns_data_find(const struct uuid *uuid,
+                                      const struct hmap *);
 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 hmap *dns_cache);
 
 void
 ovn_dns_cache_init(void)
 {
+    hmap_init(&dns_caches[0]);
+    hmap_init(&dns_caches[1]);
+    active_dns_cache_idx = 0;
+    active_dns_cache_ = &dns_caches[0];
 }
 
 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_);
+    destroy_dns_cache(&dns_caches[0]);
+    destroy_dns_cache(&dns_caches[1]);
+    hmap_destroy(&dns_caches[0]);
+    hmap_destroy(&dns_caches[1]);
+    active_dns_cache_ = NULL;
     ovs_mutex_unlock(&dns_cache_mutex);
 }
 
 void
 ovn_dns_sync_cache(const struct sbrec_dns_table *dns_table)
 {
-    ovs_mutex_lock(&dns_cache_mutex);
+    const struct sbrec_dns *sbrec_dns;
     struct dns_data *dns_data;
-    HMAP_FOR_EACH (dns_data, hmap_node, &dns_cache_) {
-        dns_data->delete = true;
-    }
 
-    const struct sbrec_dns *sbrec_dns;
+    uint8_t next_cache_idx = (active_dns_cache_idx + 1) % 2;
+    struct hmap *dns_cache = &dns_caches[next_cache_idx];
+    ovs_assert(dns_cache != active_dns_cache_);
+
     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 = dns_data_alloc(*uuid);
+        hmap_insert(dns_cache, &dns_data->hmap_node, uuid_hash(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));
@@ -107,30 +100,33 @@ ovn_dns_sync_cache(const struct sbrec_dns_table 
*dns_table)
         }
     }
 
-    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);
-        }
-    }
+    struct hmap *prev_active_cache = active_dns_cache_;
+
+    ovs_mutex_lock(&dns_cache_mutex);
+    active_dns_cache_ = dns_cache;
+    active_dns_cache_idx = next_cache_idx;
     ovs_mutex_unlock(&dns_cache_mutex);
+
+    /* Destroy the previous active dns cache. */
+    destroy_dns_cache(prev_active_cache);
 }
 
 void
 ovn_dns_update_cache(const struct sbrec_dns_table *dns_table)
 {
     ovs_mutex_lock(&dns_cache_mutex);
-
+    ovs_assert(active_dns_cache_ != NULL);
     const struct sbrec_dns *sbrec_dns;
     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);
+        struct dns_data *dns_data = dns_data_find(uuid, active_dns_cache_);
 
         if (sbrec_dns_is_deleted(sbrec_dns) && dns_data) {
-            hmap_remove(&dns_cache_, &dns_data->hmap_node);
+            hmap_remove(active_dns_cache_, &dns_data->hmap_node);
             dns_data_destroy(dns_data);
         } else {
-            update_cache_with_dns_rec(sbrec_dns, dns_data, uuid, &dns_cache_);
+            update_cache_with_dns_rec(sbrec_dns, dns_data, uuid,
+                                      active_dns_cache_);
         }
     }
 
@@ -142,10 +138,11 @@ ovn_dns_lookup(const char *query_name, uint64_t dp_key, 
bool *ovn_owned)
 {
     ovs_mutex_lock(&dns_cache_mutex);
 
+    ovs_assert(active_dns_cache_ != NULL);
     *ovn_owned = false;
     struct dns_data *dns_data;
     const char *answer_data = NULL;
-    HMAP_FOR_EACH (dns_data, hmap_node, &dns_cache_) {
+    HMAP_FOR_EACH (dns_data, hmap_node, active_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
@@ -205,11 +202,11 @@ update_cache_with_dns_rec(const struct sbrec_dns 
*sbrec_dns,
 }
 
 static struct dns_data *
-dns_data_find(const struct uuid *uuid)
+dns_data_find(const struct uuid *uuid, const struct hmap *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_) {
+    HMAP_FOR_EACH_WITH_HASH (dns_data, hmap_node, hash, dns_cache) {
         if (uuid_equals(&dns_data->uuid, uuid)) {
             return dns_data;
         }
@@ -240,3 +237,12 @@ dns_data_destroy(struct dns_data *dns_data)
     free(dns_data->dps);
     free(dns_data);
 }
+
+static void
+destroy_dns_cache(struct hmap *dns_cache)
+{
+    struct dns_data *dns_data;
+    HMAP_FOR_EACH_POP (dns_data, hmap_node, dns_cache) {
+        dns_data_destroy(dns_data);
+    }
+}
-- 
2.39.3 (Apple Git-146)

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

Reply via email to