]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
use kernel recorded arrival time for question/answer latency measurements, so we...
authorbert hubert <bert.hubert@netherlabs.nl>
Fri, 26 Sep 2014 12:38:03 +0000 (14:38 +0200)
committerbert hubert <bert.hubert@netherlabs.nl>
Fri, 26 Sep 2014 12:38:03 +0000 (14:38 +0200)
pdns/misc.cc
pdns/misc.hh
pdns/nameserver.cc

index a43030ba6f28506dc1e5631146d34ed532061737..41fb4525867ad8e14070dcc84b6d785720b081b0 100644 (file)
@@ -907,3 +907,10 @@ uint32_t burtle(const unsigned char* k, uint32_t length, uint32_t initval)
   /*-------------------------------------------- report the result */
   return c;
 }
+
+void setSocketTimestamps(int fd)
+{
+  int on=1;
+  if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP, (char*)&on, sizeof(on)) < 0 )
+    L<<Logger::Error<<"Warning: unable to enable timestamp reporting for socket"<<endl;
+}
index 28bede0503e6ca40143509fb8d9e5af32f1bf9ec..ea8906878b2774754abdc211325c7e69662831c2 100644 (file)
@@ -531,4 +531,5 @@ unsigned int getFilenumLimit(bool hardOrSoft=0);
 void setFilenumLimit(unsigned int lim);
 bool readFileIfThere(const char* fname, std::string* line);
 uint32_t burtle(const unsigned char* k, uint32_t lengh, uint32_t init);
+void setSocketTimestamps(int fd);
 #endif
index 10331802df6cd790ca6913acd1c246506f445145..3a52dd536e410a6c1a8b593b5384dc758afb6610 100644 (file)
@@ -121,6 +121,8 @@ void UDPNameserver::bindIPv4()
     if(localname=="0.0.0.0")
       setsockopt(s, IPPROTO_IP, GEN_IP_PKTINFO, &one, sizeof(one));
 
+    setSocketTimestamps(s);
+
 #ifdef SO_REUSEPORT
     if( d_can_reuseport )
         if( setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) )
@@ -232,6 +234,8 @@ void UDPNameserver::bindIPv6()
       setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));      // if this fails, we report an error in tcpreceiver too
     }
 
+    setSocketTimestamps(s);
+
 #ifdef SO_REUSEPORT
     if( d_can_reuseport )
         if( setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) )
@@ -332,6 +336,19 @@ void UDPNameserver::send(DNSPacket *p)
     L<<Logger::Error<<"Error sending reply with sendmsg (socket="<<p->getSocket()<<", dest="<<p->d_remote.toStringWithPort()<<"): "<<strerror(errno)<<endl;
 }
 
+static bool HarvestTimestamp(struct msghdr* msgh, struct timeval* tv) 
+{
+  struct cmsghdr *cmsg;
+  for (cmsg = CMSG_FIRSTHDR(msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(msgh,cmsg)) {
+    if ((cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SO_TIMESTAMP) && 
+       CMSG_LEN(sizeof(*tv)) == cmsg->cmsg_len) {
+      memcpy(tv, CMSG_DATA(cmsg), sizeof(*tv));
+      return true;
+    }
+  }
+  return false;
+}
+
 static bool HarvestDestinationAddress(struct msghdr* msgh, ComboAddress* destination)
 {
   memset(destination, 0, sizeof(*destination));
@@ -431,7 +448,7 @@ DNSPacket *UDPNameserver::receive(DNSPacket *prefilled)
     packet=prefilled;
   else
     packet=new DNSPacket; // don't forget to free it!
-  packet->d_dt.set(); // timing
+
   packet->setSocket(sock);
   packet->setRemote(&remote);
 
@@ -441,6 +458,13 @@ DNSPacket *UDPNameserver::receive(DNSPacket *prefilled)
     packet->d_anyLocal = dest;
   }            
 
+  struct timeval recvtv;
+  if(HarvestTimestamp(&msgh, &recvtv)) {
+    packet->d_dt.setTimeval(recvtv);
+  }
+  else
+    packet->d_dt.set(); // timing    
+
   if(packet->parse(mesg, len)<0) {
     S.inc("corrupt-packets");
     S.ringAccount("remotes-corrupt", packet->getRemote());