A Discrete-Event Network Simulator
API
prio-queue-disc-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017 Universita' degli Studi di Napoli Federico II
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Authors: Stefano Avallone <stavallo@unina.it>
18 *
19 */
20
21#include "ns3/fifo-queue-disc.h"
22#include "ns3/log.h"
23#include "ns3/packet-filter.h"
24#include "ns3/packet.h"
25#include "ns3/prio-queue-disc.h"
26#include "ns3/simulator.h"
27#include "ns3/socket.h"
28#include "ns3/string.h"
29#include "ns3/test.h"
30
31#include <array>
32#include <queue>
33
34using namespace ns3;
35
43{
44 public:
52 PrioQueueDiscTestItem(Ptr<Packet> p, const Address& addr, uint8_t priority);
53 void AddHeader() override;
54 bool Mark() override;
55};
56
58 : QueueDiscItem(p, addr, 0)
59{
60 SocketPriorityTag priorityTag;
61 priorityTag.SetPriority(priority);
62 p->ReplacePacketTag(priorityTag);
63}
64
65void
67{
68}
69
70bool
72{
73 return false;
74}
75
83{
84 public:
91 ~PrioQueueDiscTestFilter() override;
97 void SetReturnValue(int32_t ret);
98
99 private:
100 bool CheckProtocol(Ptr<QueueDiscItem> item) const override;
101 int32_t DoClassify(Ptr<QueueDiscItem> item) const override;
102
103 bool m_cls;
105};
106
108 : m_cls(cls),
109 m_ret(0)
110{
111}
112
114{
115}
116
117void
119{
120 m_ret = ret;
121}
122
123bool
125{
126 return m_cls;
127}
128
131{
132 return m_ret;
133}
134
142{
143 public:
145 void DoRun() override;
146};
147
149 : TestCase("Sanity check on the prio queue disc implementation")
150{
151}
152
153void
155{
156 Ptr<PrioQueueDisc> qdisc;
158 std::string priomap("0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3");
159 Address dest;
160 std::array<std::queue<uint64_t>, 4> uids;
161
162 /*
163 * Test 1: set priomap
164 */
165 qdisc = CreateObject<PrioQueueDisc>();
166
167 // add 4 child fifo queue discs
168 for (uint8_t i = 0; i < 4; i++)
169 {
170 Ptr<FifoQueueDisc> child = CreateObject<FifoQueueDisc>();
171 child->Initialize();
172 Ptr<QueueDiscClass> c = CreateObject<QueueDiscClass>();
173 c->SetQueueDisc(child);
174 qdisc->AddQueueDiscClass(c);
175 }
176 qdisc->Initialize();
177
178 NS_TEST_ASSERT_MSG_EQ(qdisc->GetNQueueDiscClasses(),
179 4,
180 "Verify that the queue disc has 4 child queue discs");
181
182 NS_TEST_ASSERT_MSG_EQ(qdisc->SetAttributeFailSafe("Priomap", StringValue(priomap)),
183 true,
184 "Verify that we can actually set the attribute Priomap");
185
186 StringValue sv;
187 NS_TEST_ASSERT_MSG_EQ(qdisc->GetAttributeFailSafe("Priomap", sv),
188 true,
189 "Verify that we can actually get the attribute Priomap");
190
191 NS_TEST_ASSERT_MSG_EQ(sv.Get(), priomap, "Verify that the priomap has been correctly set");
192
193 /*
194 * Test 2: classify packets based on priomap because no packet filter is installed
195 */
196
197 // create packets with priorities from 0 to 3
198 for (uint16_t i = 0; i < 4; i++)
199 {
200 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
201 0,
202 "There should be no packets in the child queue disc " << i);
203
204 item = Create<PrioQueueDiscTestItem>(Create<Packet>(100), dest, i);
205 qdisc->Enqueue(item);
206 // packet is assigned band i
207 uids[i].push(item->GetPacket()->GetUid());
208
209 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
210 1,
211 "There should be one packet in the child queue disc " << i);
212 }
213
214 /*
215 * Test 3: classify packets based on priomap because no packet filter able
216 * to classify packets is installed
217 */
218
219 Ptr<PrioQueueDiscTestFilter> pf1 = CreateObject<PrioQueueDiscTestFilter>(false);
220 qdisc->AddPacketFilter(pf1);
221
222 // create packets with priorities from 4 to 7
223 for (uint16_t i = 0; i < 4; i++)
224 {
225 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
226 1,
227 "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,
236 "There should be two packets in the child queue disc " << i);
237 }
238
239 /*
240 * Test 4: classify packets based on the value returned by the installed packet filter
241 */
242
243 Ptr<PrioQueueDiscTestFilter> pf2 = CreateObject<PrioQueueDiscTestFilter>(true);
244 qdisc->AddPacketFilter(pf2);
245
246 // create packets with priority 0 (which is neglected by the prio queue disc)
247 for (uint16_t i = 0; i < 4; i++)
248 {
249 pf2->SetReturnValue(i);
250 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
251 2,
252 "There should be two packets in the child queue disc " << i);
253
254 item = Create<PrioQueueDiscTestItem>(Create<Packet>(100), dest, 0);
255 qdisc->Enqueue(item);
256 // packet is assigned band i
257 uids[i].push(item->GetPacket()->GetUid());
258
259 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
260 3,
261 "There should be three packets in the child queue disc " << i);
262 }
263
264 /*
265 * Test 5: classify packets into the band specified by the first element of the
266 * priomap array because the value returned by the installed packet filter is
267 * not less than the number of bands
268 */
269
270 // create packets with priority 1 (which is neglected by the prio queue disc)
271 for (uint16_t i = 0; i < 4; i++)
272 {
273 pf2->SetReturnValue(4 + i);
274 NS_TEST_ASSERT_MSG_EQ(qdisc->GetBandForPriority(0),
275 0,
276 "The band for priority 0 must be band 0");
277 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
278 i + 3U,
279 "There should be " << i + 3 << " packets in the child queue disc "
280 << qdisc->GetBandForPriority(0));
281
282 item = Create<PrioQueueDiscTestItem>(Create<Packet>(100), dest, 1);
283 qdisc->Enqueue(item);
284 // packet is assigned band 0
285 uids[0].push(item->GetPacket()->GetUid());
286
287 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
288 i + 4U,
289 "There should be " << i + 4 << " packets in the child queue disc "
290 << qdisc->GetBandForPriority(0));
291 }
292
293 /*
294 * Test 6: dequeue packets starting from the highest priority band (band 0)
295 */
296
297 while ((item = qdisc->Dequeue()))
298 {
299 for (uint16_t i = 0; i < 4; i++)
300 {
301 if (uids[i].empty())
302 {
303 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
304 0,
305 "Band " << i << " should be empty");
306 continue;
307 }
308 NS_TEST_ASSERT_MSG_EQ(uids[i].front(),
309 item->GetPacket()->GetUid(),
310 "The dequeued packet is not the one we expected");
311 uids[i].pop();
312 break;
313 }
314 }
315
316 Simulator::Destroy();
317}
318
326{
327 public:
329 : TestSuite("prio-queue-disc", UNIT)
330 {
331 AddTestCase(new PrioQueueDiscTestCase(), TestCase::QUICK);
332 }
Prio Queue Disc Test Case.
void DoRun() override
Implementation to actually run this TestCase.
Prio Queue Disc Test Packet Filter.
PrioQueueDiscTestFilter(bool cls)
Constructor.
bool m_cls
whether this filter is able to classify a PrioQueueDiscTestItem
int32_t DoClassify(Ptr< QueueDiscItem > item) const override
Classify a packet.
bool CheckProtocol(Ptr< QueueDiscItem > item) const override
Checks if the filter is able to classify a kind of items.
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.
bool Mark() override
Marks the packet as a substitute for dropping it, such as for Explicit Congestion Notification.
PrioQueueDiscTestItem(Ptr< Packet > p, const Address &addr, uint8_t priority)
Constructor.
void AddHeader() override
Add the header to the packet.
Prio Queue Disc Test Suite.
a polymophic address class
Definition: address.h:92
PacketFilter is the abstract base class for filters used by queue discs to classify packets.
Definition: packet-filter.h:35
bool ReplacePacketTag(Tag &tag)
Replace the value of a packet tag.
Definition: packet.cc:994
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:1316
void SetPriority(uint8_t priority)
Set the tag's priority.
Definition: socket.cc:852
Hold variables of type string.
Definition: string.h:42
std::string Get() const
Definition: string.cc:31
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:305
A suite of tests to run.
Definition: test.h:1256
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1265
Empty class, used as a default parent class for SimpleRefCount.
#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:144
PrioQueueDiscTestSuite g_prioQueueTestSuite
the test suite
Every class exported by the ns3 library is enclosed in the ns3 namespace.