From: Chris Hofstaedtler Date: Thu, 11 Jan 2018 16:22:42 +0000 (+0100) Subject: dnsdist: record query time in DNSQuestion X-Git-Tag: dnsdist-1.3.0~112^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5ffb2f83132ee68224da5566a60833f404791134;p=pdns dnsdist: record query time in DNSQuestion --- diff --git a/pdns/dnsdist-lua-rules.cc b/pdns/dnsdist-lua-rules.cc index a6ffe6455..42734bd98 100644 --- a/pdns/dnsdist-lua-rules.cc +++ b/pdns/dnsdist-lua-rules.cc @@ -1137,15 +1137,15 @@ void setupLuaRules() int matches=0; ComboAddress dummy("127.0.0.1"); - DTime dt; - dt.set(); + StopWatch sw; + sw.start(); for(int n=0; n < times; ++n) { const item& i = items[n % items.size()]; - DNSQuestion dq(&i.qname, i.qtype, i.qclass, &i.rem, &i.rem, (struct dnsheader*)&i.packet[0], i.packet.size(), i.packet.size(), false); + DNSQuestion dq(&i.qname, i.qtype, i.qclass, &i.rem, &i.rem, (struct dnsheader*)&i.packet[0], i.packet.size(), i.packet.size(), false, &sw.d_start); if(rule->matches(&dq)) matches++; } - double udiff=dt.udiff(); + double udiff=sw.udiff(); g_outputBuffer=(boost::format("Had %d matches out of %d, %.1f qps, in %.1f usec\n") % matches % times % (1000000*(1.0*times/udiff)) % udiff).str(); }); diff --git a/pdns/dnsdist-protobuf.cc b/pdns/dnsdist-protobuf.cc index b0ba7e745..26c67b6b2 100644 --- a/pdns/dnsdist-protobuf.cc +++ b/pdns/dnsdist-protobuf.cc @@ -30,6 +30,7 @@ DNSDistProtoBufMessage::DNSDistProtoBufMessage(const DNSQuestion& dq): DNSProtoBufMessage(Query, dq.uniqueId ? *dq.uniqueId : t_uuidGenerator(), dq.remote, dq.local, *dq.qname, dq.qtype, dq.qclass, dq.dh->id, dq.tcp, dq.len) { + setQueryTime(dq.queryTime->tv_sec, dq.queryTime->tv_nsec / 1000); }; DNSDistProtoBufMessage::DNSDistProtoBufMessage(const DNSResponse& dr, bool includeCNAME): DNSProtoBufMessage(Response, dr.uniqueId ? *dr.uniqueId : t_uuidGenerator(), dr.remote, dr.local, *dr.qname, dr.qtype, dr.qclass, dr.dh->id, dr.tcp, dr.len) diff --git a/pdns/dnsdist-tcp.cc b/pdns/dnsdist-tcp.cc index ae141f668..37c6814d8 100644 --- a/pdns/dnsdist-tcp.cc +++ b/pdns/dnsdist-tcp.cc @@ -340,13 +340,6 @@ void* tcpClientThread(int pipefd) goto drop; } - const uint16_t* flags = getFlagsFromDNSHeader(dh); - uint16_t origFlags = *flags; - uint16_t qtype, qclass; - unsigned int consumed = 0; - DNSName qname(query, qlen, sizeof(dnsheader), false, &qtype, &qclass, &consumed); - DNSQuestion dq(&qname, qtype, qclass, &dest, &ci.remote, dh, queryBuffer.capacity(), qlen, true); - string poolname; int delayMsec=0; /* we need this one to be accurate ("real") for the protobuf message */ @@ -355,6 +348,13 @@ void* tcpClientThread(int pipefd) gettime(&now); gettime(&queryRealTime, true); + const uint16_t* flags = getFlagsFromDNSHeader(dh); + uint16_t origFlags = *flags; + uint16_t qtype, qclass; + unsigned int consumed = 0; + DNSName qname(query, qlen, sizeof(dnsheader), false, &qtype, &qclass, &consumed); + DNSQuestion dq(&qname, qtype, qclass, &dest, &ci.remote, dh, queryBuffer.capacity(), qlen, true, &queryRealTime); + if (!processQuery(holders, dq, poolname, &delayMsec, now)) { goto drop; } diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index bd464f8ff..8a36a0db6 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -1246,22 +1246,22 @@ static void processUDPQuery(ClientState& cs, LocalHolders& holders, const struct return; } - const uint16_t * flags = getFlagsFromDNSHeader(dh); - const uint16_t origFlags = *flags; - uint16_t qtype, qclass; - unsigned int consumed = 0; - DNSName qname(query, len, sizeof(dnsheader), false, &qtype, &qclass, &consumed); - DNSQuestion dq(&qname, qtype, qclass, dest.sin4.sin_family != 0 ? &dest : &cs.local, &remote, dh, queryBufferSize, len, false); - string poolname; int delayMsec = 0; /* we need an accurate ("real") value for the response and to store into the IDS, but not for insertion into the rings for example */ - struct timespec realTime; + struct timespec queryRealTime; struct timespec now; gettime(&now); - gettime(&realTime, true); + gettime(&queryRealTime, true); + + const uint16_t * flags = getFlagsFromDNSHeader(dh); + const uint16_t origFlags = *flags; + uint16_t qtype, qclass; + unsigned int consumed = 0; + DNSName qname(query, len, sizeof(dnsheader), false, &qtype, &qclass, &consumed); + DNSQuestion dq(&qname, qtype, qclass, dest.sin4.sin_family != 0 ? &dest : &cs.local, &remote, dh, queryBufferSize, len, false, &queryRealTime); if (!processQuery(holders, dq, poolname, &delayMsec, now)) { @@ -1276,7 +1276,7 @@ static void processUDPQuery(ClientState& cs, LocalHolders& holders, const struct char* response = query; uint16_t responseLen = dq.len; - DNSResponse dr(dq.qname, dq.qtype, dq.qclass, dq.local, dq.remote, reinterpret_cast(response), dq.size, responseLen, false, &realTime); + DNSResponse dr(dq.qname, dq.qtype, dq.qclass, dq.local, dq.remote, reinterpret_cast(response), dq.size, responseLen, false, &queryRealTime); #ifdef HAVE_PROTOBUF dr.uniqueId = dq.uniqueId; #endif @@ -1333,7 +1333,7 @@ static void processUDPQuery(ClientState& cs, LocalHolders& holders, const struct uint16_t cachedResponseSize = dq.size; uint32_t allowExpired = ss ? 0 : g_staleCacheEntriesTTL; if (packetCache->get(dq, consumed, dh->id, query, &cachedResponseSize, &cacheKey, allowExpired)) { - DNSResponse dr(dq.qname, dq.qtype, dq.qclass, dq.local, dq.remote, reinterpret_cast(query), dq.size, cachedResponseSize, false, &realTime); + DNSResponse dr(dq.qname, dq.qtype, dq.qclass, dq.local, dq.remote, reinterpret_cast(query), dq.size, cachedResponseSize, false, &queryRealTime); #ifdef HAVE_PROTOBUF dr.uniqueId = dq.uniqueId; #endif @@ -1380,7 +1380,7 @@ static void processUDPQuery(ClientState& cs, LocalHolders& holders, const struct dq.dh->rcode = RCode::ServFail; dq.dh->qr = true; - DNSResponse dr(dq.qname, dq.qtype, dq.qclass, dq.local, dq.remote, reinterpret_cast(response), dq.size, responseLen, false, &realTime); + DNSResponse dr(dq.qname, dq.qtype, dq.qclass, dq.local, dq.remote, reinterpret_cast(response), dq.size, responseLen, false, &queryRealTime); #ifdef HAVE_PROTOBUF dr.uniqueId = dq.uniqueId; #endif @@ -1431,7 +1431,7 @@ static void processUDPQuery(ClientState& cs, LocalHolders& holders, const struct ids->origFD = cs.udpFD; ids->origID = dh->id; ids->origRemote = remote; - ids->sentTime.set(realTime); + ids->sentTime.set(queryRealTime); ids->qname = qname; ids->qtype = dq.qtype; ids->qclass = dq.qclass; diff --git a/pdns/dnsdist.hh b/pdns/dnsdist.hh index f20b1a1fd..b8d711128 100644 --- a/pdns/dnsdist.hh +++ b/pdns/dnsdist.hh @@ -126,7 +126,8 @@ extern thread_local boost::uuids::random_generator t_uuidGenerator; struct DNSQuestion { - DNSQuestion(const DNSName* name, uint16_t type, uint16_t class_, const ComboAddress* lc, const ComboAddress* rem, struct dnsheader* header, size_t bufferSize, uint16_t queryLen, bool isTcp): qname(name), qtype(type), qclass(class_), local(lc), remote(rem), dh(header), size(bufferSize), len(queryLen), ecsPrefixLength(rem->sin4.sin_family == AF_INET ? g_ECSSourcePrefixV4 : g_ECSSourcePrefixV6), tempFailureTTL(boost::none), tcp(isTcp), ecsOverride(g_ECSOverride) { } + DNSQuestion(const DNSName* name, uint16_t type, uint16_t class_, const ComboAddress* lc, const ComboAddress* rem, struct dnsheader* header, size_t bufferSize, uint16_t queryLen, bool isTcp, const struct timespec* queryTime_): + qname(name), qtype(type), qclass(class_), local(lc), remote(rem), dh(header), size(bufferSize), len(queryLen), ecsPrefixLength(rem->sin4.sin_family == AF_INET ? g_ECSSourcePrefixV4 : g_ECSSourcePrefixV6), tempFailureTTL(boost::none), tcp(isTcp), queryTime(queryTime_), ecsOverride(g_ECSOverride) { } #ifdef HAVE_PROTOBUF boost::optional uniqueId; @@ -143,6 +144,7 @@ struct DNSQuestion uint16_t ecsPrefixLength; boost::optional tempFailureTTL; const bool tcp; + const struct timespec* queryTime; bool skipCache{false}; bool ecsOverride; bool useECS{true}; @@ -151,9 +153,8 @@ struct DNSQuestion struct DNSResponse : DNSQuestion { - DNSResponse(const DNSName* name, uint16_t type, uint16_t class_, const ComboAddress* lc, const ComboAddress* rem, struct dnsheader* header, size_t bufferSize, uint16_t responseLen, bool isTcp, const struct timespec* queryTime_): DNSQuestion(name, type, class_, lc, rem, header, bufferSize, responseLen, isTcp), queryTime(queryTime_) { } - - const struct timespec* queryTime; + DNSResponse(const DNSName* name, uint16_t type, uint16_t class_, const ComboAddress* lc, const ComboAddress* rem, struct dnsheader* header, size_t bufferSize, uint16_t responseLen, bool isTcp, const struct timespec* queryTime_): + DNSQuestion(name, type, class_, lc, rem, header, bufferSize, responseLen, isTcp, queryTime_) { } }; /* so what could you do: diff --git a/pdns/test-dnsdistpacketcache_cc.cc b/pdns/test-dnsdistpacketcache_cc.cc index 2acc4ba70..a08ac278a 100644 --- a/pdns/test-dnsdistpacketcache_cc.cc +++ b/pdns/test-dnsdistpacketcache_cc.cc @@ -7,6 +7,7 @@ #include "iputils.hh" #include "dnswriter.hh" #include "dnsdist-cache.hh" +#include "gettime.hh" BOOST_AUTO_TEST_SUITE(dnsdistpacketcache_cc) @@ -14,6 +15,8 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheSimple) { const size_t maxEntries = 150000; DNSDistPacketCache PC(maxEntries, 86400, 1); BOOST_CHECK_EQUAL(PC.getSize(), 0); + struct timespec queryTime; + gettime(&queryTime); // does not have to be accurate ("realTime") in tests size_t counter=0; size_t skipped=0; @@ -41,7 +44,7 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheSimple) { char responseBuf[4096]; uint16_t responseBufSize = sizeof(responseBuf); uint32_t key = 0; - DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, (struct dnsheader*) query.data(), query.size(), query.size(), false); + DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, (struct dnsheader*) query.data(), query.size(), query.size(), false, &queryTime); bool found = PC.get(dq, a.wirelength(), 0, responseBuf, &responseBufSize, &key); BOOST_CHECK_EQUAL(found, false); @@ -71,7 +74,7 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheSimple) { char responseBuf[4096]; uint16_t responseBufSize = sizeof(responseBuf); uint32_t key = 0; - DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, (struct dnsheader*) query.data(), query.size(), query.size(), false); + DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, (struct dnsheader*) query.data(), query.size(), query.size(), false, &queryTime); bool found = PC.get(dq, a.wirelength(), 0, responseBuf, &responseBufSize, &key); if (found == true) { PC.expungeByName(a); @@ -93,7 +96,7 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheSimple) { uint32_t key = 0; char response[4096]; uint16_t responseSize = sizeof(response); - DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, (struct dnsheader*) query.data(), len, query.size(), false); + DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, (struct dnsheader*) query.data(), len, query.size(), false, &queryTime); if(PC.get(dq, a.wirelength(), pwQ.getHeader()->id, response, &responseSize, &key)) { matches++; } @@ -112,6 +115,8 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheSimple) { BOOST_AUTO_TEST_CASE(test_PacketCacheServFailTTL) { const size_t maxEntries = 150000; DNSDistPacketCache PC(maxEntries, 86400, 1); + struct timespec queryTime; + gettime(&queryTime); // does not have to be accurate ("realTime") in tests ComboAddress remote; try { @@ -135,7 +140,7 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheServFailTTL) { char responseBuf[4096]; uint16_t responseBufSize = sizeof(responseBuf); uint32_t key = 0; - DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, (struct dnsheader*) query.data(), query.size(), query.size(), false); + DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, (struct dnsheader*) query.data(), query.size(), query.size(), false, &queryTime); bool found = PC.get(dq, a.wirelength(), 0, responseBuf, &responseBufSize, &key); BOOST_CHECK_EQUAL(found, false); @@ -159,6 +164,8 @@ static DNSDistPacketCache PC(500000); static void *threadMangler(void* off) { + struct timespec queryTime; + gettime(&queryTime); // does not have to be accurate ("realTime") in tests try { ComboAddress remote; unsigned int offset=(unsigned int)(unsigned long)off; @@ -182,7 +189,7 @@ static void *threadMangler(void* off) char responseBuf[4096]; uint16_t responseBufSize = sizeof(responseBuf); uint32_t key = 0; - DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, (struct dnsheader*) query.data(), query.size(), query.size(), false); + DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, (struct dnsheader*) query.data(), query.size(), query.size(), false, &queryTime); PC.get(dq, a.wirelength(), 0, responseBuf, &responseBufSize, &key); PC.insert(key, a, QType::A, QClass::IN, (const char*) response.data(), responseLen, false, 0, boost::none); @@ -199,6 +206,8 @@ AtomicCounter g_missing; static void *threadReader(void* off) { + struct timespec queryTime; + gettime(&queryTime); // does not have to be accurate ("realTime") in tests try { unsigned int offset=(unsigned int)(unsigned long)off; @@ -213,7 +222,7 @@ static void *threadReader(void* off) char responseBuf[4096]; uint16_t responseBufSize = sizeof(responseBuf); uint32_t key = 0; - DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, (struct dnsheader*) query.data(), query.size(), query.size(), false); + DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, (struct dnsheader*) query.data(), query.size(), query.size(), false, &queryTime); bool found = PC.get(dq, a.wirelength(), 0, responseBuf, &responseBufSize, &key); if (!found) { g_missing++;