]> granicus.if.org Git - pdns/commitdiff
dnsdist: Add an option so the packet cache entries don't age
authorRemi Gacogne <remi.gacogne@powerdns.com>
Sun, 12 Mar 2017 16:04:30 +0000 (17:04 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 20 Mar 2017 21:15:54 +0000 (22:15 +0100)
pdns/README-dnsdist.md
pdns/dnsdist-cache.cc
pdns/dnsdist-cache.hh
pdns/dnsdist-console.cc
pdns/dnsdist-lua2.cc
regression-tests.dnsdist/test_Caching.py

index feb433f868b89c96e6fa34548fd145559d652ad9..e5f179e0811b8c994f4c6923dc24c8115e973996 100644 (file)
@@ -870,16 +870,18 @@ 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, 0, 60, 60)
+pc = newPacketCache(10000, 86400, 0, 60, 60, false)
 getPool(""):setCache(pc)
 ```
 
 The first parameter (10000) is the maximum number of entries stored in the cache, and is the
-only one required. All the other parameter are optional and in seconds.
+only one required. The second, third, fourth and fifth parameters are optional and in seconds.
 The second one (86400) is the maximum lifetime of an entry in the cache, the third one (0) is
 the minimum TTL an entry should have to be considered for insertion in the cache,
-the fourth one (60) is the TTL used for a Server Failure or a Refused response. The last
-one (60) is the TTL that will be used when a stale cache entry is returned.
+the fourth one (60) is the TTL used for a Server Failure or a Refused response. The fifth
+one (60) is the TTL that will be used when a stale cache entry is returned. The last one
+is a boolean that indicates whether the TTL of reponses should be reduced by the number of
+seconds the response has been in the cache.
 For performance reasons the cache will pre-allocate buckets based on the maximum number
 of entries, so be careful to set the first parameter to a reasonable value. Something
 along the lines of a dozen bytes per pre-allocated entry can be expected on 64-bit.
@@ -1537,7 +1539,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=0, temporaryFailureTTL=60, staleTTL=60])`: return a new PacketCache
+    * `newPacketCache(maxEntries[, maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=false])`: 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 9b5b48ce20274f739dffe3acc25c2c8b9bc4d846..a6181f050448ff5abb2d3de2d32315e0c309cda4 100644 (file)
@@ -24,7 +24,7 @@
 #include "dnsparser.hh"
 #include "dnsdist-cache.hh"
 
