A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
tcp-pacing-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 NITK Surathkal
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 * Authors: Deepak Kumaraswamy <deepakkavoor99@gmail.com>
18 *
19 */
20#include "tcp-general-test.h"
21
22#include "ns3/config.h"
23#include "ns3/log.h"
24#include "ns3/simple-channel.h"
25#include "ns3/test.h"
26
27using namespace ns3;
28
29NS_LOG_COMPONENT_DEFINE("TcpPacingTestSuite");
30
90{
91 public:
107 uint32_t packets,
108 uint16_t pacingSsRatio,
109 uint16_t pacingCaRatio,
110 uint32_t ssThresh,
111 bool paceInitialWindow,
112 uint32_t delAckMaxCount,
113 const TypeId& congControl,
114 const std::string& desc);
115
116 protected:
117 void CWndTrace(uint32_t oldValue, uint32_t newValue) override;
118 void RttTrace(Time oldTime, Time newTime) override;
119 void BytesInFlightTrace(uint32_t oldValue, uint32_t newValue) override;
120 void Tx(const Ptr<const Packet> p, const TcpHeader& h, SocketWho who) override;
121 void Rx(const Ptr<const Packet> p, const TcpHeader& h, SocketWho who) override;
122 void QueueDrop(SocketWho who) override;
123 void PhyDrop(SocketWho who) override;
124 void NormalClose(SocketWho who) override;
125
129 virtual void UpdateExpectedInterval();
130
131 void ConfigureEnvironment() override;
132 void ConfigureProperties() override;
133
134 private:
160};
161
164 uint32_t packets,
165 uint16_t pacingSsRatio,
166 uint16_t pacingCaRatio,
167 uint32_t ssThresh,
168 bool paceInitialWindow,
169 uint32_t delAckMaxCount,
170 const TypeId& typeId,
171 const std::string& desc)
172 : TcpGeneralTest(desc),
173 m_segmentSize(segmentSize),
174 m_packetSize(packetSize),
175 m_packets(packets),
176 m_initial(true),
177 m_initialCwnd(10),
178 m_curCwnd(0),
179 m_isFullCwndSent(true),
180 m_bytesInFlight(0),
181 m_prevTxTime(0),
182 m_pacingSsRatio(pacingSsRatio),
183 m_pacingCaRatio(pacingCaRatio),
184 m_ssThresh(ssThresh),
185 m_paceInitialWindow(paceInitialWindow),
186 m_delAckMaxCount(delAckMaxCount),
187 m_isConnAboutToEnd(false),
188 m_transmissionStartTime(Seconds(0)),
189 m_expectedInterval(Seconds(0)),
190 m_packetsSent(0),
191 m_nextPacketInterval(Seconds(0)),
192 m_tracedRtt(Seconds(0))
193{
194 m_congControlTypeId = typeId;
195}
196
197void
199{
204 SetMTU(1500);
207}
208
209void
211{
216 SetPacingStatus(SENDER, true);
219 NS_LOG_DEBUG("segSize: " << m_segmentSize << " ssthresh: " << m_ssThresh
220 << " paceInitialWindow: " << m_paceInitialWindow << " delAckMaxCount "
222}
223
224void
226{
227 NS_LOG_FUNCTION(this << oldTime << newTime);
228 m_tracedRtt = newTime;
230}
231
232void
234{
235 NS_LOG_FUNCTION(this << oldValue << newValue);
236 m_curCwnd = newValue;
237 if (m_initial)
238 {
239 m_initial = false;
240 }
241 // CWndTrace () is called after Rx ()
242 // Therefore, call UpdateExpectedInterval () here instead of in Rx ()
244}
245
246void
248{
249 m_bytesInFlight = newValue;
250}
251
252void
254{
255 double_t factor;
256 Time rtt = 2 * GetPropagationDelay();
257 if (m_curCwnd < m_ssThresh / 2)
258 {
259 factor = static_cast<double>(m_pacingSsRatio) / 100;
260 }
261 else
262 {
263 factor = static_cast<double>(m_pacingCaRatio) / 100;
264 }
265
267 {
268 // If initial cwnd is not paced, we expect packet pacing interval to be zero
270 }
271 else
272 {
273 // Use the estimate according to update equation
276 }
277}
278
279void
281{
282 if (who == SENDER)
283 {
284 uint8_t flags = h.GetFlags();
285 uint8_t hasFin = flags & TcpHeader::FIN;
286 uint8_t hasAck = flags & TcpHeader::ACK;
287 if (hasFin && hasAck)
288 {
289 m_isConnAboutToEnd = true;
290 NS_LOG_DEBUG("Sender received a FIN/ACK packet");
291 }
292 else
293 {
294 m_isConnAboutToEnd = false;
295 NS_LOG_DEBUG("Sender received an ACK packet");
296 }
297 }
298}
299
300void
302{
303 NS_LOG_FUNCTION(this << p << h << who);
304
305 if (who == SENDER)
306 {
308 // Start pacing checks from the second data packet onwards because
309 // an interval to check does not exist for the first data packet.
310 // The first two (non-data) packets correspond to SYN and an
311 // empty ACK, respectively, so start checking after three packets are sent
312 bool beyondInitialDataSegment = (m_packetsSent > 3);
313 Time actualInterval = Simulator::Now() - m_prevTxTime;
314 NS_LOG_DEBUG("TX sent: packetsSent: " << m_packetsSent << " fullCwnd: " << m_isFullCwndSent
315 << " nearEnd: " << m_isConnAboutToEnd
316 << " beyondInitialDataSegment "
317 << beyondInitialDataSegment);
318 if (!m_isFullCwndSent && !m_isConnAboutToEnd && beyondInitialDataSegment)
319 {
320 // Consider a small error margin, and ensure that the actual and expected intervals lie
321 // within this error
322 Time errorMargin = NanoSeconds(10);
324 std::abs((actualInterval - m_nextPacketInterval).GetSeconds()),
325 errorMargin.GetSeconds(),
326 "Packet delivery in slow start didn't match pacing rate");
327 NS_LOG_DEBUG("Pacing Check: interval (s): "
328 << actualInterval.GetSeconds() << " expected interval (s): "
329 << m_nextPacketInterval.GetSeconds() << " difference (s): "
330 << std::abs((actualInterval - m_nextPacketInterval).GetSeconds())
331 << " errorMargin (s): " << errorMargin.GetSeconds());
332 }
333
335 // bytesInFlight isn't updated yet. Its trace is called after Tx
336 // so add an additional m_segmentSize to bytesInFlight
337 uint32_t soonBytesInFlight = m_bytesInFlight + m_segmentSize;
338 bool canPacketBeSent = ((m_curCwnd - soonBytesInFlight) >= m_segmentSize);
339 m_isFullCwndSent = (!canPacketBeSent || m_curCwnd == 0);
341 NS_LOG_DEBUG("Next expected interval (s): " << m_nextPacketInterval.GetSeconds());
342 }
343}
344
345void
347{
348 NS_FATAL_ERROR("Drop on the queue; cannot validate congestion avoidance");
349}
350
351void
353{
354 NS_FATAL_ERROR("Drop on the phy: cannot validate congestion avoidance");
355}
356
357void
359{
360 if (who == SENDER)
361 {
362 m_event.Cancel();
363 }
364}
365
372{
373 public:
375 : TestSuite("tcp-pacing-test", UNIT)
376 {
377 uint16_t pacingSsRatio = 200;
378 uint16_t pacingCaRatio = 120;
379 uint32_t segmentSize = 1000;
380 uint32_t packetSize = 1000;
381 uint32_t numPackets = 40;
382 uint32_t delAckMaxCount = 1;
384 uint32_t ssThresh = 1e9; // default large value
385 bool paceInitialWindow = false;
386 std::string description;
387
388 description = std::string("Pacing case 1: Slow start only, no initial pacing");
391 numPackets,
392 pacingSsRatio,
393 pacingCaRatio,
394 ssThresh,
395 paceInitialWindow,
396 delAckMaxCount,
397 tid,
398 description),
400
401 paceInitialWindow = true;
402 description = std::string("Pacing case 2: Slow start only, initial pacing");
405 numPackets,
406 pacingSsRatio,
407 pacingCaRatio,
408 ssThresh,
409 paceInitialWindow,
410 delAckMaxCount,
411 tid,
412 description),
414
415 // set ssThresh to some smaller value to check that pacing
416 // slows down in second half of slow start, then transitions to CA
417 description = std::string("Pacing case 3: Slow start, followed by transition to Congestion "
418 "avoidance, no initial pacing");
419 paceInitialWindow = false;
420 ssThresh = 40;
421 numPackets = 60;
424 numPackets,
425 pacingSsRatio,
426 pacingCaRatio,
427 ssThresh,
428 paceInitialWindow,
429 delAckMaxCount,
430 tid,
431 description),
433
434 // Repeat tests, but with more typical delAckMaxCount == 2
435 delAckMaxCount = 2;
436 paceInitialWindow = false;
437 ssThresh = 1e9;
438 numPackets = 40;
439 description =
440 std::string("Pacing case 4: Slow start only, no initial pacing, delayed ACKs");
443 numPackets,
444 pacingSsRatio,
445 pacingCaRatio,
446 ssThresh,
447 paceInitialWindow,
448 delAckMaxCount,
449 tid,
450 description),
452
453 paceInitialWindow = true;
454 description = std::string("Pacing case 5: Slow start only, initial pacing, delayed ACKs");
457 numPackets,
458 pacingSsRatio,
459 pacingCaRatio,
460 ssThresh,
461 paceInitialWindow,
462 delAckMaxCount,
463 tid,
464 description),
466
467 description = std::string("Pacing case 6: Slow start, followed by transition to Congestion "
468 "avoidance, no initial pacing, delayed ACKs");
469 paceInitialWindow = false;
470 ssThresh = 40;
471 numPackets = 60;
474 numPackets,
475 pacingSsRatio,
476 pacingCaRatio,
477 ssThresh,
478 paceInitialWindow,
479 delAckMaxCount,
480 tid,
481 description),
483 }
484};
485
Test the behavior of TCP pacing.
uint32_t m_initialCwnd
Initial value of cWnd.
void CWndTrace(uint32_t oldValue, uint32_t newValue) override
Tracks the congestion window changes.
uint16_t m_pacingSsRatio
Pacing factor during Slow Start.
void ConfigureProperties() override
Change the configuration of the socket properties.
uint32_t m_delAckMaxCount
Delayed ack count for receiver.
Time m_tracedRtt
Traced value of RTT, which may be different from the environment RTT in case of delayed ACKs.
uint32_t m_ssThresh
Slow start threshold.
Time m_expectedInterval
Theoretical estimate of the time at which next packet is scheduled for transmission.
void RttTrace(Time oldTime, Time newTime) override
Rtt changes.
void Tx(const Ptr< const Packet > p, const TcpHeader &h, SocketWho who) override
Packet transmitted down to IP layer.
Time m_nextPacketInterval
Time maintained by Tx () trace about interval at which next packet will be sent.
void NormalClose(SocketWho who) override
Socket closed normally.
uint32_t m_segmentSize
Segment size.
void Rx(const Ptr< const Packet > p, const TcpHeader &h, SocketWho who) override
Packet received from IP layer.
void PhyDrop(SocketWho who) override
Link drop.
Time m_prevTxTime
Time when Tx was previously called.
void BytesInFlightTrace(uint32_t oldValue, uint32_t newValue) override
Bytes in flight changes.
Time m_transmissionStartTime
Time at which sender starts data transmission.
void QueueDrop(SocketWho who) override
Drop on the queue.
bool m_isConnAboutToEnd
True when sender receives a FIN/ACK from receiver.
uint16_t m_pacingCaRatio
Pacing factor during Congestion Avoidance.
uint32_t m_bytesInFlight
Current bytes in flight.
bool m_paceInitialWindow
True if initial window should be paced.
uint32_t m_packets
Number of packets.
EventId m_event
Check event.
uint32_t m_curCwnd
Current sender cWnd.
uint32_t m_packetsSent
Number of packets sent by sender so far.
TcpPacingTest(uint32_t segmentSize, uint32_t packetSize, uint32_t packets, uint16_t pacingSsRatio, uint16_t pacingCaRatio, uint32_t ssThresh, bool paceInitialWindow, uint32_t delAckMaxCount, const TypeId &congControl, const std::string &desc)
Constructor.
bool m_isFullCwndSent
True if all bytes for that cWnd is sent and sender is waiting for an ACK.
void ConfigureEnvironment() override
Change the configuration of the environment.
virtual void UpdateExpectedInterval()
Update the expected interval at which next packet will be sent.
bool m_initial
True on first run.
uint32_t m_packetSize
Size of the packets.
TestSuite for the behavior of TCP pacing.
An identifier for simulation events.
Definition: event-id.h:55
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
General infrastructure for TCP testing.
void SetPropagationDelay(Time propDelay)
Propagation delay of the bottleneck link.
void SetAppPktCount(uint32_t pktCount)
Set app packet count.
void SetDelAckMaxCount(SocketWho who, uint32_t count)
Forcefully set the delayed acknowledgement count.
SocketWho
Used as parameter of methods, specifies on what node the caller is interested (e.g.
@ RECEIVER
Receiver node.
void SetAppPktSize(uint32_t pktSize)
Set app packet size.
void SetInitialCwnd(SocketWho who, uint32_t initialCwnd)
Forcefully set the initial cwnd.
void SetPaceInitialWindow(SocketWho who, bool paceWindow)
Enable or disable pacing of the initial window.
virtual void ConfigureProperties()
Change the configuration of the socket properties.
void SetMTU(uint32_t mtu)
MTU of the bottleneck link.
Time GetPropagationDelay() const
Get the channel Propagation Delay.
void SetAppPktInterval(Time pktInterval)
Interval between app-generated packet.
TypeId m_congControlTypeId
Congestion control.
void SetInitialSsThresh(SocketWho who, uint32_t initialSsThresh)
Forcefully set the initial ssthresh.
void SetPacingStatus(SocketWho who, bool pacing)
Enable or disable pacing in the TCP socket.
virtual void ConfigureEnvironment()
Change the configuration of the environment.
void SetTransmitStart(Time startTime)
Set the initial time at which the application sends the first data packet.
void SetSegmentSize(SocketWho who, uint32_t segmentSize)
Forcefully set the segment size.
Header for the Transmission Control Protocol.
Definition: tcp-header.h:46
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:167
static TypeId GetTypeId()
Get the type ID.
@ QUICK
Fast test.
Definition: test.h:1065
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
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:402
a unique identifier for an interface.
Definition: type-id.h:59
uint32_t segmentSize
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#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_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_TEST_ASSERT_MSG_LT_OR_EQ(actual, limit, msg)
Test that an actual value is less than or equal to a limit and report and abort if not.
Definition: test.h:750
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1372
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static TcpPacingTestSuite g_tcpPacingTest
Static variable for test initialization.
static const uint32_t packetSize
Packet size generated at the AP.