root/trunk/pdns/pdns/syncres.hh @ 1493

Revision 1493, 14.5 KB (checked in by ahu, 5 years ago)

add packetcache statistics, plus qps counter in statistics. remove edns stats since we stopped doing edns probing.

  • Property svn:eol-style set to native
  • Property svn:keywords set to author date id revision
Line 
1#ifndef PDNS_SYNCRES_HH
2#define PDNS_SYNCRES_HH
3#include <string>
4#include "dns.hh"
5#include "qtype.hh"
6#include <vector>
7#include <set>
8#include <map>
9#include <cmath>
10#include <iostream>
11#include <utility>
12#include "misc.hh"
13#include "lwres.hh"
14#include <boost/utility.hpp>
15#include "sstuff.hh"
16#include "recursor_cache.hh"
17#include "recpacketcache.hh"
18#include <boost/tuple/tuple.hpp>
19#include <boost/optional.hpp>
20#include <boost/tuple/tuple_comparison.hpp>
21#include "mtasker.hh"
22#include "iputils.hh"
23
24void primeHints(void);
25
26struct NegCacheEntry
27{
28  string d_name;
29  QType d_qtype;
30  string d_qname;
31  uint32_t d_ttd;
32};
33
34
35template<class Thing> class Throttle : public boost::noncopyable
36{
37public:
38  Throttle()
39  {
40    d_limit=3;
41    d_ttl=60;
42    d_last_clean=time(0);
43  }
44  bool shouldThrottle(time_t now, const Thing& t)
45  {
46    if(now > d_last_clean + 300 ) {
47
48      d_last_clean=now;
49      for(typename cont_t::iterator i=d_cont.begin();i!=d_cont.end();) {
50        if( i->second.ttd < now) {
51          d_cont.erase(i++);
52        }
53        else
54          ++i;
55      }
56    }
57
58    typename cont_t::iterator i=d_cont.find(t);
59    if(i==d_cont.end())
60      return false;
61    if(now > i->second.ttd || i->second.count-- < 0) {
62      d_cont.erase(i);
63    }
64
65    return true; // still listed, still blocked
66  }
67  void throttle(time_t now, const Thing& t, unsigned int ttl=0, unsigned int tries=0) 
68  {
69    typename cont_t::iterator i=d_cont.find(t);
70    entry e={ now+(ttl ? ttl : d_ttl), tries ? tries : d_limit};
71
72    if(i==d_cont.end()) {
73      d_cont[t]=e;
74    } 
75    else if(i->second.ttd > e.ttd || (i->second.count) < e.count) 
76      d_cont[t]=e;
77  }
78 
79  unsigned int size()
80  {
81    return (unsigned int)d_cont.size();
82  }
83private:
84  int d_limit;
85  int d_ttl;
86  time_t d_last_clean;
87  struct entry
88  {
89    time_t ttd;
90    int count;
91  };
92  typedef map<Thing,entry> cont_t;
93  cont_t d_cont;
94};
95
96
97/** Class that implements a decaying EWMA.
98    This class keeps an exponentially weighted moving average which, additionally, decays over time.
99    The decaying is only done on get.
100*/
101class DecayingEwma
102{
103public:
104  DecayingEwma() :  d_val(0.0) 
105  {
106    d_needinit=true;
107    d_last.tv_sec = d_last.tv_usec = 0;
108    d_lastget=d_last;
109  }
110
111  DecayingEwma(const DecayingEwma& orig) : d_last(orig.d_last),  d_lastget(orig.d_lastget), d_val(orig.d_val), d_needinit(orig.d_needinit)
112  {
113  }
114
115  struct timeval getOrMakeTime(struct timeval* tv)
116  {
117    if(tv)
118      return *tv;
119    else {
120      struct timeval ret;
121      Utility::gettimeofday(&ret, 0);
122      return ret;
123    }
124  }
125
126  void submit(int val, struct timeval* tv)
127  {
128    struct timeval now=getOrMakeTime(tv);
129
130    if(d_needinit) {
131      d_last=now;
132      d_needinit=false;
133    }
134
135    float diff= makeFloat(d_last - now);
136
137    d_last=now;
138    double factor=exp(diff)/2.0; // might be '0.5', or 0.0001
139    d_val=(float)((1-factor)*val+ (float)factor*d_val); 
140  }
141
142  double get(struct timeval* tv)
143  {
144    struct timeval now=getOrMakeTime(tv);
145    float diff=makeFloat(d_lastget-now);
146    d_lastget=now;
147    float factor=exp(diff/60.0f); // is 1.0 or less
148    return d_val*=factor;
149  }
150
151  bool stale(time_t limit) const
152  {
153    return limit > d_lastget.tv_sec;
154  }
155
156private:
157  struct timeval d_last;          // stores time
158  struct timeval d_lastget;       // stores time
159  float d_val;
160  bool d_needinit;
161};
162
163
164class SyncRes : public boost::noncopyable
165{
166public:
167  explicit SyncRes(const struct timeval& now) :  d_outqueries(0), d_tcpoutqueries(0), d_throttledqueries(0), d_timeouts(0), d_unreachables(0),
168                                                 d_now(now),
169                                                 d_cacheonly(false), d_nocache(false), d_doEDNS0(false) 
170  { 
171    if(!t_sstorage) {
172      t_sstorage = new StaticStorage();
173    }
174  }
175
176  int beginResolve(const string &qname, const QType &qtype, uint16_t qclass, vector<DNSResourceRecord>&ret);
177  void setId(int id)
178  {
179    if(s_log)
180      d_prefix="["+itoa(id)+"] ";
181  }
182  static void setLog(bool log)
183  {
184    s_log=log;
185  }
186  void setCacheOnly(bool state=true)
187  {
188    d_cacheonly=state;
189  }
190  void setNoCache(bool state=true)
191  {
192    d_nocache=state;
193  }
194
195  void setDoEDNS0(bool state=true)
196  {
197    d_doEDNS0=state;
198  }
199
200
201
202  int asyncresolveWrapper(const ComboAddress& ip, const string& domain, int type, bool doTCP, bool sendRDQuery, struct timeval* now, LWResult* res);
203 
204  static void doEDNSDumpAndClose(int fd);
205
206  static unsigned int s_queries;
207  static unsigned int s_outgoingtimeouts;
208  static unsigned int s_throttledqueries;
209  static unsigned int s_outqueries;
210  static unsigned int s_tcpoutqueries;
211  static unsigned int s_nodelegated;
212  static unsigned int s_unreachables;
213  static bool s_doIPv6;
214  unsigned int d_outqueries;
215  unsigned int d_tcpoutqueries;
216  unsigned int d_throttledqueries;
217  unsigned int d_timeouts;
218  unsigned int d_unreachables;
219
220  //  typedef map<string,NegCacheEntry> negcache_t;
221
222  typedef multi_index_container <
223    NegCacheEntry,
224    indexed_by <
225       ordered_unique<
226           composite_key<
227                 NegCacheEntry,
228                    member<NegCacheEntry, string, &NegCacheEntry::d_name>,
229                    member<NegCacheEntry, QType, &NegCacheEntry::d_qtype>
230           >,
231           composite_key_compare<CIStringCompare, std::less<QType> >
232       >,
233       ordered_non_unique<
234           member<NegCacheEntry, uint32_t, &NegCacheEntry::d_ttd>
235       >
236    >
237  > negcache_t;
238 
239  //! This represents a number of decaying Ewmas, used to store performance per namerserver-name.
240  /** Modelled to work mostly like the underlying DecayingEwma. After you've called get,
241      d_best is filled out with the best address for this collection */
242  struct DecayingEwmaCollection
243  {
244    void submit(const ComboAddress& remote, int usecs, struct timeval* now) 
245    {
246      collection_t::iterator pos;
247      for(pos=d_collection.begin(); pos != d_collection.end(); ++pos)
248        if(pos->first==remote)
249          break;
250      if(pos!=d_collection.end()) {
251        pos->second.submit(usecs, now);
252      }
253      else {
254        DecayingEwma de;
255        de.submit(usecs, now);
256        d_collection.push_back(make_pair(remote, de));
257      }
258    }
259
260    double get(struct timeval* now)
261    {
262      if(d_collection.empty())
263        return 0;
264      double ret=numeric_limits<double>::max();
265      double tmp;
266      for(collection_t::iterator pos=d_collection.begin(); pos != d_collection.end(); ++pos) {
267        if((tmp=pos->second.get(now)) < ret) {
268          ret=tmp;
269          d_best=pos->first;
270        }
271      }
272     
273      return ret;
274    }
275   
276    bool stale(time_t limit) const
277    {
278      for(collection_t::const_iterator pos=d_collection.begin(); pos != d_collection.end(); ++pos) 
279        if(!pos->second.stale(limit))
280          return false;
281      return true;
282    }
283
284    typedef vector<pair<ComboAddress, DecayingEwma> > collection_t;
285    collection_t d_collection;
286    ComboAddress d_best;
287  };
288
289  typedef map<string, DecayingEwmaCollection, CIStringCompare> nsspeeds_t;
290 
291
292  struct EDNSStatus
293  {
294    EDNSStatus() : mode(UNKNOWN), modeSetAt(0), EDNSPingHitCount(0) {}
295    enum EDNSMode { CONFIRMEDPINGER=-1, UNKNOWN=0, EDNSNOPING=1, EDNSPINGOK=2, EDNSIGNORANT=3, NOEDNS=4 } mode;
296    time_t modeSetAt;
297    int EDNSPingHitCount;
298  };
299
300  typedef map<ComboAddress, EDNSStatus> ednsstatus_t;
301
302 
303
304  static bool s_noEDNSPing;
305  static bool s_noEDNS;
306
307  struct AuthDomain
308  {
309    vector<ComboAddress> d_servers;
310    bool d_rdForward;
311    typedef multi_index_container <
312      DNSResourceRecord,
313      indexed_by < 
314        ordered_non_unique< 
315          composite_key< DNSResourceRecord,
316                         member<DNSResourceRecord, string, &DNSResourceRecord::qname>,
317                         member<DNSResourceRecord, QType, &DNSResourceRecord::qtype>
318                       >,
319          composite_key_compare<CIStringCompare, std::less<QType> >
320        >
321      >
322    > records_t;
323    records_t d_records;       
324  };
325 
326
327  typedef map<string, AuthDomain, CIStringCompare> domainmap_t;
328 
329
330  typedef Throttle<tuple<ComboAddress,string,uint16_t> > throttle_t;
331 
332  struct timeval d_now;
333  static unsigned int s_maxnegttl;
334  static unsigned int s_maxcachettl;
335  static unsigned int s_packetcachettl;
336  static unsigned int s_packetcacheservfailttl;
337  static bool s_nopacketcache;
338  static string s_serverID;
339
340  struct StaticStorage {
341    negcache_t negcache;   
342    nsspeeds_t nsSpeeds;
343    ednsstatus_t ednsstatus;
344    throttle_t throttle;
345    domainmap_t* domainmap;
346  };
347  static __thread StaticStorage* t_sstorage;
348
349private:
350  struct GetBestNSAnswer;
351  int doResolveAt(set<string, CIStringCompare> nameservers, string auth, bool flawedNSSet, const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret,
352                  int depth, set<GetBestNSAnswer>&beenthere);
353  int doResolve(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere);
354  bool doOOBResolve(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
355  domainmap_t::const_iterator getBestAuthZone(string* qname);
356  bool doCNAMECacheCheck(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
357  bool doCacheCheck(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
358  void getBestNSFromCache(const string &qname, set<DNSResourceRecord>&bestns, bool* flawedNSSet, int depth, set<GetBestNSAnswer>& beenthere);
359  void addCruft(const string &qname, vector<DNSResourceRecord>& ret);
360  string getBestNSNamesFromCache(const string &qname,set<string, CIStringCompare>& nsset, bool* flawedNSSet, int depth, set<GetBestNSAnswer>&beenthere);
361  void addAuthorityRecords(const string& qname, vector<DNSResourceRecord>& ret, int depth);
362
363  inline vector<string> shuffleInSpeedOrder(set<string, CIStringCompare> &nameservers, const string &prefix);
364  bool moreSpecificThan(const string& a, const string &b);
365  vector<ComboAddress> getAs(const string &qname, int depth, set<GetBestNSAnswer>& beenthere);
366
367private:
368  string d_prefix;
369  static bool s_log;
370  bool d_cacheonly;
371  bool d_nocache;
372  bool d_doEDNS0;
373
374  struct GetBestNSAnswer
375  {
376    string qname;
377    set<DNSResourceRecord> bestns;
378    bool operator<(const GetBestNSAnswer &b) const
379    {
380      if(qname<b.qname)
381        return true;
382      if(qname==b.qname)
383        return bestns<b.bestns;
384      return false;
385    }
386  };
387
388};
389class Socket;
390/* external functions, opaque to us */
391int asendtcp(const string& data, Socket* sock);
392int arecvtcp(string& data, int len, Socket* sock);
393
394
395struct PacketID
396{
397  PacketID() : id(0), type(0), sock(0), inNeeded(0), outPos(0), nearMisses(0), fd(-1)
398  {
399    memset(&remote, 0, sizeof(remote));
400  }
401
402  uint16_t id;  // wait for a specific id/remote pair
403  ComboAddress remote;  // this is the remote
404  string domain;             // this is the question
405  uint16_t type;             // and this is its type
406
407  Socket* sock;  // or wait for an event on a TCP fd
408  int inNeeded; // if this is set, we'll read until inNeeded bytes are read
409  string inMSG; // they'll go here
410
411  string outMSG; // the outgoing message that needs to be sent
412  string::size_type outPos;    // how far we are along in the outMSG
413
414  mutable uint32_t nearMisses; // number of near misses - host correct, id wrong
415  typedef set<uint16_t > chain_t;
416  mutable chain_t chain;
417  int fd;
418
419  bool operator<(const PacketID& b) const
420  {
421    int ourSock= sock ? sock->getHandle() : 0;
422    int bSock = b.sock ? b.sock->getHandle() : 0;
423    if( tie(remote, ourSock, type) < tie(b.remote, bSock, b.type))
424      return true;
425    if( tie(remote, ourSock, type) > tie(b.remote, bSock, b.type))
426      return false;
427
428    if(pdns_ilexicographical_compare(domain, b.domain))
429      return true;
430    if(pdns_ilexicographical_compare(b.domain, domain))
431      return false;
432
433    return tie(fd, id) < tie(b.fd, b.id);
434  }
435};
436
437struct PacketIDBirthdayCompare: public binary_function<PacketID, PacketID, bool> 
438{
439  bool operator()(const PacketID& a, const PacketID& b) const
440  {
441    int ourSock= a.sock ? a.sock->getHandle() : 0;
442    int bSock = b.sock ? b.sock->getHandle() : 0;
443    if( tie(a.remote, ourSock, a.type) < tie(b.remote, bSock, b.type))
444      return true;
445    if( tie(a.remote, ourSock, a.type) > tie(b.remote, bSock, b.type))
446      return false;
447
448    return pdns_ilexicographical_compare(a.domain, b.domain);
449  }
450};
451extern __thread MemRecursorCache* t_RC;
452extern __thread RecursorPacketCache* t_packetCache;
453typedef MTasker<PacketID,string> MT_t;
454extern __thread MT_t* MT;
455
456struct RecursorStats
457{
458  uint64_t servFails;
459  uint64_t nxDomains;
460  uint64_t noErrors;
461  uint64_t answers0_1, answers1_10, answers10_100, answers100_1000, answersSlow;
462  uint64_t avgLatencyUsec;
463  uint64_t qcounter;
464  uint64_t tcpqcounter;
465  uint64_t unauthorizedUDP;
466  uint64_t unauthorizedTCP;
467  uint64_t tcpClientOverflow;
468  uint64_t clientParseError;
469  uint64_t serverParseError;
470  uint64_t unexpectedCount;
471  uint64_t caseMismatchCount;
472  uint64_t spoofCount;
473  uint64_t resourceLimits;
474  uint64_t ipv6queries;
475  uint64_t chainResends;
476  uint64_t nsSetInvalidations;
477  uint64_t shunted;
478  uint64_t noShuntCNAME, noShuntExpired, noShuntSize, noShuntNoMatch, noShuntWrongType, noShuntWrongQuestion;
479  uint64_t ednsPingMatches;
480  uint64_t ednsPingMismatches;
481  uint64_t noPingOutQueries, noEdnsOutQueries;
482  uint64_t packetCacheHits;
483  time_t startupTime;
484
485  typedef vector<ComboAddress> remotes_t;
486  remotes_t remotes;
487  int d_remotepos;
488  void addRemote(const ComboAddress& remote)
489  {
490    if(!remotes.size())
491      return;
492
493    remotes[(d_remotepos++) % remotes.size()]=remote;
494  }
495};
496
497string doQueueReloadLuaScript(vector<string>::const_iterator begin, vector<string>::const_iterator end);
498void parseACLs();
499extern RecursorStats g_stats;
500
501
502template<typename Index>
503std::pair<typename Index::iterator,bool>
504replacing_insert(Index& i,const typename Index::value_type& x)
505{
506  std::pair<typename Index::iterator,bool> res=i.insert(x);
507  if(!res.second)res.second=i.replace(res.first,x);
508  return res;
509}
510
511
512std::string reloadAuthAndForwards();
513ComboAddress parseIPAndPort(const std::string& input, uint16_t port);
514ComboAddress getQueryLocalAddress(int family, uint16_t port);
515typedef boost::function<void*(void)> pipefunc_t;
516void broadcastFunction(const pipefunc_t& func, bool skipSelf = false);
517
518
519template<class T> T broadcastAccFunction(const boost::function<T*()>& func, bool skipSelf=false);
520
521SyncRes::domainmap_t* parseAuthAndForwards();
522
523uint64_t* pleaseGetNsSpeedsSize();
524uint64_t* pleaseGetCacheSize();
525uint64_t* pleaseGetNegCacheSize();
526uint64_t* pleaseGetCacheHits();
527uint64_t* pleaseGetCacheMisses();
528uint64_t* pleaseGetConcurrentQueries();
529uint64_t* pleaseGetThrottleSize();
530uint64_t* pleaseGetPacketCacheHits();
531uint64_t* pleaseGetPacketCacheSize();
532
533#endif
Note: See TracBrowser for help on using the browser.