+5373. [bug] Collecting DNSSEC signing operations introduced by
+ GL #513 (change 5254) allocated counters for every
+ possible key id per zone which results in a lot of
+ wasted memory. Fix by tracking up to four keys
+ per zone, rotate counters when keys are replaced.
+ [GL #1179]
+
5372. [bug] Fix migration from existing DNSSEC key files using
auto-dnssec maintain to dnssec-policy. [GL #1706]
isc_stats_t *gluecachestats;
dns_stats_t *rcvquerystats;
dns_stats_t *dnssecsignstats;
- dns_stats_t *dnssecrefreshstats;
uint64_t nsstat_values[ns_statscounter_max];
uint64_t gluecachestats_values[dns_gluecachestatscounter_max];
dnssecsignstats = dns_zone_getdnssecsignstats(zone);
if (dnssecsignstats != NULL) {
+ /* counters type="dnssec-sign"*/
TRY0(xmlTextWriterStartElement(writer,
ISC_XMLCHAR "counters"));
TRY0(xmlTextWriterWriteAttribute(
ISC_XMLCHAR "dnssec-sign"));
dumparg.result = ISC_R_SUCCESS;
- dns_dnssecsignstats_dump(dnssecsignstats,
+ dns_dnssecsignstats_dump(dnssecsignstats, false,
dnssecsignstat_dump, &dumparg,
0);
if (dumparg.result != ISC_R_SUCCESS) {
/* counters type="dnssec-sign"*/
TRY0(xmlTextWriterEndElement(writer));
- }
- dnssecrefreshstats = dns_zone_getdnssecrefreshstats(zone);
- if (dnssecrefreshstats != NULL) {
+ /* counters type="dnssec-refresh"*/
TRY0(xmlTextWriterStartElement(writer,
ISC_XMLCHAR "counters"));
TRY0(xmlTextWriterWriteAttribute(
ISC_XMLCHAR "dnssec-refresh"));
dumparg.result = ISC_R_SUCCESS;
- dns_dnssecsignstats_dump(dnssecrefreshstats,
+ dns_dnssecsignstats_dump(dnssecsignstats, true,
dnssecsignstat_dump, &dumparg,
0);
if (dumparg.result != ISC_R_SUCCESS) {
isc_stats_t *gluecachestats;
dns_stats_t *rcvquerystats;
dns_stats_t *dnssecsignstats;
- dns_stats_t *dnssecrefreshstats;
uint64_t nsstat_values[ns_statscounter_max];
uint64_t gluecachestats_values[dns_gluecachestatscounter_max];
dumparg.type = isc_statsformat_json;
dumparg.arg = counters;
dumparg.result = ISC_R_SUCCESS;
- dns_dnssecsignstats_dump(dnssecsignstats,
+ dns_dnssecsignstats_dump(dnssecsignstats, false,
dnssecsignstat_dump, &dumparg,
0);
if (dumparg.result != ISC_R_SUCCESS) {
}
}
- dnssecrefreshstats = dns_zone_getdnssecrefreshstats(zone);
- if (dnssecrefreshstats != NULL) {
+ if (dnssecsignstats != NULL) {
stats_dumparg_t dumparg;
json_object *counters = json_object_new_object();
CHECKMEM(counters);
dumparg.type = isc_statsformat_json;
dumparg.arg = counters;
dumparg.result = ISC_R_SUCCESS;
- dns_dnssecsignstats_dump(dnssecrefreshstats,
+ dns_dnssecsignstats_dump(dnssecsignstats, true,
dnssecsignstat_dump, &dumparg,
0);
if (dumparg.result != ISC_R_SUCCESS) {
isc_stats_t *zoneqrystats;
dns_stats_t *rcvquerystats;
dns_stats_t *dnssecsignstats;
- dns_stats_t *dnssecrefreshstats;
dns_zonestat_level_t statlevel = dns_zonestat_none;
int seconds;
dns_zone_t *mayberaw = (raw != NULL) ? raw : zone;
zoneqrystats = NULL;
rcvquerystats = NULL;
dnssecsignstats = NULL;
- dnssecrefreshstats = NULL;
if (statlevel == dns_zonestat_full) {
RETERR(isc_stats_create(mctx, &zoneqrystats,
ns_statscounter_max));
RETERR(dns_rdatatypestats_create(mctx, &rcvquerystats));
RETERR(dns_dnssecsignstats_create(mctx, &dnssecsignstats));
- RETERR(dns_dnssecsignstats_create(mctx, &dnssecrefreshstats));
}
dns_zone_setrequeststats(zone, zoneqrystats);
dns_zone_setrcvquerystats(zone, rcvquerystats);
dns_zone_setdnssecsignstats(zone, dnssecsignstats);
- dns_zone_setdnssecrefreshstats(zone, dnssecrefreshstats);
if (zoneqrystats != NULL) {
isc_stats_detach(&zoneqrystats);
dns_stats_detach(&dnssecsignstats);
}
- if (dnssecrefreshstats != NULL) {
- dns_stats_detach(&dnssecrefreshstats);
- }
-
/*
* Configure master functionality. This applies
* to primary masters (type "master") and slaves
*/
void
-dns_dnssecsignstats_increment(dns_stats_t *stats, dns_keytag_t id);
+dns_dnssecsignstats_increment(dns_stats_t *stats, dns_keytag_t id,
+ bool refresh);
/*%<
- * Increment the statistics counter for the DNSKEY 'id'.
+ * Increment the statistics counter for the DNSKEY 'id'. If 'refresh' is set
+ * to true, update the refresh counter, otherwise update the sign counter.
*
* Requires:
*\li 'stats' is a valid dns_stats_t created by dns_dnssecsignstats_create().
*/
void
-dns_dnssecsignstats_dump(dns_stats_t * stats,
+dns_dnssecsignstats_dump(dns_stats_t *stats, bool refresh,
dns_dnssecsignstats_dumper_t dump_fn, void *arg,
unsigned int options);
/*%<
void
dns_zone_setdnssecsignstats(dns_zone_t *zone, dns_stats_t *stats);
-
-void
-dns_zone_setdnssecrefreshstats(dns_zone_t *zone, dns_stats_t *stats);
/*%<
* Set additional statistics sets to zone. These are attached to the zone
* but are not counted in the zone module; only the caller updates the
dns_stats_t *
dns_zone_getdnssecsignstats(dns_zone_t *zone);
-
-dns_stats_t *
-dns_zone_getdnssecrefreshstats(dns_zone_t *zone);
/*%<
* Get the additional statistics for zone, if one is installed.
*
* otherwise NULL.
*/
-/*%<
- * Set additional statistics sets to zone. These are attached to the zone
- * but are not counted in the zone module; only the caller updates the
- * counters.
- *
- * Requires:
- * \li 'zone' to be a valid zone.
- *
- *\li stats is a valid statistics.
- */
-
void
dns_zone_dialup(dns_zone_t *zone);
/*%<
#include <isc/stats.h>
#include <isc/util.h>
+#include <dns/log.h>
#include <dns/opcode.h>
#include <dns/rdatatype.h>
#include <dns/stats.h>
*/
#define RDTYPECOUNTER_MAXVAL 0x0602
-/* dnssec maximum key id */
-static int dnssec_keyid_max = 65535;
+/*
+ * DNSSEC sign statistics.
+ *
+ * Per key we maintain 3 counters. The first is actually no counter but
+ * a key id reference. The second is the number of signatures the key created.
+ * The third is the number of signatures refreshed by the key.
+ */
+
+/* Maximum number of keys to keep track of for DNSSEC signing statistics. */
+static int dnssec_max_keys = 4;
+/* Attribute to signal whether a counter is actually a key id. */
+#define DNSSECSIGNSTATS_IS_KEY 0x10000
struct dns_stats {
unsigned int magic;
dns_dnssecsignstats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
REQUIRE(statsp != NULL && *statsp == NULL);
- return (create_stats(mctx, dns_statstype_dnssec, dnssec_keyid_max,
+ /*
+ * Create two counters per key, one is the key id, the other two are
+ * the actual counters for creating and refreshing signatures.
+ */
+ return (create_stats(mctx, dns_statstype_dnssec, dnssec_max_keys * 3,
statsp));
}
}
void
-dns_dnssecsignstats_increment(dns_stats_t *stats, dns_keytag_t id) {
+dns_dnssecsignstats_increment(dns_stats_t *stats, dns_keytag_t id,
+ bool refresh) {
+ isc_statscounter_t operation;
+ uint32_t kval;
+
REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_dnssec);
- isc_stats_increment(stats->counters, (isc_statscounter_t)id);
+ kval = (uint32_t)id;
+ kval |= DNSSECSIGNSTATS_IS_KEY;
+
+ /* What operation are we counting? */
+ if (refresh) {
+ operation = (isc_statscounter_t)dnssec_max_keys * 2;
+ } else {
+ operation = (isc_statscounter_t)dnssec_max_keys;
+ }
+
+ /* Look up correct counter. */
+ for (int i = 0; i < dnssec_max_keys; i++) {
+ uint32_t counter = isc_stats_get_counter(stats->counters, i);
+ if (counter == kval) {
+ /* Match */
+ isc_stats_increment(stats->counters, operation + i);
+ return;
+ }
+ }
+
+ /* No match found. Store key in unused slot. */
+ for (int i = 0; i < dnssec_max_keys; i++) {
+ uint32_t counter = isc_stats_get_counter(stats->counters, i);
+ if (counter == 0) {
+ isc_stats_set(stats->counters, kval, i);
+ isc_stats_increment(stats->counters, operation + i);
+ return;
+ }
+ }
+
+ /* No room, rotate keys. */
+ for (int i = 1; i < dnssec_max_keys; i++) {
+ uint32_t keyv = isc_stats_get_counter(stats->counters, i);
+ uint32_t sign = isc_stats_get_counter(stats->counters,
+ (dnssec_max_keys + i));
+ uint32_t refr = isc_stats_get_counter(
+ stats->counters, (dnssec_max_keys * 2 + i));
+
+ isc_stats_set(stats->counters, keyv, i - 1);
+ isc_stats_set(stats->counters, sign, dnssec_max_keys + i - 1);
+ isc_stats_set(stats->counters, refr,
+ dnssec_max_keys * 2 + i - 1);
+ }
+
+ /* Reset counters for new key. */
+ isc_stats_set(stats->counters, kval, dnssec_max_keys - 1);
+ isc_stats_set(stats->counters, 0, 2 * dnssec_max_keys - 1);
+ isc_stats_set(stats->counters, 0, 3 * dnssec_max_keys - 1);
+
+ /* And increment the counter for the given operation. */
+ isc_stats_increment(stats->counters, operation + dnssec_max_keys - 1);
}
/*%
dnssecarg->fn((dns_keytag_t)counter, value, dnssecarg->arg);
}
+static void
+dnssec_statsdump(isc_stats_t *stats, bool refresh, isc_stats_dumper_t dump_fn,
+ void *arg, unsigned int options) {
+ int i;
+ isc_statscounter_t operation;
+
+ if (refresh) {
+ operation = (isc_statscounter_t)dnssec_max_keys * 2;
+ } else {
+ operation = (isc_statscounter_t)dnssec_max_keys;
+ }
+
+ for (i = 0; i < dnssec_max_keys; i++) {
+ uint32_t kval, val;
+ dns_keytag_t id;
+
+ kval = isc_stats_get_counter(stats, i);
+ if (kval == 0) {
+ continue;
+ }
+
+ val = isc_stats_get_counter(stats, (operation + i));
+ if ((options & ISC_STATSDUMP_VERBOSE) == 0 && val == 0) {
+ continue;
+ }
+
+ id = (dns_keytag_t)kval;
+ id &= ~DNSSECSIGNSTATS_IS_KEY;
+
+ dump_fn((isc_statscounter_t)id, val, arg);
+ }
+}
+
void
-dns_dnssecsignstats_dump(dns_stats_t *stats,
+dns_dnssecsignstats_dump(dns_stats_t *stats, bool refresh,
dns_dnssecsignstats_dumper_t dump_fn, void *arg0,
unsigned int options) {
dnssecsigndumparg_t arg;
arg.fn = dump_fn;
arg.arg = arg0;
- isc_stats_dump(stats->counters, dnssec_dumpcb, &arg, options);
+
+ dnssec_statsdump(stats->counters, refresh, dnssec_dumpcb, &arg,
+ options);
}
static void
added_sig = true;
/* Update DNSSEC sign statistics. */
if (dnssecsignstats != NULL) {
- dns_dnssecsignstats_increment(dnssecsignstats,
- dst_key_id(keys[i]));
+ dns_dnssecsignstats_increment(
+ dnssecsignstats, dst_key_id(keys[i]), false);
}
}
if (!added_sig) {
dns_zone_getclass
dns_zone_getdb
dns_zone_getdbtype
-dns_zone_getdnssecrefreshstats
dns_zone_getdnssecsignstats
dns_zone_getexpiretime
dns_zone_getfile
dns_zone_setdb
dns_zone_setdbtype
dns_zone_setdialup
-dns_zone_setdnssecrefreshstats
dns_zone_setdnssecsignstats
dns_zone_setfile
dns_zone_setflag
isc_stats_t *requeststats;
dns_stats_t *rcvquerystats;
dns_stats_t *dnssecsignstats;
- dns_stats_t *dnssecrefreshstats;
uint32_t notifydelay;
dns_isselffunc_t isself;
void *isselfarg;
zone->requeststats = NULL;
zone->rcvquerystats = NULL;
zone->dnssecsignstats = NULL;
- zone->dnssecrefreshstats = NULL;
zone->notifydelay = 5;
zone->isself = NULL;
zone->isselfarg = NULL;
if (zone->dnssecsignstats != NULL) {
dns_stats_detach(&zone->dnssecsignstats);
}
- if (zone->dnssecrefreshstats != NULL) {
- dns_stats_detach(&zone->dnssecrefreshstats);
- }
if (zone->db != NULL) {
zone_detachdb(zone);
}
dns_dbnode_t *node = NULL;
dns_kasp_t *kasp = dns_zone_getkasp(zone);
dns_stats_t *dnssecsignstats;
- dns_stats_t *dnssecrefreshstats;
dns_rdataset_t rdataset;
dns_rdata_t sig_rdata = DNS_RDATA_INIT;
unsigned char data[1024]; /* XXX */
/* Update DNSSEC sign statistics. */
dnssecsignstats = dns_zone_getdnssecsignstats(zone);
- dnssecrefreshstats = dns_zone_getdnssecrefreshstats(zone);
if (dnssecsignstats != NULL) {
+ /* Generated a new signature. */
dns_dnssecsignstats_increment(
- dns_zone_getdnssecsignstats(zone),
- dst_key_id(keys[i]));
- }
- if (dnssecrefreshstats != NULL) {
+ dnssecsignstats, dst_key_id(keys[i]), false);
+ /* This is a refresh. */
dns_dnssecsignstats_increment(
- dns_zone_getdnssecrefreshstats(zone),
- dst_key_id(keys[i]));
+ dnssecsignstats, dst_key_id(keys[i]), true);
}
}
dns_rdataset_t rdataset;
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_stats_t *dnssecsignstats;
- dns_stats_t *dnssecrefreshstats;
isc_buffer_t buffer;
unsigned char data[1024];
/* Update DNSSEC sign statistics. */
dnssecsignstats = dns_zone_getdnssecsignstats(zone);
- dnssecrefreshstats = dns_zone_getdnssecrefreshstats(zone);
if (dnssecsignstats != NULL) {
- dns_dnssecsignstats_increment(
- dns_zone_getdnssecsignstats(zone),
- dst_key_id(key));
- }
- if (dnssecrefreshstats != NULL) {
- dns_dnssecsignstats_increment(
- dns_zone_getdnssecrefreshstats(zone),
- dst_key_id(key));
+ /* Generated a new signature. */
+ dns_dnssecsignstats_increment(dnssecsignstats,
+ dst_key_id(key), false);
+ /* This is a refresh. */
+ dns_dnssecsignstats_increment(dnssecsignstats,
+ dst_key_id(key), true);
}
(*signatures)--;
UNLOCK_ZONE(zone);
}
-void
-dns_zone_setdnssecrefreshstats(dns_zone_t *zone, dns_stats_t *stats) {
- REQUIRE(DNS_ZONE_VALID(zone));
-
- LOCK_ZONE(zone);
- if (stats != NULL && zone->dnssecrefreshstats == NULL) {
- dns_stats_attach(stats, &zone->dnssecrefreshstats);
- }
- UNLOCK_ZONE(zone);
-}
-
dns_stats_t *
dns_zone_getdnssecsignstats(dns_zone_t *zone) {
REQUIRE(DNS_ZONE_VALID(zone));
return (zone->dnssecsignstats);
}
-dns_stats_t *
-dns_zone_getdnssecrefreshstats(dns_zone_t *zone) {
- REQUIRE(DNS_ZONE_VALID(zone));
-
- return (zone->dnssecrefreshstats);
-}
-
isc_stats_t *
dns_zone_getrequeststats(dns_zone_t *zone) {
/*