A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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
36/**
37 * \ingroup traffic-control-test
38 *
39 * \brief Prio Queue Disc Test Item
40 */
42{
43 public:
44 /**
45 * Constructor
46 *
47 * \param p the packet
48 * \param addr the address
49 * \param priority the packet priority
50 */
51 PrioQueueDiscTestItem(Ptr<Packet> p, const Address& addr, uint8_t priority);
52 void AddHeader() override;
53 bool Mark() override;
54};
55
57 : QueueDiscItem(p, addr, 0)
58{
59 SocketPriorityTag priorityTag;
60 priorityTag.SetPriority(priority);
61 p->ReplacePacketTag(priorityTag);
62}
63
64void
66{
67}
68
69bool
71{
72 return false;
73}
74
75/**
76 * \ingroup traffic-control-test
77 *
78 * \brief Prio Queue Disc Test Packet Filter
79 */
81{
82 public:
83 /**
84 * Constructor
85 *
86 * \param cls whether this filter is able to classify a PrioQueueDiscTestItem
87 */
89 ~PrioQueueDiscTestFilter() override;
90 /**
91 * \brief Set the value returned by DoClassify
92 *
93 * \param ret the value that DoClassify returns
94 */
95 void SetReturnValue(int32_t ret);
96
97 private:
98 bool CheckProtocol(Ptr<QueueDiscItem> item) const override;
99 int32_t DoClassify(Ptr<QueueDiscItem> item) const override;
100
101 bool m_cls; //!< whether this filter is able to classify a PrioQueueDiscTestItem
102 int32_t m_ret; //!< the value that DoClassify returns if m_cls is true
103};
104
106 : m_cls(cls),
107 m_ret(0)
108{
109}
110
112{
113}
114
115void
117{
118 m_ret = ret;
119}
120
121bool
123{
124 return m_cls;
125}
126
129{
130 return m_ret;
131}
132
133/**
134 * \ingroup traffic-control-test
135 *
136 * \brief Prio Queue Disc Test Case
137 */
139{
140 public:
142 void DoRun() override;
143};
144
146 : TestCase("Sanity check on the prio queue disc implementation")
147{
148}
149
150void
152{
153 Ptr<PrioQueueDisc> qdisc;
155 std::string priomap("0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3");
156 Address dest;
157 std::array<std::queue<uint64_t>, 4> uids;
158
159 /*
160 * Test 1: set priomap
161 */
162 qdisc = CreateObject<PrioQueueDisc>();
163
164 // add 4 child fifo queue discs
165 for (uint8_t i = 0; i < 4; i++)
166 {
167 Ptr<FifoQueueDisc> child = CreateObject<FifoQueueDisc>();
168 child->Initialize();
169 Ptr<QueueDiscClass> c = CreateObject<QueueDiscClass>();
170 c->SetQueueDisc(child);
171 qdisc->AddQueueDiscClass(c);
172 }
173 qdisc->Initialize();
174
175 NS_TEST_ASSERT_MSG_EQ(qdisc->GetNQueueDiscClasses(),
176 4,
177 "Verify that the queue disc has 4 child queue discs");
178
179 NS_TEST_ASSERT_MSG_EQ(qdisc->SetAttributeFailSafe("Priomap", StringValue(priomap)),
180 true,
181 "Verify that we can actually set the attribute Priomap");
182
183 StringValue sv;
184 NS_TEST_ASSERT_MSG_EQ(qdisc->GetAttributeFailSafe("Priomap", sv),
185 true,
186 "Verify that we can actually get the attribute Priomap");
187
188 NS_TEST_ASSERT_MSG_EQ(sv.Get(), priomap, "Verify that the priomap has been correctly set");
189
190 /*
191 * Test 2: classify packets based on priomap because no packet filter is installed
192 */
193
194 // create packets with priorities from 0 to 3
195 for (uint16_t i = 0; i < 4; i++)
196 {
197 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
198 0,
199 "There should be no packets in the child queue disc " << i);
200
201 item = Create<PrioQueueDiscTestItem>(Create<Packet>(100), dest, i);
202 qdisc->Enqueue(item);
203 // packet is assigned band i
204 uids[i].push(item->GetPacket()->GetUid());
205
206 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
207 1,
208 "There should be one packet in the child queue disc " << i);
209 }
210
211 /*
212 * Test 3: classify packets based on priomap because no packet filter able
213 * to classify packets is installed
214 */
215
216 Ptr<PrioQueueDiscTestFilter> pf1 = CreateObject<PrioQueueDiscTestFilter>(false);
217 qdisc->AddPacketFilter(pf1);
218
219 // create packets with priorities from 4 to 7
220 for (uint16_t i = 0; i < 4; i++)
221 {
222 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
223 1,
224 "There should be one packet in the child queue disc " << i);
225
226 item = Create<PrioQueueDiscTestItem>(Create<Packet>(100), dest, i + 4);
227 qdisc->Enqueue(item);
228 // packet is assigned band i
229 uids[i].push(item->GetPacket()->GetUid());
230
231 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
232 2,
233 "There should be two packets in the child queue disc " << i);
234 }
235
236 /*
237 * Test 4: classify packets based on the value returned by the installed packet filter
238 */
239
240 Ptr<PrioQueueDiscTestFilter> pf2 = CreateObject<PrioQueueDiscTestFilter>(true);
241 qdisc->AddPacketFilter(pf2);
242
243 // create packets with priority 0 (which is neglected by the prio queue disc)
244 for (uint16_t i = 0; i < 4; i++)
245 {
246 pf2->SetReturnValue(i);
247 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
248 2,
249 "There should be two packets in the child queue disc " << i);
250
251 item = Create<PrioQueueDiscTestItem>(Create<Packet>(100), dest, 0);
252 qdisc->Enqueue(item);
253 // packet is assigned band i
254 uids[i].push(item->GetPacket()->GetUid());
255
256 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
257 3,
258 "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),
272 0,
273 "The band for priority 0 must be band 0");
274 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
275 i + 3U,
276 "There should be " << i + 3 << " packets in the child queue disc "
277 << qdisc->GetBandForPriority(0));
278
279 item = Create<PrioQueueDiscTestItem>(Create<Packet>(100), dest, 1);
280 qdisc->Enqueue(item);
281 // packet is assigned band 0
282 uids[0].push(item->GetPacket()->GetUid());
283
284 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
285 i + 4U,
286 "There should be " << i + 4 << " packets in the child queue disc "
287 << qdisc->GetBandForPriority(0));
288 }
289
290 /*
291 * Test 6: dequeue packets starting from the highest priority band (band 0)
292 */
293
294 while ((item = qdisc->Dequeue()))
295 {
296 for (uint16_t i = 0; i < 4; i++)
297 {
298 if (uids[i].empty())
299 {
300 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
301 0,
302 "Band " << i << " should be empty");
303 continue;
304 }
305 NS_TEST_ASSERT_MSG_EQ(uids[i].front(),
306 item->GetPacket()->GetUid(),
307 "The dequeued packet is not the one we expected");
308 uids[i].pop();
309 break;
310 }
311 }
312
314}
315
316/**
317 * \ingroup traffic-control-test
318 *
319 * \brief Prio Queue Disc Test Suite
320 */
322{
323 public:
325 : TestSuite("prio-queue-disc", Type::UNIT)
326 {
327 AddTestCase(new PrioQueueDiscTestCase(), TestCase::Duration::QUICK);
328 }
329} g_prioQueueTestSuite; ///< the test suite
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:101
PacketFilter is the abstract base class for filters used by queue discs to classify packets.
Definition: packet-filter.h:35
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
QueueDiscItem is the abstract base class for items that are stored in a queue disc.
Definition: queue-item.h:133
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
indicates whether the socket has a priority set.
Definition: socket.h:1318
void SetPriority(uint8_t priority)
Set the tag's priority.
Definition: socket.cc:854
Hold variables of type string.
Definition: string.h:56
std::string Get() const
Definition: string.cc:31
encapsulates test code
Definition: test.h:1061
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1268
Type
Type of test.
Definition: test.h:1275
static constexpr auto UNIT
Definition: test.h:1286
#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:145
PrioQueueDiscTestSuite g_prioQueueTestSuite
the test suite
Every class exported by the ns3 library is enclosed in the ns3 namespace.