wifi: Add unit test for extraction of expired MPDUs

This commit is contained in:
Stefano Avallone
2023-03-10 11:44:52 +01:00
parent 101a5a1a40
commit 44f6309bf2

View File

@@ -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