A Discrete-Event Network Simulator
API
tcp-pacing-test.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2020 NITK Surathkal
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Authors: Deepak Kumaraswamy <deepakkavoor99@gmail.com>
19  *
20  */
21 #include "ns3/log.h"
22 #include "ns3/simple-channel.h"
23 #include "ns3/config.h"
24 #include "ns3/test.h"
25 #include "tcp-general-test.h"
26 
27 using namespace ns3;
28 
29 NS_LOG_COMPONENT_DEFINE ("TcpPacingTestSuite");
30 
90 class
92 {
93 public:
107  TcpPacingTest (uint32_t segmentSize, uint32_t packetSize,
108  uint32_t packets, uint16_t pacingSsRatio, uint16_t pacingCaRatio,
109  uint32_t ssThresh, bool paceInitialWindow, uint32_t delAckMaxCount,
110  const TypeId& congControl, const std::string &desc);
111 
112 protected:
113  virtual void CWndTrace (uint32_t oldValue, uint32_t newValue);
114  virtual void RttTrace (Time oldTime, Time newTime);
115  virtual void BytesInFlightTrace (uint32_t oldValue, uint32_t newValue);
116  virtual void Tx (const Ptr<const Packet> p, const TcpHeader &h, SocketWho who);
117  virtual void Rx (const Ptr<const Packet> p, const TcpHeader &h, SocketWho who);
118  virtual void QueueDrop (SocketWho who);
119  virtual void PhyDrop (SocketWho who);
120  virtual void NormalClose (SocketWho who);
121 
125  virtual void UpdateExpectedInterval (void);
126 
127  virtual void ConfigureEnvironment ();
128  virtual void ConfigureProperties ();
129 
130 private:
131  uint32_t m_segmentSize;
132  uint32_t m_packetSize;
133  uint32_t m_packets;
135  bool m_initial;
136  uint32_t m_initialCwnd;
137  uint32_t m_curCwnd;
139  uint32_t m_bytesInFlight;
141  uint16_t m_pacingSsRatio;
142  uint16_t m_pacingCaRatio;
143  uint32_t m_ssThresh;
145  uint32_t m_delAckMaxCount;
149  uint32_t m_packetsSent;
152 };
153 
154 
156  uint32_t packetSize,
157  uint32_t packets,
158  uint16_t pacingSsRatio,
159  uint16_t pacingCaRatio,
160  uint32_t ssThresh,
161  bool paceInitialWindow,
162  uint32_t delAckMaxCount,
163  const TypeId &typeId,
164  const std::string &desc)
165  : TcpGeneralTest (desc),
166  m_segmentSize (segmentSize),
167  m_packetSize (packetSize),
168  m_packets (packets),
169  m_initial (true),
170  m_initialCwnd (10),
171  m_curCwnd (0),
172  m_isFullCwndSent (true),
173  m_bytesInFlight (0),
174  m_prevTxTime (0),
175  m_pacingSsRatio (pacingSsRatio),
176  m_pacingCaRatio (pacingCaRatio),
177  m_ssThresh (ssThresh),
178  m_paceInitialWindow (paceInitialWindow),
179  m_delAckMaxCount (delAckMaxCount),
180  m_isConnAboutToEnd (false),
181  m_transmissionStartTime (Seconds (0)),
182  m_expectedInterval (Seconds (0)),
183  m_packetsSent (0),
184  m_nextPacketInterval (Seconds (0)),
185  m_tracedRtt (Seconds (0))
186 {
187  m_congControlTypeId = typeId;
188 }
189 
190 void
192 {
193  TcpGeneralTest::ConfigureEnvironment ();
197  SetMTU (1500);
200 }
201 
203 {
204  TcpGeneralTest::ConfigureProperties ();
208  SetPacingStatus (SENDER, true);
211  NS_LOG_DEBUG ("segSize: " << m_segmentSize << " ssthresh: " << m_ssThresh <<
212  " paceInitialWindow: " << m_paceInitialWindow << " delAckMaxCount " << m_delAckMaxCount);
213 }
214 
215 void
217 {
218  NS_LOG_FUNCTION (this << oldTime << newTime);
219  m_tracedRtt = newTime;
221 }
222 
223 void
224 TcpPacingTest::CWndTrace (uint32_t oldValue, uint32_t newValue)
225 {
226  NS_LOG_FUNCTION (this << oldValue << newValue);
227  m_curCwnd = newValue;
228  if (m_initial)
229  {
230  m_initial = false;
231  }
232  // CWndTrace () is called after Rx ()
233  // Therefore, call UpdateExpectedInterval () here instead of in Rx ()
235 }
236 
237 void
238 TcpPacingTest::BytesInFlightTrace (uint32_t oldValue, uint32_t newValue)
239 {
240  m_bytesInFlight = newValue;
241 }
242 
243 void
245 {
246  double_t factor;
247  Time rtt = 2 * GetPropagationDelay ();
248  if (m_curCwnd < m_ssThresh / 2)
249  {
250  factor = static_cast<double> (m_pacingSsRatio) / 100;
251  }
252  else
253  {
254  factor = static_cast<double> (m_pacingCaRatio) / 100;
255  }
256 
258  {
259  // If initial cwnd is not paced, we expect packet pacing interval to be zero
261  }
262  else
263  {
264  // Use the estimate according to update equation
266  }
267 }
268 
269 void
271 {
272  if (who == SENDER)
273  {
274  uint8_t flags = h.GetFlags ();
275  uint8_t hasFin = flags & TcpHeader::FIN;
276  uint8_t hasAck = flags & TcpHeader::ACK;
277  if (hasFin && hasAck)
278  {
279  m_isConnAboutToEnd = true;
280  NS_LOG_DEBUG ("Sender received a FIN/ACK packet");
281  }
282  else
283  {
284  m_isConnAboutToEnd = false;
285  NS_LOG_DEBUG ("Sender received an ACK packet");
286  }
287  }
288 }
289 
290 void
292 {
293  NS_LOG_FUNCTION (this << p << h << who);
294 
295  if (who == SENDER)
296  {
297  m_packetsSent++;
298  // Start pacing checks from the second data packet onwards because
299  // an interval to check does not exist for the first data packet.
300  // The first two (non-data) packets correspond to SYN and an
301  // empty ACK, respectively, so start checking after three packets are sent
302  bool beyondInitialDataSegment = (m_packetsSent > 3);
303  Time actualInterval = Simulator::Now () - m_prevTxTime;
304  NS_LOG_DEBUG ("TX sent: packetsSent: " << m_packetsSent << " fullCwnd: " << m_isFullCwndSent << " nearEnd: " <<
305  m_isConnAboutToEnd << " beyondInitialDataSegment " << beyondInitialDataSegment);
306  if (!m_isFullCwndSent && !m_isConnAboutToEnd && beyondInitialDataSegment)
307  {
308  // Consider a small error margin, and ensure that the actual and expected intervals lie within this error
309  Time errorMargin = NanoSeconds (10);
310  NS_TEST_ASSERT_MSG_LT_OR_EQ (std::abs ((actualInterval - m_nextPacketInterval).GetSeconds ()), errorMargin.GetSeconds (), "Packet delivery in slow start didn't match pacing rate");
311  NS_LOG_DEBUG ("Pacing Check: interval (s): " << actualInterval.GetSeconds () <<
312  " expected interval (s): " << m_nextPacketInterval.GetSeconds () <<
313  " difference (s): " << std::abs ((actualInterval - m_nextPacketInterval).GetSeconds ()) <<
314  " errorMargin (s): " << errorMargin.GetSeconds ());
315  }
316 
318  // bytesInFlight isn't updated yet. Its trace is called after Tx
319  // so add an additional m_segmentSize to bytesInFlight
320  uint32_t soonBytesInFlight = m_bytesInFlight + m_segmentSize;
321  bool canPacketBeSent = ((m_curCwnd - soonBytesInFlight) >= m_segmentSize);
322  if (!canPacketBeSent || (m_curCwnd == 0))
323  {
324  m_isFullCwndSent = true;
325  }
326  else
327  {
328  m_isFullCwndSent = false;
329  }
331  NS_LOG_DEBUG ("Next expected interval (s): " << m_nextPacketInterval.GetSeconds ());
332  }
333 }
334 
335 void
337 {
338  NS_FATAL_ERROR ("Drop on the queue; cannot validate congestion avoidance");
339 }
340 
341 void
343 {
344  NS_FATAL_ERROR ("Drop on the phy: cannot validate congestion avoidance");
345 }
346 
347 void
349 {
350  if (who == SENDER)
351  {
352  m_event.Cancel ();
353  }
354 }
355 
363 {
364 public:
365  TcpPacingTestSuite () : TestSuite ("tcp-pacing-test", UNIT)
366  {
367  uint16_t pacingSsRatio = 200;
368  uint16_t pacingCaRatio = 120;
369  uint32_t segmentSize = 1000;
370  uint32_t packetSize = 1000;
371  uint32_t numPackets = 40;
372  uint32_t delAckMaxCount = 1;
373  TypeId tid = TcpNewReno::GetTypeId ();
374  uint32_t ssThresh = 1e9; // default large value
375  bool paceInitialWindow = false;
376  std::string description;
377 
378  description = std::string ("Pacing case 1: Slow start only, no initial pacing");
379  AddTestCase (new TcpPacingTest (segmentSize, packetSize, numPackets, pacingSsRatio, pacingCaRatio, ssThresh, paceInitialWindow, delAckMaxCount, tid, description), TestCase::QUICK);
380 
381  paceInitialWindow = true;
382  description = std::string ("Pacing case 2: Slow start only, initial pacing");
383  AddTestCase (new TcpPacingTest (segmentSize, packetSize, numPackets, pacingSsRatio, pacingCaRatio, ssThresh, paceInitialWindow, delAckMaxCount, tid, description), TestCase::QUICK);
384 
385  // set ssThresh to some smaller value to check that pacing
386  // slows down in second half of slow start, then transitions to CA
387  description = std::string ("Pacing case 3: Slow start, followed by transition to Congestion avoidance, no initial pacing");
388  paceInitialWindow = false;
389  ssThresh = 40;
390  numPackets = 60;
391  AddTestCase (new TcpPacingTest (segmentSize, packetSize, numPackets, pacingSsRatio, pacingCaRatio, ssThresh, paceInitialWindow, delAckMaxCount, tid, description), TestCase::QUICK);
392 
393  // Repeat tests, but with more typical delAckMaxCount == 2
394  delAckMaxCount = 2;
395  paceInitialWindow = false;
396  ssThresh = 1e9;
397  numPackets = 40;
398  description = std::string ("Pacing case 4: Slow start only, no initial pacing, delayed ACKs");
399  AddTestCase (new TcpPacingTest (segmentSize, packetSize, numPackets, pacingSsRatio, pacingCaRatio, ssThresh, paceInitialWindow, delAckMaxCount, tid, description), TestCase::QUICK);
400 
401  paceInitialWindow = true;
402  description = std::string ("Pacing case 5: Slow start only, initial pacing, delayed ACKs");
403  AddTestCase (new TcpPacingTest (segmentSize, packetSize, numPackets, pacingSsRatio, pacingCaRatio, ssThresh, paceInitialWindow, delAckMaxCount, tid, description), TestCase::QUICK);
404 
405  description = std::string ("Pacing case 6: Slow start, followed by transition to Congestion avoidance, no initial pacing, delayed ACKs");
406  paceInitialWindow = false;
407  ssThresh = 40;
408  numPackets = 60;
409  AddTestCase (new TcpPacingTest (segmentSize, packetSize, numPackets, pacingSsRatio, pacingCaRatio, ssThresh, paceInitialWindow, delAckMaxCount, tid, description), TestCase::QUICK);
410  }
411 };
412 
ns3::TypeId
a unique identifier for an interface.
Definition: type-id.h:59
NS_LOG_COMPONENT_DEFINE
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
NS_TEST_ASSERT_MSG_LT_OR_EQ
#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:830
TcpPacingTest::PhyDrop
virtual void PhyDrop(SocketWho who)
Link drop.
Definition: tcp-pacing-test.cc:342
TcpPacingTest::QueueDrop
virtual void QueueDrop(SocketWho who)
Drop on the queue.
Definition: tcp-pacing-test.cc:336
ns3::TcpGeneralTest::SocketWho
SocketWho
Used as parameter of methods, specifies on what node the caller is interested (e.g.
Definition: tcp-general-test.h:275
ns3::TestCase::AddTestCase
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
TcpPacingTest::Rx
virtual void Rx(const Ptr< const Packet > p, const TcpHeader &h, SocketWho who)
Packet received from IP layer.
Definition: tcp-pacing-test.cc:270
ns3::EventId
An identifier for simulation events.
Definition: event-id.h:54
TcpPacingTest::NormalClose
virtual void NormalClose(SocketWho who)
Socket closed normally.
Definition: tcp-pacing-test.cc:348
ns3
Every class exported by the ns3 library is enclosed in the ns3 namespace.
TcpPacingTest::ConfigureProperties
virtual void ConfigureProperties()
Change the configuration of the socket properties.
Definition: tcp-pacing-test.cc:202
ns3::TcpGeneralTest::SENDER
@ SENDER
Sender node.
Definition: tcp-general-test.h:276
ns3::TcpGeneralTest::SetTransmitStart
void SetTransmitStart(Time startTime)
Set the initial time at which the application sends the first data packet.
Definition: tcp-general-test.h:671
ns3::TcpGeneralTest::SetAppPktCount
void SetAppPktCount(uint32_t pktCount)
Set app packet count.
Definition: tcp-general-test.h:650
ns3::TcpGeneralTest::SetPaceInitialWindow
void SetPaceInitialWindow(SocketWho who, bool paceWindow)
Enable or disable pacing of the initial window.
Definition: tcp-general-test.cc:1005
TcpPacingTest::m_packets
uint32_t m_packets
Number of packets.
Definition: tcp-pacing-test.cc:133
ns3::TcpGeneralTest::SetInitialCwnd
void SetInitialCwnd(SocketWho who, uint32_t initialCwnd)
Forcefully set the initial cwnd.
Definition: tcp-general-test.cc:939
TcpPacingTest::m_delAckMaxCount
uint32_t m_delAckMaxCount
Delayed ack count for receiver.
Definition: tcp-pacing-test.cc:145
TcpPacingTest::m_ssThresh
uint32_t m_ssThresh
Slow start threshold.
Definition: tcp-pacing-test.cc:143
ns3::TcpGeneralTest::SetMTU
void SetMTU(uint32_t mtu)
MTU of the bottleneck link.
Definition: tcp-general-test.h:692
ns3::TcpGeneralTest::GetPropagationDelay
Time GetPropagationDelay() const
Get the channel Propagation Delay.
Definition: tcp-general-test.h:985
g_tcpPacingTest
static TcpPacingTestSuite g_tcpPacingTest
Static variable for test initialization.
Definition: tcp-pacing-test.cc:413
TcpPacingTest::TcpPacingTest
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.
Definition: tcp-pacing-test.cc:155
ns3::Ptr< const Packet >
TcpPacingTest::UpdateExpectedInterval
virtual void UpdateExpectedInterval(void)
Update the expected interval at which next packet will be sent.
Definition: tcp-pacing-test.cc:244
NS_FATAL_ERROR
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
TcpPacingTestSuite
TestSuite for the behavior of TCP pacing.
Definition: tcp-pacing-test.cc:363
ns3::Now
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
TcpPacingTest::m_nextPacketInterval
Time m_nextPacketInterval
Time maintained by Tx () trace about interval at which next packet will be sent.
Definition: tcp-pacing-test.cc:150
ns3::NanoSeconds
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1313
TcpPacingTestSuite::TcpPacingTestSuite
TcpPacingTestSuite()
Definition: tcp-pacing-test.cc:365
TcpPacingTest::m_bytesInFlight
uint32_t m_bytesInFlight
Current bytes in flight.
Definition: tcp-pacing-test.cc:139
ns3::TcpGeneralTest::SetDelAckMaxCount
void SetDelAckMaxCount(SocketWho who, uint32_t count)
Forcefully set the delayed acknowledgement count.
Definition: tcp-general-test.cc:955
ns3::MilliSeconds
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1297
ns3::EventId::Cancel
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
TcpPacingTest::m_event
EventId m_event
Check event.
Definition: tcp-pacing-test.cc:134
ns3::TcpGeneralTest::SetAppPktInterval
void SetAppPktInterval(Time pktInterval)
Interval between app-generated packet.
Definition: tcp-general-test.h:657
TcpPacingTest::m_pacingSsRatio
uint16_t m_pacingSsRatio
Pacing factor during Slow Start.
Definition: tcp-pacing-test.cc:141
TcpPacingTest::m_initialCwnd
uint32_t m_initialCwnd
Initial value of cWnd.
Definition: tcp-pacing-test.cc:136
ns3::TcpGeneralTest::RECEIVER
@ RECEIVER
Receiver node.
Definition: tcp-general-test.h:277
ns3::TcpGeneralTest::SetPacingStatus
void SetPacingStatus(SocketWho who, bool pacing)
Enable or disable pacing in the TCP socket.
Definition: tcp-general-test.cc:988
ns3::Time
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:104
TcpPacingTest::m_isFullCwndSent
bool m_isFullCwndSent
True if all bytes for that cWnd is sent and sender is waiting for an ACK.
Definition: tcp-pacing-test.cc:138
ns3::TcpHeader
Header for the Transmission Control Protocol.
Definition: tcp-header.h:45
TcpPacingTest::m_packetSize
uint32_t m_packetSize
Size of the packets.
Definition: tcp-pacing-test.cc:132
TcpPacingTest::BytesInFlightTrace
virtual void BytesInFlightTrace(uint32_t oldValue, uint32_t newValue)
Bytes in flight changes.
Definition: tcp-pacing-test.cc:238
TcpPacingTest::m_packetsSent
uint32_t m_packetsSent
Number of packets sent by sender so far.
Definition: tcp-pacing-test.cc:149
TcpPacingTest
Test the behavior of TCP pacing.
Definition: tcp-pacing-test.cc:92
tcp-general-test.h
ns3::TcpGeneralTest
General infrastructure for TCP testing.
Definition: tcp-general-test.h:257
TcpPacingTest::m_tracedRtt
Time m_tracedRtt
Traced value of RTT, which may be different from the environment RTT in case of delayed ACKs.
Definition: tcp-pacing-test.cc:151
TcpPacingTest::m_expectedInterval
Time m_expectedInterval
Theoretical estimate of the time at which next packet is scheduled for transmission.
Definition: tcp-pacing-test.cc:148
TcpPacingTest::m_pacingCaRatio
uint16_t m_pacingCaRatio
Pacing factor during Congestion Avoidance.
Definition: tcp-pacing-test.cc:142
ns3::TestSuite
A suite of tests to run.
Definition: test.h:1344
TcpPacingTest::m_initial
bool m_initial
True on first run.
Definition: tcp-pacing-test.cc:135
TcpPacingTest::Tx
virtual void Tx(const Ptr< const Packet > p, const TcpHeader &h, SocketWho who)
Packet transmitted down to IP layer.
Definition: tcp-pacing-test.cc:291
packetSize
static const uint32_t packetSize
Definition: wifi-power-adaptation-distance.cc:113
NS_LOG_DEBUG
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
ns3::TestSuite::UNIT
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1353
ns3::Seconds
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
TcpPacingTest::m_segmentSize
uint32_t m_segmentSize
Segment size.
Definition: tcp-pacing-test.cc:131
ns3::TcpGeneralTest::m_congControlTypeId
TypeId m_congControlTypeId
Congestion control.
Definition: tcp-general-test.h:1036
TcpPacingTest::CWndTrace
virtual void CWndTrace(uint32_t oldValue, uint32_t newValue)
Tracks the congestion window changes.
Definition: tcp-pacing-test.cc:224
segmentSize
uint32_t segmentSize
Definition: tcp-linux-reno.cc:53
NS_LOG_FUNCTION
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Definition: log-macros-enabled.h:244
ns3::TcpGeneralTest::SetAppPktSize
void SetAppPktSize(uint32_t pktSize)
Set app packet size.
Definition: tcp-general-test.h:641
ns3::TcpHeader::GetFlags
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:173
TcpPacingTest::m_curCwnd
uint32_t m_curCwnd
Current sender cWnd.
Definition: tcp-pacing-test.cc:137
TcpPacingTest::m_paceInitialWindow
bool m_paceInitialWindow
True if initial window should be paced.
Definition: tcp-pacing-test.cc:144
TcpPacingTest::RttTrace
virtual void RttTrace(Time oldTime, Time newTime)
Rtt changes.
Definition: tcp-pacing-test.cc:216
TcpPacingTest::ConfigureEnvironment
virtual void ConfigureEnvironment()
Change the configuration of the environment.
Definition: tcp-pacing-test.cc:191
ns3::TcpGeneralTest::SetInitialSsThresh
void SetInitialSsThresh(SocketWho who, uint32_t initialSsThresh)
Forcefully set the initial ssthresh.
Definition: tcp-general-test.cc:1022
TcpPacingTest::m_transmissionStartTime
Time m_transmissionStartTime
Time at which sender starts data transmission.
Definition: tcp-pacing-test.cc:147
ns3::Time::GetSeconds
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:380
TcpPacingTest::m_isConnAboutToEnd
bool m_isConnAboutToEnd
True when sender receives a FIN/ACK from receiver.
Definition: tcp-pacing-test.cc:146
ns3::TcpGeneralTest::SetPropagationDelay
void SetPropagationDelay(Time propDelay)
Propagation delay of the bottleneck link.
Definition: tcp-general-test.h:664
ns3::TcpGeneralTest::SetSegmentSize
void SetSegmentSize(SocketWho who, uint32_t segmentSize)
Forcefully set the segment size.
Definition: tcp-general-test.cc:922
TcpPacingTest::m_prevTxTime
Time m_prevTxTime
Time when Tx was previously called.
Definition: tcp-pacing-test.cc:140