View | Details | Raw Unified | Return to bug 1405
Collapse All | Expand All

(-)a/src/internet/model/rtt-estimator.cc (-173 / +53 lines)
 Lines 45-130    Link Here 
45
{
45
{
46
  static TypeId tid = TypeId ("ns3::RttEstimator")
46
  static TypeId tid = TypeId ("ns3::RttEstimator")
47
    .SetParent<Object> ()
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", 
48
    .AddAttribute ("InitialEstimation", 
54
                   "Initial RTT estimation",
49
                   "Initial RTT estimation",
55
                   TimeValue (Seconds (1.0)),
50
                   TimeValue (Seconds (1.0)),
56
                   MakeTimeAccessor (&RttEstimator::m_initialEstimatedRtt),
51
                   MakeTimeAccessor (&RttEstimator::m_initialEstimatedRtt),
57
                   MakeTimeChecker ())
52
                   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
  ;
53
  ;
65
  return tid;
54
  return tid;
66
}
55
}
67
56
68
void 
57
Time
69
RttEstimator::SetMinRto (Time minRto)
58
RttEstimator::GetEstimate (void) const
70
{
59
{
71
  NS_LOG_FUNCTION (this << minRto);
60
  return m_estimatedRtt;
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
}
61
}
90
62
91
63
Time 
92
//RttHistory methods
64
RttEstimator::GetEstimateVariation (void) const
93
RttHistory::RttHistory (SequenceNumber32 s, uint32_t c, Time t)
94
  : seq (s), count (c), time (t), retx (false)
95
{
65
{
96
  NS_LOG_FUNCTION (this);
66
  return m_estimatedRttVariation;
97
}
67
}
98
68
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
69
105
// Base class methods
70
// Base class methods
106
71
107
RttEstimator::RttEstimator ()
72
RttEstimator::RttEstimator ()
108
  : m_next (1), m_history (),
73
  : m_nSamples (0)
109
    m_nSamples (0),
110
    m_multiplier (1)
111
{ 
74
{ 
112
  NS_LOG_FUNCTION (this);
75
  NS_LOG_FUNCTION (this);
113
  //note next=1 everywhere since first segment will have sequence 1
114
  
76
  
115
  // We need attributes initialized here, not later, so use the 
77
  // We need attributes initialized here, not later, so use the 
116
  // ConstructSelf() technique documented in the manual
78
  // ConstructSelf() technique documented in the manual
117
  ObjectBase::ConstructSelf (AttributeConstructionList ());
79
  ObjectBase::ConstructSelf (AttributeConstructionList ());
118
  m_currentEstimatedRtt = m_initialEstimatedRtt;
80
  m_estimatedRtt = m_initialEstimatedRtt;
119
  NS_LOG_DEBUG ("Initialize m_currentEstimatedRtt to " << m_currentEstimatedRtt.GetSeconds () << " sec.");
81
  NS_LOG_DEBUG ("Initialize m_estimatedRtt to " << m_estimatedRtt.GetSeconds () << " sec.");
120
}
82
}
121
83
122
RttEstimator::RttEstimator (const RttEstimator& c)
84
RttEstimator::RttEstimator (const RttEstimator& c)
123
  : Object (c), m_next (c.m_next), m_history (c.m_history), 
85
  : Object (c),
124
    m_maxMultiplier (c.m_maxMultiplier), 
125
    m_initialEstimatedRtt (c.m_initialEstimatedRtt),
86
    m_initialEstimatedRtt (c.m_initialEstimatedRtt),
126
    m_currentEstimatedRtt (c.m_currentEstimatedRtt), m_minRto (c.m_minRto),
87
    m_estimatedRtt (c.m_estimatedRtt),
127
    m_nSamples (c.m_nSamples), m_multiplier (c.m_multiplier)
88
    m_estimatedRttVariation (c.m_estimatedRttVariation),
89
    m_nSamples (c.m_nSamples)
128
{
90
{
129
  NS_LOG_FUNCTION (this);
91
  NS_LOG_FUNCTION (this);
130
}
92
}
 Lines 140-232    Link Here 
140
  return GetTypeId ();
102
  return GetTypeId ();
141
}
103
}
142
104
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::EstimateRttFromSeq (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 ()
105
void RttEstimator::Reset ()
218
{ 
106
{ 
219
  NS_LOG_FUNCTION (this);
107
  NS_LOG_FUNCTION (this);
220
  // Reset to initial state
108
  // Reset to initial state
221
  m_next = 1;
109
  m_estimatedRtt = m_initialEstimatedRtt;
222
  m_currentEstimatedRtt = m_initialEstimatedRtt;
110
  m_estimatedRttVariation = Time (0);
223
  m_history.clear ();         // Remove all info from the history
224
  m_nSamples = 0;
111
  m_nSamples = 0;
225
  ResetMultiplier ();
226
}
112
}
227
113
228
229
230
//-----------------------------------------------------------------------------
114
//-----------------------------------------------------------------------------
231
//-----------------------------------------------------------------------------
115
//-----------------------------------------------------------------------------
232
// Mean-Deviation Estimator
116
// Mean-Deviation Estimator
 Lines 239-261    Link Here 
239
  static TypeId tid = TypeId ("ns3::RttMeanDeviation")
123
  static TypeId tid = TypeId ("ns3::RttMeanDeviation")
240
    .SetParent<RttEstimator> ()
124
    .SetParent<RttEstimator> ()
241
    .AddConstructor<RttMeanDeviation> ()
125
    .AddConstructor<RttMeanDeviation> ()
242
    .AddAttribute ("Gain",
126
    .AddAttribute ("Alpha",
243
                   "Gain used in estimating the RTT, must be 0 < Gain < 1",
127
                   "Gain used in estimating the RTT, must be 0 < alpha < 1",
244
                   DoubleValue (0.1),
128
                   DoubleValue (0.125),
245
                   MakeDoubleAccessor (&RttMeanDeviation::m_gain),
129
                   MakeDoubleAccessor (&RttMeanDeviation::m_alpha),
130
                   MakeDoubleChecker<double> ())
131
    .AddAttribute ("Beta",
132
                   "Gain used in estimating the RTT variance, must be 0 < beta < 1",
133
                   DoubleValue (0.25),
134
                   MakeDoubleAccessor (&RttMeanDeviation::m_beta),
246
                   MakeDoubleChecker<double> ())
135
                   MakeDoubleChecker<double> ())
247
  ;
136
  ;
248
  return tid;
137
  return tid;
249
}
138
}
250
139
251
RttMeanDeviation::RttMeanDeviation() :
140
RttMeanDeviation::RttMeanDeviation()
252
  m_variance (0) 
