@@ -245,26 +245,36 @@ class nsspeeds_t : public multi_index_container<DecayingEwmaCollection,
245
245
246
246
static LockGuarded<nsspeeds_t > s_nsSpeeds;
247
247
248
- template <class Thing >
249
- class Throttle : public boost ::noncopyable
248
+ class Throttle
250
249
{
251
250
public:
251
+ Throttle () = default ;
252
+ ~Throttle () = default ;
253
+ Throttle (Throttle&&) = delete ;
254
+ Throttle& operator =(const Throttle&) = default ;
255
+ Throttle& operator =(Throttle&&) = delete ;
256
+ Throttle (const Throttle&) = delete ;
257
+
258
+ using Key = std::tuple<ComboAddress, DNSName, QType>;
259
+ using Reason = SyncRes::ThrottleReason;
260
+
252
261
struct entry_t
253
262
{
254
- entry_t (const Thing& thing_, time_t ttd_, unsigned int count_) :
255
- thing (thing_), ttd(ttd_), count(count_)
263
+ entry_t (Key thing_, time_t ttd_, unsigned int count_, Reason reason_ ) :
264
+ thing (std::move( thing_)) , ttd(ttd_), count(count_), reason(reason_ )
256
265
{
257
266
}
258
- Thing thing;
267
+ Key thing;
259
268
time_t ttd;
260
269
mutable unsigned int count;
270
+ Reason reason;
261
271
};
262
272
using cont_t = multi_index_container<entry_t ,
263
273
indexed_by<
264
- ordered_unique<tag<Thing >, member<entry_t , Thing , &entry_t ::thing>>,
274
+ ordered_unique<tag<Key >, member<entry_t , Key , &entry_t ::thing>>,
265
275
ordered_non_unique<tag<time_t >, member<entry_t , time_t , &entry_t ::ttd>>>>;
266
276
267
- bool shouldThrottle (time_t now, const Thing & arg)
277
+ bool shouldThrottle (time_t now, const Key & arg)
268
278
{
269
279
auto iter = d_cont.find (arg);
270
280
if (iter == d_cont.end ()) {
@@ -279,18 +289,22 @@ class Throttle : public boost::noncopyable
279
289
return true ; // still listed, still blocked
280
290
}
281
291
282
- void throttle (time_t now, const Thing & arg, time_t ttl, unsigned int count)
292
+ void throttle (time_t now, const Key & arg, time_t ttl, unsigned int count, Reason reason )
283
293
{
284
294
auto iter = d_cont.find (arg);
285
295
time_t ttd = now + ttl;
286
296
if (iter == d_cont.end ()) {
287
- d_cont.emplace (arg, ttd, count);
297
+ d_cont.emplace (arg, ttd, count, reason );
288
298
}
289
299
else if (ttd > iter->ttd || count > iter->count ) {
290
300
ttd = std::max (iter->ttd , ttd);
291
301
count = std::max (iter->count , count);
292
- auto & ind = d_cont.template get <Thing>();
293
- ind.modify (iter, [ttd, count](entry_t & entry) { entry.ttd = ttd; entry.count = count; });
302
+ auto & ind = d_cont.template get <Key>();
303
+ ind.modify (iter, [ttd, count, reason](entry_t & entry) {
304
+ entry.ttd = ttd;
305
+ entry.count = count;
306
+ entry.reason = reason;
307
+ });
294
308
}
295
309
}
296
310
@@ -309,7 +323,7 @@ class Throttle : public boost::noncopyable
309
323
d_cont.clear ();
310
324
}
311
325
312
- void clear (const Thing & thing)
326
+ void clear (const Key & thing)
313
327
{
314
328
d_cont.erase (thing);
315
329
}
@@ -319,11 +333,31 @@ class Throttle : public boost::noncopyable
319
333
ind.erase (ind.begin (), ind.upper_bound (now));
320
334
}
321
335
336
+ static std::string toString (Reason reason)
337
+ {
338
+ static const std::array<std::string, 10 > reasons = {
339
+ " None" ,
340
+ " ServerDown" ,
341
+ " PermanentError" ,
342
+ " Timeout" ,
343
+ " ParseError" ,
344
+ " RCodeServFail" ,
345
+ " RCodeRefused" ,
346
+ " RCodeOther" ,
347
+ " TCPTruncate" ,
348
+ " Lame" };
349
+ const auto index = static_cast <unsigned int >(reason);
350
+ if (index >= reasons.size ()) {
351
+ return " ?" ;
352
+ }
353
+ return reasons.at (index);
354
+ }
355
+
322
356
private:
323
357
cont_t d_cont;
324
358
};
325
359
326
- static LockGuarded<Throttle<std::tuple<ComboAddress, DNSName, QType>> > s_throttle;
360
+ static LockGuarded<Throttle> s_throttle;
327
361
328
362
struct SavedParentEntry
329
363
{
@@ -1279,14 +1313,14 @@ void SyncRes::unThrottle(const ComboAddress& server, const DNSName& name, QType
1279
1313
s_throttle.lock ()->clear (std::tuple (server, name, qtype));
1280
1314
}
1281
1315
1282
- void SyncRes::doThrottle (time_t now, const ComboAddress& server, time_t duration, unsigned int tries)
1316
+ void SyncRes::doThrottle (time_t now, const ComboAddress& server, time_t duration, unsigned int tries, Throttle::Reason reason )
1283
1317
{
1284
- s_throttle.lock ()->throttle (now, std::tuple (server, g_rootdnsname, 0 ), duration, tries);
1318
+ s_throttle.lock ()->throttle (now, std::tuple (server, g_rootdnsname, 0 ), duration, tries, reason );
1285
1319
}
1286
1320
1287
- void SyncRes::doThrottle (time_t now, const ComboAddress& server, const DNSName& name, QType qtype, time_t duration, unsigned int tries)
1321
+ void SyncRes::doThrottle (time_t now, const ComboAddress& server, const DNSName& name, QType qtype, time_t duration, unsigned int tries, Throttle::Reason reason )
1288
1322
{
1289
- s_throttle.lock ()->throttle (now, std::tuple (server, name, qtype), duration, tries);
1323
+ s_throttle.lock ()->throttle (now, std::tuple (server, name, qtype), duration, tries, reason );
1290
1324
}
1291
1325
1292
1326
uint64_t SyncRes::doDumpThrottleMap (int fileDesc)
@@ -1301,16 +1335,16 @@ uint64_t SyncRes::doDumpThrottleMap(int fileDesc)
1301
1335
return 0 ;
1302
1336
}
1303
1337
fprintf (filePtr.get (), " ; throttle map dump follows\n " );
1304
- fprintf (filePtr.get (), " ; remote IP\t qname\t qtype\t count\t ttd\n " );
1338
+ fprintf (filePtr.get (), " ; remote IP\t qname\t qtype\t count\t ttd\t reason \ n" );
1305
1339
uint64_t count = 0 ;
1306
1340
1307
1341
// Get a copy to avoid holding the lock while doing I/O
1308
1342
const auto throttleMap = s_throttle.lock ()->getThrottleMap ();
1309
1343
for (const auto & iter : throttleMap) {
1310
1344
count++;
1311
1345
timebuf_t tmp;
1312
- // remote IP, dns name, qtype, count, ttd
1313
- fprintf (filePtr.get (), " %s\t %s\t %s\t %u\t %s\n " , std::get<0 >(iter.thing ).toString ().c_str (), std::get<1 >(iter.thing ).toLogString ().c_str (), std::get<2 >(iter.thing ).toString ().c_str (), iter.count , timestamp (iter.ttd , tmp));
1346
+ // remote IP, dns name, qtype, count, ttd, reason
1347
+ fprintf (filePtr.get (), " %s\t %s\t %s\t %u\t %s\t %s \ n" , std::get<0 >(iter.thing ).toString ().c_str (), std::get<1 >(iter.thing ).toLogString ().c_str (), std::get<2 >(iter.thing ).toString ().c_str (), iter.count , timestamp (iter.ttd , tmp), Throttle::toString (iter. reason ). c_str ( ));
1314
1348
}
1315
1349
1316
1350
return count;
@@ -5415,19 +5449,19 @@ bool SyncRes::doResolveAtThisIP(const std::string& prefix, const DNSName& qname,
5415
5449
if (s_serverdownmaxfails > 0 && auth != g_rootdnsname && s_fails.lock ()->incr (remoteIP, d_now) >= s_serverdownmaxfails) {
5416
5450
LOG (prefix << qname << " : Max fails reached resolving on " << remoteIP.toString () << " . Going full throttle for " << s_serverdownthrottletime << " seconds" << endl);
5417
5451
// mark server as down
5418
- doThrottle (d_now.tv_sec , remoteIP, s_serverdownthrottletime, 10000 );
5452
+ doThrottle (d_now.tv_sec , remoteIP, s_serverdownthrottletime, 10000 , Throttle::Reason::ServerDown );
5419
5453
}
5420
5454
else if (resolveret == LWResult::Result::PermanentError) {
5421
5455
// unreachable, 1 minute or 100 queries
5422
- doThrottle (d_now.tv_sec , remoteIP, qname, qtype, 60 , 100 );
5456
+ doThrottle (d_now.tv_sec , remoteIP, qname, qtype, 60 , 100 , Throttle::Reason::PermanentError );
5423
5457
}
5424
5458
else {
5425
5459
// If the actual response time was more than 80% of the default timeout, we throttle. On a
5426
5460
// busy rec we reduce the time we are willing to wait for an auth, it is unfair to throttle on
5427
5461
// such a shortened timeout.
5428
5462
if (responseUsec > g_networkTimeoutMsec * 800 ) {
5429
5463
// timeout, 10 seconds or 5 queries
5430
- doThrottle (d_now.tv_sec , remoteIP, qname, qtype, 10 , 5 );
5464
+ doThrottle (d_now.tv_sec , remoteIP, qname, qtype, 10 , 5 , Throttle::Reason::Timeout );
5431
5465
}
5432
5466
}
5433
5467
}
@@ -5444,10 +5478,10 @@ bool SyncRes::doResolveAtThisIP(const std::string& prefix, const DNSName& qname,
5444
5478
5445
5479
if (doTCP) {
5446
5480
// we can be more heavy-handed over TCP
5447
- doThrottle (d_now.tv_sec , remoteIP, qname, qtype, 60 , 10 );
5481
+ doThrottle (d_now.tv_sec , remoteIP, qname, qtype, 60 , 10 , Throttle::Reason::ParseError );
5448
5482
}
5449
5483
else {
5450
- doThrottle (d_now.tv_sec , remoteIP, qname, qtype, 10 , 2 );
5484
+ doThrottle (d_now.tv_sec , remoteIP, qname, qtype, 10 , 2 , Throttle::Reason::ParseError );
5451
5485
}
5452
5486
}
5453
5487
return false ;
@@ -5463,7 +5497,19 @@ bool SyncRes::doResolveAtThisIP(const std::string& prefix, const DNSName& qname,
5463
5497
s_nsSpeeds.lock ()->find_or_enter (nsName.empty () ? DNSName (remoteIP.toStringWithPort ()) : nsName, d_now).submit (remoteIP, 1000000 , d_now); // 1 sec
5464
5498
}
5465
5499
else {
5466
- doThrottle (d_now.tv_sec , remoteIP, qname, qtype, 60 , 3 );
5500
+ Throttle::Reason reason{};
5501
+ switch (lwr.d_rcode ) {
5502
+ case RCode::ServFail:
5503
+ reason = Throttle::Reason::RCodeServFail;
5504
+ break ;
5505
+ case RCode::Refused:
5506
+ reason = Throttle::Reason::RCodeRefused;
5507
+ break ;
5508
+ default :
5509
+ reason = Throttle::Reason::RCodeOther;
5510
+ break ;
5511
+ }
5512
+ doThrottle (d_now.tv_sec , remoteIP, qname, qtype, 60 , 3 , reason);
5467
5513
}
5468
5514
}
5469
5515
return false ;
@@ -5483,7 +5529,7 @@ bool SyncRes::doResolveAtThisIP(const std::string& prefix, const DNSName& qname,
5483
5529
LOG (prefix << qname << " : Truncated bit set, over TCP?" << endl);
5484
5530
if (!dontThrottle) {
5485
5531
/* let's treat that as a ServFail answer from this server */
5486
- doThrottle (d_now.tv_sec , remoteIP, qname, qtype, 60 , 3 );
5532
+ doThrottle (d_now.tv_sec , remoteIP, qname, qtype, 60 , 3 , Throttle::Reason::TCPTruncate );
5487
5533
}
5488
5534
return false ;
5489
5535
}
@@ -5889,7 +5935,7 @@ int SyncRes::doResolveAt(NsSet& nameservers, DNSName auth, bool flawedNSSet, con
5889
5935
}
5890
5936
/* was lame */
5891
5937
if (!shouldNotThrottle (&tns->first , &*remoteIP)) {
5892
- doThrottle (d_now.tv_sec , *remoteIP, qname, qtype, 60 , 100 );
5938
+ doThrottle (d_now.tv_sec , *remoteIP, qname, qtype, 60 , 100 , Throttle::Reason::Lame );
5893
5939
}
5894
5940
}
5895
5941
0 commit comments