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
26using namespace ns3;
27
28NS_LOG_COMPONENT_DEFINE ("TcpAdvertisedWindowTestSuite");
29
37{
38public:
43 static TypeId GetTypeId (void);
44
47
52 {
53 }
54
61 : TcpSocketMsgBase (other)
62 {
65 }
66
73
79 void SetExpectedSegmentSize (uint16_t seg) { m_segmentSize = seg; };
80
81protected:
82 virtual Ptr<TcpSocketBase> Fork ();
83 virtual uint16_t AdvertisedWindowSize (bool scale = true) const;
84
85private:
86 uint16_t OldAdvertisedWindowSize (bool scale = true) const;
88
95 uint16_t m_segmentSize;
96};
97
98void
100{
101 NS_ASSERT (!cb.IsNull ());
102 m_inwalidAwndCb = cb;
103}
104
105TypeId
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
122uint16_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
178uint16_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{
213public:
218 static TypeId GetTypeId (void);
223 TcpDropRatioErrorModel (double dropRatio)
224 : TcpGeneralErrorModel (), m_dropRatio(dropRatio)
225 {
226 m_prng = CreateObject<UniformRandomVariable> ();
227 }
228
229protected:
230 virtual bool ShouldDrop (const Ipv4Header &ipHeader, const TcpHeader &tcpHeader,
232
233private:
234 virtual void DoReset (void) { };
235 double m_dropRatio;
237};
238
240
241TypeId
243{
244 static TypeId tid = TypeId ("ns3::TcpDropRatioErrorModel")
246 ;
247 return tid;
248}
249
250bool
251TcpDropRatioErrorModel::ShouldDrop (const Ipv4Header &ipHeader, const TcpHeader &tcpHeader,
253{
254 return m_prng->GetValue () < m_dropRatio;
255}
256
281{
282public:
290 TcpAdvertisedWindowTest (const std::string &desc, uint32_t size, uint32_t packets, double lossRatio);
291
292protected:
293 virtual void ConfigureEnvironment ();
296
297private:
302 void InvalidAwndCb (uint16_t oldAwnd, uint16_t newAwnd);
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
317void
319{
320 TcpGeneralTest::ConfigureEnvironment ();
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
347void
348TcpAdvertisedWindowTest::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{
362public:
370 TcpAdvWindowOnLossTest (const std::string &desc, uint32_t size, uint32_t packets,
371 std::vector<uint32_t> &toDrop);
372
373protected:
374 virtual void ConfigureEnvironment ();
378
379private:
384 void InvalidAwndCb (uint16_t oldAwnd, uint16_t newAwnd);
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
400void
402{
403 TcpGeneralTest::ConfigureEnvironment ();
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
444void
445TcpAdvWindowOnLossTest::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{
461public:
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
484static 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.
uint16_t m_maxWinSize
Maximum window size to advertise.
uint8_t m_rcvWindShift
Window shift to apply to outgoing segments.
Ptr< TcpSocketState > m_tcb
Congestion control information.
Class for inserting callbacks special points of the flow of TCP sockets.
Ptr< TcpRxBuffer > m_rxBuffer
Rx buffer (reordering buffer)
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
double GetValue(double min, double max)
Get the next random value, as a double in the specified range .
#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
Pcket size generated at the AP.