X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=pdns%2Fpdns_recursor.cc;h=ae37f9da8d92a4d7daae3a05c00aad63e92faf07;hb=e62422ce0e86cfe959073ef061f07873ceff6be8;hp=f4842e9e7c8d02d104872d64e5f2aecb73e18565;hpb=26376f0467709f4884f5bf485489a96beff1ddb9;p=thirdparty%2Fpdns.git diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index f4842e9e7c..ae37f9da8d 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -161,6 +161,8 @@ struct RecThreadInfo deferredAdd_t deferredAdds; struct ThreadPipeSet pipes; std::thread thread; + MT_t* mt{nullptr}; + uint64_t numberOfDistributedQueries{0}; /* handle the web server, carbon, statistics and the control channel */ bool isHandler{false}; /* accept incoming queries (and distributes them to the workers if pdns-distributes-queries is set) */ @@ -226,6 +228,7 @@ static std::set s_avoidUdpSourcePorts; #endif static uint16_t s_minUdpSourcePort; static uint16_t s_maxUdpSourcePort; +static double s_balancingFactor; RecursorControlChannel s_rcc; // only active in the handler thread RecursorStats g_stats; @@ -623,6 +626,7 @@ public: if(!tries) throw PDNSException("Resolver binding to local query client socket on "+sin.toString()+": "+stringerror()); + setReceiveSocketErrors(ret, family); setNonBlocking(ret); return ret; } @@ -1044,7 +1048,6 @@ static void startDoResolve(void *p) maxanswersize = min(static_cast(edo.d_packetsize >= 512 ? edo.d_packetsize : 512), g_udpTruncationThreshold); } ednsOpts = edo.d_options; - haveEDNS=true; maxanswersize -= 11; // EDNS header size for (const auto& o : edo.d_options) { @@ -2385,6 +2388,7 @@ static void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& var) distributeAsyncFunction(data, boost::bind(doProcessUDPQuestion, data, fromaddr, dest, tv, fd)); } else { + ++s_threadInfos[t_id].numberOfDistributedQueries; doProcessUDPQuestion(data, fromaddr, dest, tv, fd); } } @@ -2633,6 +2637,14 @@ static void doStats(void) g_log<(pleaseGetPacketCacheSize) << " packet cache entries, "<<(int)(100.0*broadcastAccFunction(pleaseGetPacketCacheHits)/SyncRes::s_queries) << "% packet cache hits"<numProcesses(); + } + return 0; +} + +static unsigned int selectWorker(unsigned int hash) +{ + if (s_balancingFactor == 0) { + return /* skip handler */ 1 + g_numDistributorThreads + (hash % g_numWorkerThreads); + } + + /* we start with one, representing the query we are currently handling */ + double currentLoad = 1; + std::vector load(g_numWorkerThreads); + for (size_t idx = 0; idx < g_numWorkerThreads; idx++) { + load[idx] = getWorkerLoad(idx); + currentLoad += load[idx]; + // cerr<<"load for worker "< targetLoad) { + ++g_stats.rebalancedQueries; + do { + // cerr<<"worker "< targetLoad); + } + + return /* skip handler */ 1 + g_numDistributorThreads + worker; +} + // This function is only called by the distributor threads, when pdns-distributes-queries is set void distributeAsyncFunction(const string& packet, const pipefunc_t& func) { @@ -2855,7 +2910,7 @@ void distributeAsyncFunction(const string& packet, const pipefunc_t& func) } unsigned int hash = hashQuestion(packet.c_str(), packet.length(), g_disthashseed); - unsigned int target = /* skip handler */ 1 + g_numDistributorThreads + (hash % g_numWorkerThreads); + unsigned int target = selectWorker(hash); ThreadMSG* tmsg = new ThreadMSG(); tmsg->func = func; @@ -2979,27 +3034,27 @@ template vector > broadcastAccFunction(const boost::funct static void handleRCC(int fd, FDMultiplexer::funcparam_t& var) { - string remote; - string msg=s_rcc.recv(&remote); - RecursorControlParser rcp; - RecursorControlParser::func_t* command; + try { + string remote; + string msg=s_rcc.recv(&remote); + RecursorControlParser rcp; + RecursorControlParser::func_t* command; - string answer=rcp.getAnswer(msg, &command); + string answer=rcp.getAnswer(msg, &command); - // If we are inside a chroot, we need to strip - if (!arg()["chroot"].empty()) { - size_t len = arg()["chroot"].length(); - remote = remote.substr(len); - } + // If we are inside a chroot, we need to strip + if (!arg()["chroot"].empty()) { + size_t len = arg()["chroot"].length(); + remote = remote.substr(len); + } - try { s_rcc.send(answer, &remote); command(); } - catch(std::exception& e) { + catch(const std::exception& e) { g_log<("recursor", ::arg()["snmp-master-socket"]); g_snmpAgent->run(); @@ -4009,6 +4081,7 @@ try } MT=std::unique_ptr >(new MTasker(::arg().asNum("stack-size"))); + threadInfo.mt = MT.get(); #ifdef HAVE_PROTOBUF /* start protobuf export threads if needed */ @@ -4158,6 +4231,7 @@ int main(int argc, char **argv) g_argc = argc; g_argv = argv; g_stats.startupTime=time(0); + Utility::srandom(); versionSetProduct(ProductRecursor); reportBasicTypes(); reportOtherTypes(); @@ -4196,6 +4270,7 @@ int main(int argc, char **argv) ::arg().set("webserver-port", "Port of webserver to listen on") = "8082"; ::arg().set("webserver-password", "Password required for accessing the webserver") = ""; ::arg().set("webserver-allow-from","Webserver access is only allowed from these subnets")="127.0.0.1,::1"; + ::arg().set("webserver-loglevel", "Amount of logging in the webserver (none, normal, detailed)") = "normal"; ::arg().set("carbon-ourname", "If set, overrides our reported hostname for carbon stats")=""; ::arg().set("carbon-server", "If set, send metrics in carbon (graphite) format to this server IP address")=""; ::arg().set("carbon-interval", "Number of seconds between carbon (graphite) updates")="30"; @@ -4222,6 +4297,7 @@ int main(int argc, char **argv) ::arg().set("hint-file", "If set, load root hints from this file")=""; ::arg().set("max-cache-entries", "If set, maximum number of entries in the main cache")="1000000"; ::arg().set("max-negative-ttl", "maximum number of seconds to keep a negative cached entry in memory")="3600"; + ::arg().set("max-cache-bogus-ttl", "maximum number of seconds to keep a Bogus (positive or negative) cached entry in memory")="3600"; ::arg().set("max-cache-ttl", "maximum number of seconds to keep a cached entry in memory")="86400"; ::arg().set("packetcache-ttl", "maximum number of seconds to keep a cached entry in packetcache")="3600"; ::arg().set("max-packetcache-entries", "maximum number of entries to keep in the packetcache")="500000"; @@ -4252,7 +4328,11 @@ int main(int argc, char **argv) ::arg().set("latency-statistic-size","Number of latency values to calculate the qa-latency average")="10000"; ::arg().setSwitch( "disable-packetcache", "Disable packetcache" )= "no"; ::arg().set("ecs-ipv4-bits", "Number of bits of IPv4 address to pass for EDNS Client Subnet")="24"; + ::arg().set("ecs-ipv4-cache-bits", "Maximum number of bits of IPv4 mask to cache ECS response")="24"; ::arg().set("ecs-ipv6-bits", "Number of bits of IPv6 address to pass for EDNS Client Subnet")="56"; + ::arg().set("ecs-ipv6-cache-bits", "Maximum number of bits of IPv6 mask to cache ECS response")="56"; + ::arg().set("ecs-minimum-ttl-override", "Set under adverse conditions, a minimum TTL for records in ECS-specific answers")="0"; + ::arg().set("ecs-cache-limit-ttl", "Minimum TTL to cache ECS response")="0"; ::arg().set("edns-subnet-whitelist", "List of netmasks and domains that we should enable EDNS subnet for")=""; ::arg().set("ecs-add-for", "List of client netmasks for which EDNS Client Subnet will be added")="0.0.0.0/0, ::/0, " LOCAL_NETS_INVERSE; ::arg().set("ecs-scope-zero-address", "Address to send to whitelisted authoritative servers for incoming queries with ECS prefix-length source of 0")=""; @@ -4278,6 +4358,18 @@ int main(int argc, char **argv) ::arg().setSwitch("snmp-agent", "If set, register as an SNMP agent")="no"; ::arg().set("snmp-master-socket", "If set and snmp-agent is set, the socket to use to register to the SNMP master")=""; + std::string defaultBlacklistedStats = "cache-bytes, packetcache-bytes, special-memory-usage"; + for (size_t idx = 0; idx < 32; idx++) { + defaultBlacklistedStats += ", ecs-v4-response-bits-" + std::to_string(idx + 1); + } + for (size_t idx = 0; idx < 128; idx++) { + defaultBlacklistedStats += ", ecs-v6-response-bits-" + std::to_string(idx + 1); + } + ::arg().set("stats-api-blacklist", "List of statistics that are disabled when retrieving the complete list of statistics via the API")=defaultBlacklistedStats; + ::arg().set("stats-carbon-blacklist", "List of statistics that are prevented from being exported via Carbon")=defaultBlacklistedStats; + ::arg().set("stats-rec-control-blacklist", "List of statistics that are prevented from being exported via rec_control get-all")=defaultBlacklistedStats; + ::arg().set("stats-snmp-blacklist", "List of statistics that are prevented from being exported via SNMP")=defaultBlacklistedStats; + ::arg().set("tcp-fast-open", "Enable TCP Fast Open support on the listening sockets, using the supplied numerical value as the queue size")="0"; ::arg().set("nsec3-max-iterations", "Maximum number of iterations allowed for an NSEC3 record")="2500"; @@ -4293,6 +4385,7 @@ int main(int argc, char **argv) ::arg().set("udp-source-port-avoid", "List of comma separated UDP port number to avoid")="11211"; ::arg().set("rng", "Specify random number generator to use. Valid values are auto,sodium,openssl,getrandom,arc4random,urandom.")="auto"; ::arg().set("public-suffix-list-file", "Path to the Public Suffix List file, if any")=""; + ::arg().set("distribution-load-factor", "The load factor used when PowerDNS is distributing queries to worker threads")="0.0"; #ifdef NOD_ENABLED ::arg().set("new-domain-tracking", "Track newly observed domains (i.e. never seen before).")="no"; ::arg().set("new-domain-log", "Log newly observed domains.")="yes";