-DNSDistPacketCache::DNSDistPacketCache(size_t maxEntries, uint32_t maxTTL, uint32_t minTTL, uint32_t tempFailureTTL, uint32_t staleTTL): d_maxEntries(maxEntries), d_maxTTL(maxTTL), d_tempFailureTTL(tempFailureTTL), d_minTTL(minTTL), d_staleTTL(staleTTL)
+DNSDistPacketCache::DNSDistPacketCache(size_t maxEntries, uint32_t maxTTL, uint32_t minTTL, uint32_t tempFailureTTL, uint32_t staleTTL, bool dontAge): d_maxEntries(maxEntries), d_maxTTL(maxTTL), d_tempFailureTTL(tempFailureTTL), d_minTTL(minTTL), d_staleTTL(staleTTL), d_dontAge(dontAge)
 {
   pthread_rwlock_init(&d_lock, 0);
   /* we reserve maxEntries + 1 to avoid rehashing from occurring
@@ -209,7 +209,7 @@ bool DNSDistPacketCache::get(const DNSQuestion& dq, uint16_t consumed, uint16_t
     }
   }
 
-  if (!skipAging) {
+  if (!d_dontAge && !skipAging) {
     ageDNSPacket(response, *responseLen, age);
   }
 
index 10164c7c640eda555cf04dba6cef2172c4e4bd64..aacd8614e29e30b8d123b61f9409f6a4a50a13d2 100644 (file)
@@ -30,7 +30,7 @@ struct DNSQuestion;
 class DNSDistPacketCache : boost::noncopyable
 {
 public:
-  DNSDistPacketCache(size_t maxEntries, uint32_t maxTTL=86400, uint32_t minTTL=0, uint32_t tempFailureTTL=60, uint32_t staleTTL=60);
+  DNSDistPacketCache(size_t maxEntries, uint32_t maxTTL=86400, uint32_t minTTL=0, uint32_t tempFailureTTL=60, uint32_t staleTTL=60, bool dontAge=false);
   ~DNSDistPacketCache();
 
   void insert(uint32_t key, const DNSName& qname, uint16_t qtype, uint16_t qclass, const char* response, uint16_t responseLen, bool tcp, uint8_t rcode);
@@ -85,4 +85,5 @@ private:
   uint32_t d_tempFailureTTL;
   uint32_t d_minTTL;
   uint32_t d_staleTTL;
+  bool d_dontAge;
 };
index e73b9541c665aed7b06eca015329caeab680e636..1feff432123643a81a63b6e1a5a53c6e97a1baba 100644 (file)
@@ -329,6 +329,7 @@ const std::vector<ConsoleKeyword> g_consoleKeywords{
   { "mvResponseRule", true, "from, to", "move response rule 'from' to a position where it is in front of 'to'. 'to' can be one larger than the largest rule" },
   { "mvRule", true, "from, to", "move rule 'from' to a position where it is in front of 'to'. 'to' can be one larger than the largest rule, in which case the rule will be moved to the last position" },
   { "newDNSName", true, "name", "make a DNSName based on this .-terminated name" },
+  { "newPacketCache", true, "maxEntries[, maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=false]", "return a new Packet Cache" },
   { "newQPSLimiter", true, "rate, burst", "configure a QPS limiter with that rate and that burst capacity" },
   { "newRemoteLogger", true, "address:port [, timeout=2, maxQueuedEntries=100, reconnectWaitTime=1]", "create a Remote Logger object, to use with `RemoteLogAction()` and `RemoteLogResponseAction()`" },
   { "newRuleAction", true, "DNS rule, DNS action", "return a pair of DNS Rule and DNS Action, to be used with `setRules()`" },
index abf3deec55764b729820ef29a75f4801c313e6f0..6fccad43633f7063913f480a643108d55de6c199 100644 (file)
@@ -687,8 +687,8 @@ 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> tempFailTTL, boost::optional<uint32_t> staleTTL) {
-        return std::make_shared<DNSDistPacketCache>(maxEntries, maxTTL ? *maxTTL : 86400, minTTL ? *minTTL : 0, tempFailTTL ? *tempFailTTL : 60, staleTTL ? *staleTTL : 60);
+    g_lua.writeFunction("newPacketCache", [client](size_t maxEntries, boost::optional<uint32_t> maxTTL, boost::optional<uint32_t> minTTL, boost::optional<uint32_t> tempFailTTL, boost::optional<uint32_t> staleTTL, boost::optional<bool> dontAge) {
+        return std::make_shared<DNSDistPacketCache>(maxEntries, maxTTL ? *maxTTL : 86400, minTTL ? *minTTL : 0, tempFailTTL ? *tempFailTTL : 60, staleTTL ? *staleTTL : 60, dontAge ? *dontAge : false);
       });
     g_lua.registerFunction("toString", &DNSDistPacketCache::toString);
     g_lua.registerFunction("isFull", &DNSDistPacketCache::isFull);
index 832ca80af2fe103c548abcf40cd8c2335fdc0d9b..537c065da5e3287ca79c6bd795fca9b433d8d870 100644 (file)
@@ -1107,3 +1107,60 @@ class TestCachingFailureTTL(DNSDistTest):
             total += self._responsesCounter[key]
 
         self.assertEquals(total, misses)
+
+class TestCachingDontAge(DNSDistTest):
+
+    _config_template = """
+    pc = newPacketCache(100, 86400, 0, 60, 60, true)
+    getPool(""):setCache(pc)
+    newServer{address="127.0.0.1:%s"}
+    """
+    def testCacheDoesntDecreaseTTL(self):
+        """
+        Cache: Cache doesn't decrease TTL with 'don't age' set
+
+        dnsdist is configured to cache entries but without aging the TTL,
+        we are sending one request (cache miss) and verify that the cache
+        hits don't have a decreasing TTL.
+        """
+        ttl = 600
+        misses = 0
+        name = 'cachedoesntdecreasettl.cache-dont-age.tests.powerdns.com.'
+        query = dns.message.make_query(name, 'AAAA', 'IN')
+        response = dns.message.make_response(query)
+        rrset = dns.rrset.from_text(name,
+                                    ttl,
+                                    dns.rdataclass.IN,
+                                    dns.rdatatype.AAAA,
+                                    '::1')
+        response.answer.append(rrset)
+
+        # first query to fill the cache
+        (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
+        self.assertTrue(receivedQuery)
+        self.assertTrue(receivedResponse)
+        receivedQuery.id = query.id
+        self.assertEquals(query, receivedQuery)
+        self.assertEquals(receivedResponse, response)
+        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)
+
+        # now we wait a bit for the TTL to decrease
+        time.sleep(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)
+
+        total = 0
+        for key in self._responsesCounter:
+            total += self._responsesCounter[key]
+
+        self.assertEquals(total, misses)