Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 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 | // 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 Afanasyev | 0c39537 | 2014-12-20 15:54:02 -0800 | [diff] [blame] | 31 | #include "ndn-rtt-estimator.hpp" |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 32 | #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 Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 38 | NS_LOG_COMPONENT_DEFINE("ndn.RttEstimator"); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 39 | |
| 40 | namespace ns3 { |
| 41 | |
| 42 | namespace ndn { |
| 43 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 44 | NS_OBJECT_ENSURE_REGISTERED(RttEstimator); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 45 | |
| 46 | TypeId |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 47 | RttEstimator::GetTypeId(void) |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 48 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 49 | 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 Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 66 | return tid; |
| 67 | } |
| 68 | |
| 69 | void |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 70 | RttEstimator::SetMinRto(Time minRto) |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 71 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 72 | NS_LOG_FUNCTION(this << minRto); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 73 | m_minRto = minRto; |
| 74 | } |
| 75 | Time |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 76 | RttEstimator::GetMinRto(void) const |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 77 | { |
| 78 | return m_minRto; |
| 79 | } |
| 80 | |
| 81 | void |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 82 | RttEstimator::SetMaxRto(Time maxRto) |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 83 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 84 | NS_LOG_FUNCTION(this << maxRto); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 85 | m_maxRto = maxRto; |
| 86 | } |
| 87 | Time |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 88 | RttEstimator::GetMaxRto(void) const |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 89 | { |
| 90 | return m_maxRto; |
| 91 | } |
| 92 | |
| 93 | void |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 94 | RttEstimator::SetCurrentEstimate(Time estimate) |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 95 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 96 | NS_LOG_FUNCTION(this << estimate); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 97 | m_currentEstimatedRtt = estimate; |
| 98 | } |
| 99 | Time |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 100 | RttEstimator::GetCurrentEstimate(void) const |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 101 | { |
| 102 | return m_currentEstimatedRtt; |
| 103 | } |
| 104 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 105 | // RttHistory methods |
| 106 | RttHistory::RttHistory(SequenceNumber32 s, uint32_t c, Time t) |
| 107 | : seq(s) |
| 108 | , count(c) |
| 109 | , time(t) |
| 110 | , retx(false) |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 111 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 112 | NS_LOG_FUNCTION(this); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 113 | } |
| 114 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 115 | RttHistory::RttHistory(const RttHistory& h) |
| 116 | : seq(h.seq) |
| 117 | , count(h.count) |
| 118 | , time(h.time) |
| 119 | , retx(h.retx) |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 120 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 121 | NS_LOG_FUNCTION(this); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 122 | } |
| 123 | |
| 124 | // Base class methods |
| 125 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 126 | RttEstimator::RttEstimator() |
| 127 | : m_next(1) |
| 128 | , m_nSamples(0) |
| 129 | , m_multiplier(1) |
| 130 | , m_history() |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 131 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 132 | NS_LOG_FUNCTION(this); |
| 133 | // note next=1 everywhere since first segment will have sequence 1 |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 134 | |
| 135 | // We need attributes initialized here, not later, so use the |
| 136 | // ConstructSelf() technique documented in the manual |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 137 | ObjectBase::ConstructSelf(AttributeConstructionList()); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 138 | m_currentEstimatedRtt = m_initialEstimatedRtt; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 139 | NS_LOG_DEBUG("Initialize m_currentEstimatedRtt to " << m_currentEstimatedRtt.GetSeconds() |
| 140 | << " sec."); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 141 | } |
| 142 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 143 | RttEstimator::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 Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 154 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 155 | NS_LOG_FUNCTION(this); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 156 | } |
| 157 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 158 | RttEstimator::~RttEstimator() |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 159 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 160 | NS_LOG_FUNCTION(this); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 161 | } |
| 162 | |
Yaogong Wang | 87cd065 | 2013-05-28 11:00:45 -0400 | [diff] [blame] | 163 | TypeId |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 164 | RttEstimator::GetInstanceTypeId(void) const |
Yaogong Wang | 87cd065 | 2013-05-28 11:00:45 -0400 | [diff] [blame] | 165 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 166 | return GetTypeId(); |
Yaogong Wang | 87cd065 | 2013-05-28 11:00:45 -0400 | [diff] [blame] | 167 | } |
| 168 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 169 | void |
| 170 | RttEstimator::SentSeq(SequenceNumber32 seq, uint32_t size) |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 171 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 172 | NS_LOG_FUNCTION(this << seq << size); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 173 | // Note that a particular sequence has been sent |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 174 | 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 Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 186 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 187 | break; |
| 188 | } |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 189 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 190 | } |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 191 | } |
| 192 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 193 | Time |
| 194 | RttEstimator::AckSeq(SequenceNumber32 ackSeq) |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 195 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 196 | NS_LOG_FUNCTION(this << ackSeq); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 197 | // 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 Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 200 | 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 Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 209 | // Now delete all ack history with seq <= ack |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 210 | 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 Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 216 | return m; |
| 217 | } |
| 218 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 219 | void |
| 220 | RttEstimator::ClearSent() |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 221 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 222 | NS_LOG_FUNCTION(this); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 223 | // Clear all history entries |
| 224 | m_next = 1; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 225 | m_history.clear(); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 226 | } |
| 227 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 228 | void |
| 229 | RttEstimator::IncreaseMultiplier() |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 230 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 231 | 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 Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 234 | } |
| 235 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 236 | void |
| 237 | RttEstimator::ResetMultiplier() |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 238 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 239 | NS_LOG_FUNCTION(this); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 240 | m_multiplier = 1; |
| 241 | } |
| 242 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 243 | void |
| 244 | RttEstimator::Reset() |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 245 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 246 | NS_LOG_FUNCTION(this); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 247 | // Reset to initial state |
| 248 | m_next = 1; |
| 249 | m_currentEstimatedRtt = m_initialEstimatedRtt; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 250 | m_history.clear(); // Remove all info from the history |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 251 | m_nSamples = 0; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 252 | ResetMultiplier(); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 253 | } |
| 254 | |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 255 | } // namespace ndn |
| 256 | } // namespace ns3 |