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 namespace ns3 {
34 
35 NS_LOG_COMPONENT_DEFINE ("TcpYeahTestSuite");
36 
41 {
42 public:
43  TcpYeahIncrementTest (uint32_t cWnd,
44  uint32_t ssThresh,
45  uint32_t segmentSize,
46  SequenceNumber32 nextTxSeq,
47  SequenceNumber32 lastAckedSeq,
48  uint32_t segmentsAcked,
49  Time minRtt,
50  const std::string &name);
51 
52 private:
53  virtual void DoRun ();
54  void IncreaseWindow (Ptr<TcpYeah> cong);
55 
56  uint32_t m_cWnd;
57  uint32_t m_ssThresh;
58  uint32_t m_segmentSize;
61  uint32_t m_segmentsAcked;
64  uint32_t m_doingRenoNow;
65  uint32_t m_cntRtt;
66  uint32_t m_renoCount;
67 };
68 
70  uint32_t ssThresh,
71  uint32_t segmentSize,
72  SequenceNumber32 nextTxSeq,
73  SequenceNumber32 lastAckedSeq,
74  uint32_t segmentsAcked,
75  Time minRtt,
76  const std::string &name)
77  : TestCase (name),
78  m_cWnd (cWnd),
79  m_ssThresh (ssThresh),
80  m_segmentSize (segmentSize),
81  m_nextTxSeq (nextTxSeq),
82  m_lastAckedSeq (lastAckedSeq),
83  m_segmentsAcked (segmentsAcked),
84  m_baseRtt (MilliSeconds (100)),
85  m_minRtt (minRtt),
86  m_doingRenoNow (0),
87  m_cntRtt (4),
88  m_renoCount (2)
89 {
90 }
91 
92 void
94 {
95  Ptr<TcpSocketState> state = CreateObject <TcpSocketState> ();
96  state->m_cWnd = m_cWnd;
97  state->m_ssThresh = m_ssThresh;
98  state->m_segmentSize = m_segmentSize;
99  state->m_nextTxSequence = m_nextTxSeq;
100  state->m_lastAckedSeq = m_lastAckedSeq;
101 
102  Ptr<TcpYeah> cong = CreateObject <TcpYeah> ();
103 
104  // Set baseRtt to 100 ms
105  cong->PktsAcked (state, m_segmentsAcked, m_baseRtt);
106 
107  // Reset YeAH to assign a new value of minRtt
108  cong->CongestionStateSet (state, TcpSocketState::CA_OPEN);
109  cong->PktsAcked (state, m_segmentsAcked, m_minRtt);
110 
111  // 2 more calls to PktsAcked to increment cntRtt beyond 2
112  cong->PktsAcked (state, m_segmentsAcked, m_minRtt);
113  cong->PktsAcked (state, m_segmentsAcked, m_minRtt);
114 
115  cong->IncreaseWindow (state, m_segmentsAcked);
116  IncreaseWindow (cong);
117 
118  NS_TEST_ASSERT_MSG_EQ (state->m_cWnd.Get (), m_cWnd,
119  "CWnd has not updated correctly");
120 }
121 
122 void
124 {
125  uint32_t segCwnd = m_cWnd / m_segmentSize;
126 
127  if (m_cWnd < m_ssThresh)
128  { // NewReno slow start
129  if (m_segmentsAcked >= 1)
130  {
132  m_segmentsAcked -= 1;
133  NS_LOG_INFO ("In SlowStart, updated to cwnd " << m_cWnd <<
134  " ssthresh " << m_ssThresh);
135  }
136  }
137  else if (!m_doingRenoNow)
138  { // Fast mode, follow STCP increment rule
139  UintegerValue aiFactor;
140  cong->GetAttribute ("StcpAiFactor", aiFactor);
141  uint32_t w = std::min (segCwnd, (uint32_t) aiFactor.Get ());
142  uint32_t delta = m_segmentsAcked / w;
143  m_cWnd += delta * m_segmentSize;
144  NS_LOG_INFO ("In Fast mode, updated to cwnd " << m_cWnd <<
145  " ssthresh " << m_ssThresh);
146  }
147  else
148  { // NewReno congestion avoidance
149  if (m_segmentsAcked > 0)
150  {
151  double adder = static_cast<double> (m_segmentSize * m_segmentSize) / m_cWnd;
152  adder = std::max (1.0, adder);
153  m_cWnd += static_cast<uint32_t> (adder);
154  NS_LOG_INFO ("In CongAvoid, updated to cwnd " << m_cWnd <<
155  " ssthresh " << m_ssThresh);
156  }
157 
158  }
160  {
161  if (m_cntRtt > 2)
162  {
163  /*
164  * Calculate the extra number of packets in queue
165  */
166  Time rttQueue = m_minRtt - m_baseRtt;
167  double bw = segCwnd / m_minRtt.GetSeconds ();
168  uint32_t queue = bw * rttQueue.GetSeconds ();
169 
170  // Calculate network congestion level
171  double L = rttQueue.GetSeconds () / m_baseRtt.GetSeconds ();
172 
173  UintegerValue alpha;
174  cong->GetAttribute ("Alpha", alpha);
176  cong->GetAttribute ("Phy", phy);
177  UintegerValue gamma;
178  cong->GetAttribute ("Gamma", gamma);
180  cong->GetAttribute ("Epsilon", epsilon);
181  UintegerValue zeta;
182  cong->GetAttribute ("Zeta", zeta);
183 
184  if (queue > alpha.Get () || L > (1 / phy.Get ()) )
185  { // Slow mode
186  NS_LOG_INFO ("Enter Slow mode");
187  if (queue > alpha.Get () && segCwnd > m_renoCount)
188  { // Precautionary decongestion
189  uint32_t reduction = std::min (queue / (uint32_t) gamma.Get (),
190  segCwnd >> (uint32_t) epsilon.Get ());
191  segCwnd -= reduction;
192  segCwnd = std::max (segCwnd, m_renoCount);
193  m_cWnd = segCwnd * m_segmentSize;
194  m_ssThresh = m_cWnd;
195  NS_LOG_INFO ("In Slow mode, after precautionary decongestion, "
196  "updated to cwnd " << m_cWnd << " ssthresh " <<
197  m_ssThresh);
198  }
199  }
200  }
201  }
202 }
203 
208 {
209 public:
210  TcpYeahDecrementTest (uint32_t cWnd,
211  uint32_t ssThresh,
212  uint32_t segmentSize,
213  SequenceNumber32 nextTxSeq,
214  SequenceNumber32 lastAckedSeq,
215  Time minRtt,
216  UintegerValue rho,
217  const std::string &name);
218 
219 private:
220  virtual void DoRun (void);
221  uint32_t CalculateSsThresh (Ptr<TcpYeah> cong);
222 
223  uint32_t m_cWnd;
224  uint32_t m_ssThresh;
225  uint32_t m_segmentSize;
226  uint32_t m_doingRenoNow;
231  uint32_t m_segmentsAcked;
233 };
234 
236  uint32_t ssThresh,
237  uint32_t segmentSize,
238  SequenceNumber32 nextTxSeq,
239  SequenceNumber32 lastAckedSeq,
240  Time minRtt,
241  UintegerValue rho,
242  const std::string &name)
243  : TestCase (name),
244  m_cWnd (cWnd),
245  m_ssThresh (ssThresh),
246  m_segmentSize (segmentSize),
247  m_doingRenoNow (0),
248  m_nextTxSeq (nextTxSeq),
249  m_lastAckedSeq (lastAckedSeq),
250  m_minRtt (minRtt),
251  m_baseRtt (MilliSeconds (100)),
252  m_segmentsAcked (2),
253  m_rho (rho)
254 {
255 }
256 
257 void
259 {
260  Ptr<TcpSocketState> state = CreateObject <TcpSocketState> ();
261  state->m_cWnd = m_cWnd;
262  state->m_nextTxSequence = m_nextTxSeq;
263  state->m_lastAckedSeq = m_lastAckedSeq;
264  state->m_segmentSize = m_segmentSize;
265  state->m_ssThresh = m_ssThresh;
266 
267  Ptr<TcpYeah> cong = CreateObject <TcpYeah> ();
268 
269  // Re-set rho to 1 for this unit test
270  cong->SetAttribute ("Rho", UintegerValue (m_rho));
271 
272  // Set baseRtt to 100 ms
273  cong->PktsAcked (state, m_segmentsAcked, m_baseRtt);
274 
275  // Set minRtt to a different value
276  cong->CongestionStateSet (state, TcpSocketState::CA_OPEN);
277  cong->PktsAcked (state, m_segmentsAcked, m_minRtt);
278 
279  // 2 more calls to PktsAcked to increment cntRtt beyond 2
280  cong->PktsAcked (state, m_segmentsAcked, m_minRtt);
281  cong->PktsAcked (state, m_segmentsAcked, m_minRtt);
282 
283  // Calculate queue backlog
284  cong->IncreaseWindow (state, m_segmentsAcked);
285 
286  // Now get the value of ssThresh
287  uint32_t ssThresh = cong->GetSsThresh (state, m_cWnd);
288 
289  // Our calculation of ssThresh
290  uint32_t ssThreshVal = CalculateSsThresh (cong);
291 
292  NS_TEST_ASSERT_MSG_EQ (ssThresh, ssThreshVal,
293  "SsThresh has not updated correctly");
294 }
295 
296 uint32_t
298 {
299  // Calculate queue backlog
300  uint32_t segCwnd = m_cWnd / m_segmentSize;
301  uint32_t reduction;
302 
303  UintegerValue delta;
304  cong->GetAttribute ("Delta", delta);
305 
306  Time rttQueue = m_minRtt - m_baseRtt;
307 
308  // queue = rttQueue * bw = rttQueue * (cwnd/RTTmin)
309  double bw = segCwnd / m_minRtt.GetSeconds ();
310  uint32_t queue = bw * rttQueue.GetSeconds ();
311 
312  NS_LOG_LOGIC ("queue backlog" << queue);
313 
314  if (m_doingRenoNow < m_rho.Get ())
315  {
316  reduction = std::max (queue, segCwnd >> delta.Get ());
317  reduction = std::min (reduction, std::max (segCwnd >> 1, (uint32_t) 2));
318  NS_LOG_INFO ("Reduction amount for yeah upon loss = " << reduction);
319  }
320  else
321  {
322  reduction = std::max (segCwnd >> 1, (uint32_t) 2);
323  NS_LOG_INFO ("Reduction amount for reno upon loss = " << reduction);
324  }
325 
326 
327  return (m_cWnd - (reduction * m_segmentSize));
328 
329 }
330 
331 
332 // -------------------------------------------------------------------
333 static class TcpYeahTestSuite : public TestSuite
334 {
335 public:
336  TcpYeahTestSuite () : TestSuite ("tcp-yeah-test", UNIT)
337  {
338  AddTestCase (new TcpYeahIncrementTest (20 * 1446, 25 * 1446, 1446, SequenceNumber32 (2893),
339  SequenceNumber32 (1447), 1, MilliSeconds (105),
340  "YeAH test on cWnd when in slow start"),
342  AddTestCase (new TcpYeahIncrementTest (30 * 1446, 25 * 1446, 1446, SequenceNumber32 (2893),
343  SequenceNumber32 (1447), 30, MilliSeconds (105),
344  "YeAH test on cWnd when in Fast mode"),
346  AddTestCase (new TcpYeahIncrementTest (40 * 356, 30 * 356, 356, SequenceNumber32 (20761),
347  SequenceNumber32 (21117), 1, MilliSeconds (120),
348  "YeAH test on cWnd when in slow mode without precautionary decongestion"),
350  AddTestCase (new TcpYeahIncrementTest (100 * 356, 70 * 356, 356, SequenceNumber32 (20761),
351  SequenceNumber32 (21117), 1, MilliSeconds (600),
352  "YeAH test on cWnd when in slow mode with precautionary decongestion"),
354  AddTestCase (new TcpYeahDecrementTest (40 * 1446, 30 * 1446, 1446, SequenceNumber32 (2893),
355  SequenceNumber32 (7230), MilliSeconds (120), UintegerValue (0),
356  "YeAH test on ssThresh upon loss while competing with Reno flows"),
358  AddTestCase (new TcpYeahDecrementTest (57 * 1446, 42 * 1446, 1446, SequenceNumber32 (2893),
359  SequenceNumber32 (7230), MilliSeconds (200), UintegerValue (2),
360  "YeAH test on ssThresh upon loss while not competing with Reno flows"),
362  }
363 } g_tcpYeahTest;
364 
365 } // namespace ns3
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
Normal state, no dubious events.
SequenceNumber32 m_lastAckedSeq
#define min(a, b)
Definition: 80211b.c:44
TcpYeahDecrementTest(uint32_t cWnd, uint32_t ssThresh, uint32_t segmentSize, SequenceNumber32 nextTxSeq, SequenceNumber32 lastAckedSeq, Time minRtt, UintegerValue rho, const std::string &name)
Fast test.
Definition: test.h:1152
A suite of tests to run.
Definition: test.h:1333
uint32_t CalculateSsThresh(Ptr< TcpYeah > cong)
#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:903
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:244
encapsulates test code
Definition: test.h:1147
This test suite implements a Unit Test.
Definition: test.h:1343
void IncreaseWindow(Ptr< TcpYeah > cong)
uint64_t Get(void) const
Definition: uinteger.cc:35
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:341
tuple phy
Definition: third.py:86
#define max(a, b)
Definition: 80211b.c:45
void AddTestCase(TestCase *testCase, enum TestDuration duration)
Add an individual child TestCase to this test suite.
Definition: test.cc:298
SequenceNumber32 m_nextTxSeq
Hold an unsigned integer type.
Definition: uinteger.h:44
#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:161
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:252
ns3::TcpYeahTestSuite g_tcpYeahTest
SequenceNumber32 m_nextTxSeq
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Testing TcpYeah multiplicative decrease algorithm.
SequenceNumber32 m_lastAckedSeq
virtual void DoRun()
Implementation to actually run this TestCase.
TcpYeahIncrementTest(uint32_t cWnd, uint32_t ssThresh, uint32_t segmentSize, SequenceNumber32 nextTxSeq, SequenceNumber32 lastAckedSeq, uint32_t segmentsAcked, Time minRtt, const std::string &name)
Testing TcpYeah additive increase algorithm.
virtual void DoRun(void)
Implementation to actually run this TestCase.