From 75fde3554f77be88303af05d9de7c8409c58783e Mon Sep 17 00:00:00 2001 From: Kees Monshouwer Date: Sat, 17 May 2014 19:17:00 +0200 Subject: [PATCH] packet cache improvements for recursive answers - fix tagging of recursive packets - age ttl in packet cache for recursive results - respect allow-recursion in packet cache --- pdns/common_startup.cc | 41 +++++++++++++++++++++---------------- pdns/dnsproxy.cc | 2 +- pdns/packetcache.cc | 46 +++++++++++++++++++++++++----------------- pdns/packetcache.hh | 13 ++++++------ pdns/packethandler.cc | 2 +- pdns/tcpreceiver.cc | 2 +- 6 files changed, 62 insertions(+), 44 deletions(-) diff --git a/pdns/common_startup.cc b/pdns/common_startup.cc index b8e144ef22..1fa1d08622 100644 --- a/pdns/common_startup.cc +++ b/pdns/common_startup.cc @@ -252,6 +252,7 @@ void *qthread(void *number) int diff; bool logDNSQueries = ::arg().mustDo("log-dns-queries"); + bool doRecursion = ::arg().mustDo("recursor"); bool skipfirst=true; unsigned int maintcount = 0; UDPNameserver *NS = N; @@ -305,23 +306,29 @@ void *qthread(void *number) "', do = " <d_dnssecOk <<", bufsize = "<< P->getMaxReplyLen()<<": "; } - - if((P->d.opcode != Opcode::Notify && P->d.opcode != Opcode::Update) && P->couldBeCached() && PC.get(P, &cached)) { // short circuit - does the PacketCache recognize this question? - if(logDNSQueries) - L<<"packetcache HIT"<d_remote); // inlined - cached.setSocket(P->getSocket()); // inlined - cached.d_anyLocal = P->d_anyLocal; - cached.setMaxReplyLen(P->getMaxReplyLen()); - cached.d.rd=P->d.rd; // copy in recursion desired bit - cached.d.id=P->d.id; - cached.commitD(); // commit d to the packet inlined - - NS->send(&cached); // answer it then inlined - diff=P->d_dt.udiff(); - avg_latency=(int)(0.999*avg_latency+0.001*diff); // 'EWMA' - - continue; + if((P->d.opcode != Opcode::Notify && P->d.opcode != Opcode::Update) && P->couldBeCached()) { + bool haveSomething = false; + if (doRecursion && P->d.rd && DP->recurseFor(P)) + haveSomething=PC.get(P, &cached, true); // does the PacketCache recognize this ruestion (recursive)? + if (!haveSomething) + haveSomething=PC.get(P, &cached, false); // does the PacketCache recognize this question? + if (haveSomething) { + if(logDNSQueries) + L<<"packetcache HIT"<d_remote); // inlined + cached.setSocket(P->getSocket()); // inlined + cached.d_anyLocal = P->d_anyLocal; + cached.setMaxReplyLen(P->getMaxReplyLen()); + cached.d.rd=P->d.rd; // copy in recursion desired bit + cached.d.id=P->d.id; + cached.commitD(); // commit d to the packet inlined + + NS->send(&cached); // answer it then inlined + diff=P->d_dt.udiff(); + avg_latency=(int)(0.999*avg_latency+0.001*diff); // 'EWMA' + + continue; + } } if(distributor->isOverloaded()) { diff --git a/pdns/dnsproxy.cc b/pdns/dnsproxy.cc index 981d850fd4..2bc18b6433 100644 --- a/pdns/dnsproxy.cc +++ b/pdns/dnsproxy.cc @@ -210,7 +210,7 @@ void DNSProxy::mainloop(void) if(sendmsg(i->second.outsock, &msgh, 0) < 0) L<second.created=0; } } diff --git a/pdns/packetcache.cc b/pdns/packetcache.cc index 84fc6babbc..cd244a58e6 100644 --- a/pdns/packetcache.cc +++ b/pdns/packetcache.cc @@ -51,7 +51,7 @@ PacketCache::~PacketCache() WriteLock l(&d_mut); } -int PacketCache::get(DNSPacket *p, DNSPacket *cached) +int PacketCache::get(DNSPacket *p, DNSPacket *cached, bool recursive) { extern StatBag S; @@ -75,10 +75,10 @@ int PacketCache::get(DNSPacket *p, DNSPacket *cached) } } - bool packetMeritsRecursion=d_doRecursion && p->d.rd; if(ntohs(p->d.qdcount)!=1) // we get confused by packets with more than one question return 0; + unsigned int age=0; string value; bool haveSomething; { @@ -89,13 +89,14 @@ int PacketCache::get(DNSPacket *p, DNSPacket *cached) } uint16_t maxReplyLen = p->d_tcp ? 0xffff : p->getMaxReplyLen(); - haveSomething=getEntryLocked(p->qdomain, p->qtype, PacketCache::PACKETCACHE, value, -1, packetMeritsRecursion, maxReplyLen, p->d_dnssecOk, p->hasEDNS()); + haveSomething=getEntryLocked(p->qdomain, p->qtype, PacketCache::PACKETCACHE, value, -1, recursive, maxReplyLen, p->d_dnssecOk, p->hasEDNS(), &age); } if(haveSomething) { (*d_statnumhit)++; - if(cached->noparse(value.c_str(), value.size()) < 0) { + if (recursive) + ageDNSPacket(value, age); + if(cached->noparse(value.c_str(), value.size()) < 0) return 0; - } cached->spoofQuestion(p); // for correct case cached->qdomain=p->qdomain; cached->qtype=p->qtype; @@ -116,7 +117,7 @@ void PacketCache::getTTLS() } -void PacketCache::insert(DNSPacket *q, DNSPacket *r, unsigned int maxttl) +void PacketCache::insert(DNSPacket *q, DNSPacket *r, bool recursive, unsigned int maxttl) { if(d_ttl < 0) getTTLS(); @@ -128,12 +129,17 @@ void PacketCache::insert(DNSPacket *q, DNSPacket *r, unsigned int maxttl) if(q->qclass != QClass::IN) // we only cache the INternet return; - bool packetMeritsRecursion=d_doRecursion && q->d.rd; uint16_t maxReplyLen = q->d_tcp ? 0xffff : q->getMaxReplyLen(); - unsigned int ourttl = packetMeritsRecursion ? d_recursivettl : d_ttl; - if(maxttlqdomain, q->qtype, PacketCache::PACKETCACHE, r->getString(), ourttl, -1, packetMeritsRecursion, + unsigned int ourttl = recursive ? d_recursivettl : d_ttl; + if(!recursive) { + if(maxttlgetMinTTL(); + if(minttlqdomain, q->qtype, PacketCache::PACKETCACHE, r->getString(), ourttl, -1, recursive, maxReplyLen, q->d_dnssecOk, q->hasEDNS()); } @@ -150,7 +156,8 @@ void PacketCache::insert(const string &qname, const QType& qtype, CacheEntryType //cerr<<"Inserting qname '"<ttd > now); - if(ret) + if(ret) { + if (age) + *age = now - i->created; value = i->value; - + } + return ret; } diff --git a/pdns/packetcache.hh b/pdns/packetcache.hh index 902247b182..a447a8813c 100644 --- a/pdns/packetcache.hh +++ b/pdns/packetcache.hh @@ -72,14 +72,14 @@ public: ~PacketCache(); enum CacheEntryType { PACKETCACHE, QUERYCACHE}; - void insert(DNSPacket *q, DNSPacket *r, unsigned int maxttl=UINT_MAX); //!< We copy the contents of *p into our cache. Do not needlessly call this to insert questions already in the cache as it wastes resources + void insert(DNSPacket *q, DNSPacket *r, bool recursive, unsigned int maxttl=UINT_MAX); //!< We copy the contents of *p into our cache. Do not needlessly call this to insert questions already in the cache as it wastes resources void insert(const string &qname, const QType& qtype, CacheEntryType cet, const string& value, unsigned int ttl, int zoneID=-1, bool meritsRecursion=false, unsigned int maxReplyLen=512, bool dnssecOk=false, bool EDNS=false); - int get(DNSPacket *p, DNSPacket *q); //!< We return a dynamically allocated copy out of our cache. You need to delete it. You also need to spoof in the right ID with the DNSPacket.spoofID() method. - bool getEntry(const string &content, const QType& qtype, CacheEntryType cet, string& entry, int zoneID=-1, - bool meritsRecursion=false, unsigned int maxReplyLen=512, bool dnssecOk=false, bool hasEDNS=false); + int get(DNSPacket *p, DNSPacket *q, bool recursive); //!< We return a dynamically allocated copy out of our cache. You need to delete it. You also need to spoof in the right ID with the DNSPacket.spoofID() method. + bool getEntry(const string &content, const QType& qtype, CacheEntryType cet, string& entry, int zoneID=-1, + bool meritsRecursion=false, unsigned int maxReplyLen=512, bool dnssecOk=false, bool hasEDNS=false, unsigned int *age=0); int size(); //!< number of entries in the cache void cleanup(); //!< force the cache to preen itself from expired packets @@ -88,8 +88,8 @@ public: map getCounts(); private: - bool getEntryLocked(const string &content, const QType& qtype, CacheEntryType cet, string& entry, int zoneID=-1, - bool meritsRecursion=false, unsigned int maxReplyLen=512, bool dnssecOk=false, bool hasEDNS=false); + bool getEntryLocked(const string &content, const QType& qtype, CacheEntryType cet, string& entry, int zoneID=-1, + bool meritsRecursion=false, unsigned int maxReplyLen=512, bool dnssecOk=false, bool hasEDNS=false, unsigned int *age=0); struct CacheEntry { CacheEntry() { qtype = ctype = 0; zoneID = -1; meritsRecursion=false; dnssecOk=false; hasEDNS=false;} @@ -98,6 +98,7 @@ private: uint16_t qtype; uint16_t ctype; int zoneID; + time_t created; time_t ttd; bool meritsRecursion; unsigned int maxReplyLen; diff --git a/pdns/packethandler.cc b/pdns/packethandler.cc index 47454dc9b4..9cea755e77 100644 --- a/pdns/packethandler.cc +++ b/pdns/packethandler.cc @@ -1506,7 +1506,7 @@ DNSPacket *PacketHandler::questionOrRecurse(DNSPacket *p, bool *shouldRecurse) r->wrapup(); // needed for inserting in cache if(!noCache) - PC.insert(p, r, r->getMinTTL()); // in the packet cache + PC.insert(p, r, false, r->getMinTTL()); // in the packet cache } catch(DBException &e) { L<d.rd && packet->couldBeCached() && PC.get(packet.get(), cached.get())) { // short circuit - does the PacketCache recognize this question? + if(!packet->d.rd && packet->couldBeCached() && PC.get(packet.get(), cached.get(), false)) { // short circuit - does the PacketCache recognize this question? if(logDNSQueries) L<<"packetcache HIT"<setRemote(&packet->d_remote); -- 2.47.2