]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
rec: Rename the ECS cache index and add a comment on how it works
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 27 Jun 2017 20:32:50 +0000 (22:32 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 27 Jun 2017 20:32:50 +0000 (22:32 +0200)
pdns/recursor_cache.cc
pdns/recursor_cache.hh

index 486d03ec994af3b2fc2ef3ed5eca1675bcdfbea7..e78c986394e51affd40ab21e63ea2f1d22998e17 100644 (file)
@@ -76,14 +76,14 @@ int32_t MemRecursorCache::handleHit(cache_t::iterator entry, const DNSName& qnam
   return ttd;
 }
 
-MemRecursorCache::cache_t::const_iterator MemRecursorCache::getEntryUsingIndex(time_t now, const DNSName &qname, uint16_t qtype, bool requireAuth, const ComboAddress& who)
+MemRecursorCache::cache_t::const_iterator MemRecursorCache::getEntryUsingECSIndex(time_t now, const DNSName &qname, uint16_t qtype, bool requireAuth, const ComboAddress& who)
 {
-  auto indexKey = tie(qname, qtype);
-  auto index = d_index.find(indexKey);
-  if (index != d_index.end() && !index->isEmpty()) {
+  auto ecsIndexKey = tie(qname, qtype);
+  auto ecsIndex = d_ecsIndex.find(ecsIndexKey);
+  if (ecsIndex != d_ecsIndex.end() && !ecsIndex->isEmpty()) {
     /* we have netmask-specific entries, let's see if we match one */
     while (true) {
-      const Netmask best = index->lookupBestMatch(who);
+      const Netmask best = ecsIndex->lookupBestMatch(who);
       if (best.empty()) {
         /* we have nothing more specific for you */
         break;
@@ -92,10 +92,10 @@ MemRecursorCache::cache_t::const_iterator MemRecursorCache::getEntryUsingIndex(t
       auto key = boost::make_tuple(qname, qtype, best);
       auto entry = d_cache.find(key);
       if (entry == d_cache.end()) {
-        /* index is not up-to-date */
-        index->removeNetmask(best);
-        if (index->isEmpty()) {
-          d_index.erase(index);
+        /* ecsIndex is not up-to-date */
+        ecsIndex->removeNetmask(best);
+        if (ecsIndex->isEmpty()) {
+          d_ecsIndex.erase(ecsIndex);
           break;
         }
         continue;
@@ -109,9 +109,9 @@ MemRecursorCache::cache_t::const_iterator MemRecursorCache::getEntryUsingIndex(t
       else {
         /* this netmask-specific entry has expired */
         moveCacheItemToFront(d_cache, entry);
-        index->removeNetmask(best);
-        if (index->isEmpty()) {
-          d_index.erase(index);
+        ecsIndex->removeNetmask(best);
+        if (ecsIndex->isEmpty()) {
+          d_ecsIndex.erase(ecsIndex);
           break;
         }
       }
@@ -173,15 +173,15 @@ int32_t MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt,
   const uint16_t qtype = qt.getCode();
   /* If we don't have any netmask-specific entries at all, let's just skip this
      to be able to use the nice d_cachecache hack. */
-  if (qtype != QType::ANY && !d_index.empty()) {
+  if (qtype != QType::ANY && !d_ecsIndex.empty()) {
     if (qtype == QType::ADDR) {
       int32_t ret = -1;
 
-      auto entryA = getEntryUsingIndex(now, qname, QType::A, requireAuth, who);
+      auto entryA = getEntryUsingECSIndex(now, qname, QType::A, requireAuth, who);
       if (entryA != d_cache.end()) {
         ret = handleHit(entryA, qname, who, res, signatures, authorityRecs, variable, state, wasAuth);
       }
-      auto entryAAAA = getEntryUsingIndex(now, qname, QType::AAAA, requireAuth, who);
+      auto entryAAAA = getEntryUsingECSIndex(now, qname, QType::AAAA, requireAuth, who);
       if (entryAAAA != d_cache.end()) {
         int32_t ttdAAAA = handleHit(entryA, qname, who, res, signatures, authorityRecs, variable, state, wasAuth);
         if (ret > 0) {
@@ -193,7 +193,7 @@ int32_t MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt,
       return ret > 0 ? static_cast<int32_t>(ret-now) : ret;
     }
     else {
-      auto entry = getEntryUsingIndex(now, qname, qtype, requireAuth, who);
+      auto entry = getEntryUsingECSIndex(now, qname, qtype, requireAuth, who);
       if (entry != d_cache.end()) {
         return static_cast<int32_t>(handleHit(entry, qname, who, res, signatures, authorityRecs, variable, state, wasAuth) - now);
       }
@@ -265,14 +265,14 @@ void MemRecursorCache::replace(time_t now, const DNSName &qname, const QType& qt
     stored = d_cache.insert(CacheEntry(key, CacheEntry::records_t(), auth)).first;
     isNew = true;
 
-    /* don't bother building an index if we don't have any netmask-specific entries */
+    /* don't bother building an ecsIndex if we don't have any netmask-specific entries */
     if (ednsmask && !ednsmask->empty()) {
-      auto indexKey = boost::make_tuple(qname, qt.getCode());
-      auto index = d_index.find(indexKey);
-      if (index == d_index.end()) {
-        index = d_index.insert(IndexEntry(qname, qt.getCode())).first;
+      auto ecsIndexKey = boost::make_tuple(qname, qt.getCode());
+      auto ecsIndex = d_ecsIndex.find(ecsIndexKey);
+      if (ecsIndex == d_ecsIndex.end()) {
+        ecsIndex = d_ecsIndex.insert(ECSIndexEntry(qname, qt.getCode())).first;
       }
-      index->addMask(*ednsmask);
+      ecsIndex->addMask(*ednsmask);
     }
   }
 
@@ -335,21 +335,21 @@ int MemRecursorCache::doWipeCache(const DNSName& name, bool sub, uint16_t qtype)
   pair<cache_t::iterator, cache_t::iterator> range;
 
   if(!sub) {
-    pair<index_t::iterator, index_t::iterator> indexRange;
+    pair<ecsIndex_t::iterator, ecsIndex_t::iterator> ecsIndexRange;
     if(qtype==0xffff) {
       range = d_cache.equal_range(tie(name));
-      indexRange = d_index.equal_range(tie(name));
+      ecsIndexRange = d_ecsIndex.equal_range(tie(name));
     }
     else {
       range=d_cache.equal_range(tie(name, qtype));
-      indexRange = d_index.equal_range(tie(name, qtype));
+      ecsIndexRange = d_ecsIndex.equal_range(tie(name, qtype));
     }
     for(cache_t::const_iterator i=range.first; i != range.second; ) {
       count++;
       d_cache.erase(i++);
     }
-    for(auto i = indexRange.first; i != indexRange.second; ) {
-      d_index.erase(i++);
+    for(auto i = ecsIndexRange.first; i != ecsIndexRange.second; ) {
+      d_ecsIndex.erase(i++);
     }
   }
   else {
@@ -363,11 +363,11 @@ int MemRecursorCache::doWipeCache(const DNSName& name, bool sub, uint16_t qtype)
       else 
        iter++;
     }
-    for(auto iter = d_index.lower_bound(tie(name)); iter != d_index.end(); ) {
+    for(auto iter = d_ecsIndex.lower_bound(tie(name)); iter != d_ecsIndex.end(); ) {
       if(!iter->d_qname.isPartOf(name))
        break;
       if(iter->d_qtype == qtype || qtype == 0xffff) {
-       d_index.erase(iter++);
+       d_ecsIndex.erase(iter++);
       }
       else {
        iter++;
@@ -409,8 +409,8 @@ bool MemRecursorCache::updateValidationStatus(time_t now, const DNSName &qname,
 {
   bool updated = false;
   uint16_t qtype = qt.getCode();
-  if (qtype != QType::ANY && qtype != QType::ADDR && !d_index.empty()) {
-    auto entry = getEntryUsingIndex(now, qname, qtype, requireAuth, who);
+  if (qtype != QType::ANY && qtype != QType::ADDR && !d_ecsIndex.empty()) {
+    auto entry = getEntryUsingECSIndex(now, qname, qtype, requireAuth, who);
     if (entry == d_cache.end()) {
       return false;
     }
index cd79a75a045ca6c23d3b3b4f3b1be84a7d993a6d..831a86f619467d8802e10be89bc851ea9bab125a 100644 (file)
@@ -94,10 +94,20 @@ private:
     bool d_auth;
   };
 
-  class IndexEntry
+  /* The ECS Index (d_ecsIndex) keeps track of whether there is any ECS-specific
+     entry for a given (qname,qtype) entry in the cache (d_cache), and if so
+     provides a NetmaskTree of those ECS entries.
+     This allows figuring out quickly if we should look for an entry
+     specific to the requestor IP, and if so which entry is the most
+     specific one.
+     Keeping the entries in the regular cache is currently necessary
+     because of the way we manage expired entries (moving them to the
+     front of the expunge queue to be deleted at a regular interval).
+  */
+  class ECSIndexEntry
   {
   public:
-    IndexEntry(const DNSName& qname, uint16_t qtype): d_qname(qname), d_qtype(qtype)
+    ECSIndexEntry(const DNSName& qname, uint16_t qtype): d_qname(qname), d_qtype(qtype)
     {
     }
 
@@ -149,20 +159,20 @@ private:
                >
   > cache_t;
   typedef multi_index_container<
-    IndexEntry,
+    ECSIndexEntry,
     indexed_by <
       ordered_unique <
         composite_key<
-          IndexEntry,
-          member<IndexEntry,DNSName,&IndexEntry::d_qname>,
-          member<IndexEntry,uint16_t,&IndexEntry::d_qtype>
+          ECSIndexEntry,
+          member<ECSIndexEntry,DNSName,&ECSIndexEntry::d_qname>,
+          member<ECSIndexEntry,uint16_t,&ECSIndexEntry::d_qtype>
         >
       >
     >
-  > index_t;
+  > ecsIndex_t;
 
   cache_t d_cache;
-  index_t d_index;
+  ecsIndex_t d_ecsIndex;
   pair<cache_t::iterator, cache_t::iterator> d_cachecache;
   DNSName d_cachedqname;
   bool d_cachecachevalid;
@@ -170,7 +180,7 @@ private:
   bool attemptToRefreshNSTTL(const QType& qt, const vector<DNSRecord>& content, const CacheEntry& stored);
   bool entryMatches(cache_t::const_iterator& entry, uint16_t qt, bool requireAuth, const ComboAddress& who);
   std::pair<cache_t::const_iterator, cache_t::const_iterator> getEntries(const DNSName &qname, const QType& qt);
-  cache_t::const_iterator getEntryUsingIndex(time_t now, const DNSName &qname, uint16_t qtype, bool requireAuth, const ComboAddress& who);
+  cache_t::const_iterator getEntryUsingECSIndex(time_t now, const DNSName &qname, uint16_t qtype, bool requireAuth, const ComboAddress& who);
   int32_t handleHit(cache_t::iterator entry, const DNSName& qname, const ComboAddress& who, vector<DNSRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, vState* state, bool* wasAuth);
 
 public:
@@ -181,11 +191,11 @@ public:
     }
 
     auto key = tie(entry.d_qname, entry.d_qtype);
-    auto indexEntry = d_index.find(key);
-    if (indexEntry != d_index.end()) {
-      indexEntry->removeNetmask(entry.d_netmask);
-      if (indexEntry->isEmpty()) {
-        d_index.erase(indexEntry);
+    auto ecsIndexEntry = d_ecsIndex.find(key);
+    if (ecsIndexEntry != d_ecsIndex.end()) {
+      ecsIndexEntry->removeNetmask(entry.d_netmask);
+      if (ecsIndexEntry->isEmpty()) {
+        d_ecsIndex.erase(ecsIndexEntry);
       }
     }
   }