A Discrete-Event Network Simulator
API
tbf-queue-disc-test-suite.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2017 Kungliga Tekniska Högskolan
4  * 2017 Universita' degli Studi di Napoli Federico II
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Authors: Surya Seetharaman <suryaseetharaman.9@gmail.com>
20  * Stefano Avallone <stavallo@unina.it>
21  */
22 
23 #include "ns3/test.h"
24 #include "ns3/tbf-queue-disc.h"
25 #include "ns3/packet.h"
26 #include "ns3/uinteger.h"
27 #include "ns3/string.h"
28 #include "ns3/double.h"
29 #include "ns3/log.h"
30 #include "ns3/simulator.h"
31 #include "ns3/node-container.h"
32 #include "ns3/simple-net-device.h"
33 #include "ns3/simple-channel.h"
34 #include "ns3/traffic-control-layer.h"
35 #include "ns3/config.h"
36 
37 using namespace ns3;
38 
46 public:
53  TbfQueueDiscTestItem (Ptr<Packet> p, const Address & addr);
54  virtual ~TbfQueueDiscTestItem ();
55  virtual void AddHeader (void);
56  virtual bool Mark (void);
57 
58 private:
70  TbfQueueDiscTestItem &operator = (const TbfQueueDiscTestItem &);
71 };
72 
74  : QueueDiscItem (p, addr, 0)
75 {
76 }
77 
79 {
80 }
81 
82 void
84 {
85 }
86 
87 bool
89 {
90  return false;
91 }
92 
100 {
101 public:
103  virtual void DoRun (void);
104 private:
111  void Enqueue (Ptr<TbfQueueDisc> queue, Address dest, uint32_t size);
118  void DequeueAndCheck (Ptr<TbfQueueDisc> queue, bool flag, std::string printStatement);
123  void RunTbfTest (QueueSizeUnit mode);
124 };
125 
127  : TestCase ("Sanity check on the TBF queue implementation")
128 {
129 }
130 
131 void
133 {
134  uint32_t pktSize = 1500;
135  // 1 for packets; pktSize for bytes
136  uint32_t modeSize = 1;
137  uint32_t qSize = 4;
138  uint32_t burst = 6000;
139  uint32_t mtu = 0;
140  DataRate rate = DataRate ("6KB/s");
141  DataRate peakRate = DataRate ("0KB/s");
142 
143  Ptr<TbfQueueDisc> queue = CreateObject<TbfQueueDisc> ();
144 
145  // test 1: Simple Enqueue/Dequeue with verification of attribute setting
146  /* 1. There is no second bucket since "peakRate" is set to 0.
147  2. A simple enqueue of five packets, each containing 1500B is followed by
148  the dequeue those five packets.
149  3. The subtraction of tokens from the first bucket to send out each of the
150  five packets is monitored and verified.
151  Note : The number of tokens in the first bucket is full at the beginning.
152  With the dequeuing of each packet, the number of tokens keeps decreasing.
153  So packets are dequeued as long as there are enough tokens in the bucket. */
154 
155  if (mode == QueueSizeUnit::BYTES)
156  {
157  modeSize = pktSize;
158  qSize = qSize * modeSize;
159  }
160 
161  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
162  true, "Verify that we can actually set the attribute MaxSize");
163  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Burst", UintegerValue (burst)), true,
164  "Verify that we can actually set the attribute Burst");
165  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mtu", UintegerValue (mtu)), true,
166  "Verify that we can actually set the attribute Mtu");
167  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Rate", DataRateValue (rate)), true,
168  "Verify that we can actually set the attribute Rate");
169  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("PeakRate", DataRateValue (peakRate)), true,
170  "Verify that we can actually set the attribute PeakRate");
171 
172  Address dest;
173 
174  Ptr<Packet> p1, p2, p3, p4, p5;
175  p1 = Create<Packet> (pktSize);
176  p2 = Create<Packet> (pktSize);
177  p3 = Create<Packet> (pktSize);
178  p4 = Create<Packet> (pktSize);
179  p5 = Create<Packet> (pktSize);
180 
181  queue->Initialize ();
182  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 0 * modeSize, "There should be no packets in there");
183  queue->Enqueue (Create<TbfQueueDiscTestItem> (p1, dest));
184  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 1 * modeSize, "There should be one packet in there");
185  queue->Enqueue (Create<TbfQueueDiscTestItem> (p2, dest));
186  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 2 * modeSize, "There should be two packets in there");
187  queue->Enqueue (Create<TbfQueueDiscTestItem> (p3, dest));
188  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 3 * modeSize, "There should be three packets in there");
189  queue->Enqueue (Create<TbfQueueDiscTestItem> (p4, dest));
190  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 4 * modeSize, "There should be four packets in there");
191  queue->Enqueue (Create<TbfQueueDiscTestItem> (p5, dest));
192  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 4 * modeSize,
193  "There should still be four packets in there as this enqueue cannot happen since QueueLimit will be exceeded");
194 
195  Ptr<QueueDiscItem> item;
196  NS_TEST_EXPECT_MSG_EQ (queue->GetFirstBucketTokens (), burst, "The first token bucket should be full");
197  item = queue->Dequeue ();
198  NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the first packet");
199  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 3 * modeSize, "There should be three packets in there");
200  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p1->GetUid (), "was this the first packet ?");
201  NS_TEST_EXPECT_MSG_EQ (queue->GetFirstBucketTokens (), burst - (1 * pktSize),
202  "The number of tokens in the first bucket should be one pktSize lesser");
203 
204  item = queue->Dequeue ();
205  NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the second packet");
206  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 2 * modeSize, "There should be two packets in there");
207  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p2->GetUid (), "Was this the second packet ?");
208  NS_TEST_EXPECT_MSG_EQ (queue->GetFirstBucketTokens (), burst - (2 * pktSize),
209  "The number of tokens in the first bucket should be two pktSizes lesser");
210 
211  item = queue->Dequeue ();
212  NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the third packet");
213  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 1 * modeSize, "There should be one packet in there");
214  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p3->GetUid (), "Was this the third packet ?");
215  NS_TEST_EXPECT_MSG_EQ (queue->GetFirstBucketTokens (), burst - (3 * pktSize),
216  "The number of tokens in the first bucket should be three pktSizes lesser");
217 
218  item = queue->Dequeue ();
219  NS_TEST_EXPECT_MSG_EQ ((item != 0), true, "I want to remove the fourth packet");
220  NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 0 * modeSize, "There should be zero packet in there");
221  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p4->GetUid (), "Was this the fourth packet ?");
222  NS_TEST_EXPECT_MSG_EQ (queue->GetFirstBucketTokens (), burst - (4 * pktSize),
223  "The number of tokens in the first bucket should be four pktSizes lesser");
224 
225  // test 2 : When DataRate == FirstBucketTokenRate; packets should pass smoothly.
226  queue = CreateObject<TbfQueueDisc> ();
227  qSize = 10;
228  pktSize = 1000;
229  burst = 10000;
230  mtu = 1000;
231  rate = DataRate ("10KB/s");
232  peakRate = DataRate ("100KB/s");
233  uint32_t nPkt = qSize;
234 
235  if (mode == QueueSizeUnit::BYTES)
236  {
237  modeSize = pktSize;
238  qSize = qSize * modeSize;
239  }
240 
241  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
242  true, "Verify that we can actually set the attribute MaxSize");
243  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Burst", UintegerValue (burst)), true,
244  "Verify that we can actually set the attribute Burst");
245  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mtu", UintegerValue (mtu)), true,
246  "Verify that we can actually set the attribute Mtu");
247  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Rate", DataRateValue (rate)), true,
248  "Verify that we can actually set the attribute Rate");
249  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("PeakRate", DataRateValue (peakRate)), true,
250  "Verify that we can actually set the attribute PeakRate");
251 
252  queue->Initialize ();
253  double delay = 0.09;
254  for (uint32_t i = 1; i <= nPkt; i++)
255  {
256  Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &TbfQueueDiscTestCase::Enqueue, this, queue, dest, pktSize);
257  }
258  delay = 0.1;
259  for (uint32_t i = 1; i <= nPkt; i++)
260  {
261  Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &TbfQueueDiscTestCase::DequeueAndCheck, this,
262  queue, true, "No packet should be blocked");
263  }
264  Simulator::Stop (Seconds (1));
265  Simulator::Run ();
266 
267  // test 3 : When DataRate >>> FirstBucketTokenRate; some packets should get blocked and waking of queue should get scheduled.
268  /* 10 packets are enqueued and then dequeued. Since the token rate is less than the data rate, the last packet i.e the 10th
269  packet gets blocked and waking of queue is scheduled after a time when enough tokens will be available. At that time the
270  10th packet passes through. */
271  queue = CreateObject<TbfQueueDisc> ();
272 
273  Config::SetDefault ("ns3::QueueDisc::Quota", UintegerValue (1));
274  NodeContainer nodesA;
275  nodesA.Create (2);
276  Ptr<SimpleNetDevice> txDevA = CreateObject<SimpleNetDevice> ();
277  nodesA.Get (0)->AddDevice (txDevA);
278  Ptr<SimpleNetDevice> rxDevA = CreateObject<SimpleNetDevice> ();
279  nodesA.Get (1)->AddDevice (rxDevA);
280  Ptr<SimpleChannel> channelA = CreateObject<SimpleChannel> ();
281  txDevA->SetChannel (channelA);
282  rxDevA->SetChannel (channelA);
283  txDevA->SetNode (nodesA.Get (0));
284  rxDevA->SetNode (nodesA.Get (1));
285 
286  dest = txDevA->GetAddress ();
287 
288  Ptr<TrafficControlLayer> tcA = CreateObject<TrafficControlLayer> ();
289  nodesA.Get (0)->AggregateObject (tcA);
290  queue->SetNetDevice (txDevA);
291  tcA->SetRootQueueDiscOnDevice (txDevA, queue);
292  tcA->Initialize ();
293 
294  burst = 5000;
295  mtu = 1000;
296  rate = DataRate ("5KB/s");
297  peakRate = DataRate ("100KB/s");
298 
299  if (mode == QueueSizeUnit::BYTES)
300  {
301  modeSize = pktSize;
302  qSize = qSize * modeSize;
303  }
304 
305  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
306  true, "Verify that we can actually set the attribute MaxSize");
307  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Burst", UintegerValue (burst)), true,
308  "Verify that we can actually set the attribute Burst");
309  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mtu", UintegerValue (mtu)), true,
310  "Verify that we can actually set the attribute Mtu");
311  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Rate", DataRateValue (rate)), true,
312  "Verify that we can actually set the attribute Rate");
313  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("PeakRate", DataRateValue (peakRate)), true,
314  "Verify that we can actually set the attribute PeakRate");
315 
316  delay = 0.09;
317  for (uint32_t i = 1; i <= nPkt; i++)
318  {
319  Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &TbfQueueDiscTestCase::Enqueue, this, queue, dest, pktSize);
320  }
321  delay = 0.1;
322  for (uint32_t i = 1; i <= nPkt; i++)
323  {
324  if (i == 10)
325  {
326  Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &TbfQueueDiscTestCase::DequeueAndCheck, this,
327  queue, false, "10th packet should be blocked");
328  }
329  else
330  {
331  Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &TbfQueueDiscTestCase::DequeueAndCheck, this,
332  queue, true, "This packet should not be blocked");
333  }
334  }
335  Simulator::Stop (Seconds (1.3));
336  Simulator::Run ();
337 
338  // test 4 : When DataRate < FirstBucketTokenRate; burst condition, peakRate is set so that bursts are controlled.
339  /* This test checks the burst control ability of TBF. 10 packets each of size 1000 bytes are enqueued followed by
340  their dequeue. The data rate (25 KB/s) is not sufficiently higher than the btokens rate (15 KB/s), so that in
341  the startup phase the first bucket is not empty. Hence when adequate tokens are present in the second bucket,
342  the packets get transmitted, otherwise they are blocked. So basically the transmission of packets falls under the
343  regulation of the second bucket since first bucket will always have excess tokens. TBF does not let all
344  the packets go smoothly without any control just because there are excess tokens in the first bucket. */
345  queue = CreateObject<TbfQueueDisc> ();
346 
347  Config::SetDefault ("ns3::QueueDisc::Quota", UintegerValue (1));
348  NodeContainer nodesB;
349  nodesB.Create (2);
350  Ptr<SimpleNetDevice> txDevB = CreateObject<SimpleNetDevice> ();
351  nodesB.Get (0)->AddDevice (txDevB);
352  Ptr<SimpleNetDevice> rxDevB = CreateObject<SimpleNetDevice> ();
353  nodesB.Get (1)->AddDevice (rxDevB);
354  Ptr<SimpleChannel> channelB = CreateObject<SimpleChannel> ();
355  txDevB->SetChannel (channelB);
356  rxDevB->SetChannel (channelB);
357  txDevB->SetNode (nodesB.Get (0));
358  rxDevB->SetNode (nodesB.Get (1));
359 
360  dest = txDevB->GetAddress ();
361 
362  Ptr<TrafficControlLayer> tcB = CreateObject<TrafficControlLayer> ();
363  nodesB.Get (0)->AggregateObject (tcB);
364  queue->SetNetDevice (txDevB);
365  tcB->SetRootQueueDiscOnDevice (txDevB, queue);
366  tcB->Initialize ();
367 
368  burst = 15000;
369  mtu = 1000;
370  rate = DataRate ("15KB/s");
371  peakRate = DataRate ("20KB/s");
372 
373  if (mode == QueueSizeUnit::BYTES)
374  {
375  modeSize = pktSize;
376  qSize = qSize * modeSize;
377  }
378 
379  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
380  true, "Verify that we can actually set the attribute MaxSize");
381  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Burst", UintegerValue (burst)), true,
382  "Verify that we can actually set the attribute Burst");
383  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mtu", UintegerValue (mtu)), true,
384  "Verify that we can actually set the attribute Mtu");
385  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Rate", DataRateValue (rate)), true,
386  "Verify that we can actually set the attribute Rate");
387  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("PeakRate", DataRateValue (peakRate)), true,
388  "Verify that we can actually set the attribute PeakRate");
389 
390  queue->Initialize ();
391  delay = 0.04;
392  for (uint32_t i = 1; i <= nPkt; i++)
393  {
394  Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &TbfQueueDiscTestCase::Enqueue, this, queue, dest, pktSize);
395  }
396 
397  for (uint32_t i = 1; i <= nPkt; i++)
398  {
399  if (i % 2 == 1)
400  {
401  Simulator::Schedule (Time (Seconds ((i + 1) * delay + 0.02)), &TbfQueueDiscTestCase::DequeueAndCheck, this,
402  queue, true, "1st packet should not be blocked");
403  }
404  else
405  {
406  Simulator::Schedule (Time (Seconds ((i + 1) * delay + 0.02)), &TbfQueueDiscTestCase::DequeueAndCheck, this,
407  queue, false, "This packet should be blocked");
408  }
409  }
410  Simulator::Stop (Seconds (0.55));
411  Simulator::Run ();
412 
413 }
414 
415 void
417 {
418  queue->Enqueue (Create<TbfQueueDiscTestItem> (Create<Packet> (size), dest));
419 }
420 
421 void
422 TbfQueueDiscTestCase::DequeueAndCheck (Ptr<TbfQueueDisc> queue, bool flag, std::string printStatement)
423 {
424  Ptr<QueueDiscItem> item = queue->Dequeue ();
425  NS_TEST_EXPECT_MSG_EQ ((item != 0), flag, printStatement);
426 }
427 
428 void
430 {
433  Simulator::Destroy ();
434 
435 }
436 
443 static class TbfQueueDiscTestSuite : public TestSuite
444 {
445 public:
447  : TestSuite ("tbf-queue-disc", UNIT)
448  {
449  AddTestCase (new TbfQueueDiscTestCase (), TestCase::QUICK);
450  }
Tbf Queue Disc Test Item.
Tbf Queue Disc Test Case.
uint64_t GetUid(void) const
Returns the packet&#39;s Uid.
Definition: packet.cc:390
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
uint32_t GetFirstBucketTokens(void) const
Get the current number of tokens inside the first bucket in bytes.
virtual void SetRootQueueDiscOnDevice(Ptr< NetDevice > device, Ptr< QueueDisc > qDisc)
This method can be used to set the root queue disc installed on a device.
Class for representing queue sizes.
Definition: queue-size.h:94
bool Enqueue(Ptr< QueueDiscItem > item)
Pass a packet to store to the queue discipline.
Definition: queue-disc.cc:844
uint32_t GetValue() const
Get the underlying value.
Definition: queue-size.cc:175
QueueSizeUnit
Enumeration of the operating modes of queues.
Definition: queue-size.h:42
QueueSize GetCurrentSize(void)
Get the current size of the queue disc in bytes, if operating in bytes mode, or packets, otherwise.
Definition: queue-disc.cc:523
A suite of tests to run.
Definition: test.h:1342
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition: object.cc:252
virtual void DoRun(void)
Implementation to actually run this TestCase.
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:285
bool SetAttributeFailSafe(std::string name, const AttributeValue &value)
Set a single attribute without raising errors.
Definition: object-base.cc:205
QueueDiscItem is the abstract base class for items that are stored in a queue disc.
Definition: queue-item.h:148
encapsulates test code
Definition: test.h:1155
TbfQueueDiscTestSuite g_tbfQueueTestSuite
the test suite
Tbf Queue Disc Test Suite.
a polymophic address class
Definition: address.h:90
Class for representing data rates.
Definition: data-rate.h:88
virtual void SetNode(Ptr< Node > node)
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
Hold an unsigned integer type.
Definition: uinteger.h:44
Use number of packets for queue size.
Definition: queue-size.h:44
void Enqueue(Ptr< TbfQueueDisc > queue, Address dest, uint32_t size)
Enqueue function.
void DequeueAndCheck(Ptr< TbfQueueDisc > queue, bool flag, std::string printStatement)
DequeueAndCheck function to check if a packet is blocked or not after dequeuing and verify against ex...
virtual Address GetAddress(void) const
virtual bool Mark(void)
Marks the packet as a substitute for dropping it, such as for Explicit Congestion Notification...
Ptr< QueueDiscItem > Dequeue(void)
Extract from the queue disc the packet that has been dequeued by calling Peek, if any...
Definition: queue-disc.cc:879
Every class exported by the ns3 library is enclosed in the ns3 namespace.
keep track of a set of node pointers.
uint32_t AddDevice(Ptr< NetDevice > device)
Associate a NetDevice to this node.
Definition: node.cc:128
AttributeValue implementation for DataRate.
Definition: data-rate.h:242
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1014
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:782
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
virtual void AddHeader(void)
Add the header to the packet.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
This test suite implements a Unit Test.
Definition: test.h:1352
void SetChannel(Ptr< SimpleChannel > channel)
Attach a channel to this net device.
Use number of bytes for queue size.
Definition: queue-size.h:45
void RunTbfTest(QueueSizeUnit mode)
Run TBF test function.
void Initialize(void)
Invoke DoInitialize on all Objects aggregated to this one.
Definition: object.cc:183
void SetNetDevice(Ptr< NetDevice > device)
Set the NetDevice on which this queue discipline is installed.
Definition: queue-disc.cc:539