141
{
253
{ 
254
  NS_LOG_FUNCTION (this);
142
  NS_LOG_FUNCTION (this);
255
}
143
}
256
144
257
RttMeanDeviation::RttMeanDeviation (const RttMeanDeviation& c)
145
RttMeanDeviation::RttMeanDeviation (const RttMeanDeviation& c)
258
  : RttEstimator (c), m_gain (c.m_gain), m_variance (c.m_variance)
146
  : RttEstimator (c), m_alpha (c.m_alpha), m_beta (c.m_beta)
259
{
147
{
260
  NS_LOG_FUNCTION (this);
148
  NS_LOG_FUNCTION (this);
261
}
149
}
 Lines 270-308    Link Here 
270
{
158
{
271
  NS_LOG_FUNCTION (this << m);
159
  NS_LOG_FUNCTION (this << m);
272
  if (m_nSamples)
160
  if (m_nSamples)
273
    { // Not first
161
    { // Not first sample
274
      Time err (m - m_currentEstimatedRtt);
162
      Time err (m - m_estimatedRtt);
275
      double gErr = err.ToDouble (Time::S) * m_gain;
163
      double gErr = err.ToDouble (Time::S) * m_alpha;
276
      m_currentEstimatedRtt += Time::FromDouble (gErr, Time::S);
164
      m_estimatedRtt += Time::FromDouble (gErr, Time::S);
277
      Time difference = Abs (err) - m_variance;
165
278
      NS_LOG_DEBUG ("m_variance += " << Time::FromDouble (difference.ToDouble (Time::S) * m_gain, Time::S));
166
      Time difference = Abs (err) - m_estimatedRttVariation;
279
      m_variance += Time::FromDouble (difference.ToDouble (Time::S) * m_gain, Time::S);
167
      NS_LOG_DEBUG ("m_estimatedRttVariation += " << Time::FromDouble (difference.ToDouble (Time::S) * m_beta, Time::S));
168
      m_estimatedRttVariation += Time::FromDouble (difference.ToDouble (Time::S) * m_beta, Time::S);
280
    }
169
    }
281
  else
170
  else
282
    { // First sample
171
    { // First sample
283
      m_currentEstimatedRtt = m;             // Set estimate to current
172
      m_estimatedRtt = m;               // Set estimate to current
284
      //variance = sample / 2;               // And variance to current / 2
173
      m_estimatedRttVariation = m / 2;  // And variation to current / 2
285
      m_variance = m; // try this
174
      NS_LOG_DEBUG ("(first sample) m_estimatedRttVariation += " << m);
286
      NS_LOG_DEBUG ("(first sample) m_variance += " << m);
287
    }
175
    }
288
  m_nSamples++;
176
  m_nSamples++;
289
}
177
}
290
178
291
Time RttMeanDeviation::RetransmitTimeout ()
179
//Time RttMeanDeviation::RetransmitTimeout ()
292
{
180
//{
293
  NS_LOG_FUNCTION (this);
181
//  NS_LOG_FUNCTION (this);
294
  NS_LOG_DEBUG ("RetransmitTimeout:  var " << m_variance.GetSeconds () << " est " << m_currentEstimatedRtt.GetSeconds () << " multiplier " << m_multiplier);
182
//  NS_LOG_DEBUG ("RetransmitTimeout:  var " << m_variance.GetSeconds () << " est " << m_currentEstimatedRtt.GetSeconds () << " multiplier " << m_multiplier);
295
  // RTO = srtt + 4* rttvar
183
//  // RTO = srtt + 4* rttvar
296
  int64_t temp = m_currentEstimatedRtt.ToInteger (Time::MS) + 4 * m_variance.ToInteger (Time::MS);
184
//  int64_t temp = m_currentEstimatedRtt.ToInteger (Time::MS) + 4 * m_variance.ToInteger (Time::MS);
297
  if (temp < m_minRto.ToInteger (Time::MS))
185
//  if (temp < m_minRto.ToInteger (Time::MS))
298
    {
186
//    {
299
      temp = m_minRto.ToInteger (Time::MS);
187
//      temp = m_minRto.ToInteger (Time::MS);
300
    } 
188
//    }
301
  temp = temp * m_multiplier; // Apply backoff
189
//  temp = temp * m_multiplier; // Apply backoff
302
  Time retval = Time::FromInteger (temp, Time::MS);
190
//  Time retval = Time::FromInteger (temp, Time::MS);
303
  NS_LOG_DEBUG ("RetransmitTimeout:  return " << retval.GetSeconds ());
191
//  NS_LOG_DEBUG ("RetransmitTimeout:  return " << retval.GetSeconds ());
304
  return (retval);  
192
//  return (retval);
305
}
193
//}
306
194
307
Ptr<RttEstimator> RttMeanDeviation::Copy () const
195
Ptr<RttEstimator> RttMeanDeviation::Copy () const
308
{
196
{
 Lines 313-327    Link Here 
313
void RttMeanDeviation::Reset ()
201
void RttMeanDeviation::Reset ()
314
{ 
202
{ 
315
  NS_LOG_FUNCTION (this);
203
  NS_LOG_FUNCTION (this);
316
  // Reset to initial state
317
  m_variance = Seconds (0);
318
  RttEstimator::Reset ();
204
  RttEstimator::Reset ();
319
}
205
}
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
206
327
} //namespace ns3
207
} //namespace ns3
(-)a/src/internet/model/rtt-estimator.h (-101 / +12 lines)
 Lines 32-65    Link Here 
