]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Initial integration with recursor
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Wed, 22 Feb 2023 15:30:48 +0000 (16:30 +0100)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Mon, 3 Apr 2023 11:31:45 +0000 (13:31 +0200)
pdns/recursordist/pdns_recursor.cc
pdns/recursordist/rec-main.cc
pdns/recursordist/rec-main.hh
pdns/recursordist/rec-tcounters.hh
pdns/recursordist/rec_channel_rec.cc
pdns/recursordist/recpacketcache.cc
pdns/recursordist/recpacketcache.hh
pdns/recursordist/syncres.hh

index 69c70f5d7ed42fa16cb72521f72b31af69f5e6eb..071c09d201170629be1ebeea183141c263e63087 100644 (file)
@@ -49,8 +49,8 @@ thread_local ProtobufServersInfo t_outgoingProtobufServers;
 thread_local std::unique_ptr<MT_t> MT; // the big MTasker
 std::unique_ptr<MemRecursorCache> g_recCache;
 std::unique_ptr<NegCache> g_negCache;
+std::unique_ptr<RecursorPacketCache> g_packetCache;
 
-thread_local std::unique_ptr<RecursorPacketCache> t_packetCache;
 thread_local std::unique_ptr<FDMultiplexer> t_fdm;
 thread_local std::unique_ptr<addrringbuf_t> t_remotes, t_servfailremotes, t_largeanswerremotes, t_bogusremotes;
 thread_local std::unique_ptr<boost::circular_buffer<pair<DNSName, uint16_t>>> t_queryring, t_servfailqueryring, t_bogusqueryring;
@@ -1673,9 +1673,9 @@ void startDoResolve(void* p)
 #endif
     }
 
