]> granicus.if.org Git - pdns/commitdiff
dnsdist: Count "TTL too short" events, default min TTL to 0
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 29 Mar 2016 09:58:36 +0000 (11:58 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 29 Mar 2016 09:58:36 +0000 (11:58 +0200)
This means that we'll cache response regardless of their TTL value
by default.

pdns/README-dnsdist.md
pdns/dnsdist-cache.cc
pdns/dnsdist-cache.hh
pdns/dnsdist-carbon.cc
pdns/dnsdist-lua2.cc
regression-tests.dnsdist/test_Caching.py

index c797d53507d179be7e71b96d4d557a7eece6c61b..83e823460f9d7a0e0fc32bcbd0669ab79921dc4b 100644 (file)
@@ -713,7 +713,7 @@ The first step is to define a cache, then to assign that cache to the chosen poo
 the default one being represented by the empty string:
 
 ```
-pc = newPacketCache(10000, 86400, 600, 60, 60)
+pc = newPacketCache(10000, 86400, 0, 60, 60)
 getPool(""):setCache(pc)
 ```
 
@@ -1091,7 +1091,7 @@ instantiate a server with additional parameters
     * `expunge(n)`: remove entries from the cache, leaving at most `n` entries
     * `expungeByName(DNSName [, qtype=ANY])`: remove entries matching the supplied DNSName and type from the cache
     * `isFull()`: return true if the cache has reached the maximum number of entries
-    * `newPacketCache(maxEntries[, maxTTL=86400, minTTL=60, servFailTTL=60, stateTTL=60])`: return a new PacketCache
+    * `newPacketCache(maxEntries[, maxTTL=86400, minTTL=0, servFailTTL=60, stateTTL=60])`: return a new PacketCache
     * `printStats()`: print the cache stats (hits, misses, deferred lookups and deferred inserts)
     * `purgeExpired(n)`: remove expired entries from the cache until there is at most `n` entries remaining in the cache
     * `toString()`: return the number of entries in the Packet Cache, and the maximum number of entries
index 9e164b33860a8d35002989df82e861d48c7cd473..3c8b1d2eb4454b0aea28f9a83b9ecb39bb37a058 100644 (file)
@@ -38,8 +38,10 @@ void DNSDistPacketCache::insert(uint32_t key, const DNSName& qname, uint16_t qty
     if (minTTL > d_maxTTL)
       minTTL = d_maxTTL;
 
-    if (minTTL < d_minTTL)
+    if (minTTL < d_minTTL) {
+      d_ttlTooShorts++;
       return;
+    }
   }
 
   {
@@ -139,7 +141,6 @@ bool DNSDistPacketCache::get(const DNSQuestion& dq, uint16_t consumed, uint16_t
 
     /* check for collision */
     if (!cachedValueMatches(value, *dq.qname, dq.qtype, dq.qclass, dq.tcp)) {
-      d_misses++;
       d_lookupCollisions++;
       return false;
     }
index a154ab86a1f5da2e640478e976f560a9c192692f..dbc59e61b97795a1c3b294e881df7e09b36a3e7b 100644 (file)
@@ -9,7 +9,7 @@ struct DNSQuestion;
 class DNSDistPacketCache : boost::noncopyable
 {
 public:
-  DNSDistPacketCache(size_t maxEntries, uint32_t maxTTL=86400, uint32_t minTTL=60, uint32_t servFailTTL=60, uint32_t staleTTL=60);
+  DNSDistPacketCache(size_t maxEntries, uint32_t maxTTL=86400, uint32_t minTTL=0, uint32_t servFailTTL=60, uint32_t staleTTL=60);
   ~DNSDistPacketCache();
 
   void insert(uint32_t key, const DNSName& qname, uint16_t qtype, uint16_t qclass, const char* response, uint16_t responseLen, bool tcp, bool servFail=false);
@@ -27,6 +27,7 @@ public:
   uint64_t getLookupCollisions() const { return d_lookupCollisions; }
   uint64_t getInsertCollisions() const { return d_insertCollisions; }
   uint64_t getMaxEntries() const { return d_maxEntries; }
+  uint64_t getTTLTooShorts() const { return d_ttlTooShorts; }
   uint64_t getEntriesCount();
 
   static uint32_t getMinTTL(const char* packet, uint16_t length);
@@ -57,6 +58,7 @@ private:
   std::atomic<uint64_t> d_misses{0};
   std::atomic<uint64_t> d_insertCollisions{0};
   std::atomic<uint64_t> d_lookupCollisions{0};
+  std::atomic<uint64_t> d_ttlTooShorts{0};
   size_t d_maxEntries;
   uint32_t d_maxTTL;
   uint32_t d_servFailTTL;
index 29f00d069b65ac9d0c03fc75835391299748c7d1..bd3c042b491519aa2fa5fdbf5ae349302e600a2f 100644 (file)
@@ -101,6 +101,7 @@ try
             str<<base<<"cache-deferred-lookups" << " " << cache->getDeferredLookups() << " " << now << "\r\n";
             str<<base<<"cache-lookup-collisions" << " " << cache->getLookupCollisions() << " " << now << "\r\n";
             str<<base<<"cache-insert-collisions" << " " << cache->getInsertCollisions() << " " << now << "\r\n";
+            str<<base<<"cache-ttl-too-shorts" << " " << cache->getTTLTooShorts() << " " << now << "\r\n";
           }
         }
         const string msg = str.str();
index e5a1d21bf4c0692249bfb4766e83d9e81c25ab75..3718223cc1bc3e6aa1b5d9ac106404e210a51ec7 100644 (file)
@@ -539,7 +539,7 @@ void moreLua(bool client)
     });
 
     g_lua.writeFunction("newPacketCache", [client](size_t maxEntries, boost::optional<uint32_t> maxTTL, boost::optional<uint32_t> minTTL, boost::optional<uint32_t> servFailTTL, boost::optional<uint32_t> staleTTL) {
-        return std::make_shared<DNSDistPacketCache>(maxEntries, maxTTL ? *maxTTL : 86400, minTTL ? *minTTL : 60, servFailTTL ? *servFailTTL : 60, staleTTL ? *staleTTL : 60);
+        return std::make_shared<DNSDistPacketCache>(maxEntries, maxTTL ? *maxTTL : 86400, minTTL ? *minTTL : 0, servFailTTL ? *servFailTTL : 60, staleTTL ? *staleTTL : 60);
       });
     g_lua.registerFunction("toString", &DNSDistPacketCache::toString);
     g_lua.registerFunction("isFull", &DNSDistPacketCache::isFull);
