From: Daniel Salzman Date: Mon, 27 Jul 2026 10:43:06 +0000 (+0200) Subject: conf: add percent support to 'dnssec-jitter' and 'refresh-jitter' X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a4300780ce8e828057de11200a2e655695f51526;p=thirdparty%2Fknot-dns.git conf: add percent support to 'dnssec-jitter' and 'refresh-jitter' --- diff --git a/doc/reference.rst b/doc/reference.rst index eaef49cbd9..59a21ca97a 100644 --- a/doc/reference.rst +++ b/doc/reference.rst @@ -2119,7 +2119,7 @@ DNSSEC policy configuration. 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 @@ -2305,8 +2305,9 @@ dnssec-jitter 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. @@ -2828,7 +2829,7 @@ Definition of zones served by the server. 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 @@ -3546,8 +3547,9 @@ refresh-jitter 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. diff --git a/src/knot/conf/conf.c b/src/knot/conf/conf.c index 5c5ca330fc..5f0e2f1eb6 100644 --- a/src/knot/conf/conf.c +++ b/src/knot/conf/conf.c @@ -616,7 +616,8 @@ void conf_mix_iter_next( 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 || @@ -627,19 +628,27 @@ int64_t conf_int_alt( 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 }; @@ -649,7 +658,8 @@ int64_t conf_jitter( 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( diff --git a/src/knot/conf/conf.h b/src/knot/conf/conf.h index adb8f28e64..bb5da9738d 100644 --- a/src/knot/conf/conf.h +++ b/src/knot/conf/conf.h @@ -469,18 +469,20 @@ void conf_mix_iter_next( * 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); } /*! @@ -490,13 +492,18 @@ inline static int64_t conf_int( * ...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. diff --git a/src/knot/conf/schema.c b/src/knot/conf/schema.c index 75e7e7e522..d966cb23c7 100644 --- a/src/knot/conf/schema.c +++ b/src/knot/conf/schema.c @@ -444,7 +444,7 @@ static const yp_item_t desc_policy[] = { { 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 }, @@ -537,7 +537,7 @@ static const yp_item_t desc_external[] = { { 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 } }, \ diff --git a/src/knot/dnssec/context.c b/src/knot/dnssec/context.c index a1a7bda4d8..2759885e11 100644 --- a/src/knot/dnssec/context.c +++ b/src/knot/dnssec/context.c @@ -177,9 +177,10 @@ static void policy_load(knot_kasp_policy_t *policy, conf_t *conf, conf_val_t *id } 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) @@ -390,7 +391,7 @@ int kdnssec_validation_ctx(conf_t *conf, kdnssec_ctx_t *ctx, const zone_contents 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 { diff --git a/src/knot/events/handlers/refresh.c b/src/knot/events/handlers/refresh.c index e0f5041073..37244cae8e 100644 --- a/src/knot/events/handlers/refresh.c +++ b/src/knot/events/handlers/refresh.c @@ -204,7 +204,8 @@ static void finalize_timers_base(struct refresh_data *data, bool also_expire) 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) {