A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7#include "tcp-error-model.h"
8#include "tcp-general-test.h"
9
10#include "ns3/log.h"
11#include "ns3/node.h"
12#include "ns3/random-variable-stream.h"
13#include "ns3/tcp-rx-buffer.h"
14
15using namespace ns3;
16
17NS_LOG_COMPONENT_DEFINE("TcpAdvertisedWindowTestSuite");
18
19/**
20 * \ingroup internet-test
21 * \ingroup tests
22 * \brief Socket that wraps every call to AdvertisedWindowSize ().
23 */
24
26{
27 public:
28 /**
29 * \brief Get the type ID.
30 * \return the object TypeId
31 */
32 static TypeId GetTypeId();
33
34 /** \brief typedef for a cb */
36
37 /**
38 * \brief Constructor
39 */
45
46 /**
47 * \brief Copy-constructor
48 *
49 * \param other Other obj
50 */
57
58 /**
59 * \brief Set the invalid AdvWnd callback
60 *
61 * \param cb callback to set
62 */
64
65 /**
66 * \brief Set the expected segment size
67 *
68 * \param seg Segment size
69 */
70 void SetExpectedSegmentSize(uint16_t seg)
71 {
72 m_segmentSize = seg;
73 }
74
75 protected:
76 Ptr<TcpSocketBase> Fork() override;
77 uint16_t AdvertisedWindowSize(bool scale = true) const override;
78
79 private:
80 uint16_t OldAdvertisedWindowSize(bool scale = true) const;
82
83 /**
84 * \brief Test meta-information: size of the segments that are received.
85 *
86 * This is necessary for making sure the calculated awnd only differs by
87 * exactly that one segment that was not yet read by the application.
88 */
89 uint16_t m_segmentSize;
90};
91
92void
98
101{
102 static TypeId tid = TypeId("ns3::TcpSocketAdvertisedWindowProxy")
104 .SetGroupName("Internet")
105 .AddConstructor<TcpSocketAdvertisedWindowProxy>();
106 return tid;
107}
108
114
115uint16_t
117{
118 NS_LOG_FUNCTION(this << scale);
119
120 uint16_t newAwnd = TcpSocketMsgBase::AdvertisedWindowSize(scale);
121 uint16_t oldAwnd = OldAdvertisedWindowSize(scale);
122
123 if (!m_tcb->m_rxBuffer->Finished())
124 {
125 // The calculated windows will only be exactly equal if there is no data
126 // in the receive buffer yet.
127 if (newAwnd != oldAwnd)
128 {
129 uint32_t available = m_tcb->m_rxBuffer->Available();
130 // If the values differ, make sure this is only due to the single segment
131 // the socket just got, which has not yet been read by the application.
132 // Therefore, the difference should be exactly the size of one segment
133 // (but taking scale and m_maxWinSize into account).
134 uint32_t newAwndKnownDifference = newAwnd;
135 if (scale)
136 {
137 newAwndKnownDifference += (available >> m_rcvWindShift);
138 }
139 else
140 {
141 newAwndKnownDifference += available;
142 }
143
144 if (newAwndKnownDifference > m_maxWinSize)
145 {
146 newAwndKnownDifference = m_maxWinSize;
147 }
148
149 if (static_cast<uint16_t>(newAwndKnownDifference) != oldAwnd)
150 {
151 if (!m_inwalidAwndCb.IsNull())
152 {
153 m_inwalidAwndCb(oldAwnd, newAwnd);
154 }
155 }
156 }
157 }
158
159 return newAwnd;
160}
161
162/**
163 * The legacy code used for calculating the advertised window.
164 *
165 * This was copied from tcp-socket-base.cc before changing the formula.
166 * \param scale true if should scale the window
167 * \return the old adv wnd value
168 */
169uint16_t
171{
172 NS_LOG_FUNCTION(this << scale);
173 // NS_LOG_DEBUG ("MaxRxSequence () = " << m_tcb->m_rxBuffer->MaxRxSequence ());
174 // NS_LOG_DEBUG ("NextRxSequence () = " << m_tcb->m_rxBuffer->NextRxSequence ());
175 // NS_LOG_DEBUG ("MaxBufferSize () = " << m_tcb->m_rxBuffer->MaxBufferSize ());
176 // NS_LOG_DEBUG ("m_rcvWindShift = " << static_cast<uint16_t> (m_rcvWindShift));
177 // NS_LOG_DEBUG ("m_maxWinSize = " << m_maxWinSize);
178 // NS_LOG_DEBUG ("Available () = " << m_tcb->m_rxBuffer->Available ());
179 uint32_t w = m_tcb->m_rxBuffer->MaxBufferSize();
180
181 if (scale)
182 {
183 w >>= m_rcvWindShift;
184 }
185 if (w > m_maxWinSize)
186 {
187 w = m_maxWinSize;
188 NS_LOG_WARN("Adv window size truncated to "
189 << m_maxWinSize << "; possibly to avoid overflow of the 16-bit integer");
190 }
191 NS_LOG_DEBUG("Returning AdvertisedWindowSize of " << static_cast<uint16_t>(w));
192 return static_cast<uint16_t>(w);
193}
194
196
197/**
198 * \ingroup internet-test
199 * \ingroup tests
200 *
201 * \brief An error model that randomly drops a given rátio of TCP segments.
202 */
204{
205 public:
206 /**
207 * \brief Get the type ID.
208 * \return the object TypeId
209 */
210 static TypeId GetTypeId();
211
212 /**
213 * \brief Constructor
214 * \param dropRatio the drop ratio
215 */
216 TcpDropRatioErrorModel(double dropRatio)
218 m_dropRatio(dropRatio)
219 {
221 }
222
223 protected:
224 bool ShouldDrop(const Ipv4Header& ipHeader,
225 const TcpHeader& tcpHeader,
226 uint32_t packetSize) override;
227
228 private:
229 void DoReset() override{};
230 double m_dropRatio; //!< Drop ratio
231 Ptr<UniformRandomVariable> m_prng; //!< Random variable
232};
233
235
236TypeId
238{
239 static TypeId tid = TypeId("ns3::TcpDropRatioErrorModel").SetParent<TcpGeneralErrorModel>();
240 return tid;
241}
242
243bool
245 const TcpHeader& tcpHeader,
247{
248 return m_prng->GetValue() < m_dropRatio;
249}
250
251/**
252 * \ingroup internet-test
253 * \ingroup tests
254 * \brief Test the new formula for calculating TCP's advertised window size.
255 *
256 * In TcpSocketBase, the advertised window is now calculated as
257 *
258 * m_tcb->m_rxBuffer->MaxRxSequence () - m_tcb->m_rxBuffer->NextRxSequence ()
259 *
260 * instead of the previous
261 *
262 * m_tcb->m_rxBuffer->MaxBufferSize ()
263 *
264 * This change was introduced with regard to situations in which the receiving
265 * application does not read from the socket as fast as possible (see bug 2559
266 * for details). This test ensures that no regression is introduced for other,
267 * "normal" cases.
268 *
269 * TcpGeneralTest ensures via ReceivePacket () that incoming packets are
270 * quickly consumed by the application layer, simulating a fast-reading
271 * application. We can only reasonably compare the old and the new AWND
272 * computation in this case.
273 */
275{
276 public:
277 /**
278 * \brief Constructor
279 * \param desc description
280 * \param size segment size
281 * \param packets number of packets to send
282 * \param lossRatio error ratio
283 */
284 TcpAdvertisedWindowTest(const std::string& desc,
285 uint32_t size,
286 uint32_t packets,
287 double lossRatio);
288
289 protected:
290 void ConfigureEnvironment() override;
293
294 private:
295 /**
296 * \brief Callback called for the update of the awnd
297 * \param oldAwnd Old advertised window
298 * \param newAwnd new value
299 */
300 void InvalidAwndCb(uint16_t oldAwnd, uint16_t newAwnd);
301 uint32_t m_pktSize; //!< Packet size
302 uint32_t m_pktCount; //!< Pkt count
303 double m_lossRatio; //!< Loss ratio
304};
305
307 uint32_t size,
308 uint32_t packets,
309 double lossRatio)
310 : TcpGeneralTest(desc),
311 m_pktSize(size),
312 m_pktCount(packets),
313 m_lossRatio(lossRatio)
314{
315}
316
317void
326
340
346
347void
348TcpAdvertisedWindowTest::InvalidAwndCb(uint16_t oldAwnd, uint16_t newAwnd)
349{
350 NS_TEST_ASSERT_MSG_EQ(oldAwnd, newAwnd, "Old and new AWND calculations do not match.");
351}
352
353//-----------------------------------------------------------------------------
354
355/**
356 * \ingroup internet-test
357 * \ingroup tests
358 * \brief Test the TCP's advertised window size when there is a loss of specific packets.
359 */
361{
362 public:
363 /**
364 * \brief Constructor
365 * \param desc description
366 * \param size segment size
367 * \param packets number of packets to send
368 * \param toDrop packets to be dropped
369 */
370 TcpAdvWindowOnLossTest(const std::string& desc,
371 uint32_t size,
372 uint32_t packets,
373 std::vector<uint32_t>& toDrop);
374
375 protected:
376 void ConfigureEnvironment() override;
380
381 private:
382 /**
383 * \brief Callback called for the update of the awnd
384 * \param oldAwnd Old advertised window
385 * \param newAwnd new value
386 */
387 void InvalidAwndCb(uint16_t oldAwnd, uint16_t newAwnd);
388 uint32_t m_pktSize; //!< Packet size
389 uint32_t m_pktCount; //!< Pkt count
390 std::vector<uint32_t> m_toDrop; //!< Sequences to drop
391};
392
394 uint32_t size,
395 uint32_t packets,
396 std::vector<uint32_t>& toDrop)
397 : TcpGeneralTest(desc),
398 m_pktSize(size),
399 m_pktCount(packets),
400 m_toDrop(toDrop)
401{
402}
403
404void
413
427
430{
431 auto socket = TcpGeneralTest::CreateSenderSocket(node);
432 socket->SetAttribute("InitialCwnd", UintegerValue(10 * m_pktSize));
433
434 return socket;
435}
436
439{
441 for (auto it = m_toDrop.begin(); it != m_toDrop.end(); ++it)
442 {
443 m_errorModel->AddSeqToKill(SequenceNumber32(*it));
444 }
445
446 return m_errorModel;
447}
448
449void
450TcpAdvWindowOnLossTest::InvalidAwndCb(uint16_t oldAwnd, uint16_t newAwnd)
451{
452 NS_TEST_ASSERT_MSG_EQ(oldAwnd, newAwnd, "Old and new AWND calculations do not match.");
453}
454
455//-----------------------------------------------------------------------------
456
457/**
458 * \ingroup internet-test
459 * \ingroup tests
460 *
461 * \brief Test Suite for TCP adv window
462 */
464{
465 public:
467 : TestSuite("tcp-advertised-window-test", Type::UNIT)
468 {
469 AddTestCase(new TcpAdvertisedWindowTest("TCP advertised window size, small seg + no loss",
470 500,
471 100,
472 0.0),
473 TestCase::Duration::QUICK);
474 AddTestCase(new TcpAdvertisedWindowTest("TCP advertised window size, small seg + loss",
475 500,
476 100,
477 0.1),
478 TestCase::Duration::QUICK);
479 AddTestCase(new TcpAdvertisedWindowTest("TCP advertised window size, large seg + no loss",
480 1000,
481 100,
482 0.0),
483 TestCase::Duration::QUICK);
485 new TcpAdvertisedWindowTest("TCP advertised window size, large seg + small loss",
486 1000,
487 100,
488 0.1),
489 TestCase::Duration::QUICK);
490 AddTestCase(new TcpAdvertisedWindowTest("TCP advertised window size, large seg + big loss",
491 1000,
492 100,
493 0.3),
494 TestCase::Duration::QUICK);
495 AddTestCase(new TcpAdvertisedWindowTest("TCP advertised window size, complete loss",
496 1000,
497 100,
498 1.0),
499 TestCase::Duration::QUICK);
500
501 std::vector<uint32_t> toDrop;
502 toDrop.push_back(8001);
503 toDrop.push_back(9001);
504 AddTestCase(new TcpAdvWindowOnLossTest("TCP advertised window size, after FIN loss",
505 1000,
506 10,
507 toDrop));
508 }
509};
510
512 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.
Callback template class.
Definition callback.h:422
bool IsNull() const
Check for null implementation.
Definition callback.h:555
Packet header for IPv4.
Definition ipv4-header.h:23
friend Ptr< T > CopyObject(Ptr< T > object)
Copy an Object.
Definition object.h:581
Smart pointer class similar to boost::intrusive_ptr.
A general (TCP-aware) error model.
General infrastructure for TCP testing.
virtual Ptr< TcpSocketMsgBase > CreateSenderSocket(Ptr< Node > node)
Create and install the socket to install on the sender.
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.
virtual void ConfigureEnvironment()
Change the configuration of the environment.
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:36
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.
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
static constexpr auto UNIT
Definition test.h:1291
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Hold an unsigned integer type.
Definition uinteger.h:34
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#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:250
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
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:134
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1320
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:684
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
static TcpAdvertisedWindowTestSuite g_tcpAdvertisedWindowTestSuite
static const uint32_t packetSize
Packet size generated at the AP.