32
32
33
namespace ns3 {
33
namespace ns3 {
34
34
35
/**
35
class Packet;
36
 * \ingroup tcp
36
class TcpHeader;
37
 *
38
 * \brief Helper class to store RTT measurements
39
 */
40
class RttHistory {
41
public:
42
  /**
43
   * \brief Constructor - builds an RttHistory with the given parameters
44
   * \param s First sequence number in packet sent
45
   * \param c Number of bytes sent
46
   * \param t Time this one was sent
47
   */
48
  RttHistory (SequenceNumber32 s, uint32_t c, Time t);
49
  /**
50
   * \brief Copy constructor
51
   * \param h the object to copy
52
   */
53
  RttHistory (const RttHistory& h); // Copy constructor
54
public:
55
  SequenceNumber32  seq;  //!< First sequence number in packet sent
56
  uint32_t        count;  //!< Number of bytes sent
57
  Time            time;   //!< Time this one was sent
58
  bool            retx;   //!< True if this has been retransmitted
59
};
60
61
/// Container for RttHistory objects
62
typedef std::deque<RttHistory> RttHistory_t;
63
37
64
/**
38
/**
65
 * \ingroup tcp
39
 * \ingroup tcp
 Lines 86-177    Link Here 
86
  virtual TypeId GetInstanceTypeId (void) const;
60
  virtual TypeId GetInstanceTypeId (void) const;
87
61
88
  /**
62
  /**
89
   * \brief Note that a particular sequence has been sent
90
   * \param seq the packet sequence number.
91
   * \param size the packet size.
92
   */
93
  virtual void SentSeq (SequenceNumber32 seq, uint32_t size);
94
95
  /**
96
   * \brief Note that a particular ack sequence has been received
97
   * \param ackSeq the ack sequence number.
98
   * \return The measured RTT for this ack.
99
   */
100
  virtual Time EstimateRttFromSeq (SequenceNumber32 ackSeq);
101
102
  /**
103
   * \brief Clear all history entries
104
   */
105
  virtual void ClearSent ();
106
107
  /**
108
   * \brief Add a new measurement to the estimator. Pure virtual function.
63
   * \brief Add a new measurement to the estimator. Pure virtual function.
109
   * \param t the new RTT measure.
64
   * \param t the new RTT measure.
110
   */
65
   */
111
  virtual void  Measurement (Time t) = 0;
66
  virtual void  Measurement (Time t) = 0;
112
67
113
  /**
68
  /**
114
   * \brief Returns the estimated RTO. Pure virtual function.
115
   * \return the estimated RTO.
116
   */
117
  virtual Time RetransmitTimeout () = 0;
118
119
  /**
120
   * \brief Copy object
69
   * \brief Copy object
121
   * \returns a copy of itself
70
   * \returns a copy of itself
122
   */
71
   */
123
  virtual Ptr<RttEstimator> Copy () const = 0;
72
  virtual Ptr<RttEstimator> Copy () const = 0;
124
73
125
  /**
74
  /**
126
   * \brief Increase the estimation multiplier up to MaxMultiplier.
127
   */
128
  virtual void IncreaseMultiplier ();
129
130
  /**
131
   * \brief Resets the estimation multiplier to 1.
132
   */
133
  virtual void ResetMultiplier ();
134
135
  /**
136
   * \brief Resets the estimation to its initial state.
75
   * \brief Resets the estimation to its initial state.
137
   */
76
   */
138
  virtual void Reset ();
77
  virtual void Reset ();
139
78
140
  /**
79
  /**
141
   * \brief Sets the Minimum RTO.
80
   * \brief gets the RTT estimate.
142
   * \param minRto The minimum RTO returned by the estimator.
81
   * \return The RTT estimate.
143
   */
82
   */
144
  void SetMinRto (Time minRto);
83
  Time GetEstimate (void) const;
145
84
146
  /**
85
  /**
147
   * \brief Get the Minimum RTO.
86
   * \brief gets the RTT estimate variation.
148
   * \return The minimum RTO returned by the estimator.
87
   * \return The RTT estimate variation.
149
   */
88
   */
150
  Time GetMinRto (void) const;
89
  Time GetEstimateVariation (void) const;
151
152
  /**
153
   * \brief Sets the current RTT estimate (forcefully).
154
   * \param estimate The current RTT estimate.
155
   */
156
  void SetCurrentEstimate (Time estimate);
157
158
  /**
159
   * \brief gets the current RTT estimate.
160
   * \return The current RTT estimate.
161
   */
162
  Time GetCurrentEstimate (void) const;
163
90
164
private:
91
private:
165
  SequenceNumber32 m_next;    //!< Next expected sequence to be sent
166
  RttHistory_t m_history;     //!< List of sent packet
167
  uint16_t m_maxMultiplier;   //!< Maximum RTO Multiplier
168
  Time m_initialEstimatedRtt; //!< Initial RTT estimation
92
  Time m_initialEstimatedRtt; //!< Initial RTT estimation
169
93
170
protected:
94
protected:
171
  Time         m_currentEstimatedRtt;     //!< Current estimate
95
  Time         m_estimatedRtt;            //!< Current estimate
172
  Time         m_minRto;                  //!< minimum value of the timeout
96
  Time         m_estimatedRttVariation;   //!< Current estimate variation
173
  uint32_t     m_nSamples;                //!< Number of samples
97
  uint32_t     m_nSamples;                //!< Number of samples
174
  uint16_t     m_multiplier;              //!< RTO Multiplier
175
};
98
};
176
99
177
/**
100
/**
 Lines 208-219    Link Here 
208
   */
