Commit fd780f3d authored by Mark Andrews's avatar Mark Andrews

1891. [func] Limit the number of recursive clients that can be

                        waiting for a single query (<qname,qtype,qclass>) to
                        resolve.  New options clients-per-query and
                        max-clients-per-query.
parent 096103ae
1891. [func] Limit the number of recursive clients that can be
waiting for a single query (<qname,qtype,qclass>) to
resolve. New options clients-per-query and
max-clients-per-query.
1890. [func] Add a system test for named-checkconf. [RT #14931]
1889. [func] The lame cache is now done on a <qname,qclass,qtype>
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: config.c,v 1.57 2005/05/19 04:59:00 marka Exp $ */
/* $Id: config.c,v 1.58 2005/06/27 00:15:41 marka Exp $ */
/*! \file */
......@@ -134,6 +134,8 @@ options {\n\
max-acache-size 0;\n\
dnssec-enable no; /* Make yes for 9.4. */ \n\
integrity-check yes;\n\
clients-per-query 10;\n\
max-clients-per-query 100;\n\
"
" /* zone */\n\
......
......@@ -17,7 +17,7 @@
- PERFORMANCE OF THIS SOFTWARE.
-->
<!-- $Id: named.conf.docbook,v 1.12 2005/06/07 00:27:31 marka Exp $ -->
<!-- $Id: named.conf.docbook,v 1.13 2005/06/27 00:15:41 marka Exp $ -->
<refentry>
<refentryinfo>
<date>Aug 13, 2004</date>
......@@ -239,6 +239,9 @@ options {
max-cache-ttl <replaceable>integer</replaceable>;
transfer-format ( many-answers | one-answer );
max-cache-size <replaceable>size_no_default</replaceable>;
max-acache-size <replaceable>size_no_default</replaceable>;
clients-per-query <replaceable>number</replaceable>;
max-clients-per-query <replaceable>number</replaceable>;
check-names ( master | slave | response )
( fail | warn | ignore );
check-mx ( fail | warn | ignore );
......@@ -371,6 +374,9 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable>
max-cache-ttl <replaceable>integer</replaceable>;
transfer-format ( many-answers | one-answer );
max-cache-size <replaceable>size_no_default</replaceable>;
max-acache-size <replaceable>size_no_default</replaceable>;
clients-per-query <replaceable>number</replaceable>;
max-clients-per-query <replaceable>number</replaceable>;
check-names ( master | slave | response )
( fail | warn | ignore );
check-mx ( fail | warn | ignore );
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: query.c,v 1.267 2005/06/17 01:58:21 marka Exp $ */
/* $Id: query.c,v 1.268 2005/06/27 00:15:42 marka Exp $ */
/*! \file */
......@@ -163,6 +163,8 @@ static void
query_next(ns_client_t *client, isc_result_t result) {
if (result == DNS_R_DUPLICATE)
inc_stats(client, dns_statscounter_duplicate);
else if (result == DNS_R_DROP)
inc_stats(client, dns_statscounter_dropped);
else
inc_stats(client, dns_statscounter_failure);
ns_client_next(client, result);
......@@ -3228,7 +3230,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
if (result == ISC_R_SUCCESS)
client->query.attributes |=
NS_QUERYATTR_RECURSING;
else if (result == DNS_R_DUPLICATE) {
else if (result == DNS_R_DUPLICATE ||
result == DNS_R_DROP) {
/* Duplicate query. */
QUERY_ERROR(result);
} else {
......@@ -3401,7 +3404,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
if (result == ISC_R_SUCCESS)
client->query.attributes |=
NS_QUERYATTR_RECURSING;
else if (result == DNS_R_DUPLICATE)
else if (result == DNS_R_DUPLICATE ||
result == DNS_R_DROP)
QUERY_ERROR(result);
else
QUERY_ERROR(DNS_R_SERVFAIL);
......@@ -3944,7 +3948,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
if (eresult != ISC_R_SUCCESS &&
(!PARTIALANSWER(client) || WANTRECURSION(client))) {
if (eresult == DNS_R_DUPLICATE) {
if (eresult == DNS_R_DUPLICATE || eresult == DNS_R_DROP) {
/*
* This was a duplicate query that we are
* recursing on. Don't send a response now.
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.c,v 1.444 2005/06/07 01:52:51 marka Exp $ */
/* $Id: server.c,v 1.445 2005/06/27 00:15:42 marka Exp $ */
/*! \file */
......@@ -764,6 +764,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
dns_order_t *order = NULL;
isc_uint32_t udpsize;
unsigned int check = 0;
isc_uint32_t max_clients_per_query;
REQUIRE(DNS_VIEW_VALID(view));
......@@ -1243,6 +1244,18 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
result = ns_config_get(maps, "provide-ixfr", &obj);
INSIST(result == ISC_R_SUCCESS);
view->provideixfr = cfg_obj_asboolean(obj);
obj = NULL;
result = ns_config_get(maps, "max-clients-per-query", &obj);
INSIST(result == ISC_R_SUCCESS);
max_clients_per_query = cfg_obj_asuint32(obj);
obj = NULL;
result = ns_config_get(maps, "clients-per-query", &obj);
INSIST(result == ISC_R_SUCCESS);
dns_resolver_setclientsperquery(view->resolver,
cfg_obj_asuint32(obj),
max_clients_per_query);
obj = NULL;
result = ns_config_get(maps, "dnssec-enable", &obj);
......
......@@ -18,7 +18,7 @@
- PERFORMANCE OF THIS SOFTWARE.
-->
<!-- File: $Id: Bv9ARM-book.xml,v 1.273 2005/06/20 01:11:57 marka Exp $ -->
<!-- File: $Id: Bv9ARM-book.xml,v 1.274 2005/06/27 00:15:42 marka Exp $ -->
<book>
<title>BIND 9 Administrator Reference Manual</title>
......@@ -1522,6 +1522,42 @@ controls {
</listitem>
</varlistentry>
<varlistentry>
<term><command>clients-per-query</command></term>
<term><command>max-clients-per-query</command></term>
<listitem>
<para><command>clients-per-query</command>
and <command>max-clients-per-query</command> set the
initial value (minimum) and maximum number of recursive
simultanious clients for any given query
(&lt;qname,qtype,qclass&gt;) that the server will accept
before dropping additional clients. named will attempt to
self tune this value and changes will be logged. The
default values are 10 and 100.
</para>
<para>
This value should reflect how many queries come in for
a given name in the time it takes to resolve that name.
If the number of queries exceed this value named will
assume that it is dealing with a non-responsive zone
and will drop additional queries. If it gets a response
after dropping queries it will raise the estimate. The
estimate will then be lowered in 20 minutes if it has
remained unchanged.
</para>
<para>
If <command>clients-per-query</command> is set to zero
then there is no limit on the number of clients per query
and no queries will be dropped.
</para>
<para>
If <command>max-clients-per-query</command> is set to zero
then there is no upper bound other than imposed by
<command>recurive-clients</command>.
</para>
</listitem>
</varlistentry>
</variablelist>
</sect3>
......@@ -4396,6 +4432,8 @@ category notify { null; };
<optional> use-additional-cache <replaceable>yes_or_no</replaceable> ; </optional>
<optional> acache-cleaning-interval <replaceable>number</replaceable>; </optional>
<optional> max-acache-size <replaceable>size_spec</replaceable> ; </optional>
<optional> clients-per-query <replaceable>number</replaceable> ; </optional>
<optional> max-clients-per-query <replaceable>number</replaceable> ; </optional>
<optional> masterfile-format (<constant>text</constant>|<constant>raw</constant>) ; </optional>
};
</programlisting>
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: resolver.h,v 1.46 2005/06/17 01:58:23 marka Exp $ */
/* $Id: resolver.h,v 1.47 2005/06/27 00:15:44 marka Exp $ */
#ifndef DNS_RESOLVER_H
#define DNS_RESOLVER_H 1
......@@ -309,6 +309,7 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
*
*\li #ISC_R_SUCCESS Success
*\li #DNS_R_DUPLICATE
*\li #DNS_R_DROP
*
*\li Many other values are possible, all of which indicate failure.
*/
......@@ -457,6 +458,13 @@ dns_resolver_setmustbesecure(dns_resolver_t *resolver, dns_name_t *name,
isc_boolean_t
dns_resolver_getmustbesecure(dns_resolver_t *resolver, dns_name_t *name);
void
dns_resolver_setclientsperquery(dns_resolver_t *resolver,
isc_uint32_t min, isc_uint32_t max);
void
dns_resolver_getclientsperquery(dns_resolver_t *resolver, isc_uint32_t *cur,
isc_uint32_t *min, isc_uint32_t *max);
ISC_LANG_ENDDECLS
#endif /* DNS_RESOLVER_H */
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: stats.h,v 1.8 2005/06/17 01:58:23 marka Exp $ */
/* $Id: stats.h,v 1.9 2005/06/27 00:15:44 marka Exp $ */
#ifndef DNS_STATS_H
#define DNS_STATS_H 1
......@@ -34,10 +34,11 @@ typedef enum {
dns_statscounter_nxdomain = 3, /*%< NXDOMAIN result */
dns_statscounter_recursion = 4, /*%< Recursion was used */
dns_statscounter_failure = 5, /*%< Some other failure */
dns_statscounter_duplicate = 6 /*%< Duplicate query */
dns_statscounter_duplicate = 6, /*%< Duplicate query */
dns_statscounter_dropped = 7 /*%< Duplicate query */
} dns_statscounter_t;
#define DNS_STATS_NCOUNTERS 7
#define DNS_STATS_NCOUNTERS 8
LIBDNS_EXTERNAL_DATA extern const char *dns_statscounter_names[];
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: resolver.c,v 1.313 2005/06/23 06:12:56 marka Exp $ */
/* $Id: resolver.c,v 1.314 2005/06/27 00:15:43 marka Exp $ */
/*! \file */
......@@ -166,6 +166,7 @@ struct fetchctx {
fetchstate state;
isc_boolean_t want_shutdown;
isc_boolean_t cloned;
isc_boolean_t spilled;
unsigned int references;
isc_event_t control_event;
ISC_LINK(struct fetchctx) link;
......@@ -307,12 +308,16 @@ struct dns_resolver {
isc_rwlock_t mbslock;
#endif
dns_rbt_t * mustbesecure;
unsigned int spillatmax;
unsigned int spillatmin;
isc_timer_t * spillattimer;
/* Locked by lock. */
unsigned int references;
isc_boolean_t exiting;
isc_eventlist_t whenshutdown;
unsigned int activebuckets;
isc_boolean_t priming;
unsigned int spillat;
/* Locked by primelock. */
dns_fetch_t * primefetch;
/* Locked by nlock. */
......@@ -433,8 +438,7 @@ fctx_starttimer(fetchctx_t *fctx) {
* no further idle events are delivered.
*/
return (isc_timer_reset(fctx->timer, isc_timertype_once,
&fctx->expires, NULL,
ISC_TRUE));
&fctx->expires, NULL, ISC_TRUE));
}
static inline void
......@@ -713,6 +717,9 @@ static inline void
fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
dns_fetchevent_t *event, *next_event;
isc_task_t *task;
unsigned int count = 0;
isc_interval_t i;
isc_boolean_t logit = ISC_FALSE;
/*
* Caller must be holding the appropriate bucket lock.
......@@ -737,6 +744,31 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
fctx->type == dns_rdatatype_rrsig);
isc_task_sendanddetach(&task, ISC_EVENT_PTR(&event));
count++;
}
if ((fctx->attributes & FCTX_ATTR_HAVEANSWER) != 0 &&
fctx->spilled &&
(count < fctx->res->spillatmax || fctx->res->spillatmax == 0)) {
LOCK(&fctx->res->lock);
if (count == fctx->res->spillat && !fctx->res->exiting) {
fctx->res->spillat += 5;
if (fctx->res->spillat > fctx->res->spillatmax &&
fctx->res->spillatmax != 0)
fctx->res->spillat = fctx->res->spillatmax;
isc_interval_set(&i, 20 * 60, 0);
result = isc_timer_reset(fctx->res->spillattimer,
isc_timertype_ticker, NULL,
&i, ISC_TRUE);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
logit = ISC_TRUE;
}
UNLOCK(&fctx->res->lock);
if (logit)
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
"clients-per-query increased to %u",
count + 1);
}
}
......@@ -2726,6 +2758,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
fctx->restarts = 0;
fctx->timeouts = 0;
fctx->attributes = 0;
fctx->spilled = ISC_FALSE;
dns_name_init(&fctx->nsname, NULL);
fctx->nsfetch = NULL;
......@@ -5665,6 +5698,7 @@ destroy(dns_resolver_t *res) {
#if USE_MBSLOCK
isc_rwlock_destroy(&res->mbslock);
#endif
isc_timer_detach(&res->spillattimer);
res->magic = 0;
isc_mem_put(res->mctx, res, sizeof(*res));
}
......@@ -5703,11 +5737,42 @@ empty_bucket(dns_resolver_t *res) {
UNLOCK(&res->lock);
}
static void
spillattimer_countdown(isc_task_t *task, isc_event_t *event) {
dns_resolver_t *res = event->ev_arg;
isc_result_t result;
unsigned int count;
isc_boolean_t logit = ISC_FALSE;
REQUIRE(VALID_RESOLVER(res));
UNUSED(task);
LOCK(&res->lock);
INSIST(!res->exiting);
if (res->spillat > res->spillatmin) {
res->spillat--;
logit = ISC_TRUE;
}
if (res->spillat <= res->spillatmin) {
result = isc_timer_reset(res->spillattimer,
isc_timertype_inactive, NULL,
NULL, ISC_TRUE);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
}
count = res->spillat;
UNLOCK(&res->lock);
if (logit)
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
"clients-per-query decreased to %u", count);
}
isc_result_t
dns_resolver_create(dns_view_t *view,
isc_taskmgr_t *taskmgr, unsigned int ntasks,
isc_socketmgr_t *socketmgr,
isc_timermgr_t *timermgr,
isc_timermgr_t *timermgr,
unsigned int options,
dns_dispatchmgr_t *dispatchmgr,
dns_dispatch_t *dispatchv4,
......@@ -5717,6 +5782,7 @@ dns_resolver_create(dns_view_t *view,
dns_resolver_t *res;
isc_result_t result = ISC_R_SUCCESS;
unsigned int i, buckets_created = 0;
isc_task_t *task = NULL;
char name[16];
/*
......@@ -5746,6 +5812,9 @@ dns_resolver_create(dns_view_t *view,
res->udpsize = RECV_BUFFER_SIZE;
res->algorithms = NULL;
res->mustbesecure = NULL;
res->spillatmin = res->spillat = 10;
res->spillatmax = 100;
res->spillattimer = NULL;
res->nbuckets = ntasks;
res->activebuckets = ntasks;
......@@ -5806,10 +5875,22 @@ dns_resolver_create(dns_view_t *view,
if (result != ISC_R_SUCCESS)
goto cleanup_nlock;
task = NULL;
result = isc_task_create(taskmgr, 0, &task);
if (result != ISC_R_SUCCESS)
goto cleanup_primelock;
result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
task, spillattimer_countdown, res,
&res->spillattimer);
isc_task_detach(&task);
if (result != ISC_R_SUCCESS)
goto cleanup_primelock;
#if USE_ALGLOCK
result = isc_rwlock_init(&res->alglock, 0, 0);
if (result != ISC_R_SUCCESS)
goto cleanup_primelock;
goto cleanup_spillattimer;
#endif
#if USE_MBSLOCK
result = isc_rwlock_init(&res->mbslock, 0, 0);
......@@ -5830,9 +5911,12 @@ dns_resolver_create(dns_view_t *view,
#endif
#endif
#if USE_ALGLOCK || USE_MBSLOCK
cleanup_spillattimer:
isc_timer_detach(&res->spillattimer);
#endif
cleanup_primelock:
DESTROYLOCK(&res->primelock);
#endif
cleanup_nlock:
DESTROYLOCK(&res->nlock);
......@@ -6034,6 +6118,7 @@ dns_resolver_shutdown(dns_resolver_t *res) {
unsigned int i;
fetchctx_t *fctx;
isc_socket_t *sock;
isc_result_t result;
REQUIRE(VALID_RESOLVER(res));
......@@ -6070,6 +6155,10 @@ dns_resolver_shutdown(dns_resolver_t *res) {
}
if (res->activebuckets == 0)
send_shutdown_events(res);
result = isc_timer_reset(res->spillattimer,
isc_timertype_inactive, NULL,
NULL, ISC_TRUE);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
}
UNLOCK(&res->lock);
......@@ -6160,10 +6249,11 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
{
dns_fetch_t *fetch;
fetchctx_t *fctx = NULL;
isc_result_t result;
isc_result_t result = ISC_R_SUCCESS;
unsigned int bucketnum;
isc_boolean_t new_fctx = ISC_FALSE;
isc_event_t *event;
unsigned int count = 0;
UNUSED(forwarders);
......@@ -6221,6 +6311,19 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
result = DNS_R_DUPLICATE;
goto unlock;
}
count++;
}
}
if (count >= res->spillatmin && res->spillatmin != 0) {
if (!fctx->spilled) {
LOCK(&fctx->res->lock);
if (count >= res->spillat)
fctx->spilled = ISC_TRUE;
UNLOCK(&fctx->res->lock);
}
if (fctx->spilled) {
result = DNS_R_DROP;
goto unlock;
}
}
......@@ -6669,3 +6772,31 @@ dns_resolver_getmustbesecure(dns_resolver_t *resolver, dns_name_t *name) {
#endif
return (value);
}
void
dns_resolver_getclientsperquery(dns_resolver_t *resolver, isc_uint32_t *cur,
isc_uint32_t *min, isc_uint32_t *max)
{
REQUIRE(VALID_RESOLVER(resolver));
LOCK(&resolver->lock);
if (cur != NULL)
*cur = resolver->spillat;
if (min != NULL)
*min = resolver->spillatmin;
if (max != NULL)
*max = resolver->spillatmax;
UNLOCK(&resolver->lock);
}
void
dns_resolver_setclientsperquery(dns_resolver_t *resolver, isc_uint32_t min,
isc_uint32_t max)
{
REQUIRE(VALID_RESOLVER(resolver));
LOCK(&resolver->lock);
resolver->spillatmin = resolver->spillat = min;
resolver->spillatmax = max;
UNLOCK(&resolver->lock);
}
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: stats.c,v 1.9 2005/06/17 01:58:22 marka Exp $ */
/* $Id: stats.c,v 1.10 2005/06/27 00:15:44 marka Exp $ */
/*! \file */
......@@ -33,7 +33,8 @@ LIBDNS_EXTERNAL_DATA const char *dns_statscounter_names[DNS_STATS_NCOUNTERS] =
"nxdomain",
"recursion",
"failure",
"duplicate"
"duplicate",
"dropped"
};
isc_result_t
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: namedconf.c,v 1.52 2005/06/20 01:03:55 marka Exp $ */
/* $Id: namedconf.c,v 1.53 2005/06/27 00:15:45 marka Exp $ */
/*! \file */
......@@ -745,6 +745,8 @@ view_clauses[] = {
{ "use-additional-cache", &cfg_type_boolean, 0 },
{ "acache-cleaning-interval", &cfg_type_uint32, 0 },
{ "max-acache-size", &cfg_type_sizenodefault, 0 },
{ "clients-per-query", &cfg_type_uint32, 0 },
{ "max-clients-per-query", &cfg_type_uint32, 0 },
{ NULL, NULL, 0 }
};
......
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