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),
477 AddTestCase(new TcpAdvertisedWindowTest("TCP advertised window size, small seg + loss",
478 500,
479 100,
480 0.1),
482 AddTestCase(new TcpAdvertisedWindowTest("TCP advertised window size, large seg + no loss",
483 1000,
484 100,
485 0.0),
488 new TcpAdvertisedWindowTest("TCP advertised window size, large seg + small loss",
489 1000,
490 100,
491 0.1),
493 AddTestCase(new TcpAdvertisedWindowTest("TCP advertised window size, large seg + big loss",
494 1000,
495 100,
496 0.3),
498 AddTestCase(new TcpAdvertisedWindowTest("TCP advertised window size, complete loss",
499 1000,
500 100,
501 1.0),
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
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:66
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.
TcpGeneralTest(const std::string &desc)
TcpGeneralTest constructor.
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.
virtual uint16_t AdvertisedWindowSize(bool scale=true) const
The amount of Rx window announced to the peer.
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
@ QUICK
Fast test.
Definition test.h:1055
Type
Type of test.
Definition test.h:1274
TestSuite(std::string name, Type type=Type::UNIT)
Construct a new test suite.
Definition test.cc:490
static constexpr auto UNIT
Definition test.h:1291
a unique identifier for an interface.
Definition type-id.h:49
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:1345
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1357
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
Ptr< T > CopyObject(Ptr< const T > object)
Definition object.h:581
static TcpAdvertisedWindowTestSuite g_tcpAdvertisedWindowTestSuite
static const uint32_t packetSize
Packet size generated at the AP.