131
   */
209
  void Measurement (Time measure);
132
  void Measurement (Time measure);
210
133
211
  /**
212
   * \brief Returns the estimated RTO.
213
   * \return the estimated RTO.
214
   */
215
  Time RetransmitTimeout ();
216
217
  Ptr<RttEstimator> Copy () const;
134
  Ptr<RttEstimator> Copy () const;
218
135
219
  /**
136
  /**
 Lines 221-235    Link Here 
221
   */
138
   */
222
  void Reset ();
139
  void Reset ();
223
140
224
  /**
225
   * \brief Sets the estimator Gain.
226
   * \param g the gain, where 0 < g < 1.
227
   */
228
  void Gain (double g);
229
230
private:
141
private:
231
  double       m_gain;       //!< Filter gain
142
  double       m_alpha;       //!< Filter gain for average
232
  Time         m_variance;   //!< Current variance
143
  double       m_beta;        //!< Filter gain for variance
233
};
144
};
234
} // namespace ns3
145
} // namespace ns3
235
146
(-)a/src/internet/model/tcp-newreno.cc (-1 lines)
 Lines 213-219    Link Here 
213
  m_nextTxSequence = m_txBuffer.HeadSequence (); // Restart from highest Ack
213
  m_nextTxSequence = m_txBuffer.HeadSequence (); // Restart from highest Ack
214
  NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd <<
214
  NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd <<
215
               ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence);
215
               ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence);
216
  m_rtt->IncreaseMultiplier ();             // Double the next RTO
217
  DoRetransmit ();                          // Retransmit the packet
216
  DoRetransmit ();                          // Retransmit the packet
218
}
217
}
219
218
(-)a/src/internet/model/tcp-reno.cc (-1 lines)
 Lines 188-194    Link Here 
188
  m_nextTxSequence = m_txBuffer.HeadSequence (); // Restart from highest Ack
188
  m_nextTxSequence = m_txBuffer.HeadSequence (); // Restart from highest Ack
189
  NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd <<
189
  NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd <<
190
               ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence);
190
               ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence);
191
  m_rtt->IncreaseMultiplier ();             // Double the next RTO
192
  DoRetransmit ();                          // Retransmit the packet
191
  DoRetransmit ();                          // Retransmit the packet
193
}
192
}
194
193
(-)a/src/internet/model/tcp-socket-base.cc (-32 / +133 lines)
 Lines 94-99    Link Here 
94
                   BooleanValue (true),
94
                   BooleanValue (true),
95
                   MakeBooleanAccessor (&TcpSocketBase::m_timestampEnabled),
95
                   MakeBooleanAccessor (&TcpSocketBase::m_timestampEnabled),
96
                   MakeBooleanChecker ())
96
                   MakeBooleanChecker ())
97
    .AddAttribute ("MinRto",
98
                   "Minimum retransmit timeout value",
99
                   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
100
                   MakeTimeAccessor (&TcpSocketBase::SetMinRto,
101
                                     &TcpSocketBase::GetMinRto),
102
                                     MakeTimeChecker ())
103
    .AddAttribute ("ClockGranularity",
104
                   "Clock Granularity used in RTO calculations",
105
                   TimeValue (MilliSeconds (1)), // RFC6298 suggest to use fine clock granularity
106
                   MakeTimeAccessor (&TcpSocketBase::SetClockGranularity,
107
                                     &TcpSocketBase::GetClockGranularity),
108
                                     MakeTimeChecker ())
