1b7579f77SDag-Erling Smørgrav /*
2b7579f77SDag-Erling Smørgrav * util/rtt.c - UDP round trip time estimator for resend timeouts.
3b7579f77SDag-Erling Smørgrav *
4b7579f77SDag-Erling Smørgrav * Copyright (c) 2007, NLnet Labs. All rights reserved.
5b7579f77SDag-Erling Smørgrav *
6b7579f77SDag-Erling Smørgrav * This software is open source.
7b7579f77SDag-Erling Smørgrav *
8b7579f77SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without
9b7579f77SDag-Erling Smørgrav * modification, are permitted provided that the following conditions
10b7579f77SDag-Erling Smørgrav * are met:
11b7579f77SDag-Erling Smørgrav *
12b7579f77SDag-Erling Smørgrav * Redistributions of source code must retain the above copyright notice,
13b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer.
14b7579f77SDag-Erling Smørgrav *
15b7579f77SDag-Erling Smørgrav * Redistributions in binary form must reproduce the above copyright notice,
16b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer in the documentation
17b7579f77SDag-Erling Smørgrav * and/or other materials provided with the distribution.
18b7579f77SDag-Erling Smørgrav *
19b7579f77SDag-Erling Smørgrav * Neither the name of the NLNET LABS nor the names of its contributors may
20b7579f77SDag-Erling Smørgrav * be used to endorse or promote products derived from this software without
21b7579f77SDag-Erling Smørgrav * specific prior written permission.
22b7579f77SDag-Erling Smørgrav *
23b7579f77SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2417d15b25SDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2517d15b25SDag-Erling Smørgrav * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2617d15b25SDag-Erling Smørgrav * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2717d15b25SDag-Erling Smørgrav * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2817d15b25SDag-Erling Smørgrav * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2917d15b25SDag-Erling Smørgrav * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3017d15b25SDag-Erling Smørgrav * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3117d15b25SDag-Erling Smørgrav * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3217d15b25SDag-Erling Smørgrav * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3317d15b25SDag-Erling Smørgrav * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34b7579f77SDag-Erling Smørgrav */
35b7579f77SDag-Erling Smørgrav
36b7579f77SDag-Erling Smørgrav /**
37b7579f77SDag-Erling Smørgrav * \file
38b7579f77SDag-Erling Smørgrav *
39b7579f77SDag-Erling Smørgrav * This file contains a data type and functions to help estimate good
40b7579f77SDag-Erling Smørgrav * round trip times for UDP resend timeout values.
41b7579f77SDag-Erling Smørgrav */
42b7579f77SDag-Erling Smørgrav #include "config.h"
43b7579f77SDag-Erling Smørgrav #include "util/rtt.h"
444c75e3aaSDag-Erling Smørgrav #include "iterator/iterator.h"
45b7579f77SDag-Erling Smørgrav
466480faa8SDag-Erling Smørgrav /* overwritten by config: infra_cache_min_rtt: */
476480faa8SDag-Erling Smørgrav int RTT_MIN_TIMEOUT = 50;
48*790c6b24SCy Schubert /* overwritten by config: infra_cache_max_rtt: */
49*790c6b24SCy Schubert int RTT_MAX_TIMEOUT = 120000;
50*790c6b24SCy Schubert
51b7579f77SDag-Erling Smørgrav /** calculate RTO from rtt information */
52b7579f77SDag-Erling Smørgrav static int
calc_rto(const struct rtt_info * rtt)53b7579f77SDag-Erling Smørgrav calc_rto(const struct rtt_info* rtt)
54b7579f77SDag-Erling Smørgrav {
55b7579f77SDag-Erling Smørgrav /* From Stevens, Unix Network Programming, Vol1, 3rd ed., p.598 */
56b7579f77SDag-Erling Smørgrav int rto = rtt->srtt + 4*rtt->rttvar;
57b7579f77SDag-Erling Smørgrav if(rto < RTT_MIN_TIMEOUT)
58b7579f77SDag-Erling Smørgrav rto = RTT_MIN_TIMEOUT;
59b7579f77SDag-Erling Smørgrav if(rto > RTT_MAX_TIMEOUT)
60b7579f77SDag-Erling Smørgrav rto = RTT_MAX_TIMEOUT;
61b7579f77SDag-Erling Smørgrav return rto;
62b7579f77SDag-Erling Smørgrav }
63b7579f77SDag-Erling Smørgrav
64b7579f77SDag-Erling Smørgrav void
rtt_init(struct rtt_info * rtt)65b7579f77SDag-Erling Smørgrav rtt_init(struct rtt_info* rtt)
66b7579f77SDag-Erling Smørgrav {
67b7579f77SDag-Erling Smørgrav rtt->srtt = 0;
684c75e3aaSDag-Erling Smørgrav rtt->rttvar = UNKNOWN_SERVER_NICENESS/4;
69b7579f77SDag-Erling Smørgrav rtt->rto = calc_rto(rtt);
70b7579f77SDag-Erling Smørgrav /* default value from the book is 0 + 4*0.75 = 3 seconds */
71b7579f77SDag-Erling Smørgrav /* first RTO is 0 + 4*0.094 = 0.376 seconds */
72b7579f77SDag-Erling Smørgrav }
73b7579f77SDag-Erling Smørgrav
74b7579f77SDag-Erling Smørgrav int
rtt_timeout(const struct rtt_info * rtt)75b7579f77SDag-Erling Smørgrav rtt_timeout(const struct rtt_info* rtt)
76b7579f77SDag-Erling Smørgrav {
77b7579f77SDag-Erling Smørgrav return rtt->rto;
78b7579f77SDag-Erling Smørgrav }
79b7579f77SDag-Erling Smørgrav
80b7579f77SDag-Erling Smørgrav int
rtt_unclamped(const struct rtt_info * rtt)81b7579f77SDag-Erling Smørgrav rtt_unclamped(const struct rtt_info* rtt)
82b7579f77SDag-Erling Smørgrav {
83b7579f77SDag-Erling Smørgrav if(calc_rto(rtt) != rtt->rto) {
84b7579f77SDag-Erling Smørgrav /* timeout fallback has happened */
85b7579f77SDag-Erling Smørgrav return rtt->rto;
86b7579f77SDag-Erling Smørgrav }
87b7579f77SDag-Erling Smørgrav /* return unclamped value */
88b7579f77SDag-Erling Smørgrav return rtt->srtt + 4*rtt->rttvar;
89b7579f77SDag-Erling Smørgrav }
90b7579f77SDag-Erling Smørgrav
91b7579f77SDag-Erling Smørgrav void
rtt_update(struct rtt_info * rtt,int ms)92b7579f77SDag-Erling Smørgrav rtt_update(struct rtt_info* rtt, int ms)
93b7579f77SDag-Erling Smørgrav {
94b7579f77SDag-Erling Smørgrav int delta = ms - rtt->srtt;
95b7579f77SDag-Erling Smørgrav rtt->srtt += delta / 8; /* g = 1/8 */
96b7579f77SDag-Erling Smørgrav if(delta < 0)
97b7579f77SDag-Erling Smørgrav delta = -delta; /* |delta| */
98b7579f77SDag-Erling Smørgrav rtt->rttvar += (delta - rtt->rttvar) / 4; /* h = 1/4 */
99b7579f77SDag-Erling Smørgrav rtt->rto = calc_rto(rtt);
100b7579f77SDag-Erling Smørgrav }
101b7579f77SDag-Erling Smørgrav
102b7579f77SDag-Erling Smørgrav void
rtt_lost(struct rtt_info * rtt,int orig)103b7579f77SDag-Erling Smørgrav rtt_lost(struct rtt_info* rtt, int orig)
104b7579f77SDag-Erling Smørgrav {
105b7579f77SDag-Erling Smørgrav /* exponential backoff */
106b7579f77SDag-Erling Smørgrav
107b7579f77SDag-Erling Smørgrav /* if a query succeeded and put down the rto meanwhile, ignore this */
108b7579f77SDag-Erling Smørgrav if(rtt->rto < orig)
109b7579f77SDag-Erling Smørgrav return;
110b7579f77SDag-Erling Smørgrav
111b7579f77SDag-Erling Smørgrav /* the original rto is doubled, not the current one to make sure
112b7579f77SDag-Erling Smørgrav * that the values in the cache are not increased by lots of
113b7579f77SDag-Erling Smørgrav * queries simultaneously as they time out at the same time */
114b7579f77SDag-Erling Smørgrav orig *= 2;
115b7579f77SDag-Erling Smørgrav if(rtt->rto <= orig) {
116b7579f77SDag-Erling Smørgrav rtt->rto = orig;
117b7579f77SDag-Erling Smørgrav if(rtt->rto > RTT_MAX_TIMEOUT)
118b7579f77SDag-Erling Smørgrav rtt->rto = RTT_MAX_TIMEOUT;
119b7579f77SDag-Erling Smørgrav }
120b7579f77SDag-Erling Smørgrav }
121b7579f77SDag-Erling Smørgrav
rtt_notimeout(const struct rtt_info * rtt)122b7579f77SDag-Erling Smørgrav int rtt_notimeout(const struct rtt_info* rtt)
123b7579f77SDag-Erling Smørgrav {
124b7579f77SDag-Erling Smørgrav return calc_rto(rtt);
125b7579f77SDag-Erling Smørgrav }
126