A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
tcp-yeah-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2016 ResiliNets, ITTC, University of Kansas
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Truc Anh N. Nguyen <annguyen@ittc.ku.edu>
7 *
8 * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
9 * ResiliNets Research Group https://resilinets.org/
10 * Information and Telecommunication Technology Center (ITTC)
11 * and Department of Electrical Engineering and Computer Science
12 * The University of Kansas Lawrence, KS USA.
13 */
14
15#include "ns3/log.h"
16#include "ns3/tcp-congestion-ops.h"
17#include "ns3/tcp-socket-base.h"
18#include "ns3/tcp-yeah.h"
19#include "ns3/test.h"
20
21using namespace ns3;
22
23NS_LOG_COMPONENT_DEFINE("TcpYeahTestSuite");
24
25/**
26 * @ingroup internet-test
27 *
28 * @brief Testing TcpYeah additive increase algorithm.
29 */
31{
32 public:
33 /**
34 * @brief Constructor.
35 * @param cWnd Congestion window.
36 * @param ssThresh Slow Start Threshold.
37 * @param segmentSize Segment size.
38 * @param nextTxSeq Next Tx sequence number.
39 * @param lastAckedSeq Last ACKed sequence number.
40 * @param segmentsAcked Number of segments ACKed.
41 * @param minRtt Minimum RTT.
42 * @param name Test description.
43 */
45 uint32_t ssThresh,
47 SequenceNumber32 nextTxSeq,
48 SequenceNumber32 lastAckedSeq,
49 uint32_t segmentsAcked,
50 Time minRtt,
51 const std::string& name);
52
53 private:
54 void DoRun() override;
55 /**
56 * @brief Increases the TCP window.
57 * @param cong The congestion control.
58 */
60
61 uint32_t m_cWnd; //!< Congestion window.
62 uint32_t m_ssThresh; //!< Slow Start Threshold.
63 uint32_t m_segmentSize; //!< Segment size.
64 SequenceNumber32 m_nextTxSeq; //!< Next Tx sequence number.
65 SequenceNumber32 m_lastAckedSeq; //!< Last ACKed sequence number.
66 uint32_t m_segmentsAcked; //!< Number of segments ACKed.
67 Time m_baseRtt; //!< Base RTT.
68 Time m_minRtt; //!< Min RTT.
69 uint32_t m_doingRenoNow; //!< TCP Reno fallback.
70 uint32_t m_cntRtt; //!< RTT counter.
71 uint32_t m_renoCount; //!< Reno counter.
72};
73
75 uint32_t ssThresh,
77 SequenceNumber32 nextTxSeq,
78 SequenceNumber32 lastAckedSeq,
79 uint32_t segmentsAcked,
80 Time minRtt,
81 const std::string& name)
82 : TestCase(name),
83 m_cWnd(cWnd),
84 m_ssThresh(ssThresh),
85 m_segmentSize(segmentSize),
86 m_nextTxSeq(nextTxSeq),
87 m_lastAckedSeq(lastAckedSeq),
88 m_segmentsAcked(segmentsAcked),
89 m_baseRtt(MilliSeconds(100)),
90 m_minRtt(minRtt),
91 m_doingRenoNow(0),
92 m_cntRtt(4),
93 m_renoCount(2)
94{
95}
96
97void
99{
101 state->m_cWnd = m_cWnd;
102 state->m_ssThresh = m_ssThresh;
103 state->m_segmentSize = m_segmentSize;
104 state->m_nextTxSequence = m_nextTxSeq;
105 state->m_lastAckedSeq = m_lastAckedSeq;
106 state->m_minRtt = m_minRtt;
107
109
110 // Set baseRtt to 100 ms
111 cong->PktsAcked(state, m_segmentsAcked, m_baseRtt);
112
113 // Reset YeAH to assign a new value of minRtt
114 cong->CongestionStateSet(state, TcpSocketState::CA_OPEN);
115 cong->PktsAcked(state, m_segmentsAcked, m_minRtt);
116
117 // 2 more calls to PktsAcked to increment cntRtt beyond 2
118 cong->PktsAcked(state, m_segmentsAcked, m_minRtt);
119 cong->PktsAcked(state, m_segmentsAcked, m_minRtt);
120
121 cong->IncreaseWindow(state, m_segmentsAcked);
122 IncreaseWindow(cong);
123
124 NS_TEST_ASSERT_MSG_EQ(state->m_cWnd.Get(), m_cWnd, "CWnd has not updated correctly");
125}
126
127void
129{
130 uint32_t segCwnd = m_cWnd / m_segmentSize;
131
132 if (m_cWnd < m_ssThresh)
133 { // NewReno slow start
134 if (m_segmentsAcked >= 1)
135 {
137 m_segmentsAcked -= 1;
138 NS_LOG_INFO("In SlowStart, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
139 }
140 }
141 else if (!m_doingRenoNow)
142 { // Fast mode, follow STCP increment rule
143 UintegerValue aiFactor;
144 cong->GetAttribute("StcpAiFactor", aiFactor);
145 uint32_t w = std::min(segCwnd, (uint32_t)aiFactor.Get());
146 uint32_t delta = m_segmentsAcked / w;
147 m_cWnd += delta * m_segmentSize;
148 NS_LOG_INFO("In Fast mode, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
149 }
150 else
151 { // NewReno congestion avoidance
152 if (m_segmentsAcked > 0)
153 {
154 double adder = static_cast<double>(m_segmentSize * m_segmentSize) / m_cWnd;
155 adder = std::max(1.0, adder);
156 m_cWnd += static_cast<uint32_t>(adder);
157 NS_LOG_INFO("In CongAvoid, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
158 }
159 }
161 {
162 if (m_cntRtt > 2)
163 {
164 /*
165 * Calculate the extra number of packets in queue
166 */
167 Time rttQueue = m_minRtt - m_baseRtt;
168 double bw = segCwnd / m_minRtt.GetSeconds();
169 uint32_t queue = bw * rttQueue.GetSeconds();
170
171 // Calculate network congestion level
172 double L = rttQueue.GetSeconds() / m_baseRtt.GetSeconds();
173
174 UintegerValue alpha;
175 cong->GetAttribute("Alpha", alpha);
176 UintegerValue phy;
177 cong->GetAttribute("Phy", phy);
178 UintegerValue gamma;
179 cong->GetAttribute("Gamma", gamma);
181 cong->GetAttribute("Epsilon", epsilon);
182 UintegerValue zeta;
183 cong->GetAttribute("Zeta", zeta);
184
185 if (queue > alpha.Get() || L > (1 / phy.Get()))
186 { // Slow mode
187 NS_LOG_INFO("Enter Slow mode");
188 if (queue > alpha.Get() && segCwnd > m_renoCount)
189 { // Precautionary decongestion
190 uint32_t reduction =
191 std::min(queue / (uint32_t)gamma.Get(), segCwnd >> (uint32_t)epsilon.Get());
192 segCwnd -= reduction;
193 segCwnd = std::max(segCwnd, m_renoCount);
194 m_cWnd = segCwnd * m_segmentSize;
196 NS_LOG_INFO("In Slow mode, after precautionary decongestion, "
197 "updated to cwnd "
198 << m_cWnd << " ssthresh " << m_ssThresh);
199 }
200 }
201 }
202 }
203}
204
205/**
206 * @ingroup internet-test
207 *
208 * @brief Testing TcpYeah multiplicative decrease algorithm
209 */
211{
212 public:
213 /**
214 * @brief Constructor.
215 * @param cWnd Congestion window.
216 * @param ssThresh Slow Start Threshold.
217 * @param segmentSize Segment size.
218 * @param nextTxSeq Next Tx sequence number.
219 * @param lastAckedSeq Last ACKed sequence number.
220 * @param minRtt Minimum RTT.
221 * @param rho TCP Yeah rho param.
222 * @param name Test description.
223 */
225 uint32_t ssThresh,
227 SequenceNumber32 nextTxSeq,
228 SequenceNumber32 lastAckedSeq,
229 Time minRtt,
230 UintegerValue rho,
231 const std::string& name);
232
233 private:
234 void DoRun() override;
235 /**
236 * @brief Calculate the Slow Start threshold.
237 * @param cong The TCP state.
238 * @returns The SshThreshold.
239 */
241
242 uint32_t m_cWnd; //!< Congestion window.
243 uint32_t m_ssThresh; //!< Slow Start Threshold.
244 uint32_t m_segmentSize; //!< Segment size.
245 uint32_t m_doingRenoNow; //!< TCP Reno fallback.
246 SequenceNumber32 m_nextTxSeq; //!< Next Tx sequence number.
247 SequenceNumber32 m_lastAckedSeq; //!< Last ACKed sequence number.
248 Time m_minRtt; //!< Min RTT.
249 Time m_baseRtt; //!< Base RTT.
250 uint32_t m_segmentsAcked; //!< Number of segments ACKed.
251 UintegerValue m_rho; //!< TCP Yeah rho param.
252};
253
255 uint32_t ssThresh,
257 SequenceNumber32 nextTxSeq,
258 SequenceNumber32 lastAckedSeq,
259 Time minRtt,
260 UintegerValue rho,
261 const std::string& name)
262 : TestCase(name),
263 m_cWnd(cWnd),
264 m_ssThresh(ssThresh),
265 m_segmentSize(segmentSize),
266 m_doingRenoNow(0),
267 m_nextTxSeq(nextTxSeq),
268 m_lastAckedSeq(lastAckedSeq),
269 m_minRtt(minRtt),
270 m_baseRtt(MilliSeconds(100)),
271 m_segmentsAcked(2),
272 m_rho(rho)
273{
274}
275
276void
278{
280 state->m_cWnd = m_cWnd;
281 state->m_nextTxSequence = m_nextTxSeq;
282 state->m_lastAckedSeq = m_lastAckedSeq;
283 state->m_segmentSize = m_segmentSize;
284 state->m_ssThresh = m_ssThresh;
285
287
288 // Re-set rho to 1 for this unit test
289 cong->SetAttribute("Rho", UintegerValue(m_rho));
290
291 // Set baseRtt to 100 ms
292 cong->PktsAcked(state, m_segmentsAcked, m_baseRtt);
293
294 // Set minRtt to a different value
295 cong->CongestionStateSet(state, TcpSocketState::CA_OPEN);
296 cong->PktsAcked(state, m_segmentsAcked, m_minRtt);
297
298 // 2 more calls to PktsAcked to increment cntRtt beyond 2
299 cong->PktsAcked(state, m_segmentsAcked, m_minRtt);
300 cong->PktsAcked(state, m_segmentsAcked, m_minRtt);
301
302 // Calculate queue backlog
303 cong->IncreaseWindow(state, m_segmentsAcked);
304
305 // Now get the value of ssThresh
306 uint32_t ssThresh = cong->GetSsThresh(state, m_cWnd);
307
308 // Our calculation of ssThresh
309 uint32_t ssThreshVal = CalculateSsThresh(cong);
310
311 NS_TEST_ASSERT_MSG_EQ(ssThresh, ssThreshVal, "SsThresh has not updated correctly");
312}
313
316{
317 // Calculate queue backlog
318 uint32_t segCwnd = m_cWnd / m_segmentSize;
319 uint32_t reduction;
320
321 UintegerValue delta;
322 cong->GetAttribute("Delta", delta);
323
324 Time rttQueue = m_minRtt - m_baseRtt;
325
326 // queue = rttQueue * bw = rttQueue * (cwnd/RTTmin)
327 double bw = segCwnd / m_minRtt.GetSeconds();
328 uint32_t queue = bw * rttQueue.GetSeconds();
329
330 NS_LOG_LOGIC("queue backlog" << queue);
331
332 if (m_doingRenoNow < m_rho.Get())
333 {
334 reduction = std::max(queue, segCwnd >> delta.Get());
335 reduction = std::min(reduction, std::max(segCwnd >> 1, (uint32_t)2));
336 NS_LOG_INFO("Reduction amount for yeah upon loss = " << reduction);
337 }
338 else
339 {
340 reduction = std::max(segCwnd >> 1, (uint32_t)2);
341 NS_LOG_INFO("Reduction amount for reno upon loss = " << reduction);
342 }
343
344 return (m_cWnd - (reduction * m_segmentSize));
345}
346
347/**
348 * @ingroup internet-test
349 *
350 * @brief TCP Yeah TestSuite
351 */
353{
354 public:
356 : TestSuite("tcp-yeah-test", Type::UNIT)
357 {
358 AddTestCase(new TcpYeahIncrementTest(20 * 1446,
359 25 * 1446,
360 1446,
361 SequenceNumber32(2893),
362 SequenceNumber32(1447),
363 1,
364 MilliSeconds(105),
365 "YeAH test on cWnd when in slow start"),
366 TestCase::Duration::QUICK);
367 AddTestCase(new TcpYeahIncrementTest(30 * 1446,
368 25 * 1446,
369 1446,
370 SequenceNumber32(2893),
371 SequenceNumber32(1447),
372 30,
373 MilliSeconds(105),
374 "YeAH test on cWnd when in Fast mode"),
375 TestCase::Duration::QUICK);
377 40 * 356,
378 30 * 356,
379 356,
380 SequenceNumber32(20761),
381 SequenceNumber32(21117),
382 1,
383 MilliSeconds(120),
384 "YeAH test on cWnd when in slow mode without precautionary decongestion"),
385 TestCase::Duration::QUICK);
387 100 * 356,
388 70 * 356,
389 356,
390 SequenceNumber32(20761),
391 SequenceNumber32(21117),
392 1,
393 MilliSeconds(600),
394 "YeAH test on cWnd when in slow mode with precautionary decongestion"),
395 TestCase::Duration::QUICK);
397 40 * 1446,
398 30 * 1446,
399 1446,
400 SequenceNumber32(2893),
401 SequenceNumber32(7230),
402 MilliSeconds(120),
403 UintegerValue(0),
404 "YeAH test on ssThresh upon loss while competing with Reno flows"),
405 TestCase::Duration::QUICK);
407 57 * 1446,
408 42 * 1446,
409 1446,
410 SequenceNumber32(2893),
411 SequenceNumber32(7230),
412 MilliSeconds(200),
413 UintegerValue(2),
414 "YeAH test on ssThresh upon loss while not competing with Reno flows"),
415 TestCase::Duration::QUICK);
416 }
417};
418
419static TcpYeahTestSuite g_tcpYeahTest; //!< Static variable for test initialization
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.
uint32_t m_cntRtt
RTT counter.
TCP Yeah TestSuite.
Smart pointer class similar to boost::intrusive_ptr.
@ CA_OPEN
Normal state, no dubious events.
encapsulates test code
Definition test.h:1050
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
static constexpr auto UNIT
Definition test.h:1291
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:392
Hold an unsigned integer type.
Definition uinteger.h:34
uint64_t Get() const
Definition uinteger.cc:26
uint32_t segmentSize
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
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:134
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1356
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static TcpYeahTestSuite g_tcpYeahTest
Static variable for test initialization.