A Discrete-Event Network Simulator
API
prio-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 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 * Authors: Stefano Avallone <stavallo@unina.it>
19 *
20 */
21
22#include "ns3/test.h"
23#include "ns3/prio-queue-disc.h"
24#include "ns3/fifo-queue-disc.h"
25#include "ns3/packet-filter.h"
26#include "ns3/packet.h"
27#include "ns3/socket.h"
28#include "ns3/string.h"
29#include "ns3/log.h"
30#include "ns3/simulator.h"
31#include <array>
32#include <queue>
33
34using namespace ns3;
35
43{
44public:
52 PrioQueueDiscTestItem (Ptr<Packet> p, const Address & addr, uint8_t priority);
53 virtual ~PrioQueueDiscTestItem ();
54 virtual void AddHeader (void);
55 virtual bool Mark (void);
56};
57
59 : QueueDiscItem (p, addr, 0)
60{
61 SocketPriorityTag priorityTag;
62 priorityTag.SetPriority (priority);
63 p->ReplacePacketTag (priorityTag);
64}
65
67{
68}
69
70void
72{
73}
74
75bool
77{
78 return false;
79}
80
81
89{
90public:
96 PrioQueueDiscTestFilter (bool cls);
97 virtual ~PrioQueueDiscTestFilter ();
103 void SetReturnValue (int32_t ret);
104
105private:
106 virtual bool CheckProtocol (Ptr<QueueDiscItem> item) const;
107 virtual int32_t DoClassify (Ptr<QueueDiscItem> item) const;
108
109 bool m_cls;
111};
112
114 : m_cls (cls),
115 m_ret (0)
116{
117}
118
120{
121}
122
123void
125{
126 m_ret = ret;
127}
128
129bool
131{
132 return m_cls;
133}
134
137{
138 return m_ret;
139}
140
141
149{
150public:
152 virtual void DoRun (void);
153};
154
156 : TestCase ("Sanity check on the prio queue disc implementation")
157{
158}
159
160void
162{
163 Ptr<PrioQueueDisc> qdisc;
165 std::string priomap ("0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3");
166 Address dest;
167 std::array<std::queue<uint64_t>,4> uids;
168
169 /*
170 * Test 1: set priomap
171 */
172 qdisc = CreateObject<PrioQueueDisc> ();
173
174 // add 4 child fifo queue discs
175 for (uint8_t i = 0; i < 4; i++)
176 {
177 Ptr<FifoQueueDisc> child = CreateObject<FifoQueueDisc> ();
178 child->Initialize ();
179 Ptr<QueueDiscClass> c = CreateObject<QueueDiscClass> ();
180 c->SetQueueDisc (child);
181 qdisc->AddQueueDiscClass (c);
182 }
183 qdisc->Initialize ();
184
185 NS_TEST_ASSERT_MSG_EQ (qdisc->GetNQueueDiscClasses (), 4, "Verify that the queue disc has 4 child queue discs");
186
187 NS_TEST_ASSERT_MSG_EQ (qdisc->SetAttributeFailSafe ("Priomap", StringValue (priomap)),
188 true, "Verify that we can actually set the attribute Priomap");
189
190 StringValue sv;
191 NS_TEST_ASSERT_MSG_EQ (qdisc->GetAttributeFailSafe ("Priomap", sv),
192 true, "Verify that we can actually get the attribute Priomap");
193
194 NS_TEST_ASSERT_MSG_EQ (sv.Get (), priomap, "Verify that the priomap has been correctly set");
195
196 /*
197 * Test 2: classify packets based on priomap because no packet filter is installed
198 */
199
200 // create packets with priorities from 0 to 3
201 for (uint16_t i = 0; i < 4; i++)
202 {
203 NS_TEST_ASSERT_MSG_EQ (qdisc->GetQueueDiscClass (i)->GetQueueDisc ()->GetNPackets (),
204 0, "There should be no packets in the child queue disc " << i);
205
206 item = Create<PrioQueueDiscTestItem> (Create<Packet> (100), dest, i);
207 qdisc->Enqueue (item);
208 // packet is assigned band i
209 uids[i].push (item->GetPacket ()->GetUid ());
210
211 NS_TEST_ASSERT_MSG_EQ (qdisc->GetQueueDiscClass (i)->GetQueueDisc ()->GetNPackets (),
212 1, "There should be one packet in the child queue disc " << i);
213 }
214
215 /*
216 * Test 3: classify packets based on priomap because no packet filter able
217 * to classify packets is installed
218 */
219
220 Ptr<PrioQueueDiscTestFilter> pf1 = CreateObject<PrioQueueDiscTestFilter> (false);
221 qdisc->AddPacketFilter (pf1);
222
223 // create packets with priorities from 4 to 7
224 for (uint16_t i = 0; i < 4; i++)
225 {
226 NS_TEST_ASSERT_MSG_EQ (qdisc->GetQueueDiscClass (i)->GetQueueDisc ()->GetNPackets (),
227 1, "There should be one packet in the child queue disc " << i);
228
229 item = Create<PrioQueueDiscTestItem> (Create<Packet> (100), dest, i+4);
230 qdisc->Enqueue (item);
231 // packet is assigned band i
232 uids[i].push (item->GetPacket ()->GetUid ());
233
234 NS_TEST_ASSERT_MSG_EQ (qdisc->GetQueueDiscClass (i)->GetQueueDisc ()->GetNPackets (),
235 2, "There should be two packets in the child queue disc " << i);
236 }
237
238 /*
239 * Test 4: classify packets based on the value returned by the installed packet filter
240 */
241
242 Ptr<PrioQueueDiscTestFilter> pf2 = CreateObject<PrioQueueDiscTestFilter> (true);
243 qdisc->AddPacketFilter (pf2);
244
245 // create packets with priority 0 (which is neglected by the prio queue disc)
246 for (uint16_t i = 0; i < 4; i++)
247 {
248 pf2->SetReturnValue (i);
249 NS_TEST_ASSERT_MSG_EQ (qdisc->GetQueueDiscClass (i)->GetQueueDisc ()->GetNPackets (),
250 2, "There should be two packets in the child queue disc " << i);
251
252 item = Create<PrioQueueDiscTestItem> (Create<Packet> (100), dest, 0);
253 qdisc->Enqueue (item);
254 // packet is assigned band i
255 uids[i].push (item->GetPacket ()->GetUid ());
256
257 NS_TEST_ASSERT_MSG_EQ (qdisc->GetQueueDiscClass (i)->GetQueueDisc ()->GetNPackets (),
258 3, "There should be three packets in the child queue disc " << i);
259 }
260
261 /*
262 * Test 5: classify packets into the band specified by the first element of the
263 * priomap array because the value returned by the installed packet filter is
264 * not less than the number of bands
265 */
266
267 // create packets with priority 1 (which is neglected by the prio queue disc)
268 for (uint16_t i = 0; i < 4; i++)
269 {
270 pf2->SetReturnValue (4+i);
271 NS_TEST_ASSERT_MSG_EQ (qdisc->GetBandForPriority (0), 0, "The band for priority 0 must be band 0");
272 NS_TEST_ASSERT_MSG_EQ (qdisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), i+3u,
273 "There should be " << i+3 << " packets in the child queue disc "
274 << qdisc->GetBandForPriority (0));
275
276 item = Create<PrioQueueDiscTestItem> (Create<Packet> (100), dest, 1);
277 qdisc->Enqueue (item);
278 // packet is assigned band 0
279 uids[0].push (item->GetPacket ()->GetUid ());
280
281 NS_TEST_ASSERT_MSG_EQ (qdisc->GetQueueDiscClass (0)->GetQueueDisc ()->GetNPackets (), i+4u,
282 "There should be " << i+4 << " packets in the child queue disc "
283 << qdisc->GetBandForPriority (0));
284 }
285
286 /*
287 * Test 6: dequeue packets starting from the highest priority band (band 0)
288 */
289
290 while ((item = qdisc->Dequeue ()))
291 {
292 for (uint16_t i = 0; i < 4; i++)
293 {
294 if (uids[i].empty ())
295 {
296 NS_TEST_ASSERT_MSG_EQ (qdisc->GetQueueDiscClass (i)->GetQueueDisc ()->GetNPackets (),
297 0, "Band " << i << " should be empty");
298 continue;
299 }
300 NS_TEST_ASSERT_MSG_EQ (uids[i].front (), item->GetPacket ()->GetUid (),
301 "The dequeued packet is not the one we expected");
302 uids[i].pop ();
303 break;
304 }
305 }
306
307 Simulator::Destroy ();
308}
309
317{
318public:
320 : TestSuite ("prio-queue-disc", UNIT)
321 {
322 AddTestCase (new PrioQueueDiscTestCase (), TestCase::QUICK);
323 }
Prio Queue Disc Test Case.
virtual void DoRun(void)
Implementation to actually run this TestCase.
Prio Queue Disc Test Packet Filter.
PrioQueueDiscTestFilter(bool cls)
Constructor.
virtual bool CheckProtocol(Ptr< QueueDiscItem > item) const
Checks if the filter is able to classify a kind of items.
bool m_cls
whether this filter is able to classify a PrioQueueDiscTestItem
virtual int32_t DoClassify(Ptr< QueueDiscItem > item) const
Classify a packet.
void SetReturnValue(int32_t ret)
Set the value returned by DoClassify.
int32_t m_ret
the value that DoClassify returns if m_cls is true
Prio Queue Disc Test Item.
virtual void AddHeader(void)
Add the header to the packet.
PrioQueueDiscTestItem(Ptr< Packet > p, const Address &addr, uint8_t priority)
Constructor.
virtual bool Mark(void)
Marks the packet as a substitute for dropping it, such as for Explicit Congestion Notification.
Prio Queue Disc Test Suite.
a polymophic address class
Definition: address.h:91
PacketFilter is the abstract base class for filters used by queue discs to classify packets.
Definition: packet-filter.h:34
bool ReplacePacketTag(Tag &tag)
Replace the value of a packet tag.
Definition: packet.cc:970
QueueDiscItem is the abstract base class for items that are stored in a queue disc.
Definition: queue-item.h:133
indicates whether the socket has a priority set.
Definition: socket.h:1309
void SetPriority(uint8_t priority)
Set the tag's priority.
Definition: socket.cc:842
Hold variables of type string.
Definition: string.h:41
std::string Get(void) const
Definition: string.cc:31
encapsulates test code
Definition: test.h:994
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1188
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1197
make Callback use a separate empty type
Definition: empty.h:34
#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:141
PrioQueueDiscTestSuite g_prioQueueTestSuite
the test suite
Every class exported by the ns3 library is enclosed in the ns3 namespace.