From: Wouter Wijngaards Date: Wed, 23 May 2007 06:24:01 +0000 (+0000) Subject: precise timers for roundtrip UDP timeouts. X-Git-Tag: release-0.4~134 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c4096b865462fe1fc5e2d0d3042e6199d499a4bb;p=thirdparty%2Funbound.git precise timers for roundtrip UDP timeouts. git-svn-id: file:///svn/unbound/trunk@332 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/daemon/worker.c b/daemon/worker.c index f3d51d1e3..165cc9a59 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -730,8 +730,9 @@ worker_send_packet(ldns_buffer* pkt, struct sockaddr_storage* addr, timeout, worker_handle_reply, q->work_info, worker->rndstate) != 0; } - return pending_udp_query(worker->back, pkt, addr, addrlen, timeout, - worker_handle_reply, q->work_info, worker->rndstate) != 0; + return pending_udp_query(worker->back, pkt, addr, addrlen, + timeout*1000, worker_handle_reply, q->work_info, + worker->rndstate) != 0; } struct outbound_entry* diff --git a/doc/Changelog b/doc/Changelog index 53b8af6a5..e1fa1339b 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,7 @@ +23 May 2007: Wouter + - outside network does precise timers for roundtrip estimates for rtt + and for setting timeout for UDP. Pending_udp takes milliseconds. + 22 May 2007: Wouter - outbound query list for modules and support to callback with the outbound entry to the module. diff --git a/services/outside_network.c b/services/outside_network.c index 0fcb7a4a1..e312ebe57 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -745,8 +745,8 @@ pending_udp_query(struct outside_network* outnet, ldns_buffer* packet, /* system calls to set timeout after sending UDP to make roundtrip smaller. */ - tv.tv_sec = timeout; - tv.tv_usec = 0; + tv.tv_sec = timeout/1000; + tv.tv_usec = (timeout%1000)*1000; comm_timer_set(pend->timer, &tv); return pend; } @@ -988,9 +988,11 @@ serviced_udp_send(struct serviced_query* sq, ldns_buffer* buff) else sq->status = serviced_query_UDP; } serviced_encode(sq, buff, sq->status == serviced_query_UDP_EDNS); - sq->last_sent_time = now; - /* round rtt to whole seconds for now. TODO better timing */ - rtt = rtt/1000 + 1; + if(gettimeofday(&sq->last_sent_time, NULL) < 0) { + log_err("gettimeofday: %s", strerror(errno)); + return 0; + } + verbose(VERB_DETAIL, "serviced query UDP timeout=%d msec", rtt); sq->pending = pending_udp_query(sq->outnet, buff, &sq->addr, sq->addrlen, rtt, serviced_udp_callback, sq, sq->outnet->rnd); if(!sq->pending) @@ -1058,13 +1060,17 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error, { struct serviced_query* sq = (struct serviced_query*)arg; struct outside_network* outnet = sq->outnet; - time_t now = time(NULL); - int roundtime; + struct timeval now; + if(gettimeofday(&now, NULL) < 0) { + log_err("gettimeofday: %s", strerror(errno)); + /* this option does not need current time */ + error = NETEVENT_CLOSED; + } sq->pending = NULL; /* removed after callback */ if(error == NETEVENT_TIMEOUT) { sq->retry++; if(!infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen, - -1, now)) + -1, now.tv_sec)) log_err("out of memory in UDP exponential backoff"); if(sq->retry < OUTBOUND_UDP_RETRY) { if(!serviced_udp_send(sq, c->buffer)) { @@ -1082,7 +1088,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error, == LDNS_RCODE_FORMERR) { /* note no EDNS, fallback without EDNS */ if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen, - -1, now)) { + -1, now.tv_sec)) { log_err("Out of memory caching no edns for host"); } sq->status = serviced_query_UDP; @@ -1105,11 +1111,17 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error, return 0; } /* yay! an answer */ - roundtime = (int)now - (int)sq->last_sent_time; - if(roundtime >= 0) + if(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)) { + /* convert from microseconds to milliseconds */ + int roundtime = (now.tv_sec - sq->last_sent_time.tv_sec)*1000 + + ((int)now.tv_usec - (int)sq->last_sent_time.tv_usec)/1000; + log_info("measured roundtrip at %d msec", roundtime); if(!infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen, - roundtime*1000, now)) + roundtime, now.tv_sec)) log_err("out of memory noting rtt."); + } (void)rbtree_delete(outnet->serviced, sq); serviced_callbacks(sq, error, c, rep); serviced_delete(sq); diff --git a/services/outside_network.h b/services/outside_network.h index e1a565278..45d0d2dae 100644 --- a/services/outside_network.h +++ b/services/outside_network.h @@ -226,7 +226,7 @@ struct serviced_query { /** number of UDP retries */ int retry; /** time last UDP was sent */ - time_t last_sent_time; + struct timeval last_sent_time; /** outside network this is part of */ struct outside_network* outnet; /** list of interested parties that need callback on results. */ @@ -270,7 +270,7 @@ void outside_network_delete(struct outside_network* outnet); * @param packet: wireformat query to send to destination. * @param addr: address to send to. * @param addrlen: length of addr. - * @param timeout: in seconds from now. + * @param timeout: in milliseconds from now. * @param callback: function to call on error, timeout or reply. * @param callback_arg: user argument for callback function. * @param rnd: random state for generating ID and port. diff --git a/testcode/fake_event.c b/testcode/fake_event.c index 0255c9df3..ee60f1166 100644 --- a/testcode/fake_event.c +++ b/testcode/fake_event.c @@ -687,7 +687,7 @@ pending_udp_query(struct outside_network* outnet, ldns_buffer* packet, pend->addrlen = addrlen; pend->callback = callback; pend->cb_arg = callback_arg; - pend->timeout = timeout; + pend->timeout = timeout/1000; pend->transport = transport_udp; pend->pkt = NULL; pend->runtime = runtime; diff --git a/util/mini_event.c b/util/mini_event.c index 6eb5b500c..d33faabab 100644 --- a/util/mini_event.c +++ b/util/mini_event.c @@ -159,8 +159,6 @@ static int handle_select(struct event_base* base, struct timeval* wait) if(wait->tv_sec==(time_t)-1) wait = NULL; #endif - if(wait) log_info("waiting for %d %d", wait->tv_sec, wait->tv_usec); - else log_info("wait forever"); memmove(&r, &base->reads, sizeof(fd_set)); memmove(&w, &base->writes, sizeof(fd_set));