-    if (t_packetCache && !variableAnswer && !sr.wasVariable()) {
+    if (g_packetCache && !variableAnswer && !sr.wasVariable()) {
       minTTL = capPacketCacheTTL(*pw.getHeader(), minTTL, seenAuthSOA);
-      t_packetCache->insertResponsePacket(dc->d_tag, dc->d_qhash, std::move(dc->d_query), dc->d_mdp.d_qname,
+      g_packetCache->insertResponsePacket(dc->d_tag, dc->d_qhash, std::move(dc->d_query), dc->d_mdp.d_qname,
                                           dc->d_mdp.d_qtype, dc->d_mdp.d_qclass,
                                           string((const char*)&*packet.begin(), packet.size()),
                                           g_now.tv_sec,
@@ -1957,7 +1957,7 @@ bool checkForCacheHit(bool qnameParsed, unsigned int tag, const string& data,
                       string& response, uint32_t& qhash,
                       RecursorPacketCache::OptPBData& pbData, bool tcp, const ComboAddress& source, const ComboAddress& mappedSource)
 {
-  if (!t_packetCache) {
+  if (!g_packetCache) {
     return false;
   }
   bool cacheHit = false;
@@ -1965,10 +1965,10 @@ bool checkForCacheHit(bool qnameParsed, unsigned int tag, const string& data,
   vState valState;
 
   if (qnameParsed) {
-    cacheHit = t_packetCache->getResponsePacket(tag, data, qname, qtype, qclass, now.tv_sec, &response, &age, &valState, &qhash, &pbData, tcp);
+    cacheHit = g_packetCache->getResponsePacket(tag, data, qname, qtype, qclass, now.tv_sec, &response, &age, &valState, &qhash, &pbData, tcp);
   }
   else {
-    cacheHit = t_packetCache->getResponsePacket(tag, data, qname, &qtype, &qclass, now.tv_sec, &response, &age, &valState, &qhash, &pbData, tcp);
+    cacheHit = g_packetCache->getResponsePacket(tag, data, qname, &qtype, &qclass, now.tv_sec, &response, &age, &valState, &qhash, &pbData, tcp);
   }
 
   if (cacheHit) {
index 6b84332ba2b02127f9c5eeadeed8ac0cd2e5fb6f..4720cca1b3f8590c42b5f6086e82a2cb1f2acfb3 100644 (file)
@@ -992,8 +992,8 @@ static void doStats(void)
   auto taskPushes = getTaskPushes();
   auto taskExpired = getTaskExpired();
   auto taskSize = getTaskSize();
-  uint64_t pcSize = broadcastAccFunction<uint64_t>(pleaseGetPacketCacheSize);
-  uint64_t pcHits = broadcastAccFunction<uint64_t>(pleaseGetPacketCacheHits);
+  uint64_t pcSize = g_packetCache ? g_packetCache->size() : 0;
+  uint64_t pcHits = g_packetCache ? g_packetCache->getHits() : 0;
 
   auto log = g_slog->withName("stats");
 
@@ -2139,14 +2139,6 @@ static void houseKeeping(void*)
     t_Counters.updateSnap(now, g_regressionTestMode);
 
     // Below are the tasks that run for every recursorThread, including handler and taskThread
-    if (t_packetCache) {
-      static thread_local PeriodicTask packetCacheTask{"packetCacheTask", 5};
-      packetCacheTask.runIfDue(now, []() {
-        size_t sz = g_maxPacketCacheEntries / (RecThreadInfo::numWorkers() + RecThreadInfo::numDistributors());
-        t_packetCache->setMaxSize(sz); // g_maxPacketCacheEntries might have changed by rec_control
-        t_packetCache->doPruneTo(sz);
-      });
-    }
 
     static thread_local PeriodicTask pruneTCPTask{"pruneTCPTask", 5};
     pruneTCPTask.runIfDue(now, [now]() {
@@ -2184,6 +2176,13 @@ static void houseKeeping(void*)
       });
     }
     else if (info.isHandler()) {
+      if (g_packetCache) {
+        static PeriodicTask packetCacheTask{"packetCacheTask", 5};
+        packetCacheTask.runIfDue(now, []() {
+          g_packetCache->setMaxSize(g_maxPacketCacheEntries); // g_maxPacketCacheEntries might have changed by rec_control
+          g_packetCache->doPruneTo(g_maxPacketCacheEntries);
+        });
+      }
       static PeriodicTask recordCachePruneTask{"RecordCachePruneTask", 5};
       recordCachePruneTask.runIfDue(now, []() {
         g_recCache->doPrune(g_maxCacheEntries);
@@ -2362,11 +2361,6 @@ static void recursorThread()
       }
     }
 
-    if (!::arg().mustDo("disable-packetcache") && (threadInfo.isDistributor() || threadInfo.isWorker())) {
-      // Only enable packet cache for thread processing queries from the outside world
-      t_packetCache = std::make_unique<RecursorPacketCache>(g_maxPacketCacheEntries / (RecThreadInfo::numWorkers() + RecThreadInfo::numDistributors()));
-    }
-
 #ifdef NOD_ENABLED
     if (threadInfo.isWorker())
       setupNODThread(log);
@@ -3035,6 +3029,10 @@ int main(int argc, char** argv)
 
     g_recCache = std::make_unique<MemRecursorCache>(::arg().asNum("record-cache-shards"));
     g_negCache = std::make_unique<NegCache>(::arg().asNum("record-cache-shards") / 8);
+    if (!::arg().mustDo("disable-packetcache")) {
+      // Only enable packet cache for thread processing queries from the outside world
+      g_packetCache = std::make_unique<RecursorPacketCache>(g_maxPacketCacheEntries /*, shards */);
+    }
 
     ret = serviceMain(argc, argv, startupLog);
   }
@@ -3126,11 +3124,6 @@ string doTraceRegex(FDWrapper file, vector<string>::const_iterator begin, vector
   return broadcastAccFunction<string>([=] { return pleaseUseNewTraceRegex(begin != end ? *begin : "", fileno); });
 }
 
-static uint64_t* pleaseWipePacketCache(const DNSName& canon, bool subtree, uint16_t qtype)
-{
-  return new uint64_t(t_packetCache ? t_packetCache->doWipePacketCache(canon, qtype, subtree) : 0);
-}
-
 struct WipeCacheResult wipeCaches(const DNSName& canon, bool subtree, uint16_t qtype)
 {
   struct WipeCacheResult res;
@@ -3138,7 +3131,9 @@ struct WipeCacheResult wipeCaches(const DNSName& canon, bool subtree, uint16_t q
   try {
     res.record_count = g_recCache->doWipeCache(canon, subtree, qtype);
     // scanbuild complains here about an allocated function object that is being leaked. Needs investigation
-    res.packet_count = broadcastAccFunction<uint64_t>([=] { return pleaseWipePacketCache(canon, subtree, qtype); });
+    if (g_packetCache) {
+      res.packet_count = g_packetCache->doWipePacketCache(canon, qtype, subtree);
+    }
     res.negative_record_count = g_negCache->wipe(canon, subtree);
     if (g_aggressiveNSECCache) {
       g_aggressiveNSECCache->removeZoneInfo(canon, subtree);
index 1a1c9ee63006433784eea535eb3adc66b9e9e7a9..72ded229e7dd92dbb097e118cdb23a9cbf6afc0e 100644 (file)
@@ -187,7 +187,7 @@ enum class PaddingMode
 
 typedef MTasker<std::shared_ptr<PacketID>, PacketBuffer, PacketIDCompare> MT_t;
 extern thread_local std::unique_ptr<MT_t> MT; // the big MTasker
-extern thread_local std::unique_ptr<RecursorPacketCache> t_packetCache;
+extern std::unique_ptr<RecursorPacketCache> g_packetCache;
 
 using RemoteLoggerStats_t = std::unordered_map<std::string, RemoteLoggerInterface::Stats>;
 
index 7d59bde46cfc91d4429d444c13bf65a45be438d6..db5b3111924081fececf298ce8defa2d3da7b6d3 100644 (file)
@@ -95,6 +95,8 @@ enum class Counter : uint8_t
   maintenanceUsec,
   maintenanceCalls,
 
+  pcHits,
+  pcMisses,
   numberOfCounters
 };
 
index 2766c7cf5741e42f8faeb5c7778cd2589879b257..9bbc49df6e099baf523fdf3dc5657bac006e61ff 100644 (file)
@@ -334,11 +334,6 @@ static uint64_t dumpAggressiveNSECCache(int fd)
   return g_aggressiveNSECCache->dumpToFile(fp, now);
 }
 
-static uint64_t* pleaseDump(int fd)
-{
-  return new uint64_t(t_packetCache ? t_packetCache->doDump(fd) : 0);
-}
-
 static uint64_t* pleaseDumpEDNSMap(int fd)
 {
   return new uint64_t(SyncRes::doEDNSDump(fd));
@@ -416,7 +411,8 @@ static RecursorControlChannel::Answer doDumpCache(int s)
   uint64_t total = 0;
   try {
     int fd = fdw;
-    total = g_recCache->doDump(fd, g_maxCacheEntries.load()) + g_negCache->doDump(fd, g_maxCacheEntries.load() / 8) + broadcastAccFunction<uint64_t>([fd] { return pleaseDump(fd); }) + dumpAggressiveNSECCache(fd);
+    total = g_recCache->doDump(fd, g_maxCacheEntries.load()) + g_negCache->doDump(fd, g_maxCacheEntries.load() / 8) +
+      (g_packetCache ? g_packetCache->doDump(fd) : 0) + dumpAggressiveNSECCache(fd);
   }
   catch (...) {
   }
@@ -1078,46 +1074,6 @@ static uint64_t doGetCacheMisses()
   return g_recCache->cacheMisses;
 }
 
-uint64_t* pleaseGetPacketCacheSize()
-{
-  return new uint64_t(t_packetCache ? t_packetCache->size() : 0);
-}
-
-static uint64_t* pleaseGetPacketCacheBytes()
-{
-  return new uint64_t(t_packetCache ? t_packetCache->bytes() : 0);
-}
-
-static uint64_t doGetPacketCacheSize()
-{
-  return broadcastAccFunction<uint64_t>(pleaseGetPacketCacheSize);
-}
-
-static uint64_t doGetPacketCacheBytes()
-{
-  return broadcastAccFunction<uint64_t>(pleaseGetPacketCacheBytes);
-}
-
-uint64_t* pleaseGetPacketCacheHits()
-{
-  return new uint64_t(t_packetCache ? t_packetCache->d_hits : 0);
-}
-
-static uint64_t doGetPacketCacheHits()
-{
-  return broadcastAccFunction<uint64_t>(pleaseGetPacketCacheHits);
-}
-
-static uint64_t* pleaseGetPacketCacheMisses()
-{
-  return new uint64_t(t_packetCache ? t_packetCache->d_misses : 0);
-}
-
-static uint64_t doGetPacketCacheMisses()
-{
-  return broadcastAccFunction<uint64_t>(pleaseGetPacketCacheMisses);
-}
-
 static uint64_t doGetMallocated()
 {
   // this turned out to be broken
@@ -1306,10 +1262,10 @@ static void registerAllStats1()
   addGetStat("record-cache-contended", []() { return g_recCache->stats().first; });
   addGetStat("record-cache-acquired", []() { return g_recCache->stats().second; });
 
-  addGetStat("packetcache-hits", doGetPacketCacheHits);
-  addGetStat("packetcache-misses", doGetPacketCacheMisses);
-  addGetStat("packetcache-entries", doGetPacketCacheSize);
-  addGetStat("packetcache-bytes", doGetPacketCacheBytes);
+  addGetStat("packetcache-hits", [] { return g_packetCache ? g_packetCache->getHits() : 0; });
+  addGetStat("packetcache-misses", [] { return g_packetCache ? g_packetCache->getMisses() : 0; });
+  addGetStat("packetcache-entries", [] { return g_packetCache ? g_packetCache->size() : 0; });
+  addGetStat("packetcache-bytes", [] { return g_packetCache ? g_packetCache->bytes() : 0; });;
 
   addGetStat("aggressive-nsec-cache-entries", []() { return g_aggressiveNSECCache ? g_aggressiveNSECCache->getEntriesCount() : 0; });
   addGetStat("aggressive-nsec-cache-nsec-hits", []() { return g_aggressiveNSECCache ? g_aggressiveNSECCache->getNSECHits() : 0; });
index 054efc9714620d71fcf40bcc439cb5080e84f88a..10fa9cbd1d9ea8adfae8ed4002ce1a0d13ea84ff 100644 (file)
 
 unsigned int RecursorPacketCache::s_refresh_ttlperc{0};
 
+uint64_t RecursorPacketCache::size() const
+{
+  uint64_t count = 0;
+  for (const auto& map : d_maps) {
+    count += map.d_entriesCount;
+  }
+  return count;
+}
+
+uint64_t RecursorPacketCache::bytes()
+{
+  uint64_t sum = 0;
+  for (auto& shard : d_maps) {
+    auto lock = shard.lock();
+    for (const auto& entry : lock->d_map) {
+      sum += sizeof(entry) + entry.d_packet.length() + 4;
+    }
+  }
+  return sum;
+}
+
+uint64_t RecursorPacketCache::getHits()
+{
+  uint64_t sum = 0;
+  for (auto& shard : d_maps) {
+    auto lock = shard.lock();
+    sum += lock->d_hits;
+  }
+  return sum;
+}
+
+uint64_t RecursorPacketCache::getMisses()
+{
+  uint64_t sum = 0;
+  for (auto& shard : d_maps) {
+    auto lock = shard.lock();
+    sum += lock->d_misses;
+  }
+  return sum;
+}
+
 uint64_t RecursorPacketCache::doWipePacketCache(const DNSName& name, uint16_t qtype, bool subtree)
 {
   uint64_t count = 0;
@@ -53,7 +94,7 @@ bool RecursorPacketCache::qrMatch(const packetCache_t::index<HashTag>::type::ite
   return queryMatches(iter->d_query, queryPacket, qname, optionsToSkip);
 }
 
-bool RecursorPacketCache::checkResponseMatches(packetCache_t& shard, std::pair<packetCache_t::index<HashTag>::type::iterator, packetCache_t::index<HashTag>::type::iterator> range, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, vState* valState, OptPBData* pbdata)
+bool RecursorPacketCache::checkResponseMatches(MapCombo::LockedContent& shard, std::pair<packetCache_t::index<HashTag>::type::iterator, packetCache_t::index<HashTag>::type::iterator> range, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, vState* valState, OptPBData* pbdata)
 {
   for (auto iter = range.first; iter != range.second; ++iter) {
     // the possibility is VERY real that we get hits that are not right - birthday paradox
@@ -82,8 +123,8 @@ bool RecursorPacketCache::checkResponseMatches(packetCache_t& shard, std::pair<p
         responsePacket->replace(sizeof(dnsheader), wirelength, queryPacket, sizeof(dnsheader), wirelength);
       }
 
-      d_hits++;
-      moveCacheItemToBack<SequencedTag>(shard, iter);
+      shard.d_hits++;
+      moveCacheItemToBack<SequencedTag>(shard.d_map, iter);
 
       if (pbdata != nullptr) {
         if (iter->d_pbdata) {
@@ -98,7 +139,7 @@ bool RecursorPacketCache::checkResponseMatches(packetCache_t& shard, std::pair<p
     }
     // We used to move the item to the front of "the to be deleted" sequence,
     // but we very likely will update the entry very soon, so leave it
-    d_misses++;
+    shard.d_misses++;
     break;
   }
 
@@ -111,34 +152,36 @@ bool RecursorPacketCache::getResponsePacket(unsigned int tag, const std::string&
                                             std::string* responsePacket, uint32_t* age, vState* valState, uint32_t* qhash, OptPBData* pbdata, bool tcp)
 {
   *qhash = canHashPacket(queryPacket, s_skipOptions);
-  auto shard = getMap(tag, *qhash, tcp).lock();
+  auto& map = getMap(tag, *qhash, tcp);
+  auto shard = map.lock();
   const auto& idx = shard->d_map.get<HashTag>();
   auto range = idx.equal_range(std::tie(tag, *qhash, tcp));
 
   if (range.first == range.second) {
-    d_misses++;
+    shard->d_misses++;
     return false;
   }
 
-  return checkResponseMatches(shard->d_map, range, queryPacket, qname, qtype, qclass, now, responsePacket, age, valState, pbdata);
+  return checkResponseMatches(*shard, range, queryPacket, qname, qtype, qclass, now, responsePacket, age, valState, pbdata);
 }
 
 bool RecursorPacketCache::getResponsePacket(unsigned int tag, const std::string& queryPacket, DNSName& qname, uint16_t* qtype, uint16_t* qclass, time_t now,
                                             std::string* responsePacket, uint32_t* age, vState* valState, uint32_t* qhash, OptPBData* pbdata, bool tcp)
 {
   *qhash = canHashPacket(queryPacket, s_skipOptions);
-  auto shard = getMap(tag, *qhash, tcp).lock();
+  auto& map = getMap(tag, *qhash, tcp);
+  auto shard = map.lock();
   const auto& idx = shard->d_map.get<HashTag>();
   auto range = idx.equal_range(std::tie(tag, *qhash, tcp));
 
   if (range.first == range.second) {
-    d_misses++;
+    shard->d_misses++;
     return false;
   }
 
   qname = DNSName(queryPacket.c_str(), static_cast<int>(queryPacket.length()), sizeof(dnsheader), false, qtype, qclass);
 
-  return checkResponseMatches(shard->d_map, range, queryPacket, qname, *qtype, *qclass, now, responsePacket, age, valState, pbdata);
+  return checkResponseMatches(*shard, range, queryPacket, qname, *qtype, *qclass, now, responsePacket, age, valState, pbdata);
 }
 
 void RecursorPacketCache::insertResponsePacket(unsigned int tag, uint32_t qhash, std::string&& query, const DNSName& qname, uint16_t qtype, uint16_t qclass, std::string&& responsePacket, time_t now, uint32_t ttl, const vState& valState, OptPBData&& pbdata, bool tcp)
@@ -184,18 +227,6 @@ void RecursorPacketCache::insertResponsePacket(unsigned int tag, uint32_t qhash,
   assert(map.d_entriesCount == shard->d_map.size()); // XXX
 }
 
-uint64_t RecursorPacketCache::bytes()
-{
-  uint64_t sum = 0;
-  for (auto& shard : d_maps) {
-    auto lock = shard.lock();
-    for (const auto& entry : lock->d_map) {
-      sum += sizeof(entry) + entry.d_packet.length() + 4;
-    }
-  }
-  return sum;
-}
-
 void RecursorPacketCache::doPruneTo(size_t maxSize)
 {
   size_t cacheSize = size();
index 72f58d526ac62660d105bf28297fed14ddbf9ba8..8ebc46ecd4cd2913996b768f01c30bb786c54922 100644 (file)
@@ -95,18 +95,10 @@ public:
     d_maxSize = size;
   }
 
-  [[nodiscard]] uint64_t size() const
-  {
-    uint64_t count = 0;
-    for (const auto& map : d_maps) {
-      count += map.d_entriesCount;
-    }
-    return count;
-  }
+  [[nodiscard]] uint64_t size() const;
   [[nodiscard]] uint64_t bytes();
-
-  uint64_t d_hits{0};
-  uint64_t d_misses{0};
+  [[nodiscard]] uint64_t getHits();
+  [[nodiscard]] uint64_t getMisses();
 
 private:
   struct Entry
@@ -169,6 +161,8 @@ private:
     struct LockedContent
     {
       packetCache_t d_map;
+      uint64_t d_hits{0};
+      uint64_t d_misses{0};
       uint64_t d_contended_count{0};
       uint64_t d_acquired_count{0};
       void invalidate() {}
@@ -213,7 +207,7 @@ private:
   size_t d_maxSize;
 
   static bool qrMatch(const packetCache_t::index<HashTag>::type::iterator& iter, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass);
-  bool checkResponseMatches(packetCache_t& shard, std::pair<packetCache_t::index<HashTag>::type::iterator, packetCache_t::index<HashTag>::type::iterator> range, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, vState* valState, OptPBData* pbdata);
+bool checkResponseMatches(MapCombo::LockedContent& shard, std::pair<packetCache_t::index<HashTag>::type::iterator, packetCache_t::index<HashTag>::type::iterator> range, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, vState* valState, OptPBData* pbdata);
 public:
   void preRemoval(MapCombo::LockedContent& map, const Entry& entry)
   {
index 496ea28efea150c7982f27e46b52497f61fc2281..fef7b96178b2c2cef26e7e801855b15b4dd2a45b 100644 (file)
@@ -922,8 +922,6 @@ uint64_t* pleaseGetNsSpeedsSize();
 uint64_t* pleaseGetFailedServersSize();
 uint64_t* pleaseGetConcurrentQueries();
 uint64_t* pleaseGetThrottleSize();
-uint64_t* pleaseGetPacketCacheHits();
-uint64_t* pleaseGetPacketCacheSize();
 void doCarbonDump(void*);
 bool primeHints(time_t now = time(nullptr));
 const char* isoDateTimeMillis(const struct timeval& tv, char* buf, size_t sz);