]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Move edns table to a shared table
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Mon, 2 May 2022 09:32:15 +0000 (11:32 +0200)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Fri, 17 Jun 2022 08:33:19 +0000 (10:33 +0200)
pdns/rec_channel_rec.cc
pdns/recursordist/rec-main.cc
pdns/syncres.cc
pdns/syncres.hh

index 1f76636a02391f0f32acfcd213b4efd692a59bc1..09219c1644d3950c377cbf2020c00a75799db138 100644 (file)
@@ -971,11 +971,6 @@ static uint64_t getNegCacheSize()
   return g_negCache->size();
 }
 
-uint64_t* pleaseGetEDNSStatusesSize()
-{
-  return new uint64_t(SyncRes::getEDNSStatusesSize());
-}
-
 uint64_t* pleaseGetConcurrentQueries()
 {
   return new uint64_t(getMT() ? getMT()->numProcesses() : 0);
@@ -1977,7 +1972,7 @@ RecursorControlChannel::Answer RecursorControlParser::getAnswer(int s, const str
     return doDumpToFile(s, pleaseDumpDoTProbeMap, cmd, false);
   }
   if (cmd == "dump-ednsstatus" || cmd == "dump-edns") {
-    return doDumpToFile(s, pleaseDumpEDNSMap, cmd);
+    return doDumpToFile(s, pleaseDumpEDNSMap, cmd, false);
   }
   if (cmd == "dump-nsspeeds") {
     return doDumpToFile(s, pleaseDumpNSSpeeds, cmd, false);
index 07d9e94dd607d8e7af7c690e15aface08016246e..f07d29939c41728fb9dd8e1ebdeeabb02932e809 100644 (file)
@@ -984,7 +984,7 @@ static void doStats(void)
             << SyncRes::getThrottledServersSize() << ", ns speeds: "
             << SyncRes::getNSSpeedsSize() << ", failed ns: "
             << SyncRes::getFailedServersSize() << ", ednsmap: "
-            << broadcastAccFunction<uint64_t>(pleaseGetEDNSStatusesSize) << ", non-resolving: "
+            << SyncRes::getEDNSStatusesSize() << ", non-resolving: "
             << SyncRes::getNonResolvingNSSize() << ", saved-parentsets: "
             << SyncRes::getSaveParentsNSSetsSize()
             << endl;
@@ -1010,7 +1010,7 @@ static void doStats(void)
                 "throttle-entries", Logging::Loggable(SyncRes::getThrottledServersSize()),
                 "nsspeed-entries", Logging::Loggable(SyncRes::getNSSpeedsSize()),
                 "failed-host-entries", Logging::Loggable(SyncRes::getFailedServersSize()),
-                "edns-entries", Logging::Loggable(broadcastAccFunction<uint64_t>(pleaseGetEDNSStatusesSize)),
+                "edns-entries", Logging::Loggable(SyncRes::getEDNSStatusesSize()),
                 "non-resolving-nameserver-entries", Logging::Loggable(SyncRes::getNonResolvingNSSize()),
                 "saved-parent-ns-sets-entries", Logging::Loggable(SyncRes::getSaveParentsNSSetsSize()),
                 "outqueries-per-query", Logging::Loggable(ratePercentage(SyncRes::s_outqueries, SyncRes::s_queries)));
@@ -2069,11 +2069,6 @@ static void houseKeeping(void*)
       });
     }
 
-    static thread_local PeriodicTask pruneEDNSTask{"pruneEDNSTask", 5}; // period could likely be longer
-    pruneEDNSTask.runIfDue(now, [now]() {
-      SyncRes::pruneEDNSStatuses(now.tv_sec - 2 * 3600);
-    });
-
     static thread_local PeriodicTask pruneTCPTask{"pruneTCPTask", 5};
     pruneTCPTask.runIfDue(now, [now]() {
       t_tcp_manager.cleanup(now);
@@ -2120,6 +2115,11 @@ static void houseKeeping(void*)
         SyncRes::pruneNSSpeeds(now.tv_sec - 300);
       });
 