@@ -559,6 +559,7 @@ void moreLua(bool client)
           g_outputBuffer+="Deferred lookups: " + std::to_string(cache->getDeferredLookups()) + "\n";
           g_outputBuffer+="Lookup Collisions: " + std::to_string(cache->getLookupCollisions()) + "\n";
           g_outputBuffer+="Insert Collisions: " + std::to_string(cache->getInsertCollisions()) + "\n";
+          g_outputBuffer+="TTL Too Shorts: " + std::to_string(cache->getTTLTooShorts()) + "\n";
         }
       });
 
index be6d9ed999b4dd1230179d9a55b2c4812f2e171e..a016b6cc31e866ad4e37b2aa141e428c79df768d 100644 (file)
@@ -818,3 +818,121 @@ class TestCacheManagement(DNSDistTest):
         for key in self._responsesCounter:
             total += self._responsesCounter[key]
         self.assertEquals(total, misses)
+
+class TestCachingTTL(DNSDistTest):
+
+    _maxCacheTTL = 86400
+    _minCacheTTL = 600
+    _config_params = ['_maxCacheTTL', '_minCacheTTL', '_testServerPort']
+    _config_template = """
+    pc = newPacketCache(1000, %s, %s)
+    getPool(""):setCache(pc)
+    newServer{address="127.0.0.1:%s"}
+    """
+    def testCacheShortTTL(self):
+        """
+        Cache: Entries with a TTL shorter than minTTL
+
+        """
+        misses = 0
+        ttl = 60
+        name = 'ttltooshort.cache.tests.powerdns.com.'
+        query = dns.message.make_query(name, 'A', 'IN')
+        response = dns.message.make_response(query)
+        rrset = dns.rrset.from_text(name,
+                                    ttl,
+                                    dns.rdataclass.IN,
+                                    dns.rdatatype.A,
+                                    '127.0.0.1')
+        response.answer.append(rrset)
+
+        # Miss
+        (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
+        self.assertTrue(receivedQuery)
+        self.assertTrue(receivedResponse)
+        receivedQuery.id = query.id
+        self.assertEquals(query, receivedQuery)
+        self.assertEquals(response, receivedResponse)
+        for an in receivedResponse.answer:
+            self.assertEquals(an.ttl, ttl)
+        misses += 1
+
+        # We should not have been cached
+        (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
+        self.assertTrue(receivedQuery)
+        self.assertTrue(receivedResponse)
+        receivedQuery.id = query.id
+        self.assertEquals(query, receivedQuery)
+        self.assertEquals(response, receivedResponse)
+        for an in receivedResponse.answer:
+            self.assertEquals(an.ttl, ttl)
+        misses += 1
+
+        total = 0
+        for key in self._responsesCounter:
+            total += self._responsesCounter[key]
+
+        self.assertEquals(total, misses)
+
+class TestCachingLongTTL(DNSDistTest):
+
+    _maxCacheTTL = 2
+    _config_params = ['_maxCacheTTL', '_testServerPort']
+    _config_template = """
+    pc = newPacketCache(1000, %s)
+    getPool(""):setCache(pc)
+    newServer{address="127.0.0.1:%s"}
+    """
+    def testCacheLongTTL(self):
+        """
+        Cache: Entries with a longer TTL than the maximum
+
+        """
+        misses = 0
+        ttl = 172800
+        name = 'longttl.cache.tests.powerdns.com.'
+        query = dns.message.make_query(name, 'A', 'IN')
+        response = dns.message.make_response(query)
+        rrset = dns.rrset.from_text(name,
+                                    ttl,
+                                    dns.rdataclass.IN,
+                                    dns.rdatatype.A,
+                                    '127.0.0.1')
+        response.answer.append(rrset)
+
+        # Miss
+        (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
+        self.assertTrue(receivedQuery)
+        self.assertTrue(receivedResponse)
+        receivedQuery.id = query.id
+        self.assertEquals(query, receivedQuery)
+        self.assertEquals(response, receivedResponse)
+        for an in receivedResponse.answer:
+            self.assertEquals(an.ttl, ttl)
+        misses += 1
+
+        # next queries should hit the cache
+        (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
+        self.assertEquals(receivedResponse, response)
+        for an in receivedResponse.answer:
+            self.assertTrue(an.ttl <= ttl)
+
+        time.sleep(self._maxCacheTTL + 1)
+
+        # we should not have cached for longer than max cache
+        # so it should be a miss
+        (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
+        self.assertTrue(receivedQuery)
+        self.assertTrue(receivedResponse)
+        receivedQuery.id = query.id
+        self.assertEquals(query, receivedQuery)
+        self.assertEquals(response, receivedResponse)
+        for an in receivedResponse.answer:
+            self.assertEquals(an.ttl, ttl)
+        misses += 1
+
+        total = 0
+        for key in self._responsesCounter:
+            total += self._responsesCounter[key]
+
+        self.assertEquals(total, misses)