mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-22 07:41:16 -05:00
EDNS fallback when timeout and multiple query rtt backoff.
git-svn-id: file:///svn/unbound/trunk@1272 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
a2b261f8b2
commit
d4fadf55a8
11 changed files with 119 additions and 31 deletions
|
|
@ -1,3 +1,8 @@
|
||||||
|
29 September 2008: Wouter
|
||||||
|
- EDNS lameness detection, if EDNS packets are dropped this is
|
||||||
|
detected, eventually.
|
||||||
|
- multiple query timeout rtt backoff does not backoff too much.
|
||||||
|
|
||||||
26 September 2008: Wouter
|
26 September 2008: Wouter
|
||||||
- tests for remote-control.
|
- tests for remote-control.
|
||||||
- small memory leak in exception during remote control fixed.
|
- small memory leak in exception during remote control fixed.
|
||||||
|
|
|
||||||
12
services/cache/infra.c
vendored
12
services/cache/infra.c
vendored
|
|
@ -208,13 +208,15 @@ new_host_entry(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||||
data->ttl = tm + infra->host_ttl;
|
data->ttl = tm + infra->host_ttl;
|
||||||
data->lameness = NULL;
|
data->lameness = NULL;
|
||||||
data->edns_version = 0;
|
data->edns_version = 0;
|
||||||
|
data->edns_lame_known = 0;
|
||||||
rtt_init(&data->rtt);
|
rtt_init(&data->rtt);
|
||||||
return &key->entry;
|
return &key->entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
|
infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||||
socklen_t addrlen, uint32_t timenow, int* edns_vs, int* to)
|
socklen_t addrlen, uint32_t timenow, int* edns_vs,
|
||||||
|
uint8_t* edns_lame_known, int* to)
|
||||||
{
|
{
|
||||||
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
||||||
addrlen, 0);
|
addrlen, 0);
|
||||||
|
|
@ -231,6 +233,7 @@ infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||||
rtt_init(&data->rtt);
|
rtt_init(&data->rtt);
|
||||||
/* do not touch lameness, it may be valid still */
|
/* do not touch lameness, it may be valid still */
|
||||||
data->edns_version = 0;
|
data->edns_version = 0;
|
||||||
|
data->edns_lame_known = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!e) {
|
if(!e) {
|
||||||
|
|
@ -240,6 +243,7 @@ infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||||
data = (struct infra_host_data*)e->data;
|
data = (struct infra_host_data*)e->data;
|
||||||
*to = rtt_timeout(&data->rtt);
|
*to = rtt_timeout(&data->rtt);
|
||||||
*edns_vs = data->edns_version;
|
*edns_vs = data->edns_version;
|
||||||
|
*edns_lame_known = data->edns_lame_known;
|
||||||
slabhash_insert(infra->hosts, e->hash, e, data, NULL);
|
slabhash_insert(infra->hosts, e->hash, e, data, NULL);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -247,6 +251,7 @@ infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||||
data = (struct infra_host_data*)e->data;
|
data = (struct infra_host_data*)e->data;
|
||||||
*to = rtt_timeout(&data->rtt);
|
*to = rtt_timeout(&data->rtt);
|
||||||
*edns_vs = data->edns_version;
|
*edns_vs = data->edns_version;
|
||||||
|
*edns_lame_known = data->edns_lame_known;
|
||||||
lock_rw_unlock(&e->lock);
|
lock_rw_unlock(&e->lock);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -438,7 +443,7 @@ infra_update_tcp_works(struct infra_cache* infra,
|
||||||
int
|
int
|
||||||
infra_rtt_update(struct infra_cache* infra,
|
infra_rtt_update(struct infra_cache* infra,
|
||||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||||
int roundtrip, uint32_t timenow)
|
int roundtrip, int orig_rtt, uint32_t timenow)
|
||||||
{
|
{
|
||||||
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
|
||||||
addrlen, 1);
|
addrlen, 1);
|
||||||
|
|
@ -454,7 +459,7 @@ infra_rtt_update(struct infra_cache* infra,
|
||||||
data = (struct infra_host_data*)e->data;
|
data = (struct infra_host_data*)e->data;
|
||||||
data->ttl = timenow + infra->host_ttl;
|
data->ttl = timenow + infra->host_ttl;
|
||||||
if(roundtrip == -1)
|
if(roundtrip == -1)
|
||||||
rtt_lost(&data->rtt);
|
rtt_lost(&data->rtt, orig_rtt);
|
||||||
else rtt_update(&data->rtt, roundtrip);
|
else rtt_update(&data->rtt, roundtrip);
|
||||||
if(data->rtt.rto > 0)
|
if(data->rtt.rto > 0)
|
||||||
rto = data->rtt.rto;
|
rto = data->rtt.rto;
|
||||||
|
|
@ -483,6 +488,7 @@ infra_edns_update(struct infra_cache* infra,
|
||||||
data = (struct infra_host_data*)e->data;
|
data = (struct infra_host_data*)e->data;
|
||||||
data->ttl = timenow + infra->host_ttl;
|
data->ttl = timenow + infra->host_ttl;
|
||||||
data->edns_version = edns_version;
|
data->edns_version = edns_version;
|
||||||
|
data->edns_lame_known = 1;
|
||||||
|
|
||||||
if(needtoinsert)
|
if(needtoinsert)
|
||||||
slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
|
slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
|
||||||
|
|
|
||||||
13
services/cache/infra.h
vendored
13
services/cache/infra.h
vendored
|
|
@ -70,6 +70,10 @@ struct infra_host_data {
|
||||||
struct lruhash* lameness;
|
struct lruhash* lameness;
|
||||||
/** edns version that the host supports, -1 means no EDNS */
|
/** edns version that the host supports, -1 means no EDNS */
|
||||||
int edns_version;
|
int edns_version;
|
||||||
|
/** if the EDNS lameness is already known or not.
|
||||||
|
* EDNS lame is when EDNS queries or replies are dropped,
|
||||||
|
* and cause a timeout */
|
||||||
|
uint8_t edns_lame_known;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -166,11 +170,14 @@ struct infra_host_data* infra_lookup_host(struct infra_cache* infra,
|
||||||
* @param addrlen: length of addr.
|
* @param addrlen: length of addr.
|
||||||
* @param timenow: what time it is now.
|
* @param timenow: what time it is now.
|
||||||
* @param edns_vs: edns version it supports, is returned.
|
* @param edns_vs: edns version it supports, is returned.
|
||||||
|
* @param edns_lame_known: if EDNS lame (EDNS is dropped in transit) has
|
||||||
|
* already been probed, is returned.
|
||||||
* @param to: timeout to use, is returned.
|
* @param to: timeout to use, is returned.
|
||||||
* @return: 0 on error.
|
* @return: 0 on error.
|
||||||
*/
|
*/
|
||||||
int infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
|
int infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
|
||||||
socklen_t addrlen, uint32_t timenow, int* edns_vs, int* to);
|
socklen_t addrlen, uint32_t timenow, int* edns_vs,
|
||||||
|
uint8_t* edns_lame_known, int* to);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check for lameness of this server for a particular zone.
|
* Check for lameness of this server for a particular zone.
|
||||||
|
|
@ -213,12 +220,14 @@ int infra_set_lame(struct infra_cache* infra,
|
||||||
* @param addrlen: length of addr.
|
* @param addrlen: length of addr.
|
||||||
* @param roundtrip: estimate of roundtrip time in milliseconds or -1 for
|
* @param roundtrip: estimate of roundtrip time in milliseconds or -1 for
|
||||||
* timeout.
|
* timeout.
|
||||||
|
* @param orig_rtt: original rtt for the query that timed out (roundtrip==-1).
|
||||||
|
* ignored if roundtrip != -1.
|
||||||
* @param timenow: what time it is now.
|
* @param timenow: what time it is now.
|
||||||
* @return: 0 on error. new rto otherwise.
|
* @return: 0 on error. new rto otherwise.
|
||||||
*/
|
*/
|
||||||
int infra_rtt_update(struct infra_cache* infra,
|
int infra_rtt_update(struct infra_cache* infra,
|
||||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||||
int roundtrip, uint32_t timenow);
|
int roundtrip, int orig_rtt, uint32_t timenow);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update information for the host, store that a TCP transaction works.
|
* Update information for the host, store that a TCP transaction works.
|
||||||
|
|
|
||||||
|
|
@ -1084,7 +1084,8 @@ serviced_delete(struct serviced_query* sq)
|
||||||
if(sq->pending) {
|
if(sq->pending) {
|
||||||
/* clear up the pending query */
|
/* clear up the pending query */
|
||||||
if(sq->status == serviced_query_UDP_EDNS ||
|
if(sq->status == serviced_query_UDP_EDNS ||
|
||||||
sq->status == serviced_query_UDP) {
|
sq->status == serviced_query_UDP ||
|
||||||
|
sq->status == serviced_query_PROBE_EDNS) {
|
||||||
struct pending* p = (struct pending*)sq->pending;
|
struct pending* p = (struct pending*)sq->pending;
|
||||||
if(p->pc)
|
if(p->pc)
|
||||||
portcomm_loweruse(sq->outnet, p->pc);
|
portcomm_loweruse(sq->outnet, p->pc);
|
||||||
|
|
@ -1184,18 +1185,30 @@ static int
|
||||||
serviced_udp_send(struct serviced_query* sq, ldns_buffer* buff)
|
serviced_udp_send(struct serviced_query* sq, ldns_buffer* buff)
|
||||||
{
|
{
|
||||||
int rtt, vs;
|
int rtt, vs;
|
||||||
|
uint8_t edns_lame_known;
|
||||||
uint32_t now = *sq->outnet->now_secs;
|
uint32_t now = *sq->outnet->now_secs;
|
||||||
|
|
||||||
if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen, now, &vs,
|
if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen, now, &vs,
|
||||||
&rtt))
|
&edns_lame_known, &rtt))
|
||||||
return 0;
|
return 0;
|
||||||
if(sq->status == serviced_initial) {
|
if(sq->status == serviced_initial) {
|
||||||
if(vs != -1)
|
if(edns_lame_known == 0 && rtt > 5000) {
|
||||||
|
/* perform EDNS lame probe - check if server is
|
||||||
|
* EDNS lame (EDNS queries to it are dropped) */
|
||||||
|
verbose(VERB_ALGO, "serviced query: send probe to see "
|
||||||
|
" if use of EDNS causes timeouts");
|
||||||
|
rtt /= 10;
|
||||||
|
sq->status = serviced_query_PROBE_EDNS;
|
||||||
|
} else if(vs != -1) {
|
||||||
sq->status = serviced_query_UDP_EDNS;
|
sq->status = serviced_query_UDP_EDNS;
|
||||||
else sq->status = serviced_query_UDP;
|
} else {
|
||||||
|
sq->status = serviced_query_UDP;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
serviced_encode(sq, buff, sq->status == serviced_query_UDP_EDNS);
|
serviced_encode(sq, buff, sq->status == serviced_query_UDP_EDNS);
|
||||||
sq->last_sent_time = *sq->outnet->now_tv;
|
sq->last_sent_time = *sq->outnet->now_tv;
|
||||||
|
sq->last_rtt = rtt;
|
||||||
|
sq->edns_lame_known = (int)edns_lame_known;
|
||||||
verbose(VERB_ALGO, "serviced query UDP timeout=%d msec", rtt);
|
verbose(VERB_ALGO, "serviced query UDP timeout=%d msec", rtt);
|
||||||
sq->pending = pending_udp_query(sq->outnet, buff, &sq->addr,
|
sq->pending = pending_udp_query(sq->outnet, buff, &sq->addr,
|
||||||
sq->addrlen, rtt, serviced_udp_callback, sq);
|
sq->addrlen, rtt, serviced_udp_callback, sq);
|
||||||
|
|
@ -1392,9 +1405,17 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||||
sq->pending = NULL; /* removed after callback */
|
sq->pending = NULL; /* removed after callback */
|
||||||
if(error == NETEVENT_TIMEOUT) {
|
if(error == NETEVENT_TIMEOUT) {
|
||||||
int rto = 0;
|
int rto = 0;
|
||||||
|
if(sq->status == serviced_query_PROBE_EDNS) {
|
||||||
|
/* non-EDNS probe failed; not an EDNS lame server */
|
||||||
|
if(!infra_edns_update(outnet->infra, &sq->addr,
|
||||||
|
sq->addrlen, 0, (uint32_t)now.tv_sec)) {
|
||||||
|
log_err("Out of memory caching edns works");
|
||||||
|
}
|
||||||
|
sq->status = serviced_query_UDP_EDNS;
|
||||||
|
}
|
||||||
sq->retry++;
|
sq->retry++;
|
||||||
if(!(rto=infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
|
if(!(rto=infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||||
-1, (uint32_t)now.tv_sec)))
|
-1, sq->last_rtt, (uint32_t)now.tv_sec)))
|
||||||
log_err("out of memory in UDP exponential backoff");
|
log_err("out of memory in UDP exponential backoff");
|
||||||
if(sq->retry < OUTBOUND_UDP_RETRY) {
|
if(sq->retry < OUTBOUND_UDP_RETRY) {
|
||||||
log_name_addr(VERB_ALGO, "retry query", sq->qbuf+10,
|
log_name_addr(VERB_ALGO, "retry query", sq->qbuf+10,
|
||||||
|
|
@ -1439,6 +1460,25 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* yay! an answer */
|
/* yay! an answer */
|
||||||
|
if(sq->status == serviced_query_PROBE_EDNS) {
|
||||||
|
/* probe without EDNS succeeds, so we conclude that this
|
||||||
|
* host likely has EDNS packets dropped */
|
||||||
|
log_addr(VERB_OPS, "timeouts, concluded that connection to "
|
||||||
|
"host drops EDNS packets", &sq->addr, sq->addrlen);
|
||||||
|
if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||||
|
-1, (uint32_t)now.tv_sec)) {
|
||||||
|
log_err("Out of memory caching no edns for host");
|
||||||
|
}
|
||||||
|
sq->status = serviced_query_UDP;
|
||||||
|
} else if(sq->status == serviced_query_UDP_EDNS &&
|
||||||
|
!sq->edns_lame_known) {
|
||||||
|
/* now we know that edns queries received answers store that */
|
||||||
|
if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||||
|
0, (uint32_t)now.tv_sec)) {
|
||||||
|
log_err("Out of memory caching edns works");
|
||||||
|
}
|
||||||
|
sq->edns_lame_known = 1;
|
||||||
|
}
|
||||||
if(now.tv_sec > sq->last_sent_time.tv_sec ||
|
if(now.tv_sec > sq->last_sent_time.tv_sec ||
|
||||||
(now.tv_sec == sq->last_sent_time.tv_sec &&
|
(now.tv_sec == sq->last_sent_time.tv_sec &&
|
||||||
now.tv_usec > sq->last_sent_time.tv_usec)) {
|
now.tv_usec > sq->last_sent_time.tv_usec)) {
|
||||||
|
|
@ -1448,7 +1488,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||||
verbose(VERB_ALGO, "measured roundtrip at %d msec", roundtime);
|
verbose(VERB_ALGO, "measured roundtrip at %d msec", roundtime);
|
||||||
log_assert(roundtime >= 0);
|
log_assert(roundtime >= 0);
|
||||||
if(!infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
|
if(!infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||||
roundtime, (uint32_t)now.tv_sec))
|
roundtime, sq->last_rtt, (uint32_t)now.tv_sec))
|
||||||
log_err("out of memory noting rtt.");
|
log_err("out of memory noting rtt.");
|
||||||
}
|
}
|
||||||
serviced_callbacks(sq, error, c, rep);
|
serviced_callbacks(sq, error, c, rep);
|
||||||
|
|
@ -1631,7 +1671,8 @@ serviced_get_mem(struct serviced_query* sq)
|
||||||
for(sb = sq->cblist; sb; sb = sb->next)
|
for(sb = sq->cblist; sb; sb = sb->next)
|
||||||
s += sizeof(*sb);
|
s += sizeof(*sb);
|
||||||
if(sq->status == serviced_query_UDP_EDNS ||
|
if(sq->status == serviced_query_UDP_EDNS ||
|
||||||
sq->status == serviced_query_UDP) {
|
sq->status == serviced_query_UDP ||
|
||||||
|
sq->status == serviced_query_PROBE_EDNS) {
|
||||||
s += sizeof(struct pending);
|
s += sizeof(struct pending);
|
||||||
s += comm_timer_get_mem(NULL);
|
s += comm_timer_get_mem(NULL);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -294,7 +294,9 @@ struct serviced_query {
|
||||||
/** TCP with EDNS sent */
|
/** TCP with EDNS sent */
|
||||||
serviced_query_TCP_EDNS,
|
serviced_query_TCP_EDNS,
|
||||||
/** TCP without EDNS sent */
|
/** TCP without EDNS sent */
|
||||||
serviced_query_TCP
|
serviced_query_TCP,
|
||||||
|
/** probe to test EDNS lameness (EDNS is dropped) */
|
||||||
|
serviced_query_PROBE_EDNS
|
||||||
}
|
}
|
||||||
/** variable with current status */
|
/** variable with current status */
|
||||||
status;
|
status;
|
||||||
|
|
@ -304,6 +306,10 @@ struct serviced_query {
|
||||||
int retry;
|
int retry;
|
||||||
/** time last UDP was sent */
|
/** time last UDP was sent */
|
||||||
struct timeval last_sent_time;
|
struct timeval last_sent_time;
|
||||||
|
/** rtt of last (UDP) message */
|
||||||
|
int last_rtt;
|
||||||
|
/** do we know edns probe status already, for UDP_EDNS queries */
|
||||||
|
int edns_lame_known;
|
||||||
/** outside network this is part of */
|
/** outside network this is part of */
|
||||||
struct outside_network* outnet;
|
struct outside_network* outnet;
|
||||||
/** list of interested parties that need callback on results. */
|
/** list of interested parties that need callback on results. */
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,8 @@ static void matchline(char* line, struct entry* e)
|
||||||
e->match_ttl = true;
|
e->match_ttl = true;
|
||||||
} else if(str_keyword(&parse, "DO")) {
|
} else if(str_keyword(&parse, "DO")) {
|
||||||
e->match_do = true;
|
e->match_do = true;
|
||||||
|
} else if(str_keyword(&parse, "noedns")) {
|
||||||
|
e->match_noedns = true;
|
||||||
} else if(str_keyword(&parse, "UDP")) {
|
} else if(str_keyword(&parse, "UDP")) {
|
||||||
e->match_transport = transport_udp;
|
e->match_transport = transport_udp;
|
||||||
} else if(str_keyword(&parse, "TCP")) {
|
} else if(str_keyword(&parse, "TCP")) {
|
||||||
|
|
@ -233,6 +235,7 @@ static struct entry* new_entry()
|
||||||
e->match_all = false;
|
e->match_all = false;
|
||||||
e->match_ttl = false;
|
e->match_ttl = false;
|
||||||
e->match_do = false;
|
e->match_do = false;
|
||||||
|
e->match_noedns = false;
|
||||||
e->match_serial = false;
|
e->match_serial = false;
|
||||||
e->ixfr_soa_serial = 0;
|
e->ixfr_soa_serial = 0;
|
||||||
e->match_transport = transport_any;
|
e->match_transport = transport_any;
|
||||||
|
|
@ -697,6 +700,10 @@ find_match(struct entry* entries, ldns_pkt* query_pkt,
|
||||||
verbose(3, "no DO bit set\n");
|
verbose(3, "no DO bit set\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if(p->match_noedns && ldns_pkt_edns(query_pkt)) {
|
||||||
|
verbose(3, "bad; EDNS OPT present\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if(p->match_transport != transport_any && p->match_transport != transport) {
|
if(p->match_transport != transport_any && p->match_transport != transport) {
|
||||||
verbose(3, "bad transport\n");
|
verbose(3, "bad transport\n");
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@
|
||||||
; 'all' has to match header byte for byte and all rrs in packet.
|
; 'all' has to match header byte for byte and all rrs in packet.
|
||||||
; 'ttl' used with all, rrs in packet must also have matching TTLs.
|
; 'ttl' used with all, rrs in packet must also have matching TTLs.
|
||||||
; 'DO' will match only queries with DO bit set.
|
; 'DO' will match only queries with DO bit set.
|
||||||
|
; 'noedns' matches queries without EDNS OPT records.
|
||||||
MATCH [opcode] [qtype] [qname] [serial=<value>] [all] [ttl]
|
MATCH [opcode] [qtype] [qname] [serial=<value>] [all] [ttl]
|
||||||
MATCH [UDP|TCP] DO
|
MATCH [UDP|TCP] DO
|
||||||
MATCH ...
|
MATCH ...
|
||||||
|
|
@ -168,6 +169,8 @@ struct entry {
|
||||||
bool match_ttl;
|
bool match_ttl;
|
||||||
/** match DO bit */
|
/** match DO bit */
|
||||||
bool match_do;
|
bool match_do;
|
||||||
|
/** match absence of EDNS OPT record in query */
|
||||||
|
bool match_noedns;
|
||||||
/** match query serial with this value. */
|
/** match query serial with this value. */
|
||||||
uint32_t ixfr_soa_serial;
|
uint32_t ixfr_soa_serial;
|
||||||
/** match on UDP/TCP */
|
/** match on UDP/TCP */
|
||||||
|
|
|
||||||
|
|
@ -289,15 +289,15 @@ rtt_test()
|
||||||
rtt_init(&r);
|
rtt_init(&r);
|
||||||
/* initial value sensible */
|
/* initial value sensible */
|
||||||
unit_assert( rtt_timeout(&r) == init );
|
unit_assert( rtt_timeout(&r) == init );
|
||||||
rtt_lost(&r);
|
rtt_lost(&r, init);
|
||||||
unit_assert( rtt_timeout(&r) == init*2 );
|
unit_assert( rtt_timeout(&r) == init*2 );
|
||||||
rtt_lost(&r);
|
rtt_lost(&r, init*2);
|
||||||
unit_assert( rtt_timeout(&r) == init*4 );
|
unit_assert( rtt_timeout(&r) == init*4 );
|
||||||
rtt_update(&r, 4000);
|
rtt_update(&r, 4000);
|
||||||
unit_assert( rtt_timeout(&r) >= 2000 );
|
unit_assert( rtt_timeout(&r) >= 2000 );
|
||||||
rtt_lost(&r);
|
rtt_lost(&r, rtt_timeout(&r) );
|
||||||
for(i=0; i<100; i++) {
|
for(i=0; i<100; i++) {
|
||||||
rtt_lost(&r);
|
rtt_lost(&r, rtt_timeout(&r) );
|
||||||
unit_assert( rtt_timeout(&r) > RTT_MIN_TIMEOUT-1);
|
unit_assert( rtt_timeout(&r) > RTT_MIN_TIMEOUT-1);
|
||||||
unit_assert( rtt_timeout(&r) < RTT_MAX_TIMEOUT+1);
|
unit_assert( rtt_timeout(&r) < RTT_MAX_TIMEOUT+1);
|
||||||
}
|
}
|
||||||
|
|
@ -315,6 +315,7 @@ infra_test()
|
||||||
struct infra_cache* slab;
|
struct infra_cache* slab;
|
||||||
struct config_file* cfg = config_create();
|
struct config_file* cfg = config_create();
|
||||||
uint32_t now = 0;
|
uint32_t now = 0;
|
||||||
|
uint8_t edns_lame;
|
||||||
int vs, to;
|
int vs, to;
|
||||||
struct infra_host_key* k;
|
struct infra_host_key* k;
|
||||||
struct infra_host_data* d;
|
struct infra_host_data* d;
|
||||||
|
|
@ -323,25 +324,25 @@ infra_test()
|
||||||
|
|
||||||
slab = infra_create(cfg);
|
slab = infra_create(cfg);
|
||||||
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
|
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
|
||||||
(socklen_t)sizeof(int), now, &vs, &to) );
|
(socklen_t)sizeof(int), now, &vs, &edns_lame, &to) );
|
||||||
unit_assert( vs == 0 && to == init );
|
unit_assert( vs == 0 && to == init && edns_lame == 0 );
|
||||||
|
|
||||||
unit_assert( infra_rtt_update(slab, (struct sockaddr_storage*)&one,
|
unit_assert( infra_rtt_update(slab, (struct sockaddr_storage*)&one,
|
||||||
(socklen_t)sizeof(int), -1, now) );
|
(socklen_t)sizeof(int), -1, init, now) );
|
||||||
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
|
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
|
||||||
(socklen_t)sizeof(int), now, &vs, &to) );
|
(socklen_t)sizeof(int), now, &vs, &edns_lame, &to) );
|
||||||
unit_assert( vs == 0 && to == init*2 );
|
unit_assert( vs == 0 && to == init*2 && edns_lame == 0 );
|
||||||
|
|
||||||
unit_assert( infra_edns_update(slab, (struct sockaddr_storage*)&one,
|
unit_assert( infra_edns_update(slab, (struct sockaddr_storage*)&one,
|
||||||
(socklen_t)sizeof(int), -1, now) );
|
(socklen_t)sizeof(int), -1, now) );
|
||||||
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
|
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
|
||||||
(socklen_t)sizeof(int), now, &vs, &to) );
|
(socklen_t)sizeof(int), now, &vs, &edns_lame, &to) );
|
||||||
unit_assert( vs == -1 && to == init*2 );
|
unit_assert( vs == -1 && to == init*2 && edns_lame == 1);
|
||||||
|
|
||||||
now += cfg->host_ttl + 10;
|
now += cfg->host_ttl + 10;
|
||||||
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
|
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
|
||||||
(socklen_t)sizeof(int), now, &vs, &to) );
|
(socklen_t)sizeof(int), now, &vs, &edns_lame, &to) );
|
||||||
unit_assert( vs == 0 && to == init );
|
unit_assert( vs == 0 && to == init && edns_lame == 0 );
|
||||||
|
|
||||||
unit_assert( infra_set_lame(slab, (struct sockaddr_storage*)&one,
|
unit_assert( infra_set_lame(slab, (struct sockaddr_storage*)&one,
|
||||||
(socklen_t)sizeof(int), zone, zonelen, now, 0,
|
(socklen_t)sizeof(int), zone, zonelen, now, 0,
|
||||||
|
|
|
||||||
BIN
testdata/edns_lame.tpkg
vendored
Normal file
BIN
testdata/edns_lame.tpkg
vendored
Normal file
Binary file not shown.
15
util/rtt.c
15
util/rtt.c
|
|
@ -95,10 +95,17 @@ rtt_update(struct rtt_info* rtt, int ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rtt_lost(struct rtt_info* rtt)
|
rtt_lost(struct rtt_info* rtt, int orig)
|
||||||
{
|
{
|
||||||
/* exponential backoff */
|
/* exponential backoff */
|
||||||
rtt->rto *= 2;
|
|
||||||
if(rtt->rto > RTT_MAX_TIMEOUT)
|
/* the original rto is doubled, not the current one to make sure
|
||||||
rtt->rto = RTT_MAX_TIMEOUT;
|
* that the values in the cache are not increased by lots of
|
||||||
|
* queries simultaneously as they time out at the same time */
|
||||||
|
orig *= 2;
|
||||||
|
if(rtt->rto <= orig) {
|
||||||
|
rtt->rto = orig;
|
||||||
|
if(rtt->rto > RTT_MAX_TIMEOUT)
|
||||||
|
rtt->rto = RTT_MAX_TIMEOUT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,10 @@ void rtt_update(struct rtt_info* rtt, int ms);
|
||||||
/**
|
/**
|
||||||
* Update the statistics with a new timout expired observation.
|
* Update the statistics with a new timout expired observation.
|
||||||
* @param rtt: round trip statistics structure.
|
* @param rtt: round trip statistics structure.
|
||||||
|
* @param orig: original rtt time given for the query that timed out.
|
||||||
|
* Used to calculate the maximum responsible backed off time that
|
||||||
|
* can reasonably be applied.
|
||||||
*/
|
*/
|
||||||
void rtt_lost(struct rtt_info* rtt);
|
void rtt_lost(struct rtt_info* rtt, int orig);
|
||||||
|
|
||||||
#endif /* UTIL_RTT_H */
|
#endif /* UTIL_RTT_H */
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue