]> 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)
committermind04 <mind04@monshouwer.org>
Thu, 1 Oct 2015 14:57:16 +0000 (16:57 +0200)
pdns/dnsbackend.cc
pdns/dnsbackend.hh
pdns/ueberbackend.cc
pdns/ueberbackend.hh

index 9615aaa08a59c9016cbd52f120a7d5a6b12c90c4..09e02e47dbba9a2ff565f8703c3a863607bdb200 100644 (file)
@@ -44,7 +44,7 @@ bool DNSBackend::getRemote(DNSPacket *p, struct sockaddr *sa, Utility::socklen_t
   return true;
 }
 
-bool DNSBackend::getAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId, const int best_match_len)
+bool DNSBackend::getAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId, const int best_match_len, map<string,int>& negCacheMap)
 {
   bool found=false;
   string subdomain(target);
@@ -52,13 +52,17 @@ bool DNSBackend::getAuth(DNSPacket *p, SOAData *sd, const string &target, int *z
     if( best_match_len >= (int)subdomain.length() )
       break;
 
-    if( this->getSOA( subdomain, *sd, p ) ) {
+    map<string,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(zoneId)
         *zoneId = sd->domain_id;
 
       if(p->qtype.getCode() == QType::DS && pdns_iequals(subdomain, target)) {
         // Found authoritative zone but look for parent zone with 'DS' record.
+        negCacheMap[subdomain]=2;
         found=true;
       } else
         return true;
index b4122b96e4bca16e76e12804a9dbf09c649b31f9..4a057be21ce35cedd147fb5ece59744d2acbd94a 100644 (file)
@@ -163,7 +163,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 string &target, int *zoneId, const int best_match_len);
+  virtual bool getAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId, const int best_match_len, map<string,int>& negCacheMap);
 
   struct KeyData {
     unsigned int id;
index 0c48f691611629994ffa083dda0c7063ec71da44..8ddfa981a5791391b4d5ae78b404134b68a9f407 100644 (file)
@@ -278,6 +278,7 @@ bool UeberBackend::getAuth(DNSPacket *p, SOAData *sd, const string &target, int
 {
   int best_match_len = -1;
   bool from_cache = false;  // Was this result fetched from the cache?
+  map<string,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
@@ -308,22 +309,42 @@ bool UeberBackend::getAuth(DNSPacket *p, SOAData *sd, const string &target, int
           best_match_len = sd->qname.length();
 
           break;
-        }
+        } else if (cstat==0) {
+          negCacheMap[subdomain]=1;
+        } else
+          negCacheMap[subdomain]=0;
         loops++;
       }
       while( chopOff( subdomain ) );   // 'www.powerdns.org' -> 'powerdns.org' -> 'org' -> ''
   }
 
-  for(vector<DNSBackend *>::const_iterator i=backends.begin(); i!=backends.end();++i)
-    if((*i)->getAuth(p, sd, target, zoneId, best_match_len)) {
+  for(vector<DNSBackend *>::const_iterator i=backends.begin(); i!=backends.end();++i) {
+    if((*i)->getAuth(p, sd, target, zoneId, best_match_len, negCacheMap)) {
         best_match_len = sd->qname.length();
         from_cache = false;
 
         // Shortcut for the case that we got a direct hit - no need to go
         // through the other backends then.
         if( best_match_len == (int)target.length() )
-            goto auth_found;
+          goto auth_found;
     }
+  }
+
+  if( sd->db != (DNSBackend *)-1 && d_cache_ttl) {
+    string shorter(target);
+
+    d_question.qtype=QType::SOA;
+    d_question.zoneId=-1;
+    while((int)shorter.length() > best_match_len ) {
+      map<string,int>::iterator it = negCacheMap.find(shorter);
+      if (it == negCacheMap.end() || it->second == 0) {
+        d_question.qname=shorter;
+        addNegCache(d_question);
+      }
+      if (!chopOff(shorter))
+        break;
+    }
+  }
 
   if( best_match_len == -1 )
       return false;
index 6837ed1b72baf6eb83d63d0ae1a1bf61a6aa01e2..07cd011c95cead3c96f47353c094680282d3a74a 100644 (file)
@@ -114,8 +114,8 @@ public:
   void lookup(const QType &, const string &qdomain, DNSPacket *pkt_p=0,  int zoneId=-1);
 
   /* 5-arg version is only valid for backends and should never be called directly */
-  virtual bool getAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId, const int best_match_len) {
-    throw PDNSException("5-arg version of getAuth should not be called in UeberBackend");
+  virtual bool getAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId, const int best_match_len, map<string,int>& negCacheMap) {
+    throw PDNSException("6-arg version of getAuth should not be called in UeberBackend");
   }
 
   bool getAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId);