wifi: Add unit test for extraction of expired MPDUs
This commit is contained in:
@@ -22,6 +22,8 @@
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/wifi-mac-queue.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
/**
|
||||
@@ -120,6 +122,312 @@ WifiMacQueueDropOldestTest::DoRun()
|
||||
Simulator::Destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup wifi-test
|
||||
* \ingroup tests
|
||||
*
|
||||
* \brief Test extraction of expired MPDUs from MAC queue container
|
||||
*
|
||||
* This test verifies the correctness of the WifiMacQueueContainer methods
|
||||
* (ExtractExpiredMpdus and ExtractAllExpiredMpdus) that extract MPDUs with
|
||||
* expired lifetime from the MAC queue container.
|
||||
*/
|
||||
class WifiExtractExpiredMpdusTest : public TestCase
|
||||
{
|
||||
public:
|
||||
WifiExtractExpiredMpdusTest();
|
||||
|
||||
private:
|
||||
void DoRun() override;
|
||||
|
||||
/**
|
||||
* Enqueue a new MPDU into the container.
|
||||
*
|
||||
* \param rxAddr Receiver Address of the MPDU
|
||||
* \param inflight whether the MPDU is inflight
|
||||
* \param expiryTime the expity time for the MPDU
|
||||
*/
|
||||
void Enqueue(Mac48Address rxAddr, bool inflight, Time expiryTime);
|
||||
|
||||
WifiMacQueueContainer m_container; //!< MAC queue container
|
||||
uint16_t m_currentSeqNo{0}; //!< sequence number of current MPDU
|
||||
Mac48Address m_txAddr; //!< Transmitter Address of MPDUs
|
||||
};
|
||||
|
||||
WifiExtractExpiredMpdusTest::WifiExtractExpiredMpdusTest()
|
||||
: TestCase("Test extraction of expired MPDUs from MAC queue container")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
WifiExtractExpiredMpdusTest::Enqueue(Mac48Address rxAddr, bool inflight, Time expiryTime)
|
||||
{
|
||||
WifiMacHeader header(WIFI_MAC_QOSDATA);
|
||||
header.SetAddr1(rxAddr);
|
||||
header.SetAddr2(m_txAddr);
|
||||
header.SetQosTid(0);
|
||||
header.SetSequenceNumber(m_currentSeqNo++);
|
||||
auto mpdu = Create<WifiMpdu>(Create<Packet>(), header);
|
||||
|
||||
auto queueId = WifiMacQueueContainer::GetQueueId(mpdu);
|
||||
auto elemIt = m_container.insert(m_container.GetQueue(queueId).cend(), mpdu);
|
||||
elemIt->expiryTime = expiryTime;
|
||||
if (inflight)
|
||||
{
|
||||
elemIt->inflights.emplace(0, mpdu);
|
||||
}
|
||||
elemIt->deleter = [](auto mpdu) {};
|
||||
}
|
||||
|
||||
void
|
||||
WifiExtractExpiredMpdusTest::DoRun()
|
||||
{
|
||||
m_txAddr = Mac48Address::Allocate();
|
||||
auto rxAddr1 = Mac48Address::Allocate();
|
||||
auto rxAddr2 = Mac48Address::Allocate();
|
||||
|
||||
/**
|
||||
* At simulation time 25ms:
|
||||
*
|
||||
* Container queue for rxAddr1
|
||||
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
|
||||
* │Exp│Exp│Exp│Exp│ │ │ │ │ │ │ │
|
||||
* │Inf│ │Inf│ │Inf│ │Inf│ │ │ │ │
|
||||
* │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │10 │
|
||||
* └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
|
||||
*
|
||||
* Container queue for rxAddr2
|
||||
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┐
|
||||
* │Exp│Exp│Exp│ │ │ │ │ │ │
|
||||
* │ │Inf│Inf│ │Inf│Inf│ │ │ │
|
||||
* │11 │12 │13 │14 │15 │16 │17 │18 │19 │
|
||||
* └───┴───┴───┴───┴───┴───┴───┴───┴───┘
|
||||
*/
|
||||
Enqueue(rxAddr1, true, MilliSeconds(10));
|
||||
Enqueue(rxAddr1, false, MilliSeconds(10));
|
||||
Enqueue(rxAddr1, true, MilliSeconds(12));
|
||||
Enqueue(rxAddr1, false, MilliSeconds(15));
|
||||
Enqueue(rxAddr1, true, MilliSeconds(30));
|
||||
Enqueue(rxAddr1, false, MilliSeconds(30));
|
||||
Enqueue(rxAddr1, true, MilliSeconds(35));
|
||||
Enqueue(rxAddr1, false, MilliSeconds(35));
|
||||
Enqueue(rxAddr1, false, MilliSeconds(40));
|
||||
Enqueue(rxAddr1, false, MilliSeconds(75));
|
||||
Enqueue(rxAddr1, false, MilliSeconds(75));
|
||||
|
||||
Enqueue(rxAddr2, false, MilliSeconds(11));
|
||||
Enqueue(rxAddr2, true, MilliSeconds(11));
|
||||
Enqueue(rxAddr2, true, MilliSeconds(13));
|
||||
Enqueue(rxAddr2, false, MilliSeconds(30));
|
||||
Enqueue(rxAddr2, true, MilliSeconds(35));
|
||||
Enqueue(rxAddr2, true, MilliSeconds(40));
|
||||
Enqueue(rxAddr2, false, MilliSeconds(40));
|
||||
Enqueue(rxAddr2, false, MilliSeconds(70));
|
||||
Enqueue(rxAddr2, false, MilliSeconds(75));
|
||||
|
||||
WifiContainerQueueId queueId1{WIFI_QOSDATA_UNICAST_QUEUE, rxAddr1, 0};
|
||||
WifiContainerQueueId queueId2{WIFI_QOSDATA_UNICAST_QUEUE, rxAddr2, 0};
|
||||
|
||||
Simulator::Schedule(MilliSeconds(25), [&]() {
|
||||
/**
|
||||
* Extract expired MPDUs from container queue 1
|
||||
*/
|
||||
auto [first1, last1] = m_container.ExtractExpiredMpdus(queueId1);
|
||||
// MPDU 0 not extracted because inflight, MPDU 1 extracted
|
||||
NS_TEST_EXPECT_MSG_EQ((first1 != last1), true, "Expected one MPDU extracted");
|
||||
NS_TEST_EXPECT_MSG_EQ(first1->mpdu->GetHeader().GetSequenceNumber(),
|
||||
1,
|
||||
"Unexpected extracted MPDU");
|
||||
first1++;
|
||||
// MPDU 2 not extracted because inflight, MPDU 3 extracted
|
||||
NS_TEST_EXPECT_MSG_EQ((first1 != last1), true, "Expected two MPDUs extracted");
|
||||
NS_TEST_EXPECT_MSG_EQ(first1->mpdu->GetHeader().GetSequenceNumber(),
|
||||
3,
|
||||
"Unexpected extracted MPDU");
|
||||
first1++;
|
||||
// No other expired MPDU
|
||||
NS_TEST_EXPECT_MSG_EQ((first1 == last1), true, "Did not expect other expired MPDUs");
|
||||
|
||||
// If we try to extract expired MPDUs again, the returned set is empty
|
||||
{
|
||||
auto [first, last] = m_container.ExtractExpiredMpdus(queueId1);
|
||||
NS_TEST_EXPECT_MSG_EQ((first == last), true, "Did not expect other expired MPDUs");
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract expired MPDUs from container queue 2
|
||||
*/
|
||||
auto [first2, last2] = m_container.ExtractExpiredMpdus(queueId2);
|
||||
// MPDU 11 extracted
|
||||
NS_TEST_EXPECT_MSG_EQ((first2 != last2), true, "Expected one MPDU extracted");
|
||||
NS_TEST_EXPECT_MSG_EQ(first2->mpdu->GetHeader().GetSequenceNumber(),
|
||||
11,
|
||||
"Unexpected extracted MPDU");
|
||||
first2++;
|
||||
// MPDU 12 and 13 not extracted because inflight, no other expired MPDU
|
||||
NS_TEST_EXPECT_MSG_EQ((first2 == last2), true, "Did not expect other expired MPDUs");
|
||||
|
||||
// If we try to extract expired MPDUs again, the returned set is empty
|
||||
{
|
||||
auto [first, last] = m_container.ExtractExpiredMpdus(queueId2);
|
||||
NS_TEST_EXPECT_MSG_EQ((first == last), true, "Did not expect other expired MPDUs");
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* At simulation time 50ms:
|
||||
*
|
||||
* Container queue for rxAddr1
|
||||
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┐
|
||||
* │Exp│Exp│Exp│Exp│Exp│Exp│Exp│ │ │
|
||||
* │Inf│Inf│Inf│ │Inf│ │ │ │ │
|
||||
* │ 0 │ 2 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │10 │
|
||||
* └───┴───┴───┴───┴───┴───┴───┴───┴───┘
|
||||
*
|
||||
* Container queue for rxAddr2
|
||||
* ┌───┬───┬───┬───┬───┬───┬───┬───┐
|
||||
* │Exp│Exp│Exp│Exp│Exp│Exp│ │ │
|
||||
* │Inf│Inf│ │Inf│Inf│ │ │ │
|
||||
* │12 │13 │14 │15 │16 │17 │18 │19 │
|
||||
* └───┴───┴───┴───┴───┴───┴───┴───┘
|
||||
*/
|
||||
Simulator::Schedule(MilliSeconds(50), [&]() {
|
||||
/**
|
||||
* Extract all expired MPDUs (from container queue 1 and 2)
|
||||
*/
|
||||
auto [first, last] = m_container.ExtractAllExpiredMpdus();
|
||||
|
||||
std::set<uint16_t> expectedSeqNo{5, 7, 8, 14, 17};
|
||||
std::set<uint16_t> actualSeqNo;
|
||||
|
||||
std::transform(first, last, std::inserter(actualSeqNo, actualSeqNo.end()), [](auto& elem) {
|
||||
return elem.mpdu->GetHeader().GetSequenceNumber();
|
||||
});
|
||||
|
||||
NS_TEST_EXPECT_MSG_EQ(expectedSeqNo.size(),
|
||||
actualSeqNo.size(),
|
||||
"Unexpected number of MPDUs extracted");
|
||||
|
||||
for (auto expectedIt = expectedSeqNo.begin(), actualIt = actualSeqNo.begin();
|
||||
expectedIt != expectedSeqNo.end();
|
||||
++expectedIt, ++actualIt)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ(*expectedIt, *actualIt, "Unexpected extracted MPDU");
|
||||
}
|
||||
|
||||
// If we try to extract expired MPDUs again, the returned set is empty
|
||||
{
|
||||
auto [first, last] = m_container.ExtractAllExpiredMpdus();
|
||||
NS_TEST_EXPECT_MSG_EQ((first == last), true, "Did not expect other expired MPDUs");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check MPDUs remaining in container queue 1
|
||||
*/
|
||||
auto elemIt = m_container.GetQueue(queueId1).begin();
|
||||
auto endIt = m_container.GetQueue(queueId1).end();
|
||||
NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
|
||||
true,
|
||||
"There should be other MPDU(s) in container queue 1");
|
||||
NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
|
||||
0,
|
||||
"Unexpected queued MPDU");
|
||||
elemIt++;
|
||||
NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
|
||||
true,
|
||||
"There should be other MPDU(s) in container queue 1");
|
||||
NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
|
||||
2,
|
||||
"Unexpected queued MPDU");
|
||||
elemIt++;
|
||||
NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
|
||||
true,
|
||||
"There should be other MPDU(s) in container queue 1");
|
||||
NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
|
||||
4,
|
||||
"Unexpected queued MPDU");
|
||||
elemIt++;
|
||||
NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
|
||||
true,
|
||||
"There should be other MPDU(s) in container queue 1");
|
||||
NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
|
||||
6,
|
||||
"Unexpected queued MPDU");
|
||||
elemIt++;
|
||||
NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
|
||||
true,
|
||||
"There should be other MPDU(s) in container queue 1");
|
||||
NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
|
||||
9,
|
||||
"Unexpected queued MPDU");
|
||||
elemIt++;
|
||||
NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
|
||||
true,
|
||||
"There should be other MPDU(s) in container queue 1");
|
||||
NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
|
||||
10,
|
||||
"Unexpected queued MPDU");
|
||||
elemIt++;
|
||||
NS_TEST_EXPECT_MSG_EQ((elemIt == endIt),
|
||||
true,
|
||||
"There should be no other MPDU in container queue 1");
|
||||
|
||||
/**
|
||||
* Check MPDUs remaining in container queue 2
|
||||
*/
|
||||
elemIt = m_container.GetQueue(queueId2).begin();
|
||||
endIt = m_container.GetQueue(queueId2).end();
|
||||
NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
|
||||
true,
|
||||
"There should be other MPDU(s) in container queue 2");
|
||||
NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
|
||||
12,
|
||||
"Unexpected queued MPDU");
|
||||
elemIt++;
|
||||
NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
|
||||
true,
|
||||
"There should be other MPDU(s) in container queue 2");
|
||||
NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
|
||||
13,
|
||||
"Unexpected queued MPDU");
|
||||
elemIt++;
|
||||
NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
|
||||
true,
|
||||
"There should be other MPDU(s) in container queue 2");
|
||||
NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
|
||||
15,
|
||||
"Unexpected queued MPDU");
|
||||
elemIt++;
|
||||
NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
|
||||
true,
|
||||
"There should be other MPDU(s) in container queue 2");
|
||||
NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
|
||||
16,
|
||||
"Unexpected queued MPDU");
|
||||
elemIt++;
|
||||
NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
|
||||
true,
|
||||
"There should be other MPDU(s) in container queue 2");
|
||||
NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
|
||||
18,
|
||||
"Unexpected queued MPDU");
|
||||
elemIt++;
|
||||
NS_TEST_EXPECT_MSG_EQ((elemIt != endIt),
|
||||
true,
|
||||
"There should be other MPDU(s) in container queue 2");
|
||||
NS_TEST_EXPECT_MSG_EQ(elemIt->mpdu->GetHeader().GetSequenceNumber(),
|
||||
19,
|
||||
"Unexpected queued MPDU");
|
||||
elemIt++;
|
||||
NS_TEST_EXPECT_MSG_EQ((elemIt == endIt),
|
||||
true,
|
||||
"There should be no other MPDU in container queue 2");
|
||||
});
|
||||
|
||||
Simulator::Run();
|
||||
Simulator::Destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup wifi-test
|
||||
* \ingroup tests
|
||||
@@ -136,6 +444,7 @@ WifiMacQueueTestSuite::WifiMacQueueTestSuite()
|
||||
: TestSuite("wifi-mac-queue", UNIT)
|
||||
{
|
||||
AddTestCase(new WifiMacQueueDropOldestTest, TestCase::QUICK);
|
||||
AddTestCase(new WifiExtractExpiredMpdusTest, TestCase::QUICK);
|
||||
}
|
||||
|
||||
static WifiMacQueueTestSuite g_wifiMacQueueTestSuite; ///< the test suite
|
||||
|
||||
Reference in New Issue
Block a user