]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
add "rndc fetchlimit" to show fetchlimited servers
authorEvan Hunt <each@isc.org>
Thu, 26 May 2022 09:33:52 +0000 (02:33 -0700)
committerEvan Hunt <each@isc.org>
Thu, 7 Jul 2022 02:46:20 +0000 (19:46 -0700)
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".

bin/named/control.c
bin/named/include/named/control.h
bin/named/include/named/server.h
bin/named/server.c
bin/rndc/rndc.rst
bin/tests/system/fetchlimit/tests.sh
doc/man/rndc.8in
lib/dns/adb.c
lib/dns/include/dns/adb.h

index 29c848b0703c143fc70e37293a0e07e97aa43587..0b742407fe1c8b875b7486b5e434b3892dcdac8f 100644 (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)) {
index 1ea4c490fbbfb5678315c6bc8555c6c99d1cd16a..425b50696f8b7ad644eeb88850fa808c1d3b0d11 100644 (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);
index d1c97cd853345c20186cac7accff7d8e9f22a3fc..ce45b440c1d3c9d86ff48ee59788189784c0d510 100644 (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);
index dcb7a708f409817dd4d6c5c4b0b2ef046dadd28b..b109683711965ed44350fb0fd62bfe76b248b928 100644 (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);
+}
index 6717e242d1d6a61a0cd1d1d78b4c8b3615d45823..2236d1d911f6343e13f46318414bed373978bace 100644 (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.
index c10bee667778c2cd3f0e45279b76d400a14049c9..a96caafa9d21726c93c47d247917f063cf7f78af 100644 (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))
 
index 4023b82ee2396626c8fdd1557c34d682ffb58ee3..c21fab7a61e6417a1647d91f1f2e17030cdc511c 100644 (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
index 7d549aa5eea03baf20c3e3bd1202dd3215364469..b97f3e63905c71286060178293bbe984c5375932 100644 (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;
index 4bfe6d0a42f030331468f267d28fb1af324ad2e3..1daa6b8e08d42bdbeb974a6de071c7f6eb2c4f93 100644 (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