xref: /openbsd-src/usr.sbin/unbound/util/rtt.c (revision 1996a427c80099fb75c487fd0f8e3fdeef7d1171)
1933707f3Ssthen /*
2933707f3Ssthen  * util/rtt.c - UDP round trip time estimator for resend timeouts.
3933707f3Ssthen  *
4933707f3Ssthen  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5933707f3Ssthen  *
6933707f3Ssthen  * This software is open source.
7933707f3Ssthen  *
8933707f3Ssthen  * Redistribution and use in source and binary forms, with or without
9933707f3Ssthen  * modification, are permitted provided that the following conditions
10933707f3Ssthen  * are met:
11933707f3Ssthen  *
12933707f3Ssthen  * Redistributions of source code must retain the above copyright notice,
13933707f3Ssthen  * this list of conditions and the following disclaimer.
14933707f3Ssthen  *
15933707f3Ssthen  * Redistributions in binary form must reproduce the above copyright notice,
16933707f3Ssthen  * this list of conditions and the following disclaimer in the documentation
17933707f3Ssthen  * and/or other materials provided with the distribution.
18933707f3Ssthen  *
19933707f3Ssthen  * Neither the name of the NLNET LABS nor the names of its contributors may
20933707f3Ssthen  * be used to endorse or promote products derived from this software without
21933707f3Ssthen  * specific prior written permission.
22933707f3Ssthen  *
23933707f3Ssthen  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
245d76a658Ssthen  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
255d76a658Ssthen  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
265d76a658Ssthen  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
275d76a658Ssthen  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
285d76a658Ssthen  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
295d76a658Ssthen  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
305d76a658Ssthen  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
315d76a658Ssthen  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
325d76a658Ssthen  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
335d76a658Ssthen  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34933707f3Ssthen  */
35933707f3Ssthen 
36933707f3Ssthen /**
37933707f3Ssthen  * \file
38933707f3Ssthen  *
39933707f3Ssthen  * This file contains a data type and functions to help estimate good
40933707f3Ssthen  * round trip times for UDP resend timeout values.
41933707f3Ssthen  */
42933707f3Ssthen #include "config.h"
43933707f3Ssthen #include "util/rtt.h"
447bc20e6dSsthen #include "iterator/iterator.h"
45933707f3Ssthen 
46b2cdf21fSsthen /* overwritten by config: infra_cache_min_rtt: */
47b2cdf21fSsthen int RTT_MIN_TIMEOUT = 50;
48*1996a427Ssthen /* overwritten by config: infra_cache_max_rtt: */
49*1996a427Ssthen int RTT_MAX_TIMEOUT = 120000;
50*1996a427Ssthen 
51933707f3Ssthen /** calculate RTO from rtt information */
52933707f3Ssthen static int
calc_rto(const struct rtt_info * rtt)53933707f3Ssthen calc_rto(const struct rtt_info* rtt)
54933707f3Ssthen {
55933707f3Ssthen 	/* From Stevens, Unix Network Programming, Vol1, 3rd ed., p.598 */
56933707f3Ssthen 	int rto = rtt->srtt + 4*rtt->rttvar;
57933707f3Ssthen 	if(rto < RTT_MIN_TIMEOUT)
58933707f3Ssthen 		rto = RTT_MIN_TIMEOUT;
59933707f3Ssthen 	if(rto > RTT_MAX_TIMEOUT)
60933707f3Ssthen 		rto = RTT_MAX_TIMEOUT;
61933707f3Ssthen 	return rto;
62933707f3Ssthen }
63933707f3Ssthen 
64933707f3Ssthen void
rtt_init(struct rtt_info * rtt)65933707f3Ssthen rtt_init(struct rtt_info* rtt)
66933707f3Ssthen {
67933707f3Ssthen 	rtt->srtt = 0;
687bc20e6dSsthen 	rtt->rttvar = UNKNOWN_SERVER_NICENESS/4;
69933707f3Ssthen 	rtt->rto = calc_rto(rtt);
70933707f3Ssthen 	/* default value from the book is 0 + 4*0.75 = 3 seconds */
71933707f3Ssthen 	/* first RTO is 0 + 4*0.094 = 0.376 seconds */
72933707f3Ssthen }
73933707f3Ssthen 
74933707f3Ssthen int
rtt_timeout(const struct rtt_info * rtt)75933707f3Ssthen rtt_timeout(const struct rtt_info* rtt)
76933707f3Ssthen {
77933707f3Ssthen 	return rtt->rto;
78933707f3Ssthen }
79933707f3Ssthen 
80933707f3Ssthen int
rtt_unclamped(const struct rtt_info * rtt)81933707f3Ssthen rtt_unclamped(const struct rtt_info* rtt)
82933707f3Ssthen {
83933707f3Ssthen 	if(calc_rto(rtt) != rtt->rto) {
84933707f3Ssthen 		/* timeout fallback has happened */
85933707f3Ssthen 		return rtt->rto;
86933707f3Ssthen 	}
87933707f3Ssthen 	/* return unclamped value */
88933707f3Ssthen 	return rtt->srtt + 4*rtt->rttvar;
89933707f3Ssthen }
90933707f3Ssthen 
91933707f3Ssthen void
rtt_update(struct rtt_info * rtt,int ms)92933707f3Ssthen rtt_update(struct rtt_info* rtt, int ms)
93933707f3Ssthen {
94933707f3Ssthen 	int delta = ms - rtt->srtt;
95933707f3Ssthen 	rtt->srtt += delta / 8; /* g = 1/8 */
96933707f3Ssthen 	if(delta < 0)
97933707f3Ssthen 		delta = -delta; /* |delta| */
98933707f3Ssthen 	rtt->rttvar += (delta - rtt->rttvar) / 4; /* h = 1/4 */
99933707f3Ssthen 	rtt->rto = calc_rto(rtt);
100933707f3Ssthen }
101933707f3Ssthen 
102933707f3Ssthen void
rtt_lost(struct rtt_info * rtt,int orig)103933707f3Ssthen rtt_lost(struct rtt_info* rtt, int orig)
104933707f3Ssthen {
105933707f3Ssthen 	/* exponential backoff */
106933707f3Ssthen 
107933707f3Ssthen 	/* if a query succeeded and put down the rto meanwhile, ignore this */
108933707f3Ssthen 	if(rtt->rto < orig)
109933707f3Ssthen 		return;
110933707f3Ssthen 
111933707f3Ssthen 	/* the original rto is doubled, not the current one to make sure
112933707f3Ssthen 	 * that the values in the cache are not increased by lots of
113933707f3Ssthen 	 * queries simultaneously as they time out at the same time */
114933707f3Ssthen 	orig *= 2;
115933707f3Ssthen 	if(rtt->rto <= orig) {
116933707f3Ssthen 		rtt->rto = orig;
117933707f3Ssthen 		if(rtt->rto > RTT_MAX_TIMEOUT)
118933707f3Ssthen 			rtt->rto = RTT_MAX_TIMEOUT;
119933707f3Ssthen 	}
120933707f3Ssthen }
121933707f3Ssthen 
rtt_notimeout(const struct rtt_info * rtt)122933707f3Ssthen int rtt_notimeout(const struct rtt_info* rtt)
123933707f3Ssthen {
124933707f3Ssthen 	return calc_rto(rtt);
125933707f3Ssthen }
126