97
    .AddTraceSource ("RTO",
109
    .AddTraceSource ("RTO",
98
                     "Retransmission timeout",
110
                     "Retransmission timeout",
99
                     MakeTraceSourceAccessor (&TcpSocketBase::m_rto),
111
                     MakeTraceSourceAccessor (&TcpSocketBase::m_rto),
 Lines 148-155    Link Here 
148
    m_sndScaleFactor (0),
160
    m_sndScaleFactor (0),
149
    m_rcvScaleFactor (0),
161
    m_rcvScaleFactor (0),
150
    m_timestampEnabled (true),
162
    m_timestampEnabled (true),
151
    m_timestampToEcho (0),
163
    m_timestampToEcho (0)
152
    m_lastEchoedTime (0)
153
164
154
{
165
{
155
  NS_LOG_FUNCTION (this);
166
  NS_LOG_FUNCTION (this);
 Lines 190-197    Link Here 
190
    m_sndScaleFactor (sock.m_sndScaleFactor),
201
    m_sndScaleFactor (sock.m_sndScaleFactor),
191
    m_rcvScaleFactor (sock.m_rcvScaleFactor),
202
    m_rcvScaleFactor (sock.m_rcvScaleFactor),
192
    m_timestampEnabled (sock.m_timestampEnabled),
203
    m_timestampEnabled (sock.m_timestampEnabled),
193
    m_timestampToEcho (sock.m_timestampToEcho),
204
    m_timestampToEcho (sock.m_timestampToEcho)
194
    m_lastEchoedTime (sock.m_lastEchoedTime)
195
205
196
{
206
{
197
  NS_LOG_FUNCTION (this);
207
  NS_LOG_FUNCTION (this);
 Lines 1568-1575    Link Here 
1568
  if (m_state == LAST_ACK)
1578
  if (m_state == LAST_ACK)
1569
    {
1579
    {
1570
      NS_LOG_LOGIC ("TcpSocketBase " << this << " scheduling LATO1");
1580
      NS_LOG_LOGIC ("TcpSocketBase " << this << " scheduling LATO1");
1571
      m_lastAckEvent = Simulator::Schedule (m_rtt->RetransmitTimeout (),
1581
      Time lastRto = m_rtt->GetEstimate () + std::max (m_clockGranularity, m_rtt->GetEstimateVariation ()*4);
1572
                                            &TcpSocketBase::LastAckTimeout, this);
1582
      m_lastAckEvent = Simulator::Schedule (lastRto, &TcpSocketBase::LastAckTimeout, this);
1573
    }
1583
    }
1574
}
1584
}
1575
1585
 Lines 1687-1693    Link Here 
1687
    }
1697
    }
1688
  AddOptions (header);
1698
  AddOptions (header);
1689
  header.SetWindowSize (AdvertisedWindowSize ());
1699
  header.SetWindowSize (AdvertisedWindowSize ());
1690
  m_rto = m_rtt->RetransmitTimeout ();
1700
1701
  // RFC 6298, clause 2.4
1702
  m_rto = std::max (m_rtt->GetEstimate () + std::max (m_clockGranularity, m_rtt->GetEstimateVariation ()*4), Time::FromDouble (1,  Time::S));
1703
1691
  bool hasSyn = flags & TcpHeader::SYN;
1704
  bool hasSyn = flags & TcpHeader::SYN;
1692
  bool hasFin = flags & TcpHeader::FIN;
1705
  bool hasFin = flags & TcpHeader::FIN;
1693
  bool isAck = flags == TcpHeader::ACK;
1706
  bool isAck = flags == TcpHeader::ACK;
 Lines 1696-1701    Link Here 
1696
      if (m_cnCount == 0)
1709
      if (m_cnCount == 0)
1697
        { // No more connection retries, give up
1710
        { // No more connection retries, give up
1698
          NS_LOG_LOGIC ("Connection failed.");
1711
          NS_LOG_LOGIC ("Connection failed.");
1712
          m_rtt->Reset (); //According to recommendation -> RFC 6298
1699
          CloseAndNotify ();
1713
          CloseAndNotify ();
1700
          return;
1714
          return;
1701
        }
1715
        }
 Lines 1891-1896    Link Here 
1891
{
1905
{
1892
  NS_LOG_FUNCTION (this << seq << maxSize << withAck);
1906
  NS_LOG_FUNCTION (this << seq << maxSize << withAck);
1893
1907
1908
  bool isRetransmission = false;
1909
  if ( seq == m_txBuffer.HeadSequence () )
1910
    {
1911
      isRetransmission = true;
1912
    }
1913
1894
  Ptr<Packet> p = m_txBuffer.CopyFromSequence (maxSize, seq);
1914
  Ptr<Packet> p = m_txBuffer.CopyFromSequence (maxSize, seq);
1895
  uint32_t sz = p->GetSize (); // Size of packet
1915
  uint32_t sz = p->GetSize (); // Size of packet
1896
  uint8_t flags = withAck ? TcpHeader::ACK : 0;
1916
  uint8_t flags = withAck ? TcpHeader::ACK : 0;
 Lines 1960-1968    Link Here 
1960
    }
1980
    }
1961
  header.SetWindowSize (AdvertisedWindowSize ());
1981
  header.SetWindowSize (AdvertisedWindowSize ());
1962
  AddOptions (header);
1982
  AddOptions (header);
1983
1963
  if (m_retxEvent.IsExpired () )
1984
  if (m_retxEvent.IsExpired () )
1964
    { // Schedule retransmit
1985
    {
1965
      m_rto = m_rtt->RetransmitTimeout ();
1986
      // RFC 6298, clause 2.5
1987
      Time doubledRto = 2 * m_rto;
1988
      m_rto = std::min (doubledRto, Time::FromDouble (60,  Time::S));
1989
1990
      // Schedules retransmit
1991
1966
      NS_LOG_LOGIC (this << " SendDataPacket Schedule ReTxTimeout at time " <<
1992
      NS_LOG_LOGIC (this << " SendDataPacket Schedule ReTxTimeout at time " <<
1967
                    Simulator::Now ().GetSeconds () << " to expire at time " <<
1993
                    Simulator::Now ().GetSeconds () << " to expire at time " <<
1968
                    (Simulator::Now () + m_rto.Get ()).GetSeconds () );
1994
                    (Simulator::Now () + m_rto.Get ()).GetSeconds () );
 Lines 1979-1985    Link Here 
1979
      m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
2005
      m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
1980
                         m_endPoint6->GetPeerAddress (), m_boundnetdevice);
2006
                         m_endPoint6->GetPeerAddress (), m_boundnetdevice);
1981
    }
2007
    }
1982
  m_rtt->SentSeq (seq, sz);       // notify the RTT
2008
2009
  // update the history of sequence numbers used to calculate the RTT
2010
  if (isRetransmission == false)
2011
    { // This is the next expected one, just log at end
2012
      m_history.push_back (RttHistory (seq, sz, Simulator::Now () ));
2013
    }
2014
  else
2015
    { // This is a retransmit, find in list and mark as re-tx
2016
      for (RttHistory_t::iterator i = m_history.begin (); i != m_history.end (); ++i)
2017
        {
2018
          if ((seq >= i->seq) && (seq < (i->seq + SequenceNumber32 (i->count))))
2019
            { // Found it
2020
              i->retx = true;
2021
              i->count = ((seq + SequenceNumber32 (sz)) - i->seq); // And update count in hist
2022
              break;
2023
            }
2024
        }
2025
    }
2026
1983
  // Notify the application of the data being sent unless this is a retransmit
2027
  // Notify the application of the data being sent unless this is a retransmit
1984
  if (seq == m_nextTxSequence)
2028
  if (seq == m_nextTxSequence)
