blob: 376c4ab9261c02c446952e0382a0c9039a754521 [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
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080038NS_LOG_COMPONENT_DEFINE("ndn.RttEstimator");
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -080039
40namespace ns3 {
41
42namespace ndn {
43
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080044NS_OBJECT_ENSURE_REGISTERED(RttEstimator);
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -080045
46TypeId
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080047RttEstimator::GetTypeId(void)
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -080048{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080049 static TypeId tid =
50 TypeId("ns3::ndn::RttEstimator")
51 .SetParent<Object>()
52 .AddAttribute("MaxMultiplier", "Maximum RTO Multiplier", UintegerValue(64),
53 MakeUintegerAccessor(&RttEstimator::m_maxMultiplier),
54 MakeUintegerChecker<uint16_t>())
55 .AddAttribute("InitialEstimation", "Initial RTT estimation", TimeValue(Seconds(1.0)),
56 MakeTimeAccessor(&RttEstimator::m_initialEstimatedRtt), MakeTimeChecker())
57 .AddAttribute("MinRTO", "Minimum retransmit timeout value",
58 TimeValue(
59 Seconds(0.2)), // RFC2988 says min RTO=1 sec, but Linux uses 200ms. See
60 // http://www.postel.org/pipermail/end2end-interest/2004-November/004402.html
61 MakeTimeAccessor(&RttEstimator::SetMinRto, &RttEstimator::GetMinRto),
62 MakeTimeChecker())
63 .AddAttribute("MaxRTO", "Maximum retransmit timeout value", TimeValue(Seconds(200.0)),
64 MakeTimeAccessor(&RttEstimator::SetMaxRto, &RttEstimator::GetMaxRto),
65 MakeTimeChecker());
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -080066 return tid;
67}
68
69void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080070RttEstimator::SetMinRto(Time minRto)
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -080071{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080072 NS_LOG_FUNCTION(this << minRto);
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -080073 m_minRto = minRto;
74}
75Time
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080076RttEstimator::GetMinRto(void) const
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -080077{
78 return m_minRto;
79}
80
81void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080082RttEstimator::SetMaxRto(Time maxRto)
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -080083{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080084 NS_LOG_FUNCTION(this << maxRto);
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -080085 m_maxRto = maxRto;
86}
87Time
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080088RttEstimator::GetMaxRto(void) const
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -080089{
90 return m_maxRto;
91}
92
93void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080094RttEstimator::SetCurrentEstimate(Time estimate)
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -080095{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080096 NS_LOG_FUNCTION(this << estimate);
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -080097 m_currentEstimatedRtt = estimate;
98}
99Time
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800100RttEstimator::GetCurrentEstimate(void) const
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800101{
102 return m_currentEstimatedRtt;
103}
104
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800105// RttHistory methods
106RttHistory::RttHistory(SequenceNumber32 s, uint32_t c, Time t)
107 : seq(s)
108 , count(c)
109 , time(t)
110 , retx(false)
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800111{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800112 NS_LOG_FUNCTION(this);
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800113}
114
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800115RttHistory::RttHistory(const RttHistory& h)
116 : seq(h.seq)
117 , count(h.count)
118 , time(h.time)
119 , retx(h.retx)
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800120{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800121 NS_LOG_FUNCTION(this);
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800122}
123
124// Base class methods
125
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800126RttEstimator::RttEstimator()
127 : m_next(1)
128 , m_nSamples(0)
129 , m_multiplier(1)
130 , m_history()
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800131{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800132 NS_LOG_FUNCTION(this);
133 // note next=1 everywhere since first segment will have sequence 1
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800134
135 // We need attributes initialized here, not later, so use the
136 // ConstructSelf() technique documented in the manual
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800137 ObjectBase::ConstructSelf(AttributeConstructionList());
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800138 m_currentEstimatedRtt = m_initialEstimatedRtt;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800139 NS_LOG_DEBUG("Initialize m_currentEstimatedRtt to " << m_currentEstimatedRtt.GetSeconds()
140 << " sec.");
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800141}
142
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800143RttEstimator::RttEstimator(const RttEstimator& c)
144 : Object(c)
145 , m_next(c.m_next)
146 , m_maxMultiplier(c.m_maxMultiplier)
147 , m_initialEstimatedRtt(c.m_initialEstimatedRtt)
148 , m_currentEstimatedRtt(c.m_currentEstimatedRtt)
149 , m_minRto(c.m_minRto)
150 , m_maxRto(c.m_maxRto)
151 , m_nSamples(c.m_nSamples)
152 , m_multiplier(c.m_multiplier)
153 , m_history(c.m_history)
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800154{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800155 NS_LOG_FUNCTION(this);
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800156}
157
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800158RttEstimator::~RttEstimator()
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800159{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800160 NS_LOG_FUNCTION(this);
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800161}
162
Yaogong Wang87cd0652013-05-28 11:00:45 -0400163TypeId
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800164RttEstimator::GetInstanceTypeId(void) const
Yaogong Wang87cd0652013-05-28 11:00:45 -0400165{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800166 return GetTypeId();
Yaogong Wang87cd0652013-05-28 11:00:45 -0400167}
168
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800169void
170RttEstimator::SentSeq(SequenceNumber32 seq, uint32_t size)
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800171{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800172 NS_LOG_FUNCTION(this << seq << size);
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800173 // Note that a particular sequence has been sent
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800174 if (seq == m_next) { // This is the next expected one, just log at end
175 m_history.push_back(RttHistory(seq, size, Simulator::Now()));
176 m_next = seq + SequenceNumber32(size); // Update next expected
177 }
178 else { // This is a retransmit, find in list and mark as re-tx
179 for (RttHistory_t::iterator i = m_history.begin(); i != m_history.end(); ++i) {
180 if ((seq >= i->seq) && (seq < (i->seq + SequenceNumber32(i->count)))) { // Found it
181 i->retx = true;
182 // One final test..be sure this re-tx does not extend "next"
183 if ((seq + SequenceNumber32(size)) > m_next) {
184 m_next = seq + SequenceNumber32(size);
185 i->count = ((seq + SequenceNumber32(size)) - i->seq); // And update count in hist
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800186 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800187 break;
188 }
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800189 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800190 }
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800191}
192
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800193Time
194RttEstimator::AckSeq(SequenceNumber32 ackSeq)
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800195{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800196 NS_LOG_FUNCTION(this << ackSeq);
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800197 // An ack has been received, calculate rtt and log this measurement
198 // Note we use a linear search (O(n)) for this since for the common
199 // case the ack'ed packet will be at the head of the list
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800200 Time m = Seconds(0.0);
201 if (m_history.size() == 0)
202 return (m); // No pending history, just exit
203 RttHistory& h = m_history.front();
204 if (!h.retx && ackSeq >= (h.seq + SequenceNumber32(h.count))) { // Ok to use this sample
205 m = Simulator::Now() - h.time; // Elapsed time
206 Measurement(m); // Log the measurement
207 ResetMultiplier(); // Reset multiplier on valid measurement
208 }
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800209 // Now delete all ack history with seq <= ack
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800210 while (m_history.size() > 0) {
211 RttHistory& h = m_history.front();
212 if ((h.seq + SequenceNumber32(h.count)) > ackSeq)
213 break; // Done removing
214 m_history.pop_front(); // Remove
215 }
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800216 return m;
217}
218
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800219void
220RttEstimator::ClearSent()
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800221{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800222 NS_LOG_FUNCTION(this);
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800223 // Clear all history entries
224 m_next = 1;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800225 m_history.clear();
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800226}
227
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800228void
229RttEstimator::IncreaseMultiplier()
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800230{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800231 NS_LOG_FUNCTION(this);
232 m_multiplier = (m_multiplier * 2 < m_maxMultiplier) ? m_multiplier * 2 : m_maxMultiplier;
233 NS_LOG_DEBUG("Multiplier increased to " << m_multiplier);
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800234}
235
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800236void
237RttEstimator::ResetMultiplier()
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800238{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800239 NS_LOG_FUNCTION(this);
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800240 m_multiplier = 1;
241}
242
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800243void
244RttEstimator::Reset()
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800245{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800246 NS_LOG_FUNCTION(this);
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800247 // Reset to initial state
248 m_next = 1;
249 m_currentEstimatedRtt = m_initialEstimatedRtt;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800250 m_history.clear(); // Remove all info from the history
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800251 m_nSamples = 0;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800252 ResetMultiplier();
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800253}
254
Alexander Afanasyevd9a7f192013-03-07 13:58:14 -0800255} // namespace ndn
256} // namespace ns3