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 {
231 }
232
233 double m_dropRatio; //!< Drop ratio
234 Ptr<UniformRandomVariable> m_prng; //!< Random variable
235};
236
238
239TypeId
241{
242 static TypeId tid = TypeId("ns3::TcpDropRatioErrorModel").SetParent<TcpGeneralErrorModel>();
243 return tid;
244}
245
246bool
248 const TcpHeader& tcpHeader,
250{
251 return m_prng->GetValue() < m_dropRatio;
252}
253
254/**
255 * \ingroup internet-test
256 * \ingroup tests
257 * \brief Test the new formula for calculating TCP's advertised window size.
258 *
259 * In TcpSocketBase, the advertised window is now calculated as
260 *
261 * m_tcb->m_rxBuffer->MaxRxSequence () - m_tcb->m_rxBuffer->NextRxSequence ()
262 *
263 * instead of the previous
264 *
265 * m_tcb->m_rxBuffer->MaxBufferSize ()
266 *
267 * This change was introduced with regard to situations in which the receiving
268 * application does not read from the socket as fast as possible (see bug 2559
269 * for details). This test ensures that no regression is introduced for other,
270 * "normal" cases.
271 *
272 * TcpGeneralTest ensures via ReceivePacket () that incoming packets are
273 * quickly consumed by the application layer, simulating a fast-reading
274 * application. We can only reasonably compare the old and the new AWND
275 * computation in this case.
276 */
278{
279 public:
280 /**
281 * \brief Constructor
282 * \param desc description
283 * \param size segment size
284 * \param packets number of packets to send
285 * \param lossRatio error ratio
286 */
287 TcpAdvertisedWindowTest(const std::string& desc,
288 uint32_t size,
289 uint32_t packets,
290 double lossRatio);
291
292 protected:
293 void ConfigureEnvironment() override;
296
297 private:
298 /**
299 * \brief Callback called for the update of the awnd
300 * \param oldAwnd Old advertised window
301 * \param newAwnd new value
302 */
303 void InvalidAwndCb(uint16_t oldAwnd, uint16_t newAwnd);
304 uint32_t m_pktSize; //!< Packet size
305 uint32_t m_pktCount; //!< Pkt count
306 double m_lossRatio; //!< Loss ratio
307};
308
310 uint32_t size,
311 uint32_t packets,
312 double lossRatio)
313 : TcpGeneralTest(desc),
314 m_pktSize(size),
315 m_pktCount(packets),
316 m_lossRatio(lossRatio)
317{
318}
319
320void
329
343
349
350void
351TcpAdvertisedWindowTest::InvalidAwndCb(uint16_t oldAwnd, uint16_t newAwnd)
352{
353 NS_TEST_ASSERT_MSG_EQ(oldAwnd, newAwnd, "Old and new AWND calculations do not match.");
354}
355
356//-----------------------------------------------------------------------------
357
358/**
359 * \ingroup internet-test
360 * \ingroup tests
361 * \brief Test the TCP's advertised window size when there is a loss of specific packets.
362 */
364{
365 public:
366 /**
367 * \brief Constructor
368 * \param desc description
369 * \param size segment size
370 * \param packets number of packets to send
371 * \param toDrop packets to be dropped
372 */
373 TcpAdvWindowOnLossTest(const std::string& desc,
374 uint32_t size,
375 uint32_t packets,
376 std::vector<uint32_t>& toDrop);
377
378 protected:
379 void ConfigureEnvironment() override;
383
384 private:
385 /**
386 * \brief Callback called for the update of the awnd
387 * \param oldAwnd Old advertised window
388 * \param newAwnd new value
389 */
390 void InvalidAwndCb(uint16_t oldAwnd, uint16_t newAwnd);
391 uint32_t m_pktSize; //!< Packet size
392 uint32_t m_pktCount; //!< Pkt count
393 std::vector<uint32_t> m_toDrop; //!< Sequences to drop
394};
395
397 uint32_t size,
398 uint32_t packets,
399 std::vector<uint32_t>& toDrop)
400 : TcpGeneralTest(desc),
401 m_pktSize(size),
402 m_pktCount(packets),
403 m_toDrop(toDrop)
404{
405}
406
407void
416
430
433{
434 auto socket = TcpGeneralTest::CreateSenderSocket(node);
435 socket->SetAttribute("InitialCwnd", UintegerValue(10 * m_pktSize));
436
437 return socket;
438}
439
442{
444 for (auto it = m_toDrop.begin(); it != m_toDrop.end(); ++it)
445 {
446 m_errorModel->AddSeqToKill(SequenceNumber32(*it));
447 }
448
449 return m_errorModel;
450}
451
452void
453TcpAdvWindowOnLossTest::InvalidAwndCb(uint16_t oldAwnd, uint16_t newAwnd)
454{
455 NS_TEST_ASSERT_MSG_EQ(oldAwnd, newAwnd, "Old and new AWND calculations do not match.");
456}
457
458//-----------------------------------------------------------------------------
459
460/**
461 * \ingroup internet-test
462 * \ingroup tests
463 *
464 * \brief Test Suite for TCP adv window
465 */
467{
468 public:
470 : TestSuite("tcp-advertised-window-test", Type::UNIT)
471 {
472 AddTestCase(new TcpAdvertisedWindowTest("TCP advertised window size, small seg + no loss",
473 500,
474 100,
475 0.0),
476 TestCase::Duration::QUICK);
477 AddTestCase(new TcpAdvertisedWindowTest("TCP advertised window size, small seg + loss",
478 500,
479 100,
480 0.1),
481 TestCase::Duration::QUICK);
482 AddTestCase(new TcpAdvertisedWindowTest("TCP advertised window size, large seg + no loss",
483 1000,
484 100,
485 0.0),
486 TestCase::Duration::QUICK);
488 new TcpAdvertisedWindowTest("TCP advertised window size, large seg + small loss",
489 1000,
490 100,
491 0.1),
492 TestCase::Duration::QUICK);
493 AddTestCase(new TcpAdvertisedWindowTest("TCP advertised window size, large seg + big loss",
494 1000,
495 100,
496 0.3),
497 TestCase::Duration::QUICK);
498 AddTestCase(new TcpAdvertisedWindowTest("TCP advertised window size, complete loss",
499 1000,
500 100,
501 1.0),
502 TestCase::Duration::QUICK);
503
504 std::vector<uint32_t> toDrop;
505 toDrop.push_back(8001);
506 toDrop.push_back(9001);
507 AddTestCase(new TcpAdvWindowOnLossTest("TCP advertised window size, after FIN loss",
508 1000,
509 10,
510 toDrop));
511 }
512};
513
515 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.