blob: 8e990690703bed5890e29d264a60583cb0827443 [file] [log] [blame]
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2//
3// Copyright (c) 2006 Georgia Tech Research Corporation
4// (c) 2013 University of Arizona
5// (c) 2013 University of California, Los Angeles
6//
7// This program is free software; you can redistribute it and/or modify
8// it under the terms of the GNU General Public License version 2 as
9// published by the Free Software Foundation;
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with this program; if not, write to the Free Software
18// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19//
20// Author: Rajib Bhattacharjea<raj.b@gatech.edu>
21// Cheng Yi <yic@email.arizona.edu>
22// Alexander Afanasyev <alexander.afanasyev@ucla.edu>
23//
24
25// Georgia Tech Network Simulator - Round Trip Time Estimation Class
26// George F. Riley. Georgia Tech, Spring 2002
27
Alexander Afanasyev0c395372014-12-20 15:54:02 -080028#include "ndn-rtt-mean-deviation.hpp"
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -080029#include "ns3/simulator.h"
30#include "ns3/double.h"
31#include "ns3/integer.h"
32#include "ns3/uinteger.h"
33#include "ns3/log.h"
34
35NS_LOG_COMPONENT_DEFINE ("ndn.RttMeanDeviation");
36
37namespace ns3 {
38namespace ndn {
39
40//---------------------------------------------------------------------------------
41// A modified version of Mean-Deviation Estimator optimized for NDN packet delivery
42
43NS_OBJECT_ENSURE_REGISTERED (RttMeanDeviation);
44
45TypeId
46RttMeanDeviation::GetTypeId (void)
47{
48 static TypeId tid = TypeId ("ns3::ndn::RttMeanDeviation")
49 .SetParent<RttEstimator> ()
50 .AddConstructor<RttMeanDeviation> ()
51 .AddAttribute ("Gain",
52 "Gain used in estimating the RTT (smoothed RTT), must be 0 < Gain < 1",
53 DoubleValue (0.125),
54 MakeDoubleAccessor (&RttMeanDeviation::m_gain),
55 MakeDoubleChecker<double> ())
56 .AddAttribute ("Gain2",
57 "Gain2 used in estimating the RTT (variance), must be 0 < Gain2 < 1",
58 DoubleValue (0.25),
59 MakeDoubleAccessor (&RttMeanDeviation::m_gain2),
60 MakeDoubleChecker<double> ())
61 ;
62 return tid;
63}
64
65RttMeanDeviation::RttMeanDeviation() :
66 m_variance (0)
67{
68 NS_LOG_FUNCTION (this);
69}
70
71RttMeanDeviation::RttMeanDeviation (const RttMeanDeviation& c)
72 : RttEstimator (c), m_gain (c.m_gain), m_gain2 (c.m_gain2), m_variance (c.m_variance)
73{
74 NS_LOG_FUNCTION (this);
75}
76
Yaogong Wang87cd0652013-05-28 11:00:45 -040077TypeId
78RttMeanDeviation::GetInstanceTypeId (void) const
79{
80 return GetTypeId ();
81}
82
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -080083void RttMeanDeviation::Measurement (Time m)
84{
85 NS_LOG_FUNCTION (this << m);
86 if (m_nSamples)
87 { // Not first
88 Time err (m - m_currentEstimatedRtt);
89 double gErr = err.ToDouble (Time::S) * m_gain;
90 m_currentEstimatedRtt += Time::FromDouble (gErr, Time::S);
91 Time difference = Abs (err) - m_variance;
92 NS_LOG_DEBUG ("m_variance += " << Time::FromDouble (difference.ToDouble (Time::S) * m_gain2, Time::S));
93 m_variance += Time::FromDouble (difference.ToDouble (Time::S) * m_gain2, Time::S);
94 }
95 else
96 { // First sample
97 m_currentEstimatedRtt = m; // Set estimate to current
98 //variance = sample / 2; // And variance to current / 2
99 // m_variance = m; // try this why????
100 m_variance = Seconds (m.ToDouble (Time::S) / 2);
101 NS_LOG_DEBUG ("(first sample) m_variance += " << m);
102 }
103 m_nSamples++;
104}
105
106Time RttMeanDeviation::RetransmitTimeout ()
107{
108 NS_LOG_FUNCTION (this);
109
110 double retval = std::min (m_maxRto.ToDouble (Time::S),
111 std::max (m_multiplier*m_minRto.ToDouble (Time::S),
112 m_multiplier*(m_currentEstimatedRtt.ToDouble (Time::S) + 4 * m_variance.ToDouble (Time::S))));
113
114 NS_LOG_DEBUG ("RetransmitTimeout: return " << retval);
115
116 return Seconds (retval);
117}
118
119Ptr<RttEstimator> RttMeanDeviation::Copy () const
120{
121 NS_LOG_FUNCTION (this);
122 return CopyObject<RttMeanDeviation> (this);
123}
124
125void RttMeanDeviation::Reset ()
126{
127 NS_LOG_FUNCTION (this);
128 // Reset to initial state
129 m_variance = Seconds (0);
130 RttEstimator::Reset ();
131}
132
133void RttMeanDeviation::Gain (double g)
134{
135 NS_LOG_FUNCTION (this);
136 NS_ASSERT_MSG( (g > 0) && (g < 1), "RttMeanDeviation: Gain must be less than 1 and greater than 0" );
137 m_gain = g;
138}
139
Cheng Yi3089c472013-03-07 18:12:41 -0700140void RttMeanDeviation::SentSeq (SequenceNumber32 seq, uint32_t size)
141{
142 NS_LOG_FUNCTION (this << seq << size);
143
144 RttHistory_t::iterator i;
145 for (i = m_history.begin (); i != m_history.end (); ++i)
146 {
147 if (seq == i->seq)
148 { // Found it
149 i->retx = true;
150 break;
151 }
152 }
153
154 // Note that a particular sequence has been sent
155 if (i == m_history.end())
156 m_history.push_back (RttHistory (seq, size, Simulator::Now () ));
157}
158
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800159Time RttMeanDeviation::AckSeq (SequenceNumber32 ackSeq)
160{
161 NS_LOG_FUNCTION (this << ackSeq);
162 // An ack has been received, calculate rtt and log this measurement
163 // Note we use a linear search (O(n)) for this since for the common
164 // case the ack'ed packet will be at the head of the list
165 Time m = Seconds (0.0);
166 if (m_history.size () == 0) return (m); // No pending history, just exit
167
168 for (RttHistory_t::iterator i = m_history.begin (); i != m_history.end (); ++i)
169 {
170 if (ackSeq == i->seq)
171 { // Found it
Cheng Yi3089c472013-03-07 18:12:41 -0700172 if (!i->retx) {
173 m = Simulator::Now () - i->time;// Elapsed time
174 Measurement (m); // Log the measurement
175 ResetMultiplier (); // Reset multiplier on valid measurement
176 }
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800177 m_history.erase(i);
178 break;
179 }
180 }
181
182 return m;
183}
184
185} // namespace ndn
186} // namespace ns3
187