- fixup removal of nonsecure items from the additional.
- reduced timeout values to more realistic, 376 msec (262 msec has
90% of roundtrip times, 512 msec has 99% of roundtrip times.)
+ - server selection failover to next server after timeout (376 msec).
16 October 2007: Wouter
- no malloc in log_hex.
dp->usable_list = a;
memcpy(&a->addr, addr, addrlen);
a->addrlen = addrlen;
+ a->attempts = 0;
return 1;
}
struct sockaddr_storage addr;
/** length of addr */
socklen_t addrlen;
+ /** number of attempts for this addr */
+ int attempts;
};
/**
return NULL;
if(num == 1) {
a = dp->result_list;
+ if(++a->attempts < OUTBOUND_MSG_RETRY)
+ return a;
dp->result_list = a->next_result;
return a;
}
}
if(!a) /* robustness */
return NULL;
+ if(++a->attempts < OUTBOUND_MSG_RETRY)
+ return a;
/* remove it from the delegation point result list */
if(prev)
prev->next_result = a->next_result;
* Equals RTT_MAX_TIMEOUT
*/
#define USEFUL_SERVER_TOP_TIMEOUT 120000
+/** number of retries on outgoing queries */
+#define OUTBOUND_MSG_RETRY 4
/**
* Global state for the iterator.
return 1;
}
+void
+infra_update_tcp_works(struct infra_cache* infra,
+ struct sockaddr_storage* addr, socklen_t addrlen)
+{
+ struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
+ addrlen, 1);
+ struct infra_host_data* data;
+ if(!e)
+ return; /* doesn't exist */
+ data = (struct infra_host_data*)e->data;
+ if(data->rtt.rto >= RTT_MAX_TIMEOUT)
+ /* do not disqualify this server altogether, it is better
+ * than nothing */
+ data->rtt.rto = RTT_MAX_TIMEOUT-1;
+ lock_rw_unlock(&e->lock);
+}
+
int
infra_rtt_update(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
addrlen, 1);
struct infra_host_data* data;
int needtoinsert = 0;
+ int rto = 1;
if(!e) {
if(!(e = new_host_entry(infra, addr, addrlen, timenow)))
return 0;
if(roundtrip == -1)
rtt_lost(&data->rtt);
else rtt_update(&data->rtt, roundtrip);
+ if(data->rtt.rto > 0)
+ rto = data->rtt.rto;
if(needtoinsert)
slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
else { lock_rw_unlock(&e->lock); }
- return 1;
+ return rto;
}
int
* @param roundtrip: estimate of roundtrip time in milliseconds or -1 for
* timeout.
* @param timenow: what time it is now.
- * @return: 0 on error.
+ * @return: 0 on error. new rto otherwise.
*/
int infra_rtt_update(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
int roundtrip, time_t timenow);
+/**
+ * Update information for the host, store that a TCP transaction works.
+ * @param infra: infrastructure cache.
+ * @param addr: host address.
+ * @param addrlen: length of addr.
+ */
+void infra_update_tcp_works(struct infra_cache* infra,
+ struct sockaddr_storage* addr, socklen_t addrlen);
+
/**
* Update edns information for the host.
* @param infra: infrastructure cache.
/** number of times to retry making a random ID that is unique. */
#define MAX_ID_RETRY 1000
/** number of retries on outgoing UDP queries */
-#define OUTBOUND_UDP_RETRY 4
+#define OUTBOUND_UDP_RETRY 1
/** initiate TCP transaction for serviced query */
static void serviced_tcp_initiate(struct outside_network* outnet,
sq->pending = NULL; /* removed after this callback */
if(error != NETEVENT_NOERROR && verbosity >= VERB_DETAIL)
log_addr("tcp error for address", &sq->addr, sq->addrlen);
+ if(error==NETEVENT_NOERROR)
+ infra_update_tcp_works(sq->outnet->infra, &sq->addr,
+ sq->addrlen);
if(error==NETEVENT_NOERROR && LDNS_RCODE_WIRE(ldns_buffer_begin(
c->buffer)) == LDNS_RCODE_FORMERR &&
sq->status == serviced_query_TCP_EDNS) {
struct serviced_query* sq = (struct serviced_query*)arg;
struct outside_network* outnet = sq->outnet;
struct timeval now;
+ int fallback_tcp = 0;
if(gettimeofday(&now, NULL) < 0) {
log_err("gettimeofday: %s", strerror(errno));
/* this option does not need current time */
}
sq->pending = NULL; /* removed after callback */
if(error == NETEVENT_TIMEOUT) {
+ int rto = 0;
sq->retry++;
- if(!infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
- -1, (time_t)now.tv_sec))
+ if(!(rto=infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
+ -1, (time_t)now.tv_sec)))
log_err("out of memory in UDP exponential backoff");
if(sq->retry < OUTBOUND_UDP_RETRY) {
log_name_addr(VERB_ALGO, "retry query", sq->qbuf+10,
}
return 0;
}
- error = NETEVENT_TIMEOUT;
- /* UDP does not work, fallback to TCP below */
+ if(rto >= RTT_MAX_TIMEOUT) {
+ fallback_tcp = 1;
+ /* UDP does not work, fallback to TCP below */
+ } else {
+ serviced_callbacks(sq, NETEVENT_TIMEOUT, c, rep);
+ return 0;
+ }
}
if(error == NETEVENT_NOERROR && sq->status == serviced_query_UDP_EDNS
&& LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer))
}
return 0;
}
- if(error != NETEVENT_NOERROR ||
- LDNS_TC_WIRE(ldns_buffer_begin(c->buffer))) {
+ if(LDNS_TC_WIRE(ldns_buffer_begin(c->buffer)) ||
+ (error != NETEVENT_NOERROR && fallback_tcp) ) {
/* fallback to TCP */
/* this discards partial UDP contents */
if(sq->status == serviced_query_UDP_EDNS)