Created
April 26, 2013 11:42
-
-
Save Habbie/5466734 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Index: pdns/rec_channel_rec.cc | |
| =================================================================== | |
| --- pdns/rec_channel_rec.cc (Revision 2623) | |
| +++ pdns/rec_channel_rec.cc (Arbeitskopie) | |
| @@ -455,6 +455,8 @@ | |
| addGetStat("noping-outqueries", &g_stats.noPingOutQueries); | |
| addGetStat("noedns-outqueries", &g_stats.noEdnsOutQueries); | |
| + addGetStat("prefetch-queries", &g_stats.prefetched); | |
| + | |
| addGetStat("uptime", calculateUptime); | |
| #ifndef WIN32 | |
| Index: pdns/recpacketcache.cc | |
| =================================================================== | |
| --- pdns/recpacketcache.cc (Revision 2623) | |
| +++ pdns/recpacketcache.cc (Arbeitskopie) | |
| @@ -13,7 +13,7 @@ | |
| } | |
| bool RecursorPacketCache::getResponsePacket(const std::string& queryPacket, time_t now, | |
| - std::string* responsePacket, uint32_t* age) | |
| + std::string* responsePacket, uint32_t* age, unsigned int prefetchRatio) | |
| { | |
| struct Entry e; | |
| e.d_packet=queryPacket; | |
| @@ -24,8 +24,12 @@ | |
| d_misses++; | |
| return false; | |
| } | |
| - | |
| - if((uint32_t)now < iter->d_ttd) { // it is fresh! | |
| + | |
| + uint32_t origTTL = iter->d_ttd - iter->d_creation; | |
| + uint32_t ratioTTL = origTTL/100*(100-prefetchRatio); | |
| + if(origTTL>0 && ratioTTL<1) ratioTTL=1; | |
| + | |
| + if((uint32_t)now < iter->d_creation + ratioTTL) { // it is fresh! | |
| // cerr<<"Fresh for another "<<iter->d_ttd - now<<" seconds!"<<endl; | |
| *age = now - iter->d_creation; | |
| uint16_t id; | |
| Index: pdns/syncres.hh | |
| =================================================================== | |
| --- pdns/syncres.hh (Revision 2623) | |
| +++ pdns/syncres.hh (Arbeitskopie) | |
| @@ -28,6 +28,7 @@ | |
| string d_name; | |
| QType d_qtype; | |
| string d_qname; | |
| + uint32_t d_authttl; | |
| uint32_t d_ttd; | |
| uint32_t getTTD() const | |
| { | |
| @@ -479,6 +480,7 @@ | |
| uint64_t noPingOutQueries, noEdnsOutQueries; | |
| uint64_t packetCacheHits; | |
| uint64_t noPacketError; | |
| + uint64_t prefetched; | |
| time_t startupTime; | |
| unsigned int maxMThreadStackUsage; | |
| }; | |
| Index: pdns/recursor_cache.hh | |
| =================================================================== | |
| --- pdns/recursor_cache.hh (Revision 2623) | |
| +++ pdns/recursor_cache.hh (Arbeitskopie) | |
| @@ -50,6 +50,8 @@ | |
| string d_string; | |
| + uint32_t d_authttl; | |
| + | |
| bool operator<(const StoredRecord& rhs) const | |
| { | |
| return d_string < rhs.d_string; | |
| Index: pdns/pdns_recursor.cc | |
| =================================================================== | |
| --- pdns/pdns_recursor.cc (Revision 2623) | |
| +++ pdns/pdns_recursor.cc (Arbeitskopie) | |
| @@ -74,6 +74,7 @@ | |
| __thread FDMultiplexer* t_fdm; | |
| __thread unsigned int t_id; | |
| unsigned int g_maxTCPPerClient; | |
| +unsigned int g_prefetchRatio; | |
| unsigned int g_networkTimeoutMsec; | |
| bool g_logCommonErrors; | |
| __thread shared_ptr<PowerDNSLua>* t_pdl; | |
| @@ -498,6 +499,7 @@ | |
| } | |
| vector<DNSResourceRecord> ret; | |
| + vector<DNSResourceRecord> prefetch; | |
| vector<uint8_t> packet; | |
| DNSPacketWriter pw(packet, dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_mdp.d_qclass); | |
| @@ -559,6 +561,10 @@ | |
| for(vector<DNSResourceRecord>::const_iterator i=ret.begin(); i!=ret.end(); ++i) { | |
| pw.startRecord(i->qname, i->qtype.getCode(), i->ttl, i->qclass, (DNSPacketWriter::Place)i->d_place); | |
| minTTL = min(minTTL, i->ttl); | |
| + if(!sr.d_outqueries && g_prefetchRatio && i->d_place==DNSResourceRecord::ANSWER) { | |
| + if(i->ttl<i->authttl*g_prefetchRatio/100) | |
| + prefetch.push_back(*i); | |
| + } | |
| if(i->qtype.getCode() == QType::A) { // blast out A record w/o doing whole dnswriter thing | |
| uint32_t ip=0; | |
| IpToU32(i->content, &ip); | |
| @@ -648,6 +654,19 @@ | |
| if(newLat < 1000000) // outliers of several minutes exist.. | |
| g_stats.avgLatencyUsec=(uint64_t)((1-0.0001)*g_stats.avgLatencyUsec + 0.0001*newLat); | |
| + if(prefetch.size() && !variableAnswer) { | |
| + for(vector<DNSResourceRecord>::const_iterator i=prefetch.begin(); i!=prefetch.end(); ++i) { | |
| + t_RC->doAgeCache(g_now.tv_sec, i->qname, i->qtype.getCode(), 0); | |
| + } | |
| + vector<DNSResourceRecord> ret; | |
| + int res = sr.beginResolve(dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), dc->d_mdp.d_qclass, ret); | |
| + if(res == RCode::NoError) { | |
| + g_stats.prefetched++; | |
| + if(!g_quiet) | |
| + L<<Logger::Warning<<"prefetched: qname="<<dc->d_mdp.d_qname<<" qtype="<<DNSRecordContent::NumberToType(dc->d_mdp.d_qtype)<<endl; | |
| + } | |
| + } | |
| + | |
| delete dc; | |
| dc=0; | |
| } | |
| @@ -820,7 +839,7 @@ | |
| string response; | |
| try { | |
| uint32_t age; | |
| - if(!SyncRes::s_nopacketcache && t_packetCache->getResponsePacket(question, g_now.tv_sec, &response, &age)) { | |
| + if(!SyncRes::s_nopacketcache && t_packetCache->getResponsePacket(question, g_now.tv_sec, &response, &age, g_prefetchRatio)) { | |
| if(!g_quiet) | |
| L<<Logger::Error<<t_id<< " question answered from packet cache from "<<fromaddr.toString()<<endl; | |
| @@ -1720,6 +1739,7 @@ | |
| g_initialDomainMap = parseAuthAndForwards(); | |
| + g_prefetchRatio=min(::arg().asNum("prefetch-ratio"), 90); | |
| g_logCommonErrors=::arg().mustDo("log-common-errors"); | |
| @@ -2014,6 +2034,7 @@ | |
| ::arg().set("serve-rfc1918", "If we should be authoritative for RFC 1918 private IP space")=""; | |
| ::arg().set("auth-can-lower-ttl", "If we follow RFC 2181 to the letter, an authoritative server can lower the TTL of NS records")="off"; | |
| ::arg().set("lua-dns-script", "Filename containing an optional 'lua' script that will be used to modify dns answers")=""; | |
| + ::arg().set("prefetch-ratio", "Prefetch RR if request within <number> percent of TTL. 0=off, maximum is 90")="10"; | |
| ::arg().setSwitch( "ignore-rd-bit", "Assume each packet requires recursion, for compatibility" )= "off"; | |
| ::arg().setSwitch( "disable-edns-ping", "Disable EDNSPing" )= "no"; | |
| ::arg().setSwitch( "disable-edns", "Disable EDNS" )= ""; | |
| Index: pdns/dns.hh | |
| =================================================================== | |
| --- pdns/dns.hh (Revision 2623) | |
| +++ pdns/dns.hh (Arbeitskopie) | |
| @@ -80,6 +80,7 @@ | |
| string content; //!< what this record points to. Example: 10.1.2.3 | |
| uint16_t priority; //!< For qtypes that support a priority or preference (MX, SRV) | |
| uint32_t ttl; //!< Time To Live of this record | |
| + uint32_t authttl; //!< Authoritative Time To Live of this record | |
| int domain_id; //!< If a backend implements this, the domain_id of the zone this record is in | |
| time_t last_modified; //!< For autocalculating SOA serial numbers - the backend needs to fill this in | |
| enum Place {QUESTION=0, ANSWER=1, AUTHORITY=2, ADDITIONAL=3}; //!< Type describing the positioning of a DNSResourceRecord within, say, a DNSPacket | |
| @@ -98,6 +99,7 @@ | |
| ar & content; | |
| ar & priority; | |
| ar & ttl; | |
| + ar & authttl; | |
| ar & domain_id; | |
| ar & last_modified; | |
| ar & d_place; | |
| Index: pdns/syncres.cc | |
| =================================================================== | |
| --- pdns/syncres.cc (Revision 2623) | |
| +++ pdns/syncres.cc (Arbeitskopie) | |
| @@ -90,6 +90,7 @@ | |
| rr.qtype=qtype; | |
| rr.qclass=1; | |
| rr.ttl=86400; | |
| + rr.authttl=86400; | |
| if(qtype.getCode()==QType::PTR) | |
| rr.content="localhost."; | |
| else | |
| @@ -107,6 +108,7 @@ | |
| rr.qtype=qtype; | |
| rr.qclass=qclass; | |
| rr.ttl=86400; | |
| + rr.authttl=86400; | |
| if(pdns_iequals(qname,"version.bind.") || pdns_iequals(qname,"version.pdns.")) | |
| rr.content="\""+::arg()["version-string"]+"\""; | |
| else | |
| @@ -991,6 +993,9 @@ | |
| DNSResourceRecord rr=*i; | |
| rr.d_place=DNSResourceRecord::ANSWER; | |
| + rr.authttl = rr.ttl; | |
| + i->authttl = rr.authttl; | |
| + | |
| rr.ttl += d_now.tv_sec; | |
| if(rr.qtype.getCode() == QType::NS) // people fiddle with the case | |
| Index: pdns/recursor_cache.cc | |
| =================================================================== | |
| --- pdns/recursor_cache.cc (Revision 2623) | |
| +++ pdns/recursor_cache.cc (Arbeitskopie) | |
| @@ -132,6 +132,7 @@ | |
| ttd=k->d_ttd; | |
| if(res) { | |
| DNSResourceRecord rr=String2DNSRR(qname, QType(i->d_qtype), k->d_string, ttd); | |
| + rr.authttl=k->d_authttl; | |
| res->insert(rr); | |
| } | |
| } | |
| @@ -235,6 +236,7 @@ | |
| // cerr<<"\tHave "<<content.size()<<" records to store\n"; | |
| for(set<DNSResourceRecord>::const_iterator i=content.begin(); i != content.end(); ++i) { | |
| // cerr<<"To store: "<<i->content<<endl; | |
| + dr.d_authttl=i->authttl; | |
| dr.d_ttd=i->ttl; | |
| dr.d_string=DNSRR2String(*i); | |
| @@ -246,6 +248,7 @@ | |
| if(range.first != range.second) { | |
| // cerr<<"\t\tMay need to modify TTL of stored record\n"; | |
| for(vector<StoredRecord>::iterator j=range.first ; j!=range.second; ++j) { | |
| + j->d_authttl=i->authttl; | |
| /* see http://mailman.powerdns.com/pipermail/pdns-users/2006-May/003413.html */ | |
| if(j->d_ttd > (unsigned int) now && i->ttl > j->d_ttd && qt.getCode()==QType::NS && auth) { // don't allow auth servers to *raise* TTL of an NS record | |
| //~ cerr<<"\t\tNot doing so, trying to raise TTL NS\n"; | |
| @@ -299,24 +302,36 @@ | |
| bool MemRecursorCache::doAgeCache(time_t now, const string& name, uint16_t qtype, int32_t newTTL) | |
| { | |
| cache_t::iterator iter = d_cache.find(tie(name, qtype)); | |
| - if(iter == d_cache.end()) | |
| + uint32_t maxTTD=std::numeric_limits<uint32_t>::min(); | |
| + if(iter == d_cache.end()) { | |
| return false; | |
| + } | |
| - int32_t ttl = iter->getTTD() - now; | |
| - if(ttl < 0) | |
| + CacheEntry ce = *iter; | |
| + | |
| + if(ce.d_records.size()==1) { | |
| + maxTTD=ce.d_records.begin()->d_ttd; | |
| + } | |
| + else { // find the LATEST ttd | |
| + for(vector<StoredRecord>::const_iterator i=ce.d_records.begin(); i != ce.d_records.end(); ++i) | |
| + maxTTD=max(maxTTD, i->d_ttd); | |
| + } | |
| + | |
| + int32_t maxTTL = maxTTD - now; | |
| + | |
| + if(maxTTL < 0) | |
| return false; // would be dead anyhow | |
| - if(ttl > newTTL) { | |
| + if(maxTTL > newTTL) { | |
| d_cachecachevalid=false; | |
| - ttl = newTTL; | |
| - uint32_t newTTD = now + ttl; | |
| - | |
| - CacheEntry ce = *iter; | |
| + uint32_t newTTD = now + newTTL; | |
| + | |
| for(vector<StoredRecord>::iterator j = ce.d_records.begin() ; j != ce.d_records.end(); ++j) { | |
| - j->d_ttd = newTTD; | |
| + if(j->d_ttd>newTTD) // do never renew expired or older TTLs | |
| + j->d_ttd = newTTD; | |
| } | |
| - | |
| + | |
| d_cache.replace(iter, ce); | |
| return true; | |
| } | |
| Index: pdns/recpacketcache.hh | |
| =================================================================== | |
| --- pdns/recpacketcache.hh (Revision 2623) | |
| +++ pdns/recpacketcache.hh (Arbeitskopie) | |
| @@ -19,7 +19,7 @@ | |
| { | |
| public: | |
| RecursorPacketCache(); | |
| - bool getResponsePacket(const std::string& queryPacket, time_t now, std::string* responsePacket, uint32_t* age); | |
| + bool getResponsePacket(const std::string& queryPacket, time_t now, std::string* responsePacket, uint32_t* age, unsigned int prefetchRatio); | |
| void insertResponsePacket(const std::string& responsePacket, time_t now, uint32_t ttd); | |
| void doPruneTo(unsigned int maxSize=250000); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment