summaryrefslogtreecommitdiff
path: root/services/cache
diff options
context:
space:
mode:
Diffstat (limited to 'services/cache')
-rw-r--r--services/cache/infra.c28
-rw-r--r--services/cache/infra.h2
2 files changed, 26 insertions, 4 deletions
diff --git a/services/cache/infra.c b/services/cache/infra.c
index c2484a9f1aa8..2d16bcd6e405 100644
--- a/services/cache/infra.c
+++ b/services/cache/infra.c
@@ -244,6 +244,7 @@ infra_create(struct config_file* cfg)
return NULL;
}
infra->host_ttl = cfg->host_ttl;
+ infra->infra_keep_probing = cfg->infra_keep_probing;
infra_dp_ratelimit = cfg->ratelimit;
infra->domain_rates = slabhash_create(cfg->ratelimit_slabs,
INFRA_HOST_STARTSIZE, cfg->ratelimit_size,
@@ -297,6 +298,7 @@ infra_adjust(struct infra_cache* infra, struct config_file* cfg)
if(!infra)
return infra_create(cfg);
infra->host_ttl = cfg->host_ttl;
+ infra->infra_keep_probing = cfg->infra_keep_probing;
infra_dp_ratelimit = cfg->ratelimit;
infra_ip_ratelimit = cfg->ip_ratelimit;
maxmem = cfg->infra_cache_numhosts * (sizeof(struct infra_key)+
@@ -445,6 +447,7 @@ infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
if(e && ((struct infra_data*)e->data)->ttl < timenow) {
/* it expired, try to reuse existing entry */
int old = ((struct infra_data*)e->data)->rtt.rto;
+ time_t tprobe = ((struct infra_data*)e->data)->probedelay;
uint8_t tA = ((struct infra_data*)e->data)->timeout_A;
uint8_t tAAAA = ((struct infra_data*)e->data)->timeout_AAAA;
uint8_t tother = ((struct infra_data*)e->data)->timeout_other;
@@ -460,6 +463,7 @@ infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
if(old >= USEFUL_SERVER_TOP_TIMEOUT) {
((struct infra_data*)e->data)->rtt.rto
= USEFUL_SERVER_TOP_TIMEOUT;
+ ((struct infra_data*)e->data)->probedelay = tprobe;
((struct infra_data*)e->data)->timeout_A = tA;
((struct infra_data*)e->data)->timeout_AAAA = tAAAA;
((struct infra_data*)e->data)->timeout_other = tother;
@@ -482,7 +486,8 @@ infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
*edns_vs = data->edns_version;
*edns_lame_known = data->edns_lame_known;
*to = rtt_timeout(&data->rtt);
- if(*to >= PROBE_MAXRTO && rtt_notimeout(&data->rtt)*4 <= *to) {
+ if(*to >= PROBE_MAXRTO && (infra->infra_keep_probing ||
+ rtt_notimeout(&data->rtt)*4 <= *to)) {
/* delay other queries, this is the probe query */
if(!wr) {
lock_rw_unlock(&e->lock);
@@ -566,18 +571,27 @@ infra_rtt_update(struct infra_cache* infra, struct sockaddr_storage* addr,
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
nm, nmlen, 1);
struct infra_data* data;
- int needtoinsert = 0;
+ int needtoinsert = 0, expired = 0;
int rto = 1;
+ time_t oldprobedelay = 0;
if(!e) {
if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow)))
return 0;
needtoinsert = 1;
} else if(((struct infra_data*)e->data)->ttl < timenow) {
+ oldprobedelay = ((struct infra_data*)e->data)->probedelay;
data_entry_init(infra, e, timenow);
+ expired = 1;
}
/* have an entry, update the rtt */
data = (struct infra_data*)e->data;
if(roundtrip == -1) {
+ if(needtoinsert || expired) {
+ /* timeout on entry that has expired before the timer
+ * keep old timeout from the function caller */
+ data->rtt.rto = orig_rtt;
+ data->probedelay = oldprobedelay;
+ }
rtt_lost(&data->rtt, orig_rtt);
if(qtype == LDNS_RR_TYPE_A) {
if(data->timeout_A < TIMEOUT_COUNT_MAX)
@@ -681,7 +695,12 @@ infra_get_lame_rtt(struct infra_cache* infra,
return 0;
host = (struct infra_data*)e->data;
*rtt = rtt_unclamped(&host->rtt);
- if(host->rtt.rto >= PROBE_MAXRTO && timenow < host->probedelay
+ if(host->rtt.rto >= PROBE_MAXRTO && timenow >= host->probedelay
+ && infra->infra_keep_probing) {
+ /* single probe, keep probing */
+ if(*rtt >= USEFUL_SERVER_TOP_TIMEOUT)
+ *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
+ } else if(host->rtt.rto >= PROBE_MAXRTO && timenow < host->probedelay
&& rtt_notimeout(&host->rtt)*4 <= host->rtt.rto) {
/* single probe for this domain, and we are not probing */
/* unless the query type allows a probe to happen */
@@ -704,7 +723,8 @@ infra_get_lame_rtt(struct infra_cache* infra,
/* see if this can be a re-probe of an unresponsive server */
/* minus 1000 because that is outside of the RTTBAND, so
* blacklisted servers stay blacklisted if this is chosen */
- if(host->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
+ if(host->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT ||
+ infra->infra_keep_probing) {
lock_rw_unlock(&e->lock);
*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
*lame = 0;
diff --git a/services/cache/infra.h b/services/cache/infra.h
index e33f2a6c04ee..14f97c4c64d3 100644
--- a/services/cache/infra.h
+++ b/services/cache/infra.h
@@ -114,6 +114,8 @@ struct infra_cache {
struct slabhash* hosts;
/** TTL value for host information, in seconds */
int host_ttl;
+ /** the hosts that are down are kept probed for recovery */
+ int infra_keep_probing;
/** hash table with query rates per name: rate_key, rate_data */
struct slabhash* domain_rates;
/** ratelimit settings for domains, struct domain_limit_data */