]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
rec: Add support for wiping the aggressive cache
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 5 Jan 2021 16:19:50 +0000 (17:19 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 22 Feb 2021 17:43:06 +0000 (18:43 +0100)
pdns/dnsname.hh
pdns/rec_channel_rec.cc
pdns/recursordist/aggressive_nsec.cc
pdns/recursordist/aggressive_nsec.hh

index 10a4f0d2b1b5ee6431675cf32b571dd6e4934d33..76981f513a870c26e70933d268a8eadcebc0cea6 100644 (file)
@@ -326,19 +326,22 @@ struct SuffixMatchTree
     }
   }
 
-  void remove(const DNSName &name) const
+  void remove(const DNSName &name, bool subtree=false) const
   {
     auto labels = name.getRawLabels();
-    remove(labels);
+    remove(labels, subtree);
   }
 
   /* Removes the node at `labels`, also make sure that no empty
    * children will be left behind in memory
    */
-  void remove(std::vector<std::string>& labels) const
+  void remove(std::vector<std::string>& labels, bool subtree = false) const
   {
     if (labels.empty()) { // this allows removal of the root
       endNode = false;
+      if (subtree) {
+        children.clear();
+      }
       return;
     }
 
@@ -355,6 +358,10 @@ struct SuffixMatchTree
       // The child is no longer an endnode
       child->endNode = false;
 
+      if (subtree) {
+        child->children.clear();
+      }
+
       // If the child has no further children, just remove it from the set.
       if (child->children.empty()) {
         children.erase(child);
index e13a421062fcf61406aaf4a6d6105dfda293d29c..ca92008537870bc9095899c7a320c2cd2110a996 100644 (file)
@@ -442,6 +442,9 @@ static string doWipeCache(T begin, T end, uint16_t qtype)
       count += g_recCache->doWipeCache(wipe.first, wipe.second, qtype);
       pcount += broadcastAccFunction<uint64_t>([=]{ return pleaseWipePacketCache(wipe.first, wipe.second, qtype);});
       countNeg += g_negCache->wipe(wipe.first, wipe.second);
+      if (g_aggressiveNSECCache) {
+        g_aggressiveNSECCache->removeZoneInfo(wipe.first, wipe.second);
+      }
     }
     catch (const std::exception& e) {
       g_log<<Logger::Warning<<", failed: "<<e.what()<<endl;
@@ -550,6 +553,9 @@ static string doAddNTA(T begin, T end)
     g_recCache->doWipeCache(who, true, 0xffff);
     broadcastAccFunction<uint64_t>([=]{return pleaseWipePacketCache(who, true, 0xffff);});
     g_negCache->wipe(who, true);
+    if (g_aggressiveNSECCache) {
+      g_aggressiveNSECCache->removeZoneInfo(who, true);
+    }
   }
   catch (std::exception& e) {
     g_log<<Logger::Warning<<", failed: "<<e.what()<<endl;
@@ -604,6 +610,9 @@ static string doClearNTA(T begin, T end)
       g_recCache->doWipeCache(entry, true, 0xffff);
       broadcastAccFunction<uint64_t>([=]{return pleaseWipePacketCache(entry, true, 0xffff);});
       g_negCache->wipe(entry, true);
+      if (g_aggressiveNSECCache) {
+        g_aggressiveNSECCache->removeZoneInfo(entry, true);
+      }
       if (!first) {
         first = false;
         removed += ",";
@@ -667,6 +676,9 @@ static string doAddTA(T begin, T end)
     g_recCache->doWipeCache(who, true, 0xffff);
     broadcastAccFunction<uint64_t>([=]{return pleaseWipePacketCache(who, true, 0xffff);});
     g_negCache->wipe(who, true);
+    if (g_aggressiveNSECCache) {
+      g_aggressiveNSECCache->removeZoneInfo(who, true);
+    }
     g_log<<Logger::Warning<<endl;
     return "Added Trust Anchor for " + who.toStringRootDot() + " with data " + what + "\n";
   }
@@ -714,6 +726,9 @@ static string doClearTA(T begin, T end)
       g_recCache->doWipeCache(entry, true, 0xffff);
       broadcastAccFunction<uint64_t>([=]{return pleaseWipePacketCache(entry, true, 0xffff);});
       g_negCache->wipe(entry, true);
+      if (g_aggressiveNSECCache) {
+        g_aggressiveNSECCache->removeZoneInfo(entry, true);
+      }
       if (!first) {
         first = false;
         removed += ",";
index 014bcb955bd653fb18b47d2bd59c0e5f6da62d0b..d6bbef640121081aef83c1a2c68932a202719437 100644 (file)
@@ -70,6 +70,36 @@ std::shared_ptr<AggressiveNSECCache::ZoneEntry> AggressiveNSECCache::getZone(con
   }
 }
 
+void AggressiveNSECCache::updateEntriesCount()
+{
+  /* need to be called while holding a write lock */
+  uint64_t counter = 0;
+  d_zones.visit([&counter](const SuffixMatchTree<std::shared_ptr<ZoneEntry>>& node) {
+    counter += node.d_value->d_entries.size();
+  });
+  d_entriesCount = counter;
+}
+
+void AggressiveNSECCache::removeZoneInfo(const DNSName& zone, bool subzones)
+{
+  WriteLock rl(d_lock);
+  auto got = d_zones.lookup(zone);
+  if (!got || !*got || (*got)->d_zone != zone) {
+    return;
+  }
+
+  if (subzones) {
+    d_zones.remove(zone, true);
+    updateEntriesCount();
+  }
+  else {
+    std::lock_guard<std::mutex> lock((*got)->d_lock);
+    auto removed = (*got)->d_entries.size();
+    d_zones.remove(zone, false);
+    d_entriesCount -= removed;
+  }
+}
+
 static bool isMinimallyCoveringNSEC(const DNSName& owner, const std::shared_ptr<NSECRecordContent>& nsec)
 {
   /* this test only covers Cloudflare's ones (https://blog.cloudflare.com/black-lies/),
@@ -219,8 +249,9 @@ bool AggressiveNSECCache::getNSECBefore(time_t now, std::shared_ptr<AggressiveNS
   }
 
   if (it->d_ttd <= now) {
-    idx.erase(it);
-    --d_entriesCount;
+    moveCacheItemToFront<ZoneEntry::SequencedTag>(zoneEntry->d_entries, it);
+    //idx.erase(it);
+    //--d_entriesCount;
     return false;
   }
 
@@ -245,14 +276,15 @@ bool AggressiveNSECCache::getNSEC3(time_t now, std::shared_ptr<AggressiveNSECCac
       continue;
     }
 
+    auto firstIndexIterator = zoneEntry->d_entries.project<ZoneEntry::OrderedTag>(it);
     if (it->d_ttd <= now) {
-      idx.erase(it);
-      --d_entriesCount;
+      moveCacheItemToBack<ZoneEntry::SequencedTag>(zoneEntry->d_entries, firstIndexIterator);
+      //idx.erase(it);
+      //--d_entriesCount;
       return false;
     }
 
     entry = *it;
-    auto firstIndexIterator = zoneEntry->d_entries.project<ZoneEntry::OrderedTag>(it);
     moveCacheItemToBack<ZoneEntry::SequencedTag>(zoneEntry->d_entries, firstIndexIterator);
     return true;
   }
index 659e3d9414bf7fde24f3811f45760c1ebc014489..132a53a4b342ac7eeb9c9483800f53aafbe64dfb 100644 (file)
@@ -41,7 +41,7 @@ public:
   void insertNSEC(const DNSName& zone, const DNSName& owner, const DNSRecord& record, const std::vector<std::shared_ptr<RRSIGRecordContent>>& signatures, bool nsec3);
   bool getDenial(time_t, const DNSName& name, const QType& type, std::vector<DNSRecord>& ret, int& res, const ComboAddress& who, const boost::optional<std::string>& routingTag, bool doDNSSEC);
 
-  //void removeZoneInfo(const DNSName& zone);
+  void removeZoneInfo(const DNSName& zone, bool subzones);
 
   uint64_t getEntriesCount() const
   {
@@ -124,13 +124,16 @@ private:
   bool synthesizeFromNSEC3Wildcard(time_t now, const DNSName& name, const QType& type, std::vector<DNSRecord>& ret, int& res, bool doDNSSEC, ZoneEntry::CacheEntry& nextCloser, const DNSName& wildcardName);
   bool synthesizeFromNSECWildcard(time_t now, const DNSName& name, const QType& type, std::vector<DNSRecord>& ret, int& res, bool doDNSSEC, ZoneEntry::CacheEntry& nsec, const DNSName& wildcardName);
 
+  /* slowly updates d_entriesCount */
+  void updateEntriesCount();
+
   SuffixMatchTree<std::shared_ptr<ZoneEntry>> d_zones;
   ReadWriteLock d_lock;
-  std::atomic<uint64_t> d_entriesCount{0};
   std::atomic<uint64_t> d_nsecHits{0};
   std::atomic<uint64_t> d_nsec3Hits{0};
   std::atomic<uint64_t> d_nsecWildcardHits{0};
   std::atomic<uint64_t> d_nsec3WildcardHits{0};
+  std::atomic<uint64_t> d_entriesCount{0};
 };