From c29d820cc4f2dedcb5ecb05a563be4e11a866dd5 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Thu, 21 Feb 2019 16:06:21 +0100 Subject: [PATCH] rec: Add 'protobuf-use-kernel-timestamp' for sharper latencies --- pdns/pdns_recursor.cc | 32 ++++++++++++++++++++++------- pdns/recursordist/docs/settings.rst | 11 ++++++++++ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index b8d1f8ade..ca47663b2 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -208,6 +208,7 @@ static bool g_reusePort{false}; static bool g_gettagNeedsEDNSOptions{false}; static time_t g_statisticsInterval; static bool g_useIncomingECS; +static bool g_useKernelTimestamp; std::atomic g_maxCacheEntries, g_maxPacketCacheEntries; #ifdef NOD_ENABLED static bool g_nodEnabled; @@ -308,6 +309,7 @@ struct DNSComboWriter { boost::uuids::uuid d_uuid; string d_requestorId; string d_deviceId; + struct timeval d_kernelTimestamp{0,0}; #endif std::string d_query; std::vector d_policyTags; @@ -1534,7 +1536,12 @@ static void startDoResolve(void *p) pbMessage->setAppliedPolicyType(appliedPolicy.d_type); } pbMessage->setPolicyTags(dc->d_policyTags); - pbMessage->setQueryTime(dc->d_now.tv_sec, dc->d_now.tv_usec); + if (g_useKernelTimestamp && dc->d_kernelTimestamp.tv_sec) { + pbMessage->setQueryTime(dc->d_kernelTimestamp.tv_sec, dc->d_kernelTimestamp.tv_usec); + } + else { + pbMessage->setQueryTime(dc->d_now.tv_sec, dc->d_now.tv_usec); + } pbMessage->setRequestorId(dq.requestorId); pbMessage->setDeviceId(dq.deviceId); #ifdef NOD_ENABLED @@ -2058,12 +2065,14 @@ static void handleNewTCPQuestion(int fd, FDMultiplexer::funcparam_t& ) static string* doProcessUDPQuestion(const std::string& question, const ComboAddress& fromaddr, const ComboAddress& destaddr, struct timeval tv, int fd) { gettimeofday(&g_now, 0); - struct timeval diff = g_now - tv; - double delta=(diff.tv_sec*1000 + diff.tv_usec/1000.0); + if (tv.tv_sec) { + struct timeval diff = g_now - tv; + double delta=(diff.tv_sec*1000 + diff.tv_usec/1000.0); - if(tv.tv_sec && delta > 1000.0) { - g_stats.tooOldDrops++; - return 0; + if(delta > 1000.0) { + g_stats.tooOldDrops++; + return nullptr; + } } ++g_stats.qcounter; @@ -2193,7 +2202,12 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr const ComboAddress& requestor = requestorNM.getMaskedNetwork(); pbMessage->update(uniqueId, &requestor, &destination, false, dh->id); pbMessage->setEDNSSubnet(ednssubnet.source, ednssubnet.source.isIpv4() ? luaconfsLocal->protobufMaskV4 : luaconfsLocal->protobufMaskV6); - pbMessage->setQueryTime(g_now.tv_sec, g_now.tv_usec); + if (g_useKernelTimestamp && tv.tv_sec) { + pbMessage->setQueryTime(tv.tv_sec, tv.tv_usec); + } + else { + pbMessage->setQueryTime(g_now.tv_sec, g_now.tv_usec); + } pbMessage->setRequestorId(requestorId); pbMessage->setDeviceId(deviceId); protobufLogResponse(*pbMessage); @@ -2271,6 +2285,7 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr } dc->d_requestorId = requestorId; dc->d_deviceId = deviceId; + dc->d_kernelTimestamp = tv; #endif MT->makeThread(startDoResolve, (void*) dc.release()); // deletes dc @@ -3859,6 +3874,8 @@ static int serviceMain(int argc, char*argv[]) g_tcpMaxQueriesPerConn=::arg().asNum("max-tcp-queries-per-connection"); s_maxUDPQueriesPerRound=::arg().asNum("max-udp-queries-per-round"); + g_useKernelTimestamp = ::arg().mustDo("protobuf-use-kernel-timestamp"); + blacklistStats(StatComponent::API, ::arg()["stats-api-blacklist"]); blacklistStats(StatComponent::Carbon, ::arg()["stats-carbon-blacklist"]); blacklistStats(StatComponent::RecControl, ::arg()["stats-rec-control-blacklist"]); @@ -4280,6 +4297,7 @@ int main(int argc, char **argv) ::arg().set("max-total-msec", "Maximum total wall-clock time per query in milliseconds, 0 for unlimited")="7000"; ::arg().set("max-recursion-depth", "Maximum number of internal recursion calls per query, 0 for unlimited")="40"; ::arg().set("max-udp-queries-per-round", "Maximum number of UDP queries processed per recvmsg() round, before returning back to normal processing")="10000"; + ::arg().set("protobuf-use-kernel-timestamp", "Compute the latency of queries in protobuf messages by using the timestamp set by the kernel when the query was received (when available)")=""; ::arg().set("include-dir","Include *.conf files from this directory")=""; ::arg().set("security-poll-suffix","Domain name from which to query security update notifications")="secpoll.powerdns.com."; diff --git a/pdns/recursordist/docs/settings.rst b/pdns/recursordist/docs/settings.rst index 5d9b529bf..f76a990e0 100644 --- a/pdns/recursordist/docs/settings.rst +++ b/pdns/recursordist/docs/settings.rst @@ -1038,6 +1038,17 @@ maximizing the cache hit ratio. Starting with version 4.2.0, more than one distr setting. Improves performance on Linux. +.. _settting-protobuf-use-kernel-timestamp: + +``protobuf-use-kernel-timestamp`` +--------------------------- +.. versionadded:: 4.2.0 + +- Boolean +- Default: false + +Whether to compute the latency of responses in protobuf messages using the timestamp set by the kernel when the query packet was received (when available), instead of computing it based on the moment we start processing the query. + .. _settting-public-suffix-list-file: ``public-suffix-list-file`` -- 2.40.0