#include "base64.hh"
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters): too cumbersome to change at this point
-DNSDistPacketCache::DNSDistPacketCache(size_t maxEntries, uint32_t maxTTL, uint32_t minTTL, uint32_t tempFailureTTL, uint32_t maxNegativeTTL, uint32_t staleTTL, bool dontAge, uint32_t shards, bool deferrableInsertLock, bool parseECS) :
- d_maxEntries(maxEntries), d_shardCount(shards), d_maxTTL(maxTTL), d_tempFailureTTL(tempFailureTTL), d_maxNegativeTTL(maxNegativeTTL), d_minTTL(minTTL), d_staleTTL(staleTTL), d_dontAge(dontAge), d_deferrableInsertLock(deferrableInsertLock), d_parseECS(parseECS)
+DNSDistPacketCache::DNSDistPacketCache(const CacheSettings& settings) :
+ d_settings(settings)
{
- if (d_maxEntries == 0) {
+ if (d_settings.d_maxEntries == 0) {
throw std::runtime_error("Trying to create a 0-sized packet-cache");
}
- d_shards.resize(d_shardCount);
+ if (d_settings.d_shardCount == 0) {
+ d_settings.d_shardCount = 1;
+ }
+
+ d_shards.resize(d_settings.d_shardCount);
/* we reserve maxEntries + 1 to avoid rehashing from occurring
when we get to maxEntries, as it means a load factor of 1 */
for (auto& shard : d_shards) {
- shard.setSize((maxEntries / d_shardCount) + 1);
+ shard.setSize((d_settings.d_maxEntries / d_settings.d_shardCount) + 1);
}
}
return false;
}
- if (d_parseECS && cachedValue.subnet != subnet) {
+ if (d_settings.d_parseECS && cachedValue.subnet != subnet) {
return false;
}
void DNSDistPacketCache::insertLocked(CacheShard& shard, std::unordered_map<uint32_t, CacheValue>& map, uint32_t key, CacheValue& newValue)
{
/* check again now that we hold the lock to prevent a race */
- if (map.size() >= (d_maxEntries / d_shardCount)) {
+ if (map.size() >= (d_settings.d_maxEntries / d_settings.d_shardCount)) {
return;
}
uint32_t minTTL{0};
if (rcode == RCode::ServFail || rcode == RCode::Refused) {
- minTTL = tempFailureTTL == boost::none ? d_tempFailureTTL : *tempFailureTTL;
+ minTTL = tempFailureTTL == boost::none ? d_settings.d_tempFailureTTL : *tempFailureTTL;
if (minTTL == 0) {
return;
}
}
if (rcode == RCode::NXDomain || (rcode == RCode::NoError && seenAuthSOA)) {
- minTTL = std::min(minTTL, d_maxNegativeTTL);
+ minTTL = std::min(minTTL, d_settings.d_maxNegativeTTL);
}
- else if (minTTL > d_maxTTL) {
- minTTL = d_maxTTL;
+ else if (minTTL > d_settings.d_maxTTL) {
+ minTTL = d_settings.d_maxTTL;
}
- if (minTTL < d_minTTL) {
+ if (minTTL < d_settings.d_minTTL) {
++d_ttlTooShorts;
return;
}
uint32_t shardIndex = getShardIndex(key);
- if (d_shards.at(shardIndex).d_entriesCount >= (d_maxEntries / d_shardCount)) {
+ if (d_shards.at(shardIndex).d_entriesCount >= (d_settings.d_maxEntries / d_settings.d_shardCount)) {
return;
}
auto& shard = d_shards.at(shardIndex);
- if (d_deferrableInsertLock) {
+ if (d_settings.d_deferrableInsertLock) {
auto lock = shard.d_map.try_write_lock();
if (!lock.owns_lock()) {
*keyOut = key;
}
- if (d_parseECS) {
+ if (d_settings.d_parseECS) {
getClientSubnet(dnsQuestion.getData(), dnsQuestion.ids.qname.wirelength(), subnet);
}
age = now - value.added;
}
else {
- age = (value.validity - value.added) - d_staleTTL;
+ age = (value.validity - value.added) - d_settings.d_staleTTL;
}
}
- if (!d_dontAge && !skipAging) {
+ if (!d_settings.d_dontAge && !skipAging) {
if (!stale) {
// coverity[store_truncates_time_t]
dnsheader_aligned dh_aligned(response.data());
else {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
editDNSPacketTTL(reinterpret_cast<char*>(response.data()), response.size(),
- [staleTTL = d_staleTTL](uint8_t /* section */, uint16_t /* class_ */, uint16_t /* type */, uint32_t /* ttl */) { return staleTTL; });
+ [staleTTL = d_settings.d_staleTTL](uint8_t /* section */, uint16_t /* class_ */, uint16_t /* type */, uint32_t /* ttl */) { return staleTTL; });
}
}
*/
size_t DNSDistPacketCache::purgeExpired(size_t upTo, const time_t now)
{
- const size_t maxPerShard = upTo / d_shardCount;
+ const size_t maxPerShard = upTo / d_settings.d_shardCount;
size_t removed = 0;
*/
size_t DNSDistPacketCache::expunge(size_t upTo)
{
- const size_t maxPerShard = upTo / d_shardCount;
+ const size_t maxPerShard = upTo / d_settings.d_shardCount;
size_t removed = 0;
bool DNSDistPacketCache::isFull()
{
- return (getSize() >= d_maxEntries);
+ return (getSize() >= d_settings.d_maxEntries);
}
uint64_t DNSDistPacketCache::getSize()
throw std::range_error("Computing packet cache key for an invalid packet (" + std::to_string(packet.size()) + " < " + std::to_string(sizeof(dnsheader) + qnameWireLength) + ")");
}
if (packet.size() > ((sizeof(dnsheader) + qnameWireLength))) {
- if (!d_optionsToSkip.empty()) {
+ if (!d_settings.d_optionsToSkip.empty()) {
/* skip EDNS options if any */
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
- result = PacketCache::hashAfterQname(std::string_view(reinterpret_cast<const char*>(packet.data()), packet.size()), result, sizeof(dnsheader) + qnameWireLength, d_optionsToSkip);
+ result = PacketCache::hashAfterQname(std::string_view(reinterpret_cast<const char*>(packet.data()), packet.size()), result, sizeof(dnsheader) + qnameWireLength, d_settings.d_optionsToSkip);
}
else {
result = burtle(&packet.at(sizeof(dnsheader) + qnameWireLength), packet.size() - (sizeof(dnsheader) + qnameWireLength), result);
uint32_t DNSDistPacketCache::getShardIndex(uint32_t key) const
{
- return key % d_shardCount;
+ return key % d_settings.d_shardCount;
}
string DNSDistPacketCache::toString()
{
- return std::to_string(getSize()) + "/" + std::to_string(d_maxEntries);
+ return std::to_string(getSize()) + "/" + std::to_string(d_settings.d_maxEntries);
}
uint64_t DNSDistPacketCache::getEntriesCount()
return count;
}
-void DNSDistPacketCache::setSkippedOptions(const std::unordered_set<uint16_t>& optionsToSkip)
-{
- d_optionsToSkip = optionsToSkip;
-}
-
std::set<DNSName> DNSDistPacketCache::getDomainsContainingRecords(const ComboAddress& addr)
{
std::set<DNSName> domains;
return addresses;
}
-
-void DNSDistPacketCache::setMaximumEntrySize(size_t maxSize)
-{
- d_maximumEntrySize = maxSize;
-}
/* PacketCache */
luaCtx.writeFunction("newPacketCache", [client](size_t maxEntries, boost::optional<LuaAssociativeTable<boost::variant<bool, size_t, LuaArray<uint16_t>>>> vars) {
- bool keepStaleData = false;
- size_t maxTTL = 86400;
- size_t minTTL = 0;
- size_t tempFailTTL = 60;
- size_t maxNegativeTTL = 3600;
- size_t staleTTL = 60;
- size_t numberOfShards = 20;
- size_t maxEntrySize{0};
- bool dontAge = false;
- bool deferrableInsertLock = true;
- bool ecsParsing = false;
+ DNSDistPacketCache::CacheSettings settings {
+ .d_maxEntries = maxEntries,
+ .d_shardCount = 20,
+ };
bool cookieHashing = false;
LuaArray<uint16_t> skipOptions;
- std::unordered_set<uint16_t> optionsToSkip{EDNSOptionCode::COOKIE};
-
- getOptionalValue<bool>(vars, "deferrableInsertLock", deferrableInsertLock);
- getOptionalValue<bool>(vars, "dontAge", dontAge);
- getOptionalValue<bool>(vars, "keepStaleData", keepStaleData);
- getOptionalValue<size_t>(vars, "maxNegativeTTL", maxNegativeTTL);
- getOptionalValue<size_t>(vars, "maxTTL", maxTTL);
- getOptionalValue<size_t>(vars, "minTTL", minTTL);
- getOptionalValue<size_t>(vars, "numberOfShards", numberOfShards);
- getOptionalValue<bool>(vars, "parseECS", ecsParsing);
- getOptionalValue<size_t>(vars, "staleTTL", staleTTL);
- getOptionalValue<size_t>(vars, "temporaryFailureTTL", tempFailTTL);
+ size_t maximumEntrySize{4096};
+
+ getOptionalValue<bool>(vars, "deferrableInsertLock", settings.d_deferrableInsertLock);
+ getOptionalValue<bool>(vars, "dontAge", settings.d_dontAge);
+ getOptionalValue<bool>(vars, "keepStaleData", settings.d_keepStaleData);
+ getOptionalValue<size_t>(vars, "maxNegativeTTL", settings.d_maxNegativeTTL);
+ getOptionalValue<size_t>(vars, "maxTTL", settings.d_maxTTL);
+ getOptionalValue<size_t>(vars, "minTTL", settings.d_minTTL);
+ getOptionalValue<size_t>(vars, "numberOfShards", settings.d_shardCount);
+ getOptionalValue<bool>(vars, "parseECS", settings.d_parseECS);
+ getOptionalValue<size_t>(vars, "staleTTL", settings.d_staleTTL);
+ getOptionalValue<size_t>(vars, "temporaryFailureTTL", settings.d_tempFailureTTL);
getOptionalValue<bool>(vars, "cookieHashing", cookieHashing);
- getOptionalValue<size_t>(vars, "maximumEntrySize", maxEntrySize);
+ getOptionalValue<size_t>(vars, "maximumEntrySize", maximumEntrySize);
+
+ if (maximumEntrySize >= sizeof(dnsheader)) {
+ settings.d_maximumEntrySize = maximumEntrySize;
+ }
if (getOptionalValue<decltype(skipOptions)>(vars, "skipOptions", skipOptions) > 0) {
for (const auto& option : skipOptions) {
- optionsToSkip.insert(option.second);
+ settings.d_optionsToSkip.insert(option.second);
}
}
if (cookieHashing) {
- optionsToSkip.erase(EDNSOptionCode::COOKIE);
+ settings.d_optionsToSkip.erase(EDNSOptionCode::COOKIE);
}
checkAllParametersConsumed("newPacketCache", vars);
- if (maxEntries < numberOfShards) {
- warnlog("The number of entries (%d) in the packet cache is smaller than the number of shards (%d), decreasing the number of shards to %d", maxEntries, numberOfShards, maxEntries);
- g_outputBuffer += "The number of entries (" + std::to_string(maxEntries) + " in the packet cache is smaller than the number of shards (" + std::to_string(numberOfShards) + "), decreasing the number of shards to " + std::to_string(maxEntries);
- numberOfShards = maxEntries;
+ if (maxEntries < settings.d_shardCount) {
+ warnlog("The number of entries (%d) in the packet cache is smaller than the number of shards (%d), decreasing the number of shards to %d", maxEntries, settings.d_shardCount, maxEntries);
+ g_outputBuffer += "The number of entries (" + std::to_string(maxEntries) + " in the packet cache is smaller than the number of shards (" + std::to_string(settings.d_shardCount) + "), decreasing the number of shards to " + std::to_string(maxEntries);
+ settings.d_shardCount = maxEntries;
}
if (client) {
- maxEntries = 1;
- numberOfShards = 1;
- }
-
- auto res = std::make_shared<DNSDistPacketCache>(maxEntries, maxTTL, minTTL, tempFailTTL, maxNegativeTTL, staleTTL, dontAge, numberOfShards, deferrableInsertLock, ecsParsing);
-
- res->setKeepStaleData(keepStaleData);
- res->setSkippedOptions(optionsToSkip);
- if (maxEntrySize >= sizeof(dnsheader)) {
- res->setMaximumEntrySize(maxEntrySize);
+ settings.d_maxEntries = 1;
+ settings.d_shardCount = 1;
}
- return res;
+ return std::make_shared<DNSDistPacketCache>(settings);
});
#ifndef DISABLE_PACKETCACHE_BINDINGS
BOOST_AUTO_TEST_CASE(test_PacketCacheSimple)
{
- const size_t maxEntries = 150000;
- DNSDistPacketCache localCache(maxEntries, 86400, 1);
+ const DNSDistPacketCache::CacheSettings settings{
+ .d_maxEntries = 150000,
+ .d_maxTTL = 86400,
+ .d_minTTL = 1,
+ };
+ DNSDistPacketCache localCache(settings);
BOOST_CHECK_EQUAL(localCache.getSize(), 0U);
size_t counter = 0;
BOOST_AUTO_TEST_CASE(test_PacketCacheSharded)
{
- const size_t maxEntries = 150000;
- const size_t numberOfShards = 10;
- DNSDistPacketCache localCache(maxEntries, 86400, 1, 60, 3600, 60, false, numberOfShards);
+ const DNSDistPacketCache::CacheSettings settings{
+ .d_maxEntries = 150000,
+ .d_maxTTL = 86400,
+ .d_minTTL = 1,
+ .d_tempFailureTTL = 60,
+ .d_maxNegativeTTL = 3600,
+ .d_staleTTL = 60,
+ .d_shardCount = 10,
+ .d_dontAge = false,
+ };
+ DNSDistPacketCache localCache(settings);
BOOST_CHECK_EQUAL(localCache.getSize(), 0U);
size_t counter = 0;
BOOST_AUTO_TEST_CASE(test_PacketCacheTCP)
{
- const size_t maxEntries = 150000;
- DNSDistPacketCache localCache(maxEntries, 86400, 1);
+ const DNSDistPacketCache::CacheSettings settings{
+ .d_maxEntries = 150000,
+ .d_maxTTL = 86400,
+ .d_minTTL = 1,
+ };
+ DNSDistPacketCache localCache(settings);
InternalQueryState ids;
ids.qtype = QType::A;
ids.qclass = QClass::IN;
BOOST_AUTO_TEST_CASE(test_PacketCacheServFailTTL)
{
- const size_t maxEntries = 150000;
- DNSDistPacketCache localCache(maxEntries, 86400, 1);
+ const DNSDistPacketCache::CacheSettings settings{
+ .d_maxEntries = 150000,
+ .d_maxTTL = 86400,
+ .d_minTTL = 1,
+ };
+ DNSDistPacketCache localCache(settings);
InternalQueryState ids;
ids.qtype = QType::A;
ids.qclass = QClass::IN;
BOOST_AUTO_TEST_CASE(test_PacketCacheNoDataTTL)
{
- const size_t maxEntries = 150000;
- DNSDistPacketCache localCache(maxEntries, /* maxTTL */ 86400, /* minTTL */ 1, /* tempFailureTTL */ 60, /* maxNegativeTTL */ 1);
+ const DNSDistPacketCache::CacheSettings settings{
+ .d_maxEntries = 150000,
+ .d_maxTTL = 86400,
+ .d_minTTL = 1,
+ .d_tempFailureTTL = 60,
+ .d_maxNegativeTTL = 1,
+ };
+ DNSDistPacketCache localCache(settings);
ComboAddress remote;
bool dnssecOK = false;
BOOST_AUTO_TEST_CASE(test_PacketCacheNXDomainTTL)
{
- const size_t maxEntries = 150000;
- DNSDistPacketCache localCache(maxEntries, /* maxTTL */ 86400, /* minTTL */ 1, /* tempFailureTTL */ 60, /* maxNegativeTTL */ 1);
+ const DNSDistPacketCache::CacheSettings settings{
+ .d_maxEntries = 150000,
+ .d_maxTTL = 86400,
+ .d_minTTL = 1,
+ .d_tempFailureTTL = 60,
+ .d_maxNegativeTTL = 1,
+ };
+ DNSDistPacketCache localCache(settings);
InternalQueryState ids;
ids.qtype = QType::A;
BOOST_AUTO_TEST_CASE(test_PacketCacheTruncated)
{
- const size_t maxEntries = 150000;
- DNSDistPacketCache localCache(maxEntries, /* maxTTL */ 86400, /* minTTL */ 1, /* tempFailureTTL */ 60, /* maxNegativeTTL */ 1);
+ const DNSDistPacketCache::CacheSettings settings{
+ .d_maxEntries = 150000,
+ .d_maxTTL = 86400,
+ .d_minTTL = 1,
+ .d_tempFailureTTL = 60,
+ .d_maxNegativeTTL = 1,
+ };
+ DNSDistPacketCache localCache(settings);
InternalQueryState ids;
ids.qtype = QType::A;
BOOST_AUTO_TEST_CASE(test_PacketCacheMaximumSize)
{
- const size_t maxEntries = 150000;
- DNSDistPacketCache packetCache(maxEntries, 86400, 1);
InternalQueryState ids;
ids.qtype = QType::A;
ids.qclass = QClass::IN;
pwR.commit();
}
- /* first, we set the maximum entry size to the response packet size */
- packetCache.setMaximumEntrySize(response.size());
-
{
- /* UDP */
- uint32_t key = 0;
- boost::optional<Netmask> subnet;
- DNSQuestion dnsQuestion(ids, query);
- bool found = packetCache.get(dnsQuestion, 0, &key, subnet, dnssecOK, receivedOverUDP);
- BOOST_CHECK_EQUAL(found, false);
- BOOST_CHECK(!subnet);
+ /* first, we set the maximum entry size to the response packet size */
+ const DNSDistPacketCache::CacheSettings settings{
+ .d_maxEntries = 150000,
+ .d_maximumEntrySize = response.size(),
+ .d_maxTTL = 86400,
+ .d_minTTL = 1,
+ };
+ DNSDistPacketCache packetCache(settings);
- packetCache.insert(key, subnet, *(getFlagsFromDNSHeader(dnsQuestion.getHeader().get())), dnssecOK, ids.qname, QType::A, QClass::IN, response, receivedOverUDP, RCode::NoError, boost::none);
- found = packetCache.get(dnsQuestion, queryID, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
- BOOST_CHECK_EQUAL(found, true);
- BOOST_CHECK(!subnet);
- }
+ {
+ /* UDP */
+ uint32_t key = 0;
+ boost::optional<Netmask> subnet;
+ DNSQuestion dnsQuestion(ids, query);
+ bool found = packetCache.get(dnsQuestion, 0, &key, subnet, dnssecOK, receivedOverUDP);
+ BOOST_CHECK_EQUAL(found, false);
+ BOOST_CHECK(!subnet);
- {
- /* same but over TCP */
- uint32_t key = 0;
- boost::optional<Netmask> subnet;
- ids.protocol = dnsdist::Protocol::DoTCP;
- DNSQuestion dnsQuestion(ids, query);
- bool found = packetCache.get(dnsQuestion, 0, &key, subnet, dnssecOK, !receivedOverUDP);
- BOOST_CHECK_EQUAL(found, false);
- BOOST_CHECK(!subnet);
+ packetCache.insert(key, subnet, *(getFlagsFromDNSHeader(dnsQuestion.getHeader().get())), dnssecOK, ids.qname, QType::A, QClass::IN, response, receivedOverUDP, RCode::NoError, boost::none);
+ found = packetCache.get(dnsQuestion, queryID, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
+ BOOST_CHECK_EQUAL(found, true);
+ BOOST_CHECK(!subnet);
+ }
- packetCache.insert(key, subnet, *(getFlagsFromDNSHeader(dnsQuestion.getHeader().get())), dnssecOK, ids.qname, QType::A, QClass::IN, response, !receivedOverUDP, RCode::NoError, boost::none);
- found = packetCache.get(dnsQuestion, queryID, &key, subnet, dnssecOK, !receivedOverUDP, 0, true);
- BOOST_CHECK_EQUAL(found, true);
- BOOST_CHECK(!subnet);
+ {
+ /* same but over TCP */
+ uint32_t key = 0;
+ boost::optional<Netmask> subnet;
+ ids.protocol = dnsdist::Protocol::DoTCP;
+ DNSQuestion dnsQuestion(ids, query);
+ bool found = packetCache.get(dnsQuestion, 0, &key, subnet, dnssecOK, !receivedOverUDP);
+ BOOST_CHECK_EQUAL(found, false);
+ BOOST_CHECK(!subnet);
+
+ packetCache.insert(key, subnet, *(getFlagsFromDNSHeader(dnsQuestion.getHeader().get())), dnssecOK, ids.qname, QType::A, QClass::IN, response, !receivedOverUDP, RCode::NoError, boost::none);
+ found = packetCache.get(dnsQuestion, queryID, &key, subnet, dnssecOK, !receivedOverUDP, 0, true);
+ BOOST_CHECK_EQUAL(found, true);
+ BOOST_CHECK(!subnet);
+ }
}
- /* then we set it slightly below response packet size */
- packetCache.expunge(0);
- packetCache.setMaximumEntrySize(response.size() - 1);
{
- /* UDP */
- uint32_t key = 0;
- boost::optional<Netmask> subnet;
- DNSQuestion dnsQuestion(ids, query);
- bool found = packetCache.get(dnsQuestion, 0, &key, subnet, dnssecOK, receivedOverUDP);
- BOOST_CHECK_EQUAL(found, false);
- BOOST_CHECK(!subnet);
+ /* then we set it slightly below response packet size */
+ const DNSDistPacketCache::CacheSettings settings{
+ .d_maxEntries = 150000,
+ .d_maximumEntrySize = response.size() - 1,
+ .d_maxTTL = 86400,
+ .d_minTTL = 1,
+ };
+ DNSDistPacketCache packetCache(settings);
- packetCache.insert(key, subnet, *(getFlagsFromDNSHeader(dnsQuestion.getHeader().get())), dnssecOK, ids.qname, QType::A, QClass::IN, response, receivedOverUDP, RCode::NoError, boost::none);
- found = packetCache.get(dnsQuestion, queryID, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
- BOOST_CHECK_EQUAL(found, false);
- }
+ {
+ /* UDP */
+ uint32_t key = 0;
+ boost::optional<Netmask> subnet;
+ DNSQuestion dnsQuestion(ids, query);
+ bool found = packetCache.get(dnsQuestion, 0, &key, subnet, dnssecOK, receivedOverUDP);
+ BOOST_CHECK_EQUAL(found, false);
+ BOOST_CHECK(!subnet);
- {
- /* same but over TCP */
- uint32_t key = 0;
- boost::optional<Netmask> subnet;
- ids.protocol = dnsdist::Protocol::DoTCP;
- DNSQuestion dnsQuestion(ids, query);
- bool found = packetCache.get(dnsQuestion, 0, &key, subnet, dnssecOK, !receivedOverUDP);
- BOOST_CHECK_EQUAL(found, false);
- BOOST_CHECK(!subnet);
+ packetCache.insert(key, subnet, *(getFlagsFromDNSHeader(dnsQuestion.getHeader().get())), dnssecOK, ids.qname, QType::A, QClass::IN, response, receivedOverUDP, RCode::NoError, boost::none);
+ found = packetCache.get(dnsQuestion, queryID, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
+ BOOST_CHECK_EQUAL(found, false);
+ }
- packetCache.insert(key, subnet, *(getFlagsFromDNSHeader(dnsQuestion.getHeader().get())), dnssecOK, ids.qname, QType::A, QClass::IN, response, !receivedOverUDP, RCode::NoError, boost::none);
- found = packetCache.get(dnsQuestion, queryID, &key, subnet, dnssecOK, !receivedOverUDP, 0, true);
- BOOST_CHECK_EQUAL(found, false);
+ {
+ /* same but over TCP */
+ uint32_t key = 0;
+ boost::optional<Netmask> subnet;
+ ids.protocol = dnsdist::Protocol::DoTCP;
+ DNSQuestion dnsQuestion(ids, query);
+ bool found = packetCache.get(dnsQuestion, 0, &key, subnet, dnssecOK, !receivedOverUDP);
+ BOOST_CHECK_EQUAL(found, false);
+ BOOST_CHECK(!subnet);
+
+ packetCache.insert(key, subnet, *(getFlagsFromDNSHeader(dnsQuestion.getHeader().get())), dnssecOK, ids.qname, QType::A, QClass::IN, response, !receivedOverUDP, RCode::NoError, boost::none);
+ found = packetCache.get(dnsQuestion, queryID, &key, subnet, dnssecOK, !receivedOverUDP, 0, true);
+ BOOST_CHECK_EQUAL(found, false);
+ }
}
/* now we generate a very big response packet, it should be cached over TCP and UDP (although in practice dnsdist will refuse to cache it for the UDP case) */
- packetCache.expunge(0);
response.clear();
{
GenericDNSPacketWriter<PacketBuffer> pwR(response, ids.qname, QType::AAAA, QClass::IN, 0);
}
BOOST_REQUIRE_GT(response.size(), 4096U);
- packetCache.setMaximumEntrySize(response.size());
{
- /* UDP */
- uint32_t key = 0;
- boost::optional<Netmask> subnet;
- DNSQuestion dnsQuestion(ids, query);
- bool found = packetCache.get(dnsQuestion, 0, &key, subnet, dnssecOK, receivedOverUDP);
- BOOST_CHECK_EQUAL(found, false);
- BOOST_CHECK(!subnet);
+ /* then we set it slightly below response packet size */
+ const DNSDistPacketCache::CacheSettings settings{
+ .d_maxEntries = 150000,
+ .d_maximumEntrySize = response.size(),
+ .d_maxTTL = 86400,
+ .d_minTTL = 1,
+ };
+ DNSDistPacketCache packetCache(settings);
- packetCache.insert(key, subnet, *(getFlagsFromDNSHeader(dnsQuestion.getHeader().get())), dnssecOK, ids.qname, QType::A, QClass::IN, response, receivedOverUDP, RCode::NoError, boost::none);
- found = packetCache.get(dnsQuestion, queryID, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
- BOOST_CHECK_EQUAL(found, true);
- }
+ {
+ /* UDP */
+ uint32_t key = 0;
+ boost::optional<Netmask> subnet;
+ DNSQuestion dnsQuestion(ids, query);
+ bool found = packetCache.get(dnsQuestion, 0, &key, subnet, dnssecOK, receivedOverUDP);
+ BOOST_CHECK_EQUAL(found, false);
+ BOOST_CHECK(!subnet);
- {
- /* same but over TCP */
- uint32_t key = 0;
- boost::optional<Netmask> subnet;
- ids.protocol = dnsdist::Protocol::DoTCP;
- DNSQuestion dnsQuestion(ids, query);
- bool found = packetCache.get(dnsQuestion, 0, &key, subnet, dnssecOK, !receivedOverUDP);
- BOOST_CHECK_EQUAL(found, false);
- BOOST_CHECK(!subnet);
+ packetCache.insert(key, subnet, *(getFlagsFromDNSHeader(dnsQuestion.getHeader().get())), dnssecOK, ids.qname, QType::A, QClass::IN, response, receivedOverUDP, RCode::NoError, boost::none);
+ found = packetCache.get(dnsQuestion, queryID, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
+ BOOST_CHECK_EQUAL(found, true);
+ }
- packetCache.insert(key, subnet, *(getFlagsFromDNSHeader(dnsQuestion.getHeader().get())), dnssecOK, ids.qname, QType::A, QClass::IN, response, !receivedOverUDP, RCode::NoError, boost::none);
- found = packetCache.get(dnsQuestion, queryID, &key, subnet, dnssecOK, !receivedOverUDP, 0, true);
- BOOST_CHECK_EQUAL(found, true);
+ {
+ /* same but over TCP */
+ uint32_t key = 0;
+ boost::optional<Netmask> subnet;
+ ids.protocol = dnsdist::Protocol::DoTCP;
+ DNSQuestion dnsQuestion(ids, query);
+ bool found = packetCache.get(dnsQuestion, 0, &key, subnet, dnssecOK, !receivedOverUDP);
+ BOOST_CHECK_EQUAL(found, false);
+ BOOST_CHECK(!subnet);
+
+ packetCache.insert(key, subnet, *(getFlagsFromDNSHeader(dnsQuestion.getHeader().get())), dnssecOK, ids.qname, QType::A, QClass::IN, response, !receivedOverUDP, RCode::NoError, boost::none);
+ found = packetCache.get(dnsQuestion, queryID, &key, subnet, dnssecOK, !receivedOverUDP, 0, true);
+ BOOST_CHECK_EQUAL(found, true);
+ }
}
}
-static DNSDistPacketCache s_localCache(500000);
+const DNSDistPacketCache::CacheSettings s_localCacheSettings{
+ .d_maxEntries = 500000,
+};
+static DNSDistPacketCache s_localCache(s_localCacheSettings);
static void threadMangler(unsigned int offset)
{
BOOST_AUTO_TEST_CASE(test_PCCollision)
{
- const size_t maxEntries = 150000;
- DNSDistPacketCache localCache(maxEntries, 86400, 1, 60, 3600, 60, false, 1, true, true);
+ const DNSDistPacketCache::CacheSettings settings{
+ .d_maxEntries = 150000,
+ .d_maxTTL = 86400,
+ .d_minTTL = 1,
+ .d_tempFailureTTL = 60,
+ .d_maxNegativeTTL = 3600,
+ .d_staleTTL = 60,
+ .d_shardCount = 1,
+ .d_dontAge = false,
+ .d_deferrableInsertLock = true,
+ .d_parseECS = true,
+ };
+ DNSDistPacketCache localCache(settings);
BOOST_CHECK_EQUAL(localCache.getSize(), 0U);
InternalQueryState ids;
#if 0
/* to be able to compute a new collision if the packet cache hashing code is updated */
{
- DNSDistPacketCache pc(10000);
+ const DNSDistPacketCache::CacheSettings settings{
+ .d_maxEntries = 10000,
+ };
+ DNSDistPacketCache pc(settings);
GenericDNSPacketWriter<PacketBuffer>::optvect_t ednsOptions;
EDNSSubnetOpts opt;
std::map<uint32_t, Netmask> colMap;
BOOST_AUTO_TEST_CASE(test_PCDNSSECCollision)
{
- const size_t maxEntries = 150000;
- DNSDistPacketCache localCache(maxEntries, 86400, 1, 60, 3600, 60, false, 1, true, true);
+ const DNSDistPacketCache::CacheSettings settings{
+ .d_maxEntries = 150000,
+ .d_maxTTL = 86400,
+ .d_minTTL = 1,
+ .d_tempFailureTTL = 60,
+ .d_maxNegativeTTL = 3600,
+ .d_staleTTL = 60,
+ .d_shardCount = 1,
+ .d_dontAge = false,
+ .d_deferrableInsertLock = true,
+ .d_parseECS = true,
+ };
+ DNSDistPacketCache localCache(settings);
BOOST_CHECK_EQUAL(localCache.getSize(), 0U);
InternalQueryState ids;
BOOST_AUTO_TEST_CASE(test_PacketCacheInspection)
{
- const size_t maxEntries = 100;
- DNSDistPacketCache localCache(maxEntries, 86400, 1);
+ const DNSDistPacketCache::CacheSettings settings{
+ .d_maxEntries = 150000,
+ .d_maxTTL = 86400,
+ .d_minTTL = 1,
+ };
+ DNSDistPacketCache localCache(settings);
BOOST_CHECK_EQUAL(localCache.getSize(), 0U);
ComboAddress remote;
BOOST_AUTO_TEST_CASE(test_PacketCacheXFR)
{
- const size_t maxEntries = 150000;
- DNSDistPacketCache localCache(maxEntries, 86400, 1);
+ const DNSDistPacketCache::CacheSettings settings{
+ .d_maxEntries = 150000,
+ .d_maxTTL = 86400,
+ .d_minTTL = 1,
+ };
+ DNSDistPacketCache localCache(settings);
BOOST_CHECK_EQUAL(localCache.getSize(), 0U);
const std::set<QType> xfrTypes = {QType::AXFR, QType::IXFR};