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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Authors: Stefano Avallone <stavallo@unina.it>
7 *
8 */
9
10#include "ns3/fifo-queue-disc.h"
11#include "ns3/log.h"
12#include "ns3/packet-filter.h"
13#include "ns3/packet.h"
14#include "ns3/prio-queue-disc.h"
15#include "ns3/simulator.h"
16#include "ns3/socket.h"
17#include "ns3/string.h"
18#include "ns3/test.h"
19
20#include <array>
21#include <queue>
22
23using namespace ns3;
24
25/**
26 * \ingroup traffic-control-test
27 *
28 * \brief Prio Queue Disc Test Item
29 */
31{
32 public:
33 /**
34 * Constructor
35 *
36 * \param p the packet
37 * \param addr the address
38 * \param priority the packet priority
39 */
40 PrioQueueDiscTestItem(Ptr<Packet> p, const Address& addr, uint8_t priority);
41 void AddHeader() override;
42 bool Mark() override;
43};
44
46 : QueueDiscItem(p, addr, 0)
47{
48 SocketPriorityTag priorityTag;
49 priorityTag.SetPriority(priority);
50 p->ReplacePacketTag(priorityTag);
51}
52
53void
57
58bool
60{
61 return false;
62}
63
64/**
65 * \ingroup traffic-control-test
66 *
67 * \brief Prio Queue Disc Test Packet Filter
68 */
70{
71 public:
72 /**
73 * Constructor
74 *
75 * \param cls whether this filter is able to classify a PrioQueueDiscTestItem
76 */
78 ~PrioQueueDiscTestFilter() override;
79 /**
80 * \brief Set the value returned by DoClassify
81 *
82 * \param ret the value that DoClassify returns
83 */
84 void SetReturnValue(int32_t ret);
85
86 private:
87 bool CheckProtocol(Ptr<QueueDiscItem> item) const override;
88 int32_t DoClassify(Ptr<QueueDiscItem> item) const override;
89
90 bool m_cls; //!< whether this filter is able to classify a PrioQueueDiscTestItem
91 int32_t m_ret; //!< the value that DoClassify returns if m_cls is true
92};
93
95 : m_cls(cls),
96 m_ret(0)
97{
98}
99
103
104void
109
110bool
115
121
122/**
123 * \ingroup traffic-control-test
124 *
125 * \brief Prio Queue Disc Test Case
126 */
128{
129 public:
131 void DoRun() override;
132};
133
135 : TestCase("Sanity check on the prio queue disc implementation")
136{
137}
138
139void
141{
142 Ptr<PrioQueueDisc> qdisc;
144 std::string priomap("0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3");
145 Address dest;
146 std::array<std::queue<uint64_t>, 4> uids;
147
148 /*
149 * Test 1: set priomap
150 */
152
153 // add 4 child fifo queue discs
154 for (uint8_t i = 0; i < 4; i++)
155 {
157 child->Initialize();
159 c->SetQueueDisc(child);
160 qdisc->AddQueueDiscClass(c);
161 }
162 qdisc->Initialize();
163
164 NS_TEST_ASSERT_MSG_EQ(qdisc->GetNQueueDiscClasses(),
165 4,
166 "Verify that the queue disc has 4 child queue discs");
167
168 NS_TEST_ASSERT_MSG_EQ(qdisc->SetAttributeFailSafe("Priomap", StringValue(priomap)),
169 true,
170 "Verify that we can actually set the attribute Priomap");
171
172 StringValue sv;
173 NS_TEST_ASSERT_MSG_EQ(qdisc->GetAttributeFailSafe("Priomap", sv),
174 true,
175 "Verify that we can actually get the attribute Priomap");
176
177 NS_TEST_ASSERT_MSG_EQ(sv.Get(), priomap, "Verify that the priomap has been correctly set");
178
179 /*
180 * Test 2: classify packets based on priomap because no packet filter is installed
181 */
182
183 // create packets with priorities from 0 to 3
184 for (uint16_t i = 0; i < 4; i++)
185 {
186 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
187 0,
188 "There should be no packets in the child queue disc " << i);
189
190 item = Create<PrioQueueDiscTestItem>(Create<Packet>(100), dest, i);
191 qdisc->Enqueue(item);
192 // packet is assigned band i
193 uids[i].push(item->GetPacket()->GetUid());
194
195 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
196 1,
197 "There should be one packet in the child queue disc " << i);
198 }
199
200 /*
201 * Test 3: classify packets based on priomap because no packet filter able
202 * to classify packets is installed
203 */
204
206 qdisc->AddPacketFilter(pf1);
207
208 // create packets with priorities from 4 to 7
209 for (uint16_t i = 0; i < 4; i++)
210 {
211 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
212 1,
213 "There should be one packet in the child queue disc " << i);
214
215 item = Create<PrioQueueDiscTestItem>(Create<Packet>(100), dest, i + 4);
216 qdisc->Enqueue(item);
217 // packet is assigned band i
218 uids[i].push(item->GetPacket()->GetUid());
219
220 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
221 2,
222 "There should be two packets in the child queue disc " << i);
223 }
224
225 /*
226 * Test 4: classify packets based on the value returned by the installed packet filter
227 */
228
230 qdisc->AddPacketFilter(pf2);
231
232 // create packets with priority 0 (which is neglected by the prio queue disc)
233 for (uint16_t i = 0; i < 4; i++)
234 {
235 pf2->SetReturnValue(i);
236 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
237 2,
238 "There should be two packets in the child queue disc " << i);
239
240 item = Create<PrioQueueDiscTestItem>(Create<Packet>(100), dest, 0);
241 qdisc->Enqueue(item);
242 // packet is assigned band i
243 uids[i].push(item->GetPacket()->GetUid());
244
245 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
246 3,
247 "There should be three packets in the child queue disc " << i);
248 }
249
250 /*
251 * Test 5: classify packets into the band specified by the first element of the
252 * priomap array because the value returned by the installed packet filter is
253 * not less than the number of bands
254 */
255
256 // create packets with priority 1 (which is neglected by the prio queue disc)
257 for (uint16_t i = 0; i < 4; i++)
258 {
259 pf2->SetReturnValue(4 + i);
260 NS_TEST_ASSERT_MSG_EQ(qdisc->GetBandForPriority(0),
261 0,
262 "The band for priority 0 must be band 0");
263 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
264 i + 3U,
265 "There should be " << i + 3 << " packets in the child queue disc "
266 << qdisc->GetBandForPriority(0));
267
268 item = Create<PrioQueueDiscTestItem>(Create<Packet>(100), dest, 1);
269 qdisc->Enqueue(item);
270 // packet is assigned band 0
271 uids[0].push(item->GetPacket()->GetUid());
272
273 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(0)->GetQueueDisc()->GetNPackets(),
274 i + 4U,
275 "There should be " << i + 4 << " packets in the child queue disc "
276 << qdisc->GetBandForPriority(0));
277 }
278
279 /*
280 * Test 6: dequeue packets starting from the highest priority band (band 0)
281 */
282
283 while ((item = qdisc->Dequeue()))
284 {
285 for (uint16_t i = 0; i < 4; i++)
286 {
287 if (uids[i].empty())
288 {
289 NS_TEST_ASSERT_MSG_EQ(qdisc->GetQueueDiscClass(i)->GetQueueDisc()->GetNPackets(),
290 0,
291 "Band " << i << " should be empty");
292 continue;
293 }
294 NS_TEST_ASSERT_MSG_EQ(uids[i].front(),
295 item->GetPacket()->GetUid(),
296 "The dequeued packet is not the one we expected");
297 uids[i].pop();
298 break;
299 }
300 }
301
303}
304
305/**
306 * \ingroup traffic-control-test
307 *
308 * \brief Prio Queue Disc Test Suite
309 */
311{
312 public:
314 : TestSuite("prio-queue-disc", Type::UNIT)
315 {
316 AddTestCase(new PrioQueueDiscTestCase(), TestCase::Duration::QUICK);
317 }
318} 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:90
PacketFilter is the abstract base class for filters used by queue discs to classify packets.
Smart pointer class similar to boost::intrusive_ptr.
QueueDiscItem is the abstract base class for items that are stored in a queue disc.
Definition queue-item.h:122
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
indicates whether the socket has a priority set.
Definition socket.h:1307
void SetPriority(uint8_t priority)
Set the tag's priority.
Definition socket.cc:843
Hold variables of type string.
Definition string.h:45
std::string Get() const
Definition string.cc:20
encapsulates test code
Definition test.h:1050
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
static constexpr auto UNIT
Definition test.h:1291
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
#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:134
PrioQueueDiscTestSuite g_prioQueueTestSuite
the test suite
Every class exported by the ns3 library is enclosed in the ns3 namespace.