A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-mac-queue-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 IITP RAS
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Alexander Krotov <krotov@iitp.ru>
7 */
8
9#include "ns3/fcfs-wifi-queue-scheduler.h"
10#include "ns3/simulator.h"
11#include "ns3/test.h"
12#include "ns3/wifi-mac-queue.h"
13
14#include <algorithm>
15
16using namespace ns3;
17
18/**
19 * \ingroup wifi-test
20 * \ingroup tests
21 *
22 * \brief Test DROP_OLDEST setting.
23 *
24 * This test verifies the correctness of DROP_OLDEST policy when packets
25 * are pushed into the front of the queue. This case is not handled
26 * by the underlying ns3::Queue<WifiMpdu>.
27 */
29{
30 public:
31 /**
32 * \brief Constructor
33 */
35
36 void DoRun() override;
37};
38
40 : TestCase("Test DROP_OLDEST setting")
41{
42}
43
44void
46{
47 auto wifiMacQueue = CreateObject<WifiMacQueue>(AC_BE);
48 wifiMacQueue->SetMaxSize(QueueSize("5p"));
49 auto wifiMacScheduler = CreateObject<FcfsWifiQueueScheduler>();
50 wifiMacScheduler->SetAttribute("DropPolicy", EnumValue(FcfsWifiQueueScheduler::DROP_OLDEST));
51 wifiMacScheduler->m_perAcInfo[AC_BE].wifiMacQueue = wifiMacQueue;
52 wifiMacQueue->SetScheduler(wifiMacScheduler);
53
55
56 // Initialize the queue with 5 packets.
57 std::list<uint64_t> packetUids;
58 for (uint32_t i = 0; i < 5; i++)
59 {
60 WifiMacHeader header;
62 header.SetAddr1(addr1);
63 header.SetQosTid(0);
64 auto packet = Create<Packet>();
65 auto item = Create<WifiMpdu>(packet, header);
66 wifiMacQueue->Enqueue(item);
67
68 packetUids.push_back(packet->GetUid());
69 }
70
71 // Check that all elements are inserted successfully.
72 auto mpdu = wifiMacQueue->PeekByTidAndAddress(0, addr1);
73 NS_TEST_EXPECT_MSG_EQ(wifiMacQueue->GetNPackets(),
74 5,
75 "Queue has unexpected number of elements");
76 for (auto packetUid : packetUids)
77 {
78 NS_TEST_EXPECT_MSG_EQ(mpdu->GetPacket()->GetUid(),
79 packetUid,
80 "Stored packet is not the expected one");
81 mpdu = wifiMacQueue->PeekByTidAndAddress(0, addr1, mpdu);
82 }
83
84 // Push another element into the queue.
85 WifiMacHeader header;
87 header.SetAddr1(addr1);
88 header.SetQosTid(0);
89 auto packet = Create<Packet>();
90 auto item = Create<WifiMpdu>(packet, header);
91 wifiMacQueue->Enqueue(item);
92
93 // Update the list of expected packet UIDs.
94 packetUids.pop_front();
95 packetUids.push_back(packet->GetUid());
96
97 // Check that front packet was replaced correctly.
98 mpdu = wifiMacQueue->PeekByTidAndAddress(0, addr1);
99 NS_TEST_EXPECT_MSG_EQ(wifiMacQueue->GetNPackets(),
100 5,
101 "Queue has unexpected number of elements");
102 for (auto packetUid : packetUids)
103 {
104 NS_TEST_EXPECT_MSG_EQ(mpdu->GetPacket()->GetUid(),
105 packetUid,
106 "Stored packet is not the expected one");
107 mpdu = wifiMacQueue->PeekByTidAndAddress(0, addr1, mpdu);
108 }
109
110 wifiMacScheduler->Dispose();
112}
113
114/**
115 * \ingroup wifi-test
116 * \ingroup tests
117 *
118 * \brief Test extraction of expired MPDUs from MAC queue container
119 *
120 * This test verifies the correctness of the WifiMacQueueContainer methods
121 * (ExtractExpiredMpdus and ExtractAllExpiredMpdus) that extract MPDUs with
122 * expired lifetime from the MAC queue container.
123 */
125{
126 public:
128
129 private:
130 void DoRun() override;
131
132 /**
133 * Enqueue a new MPDU into the container.
134 *
135 * \param rxAddr Receiver Address of the MPDU
136 * \param inflight whether the MPDU is inflight
137 * \param expiryTime the expity time for the MPDU
138 */
139 void Enqueue(Mac48Address rxAddr, bool inflight, Time expiryTime);
140
141 WifiMacQueueContainer m_container; //!< MAC queue container
142 uint16_t m_currentSeqNo{0}; //!< sequence number of current MPDU
143 Mac48Address m_txAddr; //!< Transmitter Address of MPDUs
144};
145
147 : TestCase("Test extraction of expired MPDUs from MAC queue container")
148{
149}
150
151void
153{
155 header.SetAddr1(rxAddr);
156 header.SetAddr2(m_txAddr);
157 header.SetQosTid(0);
159 auto mpdu = Create<WifiMpdu>(Create<Packet>(), header);
160
161 auto queueId = WifiMacQueueContainer::GetQueueId(mpdu);
162 auto elemIt = m_container.insert(m_container.GetQueue(queueId).cend(), mpdu);
163 elemIt->expiryTime = expiryTime;
164 if (inflight)
165 {
166 elemIt->inflights.emplace(0, mpdu);
167 }
168 elemIt->deleter = [](auto mpdu) {};
169}
170
171void
173{
175 auto rxAddr1 = Mac48Address::Allocate();
176 auto rxAddr2 = Mac48Address::Allocate();
177
178 /**
179 * At simulation time 25ms:
180 *
181 * Container queue for rxAddr1
182 * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
183 * │Exp│Exp│Exp│Exp│ │ │ │ │ │ │ │
184 * │Inf│ │Inf│ │Inf│ │Inf│ │ │ │ │
185 * │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │10 │
186 * └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
187 *
188 * Container queue for rxAddr2
189 * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┐
190 * │Exp│Exp│Exp│ │ │ │ │ │ │
191 * │ │Inf│Inf│ │Inf│Inf│ │ │ │
192 * │11 │12 │13 │14 │15 │16 │17 │18 │19 │
193 * └───┴───┴───┴───┴───┴───┴───┴───┴───┘
194 */
195 Enqueue(rxAddr1, true, MilliSeconds(10));
196 Enqueue(rxAddr1, false, MilliSeconds(10));
197 Enqueue(rxAddr1, true, MilliSeconds(12));
198 Enqueue(rxAddr1, false, MilliSeconds(15));
199 Enqueue(rxAddr1, true, MilliSeconds(30));
200 Enqueue(rxAddr1, false, MilliSeconds(30));
201 Enqueue(rxAddr1, true, MilliSeconds(35));
202 Enqueue(rxAddr1, false, MilliSeconds(35));
203 Enqueue(rxAddr1, false, MilliSeconds(40));
204 Enqueue(rxAddr1, false, MilliSeconds(75));
205 Enqueue(rxAddr1, false, MilliSeconds(75));
206
207 Enqueue(rxAddr2, false, MilliSeconds(11));
208 Enqueue(rxAddr2, true, MilliSeconds(11));
209 Enqueue(rxAddr2, true, MilliSeconds(13));
210 Enqueue(rxAddr2, false, MilliSeconds(30));
211 Enqueue(rxAddr2, true, MilliSeconds(35));
212 Enqueue(rxAddr2, true, MilliSeconds(40));
213 Enqueue(rxAddr2, false, MilliSeconds(40));
214 Enqueue(rxAddr2, false, MilliSeconds(70));
215 Enqueue(rxAddr2, false, MilliSeconds(75));
216
219
221 /**
222 * Extract expired MPDUs from container queue 1
223 */
224 auto [first1, last1] = m_container.ExtractExpiredMpdus(queueId1);
225 // MPDU 0 not extracted because inflight, MPDU 1 extracted
226 NS_TEST_EXPECT_MSG_EQ((first1 != last1), true, "Expected one MPDU extracted");
227 NS_TEST_EXPECT_MSG_EQ(first1->mpdu->GetHeader().GetSequenceNumber(),
228 1,
229 "Unexpected extracted MPDU");
230 first1++;
231 // MPDU 2 not extracted because inflight, MPDU 3 extracted
232 NS_TEST_EXPECT_MSG_EQ((first1 != last1), true, "Expected two MPDUs extracted");
233 NS_TEST_EXPECT_MSG_EQ(first1->mpdu->GetHeader().GetSequenceNumber(),
234 3,
235 "Unexpected extracted MPDU");
236 first1++;
237 // No other expired MPDU
238 NS_TEST_EXPECT_MSG_EQ((first1 == last1), true, "Did not expect other expired MPDUs");
239
240 // If we try to extract expired MPDUs again, the returned set is empty
241 {
242 auto [first, last] = m_container.ExtractExpiredMpdus(queueId1);
243 NS_TEST_EXPECT_MSG_EQ((first == last), true, "Did not expect other expired MPDUs");
244 }
245
246 /**
247 * Extract expired MPDUs from container queue 2
248 */
249 auto [first2, last2] = m_container.ExtractExpiredMpdus(queueId2);
250 // MPDU 11 extracted
251 NS_TEST_EXPECT_MSG_EQ((first2 != last2), true, "Expected one MPDU extracted");
252 NS_TEST_EXPECT_MSG_EQ(first2->mpdu->GetHeader().GetSequenceNumber(),
253 11,
254 "Unexpected extracted MPDU");
255 first2++;
256 // MPDU 12 and 13 not extracted because inflight, no other expired MPDU
257 NS_TEST_EXPECT_MSG_EQ((first2 == last2), true, "Did not expect other expired MPDUs");
258
259 // If we try to extract expired MPDUs again, the returned set is empty
260 {
261 auto [first, last] = m_container.ExtractExpiredMpdus(queueId2);
262 NS_TEST_EXPECT_MSG_EQ((first == last), true, "Did not expect other expired MPDUs");
263 }
264 });
265
266 /**
267 * At simulation time 50ms:
268 *
269 * Container queue for rxAddr1
270 * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┐
271 * │Exp│Exp│Exp│Exp│Exp│Exp│Exp│ │ │
272 * │Inf│Inf│Inf│ │Inf│ │ │ │ │
273 * │ 0 │ 2 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │10 │
274 * └───┴───┴───┴───┴───┴───┴───┴───┴───┘
275 *
276 * Container queue for rxAddr2
277 * ┌───┬───┬───┬───┬───┬───┬───┬───┐
278 * │Exp│Exp│Exp│Exp│Exp│Exp│ │ │
279 * │Inf│Inf│ │Inf│Inf│ │ │ │
280 * │12 │13 │14 │15 │16 │17 │18 │19 │
281 * └───┴───┴───┴───┴───┴───┴───┴───┘
282 */
284 /**
285 * Extract all expired MPDUs (from container queue 1 and 2)
286 */
288
289 std::set<uint16_t> expectedSeqNo{5, 7, 8, 14, 17};
290 std::set<uint16_t> actualSeqNo;
291
292 std::transform(first, last, std::inserter(actualSeqNo, actualSeqNo.end()), [](auto& elem) {
293 return elem.mpdu->GetHeader().GetSequenceNumber();
294 });
295
296 NS_TEST_EXPECT_MSG_EQ(expectedSeqNo.size(),
297 actualSeqNo.size(),
298 "Unexpected number of MPDUs extracted");
299
300 for (auto expectedIt = expectedSeqNo.begin(), actualIt = actualSeqNo.begin();
301 expectedIt != expectedSeqNo.end();
302 ++expectedIt, ++actualIt)
303 {
304 NS_TEST_EXPECT_MSG_EQ(*expectedIt, *actualIt, "Unexpected extracted MPDU");
305 }
306
307 // If we try to extract expired MPDUs again, the returned set is empty
308 {
310 NS_TEST_EXPECT_MSG_EQ((first == last), true, "Did not expect other expired MPDUs");
311 }
312
313 /**
314 * Check MPDUs remaining in container queue 1
315 */
316 auto elemIt = m_container.GetQueue(queueId1).begin();
317 auto endIt = m_container.GetQueue(queueId1).end();
318 NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
319 true,
320 "There should be other MPDU(s) in container queue 1");
321 NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
322 0,
323 "Unexpected queued MPDU");
324 elemIt++;
325 NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
326 true,
327 "There should be other MPDU(s) in container queue 1");
328 NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
329 2,
330 "Unexpected queued MPDU");
331 elemIt++;
332 NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
333 true,
334 "There should be other MPDU(s) in container queue 1");
335 NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
336 4,
337 "Unexpected queued MPDU");
338 elemIt++;
339 NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
340 true,
341 "There should be other MPDU(s) in container queue 1");
342 NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
343 6,
344 "Unexpected queued MPDU");
345 elemIt++;
346 NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
347 true,
348 "There should be other MPDU(s) in container queue 1");
349 NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
350 9,
351 "Unexpected queued MPDU");
352 elemIt++;
353 NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
354 true,
355 "There should be other MPDU(s) in container queue 1");
356 NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
357 10,
358 "Unexpected queued MPDU");
359 elemIt++;
360 NS_TEST_EXPECT_MSG_EQ((elemIt == endIt),
361 true,
362 "There should be no other MPDU in container queue 1");
363
364 /**
365 * Check MPDUs remaining in container queue 2
366 */
367 elemIt = m_container.GetQueue(queueId2).begin();
368 endIt = m_container.GetQueue(queueId2).end();
369 NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
370 true,
371 "There should be other MPDU(s) in container queue 2");
372 NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
373 12,
374 "Unexpected queued MPDU");
375 elemIt++;
376 NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
377 true,
378 "There should be other MPDU(s) in container queue 2");
379 NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
380 13,
381 "Unexpected queued MPDU");
382 elemIt++;
383 NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
384 true,
385 "There should be other MPDU(s) in container queue 2");
386 NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
387 15,
388 "Unexpected queued MPDU");
389 elemIt++;
390 NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
391 true,
392 "There should be other MPDU(s) in container queue 2");
393 NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
394 16,
395 "Unexpected queued MPDU");
396 elemIt++;
397 NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
398 true,
399 "There should be other MPDU(s) in container queue 2");
400 NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
401 18,
402 "Unexpected queued MPDU");
403 elemIt++;
404 NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
405 true,
406 "There should be other MPDU(s) in container queue 2");
407 NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
408 19,
409 "Unexpected queued MPDU");
410 elemIt++;
411 NS_TEST_EXPECT_MSG_EQ((elemIt == endIt),
412 true,
413 "There should be no other MPDU in container queue 2");
414 });
415
418}
419
420/**
421 * \ingroup wifi-test
422 * \ingroup tests
423 *
424 * \brief Wifi MAC Queue Test Suite
425 */
427{
428 public:
430};
431
433 : TestSuite("wifi-mac-queue", Type::UNIT)
434{
435 AddTestCase(new WifiMacQueueDropOldestTest, TestCase::Duration::QUICK);
436 AddTestCase(new WifiExtractExpiredMpdusTest, TestCase::Duration::QUICK);
437}
438
Test extraction of expired MPDUs from MAC queue container.
uint16_t m_currentSeqNo
sequence number of current MPDU
Mac48Address m_txAddr
Transmitter Address of MPDUs.
WifiMacQueueContainer m_container
MAC queue container.
void DoRun() override
Implementation to actually run this TestCase.
void Enqueue(Mac48Address rxAddr, bool inflight, Time expiryTime)
Enqueue a new MPDU into the container.
Test DROP_OLDEST setting.
void DoRun() override
Implementation to actually run this TestCase.
Wifi MAC Queue Test Suite.
Hold variables of type enum.
Definition enum.h:52
an EUI-48 address
static Mac48Address Allocate()
Allocate a new Mac48Address.
Class for representing queue sizes.
Definition queue-size.h:85
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static void Run()
Run the simulation.
Definition simulator.cc:167
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
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
Implements the IEEE 802.11 MAC header.
void SetSequenceNumber(uint16_t seq)
Set the sequence number of the header.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
virtual void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
void SetQosTid(uint8_t tid)
Set the TID for the QoS header.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
Class for the container used by WifiMacQueue.
const ContainerQueue & GetQueue(const WifiContainerQueueId &queueId) const
Get a const reference to the container queue identified by the given QueueId.
static WifiContainerQueueId GetQueueId(Ptr< const WifiMpdu > mpdu)
Return the QueueId identifying the container queue in which the given MPDU is (or is to be) enqueued.
std::pair< iterator, iterator > ExtractAllExpiredMpdus() const
Transfer non-inflight MPDUs with expired lifetime in all the container queues to the container queue ...
iterator insert(const_iterator pos, Ptr< WifiMpdu > item)
Insert the given item at the specified location in the container.
std::pair< iterator, iterator > ExtractExpiredMpdus(const WifiContainerQueueId &queueId) const
Transfer non-inflight MPDUs with expired lifetime in the container queue identified by the given Queu...
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_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition test.h:241
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1320
@ AC_BE
Best Effort.
Definition qos-utils.h:64
Definition first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std:: tuple< WifiContainerQueueType, WifiReceiverAddressType, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, receiver address type, Address, TID) identifying a container queue.
@ WIFI_MAC_QOSDATA
static WifiMacQueueTestSuite g_wifiMacQueueTestSuite
the test suite