1985
    {
2029
    {
 Lines 2155-2181    Link Here 
2155
void
2199
void
2156
TcpSocketBase::EstimateRtt (const TcpHeader& tcpHeader)
2200
TcpSocketBase::EstimateRtt (const TcpHeader& tcpHeader)
2157
{
2201
{
2158
  Time nextRtt;
2202
  SequenceNumber32 ackSeq = tcpHeader.GetAckNumber();
2203
  Time m = Time (0.0);
2159
2204
2160
  if (m_timestampEnabled)
2205
  // An ack has been received, calculate rtt and log this measurement
2206
  // Note we use a linear search (O(n)) for this since for the common
2207
  // case the ack'ed packet will be at the head of the list
2208
  if (!m_history.empty ())
2161
    {
2209
    {
2162
      nextRtt = TcpOptionTS::ElapsedTimeFromTsValue (m_lastEchoedTime);
2210
      RttHistory& h = m_history.front ();
2163
    }
2211
      if (!h.retx && ackSeq >= (h.seq + SequenceNumber32 (h.count)))
2164
  else
2212
        { // Ok to use this sample
2165
    {
2213
          if (m_timestampEnabled && tcpHeader.HasOption (TcpOption::TS))
2166
      // Use m_rtt for the estimation. Note, RTT of duplicated acknowledgement
2214
            {
2167
      // (which should be ignored) is handled by m_rtt.
2215
              Ptr<TcpOptionTS> ts;
2168
      nextRtt =  m_rtt->EstimateRttFromSeq (tcpHeader.GetAckNumber () );
2216
              ts = DynamicCast<TcpOptionTS> (tcpHeader.GetOption (TcpOption::TS));
2217
              m = TcpOptionTS::ElapsedTimeFromTsValue (ts->GetEcho ());
2218
            }
2219
          else
2220
            {
2221
              m = Simulator::Now () - h.time; // Elapsed time
2222
            }
2223
        }
2169
    }
2224
    }
2170
2225
2171
  //nextRtt will be zero for dup acks.  Don't want to update lastRtt in that case
2226
  // Now delete all ack history with seq <= ack
2172
  //but still needed to do list clearing that is done in EstimateRttFromSeq.
2227
  while(!m_history.empty ())
2173
  if(nextRtt != Time (0))
2228
    {
2174
  {
2229
      RttHistory& h = m_history.front ();
2175
    m_lastRtt = nextRtt;
2230
      if ((h.seq + SequenceNumber32 (h.count)) > ackSeq) break;               // Done removing
2176
    NS_LOG_FUNCTION(this << m_lastRtt);
2231
      m_history.pop_front (); // Remove
2177
  }
2232
    }
2178
  
2233
2234
  if (!m.IsZero ())
2235
    {
2236
      m_rtt->Measurement (m);                // Log the measurement
2237
      // RFC 6298, clause 2.4
2238
      m_rto = std::max (m_rtt->GetEstimate () + std::max (m_clockGranularity, m_rtt->GetEstimateVariation ()*4), Time::FromDouble (1,  Time::S));
2239
      m_lastRtt = m_rtt->GetEstimate ();
2240
      NS_LOG_FUNCTION(this << m_lastRtt);
2241
    }
2179
}
2242
}
2180
2243
2181
// Called by the ReceivedAck() when new ACK received and by ProcessSynRcvd()
2244
// Called by the ReceivedAck() when new ACK received and by ProcessSynRcvd()
 Lines 2191-2198    Link Here 
2191
      NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2254
      NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2192
                    (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2255
                    (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2193
      m_retxEvent.Cancel ();
2256
      m_retxEvent.Cancel ();
2194
      // On recieving a "New" ack we restart retransmission timer .. RFC 2988
2257
      // On receiving a "New" ack we restart retransmission timer .. RFC 6298
2195
      m_rto = m_rtt->RetransmitTimeout ();
2258
      // RFC 6298, clause 2.4
2259
      m_rto = std::max (m_rtt->GetEstimate () + std::max (m_clockGranularity, m_rtt->GetEstimateVariation ()*4), Time::FromDouble (1,  Time::S));
2260
2196
      NS_LOG_LOGIC (this << " Schedule ReTxTimeout at time " <<
2261
      NS_LOG_LOGIC (this << " Schedule ReTxTimeout at time " <<
2197
                    Simulator::Now ().GetSeconds () << " to expire at time " <<
2262
                    Simulator::Now ().GetSeconds () << " to expire at time " <<
2198
                    (Simulator::Now () + m_rto.Get ()).GetSeconds ());
2263
                    (Simulator::Now () + m_rto.Get ()).GetSeconds ());
 Lines 2320-2326    Link Here 
2320
TcpSocketBase::Retransmit ()
2385
TcpSocketBase::Retransmit ()
2321
{
2386
{
2322
  m_nextTxSequence = m_txBuffer.HeadSequence (); // Start from highest Ack
2387
  m_nextTxSequence = m_txBuffer.HeadSequence (); // Start from highest Ack
2323
  m_rtt->IncreaseMultiplier (); // Double the timeout value for next retx timer
2324
  m_dupAckCount = 0;
2388
  m_dupAckCount = 0;
2325
  DoRetransmit (); // Retransmit the packet
2389
  DoRetransmit (); // Retransmit the packet
2326
}
2390
}
 Lines 2526-2531    Link Here 
2526
    }
2590
    }
2527
2591
2528
  m_timestampEnabled = false;
2592
  m_timestampEnabled = false;
2593
2529
  if (header.HasOption (TcpOption::TS))
2594
  if (header.HasOption (TcpOption::TS))
2530
    {
2595
    {
2531
      m_timestampEnabled = true;
2596
      m_timestampEnabled = true;
 Lines 2622-2631    Link Here 
2622
2687
2623
  Ptr<const TcpOptionTS> ts = DynamicCast<const TcpOptionTS> (option);
2688
  Ptr<const TcpOptionTS> ts = DynamicCast<const TcpOptionTS> (option);
2624
  m_timestampToEcho = ts->GetTimestamp ();
2689
  m_timestampToEcho = ts->GetTimestamp ();
2625
  m_lastEchoedTime = ts->GetEcho ();
2626
2690
2627
  NS_LOG_INFO (m_node->GetId () << " Got timestamp=" <<
2691
  NS_LOG_INFO (m_node->GetId () << " Got timestamp=" <<
2628
               m_timestampToEcho << " and Echo="     << m_lastEchoedTime);
2692
               m_timestampToEcho << " and Echo="     << ts->GetEcho ());
2629
}
2693
}
2630
2694
2631
void
2695
void
 Lines 2643-2646    Link Here 
2643
               option->GetTimestamp () << " echo=" << m_timestampToEcho);
2707
               option->GetTimestamp () << " echo=" << m_timestampToEcho);
