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 | // (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 Afanasyev | 0c39537 | 2014-12-20 15:54:02 -0800 | [diff] [blame] | 28 | #include "ndn-rtt-mean-deviation.hpp" |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 29 | #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 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 35 | NS_LOG_COMPONENT_DEFINE("ndn.RttMeanDeviation"); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 36 | |
| 37 | namespace ns3 { |
| 38 | namespace ndn { |
| 39 | |
| 40 | //--------------------------------------------------------------------------------- |
| 41 | // A modified version of Mean-Deviation Estimator optimized for NDN packet delivery |
| 42 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 43 | NS_OBJECT_ENSURE_REGISTERED(RttMeanDeviation); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 44 | |
| 45 | TypeId |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 46 | RttMeanDeviation::GetTypeId(void) |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 47 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 48 | static TypeId tid = |
| 49 | TypeId("ns3::ndn::RttMeanDeviation") |
| 50 | .SetParent<RttEstimator>() |
| 51 | .AddConstructor<RttMeanDeviation>() |
| 52 | .AddAttribute("Gain", "Gain used in estimating the RTT (smoothed RTT), must be 0 < Gain < 1", |
| 53 | DoubleValue(0.125), MakeDoubleAccessor(&RttMeanDeviation::m_gain), |
| 54 | MakeDoubleChecker<double>()) |
| 55 | .AddAttribute("Gain2", "Gain2 used in estimating the RTT (variance), must be 0 < Gain2 < 1", |
| 56 | DoubleValue(0.25), MakeDoubleAccessor(&RttMeanDeviation::m_gain2), |
| 57 | MakeDoubleChecker<double>()); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 58 | return tid; |
| 59 | } |
| 60 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 61 | RttMeanDeviation::RttMeanDeviation() |
| 62 | : m_variance(0) |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 63 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 64 | NS_LOG_FUNCTION(this); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 65 | } |
| 66 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 67 | RttMeanDeviation::RttMeanDeviation(const RttMeanDeviation& c) |
| 68 | : RttEstimator(c) |
| 69 | , m_gain(c.m_gain) |
| 70 | , m_gain2(c.m_gain2) |
| 71 | , m_variance(c.m_variance) |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 72 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 73 | NS_LOG_FUNCTION(this); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 74 | } |
| 75 | |
Yaogong Wang | 87cd065 | 2013-05-28 11:00:45 -0400 | [diff] [blame] | 76 | TypeId |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 77 | RttMeanDeviation::GetInstanceTypeId(void) const |
Yaogong Wang | 87cd065 | 2013-05-28 11:00:45 -0400 | [diff] [blame] | 78 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 79 | return GetTypeId(); |
Yaogong Wang | 87cd065 | 2013-05-28 11:00:45 -0400 | [diff] [blame] | 80 | } |
| 81 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 82 | void |
| 83 | RttMeanDeviation::Measurement(Time m) |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 84 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 85 | NS_LOG_FUNCTION(this << m); |
| 86 | if (m_nSamples) { // Not first |
| 87 | Time err(m - m_currentEstimatedRtt); |
| 88 | double gErr = err.ToDouble(Time::S) * m_gain; |
| 89 | m_currentEstimatedRtt += Time::FromDouble(gErr, Time::S); |
| 90 | Time difference = Abs(err) - m_variance; |
| 91 | NS_LOG_DEBUG( |
| 92 | "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 { // First sample |
| 96 | m_currentEstimatedRtt = m; // Set estimate to current |
| 97 | // variance = sample / 2; // And variance to current / 2 |
| 98 | // m_variance = m; // try this why???? |
| 99 | m_variance = Seconds(m.ToDouble(Time::S) / 2); |
| 100 | NS_LOG_DEBUG("(first sample) m_variance += " << m); |
| 101 | } |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 102 | m_nSamples++; |
| 103 | } |
| 104 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 105 | Time |
| 106 | RttMeanDeviation::RetransmitTimeout() |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 107 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 108 | NS_LOG_FUNCTION(this); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 109 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 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) |
| 113 | + 4 * m_variance.ToDouble(Time::S)))); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 114 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 115 | NS_LOG_DEBUG("RetransmitTimeout: return " << retval); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 116 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 117 | return Seconds(retval); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 118 | } |
| 119 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 120 | Ptr<RttEstimator> |
| 121 | RttMeanDeviation::Copy() const |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 122 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 123 | NS_LOG_FUNCTION(this); |
| 124 | return CopyObject<RttMeanDeviation>(this); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 125 | } |
| 126 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 127 | void |
| 128 | RttMeanDeviation::Reset() |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 129 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 130 | NS_LOG_FUNCTION(this); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 131 | // Reset to initial state |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 132 | m_variance = Seconds(0); |
| 133 | RttEstimator::Reset(); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 134 | } |
| 135 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 136 | void |
| 137 | RttMeanDeviation::Gain(double g) |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 138 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 139 | NS_LOG_FUNCTION(this); |
| 140 | NS_ASSERT_MSG((g > 0) && (g < 1), |
| 141 | "RttMeanDeviation: Gain must be less than 1 and greater than 0"); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 142 | m_gain = g; |
| 143 | } |
| 144 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 145 | void |
| 146 | RttMeanDeviation::SentSeq(SequenceNumber32 seq, uint32_t size) |
| 147 | { |
| 148 | NS_LOG_FUNCTION(this << seq << size); |
Cheng Yi | 3089c47 | 2013-03-07 18:12:41 -0700 | [diff] [blame] | 149 | |
| 150 | RttHistory_t::iterator i; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 151 | for (i = m_history.begin(); i != m_history.end(); ++i) { |
| 152 | if (seq == i->seq) { // Found it |
| 153 | i->retx = true; |
| 154 | break; |
| 155 | } |
Cheng Yi | 3089c47 | 2013-03-07 18:12:41 -0700 | [diff] [blame] | 156 | } |
| 157 | |
| 158 | // Note that a particular sequence has been sent |
| 159 | if (i == m_history.end()) |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 160 | m_history.push_back(RttHistory(seq, size, Simulator::Now())); |
Cheng Yi | 3089c47 | 2013-03-07 18:12:41 -0700 | [diff] [blame] | 161 | } |
| 162 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 163 | Time |
| 164 | RttMeanDeviation::AckSeq(SequenceNumber32 ackSeq) |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 165 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 166 | NS_LOG_FUNCTION(this << ackSeq); |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 167 | // An ack has been received, calculate rtt and log this measurement |
| 168 | // Note we use a linear search (O(n)) for this since for the common |
| 169 | // 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] | 170 | Time m = Seconds(0.0); |
| 171 | if (m_history.size() == 0) |
| 172 | return (m); // No pending history, just exit |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 173 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 174 | for (RttHistory_t::iterator i = m_history.begin(); i != m_history.end(); ++i) { |
| 175 | if (ackSeq == i->seq) { // Found it |
| 176 | if (!i->retx) { |
| 177 | m = Simulator::Now() - i->time; // Elapsed time |
| 178 | Measurement(m); // Log the measurement |
| 179 | ResetMultiplier(); // Reset multiplier on valid measurement |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 180 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 181 | m_history.erase(i); |
| 182 | break; |
| 183 | } |
Alexander Afanasyev | d9a7f19 | 2013-03-07 13:58:14 -0800 | [diff] [blame] | 184 | } |
| 185 | |
| 186 | return m; |
| 187 | } |
| 188 | |
| 189 | } // namespace ndn |
| 190 | } // namespace ns3 |