]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: record query time in DNSQuestion
authorChris Hofstaedtler <chris.hofstaedtler@deduktiva.com>
Thu, 11 Jan 2018 16:22:42 +0000 (17:22 +0100)
committerChris Hofstaedtler <chris.hofstaedtler@deduktiva.com>
Tue, 23 Jan 2018 15:06:29 +0000 (16:06 +0100)
pdns/dnsdist-lua-rules.cc
pdns/dnsdist-protobuf.cc
pdns/dnsdist-tcp.cc
pdns/dnsdist.cc
pdns/dnsdist.hh
pdns/test-dnsdistpacketcache_cc.cc

index a6ffe645545bbef7adb7bc0c978820a196263140..42734bd987dae8cf144a5d6df600f68f6011d2f6 100644 (file)
@@ -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();
 
     });
index b0ba7e745f3778fde7311d9fb20cedac9f6440c3..26c67b6b28e2557918220c0dc53c987f9c5e4ea7 100644 (file)
@@ -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)
index ae141f6683ff84e36e40170cdcb9705bd59d76cc..37c6814d8b79c5b60cd75b686fca5c8259e65974 100644 (file)
@@ -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;
        }
index bd464f8ff430abdd076e83b304a088101ccef3d3..8a36a0db6c807af502752950166f14fa3c1d0a0f 100644 (file)
@@ -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<dnsheader*>(response), dq.size, responseLen, false, &realTime);
+        DNSResponse dr(dq.qname, dq.qtype, dq.qclass, dq.local, dq.remote, reinterpret_cast<dnsheader*>(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<dnsheader*>(query), dq.size, cachedResponseSize, false, &realTime);
+        DNSResponse dr(dq.qname, dq.qtype, dq.qclass, dq.local, dq.remote, reinterpret_cast<dnsheader*>(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<dnsheader*>(response), dq.size, responseLen, false, &realTime);
+        DNSResponse dr(dq.qname, dq.qtype, dq.qclass, dq.local, dq.remote, reinterpret_cast<dnsheader*>(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;
index f20b1a1fdb5f881e3ed8f9bc4a600212e8970659..b8d7111282a96d357e90cda7ba4609dedab5d9f7 100644 (file)
@@ -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<boost::uuids::uuid> uniqueId;
@@ -143,6 +144,7 @@ struct DNSQuestion
   uint16_t ecsPrefixLength;
   boost::optional<uint32_t> 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: 
index 2acc4ba70d528d2eb29c88f20f2d3032fe9fc30e..a08ac278abac84e68df60517b84f83e4d156acad 100644 (file)
@@ -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++;