add "rndc fetchlimit" to show fetchlimited servers

this command runs dns_adb_dumpquota() to display all servers
in the ADB that are being actively fetchlimited by the
fetches-per-server controls (i.e, servers with a nonzero average
timeout ratio or with the quota having been reduced from the
default value).

the "fetchlimit" system test has been updated to use the
new command to check quota values instead of "rndc dumpdb".
This commit is contained in:
Evan Hunt 2022-05-26 02:33:52 -07:00
parent 7cac4ca03c
commit 6175897478
9 changed files with 210 additions and 12 deletions

View file

@ -218,6 +218,8 @@ named_control_docommand(isccc_sexpr_t *message, bool readonly,
result = ISC_R_SUCCESS;
} else if (command_compare(command, NAMED_COMMAND_DUMPSTATS)) {
result = named_server_dumpstats(named_g_server);
} else if (command_compare(command, NAMED_COMMAND_FETCHLIMIT)) {
result = named_server_fetchlimit(named_g_server, lex, text);
} else if (command_compare(command, NAMED_COMMAND_FLUSH)) {
result = named_server_flushcache(named_g_server, lex);
} else if (command_compare(command, NAMED_COMMAND_FLUSHNAME)) {

View file

@ -70,6 +70,7 @@
#define NAMED_COMMAND_DNSTAP "dnstap"
#define NAMED_COMMAND_TCPTIMEOUTS "tcp-timeouts"
#define NAMED_COMMAND_SERVESTALE "serve-stale"
#define NAMED_COMMAND_FETCHLIMIT "fetchlimit"
isc_result_t
named_controls_create(named_server_t *server, named_controls_t **ctrlsp);

View file

@ -401,3 +401,10 @@ named_server_tcptimeouts(isc_lex_t *lex, isc_buffer_t **text);
isc_result_t
named_server_servestale(named_server_t *server, isc_lex_t *lex,
isc_buffer_t **text);
/*%
* Report fetch-limited ADB server addresses.
*/
isc_result_t
named_server_fetchlimit(named_server_t *server, isc_lex_t *lex,
isc_buffer_t **text);

View file

@ -16600,3 +16600,70 @@ cleanup:
return (result);
}
isc_result_t
named_server_fetchlimit(named_server_t *server, isc_lex_t *lex,
isc_buffer_t **text) {
isc_result_t result = ISC_R_SUCCESS;
dns_view_t *view = NULL;
char *ptr = NULL, *viewname = NULL;
bool first = true;
REQUIRE(text != NULL);
/* Skip the command name. */
ptr = next_token(lex, text);
if (ptr == NULL) {
return (ISC_R_UNEXPECTEDEND);
}
/* Look for the view name. */
viewname = next_token(lex, text);
for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
view = ISC_LIST_NEXT(view, link))
{
char tbuf[BUFSIZ];
unsigned int used;
uint32_t val;
int s;
if (view->rdclass != dns_rdataclass_in) {
continue;
}
if (viewname != NULL && strcasecmp(view->name, viewname) != 0) {
continue;
}
if (view->adb == NULL) {
continue;
}
if (!first) {
putstr(text, "\n");
}
putstr(text, "Rate limited servers, view ");
putstr(text, view->name);
dns_adb_getquota(view->adb, &val, NULL, NULL, NULL, NULL);
s = snprintf(tbuf, sizeof(tbuf),
" (fetches-per-server %u):", val);
if (s < 0 || (unsigned)s > sizeof(tbuf)) {
return (ISC_R_NOSPACE);
}
first = false;
putstr(text, tbuf);
used = isc_buffer_usedlength(*text);
CHECK(dns_adb_dumpquota(view->adb, text));
if (used == isc_buffer_usedlength(*text)) {
putstr(text, "\n None.");
}
}
cleanup:
if (isc_buffer_usedlength(*text) > 0) {
(void)putnull(text);
}
return (result);
}

View file

@ -204,6 +204,11 @@ Currently supported commands are:
(See the ``dump-file`` option in the BIND 9 Administrator Reference
Manual.)
.. option:: fetchlimit [view]
This command dumps a list of servers which are currently being
rate-limited as a result of ``fetches-per-server`` settings.
.. option:: flush
This command flushes the server's cache.

View file

@ -58,12 +58,11 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status+ret))
echo_i "dumping ADB data"
$RNDCCMD dumpdb -adb
info=`grep '10.53.0.4' ns3/named_dump.db | sed 's/.*\(atr [.0-9]*\).*\(quota [0-9]*\).*/\1 \2/'`
info=$($RNDCCMD fetchlimit | grep 10.53.0.4 | sed 's/.*quota .*(\([0-9]*\).*atr \([.0-9]*\).*/\2 \1/')
echo_i $info
set -- $info
quota=$5
[ ${5:-200} -lt 200 ] || ret=1
quota=$2
[ ${quota:-200} -lt 200 ] || ret=1
echo_i "checking servfail statistics"
ret=0
@ -92,12 +91,11 @@ for try in 1 2 3 4 5; do
done
echo_i "dumping ADB data"
$RNDCCMD dumpdb -adb
info=`grep '10.53.0.4' ns3/named_dump.db | sed 's/.*\(atr [.0-9]*\).*\(quota [0-9]*\).*/\1 \2/'`
info=$($RNDCCMD fetchlimit | grep 10.53.0.4 | sed 's/.*quota .*(\([0-9]*\).*atr \([.0-9]*\).*/\2 \1/')
echo_i $info
set -- $info
[ ${5:-${quota}} -lt $quota ] || ret=1
quota=$5
[ ${2:-${quota}} -lt $quota ] || ret=1
quota=$2
for try in 1 2 3 4 5 6 7 8 9 10; do
burst c $try
@ -107,12 +105,11 @@ for try in 1 2 3 4 5 6 7 8 9 10; do
done
echo_i "dumping ADB data"
$RNDCCMD dumpdb -adb
info=`grep '10.53.0.4' ns3/named_dump.db | sed 's/.*\(atr [.0-9]*\).*\(quota [0-9]*\).*/\1 \2/'`
info=$($RNDCCMD fetchlimit | grep 10.53.0.4 | sed 's/.*quota .*(\([0-9]*\).*atr \([.0-9]*\).*/\2 \1/')
echo_i $info
set -- $info
[ ${5:-${quota}} -gt $quota ] || ret=1
quota=$5
[ ${2:-${quota}} -gt $quota ] || ret=1
quota=$2
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status+ret))

