+4447. [tuning] Allow the fstrm_iothr_init() options to be set using
+ named.conf to control how dnstap manages the data
+ flow. [RT #42974]
+
4446. [bug] The cache_find() and _findrdataset() functions
could find rdatasets that had been marked stale.
[RT #42853]
coresize <replaceable>size</replaceable>;
datasize <replaceable>size</replaceable>;
directory <replaceable>quoted_string</replaceable>;
+ dnstap { <replaceable>message_type</replaceable>; ... };
+ dnstap-output ( <literal>file</literal> | <literal>unix</literal> ) <replaceable>path_name</replaceable>;
+ dnstap-identity ( <replaceable>string</replaceable> | <literal>hostname</literal> | <literal>none</literal> );
+ dnstap-version ( <replaceable>string</replaceable> | <literal>none</literal> );
dump-file <replaceable>quoted_string</replaceable>;
files <replaceable>size</replaceable>;
+ fstrm-set-buffer-hint <replaceable>number</replaceable>;
+ fstrm-set-flush-timeout <replaceable>number</replaceable>;
+ fstrm-set-input-queue-size <replaceable>number</replaceable>;
+ fstrm-set-output-notify-threshold <replaceable>number</replaceable>;
+ fstrm-set-output-queue-model ( <replaceable>mpsc</replaceable> | <replaceable>spsc</replaceable> ) ;
+ fstrm-set-output-queue-size <replaceable>number</replaceable>;
+ fstrm-set-reopen-interval <replaceable>number</replaceable>;
heartbeat-interval <replaceable>integer</replaceable>;
host-statistics <replaceable>boolean</replaceable>; // not implemented
host-statistics-max <replaceable>number</replaceable>; // not implemented
const cfg_obj_t *dlist = NULL;
dns_dtmsgtype_t dttypes = 0;
dns_dtmode_t dmode;
+ unsigned int i;
+ struct fstrm_iothr_options *fopt = NULL;
result = ns_config_get(maps, "dnstap", &dlist);
if (result != ISC_R_SUCCESS)
dpath = cfg_obj_asstring(obj2);
- CHECKM(dns_dt_create(ns_g_mctx, dmode, dpath, ns_g_cpus,
+ fopt = fstrm_iothr_options_init();
+ fstrm_iothr_options_set_num_input_queues(fopt, ns_g_cpus);
+ fstrm_iothr_options_set_queue_model(fopt,
+ FSTRM_IOTHR_QUEUE_MODEL_MPSC);
+
+ obj = NULL;
+ result = ns_config_get(maps, "fstrm-set-buffer-hint", &obj);
+ if (result == ISC_R_SUCCESS) {
+ i = cfg_obj_asuint32(obj);
+ fstrm_iothr_options_set_buffer_hint(fopt, i);
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps, "fstrm-set-flush-timeout", &obj);
+ if (result == ISC_R_SUCCESS) {
+ i = cfg_obj_asuint32(obj);
+ fstrm_iothr_options_set_flush_timeout(fopt, i);
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps, "fstrm-set-input-queue-size",
+ &obj);
+ if (result == ISC_R_SUCCESS) {
+ i = cfg_obj_asuint32(obj);
+ fstrm_iothr_options_set_input_queue_size(fopt, i);
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps,
+ "fstrm-set-output-notify-threshold",
+ &obj);
+ if (result == ISC_R_SUCCESS) {
+ i = cfg_obj_asuint32(obj);
+ fstrm_iothr_options_set_queue_notify_threshold(fopt,
+ i);
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps, "fstrm-set-output-queue-model",
+ &obj);
+ if (result == ISC_R_SUCCESS) {
+ if (strcasecmp(cfg_obj_asstring(obj), "spsc") == 0)
+ i = FSTRM_IOTHR_QUEUE_MODEL_SPSC;
+ else
+ i = FSTRM_IOTHR_QUEUE_MODEL_MPSC;
+ fstrm_iothr_options_set_queue_model(fopt, i);
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps, "fstrm-set-output-queue-size",
+ &obj);
+ if (result == ISC_R_SUCCESS) {
+ i = cfg_obj_asuint32(obj);
+ fstrm_iothr_options_set_output_queue_size(fopt, i);
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps, "fstrm-set-reopen-interval",
+ &obj);
+ if (result == ISC_R_SUCCESS) {
+ i = cfg_obj_asuint32(obj);
+ fstrm_iothr_options_set_reopen_interval(fopt, i);
+ }
+
+ CHECKM(dns_dt_create(ns_g_mctx, dmode, dpath, fopt,
&ns_g_server->dtenv),
"unable to create dnstap environment");
}
result = ISC_R_SUCCESS;
cleanup:
+ if (fopt != NULL)
+ fstrm_iothr_options_destroy(&fopt);
+
return (result);
}
#endif /* HAVE_DNSTAP */
int status;
MDB_txn *txn = NULL;
MDB_dbi dbi;
- MDB_stat stat;
+ MDB_stat statbuf;
REQUIRE(countp != NULL);
if (result != ISC_R_SUCCESS)
goto cleanup;
- status = mdb_stat(txn, dbi, &stat);
+ status = mdb_stat(txn, dbi, &statbuf);
if (status != 0) {
isc_log_write(ns_g_lctx,
NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
goto cleanup;
}
- *countp = stat.ms_entries;
+ *countp = statbuf.ms_entries;
cleanup:
(void) nzd_close(&txn, ISC_FALSE);
static const char *udpoutsizestats_desc[dns_sizecounter_out_max];
static const char *tcpinsizestats_desc[dns_sizecounter_in_max];
static const char *tcpoutsizestats_desc[dns_sizecounter_out_max];
+static const char *dnstapstats_desc[dns_dnstapcounter_max];
#if defined(EXTENDED_STATS)
static const char *nsstats_xmldesc[dns_nsstatscounter_max];
static const char *resstats_xmldesc[dns_resstatscounter_max];
static const char *udpoutsizestats_xmldesc[dns_sizecounter_out_max];
static const char *tcpinsizestats_xmldesc[dns_sizecounter_in_max];
static const char *tcpoutsizestats_xmldesc[dns_sizecounter_out_max];
+static const char *dnstapstats_xmldesc[dns_dnstapcounter_max];
#else
#define nsstats_xmldesc NULL
#define resstats_xmldesc NULL
#define udpoutsizestats_xmldesc NULL
#define tcpinsizestats_xmldesc NULL
#define tcpoutsizestats_xmldesc NULL
+#define dnstapstats_xmldesc NULL
#endif /* EXTENDED_STATS */
#define TRY0(a) do { xmlrc = (a); if (xmlrc < 0) goto error; } while(0)
static int udpoutsizestats_index[dns_sizecounter_out_max];
static int tcpinsizestats_index[dns_sizecounter_in_max];
static int tcpoutsizestats_index[dns_sizecounter_out_max];
+static int dnstapstats_index[dns_dnstapcounter_max];
static inline void
set_desc(int counter, int maxcounter, const char *fdesc, const char **fdescs,
SET_DNSSECSTATDESC(fail, "dnssec validation failures", "DNSSECfail");
INSIST(i == dns_dnssecstats_max);
+ /* Initialize dnstap statistics */
+ for (i = 0; i < dns_dnstapcounter_max; i++)
+ dnstapstats_desc[i] = NULL;
+#if defined(EXTENDED_STATS)
+ for (i = 0; i < dns_dnstapcounter_max; i++)
+ dnstapstats_xmldesc[i] = NULL;
+#endif
+
+#define SET_DNSTAPSTATDESC(counterid, desc, xmldesc) \
+ do { \
+ set_desc(dns_dnstapcounter_ ## counterid, \
+ dns_dnstapcounter_max, \
+ desc, dnstapstats_desc, \
+ xmldesc, dnstapstats_xmldesc); \
+ dnstapstats_index[i++] = dns_dnstapcounter_ ## counterid; \
+ } while (0)
+ i = 0;
+ SET_DNSTAPSTATDESC(success, "dnstap messges written", "DNSTAPsuccess");
+ SET_DNSTAPSTATDESC(drop, "dnstap messages dropped", "DNSSECdropped");
+ INSIST(i == dns_dnstapcounter_max);
+
/* Sanity check */
for (i = 0; i < dns_nsstatscounter_max; i++)
INSIST(nsstats_desc[i] != NULL);
INSIST(sockstats_desc[i] != NULL);
for (i = 0; i < dns_dnssecstats_max; i++)
INSIST(dnssecstats_desc[i] != NULL);
+ for (i = 0; i < dns_dnstapcounter_max; i++)
+ INSIST(dnstapstats_desc[i] != NULL);
#if defined(EXTENDED_STATS)
for (i = 0; i < dns_nsstatscounter_max; i++)
INSIST(nsstats_xmldesc[i] != NULL);
INSIST(sockstats_xmldesc[i] != NULL);
for (i = 0; i < dns_dnssecstats_max; i++)
INSIST(dnssecstats_xmldesc[i] != NULL);
+ for (i = 0; i < dns_dnstapcounter_max; i++)
+ INSIST(dnstapstats_xmldesc[i] != NULL);
#endif
/* Initialize traffic size statistics */
isc_uint64_t udpoutsizestat_values[dns_sizecounter_out_max];
isc_uint64_t tcpinsizestat_values[dns_sizecounter_in_max];
isc_uint64_t tcpoutsizestat_values[dns_sizecounter_out_max];
+#if HAVE_DNSTAP
+ isc_uint64_t dnstapstat_values[dns_dnstapcounter_max];
+#endif
isc_result_t result;
isc_time_now(&now);
if (result != ISC_R_SUCCESS)
goto error;
TRY0(xmlTextWriterEndElement(writer)); /* resstat */
+
+#if HAVE_DNSTAP
+ if (server->dtenv != NULL) {
+ isc_stats_t *dnstapstats = NULL;
+ TRY0(xmlTextWriterStartElement(writer,
+ ISC_XMLCHAR "counters"));
+ TRY0(xmlTextWriterWriteAttribute(writer,
+ ISC_XMLCHAR "type",
+ ISC_XMLCHAR "dnstap"));
+ dns_dt_getstats(ns_g_server->dtenv, &dnstapstats);
+ result = dump_counters(dnstapstats,
+ isc_statsformat_xml, writer,
+ NULL, dnstapstats_xmldesc,
+ dns_dnstapcounter_max,
+ dnstapstats_index,
+ dnstapstat_values, 0);
+ isc_stats_detach(&dnstapstats);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+ TRY0(xmlTextWriterEndElement(writer)); /* dnstap */
+ }
+#endif
}
if ((flags & STATS_XML_NET) != 0) {
isc_uint64_t udpoutsizestat_values[dns_sizecounter_out_max];
isc_uint64_t tcpinsizestat_values[dns_sizecounter_in_max];
isc_uint64_t tcpoutsizestat_values[dns_sizecounter_out_max];
+#if HAVE_DNSTAP
+ isc_uint64_t dnstapstat_values[dns_dnstapcounter_max];
+#endif
stats_dumparg_t dumparg;
char boottime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"];
char configtime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"];
json_object_object_add(bindstats, "resstats", counters);
else
json_object_put(counters);
+
+#if HAVE_DNSTAP
+ /* dnstap stat counters */
+ if (ns_g_server->dtenv != NULL) {
+ isc_stats_t *dnstapstats = NULL;
+ dns_dt_getstats(ns_g_server->dtenv, &dnstapstats);
+ counters = json_object_new_object();
+ dumparg.result = ISC_R_SUCCESS;
+ dumparg.arg = counters;
+ result = dump_counters(dnstapstats,
+ isc_statsformat_json, counters,
+ NULL, dnstapstats_xmldesc,
+ dns_dnstapcounter_max,
+ dnstapstats_index,
+ dnstapstat_values, 0);
+ isc_stats_detach(&dnstapstats);
+ if (result != ISC_R_SUCCESS) {
+ json_object_put(counters);
+ goto error;
+ }
+
+ if (json_object_get_object(counters)->count != 0)
+ json_object_object_add(bindstats,
+ "dnstapstats",
+ counters);
+ else
+ json_object_put(counters);
+ }
+#endif
}
if ((flags & (STATS_JSON_ZONES | STATS_JSON_SERVER)) != 0) {
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ fstrm-set-buffer-hint 65537;
+};
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ fstrm-set-buffer-hint 1023;
+};
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ fstrm-set-flush-timeout 0;
+};
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ fstrm-set-flush-timeout 601;
+};
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ fstrm-set-input-queue-size 1;
+};
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ fstrm-set-input-queue-size 16385;
+};
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ fstrm-set-input-queue-size 513;
+};
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ fstrm-set-output-notify-threshold 0;
+};
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ /*
+ * This value is system dependent and matches IOV_MAX.
+ */
+ fstrm-set-output-queue-size 10000000;
+};
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ fstrm-set-output-queue-size 1;
+};
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ fstrm-set-reopen-interval 601;
+};
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ fstrm-set-reopen-interval 0;
+};
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ fstrm-set-buffer-hint 8192;
+};
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ fstrm-set-flush-timeout 1;
+};
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ fstrm-set-input-queue-size 512;
+};
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ fstrm-set-output-notify-threshold 32;
+};
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ fstrm-set-output-queue-model mpsc;
+};
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ fstrm-set-output-queue-model spsc;
+};
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ fstrm-set-output-queue-size 64;
+};
--- /dev/null
+/*
+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ fstrm-set-reopen-interval 5;
+};
status=0
+for bad in bad-*.conf
+do
+ ret=0
+ echo "I: checking that named-checkconf detects error in $bad"
+ $CHECKCONF $bad > /dev/null 2>&1
+ if [ $? != 1 ]; then echo "I:failed"; ret=1; fi
+ status=`expr $status + $ret`
+done
+
+for good in good-*.conf
+do
+ ret=0
+ echo "I: checking that named-checkconf detects no error in $good"
+ $CHECKCONF $good > /dev/null 2>&1
+ if [ $? != 0 ]; then echo "I:failed"; ret=1; fi
+ status=`expr $status + $ret`
+done
+
$DIG +short @10.53.0.3 -p 5300 a.example > dig.out
# check three different dnstap reopen/roll methods:
<optional> dnstap-output ( <literal>file</literal> | <literal>unix</literal> ) <replaceable>path_name</replaceable>; </optional>
<optional> dnstap-identity ( <replaceable>string</replaceable> | <literal>hostname</literal> | <literal>none</literal> ); </optional>
<optional> dnstap-version ( <replaceable>string</replaceable> | <literal>none</literal> ); </optional>
+ <optional> fstrm-set-buffer-hint <replaceable>number</replaceable> ; </optional>
+ <optional> fstrm-set-flush-timeout <replaceable>number</replaceable> ; </optional>
+ <optional> fstrm-set-input-queue-size <replaceable>number</replaceable> ; </optional>
+ <optional> fstrm-set-output-notify-threshold <replaceable>number</replaceable> ; </optional>
+ <optional> fstrm-set-output-queue-model ( <replaceable>mpsc</replaceable> |
+ <replaceable>spsc</replaceable> ) ; </optional>
+ <optional> fstrm-set-output-queue-size <replaceable>number</replaceable> ; </optional>
+ <optional> fstrm-set-reopen-interval <replaceable>number</replaceable> ; </optional>
<optional> geoip-directory <replaceable>path_name</replaceable>; </optional>
<optional> key-directory <replaceable>path_name</replaceable>; </optional>
<optional> managed-keys-directory <replaceable>path_name</replaceable>; </optional>
For more information on <command>dnstap</command>, see
<link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://dnstap.info">http://dnstap.info</link>.
</para>
+ <para>
+ The fstrm library has a number of tunables that are exposed
+ in <filename>named.conf</filename>, and can be modified
+ if necessary to improve performance or prevent loss of data.
+ These are:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ <command>fstrm-set-buffer-hint</command>: The
+ threshold number of bytes to accumulate in the output
+ buffer before forcing a buffer flush. The minimum is
+ 1K, the maximum is 64K, and the default is 8K.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <command>fstrm-set-flush-timeout</command>: The number
+ of seconds to allow unflushed data to remain in the
+ output buffer. The minimum is 1 second, the maximum is
+ 600 seconds (10 minutes), and the default is 1 second.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <command>fstrm-set-output-notify-threshold</command>:
+ The number of outstanding queue entries to allow on
+ an input queue before waking the I/O thread.
+ The minimum is 1 and the default is 32.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <command>fstrm-set-output-queue-model</command>:
+ Controls the queuing semantics to use for queue
+ objects. The default is <literal>mpsc</literal>
+ (multiple producer, single consumer); the other
+ option is <literal>spsc</literal> (single producer,
+ single consumer).
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <command>fstrm-set-input-queue-size</command>: The
+ number of queue entries to allocate for each
+ input queue. The minimum is 2, the maximum is 16384,
+ and the default is 512.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <command>fstrm-set-output-queue-size</command>:
+ The number of queue entries to allocate for each
+ output queue. The minimum is 2, the maximum is
+ system-dependent and based on <option>IOV_MAX</option>,
+ and the default is 64.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <command>fstrm-set-reopen-interval</command>:
+ The number of seconds to wait between attempts to
+ reopen a closed output stream. The minimum is 1 second,
+ the maximum is 600 seconds (10 minutes), and the default
+ is 5 seconds.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Note that all of the above minimum, maximum, and default
+ values are set by the <command>libfstrm</command> library,
+ and may be subject to change in future versions of the
+ library. See the <command>libfstrm</command> documentation
+ for more information.
+ </para>
</listitem>
</varlistentry>
#include <isc/util.h>
#include <dns/acl.h>
+#include <dns/dnstap.h>
#include <dns/fixedname.h>
#include <dns/rdataclass.h>
#include <dns/rdatatype.h>
unsigned int max;
} intervaltable;
+typedef struct {
+ const char *name;
+ unsigned int min;
+ unsigned int max;
+} fstrmtable;
+
typedef enum {
optlevel_config,
optlevel_options,
NULL
};
+#if HAVE_DNSTAP
+ static fstrmtable fstrm[] = {
+ {
+ "fstrm-set-buffer-hint",
+ FSTRM_IOTHR_BUFFER_HINT_MIN,
+ FSTRM_IOTHR_BUFFER_HINT_MAX
+ },
+ {
+ "fstrm-set-flush-timeout",
+ FSTRM_IOTHR_FLUSH_TIMEOUT_MIN,
+ FSTRM_IOTHR_FLUSH_TIMEOUT_MAX
+ },
+ {
+ "fstrm-set-input-queue-size",
+ FSTRM_IOTHR_INPUT_QUEUE_SIZE_MIN,
+ FSTRM_IOTHR_INPUT_QUEUE_SIZE_MAX
+ },
+ {
+ "fstrm-set-output-notify-threshold",
+ FSTRM_IOTHR_QUEUE_NOTIFY_THRESHOLD_MIN,
+ 0
+ },
+ {
+ "fstrm-set-output-queue-size",
+ FSTRM_IOTHR_OUTPUT_QUEUE_SIZE_MIN,
+ FSTRM_IOTHR_OUTPUT_QUEUE_SIZE_MAX
+ },
+ {
+ "fstrm-set-reopen-interval",
+ FSTRM_IOTHR_REOPEN_INTERVAL_MIN,
+ FSTRM_IOTHR_REOPEN_INTERVAL_MAX
+ }
+ };
+#endif
+
/*
* Check that fields specified in units of time other than seconds
* have reasonable values.
}
}
+#if HAVE_DNSTAP
+ for (i = 0; i < sizeof(fstrm) / sizeof(fstrm[0]); i++) {
+ isc_uint32_t value;
+
+ obj = NULL;
+ (void) cfg_map_get(options, fstrm[i].name, &obj);
+ if (obj == NULL)
+ continue;
+
+ value = cfg_obj_asuint32(obj);
+ if (value < fstrm[i].min ||
+ (fstrm[i].max != 0U && value > fstrm[i].max)) {
+ if (fstrm[i].max != 0U)
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "%s '%u' out of range (%u..%u)",
+ fstrm[i].name, value,
+ fstrm[i].min, fstrm[i].max);
+ else
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "%s out of range (%u < %u)",
+ fstrm[i].name, value, fstrm[i].min);
+ result = ISC_R_RANGE;
+ }
+
+ if (strcmp(fstrm[i].name, "fstrm-set-input-queue-size") == 0) {
+ int bits = 0;
+ do {
+ bits += value & 0x1;
+ value >>= 1;
+ } while (value != 0U);
+ if (bits != 1) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "%s '%u' not a power-of-2",
+ fstrm[i].name,
+ cfg_obj_asuint32(obj));
+ result = ISC_R_RANGE;
+ }
+ }
+ }
+#endif
+
return (result);
}
#include <dns/dnstap.h>
#include <dns/log.h>
-#include <dns/name.h>
#include <dns/message.h>
+#include <dns/name.h>
#include <dns/rdataset.h>
#include <dns/result.h>
+#include <dns/stats.h>
#include <dns/types.h>
#include <dns/view.h>
isc_region_t version;
char *path;
dns_dtmode_t mode;
+ isc_stats_t *stats;
};
#define CHECK(x) do { \
isc_result_t
dns_dt_create(isc_mem_t *mctx, dns_dtmode_t mode, const char *path,
- unsigned int workers, dns_dtenv_t **envp)
+ struct fstrm_iothr_options *fopt, dns_dtenv_t **envp)
{
isc_result_t result = ISC_R_SUCCESS;
fstrm_res res;
- struct fstrm_iothr_options *fopt = NULL;
struct fstrm_unix_writer_options *fuwopt = NULL;
struct fstrm_file_options *ffwopt = NULL;
struct fstrm_writer_options *fwopt = NULL;
REQUIRE(path != NULL);
REQUIRE(envp != NULL && *envp == NULL);
+ REQUIRE(fopt != NULL);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSTAP,
DNS_LOGMODULE_DNSTAP, ISC_LOG_INFO,
memset(env, 0, sizeof(dns_dtenv_t));
CHECK(isc_refcount_init(&env->refcount, 1));
+ CHECK(isc_stats_create(mctx, &env->stats, dns_dnstapcounter_max));
env->path = isc_mem_strdup(mctx, path);
if (env->path == NULL)
CHECK(ISC_R_NOMEMORY);
if (fw == NULL)
CHECK(ISC_R_FAILURE);
- fopt = fstrm_iothr_options_init();
- fstrm_iothr_options_set_num_input_queues(fopt, workers);
-
/*
* Remember 'fw' so we can close and reopen it later.
*/
*envp = env;
cleanup:
- if (fopt != NULL)
- fstrm_iothr_options_destroy(&fopt);
-
if (ffwopt != NULL)
fstrm_file_options_destroy(&ffwopt);
isc_mem_detach(&env->mctx);
if (env->path != NULL)
isc_mem_free(mctx, env->path);
+ if (env->stats != NULL)
+ isc_stats_detach(&env->stats);
isc_mem_put(mctx, env, sizeof(dns_dtenv_t));
}
}
*destp = source;
}
+isc_result_t
+dns_dt_getstats(dns_dtenv_t *env, isc_stats_t **statsp) {
+ REQUIRE(VALID_DTENV(env));
+ REQUIRE(statsp != NULL && *statsp == NULL);
+
+ if (env->stats == NULL)
+ return (ISC_R_NOTFOUND);
+ isc_stats_attach(env->stats, statsp);
+ return (ISC_R_SUCCESS);
+}
+
static void
destroy(dns_dtenv_t *env) {
}
if (env->path != NULL)
isc_mem_free(env->mctx, env->path);
+ if (env->stats != NULL)
+ isc_stats_detach(&env->stats);
isc_mem_putanddetach(&env->mctx, env, sizeof(*env));
}
res = fstrm_iothr_submit(env->iothr, ioq, buf, len,
fstrm_free_wrapper, NULL);
- if (res != fstrm_res_success)
+ if (res != fstrm_res_success) {
+ if (env->stats != NULL)
+ isc_stats_increment(env->stats,
+ dns_dnstapcounter_drop);
free(buf);
+ } else {
+ if (env->stats != NULL)
+ isc_stats_increment(env->stats,
+ dns_dnstapcounter_success);
+ }
}
static void
#include <fstrm.h>
#include <protobuf-c/protobuf-c.h>
#include <dns/dnstap.pb-c.h>
+#else
+struct fstrm_iothr_options;
#endif /* HAVE_DNSTAP */
#include <isc/refcount.h>
isc_result_t
dns_dt_create(isc_mem_t *mctx, dns_dtmode_t mode, const char *path,
- unsigned int workers, dns_dtenv_t **envp);
+ struct fstrm_iothr_options *fopt, dns_dtenv_t **envp);
/*%<
* Create and initialize the dnstap environment.
*
* with "file:", then dnstap logs are sent to a file instead of a
* socket.
*
- *\li This creates an I/O thread in libfstrm, and prepares
- * 'workers' input queues. 'workers' MUST be equal to the number
- * of worker threads in named; if it's more, some queues will be
- * wasted and if it's less, some threads will have no queue and
- * will not log any dnstap events.
- *
+ *\li 'fopt' set the options for fstrm_iothr_init(). 'fopt' must have
+ * have had the number of input queues set and this should be set
+ * to the number of worker threads. Additionally the queue model
+ * should also be set. Other options may be set if desired.
*
* Requires:
*
*
*\li 'path' is a valid C string.
*
+ *\li 'fopt' is non NULL.
+ *
*\li envp != NULL && *envp == NULL
*
* Returns:
*\li '*envp' is NULL.
*/
+isc_result_t
+dns_dt_getstats(dns_dtenv_t *env, isc_stats_t **statsp);
+/*%<
+ * Attach to the stats struct if it exists.
+ *
+ * Requires:
+ *
+ *\li 'env' is a valid dnstap environment.
+ *
+ *\li 'statsp' is non NULL and '*statsp' is NULL.
+ *
+ * Returns:
+ *
+ *\li ISC_R_SUCCESS
+ *
+ *\li ISC_R_NOTFOUND
+ */
+
void
dns_dt_shutdown(void);
/*%<
dns_statscounter_recursion = 4, /*%< Recursion was used */
dns_statscounter_failure = 5, /*%< Some other failure */
dns_statscounter_duplicate = 6, /*%< Duplicate query */
- dns_statscounter_dropped = 7 /*%< Duplicate query (dropped) */
+ dns_statscounter_dropped = 7, /*%< Duplicate query (dropped) */
+
+ /*%
+ * DNSTAP statistics counters.
+ */
+ dns_dnstapcounter_success = 0,
+ dns_dnstapcounter_drop = 1,
+ dns_dnstapcounter_max = 2
};
#define DNS_STATS_NCOUNTERS 8
ATF_TC_BODY(create, tc) {
isc_result_t result;
dns_dtenv_t *dtenv = NULL;
+ struct fstrm_iothr_options *fopt;
UNUSED(tc);
result = dns_test_begin(NULL, ISC_TRUE);
ATF_REQUIRE(result == ISC_R_SUCCESS);
- result = dns_dt_create(mctx, dns_dtmode_file, TAPFILE, 1, &dtenv);
+ fopt = fstrm_iothr_options_init();
+ ATF_REQUIRE(fopt != NULL);
+ fstrm_iothr_options_set_num_input_queues(fopt, 1);
+
+ result = dns_dt_create(mctx, dns_dtmode_file, TAPFILE, fopt, &dtenv);
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
if (dtenv != NULL)
dns_dt_detach(&dtenv);
ATF_CHECK(isc_file_exists(TAPFILE));
- result = dns_dt_create(mctx, dns_dtmode_unix, TAPSOCK, 1, &dtenv);
+ result = dns_dt_create(mctx, dns_dtmode_unix, TAPSOCK, fopt, &dtenv);
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
if (dtenv != NULL)
dns_dt_detach(&dtenv);
/* 'create' should succeed, but the file shouldn't exist yet */
ATF_CHECK(!isc_file_exists(TAPSOCK));
- result = dns_dt_create(mctx, 33, TAPSOCK, 1, &dtenv);
+ result = dns_dt_create(mctx, 33, TAPSOCK, fopt, &dtenv);
ATF_CHECK_EQ(result, ISC_R_FAILURE);
ATF_CHECK_EQ(dtenv, NULL);
cleanup();
+ fstrm_iothr_options_destroy(&fopt);
dns_dt_shutdown();
dns_test_end();
}
struct in_addr in;
isc_stdtime_t now;
isc_time_t p, f;
+ struct fstrm_iothr_options *fopt;
UNUSED(tc);
result = dns_test_makeview("test", &view);
- result = dns_dt_create(mctx, dns_dtmode_file, TAPFILE, 1, &dtenv);
+ fopt = fstrm_iothr_options_init();
+ ATF_REQUIRE(fopt != NULL);
+ fstrm_iothr_options_set_num_input_queues(fopt, 1);
+
+ result = dns_dt_create(mctx, dns_dtmode_file, TAPFILE, fopt, &dtenv);
ATF_REQUIRE(result == ISC_R_SUCCESS);
dns_dt_attach(dtenv, &view->dtenv);
dns_dtdata_free(&dtdata);
}
+ fstrm_iothr_options_destroy(&fopt);
dns_dt_close(&handle);
cleanup();
{ NULL, NULL, 0 }
};
+static const char *fstrm_model_enums[] = { "spsc", "mpsc", NULL };
+static cfg_type_t cfg_type_fstrm_model = {
+ "model", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
+ &cfg_rep_string, &fstrm_model_enums
+};
+
/*%
* Clauses that can be found within the 'options' statement.
*/
{ "dnstap-output", &cfg_type_dnstapoutput, 0 },
{ "dnstap-identity", &cfg_type_serverid, 0 },
{ "dnstap-version", &cfg_type_qstringornone, 0 },
+ { "fstrm-set-buffer-hint", &cfg_type_uint32, 0 },
+ { "fstrm-set-flush-timeout", &cfg_type_uint32, 0 },
+ { "fstrm-set-input-queue-size", &cfg_type_uint32, 0 },
+ { "fstrm-set-output-notify-threshold", &cfg_type_uint32, 0 },
+ { "fstrm-set-output-queue-model", &cfg_type_fstrm_model, 0 },
+ { "fstrm-set-output-queue-size", &cfg_type_uint32, 0 },
+ { "fstrm-set-reopen-interval", &cfg_type_uint32, 0 },
#else
{ "dnstap-output", &cfg_type_dnstapoutput,
CFG_CLAUSEFLAG_NOTCONFIGURED },
{ "dnstap-identity", &cfg_type_serverid, CFG_CLAUSEFLAG_NOTCONFIGURED },
{ "dnstap-version", &cfg_type_qstringornone, CFG_CLAUSEFLAG_NOTCONFIGURED },
+ { "fstrm-set-buffer-hint", &cfg_type_uint32,
+ CFG_CLAUSEFLAG_NOTCONFIGURED },
+ { "fstrm-set-flush-timeout", &cfg_type_uint32,
+ CFG_CLAUSEFLAG_NOTCONFIGURED },
+ { "fstrm-set-input-queue-size", &cfg_type_uint32,
+ CFG_CLAUSEFLAG_NOTCONFIGURED },
+ { "fstrm-set-output-notify-threshold", &cfg_type_uint32,
+ CFG_CLAUSEFLAG_NOTCONFIGURED },
+ { "fstrm-set-output-queue-model", &cfg_type_fstrm_model,
+ CFG_CLAUSEFLAG_NOTCONFIGURED },
+ { "fstrm-set-output-queue-size", &cfg_type_uint32,
+ CFG_CLAUSEFLAG_NOTCONFIGURED },
+ { "fstrm-set-reopen-interval", &cfg_type_uint32,
+ CFG_CLAUSEFLAG_NOTCONFIGURED },
#endif /* HAVE_DNSTAP */
{ "session-keyfile", &cfg_type_qstringornone, 0 },
{ "session-keyname", &cfg_type_astring, 0 },
./bin/tests/system/dnssec/signer/remove.db.in ZONE 2016
./bin/tests/system/dnssec/signer/remove2.db.in ZONE 2016
./bin/tests/system/dnssec/tests.sh SH 2000,2001,2002,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016
+./bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-max.conf CONF-C 2016
+./bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-min.conf CONF-C 2016
+./bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-max.conf CONF-C 2016
+./bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-min.conf CONF-C 2016
+./bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-max.conf CONF-C 2016
+./bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-min.conf CONF-C 2016
+./bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-po2.conf CONF-C 2016
+./bin/tests/system/dnstap/bad-fstrm-set-output-notify-threshold.conf CONF-C 2016
+./bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-max.conf CONF-C 2016
+./bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-min.conf CONF-C 2016
+./bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-max.conf CONF-C 2016
+./bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-min.conf CONF-C 2016
./bin/tests/system/dnstap/clean.sh SH 2015,2016
+./bin/tests/system/dnstap/good-fstrm-set-buffer-hint.conf CONF-C 2016
+./bin/tests/system/dnstap/good-fstrm-set-flush-timeout.conf CONF-C 2016
+./bin/tests/system/dnstap/good-fstrm-set-input-queue-size.conf CONF-C 2016
+./bin/tests/system/dnstap/good-fstrm-set-output-notify-threshold.conf CONF-C 2016
+./bin/tests/system/dnstap/good-fstrm-set-output-queue-model-mpsc.conf CONF-C 2016
+./bin/tests/system/dnstap/good-fstrm-set-output-queue-model-spsc.conf CONF-C 2016
+./bin/tests/system/dnstap/good-fstrm-set-output-queue-size.conf CONF-C 2016
+./bin/tests/system/dnstap/good-fstrm-set-reopen-interval.conf CONF-C 2016
./bin/tests/system/dnstap/ns1/named.conf CONF-C 2015,2016
./bin/tests/system/dnstap/ns1/root.db ZONE 2015,2016
./bin/tests/system/dnstap/ns2/example.db ZONE 2015,2016