+      static PeriodicTask pruneEDNSTask{"pruneEDNSTask", 5}; // period could likely be longer
+      pruneEDNSTask.runIfDue(now, [now]() {
+        SyncRes::pruneEDNSStatuses(now.tv_sec - 2 * 3600);
+      });
+
       if (SyncRes::s_max_busy_dot_probes > 0) {
         static PeriodicTask pruneDoTProbeMap{"pruneDoTProbeMapTask", 60};
         pruneDoTProbeMap.runIfDue(now, [now]() {
index dd8d494c92b067f16baabbe7128acb047d7d1586..3bf06b4d4185a4891d99d345480d8d3ec76354de 100644 (file)
@@ -1060,6 +1060,67 @@ static const char* timestamp(time_t t, char* buf, size_t sz)
   return buf;
 }
 
+struct ednsstatus_t : public multi_index_container<SyncRes::EDNSStatus,
+                                                   indexed_by<
+                                                     ordered_unique<tag<ComboAddress>, member<SyncRes::EDNSStatus, ComboAddress, &SyncRes::EDNSStatus::address>>,
+                                                     ordered_non_unique<tag<time_t>, member<SyncRes::EDNSStatus, time_t, &SyncRes::EDNSStatus::modeSetAt>>
+                                                     >>
+{
+  // Get a copy
+  ednsstatus_t getMap() const
+  {
+    return *this;
+  }
+
+  void reset(index<ComboAddress>::type &ind, iterator it)
+  {
+    ind.modify(it, [](SyncRes::EDNSStatus &s) { s.mode = SyncRes::EDNSStatus::EDNSMode::UNKNOWN; s.modeSetAt = 0; });
+  }
+
+  void setMode(index<ComboAddress>::type &ind, iterator it, SyncRes::EDNSStatus::EDNSMode mode)
+  {
+    it->mode = mode;
+  }
+
+  void setTS(index<ComboAddress>::type &ind, iterator it, time_t ts)
+  {
+    ind.modify(it, [ts](SyncRes::EDNSStatus &s) { s.modeSetAt = ts; });
+  }
+
+  void prune(time_t cutoff)
+  {
+    auto &ind = get<time_t>();
+    ind.erase(ind.begin(), ind.upper_bound(cutoff));
+  }
+};
+
+static LockGuarded<ednsstatus_t> s_ednsstatus;
+
+SyncRes::EDNSStatus::EDNSMode SyncRes::getEDNSStatus(const ComboAddress& server)
+{
+  auto lock = s_ednsstatus.lock();
+  const auto& it = lock->find(server);
+  if (it == lock->end()) {
+    return EDNSStatus::UNKNOWN;
+  }
+  return it->mode;
+}
+
+uint64_t SyncRes::getEDNSStatusesSize()
+{
+  return s_ednsstatus.lock()->size();
+}
+
+void SyncRes::clearEDNSStatuses()
+{
+  s_ednsstatus.lock()->clear();
+}
+
+void SyncRes::pruneEDNSStatuses(time_t cutoff)
+{
+  s_ednsstatus.lock()->prune(cutoff);
+}
+
 uint64_t SyncRes::doEDNSDump(int fd)
 {
   int newfd = dup(fd);
@@ -1073,11 +1134,12 @@ uint64_t SyncRes::doEDNSDump(int fd)
   }
   uint64_t count = 0;
 
-  fprintf(fp.get(),"; edns from thread follows\n;\n");
-  for(const auto& eds : t_sstorage.ednsstatus) {
+  fprintf(fp.get(),"; edns dump follows\n;\n");
+  const auto copy = s_ednsstatus.lock()->getMap();
+  for (const auto& eds : copy) {
     count++;
     char tmp[26];
-    fprintf(fp.get(), "%s\t%d\t%s\n", eds.address.toString().c_str(), (int)eds.mode, timestamp(eds.modeSetAt, tmp, sizeof(tmp)));
+    fprintf(fp.get(), "%s\t%s\t%s\n", eds.address.toString().c_str(), eds.toString().c_str(), timestamp(eds.modeSetAt, tmp, sizeof(tmp)));
   }
   return count;
 }
@@ -1414,26 +1476,30 @@ LWResult::Result SyncRes::asyncresolveWrapper(const ComboAddress& ip, bool ednsM
      2) EDNSIGNORANT: Ignores EDNS0, gives replies without EDNS0
      3) NOEDNS: Generates FORMERR on EDNS queries
 
-     Everybody starts out assumed to be '0'.
-     If '0', send out EDNS0
-        If you FORMERR us, go to '3',
-        If no EDNS in response, go to '2'
-     If '1', send out EDNS0
-        If FORMERR, downgrade to 3
-     If '2', keep on including EDNS0, see what happens
-        Same behaviour as 0
-     If '3', send bare queries
+     Everybody starts out assumed to be UNKNOWN.
+     If UNKNOWN, send out EDNS0
+        If you FORMERR us, go to NOEDNS, 
+        If no EDNS in response, go to EDNSIGNORANT
+     If EDNSOK, send out EDNS0
+        If FORMERR, downgrade to NOEDNS
+     If EDNSIGNORANT, keep on including EDNS0, see what happens
+        Same behaviour as UNKNOWN
+     If NOEDNS, send bare queries
   */
 
-  auto ednsstatus = t_sstorage.ednsstatus.insert(ip).first; // does this include port? YES
-  auto &ind = t_sstorage.ednsstatus.get<ComboAddress>();
-  if (ednsstatus->modeSetAt && ednsstatus->modeSetAt + 3600 < d_now.tv_sec) {
-    t_sstorage.ednsstatus.reset(ind, ednsstatus);
-    //    cerr<<"Resetting EDNS Status for "<<ip.toString()<<endl);
+  SyncRes::EDNSStatus::EDNSMode mode;
+  {
+    auto lock = s_ednsstatus.lock();
+    auto ednsstatus = lock->insert(ip).first; // does this include port? YES
+    auto &ind = lock->get<ComboAddress>();
+    if (ednsstatus->modeSetAt && ednsstatus->modeSetAt + 3600 < d_now.tv_sec) {
+      lock->reset(ind, ednsstatus);
+      // cerr<<"Resetting EDNS Status for "<<ip.toString()<<endl);
+    }
+    mode = ednsstatus->mode;
   }
 
-  const SyncRes::EDNSStatus::EDNSMode *mode = &ednsstatus->mode;
-  const SyncRes::EDNSStatus::EDNSMode oldmode = *mode;
+  const SyncRes::EDNSStatus::EDNSMode oldmode = mode;
   int EDNSLevel = 0;
   auto luaconfsLocal = g_luaconfs.getLocal();
   ResolveContext ctx;
@@ -1444,19 +1510,21 @@ LWResult::Result SyncRes::asyncresolveWrapper(const ComboAddress& ip, bool ednsM
 #endif
 
   LWResult::Result ret;
-  for(int tries = 0; tries < 3; ++tries) {
-    //    cerr<<"Remote '"<<ip.toString()<<"' currently in mode "<<mode<<endl;
 
-    if (*mode == EDNSStatus::NOEDNS) {
+  for (int tries = 0; tries < 3; ++tries) {
+
+    if (mode == EDNSStatus::NOEDNS) {
       g_stats.noEdnsOutQueries++;
       EDNSLevel = 0; // level != mode
     }
-    else if (ednsMANDATORY || *mode == EDNSStatus::UNKNOWN || *mode == EDNSStatus::EDNSOK || *mode == EDNSStatus::EDNSIGNORANT)
+    else if (ednsMANDATORY || mode != EDNSStatus::NOEDNS) {
       EDNSLevel = 1;
+    }
 
     DNSName sendQname(domain);
-    if (g_lowercaseOutgoing)
+    if (g_lowercaseOutgoing) {
       sendQname.makeUsLowerCase();
+    }
 
     if (d_asyncResolve) {
       ret = d_asyncResolve(ip, sendQname, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, res, chained);
@@ -1464,39 +1532,47 @@ LWResult::Result SyncRes::asyncresolveWrapper(const ComboAddress& ip, bool ednsM
     else {
       ret = asyncresolve(ip, sendQname, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, d_outgoingProtobufServers, d_frameStreamServers, luaconfsLocal->outgoingProtobufExportConfig.exportTypes, res, chained);
     }
-    // ednsstatus might be cleared, so do a new lookup
-    ednsstatus = t_sstorage.ednsstatus.insert(ip).first;
-    mode = &ednsstatus->mode;
+
     if (ret == LWResult::Result::PermanentError || ret == LWResult::Result::OSLimitError || ret == LWResult::Result::Spoofed) {
-      return ret; // transport error, nothing to learn here
+      break; // transport error, nothing to learn here
     }
 
     if (ret == LWResult::Result::Timeout) { // timeout, not doing anything with it now
-      return ret;
+      break;
     }
-    else if (*mode == EDNSStatus::UNKNOWN || *mode == EDNSStatus::EDNSOK || *mode == EDNSStatus::EDNSIGNORANT ) {
-      if(res->d_validpacket && !res->d_haveEDNS && res->d_rcode == RCode::FormErr)  {
-       //      cerr<<"Downgrading to NOEDNS because of "<<RCode::to_s(res->d_rcode)<<" for query to "<<ip.toString()<<" for '"<<domain<<"'"<<endl;
-        t_sstorage.ednsstatus.setMode(ind, ednsstatus, EDNSStatus::NOEDNS);
+
+    // ret is LWResult::Result::Success
+    // ednsstatus might be cleared, so do a new lookup/insert
+    auto lock = s_ednsstatus.lock();
+    auto ednsstatus = lock->insert(ip).first;
+    mode = ednsstatus->mode;
+    auto &ind = lock->get<ComboAddress>();
+
+    if (mode != EDNSStatus::NOEDNS) {
+      if (res->d_validpacket && !res->d_haveEDNS && res->d_rcode == RCode::FormErr)  {
+        mode = EDNSStatus::NOEDNS;
+        lock->setMode(ind, ednsstatus, mode);
         continue;
       }
-      else if(!res->d_haveEDNS) {
-        if (*mode != EDNSStatus::EDNSIGNORANT) {
-          t_sstorage.ednsstatus.setMode(ind, ednsstatus, EDNSStatus::EDNSIGNORANT);
-         //      cerr<<"We find that "<<ip.toString()<<" is an EDNS-ignorer for '"<<domain<<"', moving to mode 2"<<endl;
+      else if (!res->d_haveEDNS) {
+        if (mode != EDNSStatus::EDNSIGNORANT) {
+          mode =  EDNSStatus::EDNSIGNORANT;
+          lock->setMode(ind, ednsstatus, mode);
        }
       }
       else {
-        t_sstorage.ednsstatus.setMode(ind, ednsstatus, EDNSStatus::EDNSOK);
-       //      cerr<<"We find that "<<ip.toString()<<" is EDNS OK!"<<endl;
+       if (mode != EDNSStatus::EDNSOK) {
+          mode = EDNSStatus::EDNSOK;
+          lock->setMode(ind, ednsstatus, mode);
+        }
       }
     }
 
-    if (oldmode != *mode || !ednsstatus->modeSetAt) {
-      t_sstorage.ednsstatus.setTS(ind, ednsstatus, d_now.tv_sec);
+    if (oldmode != mode || !ednsstatus->modeSetAt) {
+      lock->setTS(ind, ednsstatus, d_now.tv_sec);
     }
-    //    cerr<<"Result: ret="<<ret<<", EDNS-level: "<<EDNSLevel<<", haveEDNS: "<<res->d_haveEDNS<<", new mode: "<<mode<<endl;
-    return LWResult::Result::Success;
+
+    break;
   }
   return ret;
 }
index 2210560792c2641e2a17ed11ceb351d3906d451e..b2ad364f43df591d4e0e5e67e407fe3b4d80b672 100644 (file)
@@ -144,37 +144,7 @@ public:
 
   typedef std::unordered_map<DNSName, AuthDomain> domainmap_t;
 
-  struct EDNSStatus {
-    EDNSStatus(const ComboAddress &arg) : address(arg) {}
-    ComboAddress address;
-    time_t modeSetAt{0};
-    mutable enum EDNSMode { UNKNOWN=0, EDNSOK=1, EDNSIGNORANT=2, NOEDNS=3 } mode{UNKNOWN};
-  };
-
-  struct ednsstatus_t : public multi_index_container<EDNSStatus,
-                                                     indexed_by<
-                                                       ordered_unique<tag<ComboAddress>, member<EDNSStatus, ComboAddress, &EDNSStatus::address>>,
-                                                       ordered_non_unique<tag<time_t>, member<EDNSStatus, time_t, &EDNSStatus::modeSetAt>>
-                                  >> {
-    void reset(index<ComboAddress>::type &ind, iterator it) {
-      ind.modify(it, [](EDNSStatus &s) { s.mode = EDNSStatus::EDNSMode::UNKNOWN; s.modeSetAt = 0; });
-    }
-    void setMode(index<ComboAddress>::type &ind, iterator it, EDNSStatus::EDNSMode mode) {
-      it->mode = mode;
-    }
-    void setTS(index<ComboAddress>::type &ind, iterator it, time_t ts) {
-      ind.modify(it, [ts](EDNSStatus &s) { s.modeSetAt = ts; });
-    }
-
-    void prune(time_t cutoff) {
-      auto &ind = get<time_t>();
-      ind.erase(ind.begin(), ind.upper_bound(cutoff));
-    }
-
-  };
-
   struct ThreadLocalStorage {
-    ednsstatus_t ednsstatus;
     std::shared_ptr<domainmap_t> domainmap;
   };
 
@@ -242,26 +212,27 @@ public:
   static void clearNSSpeeds();
   static float getNSSpeed(const DNSName& server, const ComboAddress& ca);
 
-  static EDNSStatus::EDNSMode getEDNSStatus(const ComboAddress& server)
-  {
-    const auto& it = t_sstorage.ednsstatus.find(server);
-    if (it == t_sstorage.ednsstatus.end())
-      return EDNSStatus::UNKNOWN;
+  struct EDNSStatus {
+    EDNSStatus(const ComboAddress &arg) : address(arg) {}
+    ComboAddress address;
+    time_t modeSetAt{0};
+    mutable enum EDNSMode : uint8_t { UNKNOWN = 0, EDNSOK = 1, EDNSIGNORANT = 2, NOEDNS = 3 } mode{UNKNOWN};
 
-    return it->mode;
-  }
-  static uint64_t getEDNSStatusesSize()
-  {
-    return t_sstorage.ednsstatus.size();
-  }
-  static void clearEDNSStatuses()
-  {
-    t_sstorage.ednsstatus.clear();
-  }
-  static void pruneEDNSStatuses(time_t cutoff)
-  {
-    t_sstorage.ednsstatus.prune(cutoff);
-  }
+    std::string toString() const
+    {
+      const std::array<std::string,4> modes = { "Unknown", "OK", "Ignorant", "NoEDNS" };
+      unsigned int m = static_cast<unsigned int>(mode);
+      if (m >= modes.size()) {
+        return "?";
+      }
+      return modes.at(m);
+    }
+  };
+
+  static EDNSStatus::EDNSMode getEDNSStatus(const ComboAddress& server);
+  static uint64_t getEDNSStatusesSize();
+  static void clearEDNSStatuses();
+  static void pruneEDNSStatuses(time_t cutoff);
 
   static uint64_t getThrottledServersSize();
   static void pruneThrottledServers(time_t now);
@@ -929,7 +900,6 @@ void* pleaseSupplantAllowNotifyFor(std::shared_ptr<notifyset_t> ns);
 
 uint64_t* pleaseGetNsSpeedsSize();
 uint64_t* pleaseGetFailedServersSize();
-uint64_t* pleaseGetEDNSStatusesSize();
 uint64_t* pleaseGetConcurrentQueries();
 uint64_t* pleaseGetThrottleSize();
 uint64_t* pleaseGetPacketCacheHits();