A Discrete-Event Network Simulator
API
tcp-yeah-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-socket-base.h"
29#include "ns3/tcp-yeah.h"
30#include "ns3/test.h"
31
32using namespace ns3;
33
34NS_LOG_COMPONENT_DEFINE("TcpYeahTestSuite");
35
43{
44 public:
57 uint32_t ssThresh,
59 SequenceNumber32 nextTxSeq,
60 SequenceNumber32 lastAckedSeq,
61 uint32_t segmentsAcked,
62 Time minRtt,
63 const std::string& name);
64
65 private:
66 void DoRun() override;
72
84};
85
87 uint32_t ssThresh,
89 SequenceNumber32 nextTxSeq,
90 SequenceNumber32 lastAckedSeq,
91 uint32_t segmentsAcked,
92 Time minRtt,
93 const std::string& name)
94 : TestCase(name),
95 m_cWnd(cWnd),
96 m_ssThresh(ssThresh),
97 m_segmentSize(segmentSize),
98 m_nextTxSeq(nextTxSeq),
99 m_lastAckedSeq(lastAckedSeq),
100 m_segmentsAcked(segmentsAcked),
101 m_baseRtt(MilliSeconds(100)),
102 m_minRtt(minRtt),
103 m_doingRenoNow(0),
104 m_cntRtt(4),
105 m_renoCount(2)
106{
107}
108
109void
111{
112 Ptr<TcpSocketState> state = CreateObject<TcpSocketState>();
113 state->m_cWnd = m_cWnd;
114 state->m_ssThresh = m_ssThresh;
118 state->m_minRtt = m_minRtt;
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
136 NS_TEST_ASSERT_MSG_EQ(state->m_cWnd.Get(), m_cWnd, "CWnd has not updated correctly");
137}
138
139void
141{
142 uint32_t segCwnd = m_cWnd / m_segmentSize;
143
144 if (m_cWnd < m_ssThresh)
145 { // NewReno slow start
146 if (m_segmentsAcked >= 1)
147 {
149 m_segmentsAcked -= 1;
150 NS_LOG_INFO("In SlowStart, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
151 }
152 }
153 else if (!m_doingRenoNow)
154 { // Fast mode, follow STCP increment rule
155 UintegerValue aiFactor;
156 cong->GetAttribute("StcpAiFactor", aiFactor);
157 uint32_t w = std::min(segCwnd, (uint32_t)aiFactor.Get());
158 uint32_t delta = m_segmentsAcked / w;
159 m_cWnd += delta * m_segmentSize;
160 NS_LOG_INFO("In Fast mode, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
161 }
162 else
163 { // NewReno congestion avoidance
164 if (m_segmentsAcked > 0)
165 {
166 double adder = static_cast<double>(m_segmentSize * m_segmentSize) / m_cWnd;
167 adder = std::max(1.0, adder);
168 m_cWnd += static_cast<uint32_t>(adder);
169 NS_LOG_INFO("In CongAvoid, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
170 }
171 }
173 {
174 if (m_cntRtt > 2)
175 {
176 /*
177 * Calculate the extra number of packets in queue
178 */
179 Time rttQueue = m_minRtt - m_baseRtt;
180 double bw = segCwnd / m_minRtt.GetSeconds();
181 uint32_t queue = bw * rttQueue.GetSeconds();
182
183 // Calculate network congestion level
184 double L = rttQueue.GetSeconds() / m_baseRtt.GetSeconds();
185
186 UintegerValue alpha;
187 cong->GetAttribute("Alpha", alpha);
189 cong->GetAttribute("Phy", phy);
190 UintegerValue gamma;
191 cong->GetAttribute("Gamma", gamma);
193 cong->GetAttribute("Epsilon", epsilon);
194 UintegerValue zeta;
195 cong->GetAttribute("Zeta", zeta);
196
197 if (queue > alpha.Get() || L > (1 / phy.Get()))
198 { // Slow mode
199 NS_LOG_INFO("Enter Slow mode");
200 if (queue > alpha.Get() && segCwnd > m_renoCount)
201 { // Precautionary decongestion
202 uint32_t reduction =
203 std::min(queue / (uint32_t)gamma.Get(), segCwnd >> (uint32_t)epsilon.Get());
204 segCwnd -= reduction;
205 segCwnd = std::max(segCwnd, m_renoCount);
206 m_cWnd = segCwnd * m_segmentSize;
208 NS_LOG_INFO("In Slow mode, after precautionary decongestion, "
209 "updated to cwnd "
210 << m_cWnd << " ssthresh " << m_ssThresh);
211 }
212 }
213 }
214 }
215}
216
224{
225 public:
238 uint32_t ssThresh,
240 SequenceNumber32 nextTxSeq,
241 SequenceNumber32 lastAckedSeq,
242 Time minRtt,
243 UintegerValue rho,
244 const std::string& name);
245
246 private:
247 void DoRun() override;
254
265};
266
268 uint32_t ssThresh,
270 SequenceNumber32 nextTxSeq,
271 SequenceNumber32 lastAckedSeq,
272 Time minRtt,
273 UintegerValue rho,
274 const std::string& name)
275 : TestCase(name),
276 m_cWnd(cWnd),
277 m_ssThresh(ssThresh),
278 m_segmentSize(segmentSize),
279 m_doingRenoNow(0),
280 m_nextTxSeq(nextTxSeq),
281 m_lastAckedSeq(lastAckedSeq),
282 m_minRtt(minRtt),
283 m_baseRtt(MilliSeconds(100)),
284 m_segmentsAcked(2),
285 m_rho(rho)
286{
287}
288
289void
291{
292 Ptr<TcpSocketState> state = CreateObject<TcpSocketState>();
293 state->m_cWnd = m_cWnd;
297 state->m_ssThresh = m_ssThresh;
298
299 Ptr<TcpYeah> cong = CreateObject<TcpYeah>();
300
301 // Re-set rho to 1 for this unit test
302 cong->SetAttribute("Rho", UintegerValue(m_rho));
303
304 // Set baseRtt to 100 ms
305 cong->PktsAcked(state, m_segmentsAcked, m_baseRtt);
306
307 // Set minRtt to a different value
308 cong->CongestionStateSet(state, TcpSocketState::CA_OPEN);
309 cong->PktsAcked(state, m_segmentsAcked, m_minRtt);
310
311 // 2 more calls to PktsAcked to increment cntRtt beyond 2
312 cong->PktsAcked(state, m_segmentsAcked, m_minRtt);
313 cong->PktsAcked(state, m_segmentsAcked, m_minRtt);
314
315 // Calculate queue backlog
316 cong->IncreaseWindow(state, m_segmentsAcked);
317
318 // Now get the value of ssThresh
319 uint32_t ssThresh = cong->GetSsThresh(state, m_cWnd);
320
321 // Our calculation of ssThresh
322 uint32_t ssThreshVal = CalculateSsThresh(cong);
323
324 NS_TEST_ASSERT_MSG_EQ(ssThresh, ssThreshVal, "SsThresh has not updated correctly");
325}
326
329{
330 // Calculate queue backlog
331 uint32_t segCwnd = m_cWnd / m_segmentSize;
332 uint32_t reduction;
333
334 UintegerValue delta;
335 cong->GetAttribute("Delta", delta);
336
337 Time rttQueue = m_minRtt - m_baseRtt;
338
339 // queue = rttQueue * bw = rttQueue * (cwnd/RTTmin)
340 double bw = segCwnd / m_minRtt.GetSeconds();
341 uint32_t queue = bw * rttQueue.GetSeconds();
342
343 NS_LOG_LOGIC("queue backlog" << queue);
344
345 if (m_doingRenoNow < m_rho.Get())
346 {
347 reduction = std::max(queue, segCwnd >> delta.Get());
348 reduction = std::min(reduction, std::max(segCwnd >> 1, (uint32_t)2));
349 NS_LOG_INFO("Reduction amount for yeah upon loss = " << reduction);
350 }
351 else
352 {
353 reduction = std::max(segCwnd >> 1, (uint32_t)2);
354 NS_LOG_INFO("Reduction amount for reno upon loss = " << reduction);
355 }
356
357 return (m_cWnd - (reduction * m_segmentSize));
358}
359
367{
368 public:
370 : TestSuite("tcp-yeah-test", UNIT)
371 {
372 AddTestCase(new TcpYeahIncrementTest(20 * 1446,
373 25 * 1446,
374 1446,
375 SequenceNumber32(2893),
376 SequenceNumber32(1447),
377 1,
378 MilliSeconds(105),
379 "YeAH test on cWnd when in slow start"),
380 TestCase::QUICK);
381 AddTestCase(new TcpYeahIncrementTest(30 * 1446,
382 25 * 1446,
383 1446,
384 SequenceNumber32(2893),
385 SequenceNumber32(1447),
386 30,
387 MilliSeconds(105),
388 "YeAH test on cWnd when in Fast mode"),
389 TestCase::QUICK);
391 40 * 356,
392 30 * 356,
393 356,
394 SequenceNumber32(20761),
395 SequenceNumber32(21117),
396 1,
397 MilliSeconds(120),
398 "YeAH test on cWnd when in slow mode without precautionary decongestion"),
399 TestCase::QUICK);
401 100 * 356,
402 70 * 356,
403 356,
404 SequenceNumber32(20761),
405 SequenceNumber32(21117),
406 1,
407 MilliSeconds(600),
408 "YeAH test on cWnd when in slow mode with precautionary decongestion"),
409 TestCase::QUICK);
411 40 * 1446,
412 30 * 1446,
413 1446,
414 SequenceNumber32(2893),
415 SequenceNumber32(7230),
416 MilliSeconds(120),
417 UintegerValue(0),
418 "YeAH test on ssThresh upon loss while competing with Reno flows"),
419 TestCase::QUICK);
421 57 * 1446,
422 42 * 1446,
423 1446,
424 SequenceNumber32(2893),
425 SequenceNumber32(7230),
426 MilliSeconds(200),
427 UintegerValue(2),
428 "YeAH test on ssThresh upon loss while not competing with Reno flows"),
429 TestCase::QUICK);
430 }
431};
432
#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.
void DoRun() override
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.
void DoRun() override
Implementation to actually run this TestCase.
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.
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:78
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:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:305
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
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:402
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_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#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:1350
Every class exported by the ns3 library is enclosed in the ns3 namespace.
phy
Definition: third.py:82
static TcpYeahTestSuite g_tcpYeahTest
Static variable for test initialization.