A Discrete-Event Network Simulator
API
tcp-advertised-window-test.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2017 Christoph Doepmann <doepmanc@informatik.hu-berlin.de>
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  */
19 
20 #include "tcp-general-test.h"
21 #include "ns3/node.h"
22 #include "ns3/log.h"
23 #include "tcp-error-model.h"
24 #include "ns3/random-variable-stream.h"
25 #include "ns3/tcp-rx-buffer.h"
26 
27 using namespace ns3;
28 
29 NS_LOG_COMPONENT_DEFINE ("TcpAdvertisedWindowTestSuite");
30 
38 {
39 public:
44  static TypeId GetTypeId (void);
45 
48 
53  {
54  }
55 
62  : TcpSocketMsgBase (other)
63  {
64  m_segmentSize = other.m_segmentSize;
65  m_inwalidAwndCb = other.m_inwalidAwndCb;
66  }
67 
73  void SetInvalidAwndCb (InvalidAwndCallback cb);
74 
80  void SetExpectedSegmentSize (uint16_t seg) { m_segmentSize = seg; };
81 
82 protected:
83  virtual Ptr<TcpSocketBase> Fork ();
84  virtual uint16_t AdvertisedWindowSize (bool scale = true) const;
85 
86 private:
87  uint16_t OldAdvertisedWindowSize (bool scale = true) const;
89 
96  uint16_t m_segmentSize;
97 };
98 
99 void
101 {
102  NS_ASSERT (!cb.IsNull ());
103  m_inwalidAwndCb = cb;
104 }
105 
106 TypeId
108 {
109  static TypeId tid = TypeId ("ns3::TcpSocketAdvertisedWindowProxy")
111  .SetGroupName ("Internet")
112  .AddConstructor<TcpSocketAdvertisedWindowProxy> ()
113  ;
114  return tid;
115 }
116 
119 {
120  return CopyObject<TcpSocketAdvertisedWindowProxy> (this);
121 }
122 
123 uint16_t
125 {
126  NS_LOG_FUNCTION (this << scale);
127 
128  uint16_t newAwnd = TcpSocketMsgBase::AdvertisedWindowSize (scale);
129  uint16_t oldAwnd = OldAdvertisedWindowSize (scale);
130 
131  if (!m_tcb->m_rxBuffer->Finished ())
132  {
133  // The calculated windows will only be exactly equal if there is no data
134  // in the receive buffer yet.
135  if (newAwnd != oldAwnd)
136  {
137  uint32_t available = m_tcb->m_rxBuffer->Available ();
138  // If the values differ, make sure this is only due to the single segment
139  // the socket just got, which has not yet been read by the application.
140  // Therefore, the difference should be exactly the size of one segment
141  // (but taking scale and m_maxWinSize into account).
142  uint32_t newAwndKnownDifference = newAwnd;
143  if (scale)
144  {
145  newAwndKnownDifference += (available >> m_rcvWindShift);
146  }
147  else
148  {
149  newAwndKnownDifference += available;
150  }
151 
152  if (newAwndKnownDifference > m_maxWinSize)
153  {
154  newAwndKnownDifference = m_maxWinSize;
155  }
156 
157  if (static_cast<uint16_t> (newAwndKnownDifference) != oldAwnd)
158  {
159  if (!m_inwalidAwndCb.IsNull ())
160  {
161  m_inwalidAwndCb(oldAwnd, newAwnd);
162  }
163 
164  }
165  }
166  }
167 
168 
169  return newAwnd;
170 }
171 
179 uint16_t
181 {
182  NS_LOG_FUNCTION (this << scale);
183  //NS_LOG_DEBUG ("MaxRxSequence () = " << m_tcb->m_rxBuffer->MaxRxSequence ());
184  //NS_LOG_DEBUG ("NextRxSequence () = " << m_tcb->m_rxBuffer->NextRxSequence ());
185  //NS_LOG_DEBUG ("MaxBufferSize () = " << m_tcb->m_rxBuffer->MaxBufferSize ());
186  //NS_LOG_DEBUG ("m_rcvWindShift = " << static_cast<uint16_t> (m_rcvWindShift));
187  //NS_LOG_DEBUG ("m_maxWinSize = " << m_maxWinSize);
188  //NS_LOG_DEBUG ("Available () = " << m_tcb->m_rxBuffer->Available ());
189  uint32_t w = m_tcb->m_rxBuffer->MaxBufferSize ();
190 
191  if (scale)
192  {
193  w >>= m_rcvWindShift;
194  }
195  if (w > m_maxWinSize)
196  {
197  w = m_maxWinSize;
198  NS_LOG_WARN ("Adv window size truncated to " << m_maxWinSize << "; possibly to avoid overflow of the 16-bit integer");
199  }
200  NS_LOG_DEBUG ("Returning AdvertisedWindowSize of " << static_cast<uint16_t> (w));
201  return static_cast<uint16_t> (w);
202 }
203 
205 
213 {
214 public:
219  static TypeId GetTypeId (void);
224  TcpDropRatioErrorModel (double dropRatio)
225  : TcpGeneralErrorModel (), m_dropRatio(dropRatio)
226  {
227  m_prng = CreateObject<UniformRandomVariable> ();
228  }
229 
230 protected:
231  virtual bool ShouldDrop (const Ipv4Header &ipHeader, const TcpHeader &tcpHeader,
232  uint32_t packetSize);
233 
234 private:
235  virtual void DoReset (void) { };
236  double m_dropRatio;
238 };
239 
241 
242 TypeId
244 {
245  static TypeId tid = TypeId ("ns3::TcpDropRatioErrorModel")
247  ;
248  return tid;
249 }
250 
251 bool
252 TcpDropRatioErrorModel::ShouldDrop (const Ipv4Header &ipHeader, const TcpHeader &tcpHeader,
253  uint32_t packetSize)
254 {
255  return m_prng->GetValue () < m_dropRatio;
256 }
257 
282 {
283 public:
291  TcpAdvertisedWindowTest (const std::string &desc, uint32_t size, uint32_t packets, double lossRatio);
292 
293 protected:
294  virtual void ConfigureEnvironment ();
295  virtual Ptr<TcpSocketMsgBase> CreateReceiverSocket (Ptr<Node> node);
296  virtual Ptr<ErrorModel> CreateReceiverErrorModel ();
297 
298 private:
303  void InvalidAwndCb (uint16_t oldAwnd, uint16_t newAwnd);
304  uint32_t m_pktSize;
305  uint32_t m_pktCount;
306  double m_lossRatio;
307 };
308 
310  uint32_t size, uint32_t packets, double lossRatio)
311  : TcpGeneralTest (desc),
312  m_pktSize (size),
313  m_pktCount (packets),
314  m_lossRatio (lossRatio)
315 {
316 }
317 
318 void
320 {
321  TcpGeneralTest::ConfigureEnvironment ();
324  SetTransmitStart (Seconds (2.0));
326 
327 }
328 
331 {
332  NS_LOG_FUNCTION (this);
333 
335  DynamicCast<TcpSocketAdvertisedWindowProxy> (sock)->SetExpectedSegmentSize (500);
336  DynamicCast<TcpSocketAdvertisedWindowProxy> (sock)->SetInvalidAwndCb (
338 
339  return sock;
340 }
341 
344 {
345  return CreateObject<TcpDropRatioErrorModel> (m_lossRatio);
346 }
347 
348 void
349 TcpAdvertisedWindowTest::InvalidAwndCb (uint16_t oldAwnd, uint16_t newAwnd)
350 {
351  NS_TEST_ASSERT_MSG_EQ (oldAwnd, newAwnd,
352  "Old and new AWND calculations do not match.");
353 }
354 //-----------------------------------------------------------------------------
355 
362 {
363 public:
371  TcpAdvWindowOnLossTest (const std::string &desc, uint32_t size, uint32_t packets,
372  std::vector<uint32_t> &toDrop);
373 
374 protected:
375  virtual void ConfigureEnvironment ();
379 
380 private:
385  void InvalidAwndCb (uint16_t oldAwnd, uint16_t newAwnd);
386  uint32_t m_pktSize;
387  uint32_t m_pktCount;
388  std::vector<uint32_t> m_toDrop;
389 };
390 
392  uint32_t size, uint32_t packets,
393  std::vector<uint32_t> &toDrop)
394  : TcpGeneralTest (desc),
395  m_pktSize (size),
396  m_pktCount (packets),
397  m_toDrop (toDrop)
398 {
399 }
400 
401 void
403 {
404  TcpGeneralTest::ConfigureEnvironment ();
407  SetTransmitStart (Seconds (2.0));
409 }
410 
413 {
414  NS_LOG_FUNCTION (this);
415 
417  DynamicCast<TcpSocketAdvertisedWindowProxy> (sock)->SetExpectedSegmentSize (500);
418  DynamicCast<TcpSocketAdvertisedWindowProxy> (sock)->SetInvalidAwndCb (
420 
421  return sock;
422 }
423 
426 {
427  auto socket = TcpGeneralTest::CreateSenderSocket (node);
428  socket->SetAttribute("InitialCwnd", UintegerValue (10*m_pktSize));
429 
430  return socket;
431 }
432 
435 {
436  Ptr<TcpSeqErrorModel> m_errorModel = CreateObject<TcpSeqErrorModel> ();
437  for (std::vector<uint32_t>::iterator it = m_toDrop.begin (); it != m_toDrop.end (); ++it)
438  {
439  m_errorModel->AddSeqToKill (SequenceNumber32 (*it));
440  }
441 
442  return m_errorModel;
443 }
444 
445 void
446 TcpAdvWindowOnLossTest::InvalidAwndCb (uint16_t oldAwnd, uint16_t newAwnd)
447 {
448  NS_TEST_ASSERT_MSG_EQ (oldAwnd, newAwnd,
449  "Old and new AWND calculations do not match.");
450 }
451 
452 //-----------------------------------------------------------------------------
453 
461 {
462 public:
463  TcpAdvertisedWindowTestSuite () : TestSuite ("tcp-advertised-window-test", UNIT)
464  {
465  AddTestCase (new TcpAdvertisedWindowTest ("TCP advertised window size, small seg + no loss", 500, 100, 0.0),
466  TestCase::QUICK);
467  AddTestCase (new TcpAdvertisedWindowTest ("TCP advertised window size, small seg + loss", 500, 100, 0.1),
468  TestCase::QUICK);
469  AddTestCase (new TcpAdvertisedWindowTest ("TCP advertised window size, large seg + no loss", 1000, 100, 0.0),
470  TestCase::QUICK);
471  AddTestCase (new TcpAdvertisedWindowTest ("TCP advertised window size, large seg + small loss", 1000, 100, 0.1),
472  TestCase::QUICK);
473  AddTestCase (new TcpAdvertisedWindowTest ("TCP advertised window size, large seg + big loss", 1000, 100, 0.3),
474  TestCase::QUICK);
475  AddTestCase (new TcpAdvertisedWindowTest ("TCP advertised window size, complete loss", 1000, 100, 1.0),
476  TestCase::QUICK);
477 
478  std::vector<uint32_t> toDrop;
479  toDrop.push_back(8001);
480  toDrop.push_back(9001);
481  AddTestCase (new TcpAdvWindowOnLossTest ("TCP advertised window size, after FIN loss", 1000, 10, toDrop));
482  }
483 };
484 
485 static TcpAdvertisedWindowTestSuite g_tcpAdvertisedWindowTestSuite; //<! static obj for test initialization
486 
Test the TCP's advertised window size when there is a loss of specific packets.
TcpAdvWindowOnLossTest(const std::string &desc, uint32_t size, uint32_t packets, std::vector< uint32_t > &toDrop)
Constructor.
virtual Ptr< TcpSocketMsgBase > CreateReceiverSocket(Ptr< Node > node)
Create and install the socket to install on the receiver.
std::vector< uint32_t > m_toDrop
Sequences to drop.
void InvalidAwndCb(uint16_t oldAwnd, uint16_t newAwnd)
Callback called for the update of the awnd.
virtual Ptr< ErrorModel > CreateReceiverErrorModel()
Create and return the error model to install in the receiver node.
virtual Ptr< TcpSocketMsgBase > CreateSenderSocket(Ptr< Node > node)
Create and install the socket to install on the sender.
virtual void ConfigureEnvironment()
Change the configuration of the environment.
Test the new formula for calculating TCP's advertised window size.
virtual Ptr< TcpSocketMsgBase > CreateReceiverSocket(Ptr< Node > node)
Create and install the socket to install on the receiver.
virtual void ConfigureEnvironment()
Change the configuration of the environment.
TcpAdvertisedWindowTest(const std::string &desc, uint32_t size, uint32_t packets, double lossRatio)
Constructor.
void InvalidAwndCb(uint16_t oldAwnd, uint16_t newAwnd)
Callback called for the update of the awnd.
virtual Ptr< ErrorModel > CreateReceiverErrorModel()
Create and return the error model to install in the receiver node.
Test Suite for TCP adv window.
An error model that randomly drops a given rĂ¡tio of TCP segments.
static TypeId GetTypeId(void)
Get the type ID.
Ptr< UniformRandomVariable > m_prng
Random variable.
virtual bool ShouldDrop(const Ipv4Header &ipHeader, const TcpHeader &tcpHeader, uint32_t packetSize)
Check if the packet should be dropped.
TcpDropRatioErrorModel(double dropRatio)
Constructor.
virtual void DoReset(void)
Re-initialize any state.
Socket that wraps every call to AdvertisedWindowSize ().
virtual uint16_t AdvertisedWindowSize(bool scale=true) const
The amount of Rx window announced to the peer.
void SetInvalidAwndCb(InvalidAwndCallback cb)
Set the invalid AdvWnd callback.
static TypeId GetTypeId(void)
Get the type ID.
void SetExpectedSegmentSize(uint16_t seg)
Set the expected segment size.
uint16_t m_segmentSize
Test meta-information: size of the segments that are received.
Callback< void, uint16_t, uint16_t > InvalidAwndCallback
typedef for a cb
TcpSocketAdvertisedWindowProxy(const TcpSocketAdvertisedWindowProxy &other)
Copy-constructor.
InvalidAwndCallback m_inwalidAwndCb
Callback.
virtual Ptr< TcpSocketBase > Fork()
Call CopyObject<> to clone me.
uint16_t OldAdvertisedWindowSize(bool scale=true) const
The legacy code used for calculating the advertised window.
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1386
Packet header for IPv4.
Definition: ipv4-header.h:34
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
A general (TCP-aware) error model.
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 SetAppPktSize(uint32_t pktSize)
Set app packet size.
virtual Ptr< TcpSocketMsgBase > CreateSocket(Ptr< Node > node, TypeId socketType, TypeId congControl)
Create a socket.
TypeId m_congControlTypeId
Congestion control.
void SetTransmitStart(Time startTime)
Set the initial time at which the application sends the first data packet.
Header for the Transmission Control Protocol.
Definition: tcp-header.h:45
void AddSeqToKill(const SequenceNumber32 &seq)
Add the sequence number to the list of segments to be killed.
virtual uint16_t AdvertisedWindowSize(bool scale=true) const
The amount of Rx window announced to the peer.
Class for inserting callbacks special points of the flow of TCP sockets.
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1344
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1353
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
Hold an unsigned integer type.
Definition: uinteger.h:44
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:265
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
#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:166
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1297
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1642
static TcpAdvertisedWindowTestSuite g_tcpAdvertisedWindowTestSuite
static const uint32_t packetSize