A Discrete-Event Network Simulator
API
tcp-advertised-window-test.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Christoph Doepmann <doepmanc@informatik.hu-berlin.de>
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  */
18 #include "tcp-error-model.h"
19 #include "tcp-general-test.h"
20 
21 #include "ns3/log.h"
22 #include "ns3/node.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();
44 
47 
52  : TcpSocketMsgBase(),
53  m_segmentSize(0)
54  {
55  }
56 
63  : TcpSocketMsgBase(other)
64  {
65  m_segmentSize = other.m_segmentSize;
66  m_inwalidAwndCb = other.m_inwalidAwndCb;
67  }
68 
74  void SetInvalidAwndCb(InvalidAwndCallback cb);
75 
81  void SetExpectedSegmentSize(uint16_t seg)
82  {
83  m_segmentSize = seg;
84  }
85 
86  protected:
87  Ptr<TcpSocketBase> Fork() override;
88  uint16_t AdvertisedWindowSize(bool scale = true) const override;
89 
90  private:
91  uint16_t OldAdvertisedWindowSize(bool scale = true) const;
93 
100  uint16_t m_segmentSize;
101 };
102 
103 void
105 {
106  NS_ASSERT(!cb.IsNull());
107  m_inwalidAwndCb = cb;
108 }
109 
110 TypeId
112 {
113  static TypeId tid = TypeId("ns3::TcpSocketAdvertisedWindowProxy")
115  .SetGroupName("Internet")
116  .AddConstructor<TcpSocketAdvertisedWindowProxy>();
117  return tid;
118 }
119 
122 {
123  return CopyObject<TcpSocketAdvertisedWindowProxy>(this);
124 }
125 
126 uint16_t
128 {
129  NS_LOG_FUNCTION(this << scale);
130 
131  uint16_t newAwnd = TcpSocketMsgBase::AdvertisedWindowSize(scale);
132  uint16_t oldAwnd = OldAdvertisedWindowSize(scale);
133 
134  if (!m_tcb->m_rxBuffer->Finished())
135  {
136  // The calculated windows will only be exactly equal if there is no data
137  // in the receive buffer yet.
138  if (newAwnd != oldAwnd)
139  {
140  uint32_t available = m_tcb->m_rxBuffer->Available();
141  // If the values differ, make sure this is only due to the single segment
142  // the socket just got, which has not yet been read by the application.
143  // Therefore, the difference should be exactly the size of one segment
144  // (but taking scale and m_maxWinSize into account).
145  uint32_t newAwndKnownDifference = newAwnd;
146  if (scale)
147  {
148  newAwndKnownDifference += (available >> m_rcvWindShift);
149  }
150  else
151  {
152  newAwndKnownDifference += available;
153  }
154 
155  if (newAwndKnownDifference > m_maxWinSize)
156  {
157  newAwndKnownDifference = m_maxWinSize;
158  }
159 
160  if (static_cast<uint16_t>(newAwndKnownDifference) != oldAwnd)
161  {
162  if (!m_inwalidAwndCb.IsNull())
163  {
164  m_inwalidAwndCb(oldAwnd, newAwnd);
165  }
166  }
167  }
168  }
169 
170  return newAwnd;
171 }
172 
180 uint16_t
182 {
183  NS_LOG_FUNCTION(this << scale);
184  // NS_LOG_DEBUG ("MaxRxSequence () = " << m_tcb->m_rxBuffer->MaxRxSequence ());
185  // NS_LOG_DEBUG ("NextRxSequence () = " << m_tcb->m_rxBuffer->NextRxSequence ());
186  // NS_LOG_DEBUG ("MaxBufferSize () = " << m_tcb->m_rxBuffer->MaxBufferSize ());
187  // NS_LOG_DEBUG ("m_rcvWindShift = " << static_cast<uint16_t> (m_rcvWindShift));
188  // NS_LOG_DEBUG ("m_maxWinSize = " << m_maxWinSize);
189  // NS_LOG_DEBUG ("Available () = " << m_tcb->m_rxBuffer->Available ());
190  uint32_t w = m_tcb->m_rxBuffer->MaxBufferSize();
191 
192  if (scale)
193  {
194  w >>= m_rcvWindShift;
195  }
196  if (w > m_maxWinSize)
197  {
198  w = m_maxWinSize;
199  NS_LOG_WARN("Adv window size truncated to "
200  << m_maxWinSize << "; possibly to avoid overflow of the 16-bit integer");
201  }
202  NS_LOG_DEBUG("Returning AdvertisedWindowSize of " << static_cast<uint16_t>(w));
203  return static_cast<uint16_t>(w);
204 }
205 
207 
215 {
216  public:
221  static TypeId GetTypeId();
222 
227  TcpDropRatioErrorModel(double dropRatio)
229  m_dropRatio(dropRatio)
230  {
231  m_prng = CreateObject<UniformRandomVariable>();
232  }
233 
234  protected:
235  bool ShouldDrop(const Ipv4Header& ipHeader,
236  const TcpHeader& tcpHeader,
237  uint32_t packetSize) override;
238 
239  private:
240  void DoReset() override{};
241  double m_dropRatio;
243 };
244 
246 
247 TypeId
249 {
250  static TypeId tid = TypeId("ns3::TcpDropRatioErrorModel").SetParent<TcpGeneralErrorModel>();
251  return tid;
252 }
253 
254 bool
256  const TcpHeader& tcpHeader,
257  uint32_t packetSize)
258 {
259  return m_prng->GetValue() < m_dropRatio;
260 }
261 
286 {
287  public:
295  TcpAdvertisedWindowTest(const std::string& desc,
296  uint32_t size,
297  uint32_t packets,
298  double lossRatio);
299 
300  protected:
301  void ConfigureEnvironment() override;
302  Ptr<TcpSocketMsgBase> CreateReceiverSocket(Ptr<Node> node) override;
303  Ptr<ErrorModel> CreateReceiverErrorModel() override;
304 
305  private:
310  void InvalidAwndCb(uint16_t oldAwnd, uint16_t newAwnd);
311  uint32_t m_pktSize;
312  uint32_t m_pktCount;
313  double m_lossRatio;
314 };
315 
317  uint32_t size,
318  uint32_t packets,
319  double lossRatio)
320  : TcpGeneralTest(desc),
321  m_pktSize(size),
322  m_pktCount(packets),
323  m_lossRatio(lossRatio)
324 {
325 }
326 
327 void
329 {
330  TcpGeneralTest::ConfigureEnvironment();
335 }
336 
339 {
340  NS_LOG_FUNCTION(this);
341 
342  Ptr<TcpSocketMsgBase> sock =
344  DynamicCast<TcpSocketAdvertisedWindowProxy>(sock)->SetExpectedSegmentSize(500);
345  DynamicCast<TcpSocketAdvertisedWindowProxy>(sock)->SetInvalidAwndCb(
347 
348  return sock;
349 }
350 
353 {
354  return CreateObject<TcpDropRatioErrorModel>(m_lossRatio);
355 }
356 
357 void
358 TcpAdvertisedWindowTest::InvalidAwndCb(uint16_t oldAwnd, uint16_t newAwnd)
359 {
360  NS_TEST_ASSERT_MSG_EQ(oldAwnd, newAwnd, "Old and new AWND calculations do not match.");
361 }
362 
363 //-----------------------------------------------------------------------------
364 
371 {
372  public:
380  TcpAdvWindowOnLossTest(const std::string& desc,
381  uint32_t size,
382  uint32_t packets,
383  std::vector<uint32_t>& toDrop);
384 
385  protected:
386  void ConfigureEnvironment() override;
390 
391  private:
396  void InvalidAwndCb(uint16_t oldAwnd, uint16_t newAwnd);
397  uint32_t m_pktSize;
398  uint32_t m_pktCount;
399  std::vector<uint32_t> m_toDrop;
400 };
401 
403  uint32_t size,
404  uint32_t packets,
405  std::vector<uint32_t>& toDrop)
406  : TcpGeneralTest(desc),
407  m_pktSize(size),
408  m_pktCount(packets),
409  m_toDrop(toDrop)
410 {
411 }
412 
413 void
415 {
416  TcpGeneralTest::ConfigureEnvironment();
421 }
422 
425 {
426  NS_LOG_FUNCTION(this);
427 
428  Ptr<TcpSocketMsgBase> sock =
430  DynamicCast<TcpSocketAdvertisedWindowProxy>(sock)->SetExpectedSegmentSize(500);
431  DynamicCast<TcpSocketAdvertisedWindowProxy>(sock)->SetInvalidAwndCb(
433 
434  return sock;
435 }
436 
439 {
440  auto socket = TcpGeneralTest::CreateSenderSocket(node);
441  socket->SetAttribute("InitialCwnd", UintegerValue(10 * m_pktSize));
442 
443  return socket;
444 }
445 
448 {
449  Ptr<TcpSeqErrorModel> m_errorModel = CreateObject<TcpSeqErrorModel>();
450  for (auto it = m_toDrop.begin(); it != m_toDrop.end(); ++it)
451  {
452  m_errorModel->AddSeqToKill(SequenceNumber32(*it));
453  }
454 
455  return m_errorModel;
456 }
457 
458 void
459 TcpAdvWindowOnLossTest::InvalidAwndCb(uint16_t oldAwnd, uint16_t newAwnd)
460 {
461  NS_TEST_ASSERT_MSG_EQ(oldAwnd, newAwnd, "Old and new AWND calculations do not match.");
462 }
463 
464 //-----------------------------------------------------------------------------
465 
473 {
474  public:
476  : TestSuite("tcp-advertised-window-test", UNIT)
477  {
478  AddTestCase(new TcpAdvertisedWindowTest("TCP advertised window size, small seg + no loss",
479  500,
480  100,
481  0.0),
482  TestCase::QUICK);
483  AddTestCase(new TcpAdvertisedWindowTest("TCP advertised window size, small seg + loss",
484  500,
485  100,
486  0.1),
487  TestCase::QUICK);
488  AddTestCase(new TcpAdvertisedWindowTest("TCP advertised window size, large seg + no loss",
489  1000,
490  100,
491  0.0),
492  TestCase::QUICK);
493  AddTestCase(
494  new TcpAdvertisedWindowTest("TCP advertised window size, large seg + small loss",
495  1000,
496  100,
497  0.1),
498  TestCase::QUICK);
499  AddTestCase(new TcpAdvertisedWindowTest("TCP advertised window size, large seg + big loss",
500  1000,
501  100,
502  0.3),
503  TestCase::QUICK);
504  AddTestCase(new TcpAdvertisedWindowTest("TCP advertised window size, complete loss",
505  1000,
506  100,
507  1.0),
508  TestCase::QUICK);
509 
510  std::vector<uint32_t> toDrop;
511  toDrop.push_back(8001);
512  toDrop.push_back(9001);
513  AddTestCase(new TcpAdvWindowOnLossTest("TCP advertised window size, after FIN loss",
514  1000,
515  10,
516  toDrop));
517  }
518 };
519 
521  g_tcpAdvertisedWindowTestSuite; //<! static obj for test initialization
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.
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.
Ptr< TcpSocketMsgBase > CreateSenderSocket(Ptr< Node > node) override
Create and install the socket to install on the sender.
void ConfigureEnvironment() override
Change the configuration of the environment.
Ptr< ErrorModel > CreateReceiverErrorModel() override
Create and return the error model to install in the receiver node.
Ptr< TcpSocketMsgBase > CreateReceiverSocket(Ptr< Node > node) override
Create and install the socket to install on the receiver.
Test the new formula for calculating TCP's advertised window size.
Ptr< ErrorModel > CreateReceiverErrorModel() override
Create and return the error model to install in the receiver node.
Ptr< TcpSocketMsgBase > CreateReceiverSocket(Ptr< Node > node) override
Create and install the socket to install on the receiver.
void ConfigureEnvironment() override
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.
Test Suite for TCP adv window.
An error model that randomly drops a given rĂ¡tio of TCP segments.
static TypeId GetTypeId()
Get the type ID.
Ptr< UniformRandomVariable > m_prng
Random variable.
void DoReset() override
Re-initialize any state.
TcpDropRatioErrorModel(double dropRatio)
Constructor.
bool ShouldDrop(const Ipv4Header &ipHeader, const TcpHeader &tcpHeader, uint32_t packetSize) override
Check if the packet should be dropped.
Socket that wraps every call to AdvertisedWindowSize ().
Ptr< TcpSocketBase > Fork() override
Call CopyObject<> to clone me.
void SetInvalidAwndCb(InvalidAwndCallback cb)
Set the invalid AdvWnd callback.
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.
uint16_t AdvertisedWindowSize(bool scale=true) const override
The amount of Rx window announced to the peer.
static TypeId GetTypeId()
Get the type ID.
uint16_t OldAdvertisedWindowSize(bool scale=true) const
The legacy code used for calculating the advertised window.
bool IsNull() const
Check for null implementation.
Definition: callback.h:569
Packet header for IPv4.
Definition: ipv4-header.h:34
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
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:47
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:301
A suite of tests to run.
Definition: test.h:1256
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1265
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
Hold an unsigned integer type.
Definition: uinteger.h:45
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#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_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
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:144
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
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.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:704
static TcpAdvertisedWindowTestSuite g_tcpAdvertisedWindowTestSuite
static const uint32_t packetSize
Packet size generated at the AP.