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)
```
* `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
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);
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);
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;
});
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);
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";
}
});
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)