]> granicus.if.org Git - pdns/commitdiff
implement max-tot-msec wallclock time limit per query (needs docs)
authorbert hubert <bert.hubert@netherlabs.nl>
Wed, 21 Jan 2015 11:21:38 +0000 (12:21 +0100)
committerbert hubert <bert.hubert@netherlabs.nl>
Wed, 21 Jan 2015 11:21:38 +0000 (12:21 +0100)
pdns/lwres.cc
pdns/lwres.hh
pdns/pdns_recursor.cc
pdns/syncres.cc
pdns/syncres.hh

index aa863bdffe09653f05f6f400c37bbacd968132c2..90b3e8a0bbdebe2e4402ca8470d9d926424e81c5 100644 (file)
@@ -78,7 +78,6 @@ int asyncresolve(const ComboAddress& ip, const string& domain, int type, bool do
   lwr->d_rcode = 0;
   lwr->d_pingCorrect = false;
   lwr->d_haveEDNS = false;
-
   int ret;
 
   DTime dt;
index db9aac708455f45464367cb168358bcd7388558b..0d43249c8f8051dee5f7badd0a657a89d73639ce 100644 (file)
@@ -56,6 +56,7 @@ public:
 class LWResult
 {
 public:
+  LWResult() : d_usec(0) {}
   typedef vector<DNSResourceRecord> res_t;
 
   vector<DNSResourceRecord> d_result;
index c47440a1094e8684ec9c38c76aabfc0dee52cc3d..d036078d88090724fde60e68820a0855c41833d8 100644 (file)
@@ -737,7 +737,8 @@ void startDoResolve(void *p)
     if(!g_quiet) {
       L<<Logger::Error<<t_id<<" ["<<MT->getTid()<<"/"<<MT->numProcesses()<<"] answer to "<<(dc->d_mdp.d_header.rd?"":"non-rd ")<<"question '"<<dc->d_mdp.d_qname<<"|"<<DNSRecordContent::NumberToType(dc->d_mdp.d_qtype);
       L<<"': "<<ntohs(pw.getHeader()->ancount)<<" answers, "<<ntohs(pw.getHeader()->arcount)<<" additional, took "<<sr.d_outqueries<<" packets, "<<
-      sr.d_throttledqueries<<" throttled, "<<sr.d_timeouts<<" timeouts, "<<sr.d_tcpoutqueries<<" tcp connections, rcode="<<res<<endl;
+       sr.d_totUsec/1000.0<<" ms, "<<
+       sr.d_throttledqueries<<" throttled, "<<sr.d_timeouts<<" timeouts, "<<sr.d_tcpoutqueries<<" tcp connections, rcode="<<res<<endl;
     }
 
     sr.d_outqueries ? t_RC->cacheMisses++ : t_RC->cacheHits++; 
@@ -1975,6 +1976,7 @@ int serviceMain(int argc, char*argv[])
   SyncRes::s_serverdownthrottletime=::arg().asNum("server-down-throttle-time");
   SyncRes::s_serverID=::arg()["server-id"];
   SyncRes::s_maxqperq=::arg().asNum("max-qperq");
+  SyncRes::s_maxtotusec=1000*::arg().asNum("max-total-msec");
   if(SyncRes::s_serverID.empty()) {
     char tmp[128];
     gethostname(tmp, sizeof(tmp)-1);
@@ -2299,6 +2301,7 @@ int main(int argc, char **argv)
     ::arg().set("udp-truncation-threshold", "Maximum UDP response size before we truncate")="1680";
     ::arg().set("minimum-ttl-override", "Set under adverse conditions, a minimum TTL")="0";
     ::arg().set("max-qperq", "Maximum outgoing queries per query")="50";
+    ::arg().set("max-total-msec", "Maximum total wall-clock time per query in milliseconds, 0 for unlimited")="5000";
 
     ::arg().set("include-dir","Include *.conf files from this directory")="";
     ::arg().set("security-poll-suffix","Domain name from which to query security update notifications")="secpoll.powerdns.com.";
index c34b10e07d12bda5c08125be0844c6ae2fe25941..3c73a95b8c03c2fd193cbf2f8c7a52fe2ca16979 100644 (file)
@@ -64,6 +64,7 @@ unsigned int SyncRes::s_minimumTTL;
 bool SyncRes::s_doIPv6;
 bool SyncRes::s_nopacketcache;
 unsigned int SyncRes::s_maxqperq;
+unsigned int SyncRes::s_maxtotusec;
 string SyncRes::s_serverID;
 SyncRes::LogMode SyncRes::s_lm;
 
@@ -73,7 +74,7 @@ bool SyncRes::s_noEDNSPing;
 bool SyncRes::s_noEDNS;
 
 SyncRes::SyncRes(const struct timeval& now) :  d_outqueries(0), d_tcpoutqueries(0), d_throttledqueries(0), d_timeouts(0), d_unreachables(0),
-                                              d_now(now),
+                                              d_totUsec(0), d_now(now),
                                               d_cacheonly(false), d_nocache(false),   d_doEDNS0(false), d_lm(s_lm)
                                                  
 { 
@@ -939,6 +940,9 @@ int SyncRes::doResolveAt(set<string, CIStringCompare> nameservers, string auth,
               s_tcpoutqueries++; d_tcpoutqueries++;
             }
             
+           if(s_maxtotusec && d_totUsec > s_maxtotusec) 
+             throw ImmediateServFailException("Too much time waiting for "+qname+"|"+qtype.getName()+", timeouts: "+boost::lexical_cast<string>(d_timeouts) +", throttles: "+boost::lexical_cast<string>(d_throttledqueries) + ", "+lexical_cast<string>(d_totUsec/1000)+"msec");
+
            if(d_pdl && d_pdl->preoutquery(*remoteIP, d_requestor, qname, qtype, lwr.d_result, resolveret)) {
              LOG(prefix<<qname<<": query handled by Lua"<<endl);
            }
@@ -949,7 +953,7 @@ int SyncRes::doResolveAt(set<string, CIStringCompare> nameservers, string auth,
             if(resolveret==-3)
              throw ImmediateServFailException("Query killed by policy");
 
-
+           d_totUsec += lwr.d_usec;
            if(resolveret != 1) {
               if(resolveret==0) {
                 LOG(prefix<<qname<<": timeout resolving after "<<lwr.d_usec/1000.0<<"msec "<< (doTCP ? "over TCP" : "")<<endl);
index 8c03e08b3718e20dba5d8ec61d8e0a70d1f7e14a..d77023181017c177e75292f488fdc5e1de344fd8 100644 (file)
@@ -299,13 +299,14 @@ public:
   static unsigned int s_minimumTTL;
   static bool s_doIPv6;
   static unsigned int s_maxqperq;
+  static unsigned int s_maxtotusec;
   unsigned int d_outqueries;
   unsigned int d_tcpoutqueries;
   unsigned int d_throttledqueries;
   unsigned int d_timeouts;
   unsigned int d_unreachables;
+  unsigned int d_totUsec;
   ComboAddress d_requestor;
-  //  typedef map<string,NegCacheEntry> negcache_t;
 
   typedef multi_index_container <
     NegCacheEntry,