A Discrete-Event Network Simulator
API
tcp-illinois-test.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 ResiliNets, ITTC, University of Kansas
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Truc Anh N. Nguyen <annguyen@ittc.ku.edu>
18  *
19  * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
20  * ResiliNets Research Group https://resilinets.org/
21  * Information and Telecommunication Technology Center (ITTC)
22  * and Department of Electrical Engineering and Computer Science
23  * The University of Kansas Lawrence, KS USA.
24  */
25 
26 #include "ns3/log.h"
27 #include "ns3/tcp-congestion-ops.h"
28 #include "ns3/tcp-illinois.h"
29 #include "ns3/tcp-socket-base.h"
30 #include "ns3/test.h"
31 
32 using namespace ns3;
33 
34 NS_LOG_COMPONENT_DEFINE("TcpIllinoisTestSuite");
35 
41 class TcpIllinoisTest : public TestCase
42 {
43  public:
56  TcpIllinoisTest(uint32_t cWnd,
57  uint32_t ssThresh,
58  uint32_t segmentSize,
59  uint32_t cntRtt,
60  Time maxRtt,
61  uint32_t segmentsAcked,
62  SequenceNumber32 nextTxSeq,
63  SequenceNumber32 lastAckedSeq,
64  const std::string& name);
65 
66  private:
67  void DoRun() override;
72  void IncreaseWindow(Ptr<TcpIllinois> cong);
77  void RecalcParam(Ptr<TcpIllinois> cong);
82  Time CalculateMaxDelay();
87  Time CalculateAvgDelay();
94  void CalculateAlpha(Ptr<TcpIllinois> cong, double da, double dm);
101  void CalculateBeta(Ptr<TcpIllinois> cong, double da, double dm);
105  void GetSsThresh();
106 
107  uint32_t m_cWnd;
108  uint32_t m_ssThresh;
109  uint32_t m_segmentSize;
112  uint32_t m_segmentsAcked;
115  double m_alpha;
116  double m_beta;
117  uint32_t m_cntRtt;
119  bool m_rttAbove;
120  uint8_t m_rttLow;
121  uint32_t m_ackCnt;
122 };
123 
125  uint32_t ssThresh,
126  uint32_t segmentSize,
127  uint32_t cntRtt,
128  Time maxRtt,
129  uint32_t segmentsAcked,
130  SequenceNumber32 nextTxSeq,
131  SequenceNumber32 lastAckedSeq,
132  const std::string& name)
133  : TestCase(name),
134  m_cWnd(cWnd),
135  m_ssThresh(ssThresh),
136  m_segmentSize(segmentSize),
137  m_baseRtt(MilliSeconds(100)),
138  m_maxRtt(maxRtt),
139  m_segmentsAcked(segmentsAcked),
140  m_nextTxSeq(nextTxSeq),
141  m_lastAckedSeq(lastAckedSeq),
142  m_alpha(0.0),
143  m_beta(0.0),
144  m_cntRtt(cntRtt),
145  m_sumRtt(0),
146  m_rttAbove(false),
147  m_rttLow(0),
148  m_ackCnt(0)
149 {
150 }
151 
152 void
154 {
155  Ptr<TcpSocketState> state = CreateObject<TcpSocketState>();
156  state->m_cWnd = m_cWnd;
157  state->m_ssThresh = m_ssThresh;
158  state->m_segmentSize = m_segmentSize;
159  state->m_nextTxSequence = m_nextTxSeq;
161 
162  Ptr<TcpIllinois> cong = CreateObject<TcpIllinois>();
163 
164  // Set baseRtt to 100 ms
165  cong->PktsAcked(state, m_segmentsAcked, m_baseRtt);
166 
167  m_sumRtt += m_baseRtt;
168 
169  // Set maxRtt and update sumRtt based on cntRtt value
170  for (uint32_t count = 1; count < m_cntRtt; ++count)
171  {
172  cong->PktsAcked(state, m_segmentsAcked, m_maxRtt);
173  m_sumRtt += m_maxRtt;
174  }
175 
176  /*
177  * Test cWnd modification during additive increase
178  */
179  cong->IncreaseWindow(state, m_segmentsAcked);
180  IncreaseWindow(cong);
181  NS_TEST_ASSERT_MSG_EQ(state->m_cWnd.Get(), m_cWnd, "CWnd has not updated correctly");
182 
183  /*
184  * Test ssThresh modification during multiplicative decrease
185  */
186  uint32_t ssThresh = cong->GetSsThresh(state, m_cWnd);
187  GetSsThresh();
188  NS_TEST_ASSERT_MSG_EQ(ssThresh, m_ssThresh, "SsThresh has not updated correctly");
189 }
190 
191 void
193 {
194  uint32_t segCwnd = m_cWnd / m_segmentSize;
195 
197  {
198  RecalcParam(cong);
199  }
200  if (m_cWnd < m_ssThresh)
201  { // NewReno slow start
202  if (m_segmentsAcked >= 1)
203  {
205  m_segmentsAcked -= 1;
206  }
207  NS_LOG_INFO("In SlowStart, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
208  }
209  else
210  {
211  uint32_t oldCwnd = segCwnd;
212 
213  if (m_segmentsAcked > 0)
214  {
216  }
217 
218  while (m_ackCnt >= segCwnd)
219  {
220  m_ackCnt -= segCwnd;
221  segCwnd += 1;
222  }
223 
224  if (segCwnd != oldCwnd)
225  {
226  m_cWnd = segCwnd * m_segmentSize;
227  NS_LOG_INFO("In CongAvoid, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
228  }
229  }
230 }
231 
232 void
234 {
235  DoubleValue alphaBase;
236  cong->GetAttribute("AlphaBase", alphaBase);
237  UintegerValue winThresh;
238  cong->GetAttribute("WinThresh", winThresh);
239 
240  if (m_cWnd < winThresh.Get())
241  {
242  NS_LOG_INFO("cWnd < winThresh, set alpha & beta to base values");
243  m_alpha = alphaBase.Get();
244  }
245  else if (m_cntRtt > 0)
246  {
247  double dm = (double)CalculateMaxDelay().GetMilliSeconds();
248  double da = (double)CalculateAvgDelay().GetMilliSeconds();
249 
250  NS_LOG_INFO("Updated to dm = " << dm << " da = " << da);
251 
252  CalculateAlpha(cong, da, dm);
253  CalculateBeta(cong, da, dm);
254  }
255 }
256 
257 Time
259 {
260  return (m_maxRtt - m_baseRtt);
261 }
262 
263 Time
265 {
266  return (m_sumRtt / m_cntRtt - m_baseRtt);
267 }
268 
269 void
271 {
272  DoubleValue alphaMax;
273  cong->GetAttribute("AlphaMax", alphaMax);
274  UintegerValue theta;
275  cong->GetAttribute("Theta", theta);
276  DoubleValue alphaMin;
277  cong->GetAttribute("AlphaMin", alphaMin);
278 
279  double d1 = dm / 100;
280 
281  if (da <= d1)
282  {
283  if (!m_rttAbove)
284  {
285  m_alpha = alphaMax.Get();
286  }
287  if (++m_rttLow >= theta.Get())
288  {
289  m_rttLow = 0;
290  m_rttAbove = false;
291  m_alpha = alphaMax.Get();
292  }
293  }
294  else
295  {
296  m_rttAbove = true;
297  dm -= d1;
298  da -= d1;
299  m_alpha = (dm * alphaMax.Get()) /
300  (dm + (da * (alphaMax.Get() - alphaMin.Get())) / alphaMin.Get());
301  }
302  NS_LOG_INFO("Updated to alpha = " << m_alpha);
303 }
304 
305 void
307 {
308  DoubleValue betaMin;
309  cong->GetAttribute("BetaMin", betaMin);
310  DoubleValue betaMax;
311  cong->GetAttribute("BetaMax", betaMax);
312 
313  double d2;
314  double d3;
315  d2 = dm / 10;
316  d3 = (8 * dm) / 10;
317 
318  if (da <= d2)
319  {
320  m_beta = betaMin.Get();
321  }
322  else if (da > d2 && da < d3)
323  {
324  m_beta = (betaMin.Get() * d3 - betaMax.Get() * d2 + (betaMax.Get() - betaMin.Get()) * da) /
325  (d3 - d2);
326  }
327 
328  else if (da >= d3 || d3 <= d2)
329  {
330  m_beta = betaMax.Get();
331  }
332  NS_LOG_INFO("Updated to beta = " << m_beta);
333 }
334 
335 void
337 {
338  uint32_t segCwnd = m_cWnd / m_segmentSize;
339  uint32_t ssThresh = std::max(2.0, (1.0 - m_beta) * segCwnd);
340 
341  NS_LOG_DEBUG("Calculated ssThresh (in segments) = " << ssThresh);
342 
343  m_ssThresh = ssThresh * m_segmentSize;
344 }
345 
352 {
353  public:
355  : TestSuite("tcp-illinois-test", UNIT)
356  {
357  AddTestCase(new TcpIllinoisTest(38 * 1446,
358  40 * 1446,
359  1446,
360  2,
361  MilliSeconds(105),
362  2,
363  SequenceNumber32(2893),
364  SequenceNumber32(5785),
365  "Illinois test on cWnd and ssThresh when in slow start"),
366  TestCase::QUICK);
368  60 * 346,
369  40 * 346,
370  346,
371  2,
372  MilliSeconds(100),
373  2,
374  SequenceNumber32(2893),
375  SequenceNumber32(5785),
376  "Illinois test on cWnd and ssThresh when avg queueing delay is at minimum"),
377  TestCase::QUICK);
379  38 * 1446,
380  40 * 1446,
381  1446,
382  5,
383  MilliSeconds(110),
384  2,
385  SequenceNumber32(2893),
386  SequenceNumber32(5785),
387  "Illinois test on cWnd and ssThresh when avg queueing delay is at maximum"),
388  TestCase::QUICK);
389  AddTestCase(new TcpIllinoisTest(40 * 1446,
390  38 * 1446,
391  1446,
392  2,
393  MilliSeconds(105),
394  55,
395  SequenceNumber32(2893),
396  SequenceNumber32(5785),
397  "Illinois test on cWnd and ssThresh when avg queueing "
398  "delay is in between its min & max"),
399  TestCase::QUICK);
400  }
401 };
402 
#define max(a, b)
Definition: 80211b.c:42
TcpIllinois C-AIMD algorithm tests.
Time CalculateAvgDelay()
Calculate the average delay.
Time CalculateMaxDelay()
Calculate the maximum delay.
void CalculateAlpha(Ptr< TcpIllinois > cong, double da, double dm)
Calculate the TCP Illinois alpha param.
SequenceNumber32 m_lastAckedSeq
Last ACKed sequence number.
void RecalcParam(Ptr< TcpIllinois > cong)
Recalculate the internal TCP Illinois params.
Time m_baseRtt
Base RTT.
uint32_t m_ackCnt
ACK counter.
void IncreaseWindow(Ptr< TcpIllinois > cong)
Increases the TCP window.
Time m_maxRtt
Max RTT.
SequenceNumber32 m_nextTxSeq
Next Tx sequence number.
uint8_t m_rttLow
RTT low counter.
TcpIllinoisTest(uint32_t cWnd, uint32_t ssThresh, uint32_t segmentSize, uint32_t cntRtt, Time maxRtt, uint32_t segmentsAcked, SequenceNumber32 nextTxSeq, SequenceNumber32 lastAckedSeq, const std::string &name)
Constructor.
uint32_t m_cntRtt
RTT counter.
uint32_t m_cWnd
Congestion window.
bool m_rttAbove
RTT above threshold.
void CalculateBeta(Ptr< TcpIllinois > cong, double da, double dm)
Calculate the TCP Illinois beta param.
Time m_sumRtt
Sum of all the RTTs.
void GetSsThresh()
brief Get and check the SSH threshold.
void DoRun() override
Implementation to actually run this TestCase.
double m_alpha
TCP Illinois alpha parameter.
uint32_t m_ssThresh
Slow Start Threshold.
double m_beta
TCP Illinois beta parameter.
uint32_t m_segmentSize
Segment size.
uint32_t m_segmentsAcked
Number of segments ACKed.
TCP Illinois TestSuite.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
double Get() const
Definition: double.cc:37
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
uint32_t m_segmentSize
Segment size.
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:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1256
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1265
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
int64_t GetMilliSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:408
T Get() const
Get the underlying value.
Definition: traced-value.h:249
Hold an unsigned integer type.
Definition: uinteger.h:45
uint64_t Get() const
Definition: uinteger.cc:37
uint32_t segmentSize
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
SequenceNumber< uint32_t, int32_t > SequenceNumber32
32 bit Sequence number.
#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:144
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static TcpIllinoisTestSuite g_tcpIllinoisTest
Static variable for test initialization.