Commit 59ffc112 authored by Daniel Salzman's avatar Daniel Salzman

Merge branch 'parallel_sign2' into 'master'

Parallel signing

Closes #186

See merge request !956
parents fdfcc172 c58f3b41
......@@ -673,6 +673,7 @@ policy:
nsec3\-opt\-out: BOOL
nsec3\-salt\-length: INT
nsec3\-salt\-lifetime: TIME
signing\-threads: INT
ksk\-submission: submission_id
cds\-cdnskey\-publish: none | delete\-dnssec | rollover | always
offline\-ksk: BOOL
......@@ -867,6 +868,20 @@ A reference to \fI\%submission\fP section holding parameters of
KSK submittion checks.
.sp
\fIDefault:\fP not set
.SS signing\-threads
.sp
When signing zone or update, use this number of threads for parallel signing.
.sp
Those are extra threads independent of \fI\%Background workers\fP\&.
.sp
\fBNOTE:\fP
.INDENT 0.0
.INDENT 3.5
Some steps of the DNSSEC signing operation are not parallelized.
.UNINDENT
.UNINDENT
.sp
\fIDefault:\fP 1 (no extra threads)
.SS cds\-cdnskey\-publish
.sp
Controls if and how shall the CDS and CDNSKEY be published in the zone.
......
......@@ -745,6 +745,7 @@ DNSSEC policy configuration.
nsec3-opt-out: BOOL
nsec3-salt-length: INT
nsec3-salt-lifetime: TIME
signing-threads: INT
ksk-submission: submission_id
cds-cdnskey-publish: none | delete-dnssec | rollover | always
offline-ksk: BOOL
......@@ -984,6 +985,20 @@ KSK submittion checks.
*Default:* not set
.. _policy_signing-threads:
signing-threads
---------------
When signing zone or update, use this number of threads for parallel signing.
Those are extra threads independent of :ref:`Background workers<server_background-workers>`.
.. NOTE::
Some steps of the DNSSEC signing operation are not parallelized.
*Default:* 1 (no extra threads)
.. _policy_cds-cdnskey-publish:
cds-cdnskey-publish
......
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -288,6 +288,7 @@ static const yp_item_t desc_policy[] = {
CONF_IO_FRLD_ZONES },
{ C_KSK_SBM, YP_TREF, YP_VREF = { C_SBM }, CONF_IO_FRLD_ZONES,
{ check_ref } },
{ C_SIGNING_THREADS, YP_TINT, YP_VINT = { 1, UINT16_MAX, 1 } },
{ C_CHILD_RECORDS, YP_TOPT, YP_VOPT = { child_record, CHILD_RECORDS_ALWAYS } },
{ C_OFFLINE_KSK, YP_TBOOL, YP_VNONE, CONF_IO_FRLD_ZONES },
{ C_COMMENT, YP_TSTR, YP_VNONE },
......
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -96,6 +96,7 @@
#define C_SEM_CHECKS "\x0F""semantic-checks"
#define C_SERIAL_POLICY "\x0D""serial-policy"
#define C_SERVER "\x06""server"
#define C_SIGNING_THREADS "\x0F""signing-threads"
#define C_SINGLE_TYPE_SIGNING "\x13""single-type-signing"
#define C_SRV "\x06""server"
#define C_STATS "\x0A""statistics"
......
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -118,6 +118,9 @@ static void policy_load(knot_kasp_policy_t *policy, conf_val_t *id)
}
}
val = conf_id_get(conf(), C_POLICY, C_SIGNING_THREADS, id);
policy->signing_threads = conf_int(&val);
val = conf_id_get(conf(), C_POLICY, C_OFFLINE_KSK, id);
policy->offline_ksk = conf_bool(&val);
}
......
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -116,6 +116,7 @@ typedef struct {
uint32_t ksk_sbm_check_interval;
unsigned child_records_publish;
parent_dynarray_t parents;
uint16_t signing_threads;
bool offline_ksk;
} knot_kasp_policy_t;
// TODO make the time parameters knot_timediff_t ??
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -16,6 +16,8 @@
#include "knot/dnssec/key_records.h"
#include "libdnssec/error.h"
#include "libdnssec/sign.h"
#include "knot/dnssec/rrset-sign.h"
#include "knot/dnssec/zone-sign.h"
#include "knot/journal/serialization.h"
......@@ -134,16 +136,23 @@ int key_records_sign(const zone_key_t *key, key_records_t *r, const kdnssec_ctx_
return KNOT_EOK;
}
int ret = KNOT_EOK;
dnssec_sign_ctx_t *sign_ctx;
int ret = dnssec_sign_new(&sign_ctx, key->key);
if (ret != DNSSEC_EOK) {
knot_error_from_libdnssec(ret);
}
if (!knot_rrset_empty(&r->dnskey) && knot_zone_sign_use_key(key, &r->dnskey)) {
ret = knot_sign_rrset(&r->rrsig, &r->dnskey, key->key, key->ctx, kctx, NULL, NULL);
ret = knot_sign_rrset(&r->rrsig, &r->dnskey, key->key, sign_ctx, kctx, NULL, NULL);
}
if (ret == KNOT_EOK && !knot_rrset_empty(&r->cdnskey) && knot_zone_sign_use_key(key, &r->cdnskey)) {
ret = knot_sign_rrset(&r->rrsig, &r->cdnskey, key->key, key->ctx, kctx, NULL, NULL);
ret = knot_sign_rrset(&r->rrsig, &r->cdnskey, key->key, sign_ctx, kctx, NULL, NULL);
}
if (ret == KNOT_EOK && !knot_rrset_empty(&r->cds) && knot_zone_sign_use_key(key, &r->cds)) {
ret = knot_sign_rrset(&r->rrsig, &r->cds, key->key, key->ctx, kctx, NULL, NULL);
ret = knot_sign_rrset(&r->rrsig, &r->cds, key->key, sign_ctx, kctx, NULL, NULL);
}
dnssec_sign_free(sign_ctx);
return ret;
}
......
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -19,6 +19,7 @@
#include "contrib/wire_ctx.h"
#include "libdnssec/error.h"
#include "knot/dnssec/rrset-sign.h"
#include "knot/dnssec/zone-sign.h"
#include "libknot/libknot.h"
#define RRSIG_RDATA_SIGNER_OFFSET 18
......@@ -278,6 +279,30 @@ int knot_sign_rrset(knot_rrset_t *rrsigs, const knot_rrset_t *covered,
return ret;
}
int knot_sign_rrset2(knot_rrset_t *rrsigs, const knot_rrset_t *rrset,
zone_sign_ctx_t *sign_ctx, knot_mm_t *mm)
{
if (rrsigs == NULL || rrset == NULL || sign_ctx == NULL) {
return KNOT_EINVAL;
}
for (size_t i = 0; i < sign_ctx->count; i++) {
zone_key_t *key = &sign_ctx->keys[i];
if (!knot_zone_sign_use_key(key, rrset)) {
continue;
}
int ret = knot_sign_rrset(rrsigs, rrset, key->key, sign_ctx->sign_ctxs[i],
sign_ctx->dnssec_ctx, mm, NULL);
if (ret != KNOT_EOK) {
return ret;
}
}
return KNOT_EOK;
}
int knot_synth_rrsig(uint16_t type, const knot_rdataset_t *rrsig_rrs,
knot_rdataset_t *out_sig, knot_mm_t *mm)
{
......
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -19,6 +19,7 @@
#include "libdnssec/key.h"
#include "libdnssec/sign.h"
#include "knot/dnssec/context.h"
#include "knot/dnssec/zone-keys.h"
#include "libknot/rrset.h"
/*!
......@@ -42,6 +43,21 @@ int knot_sign_rrset(knot_rrset_t *rrsigs,
knot_mm_t *mm,
knot_time_t *expires);
/*!
* \brief Create RRSIG RR for given RR set, choose which key to use.
*
* \param rrsigs RR set with RRSIGs into which the result will be added.
* \param rrset RR set to create a new signature for.
* \param sign_ctx Zone signing context.
* \param mm Memory context.
*
* \return Error code, KNOT_EOK if successful.
*/
int knot_sign_rrset2(knot_rrset_t *rrsigs,
const knot_rrset_t *rrset,
zone_sign_ctx_t *sign_ctx,
knot_mm_t *mm);
/*!
* \brief Add all data covered by signature into signing context.
*
......
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -177,24 +177,15 @@ int kdnssec_delete_key(kdnssec_ctx_t *ctx, knot_kasp_key_t *key_ptr)
/*!
* \brief Get key feature flags from key parameters.
*/
static int set_key(knot_kasp_key_t *kasp_key, knot_time_t now, zone_key_t *zone_key)
static void set_key(knot_kasp_key_t *kasp_key, knot_time_t now, zone_key_t *zone_key)
{
assert(kasp_key);
assert(zone_key);
knot_kasp_key_timing_t *timing = &kasp_key->timing;
// cryptographic context
dnssec_sign_ctx_t *ctx = NULL;
int r = dnssec_sign_new(&ctx, kasp_key->key);
if (r != DNSSEC_EOK) {
return r;
}
zone_key->id = kasp_key->id;
zone_key->key = kasp_key->key;
zone_key->ctx = ctx;
// next event computation
......@@ -238,8 +229,6 @@ static int set_key(knot_kasp_key_t *kasp_key, knot_time_t now, zone_key_t *zone_
(knot_time_cmp(timing->active, now) <= 0) ? (
(knot_time_cmp(timing->retire_active, now) <= 0 ||
knot_time_cmp(timing->retire, now) <= 0) ? 0 : 1) : 2) : 0);
return KNOT_EOK;
}
/*!
......@@ -440,7 +429,6 @@ void free_zone_keys(zone_keyset_t *keyset)
}
for (size_t i = 0; i < keyset->count; i++) {
dnssec_sign_free(keyset->keys[i].ctx);
dnssec_binary_free(&keyset->keys[i].precomputed_ds);
}
......@@ -449,23 +437,6 @@ void free_zone_keys(zone_keyset_t *keyset)
memset(keyset, '\0', sizeof(*keyset));
}
/*!
* \brief Get zone keys by keytag.
*/
struct keyptr_dynarray get_zone_keys(const zone_keyset_t *keyset, uint16_t search)
{
struct keyptr_dynarray res = { 0 };
for (size_t i = 0; keyset && i < keyset->count; i++) {
zone_key_t *key = &keyset->keys[i];
if (key != NULL && dnssec_key_get_keytag(key->key) == search) {
keyptr_dynarray_add(&res, &key);
}
}
return res;
}
/*!
* \brief Get timestamp of next key event.
*/
......@@ -504,3 +475,35 @@ int zone_key_calculate_ds(zone_key_t *for_key, dnssec_binary_t *out_donotfree)
*out_donotfree = for_key->precomputed_ds;
return ret;
}
zone_sign_ctx_t *zone_sign_ctx(const zone_keyset_t *keyset, const kdnssec_ctx_t *dnssec_ctx)
{
zone_sign_ctx_t *ctx = calloc(1, sizeof(*ctx) + keyset->count * sizeof(*ctx->sign_ctxs));
if (ctx == NULL) {
return NULL;
}
ctx->sign_ctxs = (dnssec_sign_ctx_t **)(ctx + 1);
ctx->count = keyset->count;
ctx->keys = keyset->keys;
ctx->dnssec_ctx = dnssec_ctx;
for (size_t i = 0; i < ctx->count; i++) {
int ret = dnssec_sign_new(&ctx->sign_ctxs[i], ctx->keys[i].key);
if (ret != DNSSEC_EOK) {
zone_sign_ctx_free(ctx);
return NULL;
}
}
return ctx;
}
void zone_sign_ctx_free(zone_sign_ctx_t *ctx)
{
if (ctx != NULL) {
for (size_t i = 0; i < ctx->count; i++) {
dnssec_sign_free(ctx->sign_ctxs[i]);
}
free(ctx);
}
}
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -29,7 +29,6 @@
typedef struct {
const char *id;
dnssec_key_t *key;
dnssec_sign_ctx_t *ctx;
dnssec_binary_t precomputed_ds;
......@@ -49,6 +48,16 @@ typedef struct {
zone_key_t *keys;
} zone_keyset_t;
/*!
* \brief Signing context used for single signing thread.
*/
typedef struct {
size_t count; // number of keys in keyset
zone_key_t *keys; // keys in keyset
dnssec_sign_ctx_t **sign_ctxs; // signing buffers for keys in keyset
const kdnssec_ctx_t *dnssec_ctx; // dnssec context
} zone_sign_ctx_t;
/*!
* \brief Flags determining key type
*/
......@@ -119,16 +128,6 @@ int kdnssec_delete_key(kdnssec_ctx_t *ctx, knot_kasp_key_t *key_ptr);
*/
int load_zone_keys(kdnssec_ctx_t *ctx, zone_keyset_t *keyset_ptr, bool verbose);
/*!
* \brief Get zone keys by a keytag.
*
* \param keyset Zone keyset.
* \param search Keytag to lookup a key for.
*
* \return Dynarray of pointers to keys.
*/
struct keyptr_dynarray get_zone_keys(const zone_keyset_t *keyset, uint16_t search);
/*!
* \brief Free structure with zone keys and associated DNSSEC contexts.
*
......@@ -156,3 +155,22 @@ knot_time_t knot_get_next_zone_key_event(const zone_keyset_t *keyset);
* \return Error code, KNOT_EOK if successful.
*/
int zone_key_calculate_ds(zone_key_t *for_key, dnssec_binary_t *out_donotfree);
/*!
* \brief Initialize local signing context.
*
* \param keyset Key set.
* \param dnssec_ctx DNSSEC context.
*
* \return New local signing context or NULL.
*/
zone_sign_ctx_t *zone_sign_ctx(const zone_keyset_t *keyset, const kdnssec_ctx_t *dnssec_ctx);
/*!
* \brief Free local signing context.
*
* \note This doesn't free the underlying keyset.
*
* \param ctx Local context to be freed.
*/
void zone_sign_ctx_free(zone_sign_ctx_t *ctx);
This diff is collapsed.
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -526,6 +526,13 @@ int knotd_mod_dnssec_init(knotd_mod_t *mod);
*/
int knotd_mod_dnssec_load_keyset(knotd_mod_t *mod, bool verbose);
/*!
* Frees up resources before re-loading DNSSEC signing keys.
*
* \param[in] mod Module context.
*/
void knotd_mod_dnssec_unload_keyset(knotd_mod_t *mod);
/*!
* Generates RRSIGs for given RRSet.
*
......
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -26,6 +26,7 @@
#include "knot/dnssec/ds_query.h"
#include "knot/dnssec/key-events.h"
#include "knot/dnssec/policy.h"
#include "knot/dnssec/rrset-sign.h"
#include "knot/dnssec/zone-events.h"
#include "knot/nameserver/query_module.h"
#include "knot/nameserver/process_query.h"
......@@ -249,6 +250,7 @@ static knot_rrset_t *synth_nsec(knot_pkt_t *pkt, knotd_qdata_t *qdata, knotd_mod
static knot_rrset_t *sign_rrset(const knot_dname_t *owner,
const knot_rrset_t *cover,
knotd_mod_t *mod,
zone_sign_ctx_t *sign_ctx,
knot_mm_t *mm)
{
// copy of RR set with replaced owner name
......@@ -275,7 +277,7 @@ static knot_rrset_t *sign_rrset(const knot_dname_t *owner,
online_sign_ctx_t *ctx = knotd_mod_ctx(mod);
pthread_rwlock_rdlock(&ctx->signing_mutex);
int ret = knotd_mod_dnssec_sign_rrset(mod, rrsig, copy, mm);
int ret = knot_sign_rrset2(rrsig, copy, sign_ctx, mm);
pthread_rwlock_unlock(&ctx->signing_mutex);
if (ret != KNOT_EOK) {
knot_rrset_free(copy, NULL);
......@@ -327,6 +329,11 @@ static knotd_in_state_t sign_section(knotd_in_state_t state, knot_pkt_t *pkt,
const knot_pktsection_t *section = knot_pkt_section(pkt, pkt->current);
assert(section);
zone_sign_ctx_t *sign_ctx = zone_sign_ctx(mod->keyset, mod->dnssec);
if (sign_ctx == NULL) {
return KNOTD_IN_STATE_ERROR;
}
uint16_t count_unsigned = section->count;
for (int i = 0; i < count_unsigned; i++) {
const knot_rrset_t *rr = knot_pkt_rr(section, i);
......@@ -340,7 +347,7 @@ static knotd_in_state_t sign_section(knotd_in_state_t state, knot_pkt_t *pkt,
knot_dname_unpack(owner, pkt->wire + rr_pos, sizeof(owner), pkt->wire);
knot_dname_to_lower(owner);
knot_rrset_t *rrsig = sign_rrset(owner, rr, mod, &pkt->mm);
knot_rrset_t *rrsig = sign_rrset(owner, rr, mod, sign_ctx, &pkt->mm);
if (!rrsig) {
state = KNOTD_IN_STATE_ERROR;
break;
......@@ -354,6 +361,8 @@ static knotd_in_state_t sign_section(knotd_in_state_t state, knot_pkt_t *pkt,
}
}
zone_sign_ctx_free(sign_ctx);
return state;
}
......@@ -550,9 +559,7 @@ static knotd_in_state_t pre_routine(knotd_in_state_t state, knot_pkt_t *pkt,
ctx->event_rollover = resch.next_rollover;
pthread_rwlock_wrlock(&ctx->signing_mutex);
free_zone_keys(mod->keyset);
free(mod->keyset);
mod->keyset = NULL;
knotd_mod_dnssec_unload_keyset(mod);
ret = knotd_mod_dnssec_load_keyset(mod, true);
if (ret != KNOT_EOK) {
ctx->zone_doomed = true;
......
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -161,6 +161,7 @@ void query_module_close(knotd_mod_t *module)
knotd_mod_stats_free(module);
conf_free_mod_id(module->id);
zone_sign_ctx_free(module->sign_ctx);
free_zone_keys(module->keyset);
free(module->keyset);
kdnssec_ctx_deinit(module->dnssec);
......@@ -604,30 +605,37 @@ int knotd_mod_dnssec_load_keyset(knotd_mod_t *mod, bool verbose)
return ret;
}
mod->sign_ctx = zone_sign_ctx(mod->keyset, mod->dnssec);
if (mod->sign_ctx == NULL) {
free_zone_keys(mod->keyset);
free(mod->keyset);
mod->keyset = NULL;
return KNOT_ENOMEM;
}
return KNOT_EOK;
}
_public_
void knotd_mod_dnssec_unload_keyset(knotd_mod_t *mod)
{
if (mod != NULL && mod->keyset != NULL) {
zone_sign_ctx_free(mod->sign_ctx);
mod->sign_ctx = NULL;
free_zone_keys(mod->keyset);
free(mod->keyset);
mod->keyset = NULL;
}
}
_public_
int knotd_mod_dnssec_sign_rrset(knotd_mod_t *mod, knot_rrset_t *rrsigs,
const knot_rrset_t *rrset, knot_mm_t *mm)
{
if (mod == NULL || mod->keyset == NULL || rrsigs == NULL || rrset == NULL) {
if (mod == NULL || rrsigs == NULL || rrset == NULL) {
return KNOT_EINVAL;
}
for (size_t i = 0; i < mod->keyset->count; i++) {
zone_key_t *key = &mod->keyset->keys[i];
if (!knot_zone_sign_use_key(key, rrset)) {
continue;
}
int ret = knot_sign_rrset(rrsigs, rrset, key->key, key->ctx,
mod->dnssec, mm, NULL);
if (ret != KNOT_EOK) {
return ret;
}
}
return KNOT_EOK;
return knot_sign_rrset2(rrsigs, rrset, mod->sign_ctx, mm);
}
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -89,6 +89,7 @@ struct knotd_mod {
const knotd_mod_api_t *api;
kdnssec_ctx_t *dnssec;
zone_keyset_t *keyset;
zone_sign_ctx_t *sign_ctx;
mod_ctr_t *stats;
uint32_t stats_count;
void *ctx;
......
......@@ -15,3 +15,12 @@
...
fun:call_rcu_memb
}
{
pthread/shared_stack
Memcheck:Leak
match-leak-kinds: possible,reachable
fun:calloc
...
fun:allocate_stack
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment