blob: 9e63cef9011b35a2fe34223dd6293685bbedf144 [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//
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// THIS IS A COPY OF rtt-estimator.cc from internet module with minor modifications
22
23// Ported from:
24// Georgia Tech Network Simulator - Round Trip Time Estimation Class
25// George F. Riley. Georgia Tech, Spring 2002
26
27// Implements several variations of round trip time estimators
28
29#include <iostream>
30
Alexander Afanasyev0c395372014-12-20 15:54:02 -080031#include "ndn-rtt-estimator.hpp"
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -080032#include "ns3/simulator.h"
33#include "ns3/double.h"
34#include "ns3/integer.h"
35#include "ns3/uinteger.h"
36#include "ns3/log.h"
37
38NS_LOG_COMPONENT_DEFINE ("ndn.RttEstimator");
39
40namespace ns3 {
41
42namespace ndn {
43
44NS_OBJECT_ENSURE_REGISTERED (RttEstimator);
45
46TypeId
47RttEstimator::GetTypeId (void)
48{
49 static TypeId tid = TypeId ("ns3::ndn::RttEstimator")
50 .SetParent<Object> ()
51 .AddAttribute ("MaxMultiplier",
52 "Maximum RTO Multiplier",
53 UintegerValue (64),
54 MakeUintegerAccessor (&RttEstimator::m_maxMultiplier),
55 MakeUintegerChecker<uint16_t> ())
56 .AddAttribute ("InitialEstimation",
57 "Initial RTT estimation",
58 TimeValue (Seconds (1.0)),
59 MakeTimeAccessor (&RttEstimator::m_initialEstimatedRtt),
60 MakeTimeChecker ())
61 .AddAttribute ("MinRTO",
62 "Minimum retransmit timeout value",
63 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
64 MakeTimeAccessor (&RttEstimator::SetMinRto,
65 &RttEstimator::GetMinRto),
66 MakeTimeChecker ())
67 .AddAttribute ("MaxRTO",
68 "Maximum retransmit timeout value",
69 TimeValue (Seconds (200.0)),
70 MakeTimeAccessor (&RttEstimator::SetMaxRto,
71 &RttEstimator::GetMaxRto),
72 MakeTimeChecker ())
73 ;
74 return tid;
75}
76
77void
78RttEstimator::SetMinRto (Time minRto)
79{
80 NS_LOG_FUNCTION (this << minRto);
81 m_minRto = minRto;
82}
83Time
84RttEstimator::GetMinRto (void) const
85{
86 return m_minRto;
87}
88
89void
90RttEstimator::SetMaxRto (Time maxRto)
91{
92 NS_LOG_FUNCTION (this << maxRto);
93 m_maxRto = maxRto;
94}
95Time
96RttEstimator::GetMaxRto (void) const
97{
98 return m_maxRto;
99}
100
101void
102RttEstimator::SetCurrentEstimate (Time estimate)
103{
104 NS_LOG_FUNCTION (this << estimate);
105 m_currentEstimatedRtt = estimate;
106}
107Time
108RttEstimator::GetCurrentEstimate (void) const
109{
110 return m_currentEstimatedRtt;
111}
112
113
114//RttHistory methods
115RttHistory::RttHistory (SequenceNumber32 s, uint32_t c, Time t)
116 : seq (s), count (c), time (t), retx (false)
117{
118 NS_LOG_FUNCTION (this);
119}
120
121RttHistory::RttHistory (const RttHistory& h)
122 : seq (h.seq), count (h.count), time (h.time), retx (h.retx)
123{
124 NS_LOG_FUNCTION (this);
125}
126
127// Base class methods
128
129RttEstimator::RttEstimator ()
130 : m_next (1),
131 m_nSamples (0),
132 m_multiplier (1),
133 m_history ()
134{
135 NS_LOG_FUNCTION (this);
136 //note next=1 everywhere since first segment will have sequence 1
137
138 // We need attributes initialized here, not later, so use the
139 // ConstructSelf() technique documented in the manual
140 ObjectBase::ConstructSelf (AttributeConstructionList ());
141 m_currentEstimatedRtt = m_initialEstimatedRtt;
142 NS_LOG_DEBUG ("Initialize m_currentEstimatedRtt to " << m_currentEstimatedRtt.GetSeconds () << " sec.");
143}
144
145RttEstimator::RttEstimator (const RttEstimator& c)
146 : Object (c), m_next (c.m_next),
147 m_maxMultiplier (c.m_maxMultiplier),
148 m_initialEstimatedRtt (c.m_initialEstimatedRtt),
149 m_currentEstimatedRtt (c.m_currentEstimatedRtt), m_minRto (c.m_minRto), m_maxRto (c.m_maxRto),
150 m_nSamples (c.m_nSamples), m_multiplier (c.m_multiplier),
151 m_history (c.m_history)
152{
153 NS_LOG_FUNCTION (this);
154}
155
156RttEstimator::~RttEstimator ()
157{
158 NS_LOG_FUNCTION (this);
159}
160
Yaogong Wang87cd0652013-05-28 11:00:45 -0400161TypeId
162RttEstimator::GetInstanceTypeId (void) const
163{
164 return GetTypeId ();
165}
166
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800167void RttEstimator::SentSeq (SequenceNumber32 seq, uint32_t size)
168{
169 NS_LOG_FUNCTION (this << seq << size);
170 // Note that a particular sequence has been sent
171 if (seq == m_next)
172 { // This is the next expected one, just log at end
173 m_history.push_back (RttHistory (seq, size, Simulator::Now () ));
174 m_next = seq + SequenceNumber32 (size); // Update next expected
175 }
176 else
177 { // This is a retransmit, find in list and mark as re-tx
178 for (RttHistory_t::iterator i = m_history.begin (); i != m_history.end (); ++i)
179 {
180 if ((seq >= i->seq) && (seq < (i->seq + SequenceNumber32 (i->count))))
181 { // Found it
182 i->retx = true;
183 // One final test..be sure this re-tx does not extend "next"
184 if ((seq + SequenceNumber32 (size)) > m_next)
185 {
186 m_next = seq + SequenceNumber32 (size);
187 i->count = ((seq + SequenceNumber32 (size)) - i->seq); // And update count in hist
188 }
189 break;
190 }
191 }
192 }
193}
194
195Time RttEstimator::AckSeq (SequenceNumber32 ackSeq)
196{
197 NS_LOG_FUNCTION (this << ackSeq);
198 // An ack has been received, calculate rtt and log this measurement
199 // Note we use a linear search (O(n)) for this since for the common
200 // case the ack'ed packet will be at the head of the list
201 Time m = Seconds (0.0);
202 if (m_history.size () == 0) return (m); // No pending history, just exit
203 RttHistory& h = m_history.front ();
204 if (!h.retx && ackSeq >= (h.seq + SequenceNumber32 (h.count)))
205 { // Ok to use this sample
206 m = Simulator::Now () - h.time; // Elapsed time
207 Measurement (m); // Log the measurement
208 ResetMultiplier (); // Reset multiplier on valid measurement
209 }
210 // Now delete all ack history with seq <= ack
211 while(m_history.size () > 0)
212 {
213 RttHistory& h = m_history.front ();
214 if ((h.seq + SequenceNumber32 (h.count)) > ackSeq) break; // Done removing
215 m_history.pop_front (); // Remove
216 }
217 return m;
218}
219
220void RttEstimator::ClearSent ()
221{
222 NS_LOG_FUNCTION (this);
223 // Clear all history entries
224 m_next = 1;
225 m_history.clear ();
226}
227
228void RttEstimator::IncreaseMultiplier ()
229{
230 NS_LOG_FUNCTION (this);
231 m_multiplier = (m_multiplier*2 < m_maxMultiplier) ? m_multiplier*2 : m_maxMultiplier;
232 NS_LOG_DEBUG ("Multiplier increased to " << m_multiplier);
233}
234
235void RttEstimator::ResetMultiplier ()
236{
237 NS_LOG_FUNCTION (this);
238 m_multiplier = 1;
239}
240
241void RttEstimator::Reset ()
242{
243 NS_LOG_FUNCTION (this);
244 // Reset to initial state
245 m_next = 1;
246 m_currentEstimatedRtt = m_initialEstimatedRtt;
247 m_history.clear (); // Remove all info from the history
248 m_nSamples = 0;
249 ResetMultiplier ();
250}
251
252
253} // namespace ndn
254} // namespace ns3