13b6c3722Schristos /*
23b6c3722Schristos * util/rtt.c - UDP round trip time estimator for resend timeouts.
33b6c3722Schristos *
43b6c3722Schristos * Copyright (c) 2007, NLnet Labs. All rights reserved.
53b6c3722Schristos *
63b6c3722Schristos * This software is open source.
73b6c3722Schristos *
83b6c3722Schristos * Redistribution and use in source and binary forms, with or without
93b6c3722Schristos * modification, are permitted provided that the following conditions
103b6c3722Schristos * are met:
113b6c3722Schristos *
123b6c3722Schristos * Redistributions of source code must retain the above copyright notice,
133b6c3722Schristos * this list of conditions and the following disclaimer.
143b6c3722Schristos *
153b6c3722Schristos * Redistributions in binary form must reproduce the above copyright notice,
163b6c3722Schristos * this list of conditions and the following disclaimer in the documentation
173b6c3722Schristos * and/or other materials provided with the distribution.
183b6c3722Schristos *
193b6c3722Schristos * Neither the name of the NLNET LABS nor the names of its contributors may
203b6c3722Schristos * be used to endorse or promote products derived from this software without
213b6c3722Schristos * specific prior written permission.
223b6c3722Schristos *
233b6c3722Schristos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
243b6c3722Schristos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
253b6c3722Schristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
263b6c3722Schristos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
273b6c3722Schristos * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
283b6c3722Schristos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
293b6c3722Schristos * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
303b6c3722Schristos * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
313b6c3722Schristos * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
323b6c3722Schristos * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
333b6c3722Schristos * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
343b6c3722Schristos */
353b6c3722Schristos
363b6c3722Schristos /**
373b6c3722Schristos * \file
383b6c3722Schristos *
393b6c3722Schristos * This file contains a data type and functions to help estimate good
403b6c3722Schristos * round trip times for UDP resend timeout values.
413b6c3722Schristos */
423b6c3722Schristos #include "config.h"
433b6c3722Schristos #include "util/rtt.h"
44f42d8de7Schristos #include "iterator/iterator.h"
453b6c3722Schristos
463b6c3722Schristos /* overwritten by config: infra_cache_min_rtt: */
473b6c3722Schristos int RTT_MIN_TIMEOUT = 50;
48*7a540f2bSchristos /* overwritten by config: infra_cache_max_rtt: */
49*7a540f2bSchristos int RTT_MAX_TIMEOUT = 120000;
50*7a540f2bSchristos
513b6c3722Schristos /** calculate RTO from rtt information */
523b6c3722Schristos static int
calc_rto(const struct rtt_info * rtt)533b6c3722Schristos calc_rto(const struct rtt_info* rtt)
543b6c3722Schristos {
553b6c3722Schristos /* From Stevens, Unix Network Programming, Vol1, 3rd ed., p.598 */
563b6c3722Schristos int rto = rtt->srtt + 4*rtt->rttvar;
573b6c3722Schristos if(rto < RTT_MIN_TIMEOUT)
583b6c3722Schristos rto = RTT_MIN_TIMEOUT;
593b6c3722Schristos if(rto > RTT_MAX_TIMEOUT)
603b6c3722Schristos rto = RTT_MAX_TIMEOUT;
613b6c3722Schristos return rto;
623b6c3722Schristos }
633b6c3722Schristos
643b6c3722Schristos void
rtt_init(struct rtt_info * rtt)653b6c3722Schristos rtt_init(struct rtt_info* rtt)
663b6c3722Schristos {
673b6c3722Schristos rtt->srtt = 0;
68f42d8de7Schristos rtt->rttvar = UNKNOWN_SERVER_NICENESS/4;
693b6c3722Schristos rtt->rto = calc_rto(rtt);
703b6c3722Schristos /* default value from the book is 0 + 4*0.75 = 3 seconds */
713b6c3722Schristos /* first RTO is 0 + 4*0.094 = 0.376 seconds */
723b6c3722Schristos }
733b6c3722Schristos
743b6c3722Schristos int
rtt_timeout(const struct rtt_info * rtt)753b6c3722Schristos rtt_timeout(const struct rtt_info* rtt)
763b6c3722Schristos {
773b6c3722Schristos return rtt->rto;
783b6c3722Schristos }
793b6c3722Schristos
803b6c3722Schristos int
rtt_unclamped(const struct rtt_info * rtt)813b6c3722Schristos rtt_unclamped(const struct rtt_info* rtt)
823b6c3722Schristos {
833b6c3722Schristos if(calc_rto(rtt) != rtt->rto) {
843b6c3722Schristos /* timeout fallback has happened */
853b6c3722Schristos return rtt->rto;
863b6c3722Schristos }
873b6c3722Schristos /* return unclamped value */
883b6c3722Schristos return rtt->srtt + 4*rtt->rttvar;
893b6c3722Schristos }
903b6c3722Schristos
913b6c3722Schristos void
rtt_update(struct rtt_info * rtt,int ms)923b6c3722Schristos rtt_update(struct rtt_info* rtt, int ms)
933b6c3722Schristos {
943b6c3722Schristos int delta = ms - rtt->srtt;
953b6c3722Schristos rtt->srtt += delta / 8; /* g = 1/8 */
963b6c3722Schristos if(delta < 0)
973b6c3722Schristos delta = -delta; /* |delta| */
983b6c3722Schristos rtt->rttvar += (delta - rtt->rttvar) / 4; /* h = 1/4 */
993b6c3722Schristos rtt->rto = calc_rto(rtt);
1003b6c3722Schristos }
1013b6c3722Schristos
1023b6c3722Schristos void
rtt_lost(struct rtt_info * rtt,int orig)1033b6c3722Schristos rtt_lost(struct rtt_info* rtt, int orig)
1043b6c3722Schristos {
1053b6c3722Schristos /* exponential backoff */
1063b6c3722Schristos
1073b6c3722Schristos /* if a query succeeded and put down the rto meanwhile, ignore this */
1083b6c3722Schristos if(rtt->rto < orig)
1093b6c3722Schristos return;
1103b6c3722Schristos
1113b6c3722Schristos /* the original rto is doubled, not the current one to make sure
1123b6c3722Schristos * that the values in the cache are not increased by lots of
1133b6c3722Schristos * queries simultaneously as they time out at the same time */
1143b6c3722Schristos orig *= 2;
1153b6c3722Schristos if(rtt->rto <= orig) {
1163b6c3722Schristos rtt->rto = orig;
1173b6c3722Schristos if(rtt->rto > RTT_MAX_TIMEOUT)
1183b6c3722Schristos rtt->rto = RTT_MAX_TIMEOUT;
1193b6c3722Schristos }
1203b6c3722Schristos }
1213b6c3722Schristos
rtt_notimeout(const struct rtt_info * rtt)1223b6c3722Schristos int rtt_notimeout(const struct rtt_info* rtt)
1233b6c3722Schristos {
1243b6c3722Schristos return calc_rto(rtt);
1253b6c3722Schristos }
126