dnskey-ttl: TIME
zone-max-ttl: TIME
keytag-modulo: INT/INT
- dnssec-jitter: TIME
+ dnssec-jitter: TIME | INT%
ksk-lifetime: TIME
zsk-lifetime: TIME
deleg-adt: BOOL
A pseudo-random jitter added to :ref:`policy_rrsig-refresh` and subtracted from
:ref:`policy_zsk-lifetime`.
-The jitter value is selected from the interval between 0 and the configured value
-and is deterministic based on the zone name.
+The jitter value (in seconds or as a percentage of the adjusted value) is selected
+from the interval between 0 and the configured value and is deterministic
+based on the zone name.
The goal is to prevent DNSSEC maintenance events for a large number of configured
zones from interfering with other regular zone events.
serial-modulo: INT/INT | +INT | -INT | INT/INT+INT | INT/INT-INT
reverse-generate: DNAME ...
include-from: DNAME ...
- refresh-jitter: TIME
+ refresh-jitter: TIME | INT%
refresh-min-interval: TIME
refresh-max-interval: TIME
retry-min-interval: TIME
A pseudo-random jitter that shortens the SOA refresh timer.
-The jitter value is selected from the interval between 0 and the configured value
-and is deterministic based on the zone name.
+The jitter value (in seconds or as a percentage of the adjusted value) is selected
+from the interval between 0 and the configured value and is deterministic
+based on the zone name.
The goal is to prevent zone refreshes for a large number of configured zones
from interfering with NOTIFY-initiated zone refreshes.
int64_t conf_int_alt(
conf_val_t *val,
- bool alternative)
+ bool alternative,
+ bool *percent)
{
assert(val != NULL && val->item != NULL);
assert(val->item->type == YP_TINT ||
if (val->code == KNOT_EOK) {
conf_val(val);
- return yp_int(val->data);
+ return (percent == NULL) ? yp_int(val->data) : yp_int_pct(val->data, percent);
} else {
+ if (percent != NULL) {
+ *percent = false;
+ }
return alternative ? val->item->var.i.dflt_alt : val->item->var.i.dflt;
}
}
int64_t conf_jitter(
conf_val_t *jitter_val,
+ int64_t base_value,
+ int64_t max_value,
const knot_dname_t *zone)
{
- int64_t intval = conf_int(jitter_val);
+ bool percent;
+ int64_t intval = conf_int_alt(jitter_val, false, &percent);
if (intval < 1) {
return intval;
+ } else if (percent) {
+ intval = intval * base_value / 100;
}
SIPHASH_KEY zero_key = { 0, 0 };
uint64_t random64 = SipHash24_End(&ctx);
uint64_t granularity = (1 << 16);
- return (1 + intval) * (random64 & (granularity - 1)) / granularity;
+ int64_t out = (1 + intval) * (random64 & (granularity - 1)) / granularity;
+ return MIN(out, max_value);
}
bool conf_bool(
* Gets the numeric value of the item.
*
* \param[in] val Item value.
+ * \param[out] percent Percentual value indication.
* \param[in] alternative Use alternative default value.
*
* \return Integer.
*/
int64_t conf_int_alt(
conf_val_t *val,
- bool alternative
+ bool alternative,
+ bool *percent
);
inline static int64_t conf_int(
conf_val_t *val)
{
- return conf_int_alt(val, false);
+ return conf_int_alt(val, false, NULL);
}
/*!
* ...pseudo-random, deterministic based on zone name.
*
* \param[in] jitter_val Jitter value item.
+ * \param[in] base_value Base value for percentual computation.
+ * \param[in] max_value Maximum allowed output value.
* \param[in] zone Zone name.
*
* \return Integer.
*/
int64_t conf_jitter(
conf_val_t *jitter_val,
- const knot_dname_t *zone);
+ int64_t base_value,
+ int64_t max_value,
+ const knot_dname_t *zone
+);
/*!
* Gets the boolean value of the item.
{ C_ZONE_MAX_TTL, YP_TINT, YP_VINT = { 0, INT32_MAX, YP_NIL, YP_STIME },
CONF_IO_FRLD_ZONES },
{ C_KEYTAG_MODULO, YP_TSTR, YP_VSTR = { "0/1" }, YP_FNONE, { check_modulo } },
- { C_DNSSEC_JITTER, YP_TINT, YP_VINT = { 0, UINT32_MAX, 0, YP_STIME } },
+ { C_DNSSEC_JITTER, YP_TINT, YP_VINT = { 0, UINT32_MAX, 0, YP_STIME | YP_SPERCENT } },
{ C_KSK_LIFETIME, YP_TINT, YP_VINT = { 0, UINT32_MAX, 0, YP_STIME },
CONF_IO_FRLD_ZONES },
{ C_ZSK_LIFETIME, YP_TINT, YP_VINT = { 0, UINT32_MAX, DAYS(30), YP_STIME },
{ C_SERIAL_MODULO, YP_TSTR, YP_VSTR = { "0/1" }, YP_FNONE, { check_modulo_shift } }, \
{ C_ZONEMD_GENERATE, YP_TOPT, YP_VOPT = { zone_digest, ZONE_DIGEST_NONE }, FLAGS }, \
{ C_ZONEMD_VERIFY, YP_TBOOL, YP_VNONE, FLAGS }, \
- { C_REFRESH_JITTER, YP_TINT, YP_VINT = { 0, UINT32_MAX, 0, YP_STIME } }, \
+ { C_REFRESH_JITTER, YP_TINT, YP_VINT = { 0, UINT32_MAX, 0, YP_STIME | YP_SPERCENT } }, \
{ C_REFRESH_MIN_INTERVAL,YP_TINT, YP_VINT = { 2, UINT32_MAX, 2, YP_STIME } }, \
{ C_REFRESH_MAX_INTERVAL,YP_TINT, YP_VINT = { 2, UINT32_MAX, UINT32_MAX, YP_STIME } }, \
{ C_RETRY_MIN_INTERVAL, YP_TINT, YP_VINT = { 1, UINT32_MAX, 1, YP_STIME } }, \
}
val = conf_id_get(conf, C_POLICY, C_DNSSEC_JITTER, id);
- int64_t jitter = conf_jitter(&val, zone_name);
- policy->rrsig_refresh_before += jitter;
- policy->zsk_lifetime -= jitter;
+ policy->rrsig_refresh_before += conf_jitter(&val, policy->rrsig_refresh_before, policy->rrsig_lifetime - 1, zone_name);
+ if (policy->zsk_lifetime != 0) { // 0 ~ infinity!
+ policy->zsk_lifetime -= conf_jitter(&val, policy->zsk_lifetime, policy->zsk_lifetime - 1, zone_name);
+ }
}
static void policy_unload(knot_kasp_policy_t *policy)
conf_val_t val = conf_id_get(conf, C_POLICY, C_SIGNING_THREADS, &policy_id);
ctx->policy->signing_threads = conf_int(&val);
val = conf_id_get(conf, C_POLICY, C_RRSIG_REFRESH, &policy_id);
- ctx->policy->rrsig_refresh_before = conf_int_alt(&val, true);
+ ctx->policy->rrsig_refresh_before = conf_int_alt(&val, true, NULL);
} else if (threads > 0) {
ctx->policy->signing_threads = threads;
} else {
limit_timer(conf, zone->name, &soa_refresh, "refresh",
C_REFRESH_MIN_INTERVAL, C_REFRESH_MAX_INTERVAL);
conf_val_t refresh_jitter = conf_zone_get(conf, C_REFRESH_JITTER, zone->name);
- zone->timers->next_refresh = now + soa_refresh - conf_jitter(&refresh_jitter, zone->name);
+ zone->timers->next_refresh = now + soa_refresh;
+ zone->timers->next_refresh -= conf_jitter(&refresh_jitter, soa_refresh, soa_refresh - 1, zone->name);
zone->timers->flags |= LAST_REFRESH_OK | TIMERS_MODIFIED;
if (zone->is_catalog_flag) {