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 * 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
36/**
37 * \ingroup internet-test
38 *
39 * \brief Testing TcpYeah additive increase algorithm.
40 */
42{
43 public:
44 /**
45 * \brief Constructor.
46 * \param cWnd Congestion window.
47 * \param ssThresh Slow Start Threshold.
48 * \param segmentSize Segment size.
49 * \param nextTxSeq Next Tx sequence number.
50 * \param lastAckedSeq Last ACKed sequence number.
51 * \param segmentsAcked Number of segments ACKed.
52 * \param minRtt Minimum RTT.
53 * \param name Test description.
54 */
56 uint32_t ssThresh,
58 SequenceNumber32 nextTxSeq,
59 SequenceNumber32 lastAckedSeq,
60 uint32_t segmentsAcked,
61 Time minRtt,
62 const std::string& name);
63
64 private:
65 void DoRun() override;
66 /**
67 * \brief Increases the TCP window.
68 * \param cong The congestion control.
69 */
71
72 uint32_t m_cWnd; //!< Congestion window.
73 uint32_t m_ssThresh; //!< Slow Start Threshold.
74 uint32_t m_segmentSize; //!< Segment size.
75 SequenceNumber32 m_nextTxSeq; //!< Next Tx sequence number.
76 SequenceNumber32 m_lastAckedSeq; //!< Last ACKed sequence number.
77 uint32_t m_segmentsAcked; //!< Number of segments ACKed.
78 Time m_baseRtt; //!< Base RTT.
79 Time m_minRtt; //!< Min RTT.
80 uint32_t m_doingRenoNow; //!< TCP Reno fallback.
81 uint32_t m_cntRtt; //!< RTT counter.
82 uint32_t m_renoCount; //!< Reno counter.
83};
84
86 uint32_t ssThresh,
88 SequenceNumber32 nextTxSeq,
89 SequenceNumber32 lastAckedSeq,
90 uint32_t segmentsAcked,
91 Time minRtt,
92 const std::string& name)
93 : TestCase(name),
94 m_cWnd(cWnd),
95 m_ssThresh(ssThresh),
96 m_segmentSize(segmentSize),
97 m_nextTxSeq(nextTxSeq),
98 m_lastAckedSeq(lastAckedSeq),
99 m_segmentsAcked(segmentsAcked),
100 m_baseRtt(MilliSeconds(100)),
101 m_minRtt(minRtt),
102 m_doingRenoNow(0),
103 m_cntRtt(4),
104 m_renoCount(2)
105{
106}
107
108void
110{
111 Ptr<TcpSocketState> state = CreateObject<TcpSocketState>();
112 state->m_cWnd = m_cWnd;
113 state->m_ssThresh = m_ssThresh;
114 state->m_segmentSize = m_segmentSize;
115 state->m_nextTxSequence = m_nextTxSeq;
116 state->m_lastAckedSeq = m_lastAckedSeq;
117 state->m_minRtt = m_minRtt;
118
119 Ptr<TcpYeah> cong = CreateObject<TcpYeah>();
120
121 // Set baseRtt to 100 ms
122 cong->PktsAcked(state, m_segmentsAcked, m_baseRtt);
123
124 // Reset YeAH to assign a new value of minRtt
125 cong->CongestionStateSet(state, TcpSocketState::CA_OPEN);
126 cong->PktsAcked(state, m_segmentsAcked, m_minRtt);
127
128 // 2 more calls to PktsAcked to increment cntRtt beyond 2
129 cong->PktsAcked(state, m_segmentsAcked, m_minRtt);
130 cong->PktsAcked(state, m_segmentsAcked, m_minRtt);
131
132 cong->IncreaseWindow(state, m_segmentsAcked);
133 IncreaseWindow(cong);
134
135 NS_TEST_ASSERT_MSG_EQ(state->m_cWnd.Get(), m_cWnd, "CWnd has not updated correctly");
136}
137
138void
140{
141 uint32_t segCwnd = m_cWnd / m_segmentSize;
142
143 if (m_cWnd < m_ssThresh)
144 { // NewReno slow start
145 if (m_segmentsAcked >= 1)
146 {
148 m_segmentsAcked -= 1;
149 NS_LOG_INFO("In SlowStart, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
150 }
151 }
152 else if (!m_doingRenoNow)
153 { // Fast mode, follow STCP increment rule
154 UintegerValue aiFactor;
155 cong->GetAttribute("StcpAiFactor", aiFactor);
156 uint32_t w = std::min(segCwnd, (uint32_t)aiFactor.Get());
157 uint32_t delta = m_segmentsAcked / w;
158 m_cWnd += delta * m_segmentSize;
159 NS_LOG_INFO("In Fast mode, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
160 }
161 else
162 { // NewReno congestion avoidance
163 if (m_segmentsAcked > 0)
164 {
165 double adder = static_cast<double>(m_segmentSize * m_segmentSize) / m_cWnd;
166 adder = std::max(1.0, adder);
167 m_cWnd += static_cast<uint32_t>(adder);
168 NS_LOG_INFO("In CongAvoid, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
169 }
170 }
172 {
173 if (m_cntRtt > 2)
174 {
175 /*
176 * Calculate the extra number of packets in queue
177 */
178 Time rttQueue = m_minRtt - m_baseRtt;
179 double bw = segCwnd / m_minRtt.GetSeconds();
180 uint32_t queue = bw * rttQueue.GetSeconds();
181
182 // Calculate network congestion level
183 double L = rttQueue.GetSeconds() / m_baseRtt.GetSeconds();
184
185 UintegerValue alpha;
186 cong->GetAttribute("Alpha", alpha);
187 UintegerValue phy;
188 cong->GetAttribute("Phy", phy);
189 UintegerValue gamma;
190 cong->GetAttribute("Gamma", gamma);
192 cong->GetAttribute("Epsilon", epsilon);
193 UintegerValue zeta;
194 cong->GetAttribute("Zeta", zeta);
195
196 if (queue > alpha.Get() || L > (1 / phy.Get()))
197 { // Slow mode
198 NS_LOG_INFO("Enter Slow mode");
199 if (queue > alpha.Get() && segCwnd > m_renoCount)
200 { // Precautionary decongestion
201 uint32_t reduction =
202 std::min(queue / (uint32_t)gamma.Get(), segCwnd >> (uint32_t)epsilon.Get());
203 segCwnd -= reduction;
204 segCwnd = std::max(segCwnd, m_renoCount);
205 m_cWnd = segCwnd * m_segmentSize;
207 NS_LOG_INFO("In Slow mode, after precautionary decongestion, "
208 "updated to cwnd "
209 << m_cWnd << " ssthresh " << m_ssThresh);
210 }
211 }
212 }
213 }
214}
215
216/**
217 * \ingroup internet-test
218 *
219 * \brief Testing TcpYeah multiplicative decrease algorithm
220 */
222{
223 public:
224 /**
225 * \brief Constructor.
226 * \param cWnd Congestion window.
227 * \param ssThresh Slow Start Threshold.
228 * \param segmentSize Segment size.
229 * \param nextTxSeq Next Tx sequence number.
230 * \param lastAckedSeq Last ACKed sequence number.
231 * \param minRtt Minimum RTT.
232 * \param rho TCP Yeah rho param.
233 * \param name Test description.
234 */
236 uint32_t ssThresh,
238 SequenceNumber32 nextTxSeq,
239 SequenceNumber32 lastAckedSeq,
240 Time minRtt,
241 UintegerValue rho,
242 const std::string& name);
243
244 private:
245 void DoRun() override;
246 /**
247 * \brief Calculate the Slow Start threshold.
248 * \param cong The TCP state.
249 * \returns The SshThreshold.
250 */
252
253 uint32_t m_cWnd; //!< Congestion window.
254 uint32_t m_ssThresh; //!< Slow Start Threshold.
255 uint32_t m_segmentSize; //!< Segment size.
256 uint32_t m_doingRenoNow; //!< TCP Reno fallback.
257 SequenceNumber32 m_nextTxSeq; //!< Next Tx sequence number.
258 SequenceNumber32 m_lastAckedSeq; //!< Last ACKed sequence number.
259 Time m_minRtt; //!< Min RTT.
260 Time m_baseRtt; //!< Base RTT.
261 uint32_t m_segmentsAcked; //!< Number of segments ACKed.
262 UintegerValue m_rho; //!< TCP Yeah rho param.
263};
264
266 uint32_t ssThresh,
268 SequenceNumber32 nextTxSeq,
269 SequenceNumber32 lastAckedSeq,
270 Time minRtt,
271 UintegerValue rho,
272 const std::string& name)
273 : TestCase(name),
274 m_cWnd(cWnd),
275 m_ssThresh(ssThresh),
276 m_segmentSize(segmentSize),
277 m_doingRenoNow(0),
278 m_nextTxSeq(nextTxSeq),
279 m_lastAckedSeq(lastAckedSeq),
280 m_minRtt(minRtt),
281 m_baseRtt(MilliSeconds(100)),
282 m_segmentsAcked(2),
283 m_rho(rho)
284{
285}
286
287void
289{
290 Ptr<TcpSocketState> state = CreateObject<TcpSocketState>();
291 state->m_cWnd = m_cWnd;
292 state->m_nextTxSequence = m_nextTxSeq;
293 state->m_lastAckedSeq = m_lastAckedSeq;
294 state->m_segmentSize = m_segmentSize;
295 state->m_ssThresh = m_ssThresh;
296
297 Ptr<TcpYeah> cong = CreateObject<TcpYeah>();
298
299 // Re-set rho to 1 for this unit test
300 cong->SetAttribute("Rho", UintegerValue(m_rho));
301
302 // Set baseRtt to 100 ms
303 cong->PktsAcked(state, m_segmentsAcked, m_baseRtt);
304
305 // Set minRtt to a different value
306 cong->CongestionStateSet(state, TcpSocketState::CA_OPEN);
307 cong->PktsAcked(state, m_segmentsAcked, m_minRtt);
308
309 // 2 more calls to PktsAcked to increment cntRtt beyond 2
310 cong->PktsAcked(state, m_segmentsAcked, m_minRtt);
311 cong->PktsAcked(state, m_segmentsAcked, m_minRtt);
312
313 // Calculate queue backlog
314 cong->IncreaseWindow(state, m_segmentsAcked);
315
316 // Now get the value of ssThresh
317 uint32_t ssThresh = cong->GetSsThresh(state, m_cWnd);
318
319 // Our calculation of ssThresh
320 uint32_t ssThreshVal = CalculateSsThresh(cong);
321
322 NS_TEST_ASSERT_MSG_EQ(ssThresh, ssThreshVal, "SsThresh has not updated correctly");
323}
324
327{
328 // Calculate queue backlog
329 uint32_t segCwnd = m_cWnd / m_segmentSize;
330 uint32_t reduction;
331
332 UintegerValue delta;
333 cong->GetAttribute("Delta", delta);
334
335 Time rttQueue = m_minRtt - m_baseRtt;
336
337 // queue = rttQueue * bw = rttQueue * (cwnd/RTTmin)
338 double bw = segCwnd / m_minRtt.GetSeconds();
339 uint32_t queue = bw * rttQueue.GetSeconds();
340
341 NS_LOG_LOGIC("queue backlog" << queue);
342
343 if (m_doingRenoNow < m_rho.Get())
344 {
345 reduction = std::max(queue, segCwnd >> delta.Get());
346 reduction = std::min(reduction, std::max(segCwnd >> 1, (uint32_t)2));
347 NS_LOG_INFO("Reduction amount for yeah upon loss = " << reduction);
348 }
349 else
350 {
351 reduction = std::max(segCwnd >> 1, (uint32_t)2);
352 NS_LOG_INFO("Reduction amount for reno upon loss = " << reduction);
353 }
354
355 return (m_cWnd - (reduction * m_segmentSize));
356}
357
358/**
359 * \ingroup internet-test
360 *
361 * \brief TCP Yeah TestSuite
362 */
364{
365 public:
367 : TestSuite("tcp-yeah-test", Type::UNIT)
368 {
369 AddTestCase(new TcpYeahIncrementTest(20 * 1446,
370 25 * 1446,
371 1446,
372 SequenceNumber32(2893),
373 SequenceNumber32(1447),
374 1,
375 MilliSeconds(105),
376 "YeAH test on cWnd when in slow start"),
377 TestCase::Duration::QUICK);
378 AddTestCase(new TcpYeahIncrementTest(30 * 1446,
379 25 * 1446,
380 1446,
381 SequenceNumber32(2893),
382 SequenceNumber32(1447),
383 30,
384 MilliSeconds(105),
385 "YeAH test on cWnd when in Fast mode"),
386 TestCase::Duration::QUICK);
388 40 * 356,
389 30 * 356,
390 356,
391 SequenceNumber32(20761),
392 SequenceNumber32(21117),
393 1,
394 MilliSeconds(120),
395 "YeAH test on cWnd when in slow mode without precautionary decongestion"),
396 TestCase::Duration::QUICK);
398 100 * 356,
399 70 * 356,
400 356,
401 SequenceNumber32(20761),
402 SequenceNumber32(21117),
403 1,
404 MilliSeconds(600),
405 "YeAH test on cWnd when in slow mode with precautionary decongestion"),
406 TestCase::Duration::QUICK);
408 40 * 1446,
409 30 * 1446,
410 1446,
411 SequenceNumber32(2893),
412 SequenceNumber32(7230),
413 MilliSeconds(120),
414 UintegerValue(0),
415 "YeAH test on ssThresh upon loss while competing with Reno flows"),
416 TestCase::Duration::QUICK);
418 57 * 1446,
419 42 * 1446,
420 1446,
421 SequenceNumber32(2893),
422 SequenceNumber32(7230),
423 MilliSeconds(200),
424 UintegerValue(2),
425 "YeAH test on ssThresh upon loss while not competing with Reno flows"),
426 TestCase::Duration::QUICK);
427 }
428};
429
430static 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.
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:77
@ CA_OPEN
Normal state, no dubious events.
encapsulates test code
Definition: test.h:1061
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1268
Type
Type of test.
Definition: test.h:1275
static constexpr auto UNIT
Definition: test.h:1286
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:403
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:145
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 TcpYeahTestSuite g_tcpYeahTest
Static variable for test initialization.