2644
}
2708
}
2645
2709
2710
void
2711
TcpSocketBase::SetMinRto (Time minRto)
2712
{
2713
  NS_LOG_FUNCTION (this << minRto);
2714
  m_minRto = minRto;
2715
}
2716
2717
Time
2718
TcpSocketBase::GetMinRto (void) const
2719
{
2720
  return m_minRto;
2721
}
2722
2723
void
2724
TcpSocketBase::SetClockGranularity (Time clockGranularity)
2725
{
2726
  NS_LOG_FUNCTION (this << clockGranularity);
2727
  m_clockGranularity = clockGranularity;
2728
}
2729
2730
Time
2731
TcpSocketBase::GetClockGranularity (void) const
2732
{
2733
  return m_clockGranularity;
2734
}
2735
2736
//RttHistory methods
2737
RttHistory::RttHistory (SequenceNumber32 s, uint32_t c, Time t)
2738
  : seq (s), count (c), time (t), retx (false)
2739
{
2740
}
2741
2742
RttHistory::RttHistory (const RttHistory& h)
2743
  : seq (h.seq), count (h.count), time (h.time), retx (h.retx)
2744
{
2745
}
2746
2646
} // namespace ns3
2747
} // namespace ns3
(-)a/src/internet/model/tcp-socket-base.h (-1 / +57 lines)
 Lines 47-52    Link Here 
47
class TcpHeader;
47
class TcpHeader;
48
48
49
/**
49
/**
50
 * \ingroup tcp
51
 *
52
 * \brief Helper class to store RTT measurements
53
 */
54
class RttHistory {
55
public:
56
  /**
57
   * \brief Constructor - builds an RttHistory with the given parameters
58
   * \param s First sequence number in packet sent
59
   * \param c Number of bytes sent
60
   * \param t Time this one was sent
61
   */
62
  RttHistory (SequenceNumber32 s, uint32_t c, Time t);
63
  /**
64
   * \brief Copy constructor
65
   * \param h the object to copy
66
   */
67
  RttHistory (const RttHistory& h); // Copy constructor
68
public:
69
  SequenceNumber32  seq;  //!< First sequence number in packet sent
70
  uint32_t        count;  //!< Number of bytes sent
71
  Time            time;   //!< Time this one was sent
72
  bool            retx;   //!< True if this has been retransmitted
73
};
74
75
/// Container for RttHistory objects
76
typedef std::deque<RttHistory> RttHistory_t;
77
78
/**
50
 * \ingroup socket
79
 * \ingroup socket
51
 * \ingroup tcp
80
 * \ingroup tcp
52
 *
81
 *
 Lines 101-106    Link Here 
101
   */
130
   */
102
  virtual void SetRtt (Ptr<RttEstimator> rtt);
131
  virtual void SetRtt (Ptr<RttEstimator> rtt);
103
132
133
  /**
134
   * \brief Sets the Minimum RTO.
135
   * \param minRto The minimum RTO.
136
   */
137
  void SetMinRto (Time minRto);
138
139
  /**
140
   * \brief Get the Minimum RTO.
141
   * \return The minimum RTO.
142
   */
143
  Time GetMinRto (void) const;
144
145
  /**
146
   * \brief Sets the Clock Granularity (used in RTO calcs).
147
   * \param clockGranularity The Clock Granularity
148
   */
149
  void SetClockGranularity (Time clockGranularity);
150
151
  /**
152
   * \brief Get the Clock Granularity (used in RTO calcs).
153
   * \return The Clock Granularity.
154
   */
155
  Time GetClockGranularity (void) const;
156
157
104
  // Necessary implementations of null functions from ns3::Socket
158
  // Necessary implementations of null functions from ns3::Socket
105
  virtual enum SocketErrno GetErrno (void) const;    // returns m_errno
159
  virtual enum SocketErrno GetErrno (void) const;    // returns m_errno
106
  virtual enum SocketType GetSocketType (void) const; // returns socket type
160
  virtual enum SocketType GetSocketType (void) const; // returns socket type
 Lines 624-633    Link Here 
624
  uint32_t          m_cnCount;         //!< Count of remaining connection retries
678
  uint32_t          m_cnCount;         //!< Count of remaining connection retries
625
  uint32_t          m_cnRetries;       //!< Number of connection retries before giving up
679
  uint32_t          m_cnRetries;       //!< Number of connection retries before giving up
626
  TracedValue<Time> m_rto;             //!< Retransmit timeout
680
  TracedValue<Time> m_rto;             //!< Retransmit timeout
681
  Time              m_minRto;          //!< minimum value of the Retransmit timeout
682
  Time              m_clockGranularity; //!< Clock Granularity used in RTO calcs
627
  TracedValue<Time> m_lastRtt;         //!< Last RTT sample collected
683
  TracedValue<Time> m_lastRtt;         //!< Last RTT sample collected
628
  Time              m_delAckTimeout;   //!< Time to delay an ACK
684
  Time              m_delAckTimeout;   //!< Time to delay an ACK
629
  Time              m_persistTimeout;  //!< Time between sending 1-byte probes
