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 #include "tcp-general-test.h"
20 #include "ns3/node.h"
21 #include "ns3/log.h"
22 #include "tcp-error-model.h"
23 #include "ns3/random-variable-stream.h"
24 #include "ns3/tcp-rx-buffer.h"
25 
26 using namespace ns3;
27 
28 NS_LOG_COMPONENT_DEFINE ("TcpAdvertisedWindowTestSuite");
29 
37 {
38 public:
43  static TypeId GetTypeId (void);
44 
47 
52  {
53  }
54 
61  : TcpSocketMsgBase (other)
62  {
63  m_segmentSize = other.m_segmentSize;
64  m_inwalidAwndCb = other.m_inwalidAwndCb;
65  }
66 
72  void SetInvalidAwndCb (InvalidAwndCallback cb);
73 
79  void SetExpectedSegmentSize (uint16_t seg) { m_segmentSize = seg; };
80 
81 protected:
82  virtual Ptr<TcpSocketBase> Fork ();
83  virtual uint16_t AdvertisedWindowSize (bool scale = true) const;
84 
85 private:
86  uint16_t OldAdvertisedWindowSize (bool scale = true) const;
88 
95  uint16_t m_segmentSize;
96 };
97 
98 void
100 {
101  NS_ASSERT (!cb.IsNull ());
102  m_inwalidAwndCb = cb;
103 }
104 
105 TypeId
107 {
108  static TypeId tid = TypeId ("ns3::TcpSocketAdvertisedWindowProxy")
110  .SetGroupName ("Internet")
111  .AddConstructor<TcpSocketAdvertisedWindowProxy> ()
112  ;
113  return tid;
114 }
115 
118 {
119  return CopyObject<TcpSocketAdvertisedWindowProxy> (this);
120 }
121 
122 uint16_t
124 {
125  NS_LOG_FUNCTION (this << scale);
126 
127  uint16_t newAwnd = TcpSocketMsgBase::AdvertisedWindowSize (scale);
128  uint16_t oldAwnd = OldAdvertisedWindowSize (scale);
129 
130  if (!m_tcb->m_rxBuffer->Finished ())
131  {
132  // The calculated windows will only be exactly equal if there is no data
133  // in the receive buffer yet.
134  if (newAwnd != oldAwnd)
135  {
136  uint32_t available = m_tcb->m_rxBuffer->Available ();
137  // If the values differ, make sure this is only due to the single segment
138  // the socket just got, which has not yet been read by the application.
139  // Therefore, the difference should be exactly the size of one segment
140  // (but taking scale and m_maxWinSize into account).
141  uint32_t newAwndKnownDifference = newAwnd;
142  if (scale)
143  {
144  newAwndKnownDifference += (available >> m_rcvWindShift);
145  }
146  else
147  {
148  newAwndKnownDifference += available;
149  }
150 
151  if (newAwndKnownDifference > m_maxWinSize)
152  {
153  newAwndKnownDifference = m_maxWinSize;
154  }
155 
156  if (static_cast<uint16_t> (newAwndKnownDifference) != oldAwnd)
157  {
158  if (!m_inwalidAwndCb.IsNull ())
159  {
160  m_inwalidAwndCb(oldAwnd, newAwnd);
161  }
162 
163  }
164  }
165  }
166 
167 
168  return newAwnd;
169 }
170 
178 uint16_t
180 {
181  NS_LOG_FUNCTION (this << scale);
182  //NS_LOG_DEBUG ("MaxRxSequence () = " << m_tcb->m_rxBuffer->MaxRxSequence ());
183  //NS_LOG_DEBUG ("NextRxSequence () = " << m_tcb->m_rxBuffer->NextRxSequence ());
184  //NS_LOG_DEBUG ("MaxBufferSize () = " << m_tcb->m_rxBuffer->MaxBufferSize ());
185  //NS_LOG_DEBUG ("m_rcvWindShift = " << static_cast<uint16_t> (m_rcvWindShift));
186  //NS_LOG_DEBUG ("m_maxWinSize = " << m_maxWinSize);
187  //NS_LOG_DEBUG ("Available () = " << m_tcb->m_rxBuffer->Available ());
188  uint32_t w = m_tcb->m_rxBuffer->MaxBufferSize ();
189 
190  if (scale)
191  {
192  w >>= m_rcvWindShift;
193  }
194  if (w > m_maxWinSize)
195  {
196  w = m_maxWinSize;
197  NS_LOG_WARN ("Adv window size truncated to " << m_maxWinSize << "; possibly to avoid overflow of the 16-bit integer");
198  }
199  NS_LOG_DEBUG ("Returning AdvertisedWindowSize of " << static_cast<uint16_t> (w));
200  return static_cast<uint16_t> (w);
201 }
202 
204 
212 {
213 public:
218  static TypeId GetTypeId (void);
223  TcpDropRatioErrorModel (double dropRatio)
224  : TcpGeneralErrorModel (), m_dropRatio(dropRatio)
225  {
226  m_prng = CreateObject<UniformRandomVariable> ();
227  }
228 
229 protected:
230  virtual bool ShouldDrop (const Ipv4Header &ipHeader, const TcpHeader &tcpHeader,
231  uint32_t packetSize);
232 
233 private:
234  virtual void DoReset (void) { };
235  double m_dropRatio;
237 };
238 
240 
241 TypeId
243 {
244  static TypeId tid = TypeId ("ns3::TcpDropRatioErrorModel")
246  ;
247  return tid;
248 }
249 
250 bool
251 TcpDropRatioErrorModel::ShouldDrop (const Ipv4Header &ipHeader, const TcpHeader &tcpHeader,
252  uint32_t packetSize)
253 {
254  return m_prng->GetValue () < m_dropRatio;
255 }
256 
281 {
282 public:
290  TcpAdvertisedWindowTest (const std::string &desc, uint32_t size, uint32_t packets, double lossRatio);
291 
292 protected:
293  virtual void ConfigureEnvironment ();
294  virtual Ptr<TcpSocketMsgBase> CreateReceiverSocket (Ptr<Node> node);
295  virtual Ptr<ErrorModel> CreateReceiverErrorModel ();
296 
297 private:
302  void InvalidAwndCb (uint16_t oldAwnd, uint16_t newAwnd);
303  uint32_t m_pktSize;
304  uint32_t m_pktCount;
305  double m_lossRatio;
306 };
307 
309  uint32_t size, uint32_t packets, double lossRatio)
310  : TcpGeneralTest (desc),
311  m_pktSize (size),
312  m_pktCount (packets),
313  m_lossRatio (lossRatio)
314 {
315 }
316 
317 void
319 {
320  TcpGeneralTest::ConfigureEnvironment ();
323  SetTransmitStart (Seconds (2.0));
325 
326 }
327 
330 {
331  NS_LOG_FUNCTION (this);
332 
334  DynamicCast<TcpSocketAdvertisedWindowProxy> (sock)->SetExpectedSegmentSize (500);
335  DynamicCast<TcpSocketAdvertisedWindowProxy> (sock)->SetInvalidAwndCb (
337 
338  return sock;
339 }
340 
343 {
344  return CreateObject<TcpDropRatioErrorModel> (m_lossRatio);
345 }
346 
347 void
348 TcpAdvertisedWindowTest::InvalidAwndCb (uint16_t oldAwnd, uint16_t newAwnd)
349 {
350  NS_TEST_ASSERT_MSG_EQ (oldAwnd, newAwnd,
351  "Old and new AWND calculations do not match.");
352 }
353 //-----------------------------------------------------------------------------
354 
361 {
362 public:
370  TcpAdvWindowOnLossTest (const std::string &desc, uint32_t size, uint32_t packets,
371  std::vector<uint32_t> &toDrop);
372 
373 protected:
374  virtual void ConfigureEnvironment ();
378 
379 private:
384  void InvalidAwndCb (uint16_t oldAwnd, uint16_t newAwnd);
385  uint32_t m_pktSize;
386  uint32_t m_pktCount;
387  std::vector<uint32_t> m_toDrop;
388 };
389 
391  uint32_t size, uint32_t packets,
392  std::vector<uint32_t> &toDrop)
393  : TcpGeneralTest (desc),
394  m_pktSize (size),
395  m_pktCount (packets),
396  m_toDrop (toDrop)
397 {
398 }
399 
400 void
402 {
403  TcpGeneralTest::ConfigureEnvironment ();
406  SetTransmitStart (Seconds (2.0));
408 }
409 
412 {
413  NS_LOG_FUNCTION (this);
414 
416  DynamicCast<TcpSocketAdvertisedWindowProxy> (sock)->SetExpectedSegmentSize (500);
417  DynamicCast<TcpSocketAdvertisedWindowProxy> (sock)->SetInvalidAwndCb (
419 
420  return sock;
421 }
422 
425 {
426  auto socket = TcpGeneralTest::CreateSenderSocket (node);
427  socket->SetAttribute("InitialCwnd", UintegerValue (10*m_pktSize));
428 
429  return socket;
430 }
431 
434 {
435  Ptr<TcpSeqErrorModel> m_errorModel = CreateObject<TcpSeqErrorModel> ();
436  for (std::vector<uint32_t>::iterator it = m_toDrop.begin (); it != m_toDrop.end (); ++it)
437  {
438  m_errorModel->AddSeqToKill (SequenceNumber32 (*it));
439  }
440 
441  return m_errorModel;
442 }
443 
444 void
445 TcpAdvWindowOnLossTest::InvalidAwndCb (uint16_t oldAwnd, uint16_t newAwnd)
446 {
447  NS_TEST_ASSERT_MSG_EQ (oldAwnd, newAwnd,
448  "Old and new AWND calculations do not match.");
449 }
450 
451 //-----------------------------------------------------------------------------
452 
460 {
461 public:
462  TcpAdvertisedWindowTestSuite () : TestSuite ("tcp-advertised-window-test", UNIT)
463  {
464  AddTestCase (new TcpAdvertisedWindowTest ("TCP advertised window size, small seg + no loss", 500, 100, 0.0),
465  TestCase::QUICK);
466  AddTestCase (new TcpAdvertisedWindowTest ("TCP advertised window size, small seg + loss", 500, 100, 0.1),
467  TestCase::QUICK);
468  AddTestCase (new TcpAdvertisedWindowTest ("TCP advertised window size, large seg + no loss", 1000, 100, 0.0),
469  TestCase::QUICK);
470  AddTestCase (new TcpAdvertisedWindowTest ("TCP advertised window size, large seg + small loss", 1000, 100, 0.1),
471  TestCase::QUICK);
472  AddTestCase (new TcpAdvertisedWindowTest ("TCP advertised window size, large seg + big loss", 1000, 100, 0.3),
473  TestCase::QUICK);
474  AddTestCase (new TcpAdvertisedWindowTest ("TCP advertised window size, complete loss", 1000, 100, 1.0),
475  TestCase::QUICK);
476 
477  std::vector<uint32_t> toDrop;
478  toDrop.push_back(8001);
479  toDrop.push_back(9001);
480  AddTestCase (new TcpAdvWindowOnLossTest ("TCP advertised window size, after FIN loss", 1000, 10, toDrop));
481  }
482 };
483 
484 static TcpAdvertisedWindowTestSuite g_tcpAdvertisedWindowTestSuite; //<! static obj for test initialization
485 
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:1188
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1197
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
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:141
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
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:1648
static TcpAdvertisedWindowTestSuite g_tcpAdvertisedWindowTestSuite
static const uint32_t packetSize