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
26using namespace ns3;
27
28NS_LOG_COMPONENT_DEFINE("TcpAdvertisedWindowTestSuite");
29
37{
38 public:
43 static TypeId GetTypeId();
44
47
54 {
55 }
56
63 : TcpSocketMsgBase(other)
64 {
67 }
68
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
101};
102
103void
105{
106 NS_ASSERT(!cb.IsNull());
107 m_inwalidAwndCb = cb;
108}
109
110TypeId
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
126uint16_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
180uint16_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
247TypeId
249{
250 static TypeId tid = TypeId("ns3::TcpDropRatioErrorModel").SetParent<TcpGeneralErrorModel>();
251 return tid;
252}
253
254bool
256 const TcpHeader& tcpHeader,
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;
304
305 private:
310 void InvalidAwndCb(uint16_t oldAwnd, uint16_t newAwnd);
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
327void
329{
330 TcpGeneralTest::ConfigureEnvironment();
335}
336
339{
340 NS_LOG_FUNCTION(this);
341
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
357void
358TcpAdvertisedWindowTest::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);
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
413void
415{
416 TcpGeneralTest::ConfigureEnvironment();
421}
422
425{
426 NS_LOG_FUNCTION(this);
427
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 (std::vector<uint32_t>::iterator it = m_toDrop.begin(); it != m_toDrop.end(); ++it)
451 {
452 m_errorModel->AddSeqToKill(SequenceNumber32(*it));
453 }
454
455 return m_errorModel;
456}
457
458void
459TcpAdvWindowOnLossTest::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);
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:572
Packet header for IPv4.
Definition: ipv4-header.h:34
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
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:46
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:305
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:935
Hold an unsigned integer type.
Definition: uinteger.h:45
double GetValue(double min, double max)
Get the next random value drawn from the distribution.
#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:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
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:707
static TcpAdvertisedWindowTestSuite g_tcpAdvertisedWindowTestSuite
static const uint32_t packetSize
Packet size generated at the AP.