A Discrete-Event Network Simulator
API
tc-flow-control-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 Universita' degli Studi di Napoli Federico II
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Stefano Avallone <stavallo@unina.it>
19  *
20  */
21 
22 #include "ns3/test.h"
23 #include "ns3/uinteger.h"
24 #include "ns3/pointer.h"
25 #include "ns3/string.h"
26 #include "ns3/double.h"
27 #include "ns3/log.h"
28 #include "ns3/simulator.h"
29 #include "ns3/node-container.h"
30 #include "ns3/traffic-control-layer.h"
31 #include "ns3/traffic-control-helper.h"
32 #include "ns3/simple-net-device.h"
33 #include "ns3/simple-channel.h"
34 #include "ns3/drop-tail-queue.h"
35 #include "ns3/net-device-queue-interface.h"
36 #include "ns3/config.h"
37 
38 using namespace ns3;
39 
47 public:
54  virtual ~QueueDiscTestItem ();
55  virtual void AddHeader (void);
56  virtual bool Mark(void);
57 
58 private:
70  QueueDiscTestItem &operator = (const QueueDiscTestItem &);
71 };
72 
74  : QueueDiscItem (p, Mac48Address (), 0)
75 {
76 }
77 
79 {
80 }
81 
82 void
84 {
85 }
86 
87 bool
89 {
90  return false;
91 }
92 
100 {
101 public:
103  enum TestType
104  {
107  };
108 
115  virtual ~TcFlowControlTestCase ();
116 private:
117  virtual void DoRun (void);
123  void SendPackets (Ptr<Node> n, uint16_t nPackets);
130  void CheckPacketsInDeviceQueue (Ptr<NetDevice> dev, uint16_t nPackets, const char* msg);
137  void CheckDeviceQueueStopped (Ptr<NetDevice> dev, bool value, const char* msg);
144  void CheckPacketsInQueueDisc (Ptr<NetDevice> dev, uint16_t nPackets, const char* msg);
146 };
147 
149  : TestCase ("Test the operation of the flow control mechanism"),
150  m_type (tt)
151 {
152 }
153 
155 {
156 }
157 
158 void
160 {
162  for (uint16_t i = 0; i < nPackets; i++)
163  {
164  tc->Send (n->GetDevice (0), Create<QueueDiscTestItem> (Create<Packet> (1000)));
165  }
166 }
167 
168 void
169 TcFlowControlTestCase::CheckPacketsInDeviceQueue (Ptr<NetDevice> dev, uint16_t nPackets, const char* msg)
170 {
171  PointerValue ptr;
172  dev->GetAttributeFailSafe ("TxQueue", ptr);
173  Ptr<Queue<Packet> > queue = ptr.Get<Queue<Packet> > ();
174  NS_TEST_EXPECT_MSG_EQ (queue->GetNPackets (), nPackets, msg);
175 }
176 
177 void
179 {
181  NS_TEST_EXPECT_MSG_EQ (ndqi->GetTxQueue (0)->IsStopped (), value, msg);
182 }
183 
184 void
185 TcFlowControlTestCase::CheckPacketsInQueueDisc (Ptr<NetDevice> dev, uint16_t nPackets, const char* msg)
186 {
188  Ptr<QueueDisc> qdisc = tc->GetRootQueueDiscOnDevice (dev);
189  NS_TEST_EXPECT_MSG_EQ (qdisc->GetNPackets (), nPackets, msg);
190 }
191 
192 
193 void
195 {
196  NodeContainer n;
197  n.Create (2);
198 
199  n.Get (0)->AggregateObject (CreateObject<TrafficControlLayer> ());
200  n.Get (1)->AggregateObject (CreateObject<TrafficControlLayer> ());
201 
202  Ptr<Queue<Packet> > queue;
203 
204  if (m_type == PACKET_MODE)
205  {
206  queue = CreateObjectWithAttributes<DropTailQueue<Packet> > ("Mode", EnumValue (QueueBase::QUEUE_MODE_PACKETS),
207  "MaxPackets", UintegerValue (5));
208  }
209  else
210  {
211  queue = CreateObjectWithAttributes<DropTailQueue<Packet> > ("Mode", EnumValue (QueueBase::QUEUE_MODE_BYTES),
212  "MaxBytes", UintegerValue (5000));
213  }
214 
215  // link the two nodes
216  Ptr<SimpleNetDevice> txDev, rxDev;
217  txDev = CreateObjectWithAttributes<SimpleNetDevice> ("TxQueue", PointerValue (queue),
218  "DataRate", DataRateValue (DataRate ("1Mb/s")));
219  rxDev = CreateObject<SimpleNetDevice> ();
220  n.Get (0)->AddDevice (txDev);
221  n.Get (1)->AddDevice (rxDev);
222  Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel> ();
223  txDev->SetChannel (channel1);
224  rxDev->SetChannel (channel1);
225 
226  txDev->SetMtu (2500);
227 
228  TrafficControlHelper tch = TrafficControlHelper::Default ();
229  tch.Install (txDev);
230 
231  // transmit 10 packets at time 0
232  Simulator::Schedule (Time (Seconds (0)), &TcFlowControlTestCase::SendPackets,
233  this, n.Get (0), 10);
234 
235  if (m_type == PACKET_MODE)
236  {
237  /*
238  * When the device queue is in packet mode, all the packets enqueued in the
239  * queue disc are correctly transmitted, even if the device queue is stopped
240  * when the last packet is received from the upper layers
241  */
242 
243  // The transmission of each packet takes 1000B/1Mbps = 8ms
244  // After 1ms, we have 5 packets in the device queue (stopped) and 4 in the queue disc
246  this, txDev, 5, "There must be 5 packets in the device queue after 1ms");
248  this, txDev, true, "The device queue must be stopped after 1ms");
250  this, txDev, 4, "There must be 4 packets in the queue disc after 1ms");
251 
252  // After 9ms, we have 5 packets in the device queue (stopped) and 3 in the queue disc
254  this, txDev, 5, "There must be 5 packets in the device queue after 9ms");
256  this, txDev, true, "The device queue must be stopped after 9ms");
258  this, txDev, 3, "There must be 3 packets in the queue disc after 9ms");
259 
260  // After 17ms, we have 5 packets in the device queue (stopped) and 2 in the queue disc
262  this, txDev, 5, "There must be 5 packets in the device queue after 17ms");
264  this, txDev, true, "The device queue must be stopped after 17ms");
266  this, txDev, 2, "There must be 2 packets in the queue disc after 17ms");
267 
268  // After 25ms, we have 5 packets in the device queue (stopped) and 1 in the queue disc
270  this, txDev, 5, "There must be 5 packets in the device queue after 25ms");
272  this, txDev, true, "The device queue must be stopped after 25ms");
274  this, txDev, 1, "There must be 1 packet in the queue disc after 25ms");
275 
276  // After 33ms, we have 5 packets in the device queue (stopped) and the queue disc is empty
278  this, txDev, 5, "There must be 5 packets in the device queue after 33ms");
280  this, txDev, true, "The device queue must be stopped after 33ms");
282  this, txDev, 0, "The queue disc must be empty after 33ms");
283 
284  // After 41ms, we have 4 packets in the device queue (not stopped) and the queue disc is empty
286  this, txDev, 4, "There must be 4 packets in the device queue after 41ms");
288  this, txDev, false, "The device queue must not be stopped after 41ms");
290  this, txDev, 0, "The queue disc must be empty after 41ms");
291 
292  // After 81ms, all packets must have been transmitted (the device queue and the queue disc are empty)
294  this, txDev, 0, "The device queue must be empty after 81ms");
296  this, txDev, false, "The device queue must not be stopped after 81ms");
298  this, txDev, 0, "The queue disc must be empty after 81ms");
299  }
300  else
301  {
302  /*
303  * When the device queue is in byte mode, all the packets enqueued in the
304  * queue disc are correctly transmitted, even if the device queue is stopped
305  * when the last packet is received from the upper layers
306  */
307 
308  // The transmission of each packet takes 1000B/1Mbps = 8ms
309  // After 1ms, we have 3 packets in the device queue (stopped) and 6 in the queue disc
311  this, txDev, 3, "There must be 3 packets in the device queue after 1ms");
313  this, txDev, true, "The device queue must be stopped after 1ms");
315  this, txDev, 6, "There must be 6 packets in the queue disc after 1ms");
316 
317  // After 9ms, we have 3 packets in the device queue (stopped) and 5 in the queue disc
319  this, txDev, 3, "There must be 3 packets in the device queue after 9ms");
321  this, txDev, true, "The device queue must be stopped after 9ms");
323  this, txDev, 5, "There must be 5 packets in the queue disc after 9ms");
324 
325  // After 17ms, we have 3 packets in the device queue (stopped) and 4 in the queue disc
327  this, txDev, 3, "There must be 3 packets in the device queue after 17ms");
329  this, txDev, true, "The device queue must be stopped after 17ms");
331  this, txDev, 4, "There must be 4 packets in the queue disc after 17ms");
332 
333  // After 25ms, we have 3 packets in the device queue (stopped) and 3 in the queue disc
335  this, txDev, 3, "There must be 3 packets in the device queue after 25ms");
337  this, txDev, true, "The device queue must be stopped after 25ms");
339  this, txDev, 3, "There must be 3 packets in the queue disc after 25ms");
340 
341  // After 33ms, we have 3 packets in the device queue (stopped) and 2 in the queue disc
343  this, txDev, 3, "There must be 3 packets in the device queue after 33ms");
345  this, txDev, true, "The device queue must be stopped after 33ms");
347  this, txDev, 2, "There must be 2 packets in the queue disc after 33ms");
348 
349  // After 41ms, we have 3 packets in the device queue (stopped) and 1 in the queue disc
351  this, txDev, 3, "There must be 3 packets in the device queue after 41ms");
353  this, txDev, true, "The device queue must be stopped after 41ms");
355  this, txDev, 1, "There must be 1 packet in the queue disc after 41ms");
356 
357  // After 49ms, we have 3 packets in the device queue (stopped) and the queue disc is empty
359  this, txDev, 3, "There must be 3 packets in the device queue after 49ms");
361  this, txDev, true, "The device queue must be stopped after 49ms");
363  this, txDev, 0, "The queue disc must be empty after 49ms");
364 
365  // After 57ms, we have 2 packets in the device queue (not stopped) and the queue disc is empty
367  this, txDev, 2, "There must be 2 packets in the device queue after 57ms");
369  this, txDev, false, "The device queue must not be stopped after 57ms");
371  this, txDev, 0, "The queue disc must be empty after 57ms");
372 
373  // After 81ms, all packets must have been transmitted (the device queue and the queue disc are empty)
375  this, txDev, 0, "The device queue must be empty after 81ms");
377  this, txDev, false, "The device queue must not be stopped after 81ms");
379  this, txDev, 0, "The queue disc must be empty after 81ms");
380  }
381 
382  Simulator::Run ();
383  Simulator::Destroy ();
384 }
385 
392 static class TcFlowControlTestSuite : public TestSuite
393 {
394 public:
396  : TestSuite ("tc-flow-control", UNIT)
397  {
400  }
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
Ptr< T > Get(void) const
Definition: pointer.h:194
QueueDiscContainer Install(NetDeviceContainer c)
void CheckPacketsInDeviceQueue(Ptr< NetDevice > dev, uint16_t nPackets, const char *msg)
Check if the device queue stores the expected number of packets.
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:459
Introspection did not find any typical Config paths.
A suite of tests to run.
Definition: test.h:1342
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition: object.cc:252
virtual Ptr< Node > GetNode(void) const =0
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1001
#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
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
This test suite implements a Unit Test.
Definition: test.h:1352
bool GetAttributeFailSafe(std::string name, AttributeValue &value) const
Get the value of an attribute without raising erros.
Definition: object-base.cc:258
TcFlowControlTestCase(TestType tt)
Constructor.
void CheckPacketsInQueueDisc(Ptr< NetDevice > dev, uint16_t nPackets, const char *msg)
Check if the queue disc stores the expected number of packets.
Class for representing data rates.
Definition: data-rate.h:88
Hold variables of type enum.
Definition: enum.h:54
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
TestType
Device queue operating mode.
Hold an unsigned integer type.
Definition: uinteger.h:44
virtual bool SetMtu(const uint16_t mtu)
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:142
Build a set of QueueDisc objects.
Network device transmission queue interface.
void CheckDeviceQueueStopped(Ptr< NetDevice > dev, bool value, const char *msg)
Check if the device queue is in the expected status (stopped or not)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
keep track of a set of node pointers.
Hold objects of type Ptr.
Definition: pointer.h:36
virtual void AddHeader(void)
Add the header to the packet.
an EUI-48 address
Definition: mac48-address.h:43
virtual void Send(Ptr< NetDevice > device, Ptr< QueueDiscItem > item)
Called from upper layer to queue a packet for the transmission.
uint32_t AddDevice(Ptr< NetDevice > device)
Associate a NetDevice to this node.
Definition: node.cc:128
virtual bool Mark(void)
Marks the packet as a substitute for dropping it, such as for Explicit Congestion Notification...
virtual Ptr< QueueDisc > GetRootQueueDiscOnDevice(Ptr< NetDevice > device) const
This method can be used to get the root queue disc installed on a device.
AttributeValue implementation for DataRate.
Definition: data-rate.h:242
Ptr< Node > Get(uint32_t i) const
Get the Ptr stored in this container at a given index.
Ptr< NetDeviceQueue > GetTxQueue(uint8_t i) const
Get the i-th transmission queue of the device.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:993
TcFlowControlTestSuite g_tcFlowControlTestSuite
the test suite
virtual void DoRun(void)
Implementation to actually run this TestCase.
Queue Disc Test Item.
Traffic Control Flow Control Test Case.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Traffic Control Flow Control Test Suite.
void SendPackets(Ptr< Node > n, uint16_t nPackets)
Instruct a node to send a specified number of packets.
void SetChannel(Ptr< SimpleChannel > channel)
Attach a channel to this net device.