A Discrete-Event Network Simulator
Home
Tutorials ▼
English
Portuguese
Docs ▼
Wiki
Manual
Models
Develop ▼
API
Bugs
API
Main Page
Related Pages
Modules
Namespaces
Classes
Files
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Properties
Friends
Macros
Groups
Pages
rtt-estimator.cc
Go to the documentation of this file.
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
//
3
// Copyright (c) 2006 Georgia Tech Research Corporation
4
//
5
// This program is free software; you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License version 2 as
7
// published by the Free Software Foundation;
8
//
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with this program; if not, write to the Free Software
16
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
//
18
// Author: Rajib Bhattacharjea<raj.b@gatech.edu>
19
//
20
21
22
// Ported from:
23
// Georgia Tech Network Simulator - Round Trip Time Estimation Class
24
// George F. Riley. Georgia Tech, Spring 2002
25
26
// Implements several variations of round trip time estimators
27
28
#include <iostream>
29
30
#include "
rtt-estimator.h
"
31
#include "ns3/simulator.h"
32
#include "ns3/double.h"
33
#include "ns3/integer.h"
34
#include "ns3/uinteger.h"
35
#include "ns3/log.h"
36
37
NS_LOG_COMPONENT_DEFINE
(
"RttEstimator"
);
38
39
namespace
ns3 {
40
41
NS_OBJECT_ENSURE_REGISTERED
(RttEstimator);
42
43
TypeId
44
RttEstimator::GetTypeId
(
void
)
45
{
46
static
TypeId
tid =
TypeId
(
"ns3::RttEstimator"
)
47
.
SetParent
<
Object
> ()
48
.AddAttribute (
"MaxMultiplier"
,
49
"Maximum RTO Multiplier"
,
50
UintegerValue
(64),
51
MakeUintegerAccessor (&
RttEstimator::m_maxMultiplier
),
52
MakeUintegerChecker<uint16_t> ())
53
.AddAttribute (
"InitialEstimation"
,
54
"Initial RTT estimation"
,
55
TimeValue
(
Seconds
(1.0)),
56
MakeTimeAccessor (&
RttEstimator::m_initialEstimatedRtt
),
57
MakeTimeChecker ())
58
.AddAttribute (
"MinRTO"
,
59
"Minimum retransmit timeout value"
,
60
TimeValue
(
Seconds
(0.2)),
// RFC2988 says min RTO=1 sec, but Linux uses 200ms. See http://www.postel.org/pipermail/end2end-interest/2004-November/004402.html
61
MakeTimeAccessor (&
RttEstimator::SetMinRto
,
62
&
RttEstimator::GetMinRto
),
63
MakeTimeChecker ())
64
;
65
return
tid;
66
}
67
68
void
69
RttEstimator::SetMinRto
(
Time
minRto)
70
{
71
NS_LOG_FUNCTION
(
this
<< minRto);
72
m_minRto
= minRto;
73
}
74
Time
75
RttEstimator::GetMinRto
(
void
)
const
76
{
77
return
m_minRto
;
78
}
79
void
80
RttEstimator::SetCurrentEstimate
(
Time
estimate)
81
{
82
NS_LOG_FUNCTION
(
this
<< estimate);
83
m_currentEstimatedRtt
= estimate;
84
}
85
Time
86
RttEstimator::GetCurrentEstimate
(
void
)
const
87
{
88
return
m_currentEstimatedRtt
;
89
}
90
91
92
//RttHistory methods
93
RttHistory::RttHistory
(
SequenceNumber32
s, uint32_t c,
Time
t)
94
: seq (s), count (c), time (t), retx (false)
95
{
96
NS_LOG_FUNCTION
(
this
);
97
}
98
99
RttHistory::RttHistory
(
const
RttHistory
& h)
100
: seq (h.seq), count (h.count), time (h.time), retx (h.retx)
101
{
102
NS_LOG_FUNCTION
(
this
);
103
}
104
105
// Base class methods
106
107
RttEstimator::RttEstimator
()
108
: m_next (1), m_history (),
109
m_nSamples (0),
110
m_multiplier (1)
111
{
112
NS_LOG_FUNCTION
(
this
);
113
//note next=1 everywhere since first segment will have sequence 1
114
115
// We need attributes initialized here, not later, so use the
116
// ConstructSelf() technique documented in the manual
117
ObjectBase::ConstructSelf
(
AttributeConstructionList
());
118
m_currentEstimatedRtt
=
m_initialEstimatedRtt
;
119
NS_LOG_DEBUG
(
"Initialize m_currentEstimatedRtt to "
<<
m_currentEstimatedRtt
.
GetSeconds
() <<
" sec."
);
120
}
121
122
RttEstimator::RttEstimator
(
const
RttEstimator
& c)
123
:
Object
(c), m_next (c.m_next), m_history (c.m_history),
124
m_maxMultiplier (c.m_maxMultiplier),
125
m_initialEstimatedRtt (c.m_initialEstimatedRtt),
126
m_currentEstimatedRtt (c.m_currentEstimatedRtt), m_minRto (c.m_minRto),
127
m_nSamples (c.m_nSamples), m_multiplier (c.m_multiplier)
128
{
129
NS_LOG_FUNCTION
(
this
);
130
}
131
132
RttEstimator::~RttEstimator
()
133
{
134
NS_LOG_FUNCTION
(
this
);
135
}
136
137
TypeId
138
RttEstimator::GetInstanceTypeId
(
void
)
const
139
{
140
return
GetTypeId
();
141
}
142
143
void
RttEstimator::SentSeq
(
SequenceNumber32
seq, uint32_t size)
144
{
145
NS_LOG_FUNCTION
(
this
<< seq << size);
146
// Note that a particular sequence has been sent
147
if
(seq ==
m_next
)
148
{
// This is the next expected one, just log at end
149
m_history
.push_back (
RttHistory
(seq, size,
Simulator::Now
() ));
150
m_next
= seq +
SequenceNumber32
(size);
// Update next expected
151
}
152
else
153
{
// This is a retransmit, find in list and mark as re-tx
154
for
(RttHistory_t::iterator i =
m_history
.begin (); i !=
m_history
.end (); ++i)
155
{
156
if
((seq >= i->seq) && (seq < (i->seq +
SequenceNumber32
(i->count))))
157
{
// Found it
158
i->retx =
true
;
159
// One final test..be sure this re-tx does not extend "next"
160
if
((seq +
SequenceNumber32
(size)) >
m_next
)
161
{
162
m_next
= seq +
SequenceNumber32
(size);
163
i->count = ((seq +
SequenceNumber32
(size)) - i->seq);
// And update count in hist
164
}
165
break
;
166
}
167
}
168
}
169
}
170
171
Time
RttEstimator::AckSeq
(
SequenceNumber32
ackSeq)
172
{
173
NS_LOG_FUNCTION
(
this
<< ackSeq);
174
// An ack has been received, calculate rtt and log this measurement
175
// Note we use a linear search (O(n)) for this since for the common
176
// case the ack'ed packet will be at the head of the list
177
Time
m =
Seconds
(0.0);
178
if
(
m_history
.size () == 0)
return
(m);
// No pending history, just exit
179
RttHistory
& h =
m_history
.front ();
180
if
(!h.
retx
&& ackSeq >= (h.
seq
+
SequenceNumber32
(h.
count
)))
181
{
// Ok to use this sample
182
m =
Simulator::Now
() - h.
time
;
// Elapsed time
183
Measurement
(m);
// Log the measurement
184
ResetMultiplier
();
// Reset multiplier on valid measurement
185
}
186
// Now delete all ack history with seq <= ack
187
while
(
m_history
.size () > 0)
188
{
189
RttHistory
& h =
m_history
.front ();
190
if
((h.
seq
+
SequenceNumber32
(h.
count
)) > ackSeq)
break
;
// Done removing
191
m_history
.pop_front ();
// Remove
192
}
193
return
m;
194
}
195
196
void
RttEstimator::ClearSent
()
197
{
198
NS_LOG_FUNCTION
(
this
);
199
// Clear all history entries
200
m_next
= 1;
201
m_history
.clear ();
202
}
203
204
void
RttEstimator::IncreaseMultiplier
()
205
{
206
NS_LOG_FUNCTION
(
this
);
207
m_multiplier
= (
m_multiplier
*2 <
m_maxMultiplier
) ?
m_multiplier
*2 :
m_maxMultiplier
;
208
NS_LOG_DEBUG
(
"Multiplier increased to "
<<
m_multiplier
);
209
}
210
211
void
RttEstimator::ResetMultiplier
()
212
{
213
NS_LOG_FUNCTION
(
this
);
214
m_multiplier
= 1;
215
}
216
217
void
RttEstimator::Reset
()
218
{
219
NS_LOG_FUNCTION
(
this
);
220
// Reset to initial state
221
m_next
= 1;
222
m_currentEstimatedRtt
=
m_initialEstimatedRtt
;
223
m_history
.clear ();
// Remove all info from the history
224
m_nSamples
= 0;
225
ResetMultiplier
();
226
}
227
228
229
230
//-----------------------------------------------------------------------------
231
//-----------------------------------------------------------------------------
232
// Mean-Deviation Estimator
233
234
NS_OBJECT_ENSURE_REGISTERED
(
RttMeanDeviation
);
235
236
TypeId
237
RttMeanDeviation::GetTypeId
(
void
)
238
{
239
static
TypeId
tid =
TypeId
(
"ns3::RttMeanDeviation"
)
240
.
SetParent
<
RttEstimator
> ()
241
.AddConstructor<RttMeanDeviation> ()
242
.AddAttribute (
"Gain"
,
243
"Gain used in estimating the RTT, must be 0 < Gain < 1"
,
244
DoubleValue
(0.1),
245
MakeDoubleAccessor (&
RttMeanDeviation::m_gain
),
246
MakeDoubleChecker<double> ())
247
;
248
return
tid;
249
}
250
251
RttMeanDeviation::RttMeanDeviation
() :
252
m_variance (0)
253
{
254
NS_LOG_FUNCTION
(
this
);
255
}
256
257
RttMeanDeviation::RttMeanDeviation
(
const
RttMeanDeviation
& c)
258
:
RttEstimator
(c), m_gain (c.m_gain), m_variance (c.m_variance)
259
{
260
NS_LOG_FUNCTION
(
this
);
261
}
262
263
TypeId
264
RttMeanDeviation::GetInstanceTypeId
(
void
)
const
265
{
266
return
GetTypeId
();
267
}
268
269
void
RttMeanDeviation::Measurement
(
Time
m)
270
{
271
NS_LOG_FUNCTION
(
this
<< m);
272
if
(
m_nSamples
)
273
{
// Not first
274
Time
err (m -
m_currentEstimatedRtt
);
275
double
gErr = err.
ToDouble
(
Time::S
) *
m_gain
;
276
m_currentEstimatedRtt
+=
Time::FromDouble
(gErr,
Time::S
);
277
Time
difference =
Abs
(err) -
m_variance
;
278
NS_LOG_DEBUG
(
"m_variance += "
<<
Time::FromDouble
(difference.
ToDouble
(
Time::S
) *
m_gain
,
Time::S
));
279
m_variance
+=
Time::FromDouble
(difference.
ToDouble
(
Time::S
) *
m_gain
,
Time::S
);
280
}
281
else
282
{
// First sample
283
m_currentEstimatedRtt
= m;
// Set estimate to current
284
//variance = sample / 2; // And variance to current / 2
285
m_variance
= m;
// try this
286
NS_LOG_DEBUG
(
"(first sample) m_variance += "
<< m);
287
}
288
m_nSamples
++;
289
}
290
291
Time
RttMeanDeviation::RetransmitTimeout
()
292
{
293
NS_LOG_FUNCTION
(
this
);
294
NS_LOG_DEBUG
(
"RetransmitTimeout: var "
<<
m_variance
.
GetSeconds
() <<
" est "
<<
m_currentEstimatedRtt
.
GetSeconds
() <<
" multiplier "
<<
m_multiplier
);
295
// RTO = srtt + 4* rttvar
296
int64_t temp =
m_currentEstimatedRtt
.
ToInteger
(
Time::MS
) + 4 *
m_variance
.
ToInteger
(
Time::MS
);
297
if
(temp <
m_minRto
.
ToInteger
(
Time::MS
))
298
{
299
temp =
m_minRto
.
ToInteger
(
Time::MS
);
300
}
301
temp = temp *
m_multiplier
;
// Apply backoff
302
Time
retval =
Time::FromInteger
(temp,
Time::MS
);
303
NS_LOG_DEBUG
(
"RetransmitTimeout: return "
<< retval.
GetSeconds
());
304
return
(retval);
305
}
306
307
Ptr<RttEstimator>
RttMeanDeviation::Copy
()
const
308
{
309
NS_LOG_FUNCTION
(
this
);
310
return
CopyObject<RttMeanDeviation> (
this
);
311
}
312
313
void
RttMeanDeviation::Reset
()
314
{
315
NS_LOG_FUNCTION
(
this
);
316
// Reset to initial state
317
m_variance
=
Seconds
(0);
318
RttEstimator::Reset
();
319
}
320
void
RttMeanDeviation::Gain
(
double
g)
321
{
322
NS_LOG_FUNCTION
(
this
);
323
NS_ASSERT_MSG
( (g > 0) && (g < 1),
"RttMeanDeviation: Gain must be less than 1 and greater than 0"
);
324
m_gain
= g;
325
}
326
327
}
//namespace ns3
src
internet
model
rtt-estimator.cc
Generated on Tue May 14 2013 11:08:23 for ns-3 by
1.8.1.2