A Discrete-Event Network Simulator
API
tcp-yeah-test.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2016 ResiliNets, ITTC, University of Kansas
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: Truc Anh N. Nguyen <annguyen@ittc.ku.edu>
19  *
20  * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
21  * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
22  * Information and Telecommunication Technology Center (ITTC)
23  * and Department of Electrical Engineering and Computer Science
24  * The University of Kansas Lawrence, KS USA.
25  */
26 
27 #include "ns3/test.h"
28 #include "ns3/log.h"
29 #include "ns3/tcp-congestion-ops.h"
30 #include "ns3/tcp-socket-base.h"
31 #include "ns3/tcp-yeah.h"
32 
33 using namespace ns3;
34 
35 NS_LOG_COMPONENT_DEFINE ("TcpYeahTestSuite");
36 
44 {
45 public:
57  TcpYeahIncrementTest (uint32_t cWnd,
58  uint32_t ssThresh,
59  uint32_t segmentSize,
60  SequenceNumber32 nextTxSeq,
61  SequenceNumber32 lastAckedSeq,
62  uint32_t segmentsAcked,
63  Time minRtt,
64  const std::string &name);
65 
66 private:
67  virtual void DoRun ();
72  void IncreaseWindow (Ptr<TcpYeah> cong);
73 
74  uint32_t m_cWnd;
75  uint32_t m_ssThresh;
76  uint32_t m_segmentSize;
79  uint32_t m_segmentsAcked;
82  uint32_t m_doingRenoNow;
83  uint32_t m_cntRtt;
84  uint32_t m_renoCount;
85 };
86 
88  uint32_t ssThresh,
89  uint32_t segmentSize,
90  SequenceNumber32 nextTxSeq,
91  SequenceNumber32 lastAckedSeq,
92  uint32_t segmentsAcked,
93  Time minRtt,
94  const std::string &name)
95  : TestCase (name),
96  m_cWnd (cWnd),
97  m_ssThresh (ssThresh),
98  m_segmentSize (segmentSize),
99  m_nextTxSeq (nextTxSeq),
100  m_lastAckedSeq (lastAckedSeq),
101  m_segmentsAcked (segmentsAcked),
102  m_baseRtt (MilliSeconds (100)),
103  m_minRtt (minRtt),
104  m_doingRenoNow (0),
105  m_cntRtt (4),
106  m_renoCount (2)
107 {
108 }
109 
110 void
112 {
113  Ptr<TcpSocketState> state = CreateObject <TcpSocketState> ();
114  state->m_cWnd = m_cWnd;
115  state->m_ssThresh = m_ssThresh;
116  state->m_segmentSize = m_segmentSize;
117  state->m_nextTxSequence = m_nextTxSeq;
119  state->m_minRtt = m_minRtt;
120 
121  Ptr<TcpYeah> cong = CreateObject <TcpYeah> ();
122 
123  // Set baseRtt to 100 ms
124  cong->PktsAcked (state, m_segmentsAcked, m_baseRtt);
125 
126  // Reset YeAH to assign a new value of minRtt
127  cong->CongestionStateSet (state, TcpSocketState::CA_OPEN);
128  cong->PktsAcked (state, m_segmentsAcked, m_minRtt);
129 
130  // 2 more calls to PktsAcked to increment cntRtt beyond 2
131  cong->PktsAcked (state, m_segmentsAcked, m_minRtt);
132  cong->PktsAcked (state, m_segmentsAcked, m_minRtt);
133 
134  cong->IncreaseWindow (state, m_segmentsAcked);
135  IncreaseWindow (cong);
136 
138  "CWnd has not updated correctly");
139 }
140 
141 void
143 {
144  uint32_t segCwnd = m_cWnd / m_segmentSize;
145 
146  if (m_cWnd < m_ssThresh)
147  { // NewReno slow start
148  if (m_segmentsAcked >= 1)
149  {
151  m_segmentsAcked -= 1;
152  NS_LOG_INFO ("In SlowStart, updated to cwnd " << m_cWnd <<
153  " ssthresh " << m_ssThresh);
154  }
155  }
156  else if (!m_doingRenoNow)
157  { // Fast mode, follow STCP increment rule
158  UintegerValue aiFactor;
159  cong->GetAttribute ("StcpAiFactor", aiFactor);
160  uint32_t w = std::min (segCwnd, (uint32_t) aiFactor.Get ());
161  uint32_t delta = m_segmentsAcked / w;
162  m_cWnd += delta * m_segmentSize;
163  NS_LOG_INFO ("In Fast mode, updated to cwnd " << m_cWnd <<
164  " ssthresh " << m_ssThresh);
165  }
166  else
167  { // NewReno congestion avoidance
168  if (m_segmentsAcked > 0)
169  {
170  double adder = static_cast<double> (m_segmentSize * m_segmentSize) / m_cWnd;
171  adder = std::max (1.0, adder);
172  m_cWnd += static_cast<uint32_t> (adder);
173  NS_LOG_INFO ("In CongAvoid, updated to cwnd " << m_cWnd <<
174  " ssthresh " << m_ssThresh);
175  }
176 
177  }
179  {
180  if (m_cntRtt > 2)
181  {
182  /*
183  * Calculate the extra number of packets in queue
184  */
185  Time rttQueue = m_minRtt - m_baseRtt;
186  double bw = segCwnd / m_minRtt.GetSeconds ();
187  uint32_t queue = bw * rttQueue.GetSeconds ();
188 
189  // Calculate network congestion level
190  double L = rttQueue.GetSeconds () / m_baseRtt.GetSeconds ();
191 
193  cong->GetAttribute ("Alpha", alpha);
195  cong->GetAttribute ("Phy", phy);
196  UintegerValue gamma;
197  cong->GetAttribute ("Gamma", gamma);
199  cong->GetAttribute ("Epsilon", epsilon);
200  UintegerValue zeta;
201  cong->GetAttribute ("Zeta", zeta);
202 
203  if (queue > alpha.Get () || L > (1 / phy.Get ()) )
204  { // Slow mode
205  NS_LOG_INFO ("Enter Slow mode");
206  if (queue > alpha.Get () && segCwnd > m_renoCount)
207  { // Precautionary decongestion
208  uint32_t reduction = std::min (queue / (uint32_t) gamma.Get (),
209  segCwnd >> (uint32_t) epsilon.Get ());
210  segCwnd -= reduction;
211  segCwnd = std::max (segCwnd, m_renoCount);
212  m_cWnd = segCwnd * m_segmentSize;
213  m_ssThresh = m_cWnd;
214  NS_LOG_INFO ("In Slow mode, after precautionary decongestion, "
215  "updated to cwnd " << m_cWnd << " ssthresh " <<
216  m_ssThresh);
217  }
218  }
219  }
220  }
221 }
222 
230 {
231 public:
243  TcpYeahDecrementTest (uint32_t cWnd,
244  uint32_t ssThresh,
245  uint32_t segmentSize,
246  SequenceNumber32 nextTxSeq,
247  SequenceNumber32 lastAckedSeq,
248  Time minRtt,
249  UintegerValue rho,
250  const std::string &name);
251 
252 private:
253  virtual void DoRun (void);
259  uint32_t CalculateSsThresh (Ptr<TcpYeah> cong);
260 
261  uint32_t m_cWnd;
262  uint32_t m_ssThresh;
263  uint32_t m_segmentSize;
264  uint32_t m_doingRenoNow;
269  uint32_t m_segmentsAcked;
271 };
272 
274  uint32_t ssThresh,
275  uint32_t segmentSize,
276  SequenceNumber32 nextTxSeq,
277  SequenceNumber32 lastAckedSeq,
278  Time minRtt,
279  UintegerValue rho,
280  const std::string &name)
281  : TestCase (name),
282  m_cWnd (cWnd),
283  m_ssThresh (ssThresh),
284  m_segmentSize (segmentSize),
285  m_doingRenoNow (0),
286  m_nextTxSeq (nextTxSeq),
287  m_lastAckedSeq (lastAckedSeq),
288  m_minRtt (minRtt),
289  m_baseRtt (MilliSeconds (100)),
290  m_segmentsAcked (2),
291  m_rho (rho)
292 {
293 }
294 
295 void
297 {
298  Ptr<TcpSocketState> state = CreateObject <TcpSocketState> ();
299  state->m_cWnd = m_cWnd;
300  state->m_nextTxSequence = m_nextTxSeq;
302  state->m_segmentSize = m_segmentSize;
303  state->m_ssThresh = m_ssThresh;
304 
305  Ptr<TcpYeah> cong = CreateObject <TcpYeah> ();
306 
307  // Re-set rho to 1 for this unit test
308  cong->SetAttribute ("Rho", UintegerValue (m_rho));
309 
310  // Set baseRtt to 100 ms
311  cong->PktsAcked (state, m_segmentsAcked, m_baseRtt);
312 
313  // Set minRtt to a different value
314  cong->CongestionStateSet (state, TcpSocketState::CA_OPEN);
315  cong->PktsAcked (state, m_segmentsAcked, m_minRtt);
316 
317  // 2 more calls to PktsAcked to increment cntRtt beyond 2
318  cong->PktsAcked (state, m_segmentsAcked, m_minRtt);
319  cong->PktsAcked (state, m_segmentsAcked, m_minRtt);
320 
321  // Calculate queue backlog
322  cong->IncreaseWindow (state, m_segmentsAcked);
323 
324  // Now get the value of ssThresh
325  uint32_t ssThresh = cong->GetSsThresh (state, m_cWnd);
326 
327  // Our calculation of ssThresh
328  uint32_t ssThreshVal = CalculateSsThresh (cong);
329 
330  NS_TEST_ASSERT_MSG_EQ (ssThresh, ssThreshVal,
331  "SsThresh has not updated correctly");
332 }
333 
334 uint32_t
336 {
337  // Calculate queue backlog
338  uint32_t segCwnd = m_cWnd / m_segmentSize;
339  uint32_t reduction;
340 
341  UintegerValue delta;
342  cong->GetAttribute ("Delta", delta);
343 
344  Time rttQueue = m_minRtt - m_baseRtt;
345 
346  // queue = rttQueue * bw = rttQueue * (cwnd/RTTmin)
347  double bw = segCwnd / m_minRtt.GetSeconds ();
348  uint32_t queue = bw * rttQueue.GetSeconds ();
349 
350  NS_LOG_LOGIC ("queue backlog" << queue);
351 
352  if (m_doingRenoNow < m_rho.Get ())
353  {
354  reduction = std::max (queue, segCwnd >> delta.Get ());
355  reduction = std::min (reduction, std::max (segCwnd >> 1, (uint32_t) 2));
356  NS_LOG_INFO ("Reduction amount for yeah upon loss = " << reduction);
357  }
358  else
359  {
360  reduction = std::max (segCwnd >> 1, (uint32_t) 2);
361  NS_LOG_INFO ("Reduction amount for reno upon loss = " << reduction);
362  }
363 
364 
365  return (m_cWnd - (reduction * m_segmentSize));
366 
367 }
368 
369 
377 {
378 public:
379  TcpYeahTestSuite () : TestSuite ("tcp-yeah-test", UNIT)
380  {
381  AddTestCase (new TcpYeahIncrementTest (20 * 1446, 25 * 1446, 1446, SequenceNumber32 (2893),
382  SequenceNumber32 (1447), 1, MilliSeconds (105),
383  "YeAH test on cWnd when in slow start"),
384  TestCase::QUICK);
385  AddTestCase (new TcpYeahIncrementTest (30 * 1446, 25 * 1446, 1446, SequenceNumber32 (2893),
386  SequenceNumber32 (1447), 30, MilliSeconds (105),
387  "YeAH test on cWnd when in Fast mode"),
388  TestCase::QUICK);
389  AddTestCase (new TcpYeahIncrementTest (40 * 356, 30 * 356, 356, SequenceNumber32 (20761),
390  SequenceNumber32 (21117), 1, MilliSeconds (120),
391  "YeAH test on cWnd when in slow mode without precautionary decongestion"),
392  TestCase::QUICK);
393  AddTestCase (new TcpYeahIncrementTest (100 * 356, 70 * 356, 356, SequenceNumber32 (20761),
394  SequenceNumber32 (21117), 1, MilliSeconds (600),
395  "YeAH test on cWnd when in slow mode with precautionary decongestion"),
396  TestCase::QUICK);
397  AddTestCase (new TcpYeahDecrementTest (40 * 1446, 30 * 1446, 1446, SequenceNumber32 (2893),
398  SequenceNumber32 (7230), MilliSeconds (120), UintegerValue (0),
399  "YeAH test on ssThresh upon loss while competing with Reno flows"),
400  TestCase::QUICK);
401  AddTestCase (new TcpYeahDecrementTest (57 * 1446, 42 * 1446, 1446, SequenceNumber32 (2893),
402  SequenceNumber32 (7230), MilliSeconds (200), UintegerValue (2),
403  "YeAH test on ssThresh upon loss while not competing with Reno flows"),
404  TestCase::QUICK);
405  }
406 };
407 
409 
#define min(a, b)
Definition: 80211b.c:42
#define max(a, b)
Definition: 80211b.c:43
Testing TcpYeah multiplicative decrease algorithm.
Time m_baseRtt
Base RTT.
uint32_t m_cWnd
Congestion window.
virtual void DoRun(void)
Implementation to actually run this TestCase.
uint32_t m_segmentsAcked
Number of segments ACKed.
uint32_t m_ssThresh
Slow Start Threshold.
SequenceNumber32 m_nextTxSeq
Next Tx sequence number.
uint32_t m_segmentSize
Segment size.
uint32_t m_doingRenoNow
TCP Reno fallback.
uint32_t CalculateSsThresh(Ptr< TcpYeah > cong)
Calculate the Slow Start threshold.
UintegerValue m_rho
TCP Yeah rho param.
TcpYeahDecrementTest(uint32_t cWnd, uint32_t ssThresh, uint32_t segmentSize, SequenceNumber32 nextTxSeq, SequenceNumber32 lastAckedSeq, Time minRtt, UintegerValue rho, const std::string &name)
Constructor.
SequenceNumber32 m_lastAckedSeq
Last ACKed sequence number.
Testing TcpYeah additive increase algorithm.
void IncreaseWindow(Ptr< TcpYeah > cong)
Increases the TCP window.
uint32_t m_segmentsAcked
Number of segments ACKed.
uint32_t m_cWnd
Congestion window.
Time m_baseRtt
Base RTT.
uint32_t m_segmentSize
Segment size.
TcpYeahIncrementTest(uint32_t cWnd, uint32_t ssThresh, uint32_t segmentSize, SequenceNumber32 nextTxSeq, SequenceNumber32 lastAckedSeq, uint32_t segmentsAcked, Time minRtt, const std::string &name)
Constructor.
uint32_t m_doingRenoNow
TCP Reno fallback.
SequenceNumber32 m_lastAckedSeq
Last ACKed sequence number.
virtual void DoRun()
Implementation to actually run this TestCase.
SequenceNumber32 m_nextTxSeq
Next Tx sequence number.
uint32_t m_ssThresh
Slow Start Threshold.
uint32_t m_renoCount
Reno counter.
Time m_minRtt
Min RTT.
uint32_t m_cntRtt
RTT counter.
TCP Yeah TestSuite.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
uint32_t m_segmentSize
Segment size.
Time m_minRtt
Minimum RTT observed throughout the connection.
SequenceNumber32 m_lastAckedSeq
Last sequence ACKed.
TracedValue< uint32_t > m_cWnd
Congestion window.
TracedValue< SequenceNumber32 > m_nextTxSequence
Next seqnum to be sent (SND.NXT), ReTx pushes it back.
TracedValue< uint32_t > m_ssThresh
Slow start threshold.
encapsulates test code
Definition: test.h:994
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1188
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1197
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:379
T Get(void) const
Get the underlying value.
Definition: traced-value.h:232
Hold an unsigned integer type.
Definition: uinteger.h:44
uint64_t Get(void) const
Definition: uinteger.cc:35
uint32_t segmentSize
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:141
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
Every class exported by the ns3 library is enclosed in the ns3 namespace.
float alpha
Plot alpha value (transparency)
phy
Definition: third.py:93
static TcpYeahTestSuite g_tcpYeahTest
Static variable for test initialization.