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  tcA->SetRootQueueDiscOnDevice (txDevA, queue);
291  tcA->Initialize ();
292 
293  burst = 5000;
294  mtu = 1000;
295  rate = DataRate ("5KB/s");
296  peakRate = DataRate ("100KB/s");
297 
298  if (mode == QueueSizeUnit::BYTES)
299  {
300  modeSize = pktSize;
301  qSize = qSize * modeSize;
302  }
303 
304  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
305  true, "Verify that we can actually set the attribute MaxSize");
306  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Burst", UintegerValue (burst)), true,
307  "Verify that we can actually set the attribute Burst");
308  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mtu", UintegerValue (mtu)), true,
309  "Verify that we can actually set the attribute Mtu");
310  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Rate", DataRateValue (rate)), true,
311  "Verify that we can actually set the attribute Rate");
312  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("PeakRate", DataRateValue (peakRate)), true,
313  "Verify that we can actually set the attribute PeakRate");
314 
315  delay = 0.09;
316  for (uint32_t i = 1; i <= nPkt; i++)
317  {
318  Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &TbfQueueDiscTestCase::Enqueue, this, queue, dest, pktSize);
319  }
320  delay = 0.1;
321  for (uint32_t i = 1; i <= nPkt; i++)
322  {
323  if (i == 10)
324  {
325  Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &TbfQueueDiscTestCase::DequeueAndCheck, this,
326  queue, false, "10th packet should be blocked");
327  }
328  else
329  {
330  Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &TbfQueueDiscTestCase::DequeueAndCheck, this,
331  queue, true, "This packet should not be blocked");
332  }
333  }
334  Simulator::Stop (Seconds (1.3));
335  Simulator::Run ();
336 
337  // test 4 : When DataRate < FirstBucketTokenRate; burst condition, peakRate is set so that bursts are controlled.
338  /* This test checks the burst control ability of TBF. 10 packets each of size 1000 bytes are enqueued followed by
339  their dequeue. The data rate (25 KB/s) is not sufficiently higher than the btokens rate (15 KB/s), so that in
340  the startup phase the first bucket is not empty. Hence when adequate tokens are present in the second bucket,
341  the packets get transmitted, otherwise they are blocked. So basically the transmission of packets falls under the
342  regulation of the second bucket since first bucket will always have excess tokens. TBF does not let all
343  the packets go smoothly without any control just because there are excess tokens in the first bucket. */
344  queue = CreateObject<TbfQueueDisc> ();
345 
346  Config::SetDefault ("ns3::QueueDisc::Quota", UintegerValue (1));
347  NodeContainer nodesB;
348  nodesB.Create (2);
349  Ptr<SimpleNetDevice> txDevB = CreateObject<SimpleNetDevice> ();
350  nodesB.Get (0)->AddDevice (txDevB);
351  Ptr<SimpleNetDevice> rxDevB = CreateObject<SimpleNetDevice> ();
352  nodesB.Get (1)->AddDevice (rxDevB);
353  Ptr<SimpleChannel> channelB = CreateObject<SimpleChannel> ();
354  txDevB->SetChannel (channelB);
355  rxDevB->SetChannel (channelB);
356  txDevB->SetNode (nodesB.Get (0));
357  rxDevB->SetNode (nodesB.Get (1));
358 
359  dest = txDevB->GetAddress ();
360 
361  Ptr<TrafficControlLayer> tcB = CreateObject<TrafficControlLayer> ();
362  nodesB.Get (0)->AggregateObject (tcB);
363  tcB->SetRootQueueDiscOnDevice (txDevB, queue);
364  tcB->Initialize ();
365 
366  burst = 15000;
367  mtu = 1000;
368  rate = DataRate ("15KB/s");
369  peakRate = DataRate ("20KB/s");
370 
371  if (mode == QueueSizeUnit::BYTES)
372  {
373  modeSize = pktSize;
374  qSize = qSize * modeSize;
375  }
376 
377  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))),
378  true, "Verify that we can actually set the attribute MaxSize");
379  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Burst", UintegerValue (burst)), true,
380  "Verify that we can actually set the attribute Burst");
381  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mtu", UintegerValue (mtu)), true,
382  "Verify that we can actually set the attribute Mtu");
383  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Rate", DataRateValue (rate)), true,
384  "Verify that we can actually set the attribute Rate");
385  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("PeakRate", DataRateValue (peakRate)), true,
386  "Verify that we can actually set the attribute PeakRate");
387 
388  queue->Initialize ();
389  delay = 0.04;
390  for (uint32_t i = 1; i <= nPkt; i++)
391  {
392  Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &TbfQueueDiscTestCase::Enqueue, this, queue, dest, pktSize);
393  }
394 
395  for (uint32_t i = 1; i <= nPkt; i++)
396  {
397  if (i % 2 == 1)
398  {
399  Simulator::Schedule (Time (Seconds ((i + 1) * delay + 0.02)), &TbfQueueDiscTestCase::DequeueAndCheck, this,
400  queue, true, "1st packet should not be blocked");
401  }
402  else
403  {
404  Simulator::Schedule (Time (Seconds ((i + 1) * delay + 0.02)), &TbfQueueDiscTestCase::DequeueAndCheck, this,
405  queue, false, "This packet should be blocked");
406  }
407  }
408  Simulator::Stop (Seconds (0.55));
409  Simulator::Run ();
410 
411 }
412 
413 void
415 {
416  queue->Enqueue (Create<TbfQueueDiscTestItem> (Create<Packet> (size), dest));
417 }
418 
419 void
420 TbfQueueDiscTestCase::DequeueAndCheck (Ptr<TbfQueueDisc> queue, bool flag, std::string printStatement)
421 {
422  Ptr<QueueDiscItem> item = queue->Dequeue ();
423  NS_TEST_EXPECT_MSG_EQ ((item != 0), flag, printStatement);
424 }
425 
426 void
428 {
431  Simulator::Destroy ();
432 
433 }
434 
441 static class TbfQueueDiscTestSuite : public TestSuite
442 {
443 public:
445  : TestSuite ("tbf-queue-disc", UNIT)
446  {
447  AddTestCase (new TbfQueueDiscTestCase (), TestCase::QUICK);
448  }
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:103
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:861
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:1343
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:283
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:1153
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:896
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:130
AttributeValue implementation for DataRate.
Definition: data-rate.h:298
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:849
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:1353
uint32_t pktSize
packet size used for the simulation (in bytes)
Definition: wifi-bianchi.cc:86
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(* DataRate)(DataRate oldValue, DataRate newValue)
TracedValue callback signature for DataRate.
Definition: data-rate.h:329
void Initialize(void)
Invoke DoInitialize on all Objects aggregated to this one.
Definition: object.cc:183