View file

@ -226,6 +226,12 @@ Manual.)
.UNINDENT
.INDENT 0.0
.TP
.B fetchlimit [view]
This command dumps a list of servers which are currently being
rate\-limited as a result of \fBfetches\-per\-server\fP settings.
.UNINDENT
.INDENT 0.0
.TP
.B flush
This command flushes the server\(aqs cache.
.UNINDENT

View file

@ -2976,6 +2976,67 @@ print_find_list(FILE *f, dns_adbname_t *name) {
}
}
static isc_result_t
putstr(isc_buffer_t **b, const char *str) {
isc_result_t result;
result = isc_buffer_reserve(b, strlen(str));
if (result != ISC_R_SUCCESS) {
return (result);
}
isc_buffer_putstr(*b, str);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_adb_dumpquota(dns_adb_t *adb, isc_buffer_t **buf) {
isc_result_t result;
isc_ht_iter_t *it = NULL;
REQUIRE(DNS_ADB_VALID(adb));
RWLOCK(&adb->entries_lock, isc_rwlocktype_read);
isc_ht_iter_create(adb->entrybuckets, &it);
for (result = isc_ht_iter_first(it); result == ISC_R_SUCCESS;
result = isc_ht_iter_next(it))
{
dns_adbentrybucket_t *ebucket = NULL;
dns_adbentry_t *entry = NULL;
isc_ht_iter_current(it, (void **)&ebucket);
LOCK(&ebucket->lock);
for (entry = ISC_LIST_HEAD(ebucket->entries); entry != NULL;
entry = ISC_LIST_NEXT(entry, plink))
{
char addrbuf[ISC_NETADDR_FORMATSIZE];
char text[BUFSIZ];
isc_netaddr_t netaddr;
if (entry->atr == 0.0 && entry->quota == adb->quota) {
continue;
}
isc_netaddr_fromsockaddr(&netaddr, &entry->sockaddr);
isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
snprintf(text, sizeof(text),
"\n- quota %s (%" PRIuFAST32 "/%d) atr %0.2f",
addrbuf, atomic_load_relaxed(&entry->quota),
adb->quota, entry->atr);
putstr(buf, text);
}
UNLOCK(&ebucket->lock);
}
RWUNLOCK(&adb->entries_lock, isc_rwlocktype_read);
isc_ht_iter_destroy(&it);
if (result == ISC_R_NOMORE) {
result = ISC_R_SUCCESS;
}
return (result);
}
static isc_result_t
dbfind_name(dns_adbname_t *adbname, isc_stdtime_t now, dns_rdatatype_t rdtype) {
isc_result_t result;
@ -3965,6 +4026,32 @@ dns_adb_setquota(dns_adb_t *adb, uint32_t quota, uint32_t freq, double low,
adb->atr_discount = discount;
}
void
dns_adb_getquota(dns_adb_t *adb, uint32_t *quotap, uint32_t *freqp,
double *lowp, double *highp, double *discountp) {
REQUIRE(DNS_ADB_VALID(adb));
if (quotap != NULL) {
*quotap = adb->quota;
}
if (freqp != NULL) {
*freqp = adb->atr_freq;
}
if (lowp != NULL) {
*lowp = adb->atr_low;
}
if (highp != NULL) {
*highp = adb->atr_high;
}
if (discountp != NULL) {
*discountp = adb->atr_discount;
}
}
bool
dns_adbentry_overquota(dns_adbentry_t *entry) {
uint_fast32_t quota, active;

View file

@ -748,6 +748,20 @@ dns_adb_setquota(dns_adb_t *adb, uint32_t quota, uint32_t freq, double low,
*\li 'adb' is valid.
*/
void
dns_adb_getquota(dns_adb_t *adb, uint32_t *quotap, uint32_t *freqp,
double *lowp, double *highp, double *discountp);
/*%<
* Get the quota values set by dns_adb_setquota().
* If any of the 'quotap', 'freqp', 'lowp', 'highp', and
* 'discountp' parameters are non-NULL, then the memory they
* point to will be updated to hold the corresponding quota
* or parameter value.
*
* Requires:
*\li 'adb' is valid.
*/
bool
dns_adbentry_overquota(dns_adbentry_t *entry);
/*%<
@ -782,4 +796,16 @@ dns_adb_getstats(dns_adb_t *adb);
* Requires:
* \li 'adb' is valid.
*/
isc_result_t
dns_adb_dumpquota(dns_adb_t *adb, isc_buffer_t **buf);
/*%
* Dump the addresses, current quota values, and current ATR values
* for all servers that are currently being fetchlimited. Servers
* for which the quota is still equal to the default and the ATR
* is zero are not printed.
*
* Requires:
* \li 'adb' is valid.
*/
ISC_LANG_ENDDECLS