685
  Time              m_persistTimeout;  //!< Time between sending 1-byte probes
630
  Time              m_cnTimeout;       //!< Timeout for connection retry
686
  Time              m_cnTimeout;       //!< Timeout for connection retry
687
  RttHistory_t      m_history;         //!< List of sent packet
631
688
632
  // Connections to other layers of TCP/IP
689
  // Connections to other layers of TCP/IP
633
  Ipv4EndPoint*       m_endPoint;   //!< the IPv4 endpoint
690
  Ipv4EndPoint*       m_endPoint;   //!< the IPv4 endpoint
 Lines 667-673    Link Here 
667
724
668
  bool     m_timestampEnabled;    //!< Timestamp option enabled
725
  bool     m_timestampEnabled;    //!< Timestamp option enabled
669
  uint32_t m_timestampToEcho;     //!< Timestamp to echo
726
  uint32_t m_timestampToEcho;     //!< Timestamp to echo
670
  uint32_t m_lastEchoedTime;      //!< Last echoed timestamp
671
};
727
};
672
728
673
} // namespace ns3
729
} // namespace ns3
(-)a/src/internet/model/tcp-tahoe.cc (-1 lines)
 Lines 166-172    Link Here 
166
  m_ssThresh = std::max (static_cast<unsigned> (m_cWnd / 2), m_segmentSize * 2);  // Half ssthresh
166
  m_ssThresh = std::max (static_cast<unsigned> (m_cWnd / 2), m_segmentSize * 2);  // Half ssthresh
167
  m_cWnd = m_segmentSize;                   // Set cwnd to 1 segSize (RFC2001, sec.2)
167
  m_cWnd = m_segmentSize;                   // Set cwnd to 1 segSize (RFC2001, sec.2)
168
  m_nextTxSequence = m_txBuffer.HeadSequence (); // Restart from highest Ack
168
  m_nextTxSequence = m_txBuffer.HeadSequence (); // Restart from highest Ack
169
  m_rtt->IncreaseMultiplier ();             // Double the next RTO
170
  DoRetransmit ();                          // Retransmit the packet
169
  DoRetransmit ();                          // Retransmit the packet
171
}
170
}
172
171
(-)a/src/internet/model/tcp-westwood.cc (-7 / +4 lines)
 Lines 307-329    Link Here 
307
  if (m_state == CLOSED || m_state == TIME_WAIT)
307
  if (m_state == CLOSED || m_state == TIME_WAIT)
308
    return;
308
    return;
309
  // If all data are received, just return
309
  // If all data are received, just return
310
  if (m_txBuffer.HeadSequence() >= m_nextTxSequence)
310
  if (m_txBuffer.HeadSequence () >= m_nextTxSequence)
311
    return;
311
    return;
312
312
313
  // Upon an RTO, adjust cwnd and ssthresh based on the estimated BW
313
  // Upon an RTO, adjust cwnd and ssthresh based on the estimated BW
314
  m_ssThresh = std::max (static_cast<double> (2 * m_segmentSize), m_currentBW.Get() * static_cast<double> (m_minRtt.GetSeconds()));
314
  m_ssThresh = std::max (static_cast<double> (2 * m_segmentSize), m_currentBW.Get () * static_cast<double> (m_minRtt.GetSeconds ()));
315
  m_cWnd = m_segmentSize;
315
  m_cWnd = m_segmentSize;
316
316
317
  // Restart from highest ACK
317
  // Restart from highest ACK
318
  m_nextTxSequence = m_txBuffer.HeadSequence();
318
  m_nextTxSequence = m_txBuffer.HeadSequence ();
319
  NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd <<
319
  NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd <<
320
      ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence);
320
      ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence);
321
321
322
  // Double the next RTO
323
  m_rtt->IncreaseMultiplier();
324
325
  // Retransmit the packet
322
  // Retransmit the packet
326
  DoRetransmit();
323
  DoRetransmit ();
327
}
324
}
328
325
329
void
326
void
(-)a/src/internet/test/rtt-test.cc (-6 / +3 lines)
 Lines 64-70    Link Here 
64
  nv->SetAttribute ("Mean", DoubleValue (m_mean));
64
  nv->SetAttribute ("Mean", DoubleValue (m_mean));
65
  nv->SetAttribute ("Variance", DoubleValue (m_variance));
65
  nv->SetAttribute ("Variance", DoubleValue (m_variance));
66
66
67
  NS_TEST_EXPECT_MSG_EQ (m_mean, rtt->GetCurrentEstimate ().GetMilliSeconds (), "Initial estimate should match mean");
67
  NS_TEST_EXPECT_MSG_EQ (m_mean, rtt->GetEstimate ().GetMilliSeconds (), "Initial estimate should match mean");
68
68
69
  double a, v, g;
69
  double a, v, g;
70
  a = v = m_mean;
70
  a = v = m_mean;
 Lines 82-93    Link Here 
82
  //5% tolerance
82
  //5% tolerance
83
  double tolerance = m_mean * .05;
83
  double tolerance = m_mean * .05;
84
84
85
  NS_TEST_ASSERT_MSG_EQ_TOL (m_mean, rtt->GetCurrentEstimate ().GetMilliSeconds (), tolerance, "Unexpected estimate");
85
  NS_TEST_ASSERT_MSG_EQ_TOL (m_mean, rtt->GetEstimate ().GetMilliSeconds (), tolerance, "Unexpected estimate");
86
}
86
87
87
  int expectedTimeout = (int)a + 4 * (int)v;
88
89
  NS_TEST_EXPECT_MSG_EQ (rtt->RetransmitTimeout ().GetMilliSeconds (), expectedTimeout, "Timeout values do not match");
90
}
91
void
88
void
92
RttTestCase::DoTeardown (void)
89
RttTestCase::DoTeardown (void)
93
{
90
{

Return to bug 1405