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 
120  Ptr<TcpYeah> cong = CreateObject <TcpYeah> ();
121 
122  // Set baseRtt to 100 ms
123  cong->PktsAcked (state, m_segmentsAcked, m_baseRtt);
124 
125  // Reset YeAH to assign a new value of minRtt
126  cong->CongestionStateSet (state, TcpSocketState::CA_OPEN);
127  cong->PktsAcked (state, m_segmentsAcked, m_minRtt);
128 
129  // 2 more calls to PktsAcked to increment cntRtt beyond 2
130  cong->PktsAcked (state, m_segmentsAcked, m_minRtt);
131  cong->PktsAcked (state, m_segmentsAcked, m_minRtt);
132 
133  cong->IncreaseWindow (state, m_segmentsAcked);
134  IncreaseWindow (cong);
135 
137  "CWnd has not updated correctly");
138 }
139 
140 void
142 {
143  uint32_t segCwnd = m_cWnd / m_segmentSize;
144 
145  if (m_cWnd < m_ssThresh)
146  { // NewReno slow start
147  if (m_segmentsAcked >= 1)
148  {
150  m_segmentsAcked -= 1;
151  NS_LOG_INFO ("In SlowStart, updated to cwnd " << m_cWnd <<
152  " ssthresh " << m_ssThresh);
153  }
154  }
155  else if (!m_doingRenoNow)
156  { // Fast mode, follow STCP increment rule
157  UintegerValue aiFactor;
158  cong->GetAttribute ("StcpAiFactor", aiFactor);
159  uint32_t w = std::min (segCwnd, (uint32_t) aiFactor.Get ());
160  uint32_t delta = m_segmentsAcked / w;
161  m_cWnd += delta * m_segmentSize;
162  NS_LOG_INFO ("In Fast mode, updated to cwnd " << m_cWnd <<
163  " ssthresh " << m_ssThresh);
164  }
165  else
166  { // NewReno congestion avoidance
167  if (m_segmentsAcked > 0)
168  {
169  double adder = static_cast<double> (m_segmentSize * m_segmentSize) / m_cWnd;
170  adder = std::max (1.0, adder);
171  m_cWnd += static_cast<uint32_t> (adder);
172  NS_LOG_INFO ("In CongAvoid, updated to cwnd " << m_cWnd <<
173  " ssthresh " << m_ssThresh);
174  }
175 
176  }
178  {
179  if (m_cntRtt > 2)
180  {
181  /*
182  * Calculate the extra number of packets in queue
183  */
184  Time rttQueue = m_minRtt - m_baseRtt;
185  double bw = segCwnd / m_minRtt.GetSeconds ();
186  uint32_t queue = bw * rttQueue.GetSeconds ();
187 
188  // Calculate network congestion level
189  double L = rttQueue.GetSeconds () / m_baseRtt.GetSeconds ();
190 
191  UintegerValue alpha;
192  cong->GetAttribute ("Alpha", alpha);
194  cong->GetAttribute ("Phy", phy);
195  UintegerValue gamma;
196  cong->GetAttribute ("Gamma", gamma);
198  cong->GetAttribute ("Epsilon", epsilon);
199  UintegerValue zeta;
200  cong->GetAttribute ("Zeta", zeta);
201 
202  if (queue > alpha.Get () || L > (1 / phy.Get ()) )
203  { // Slow mode
204  NS_LOG_INFO ("Enter Slow mode");
205  if (queue > alpha.Get () && segCwnd > m_renoCount)
206  { // Precautionary decongestion
207  uint32_t reduction = std::min (queue / (uint32_t) gamma.Get (),
208  segCwnd >> (uint32_t) epsilon.Get ());
209  segCwnd -= reduction;
210  segCwnd = std::max (segCwnd, m_renoCount);
211  m_cWnd = segCwnd * m_segmentSize;
212  m_ssThresh = m_cWnd;
213  NS_LOG_INFO ("In Slow mode, after precautionary decongestion, "
214  "updated to cwnd " << m_cWnd << " ssthresh " <<
215  m_ssThresh);
216  }
217  }
218  }
219  }
220 }
221 
229 {
230 public:
242  TcpYeahDecrementTest (uint32_t cWnd,
243  uint32_t ssThresh,
244  uint32_t segmentSize,
245  SequenceNumber32 nextTxSeq,
246  SequenceNumber32 lastAckedSeq,
247  Time minRtt,
248  UintegerValue rho,
249  const std::string &name);
250 
251 private:
252  virtual void DoRun (void);
258  uint32_t CalculateSsThresh (Ptr<TcpYeah> cong);
259 
260  uint32_t m_cWnd;
261  uint32_t m_ssThresh;
262  uint32_t m_segmentSize;
263  uint32_t m_doingRenoNow;
268  uint32_t m_segmentsAcked;
270 };
271 
273  uint32_t ssThresh,
274  uint32_t segmentSize,
275  SequenceNumber32 nextTxSeq,
276  SequenceNumber32 lastAckedSeq,
277  Time minRtt,
278  UintegerValue rho,
279  const std::string &name)
280  : TestCase (name),
281  m_cWnd (cWnd),
282  m_ssThresh (ssThresh),
283  m_segmentSize (segmentSize),
284  m_doingRenoNow (0),
285  m_nextTxSeq (nextTxSeq),
286  m_lastAckedSeq (lastAckedSeq),
287  m_minRtt (minRtt),
288  m_baseRtt (MilliSeconds (100)),
289  m_segmentsAcked (2),
290  m_rho (rho)
291 {
292 }
293 
294 void
296 {
297  Ptr<TcpSocketState> state = CreateObject <TcpSocketState> ();
298  state->m_cWnd = m_cWnd;
299  state->m_nextTxSequence = m_nextTxSeq;
301  state->m_segmentSize = m_segmentSize;
302  state->m_ssThresh = m_ssThresh;
303 
304  Ptr<TcpYeah> cong = CreateObject <TcpYeah> ();
305 
306  // Re-set rho to 1 for this unit test
307  cong->SetAttribute ("Rho", UintegerValue (m_rho));
308 
309  // Set baseRtt to 100 ms
310  cong->PktsAcked (state, m_segmentsAcked, m_baseRtt);
311 
312  // Set minRtt to a different value
313  cong->CongestionStateSet (state, TcpSocketState::CA_OPEN);
314  cong->PktsAcked (state, m_segmentsAcked, m_minRtt);
315 
316  // 2 more calls to PktsAcked to increment cntRtt beyond 2
317  cong->PktsAcked (state, m_segmentsAcked, m_minRtt);
318  cong->PktsAcked (state, m_segmentsAcked, m_minRtt);
319 
320  // Calculate queue backlog
321  cong->IncreaseWindow (state, m_segmentsAcked);
322 
323  // Now get the value of ssThresh
324  uint32_t ssThresh = cong->GetSsThresh (state, m_cWnd);
325 
326  // Our calculation of ssThresh
327  uint32_t ssThreshVal = CalculateSsThresh (cong);
328 
329  NS_TEST_ASSERT_MSG_EQ (ssThresh, ssThreshVal,
330  "SsThresh has not updated correctly");
331 }
332 
333 uint32_t
335 {
336  // Calculate queue backlog
337  uint32_t segCwnd = m_cWnd / m_segmentSize;
338  uint32_t reduction;
339 
340  UintegerValue delta;
341  cong->GetAttribute ("Delta", delta);
342 
343  Time rttQueue = m_minRtt - m_baseRtt;
344 
345  // queue = rttQueue * bw = rttQueue * (cwnd/RTTmin)
346  double bw = segCwnd / m_minRtt.GetSeconds ();
347  uint32_t queue = bw * rttQueue.GetSeconds ();
348 
349  NS_LOG_LOGIC ("queue backlog" << queue);
350 
351  if (m_doingRenoNow < m_rho.Get ())
352  {
353  reduction = std::max (queue, segCwnd >> delta.Get ());
354  reduction = std::min (reduction, std::max (segCwnd >> 1, (uint32_t) 2));
355  NS_LOG_INFO ("Reduction amount for yeah upon loss = " << reduction);
356  }
357  else
358  {
359  reduction = std::max (segCwnd >> 1, (uint32_t) 2);
360  NS_LOG_INFO ("Reduction amount for reno upon loss = " << reduction);
361  }
362 
363 
364  return (m_cWnd - (reduction * m_segmentSize));
365 
366 }
367 
368 
376 {
377 public:
378  TcpYeahTestSuite () : TestSuite ("tcp-yeah-test", UNIT)
379  {
380  AddTestCase (new TcpYeahIncrementTest (20 * 1446, 25 * 1446, 1446, SequenceNumber32 (2893),
381  SequenceNumber32 (1447), 1, MilliSeconds (105),
382  "YeAH test on cWnd when in slow start"),
383  TestCase::QUICK);
384  AddTestCase (new TcpYeahIncrementTest (30 * 1446, 25 * 1446, 1446, SequenceNumber32 (2893),
385  SequenceNumber32 (1447), 30, MilliSeconds (105),
386  "YeAH test on cWnd when in Fast mode"),
387  TestCase::QUICK);
388  AddTestCase (new TcpYeahIncrementTest (40 * 356, 30 * 356, 356, SequenceNumber32 (20761),
389  SequenceNumber32 (21117), 1, MilliSeconds (120),
390  "YeAH test on cWnd when in slow mode without precautionary decongestion"),
391  TestCase::QUICK);
392  AddTestCase (new TcpYeahIncrementTest (100 * 356, 70 * 356, 356, SequenceNumber32 (20761),
393  SequenceNumber32 (21117), 1, MilliSeconds (600),
394  "YeAH test on cWnd when in slow mode with precautionary decongestion"),
395  TestCase::QUICK);
396  AddTestCase (new TcpYeahDecrementTest (40 * 1446, 30 * 1446, 1446, SequenceNumber32 (2893),
397  SequenceNumber32 (7230), MilliSeconds (120), UintegerValue (0),
398  "YeAH test on ssThresh upon loss while competing with Reno flows"),
399  TestCase::QUICK);
400  AddTestCase (new TcpYeahDecrementTest (57 * 1446, 42 * 1446, 1446, SequenceNumber32 (2893),
401  SequenceNumber32 (7230), MilliSeconds (200), UintegerValue (2),
402  "YeAH test on ssThresh upon loss while not competing with Reno flows"),
403  TestCase::QUICK);
404  }
405 };
406 
408 
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
virtual void DoRun(void)
Implementation to actually run this TestCase.
uint32_t m_doingRenoNow
TCP Reno fallback.
uint32_t m_cWnd
Congestion window.
#define min(a, b)
Definition: 80211b.c:44
uint32_t m_renoCount
Reno counter.
A suite of tests to run.
Definition: test.h:1342
SequenceNumber32 m_lastAckedSeq
Last ACKed sequence number.
uint32_t m_segmentSize
Segment size.
virtual void CongestionStateSet(Ptr< TcpSocketState > tcb, const TcpSocketState::TcpCongState_t newState)
Enable/disable YeAH algorithm depending on the congestion state.
Definition: tcp-yeah.cc:183
SequenceNumber32 m_nextTxSeq
Next Tx sequence number.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1001
uint32_t m_segmentsAcked
Number of segments ACKed.
uint32_t m_doingRenoNow
TCP Reno fallback.
uint32_t m_segmentSize
Segment size.
Testing TcpYeah multiplicative decrease algorithm.
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:277
encapsulates test code
Definition: test.h:1155
This test suite implements a Unit Test.
Definition: test.h:1352
Time m_baseRtt
Base RTT.
T Get(void) const
Get the underlying value.
Definition: traced-value.h:218
virtual void PktsAcked(Ptr< TcpSocketState > tcb, uint32_t segmentsAcked, const Time &rtt)
Compute RTTs needed to execute YeAH algorithm.
Definition: tcp-yeah.cc:142
TcpYeahIncrementTest(uint32_t cWnd, uint32_t ssThresh, uint32_t segmentSize, SequenceNumber32 nextTxSeq, SequenceNumber32 lastAckedSeq, uint32_t segmentsAcked, Time minRtt, const std::string &name)
Constructor.
UintegerValue m_rho
TCP Yeah rho param.
uint64_t Get(void) const
Definition: uinteger.cc:35
TcpYeahDecrementTest(uint32_t cWnd, uint32_t ssThresh, uint32_t segmentSize, SequenceNumber32 nextTxSeq, SequenceNumber32 lastAckedSeq, Time minRtt, UintegerValue rho, const std::string &name)
Constructor.
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:341
uint32_t m_ssThresh
Slow Start Threshold.
tuple phy
Definition: third.py:86
#define max(a, b)
Definition: 80211b.c:45
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
static TcpYeahTestSuite g_tcpYeahTest
Static variable for test initialization.
Time m_minRtt
Min RTT.
Hold an unsigned integer type.
Definition: uinteger.h:44
uint32_t m_cntRtt
RTT counter.
#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:168
SequenceNumber32 m_lastAckedSeq
Last ACKed sequence number.
SequenceNumber32 m_lastAckedSeq
Last sequence ACKed.
SequenceNumber32 m_nextTxSeq
Next Tx sequence number.
Time m_minRtt
Min RTT.
TracedValue< uint32_t > m_ssThresh
Slow start threshold.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint32_t m_segmentsAcked
Number of segments ACKed.
uint32_t m_segmentSize
Segment size.
void GetAttribute(std::string name, AttributeValue &value) const
Get the value of an attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:223
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
uint32_t CalculateSsThresh(Ptr< TcpYeah > cong)
Calculate the Slow Start threshold.
TracedValue< uint32_t > m_cWnd
Congestion window.
Testing TcpYeah additive increase algorithm.
void IncreaseWindow(Ptr< TcpYeah > cong)
Increases the TCP window.
virtual void IncreaseWindow(Ptr< TcpSocketState > tcb, uint32_t segmentsAcked)
Adjust cwnd following YeAH dual-mode algorithm.
Definition: tcp-yeah.cc:199
virtual void DoRun()
Implementation to actually run this TestCase.
Time m_baseRtt
Base RTT.
uint32_t m_cWnd
Congestion window.
uint32_t m_ssThresh
Slow Start Threshold.
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:185
TCP Yeah TestSuite.
virtual uint32_t GetSsThresh(Ptr< const TcpSocketState > tcb, uint32_t bytesInFlight)
Get slow start threshold upon the receipt of 3 dupACKs.
Definition: tcp-yeah.cc:317
TracedValue< SequenceNumber32 > m_nextTxSequence
Next seqnum to be sent (SND.NXT), ReTx pushes it back.