]> granicus.if.org Git - pdns/commitdiff
improve negative caching for SOA lookups
authorKees Monshouwer <mind04@monshouwer.org>
Fri, 18 Sep 2015 08:12:15 +0000 (10:12 +0200)
committerPieter Lexis <pieter.lexis@powerdns.com>
Tue, 15 Dec 2015 08:39:37 +0000 (09:39 +0100)
pdns/dnsbackend.cc
pdns/dnsbackend.hh
pdns/ueberbackend.cc

index 3e96807a05ffe4dd6e34eb810dd9b98051745c7d..d4e78d168e0d6a8ef5c1d08b953df4cc1db24711 100644 (file)
@@ -33,7 +33,7 @@
 #include "dnspacket.hh"
 #include "dns.hh"
 
-bool DNSBackend::getAuth(DNSPacket *p, SOAData *sd, const DNSName &target, const int best_match_len)
+bool DNSBackend::getAuth(DNSPacket *p, SOAData *sd, const DNSName &target, const int best_match_len, map<DNSName,int>& negCacheMap)
 {
   bool found=false;
   DNSName subdomain(target);
@@ -41,11 +41,15 @@ bool DNSBackend::getAuth(DNSPacket *p, SOAData *sd, const DNSName &target, const
     if( best_match_len >= (int)subdomain.toString().length() )
       break;
 
-    if( this->getSOA( subdomain, *sd, p ) ) {
+    map<DNSName,int>::iterator it = negCacheMap.find(subdomain);
+    bool negCached = ( it != negCacheMap.end() && it->second == 1 );
+
+    if(! negCached && this->getSOA( subdomain, *sd, p ) ) {
       sd->qname = subdomain;
 
       if(p->qtype.getCode() == QType::DS && subdomain==target) {
         // Found authoritative zone but look for parent zone with 'DS' record.
+        negCacheMap[subdomain]=2;
         found=true;
       } else
         return true;
index f940661fd955d2142b179ac48d8945eefa112d62..1e1ff5cc3f8152e5e2aa4c5ef053c8481ebcb149 100644 (file)
@@ -168,7 +168,7 @@ public:
   virtual void getAllDomains(vector<DomainInfo> *domains, bool include_disabled=false) { }
 
   /** Determines if we are authoritative for a zone, and at what level */
-  virtual bool getAuth(DNSPacket *p, SOAData *sd, const DNSName &target, const int best_match_len);
+  virtual bool getAuth(DNSPacket *p, SOAData *sd, const DNSName &target, const int best_match_len, map<DNSName,int>& negCacheMap);
 
   struct KeyData {
     std::string content;
index b665184a666507b231f28c9308ec402f6e117e00..1d10c456531a04b915a08f1d2302079a7c0ef119 100644 (file)
@@ -251,6 +251,7 @@ bool UeberBackend::getAuth(DNSPacket *p, SOAData *sd, const DNSName &target)
 {
   int best_match_len = -1;
   bool from_cache = false;  // Was this result fetched from the cache?
+  map<DNSName,int> negCacheMap;
 
   // If not special case of caching explicitly disabled (sd->db = -1), first
   // find the best match from the cache. If DS then we need to find parent so
@@ -281,14 +282,17 @@ bool UeberBackend::getAuth(DNSPacket *p, SOAData *sd, const DNSName &target)
           best_match_len = sd->qname.countLabels();
 
           break;
-        }
+        } else if (cstat==0) {
+          negCacheMap[subdomain]=1;
+        } else
+          negCacheMap[subdomain]=0;
         loops++;
       }
       while( subdomain.chopOff() );   // 'www.powerdns.org' -> 'powerdns.org' -> 'org' -> ''
   }
 
-  for(vector<DNSBackend *>::const_iterator i=backends.begin(); i!=backends.end();++i)
-    if((*i)->getAuth(p, sd, target, best_match_len)) {
+  for(vector<DNSBackend *>::const_iterator i=backends.begin(); i!=backends.end();++i) {
+    if((*i)->getAuth(p, sd, target, best_match_len, negCacheMap)) {
         best_match_len = sd->qname.countLabels(); // FIXME400
         from_cache = false;
 
@@ -297,6 +301,23 @@ bool UeberBackend::getAuth(DNSPacket *p, SOAData *sd, const DNSName &target)
         if( best_match_len == (int)target.countLabels() )
             goto auth_found;
     }
+  }
+
+  if( sd->db != (DNSBackend *)-1 && d_negcache_ttl) {
+    DNSName shorter(target);
+
+    d_question.qtype=QType::SOA;
+    d_question.zoneId=-1;
+    while((int)shorter.countLabels() > best_match_len ) {
+      map<DNSName,int>::iterator it = negCacheMap.find(shorter);
+      if (it == negCacheMap.end() || it->second == 0) {
+        d_question.qname=shorter;
+        addNegCache(d_question);
+      }
+      if (!shorter.chopOff())
+        break;
+    }
+  }
 
   if( best_match_len == -1 )
       return false;