diff --git a/src/wifi/test/wifi-aggregation-test.cc b/src/wifi/test/wifi-aggregation-test.cc index 25acb0479..6ff2c4ccb 100644 --- a/src/wifi/test/wifi-aggregation-test.cc +++ b/src/wifi/test/wifi-aggregation-test.cc @@ -17,6 +17,7 @@ * Author: Sébastien Deronne */ +#include "ns3/config.h" #include "ns3/eht-configuration.h" #include "ns3/fcfs-wifi-queue-scheduler.h" #include "ns3/he-configuration.h" @@ -950,11 +951,19 @@ EhtAggregationTest::DoRun() * maximum A-MPDU size is set to 7500 bytes, hence the remaining packets are sent * in an A-MPDU containing two MPDUs, the first one including 4 MSDUs and the second * one including 3 MPDUs. + * + * It is also checked that the MAC header of every MPDU is notified to the FrameExchangeManager + * while the PSDU is being transmitted. */ class PreservePacketsInAmpdus : public TestCase { public: - PreservePacketsInAmpdus(); + /** + * Constructor. + * + * \param notifyMacHdrRxEnd whether notification of MAC header reception end is enabled + */ + PreservePacketsInAmpdus(bool notifyMacHdrRxEnd); ~PreservePacketsInAmpdus() override; void DoRun() override; @@ -963,6 +972,11 @@ class PreservePacketsInAmpdus : public TestCase std::list> m_packetList; ///< List of packets passed to the MAC std::vector m_nMpdus; ///< Number of MPDUs in PSDUs passed to the PHY std::vector m_nMsdus; ///< Number of MSDUs in MPDUs passed to the PHY + Ptr m_txPsdu; ///< PSDU being transmitted + std::vector>::const_iterator + m_expectedMpdu; ///< next MPDU expected to be received + std::size_t m_nMacHdrs{0}; ///< Number of notified MAC headers in QoS data frames + bool m_notifyMacHdrRxEnd; ///< whether notification of MAC header reception end is enabled /** * Callback invoked when an MSDU is passed to the MAC @@ -976,6 +990,17 @@ class PreservePacketsInAmpdus : public TestCase * \param txPowerW the transmit power in Watts */ void NotifyPsduForwardedDown(WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW); + /** + * Callback invoked when the reception of the MAC header of an MPDU is completed. + * \param mac the MAC to which the reception of the MAC header is notified + * \param macHdr the MAC header of the MPDU being received + * \param txVector the TXVECTOR used to transmit the PSDU + * \param psduDuration the remaining duration of the PSDU + */ + void NotifyMacHeaderEndRx(Ptr mac, + const WifiMacHeader& macHdr, + const WifiTxVector& txVector, + Time psduDuration); /** * Callback invoked when the receiver MAC forwards a packet up to the upper layer * \param p the packet @@ -983,9 +1008,10 @@ class PreservePacketsInAmpdus : public TestCase void NotifyMacForwardUp(Ptr p); }; -PreservePacketsInAmpdus::PreservePacketsInAmpdus() +PreservePacketsInAmpdus::PreservePacketsInAmpdus(bool notifyMacHdrRxEnd) : TestCase("Test case to check that the Wifi Mac forwards up the same packets received at " - "sender side.") + "sender side."), + m_notifyMacHdrRxEnd(notifyMacHdrRxEnd) { } @@ -1008,6 +1034,19 @@ PreservePacketsInAmpdus::NotifyPsduForwardedDown(WifiConstPsduMap psduMap, true, "No DL MU PPDU expected"); + // m_txPsdu is reset when the MAC header of the last MPDU in the PSDU is notified. By + // checking that m_txPsdu is nullptr when starting the transmission of a PSDU, we ensure + // that MAC headers are notified to the FEM while receiving MPDUs. + if (m_notifyMacHdrRxEnd) + { + NS_TEST_EXPECT_MSG_EQ(m_txPsdu, + nullptr, + "Missing MAC header notification: m_txPsdu was not reset"); + } + + m_txPsdu = psduMap.at(SU_STA_ID); + m_expectedMpdu = m_txPsdu->begin(); + if (!psduMap[SU_STA_ID]->GetHeader(0).IsQosData()) { return; @@ -1023,6 +1062,46 @@ PreservePacketsInAmpdus::NotifyPsduForwardedDown(WifiConstPsduMap psduMap, } } +void +PreservePacketsInAmpdus::NotifyMacHeaderEndRx(Ptr mac, + const WifiMacHeader& macHdr, + const WifiTxVector& txVector, + Time psduDuration) +{ + NS_TEST_EXPECT_MSG_NE(m_txPsdu, + nullptr, + "Notified of MAC header RX end while no PSDU is being transmitted"); + // check that the FEM stores the expected MAC header (in a nanosecond, to avoid issues + // with the ordering of the callbacks connected to the trace source) + auto expectedHdr = (*m_expectedMpdu)->GetHeader(); + Simulator::Schedule(NanoSeconds(1), [=, this]() { + auto macHdr = mac->GetFrameExchangeManager()->GetReceivedMacHdr(); + NS_TEST_ASSERT_MSG_EQ(macHdr.has_value(), + true, + "Expected the FEM to store the MAC header being received"); + NS_TEST_EXPECT_MSG_EQ(macHdr->get().GetSequenceNumber(), + expectedHdr.GetSequenceNumber(), + "Wrong sequence number in the MAC header stored by the FEM"); + }); + + if (expectedHdr.IsQosData()) + { + m_nMacHdrs++; + } + + if (++m_expectedMpdu == m_txPsdu->end()) + { + m_txPsdu = nullptr; + // check that the FEM stores no MAC header right after PSDU end + Simulator::Schedule(psduDuration + NanoSeconds(1), [=, this]() { + auto macHeader = mac->GetFrameExchangeManager()->GetReceivedMacHdr(); + NS_TEST_EXPECT_MSG_EQ(macHeader.has_value(), + false, + "Expected the FEM to store no MAC header"); + }); + } +} + void PreservePacketsInAmpdus::NotifyMacForwardUp(Ptr p) { @@ -1034,6 +1113,8 @@ PreservePacketsInAmpdus::NotifyMacForwardUp(Ptr p) void PreservePacketsInAmpdus::DoRun() { + Config::SetDefault("ns3::WifiPhy::NotifyMacHdrRxEnd", BooleanValue(m_notifyMacHdrRxEnd)); + NodeContainer wifiStaNode; wifiStaNode.Create(1); @@ -1121,6 +1202,10 @@ PreservePacketsInAmpdus::DoRun() sta_device->GetPhy()->TraceConnectWithoutContext( "PhyTxPsduBegin", MakeCallback(&PreservePacketsInAmpdus::NotifyPsduForwardedDown, this)); + ap_device->GetPhy()->TraceConnectWithoutContext( + "PhyRxMacHeaderEnd", + MakeCallback(&PreservePacketsInAmpdus::NotifyMacHeaderEndRx, this) + .Bind(ap_device->GetMac())); ap_device->GetMac()->TraceConnectWithoutContext( "MacRx", MakeCallback(&PreservePacketsInAmpdus::NotifyMacForwardUp, this)); @@ -1140,6 +1225,11 @@ PreservePacketsInAmpdus::DoRun() NS_TEST_EXPECT_MSG_EQ(m_nMpdus[1], 2, "Unexpected number of MPDUs in the second A-MPDU"); NS_TEST_EXPECT_MSG_EQ(m_nMsdus[1], 4, "Unexpected number of MSDUs in the second MPDU"); NS_TEST_EXPECT_MSG_EQ(m_nMsdus[2], 3, "Unexpected number of MSDUs in the third MPDU"); + // Three MPDUs (of type QoS data) have been transmitted, so we expect that 3 MAC headers + // have been notified to the FEM + NS_TEST_EXPECT_MSG_EQ(m_nMacHdrs, + (m_notifyMacHdrRxEnd ? 3 : 0), + "Unexpected number of MAC headers notified to the FEM"); // All the packets must have been forwarded up at the receiver NS_TEST_EXPECT_MSG_EQ(m_packetList.empty(), true, "Some packets have not been forwarded up"); } @@ -1165,7 +1255,8 @@ WifiAggregationTestSuite::WifiAggregationTestSuite() AddTestCase(new HeAggregationTest(256), TestCase::Duration::QUICK); AddTestCase(new EhtAggregationTest(512), TestCase::Duration::QUICK); AddTestCase(new EhtAggregationTest(1024), TestCase::Duration::QUICK); - AddTestCase(new PreservePacketsInAmpdus, TestCase::Duration::QUICK); + AddTestCase(new PreservePacketsInAmpdus(true), TestCase::Duration::QUICK); + AddTestCase(new PreservePacketsInAmpdus(false), TestCase::Duration::QUICK); } static WifiAggregationTestSuite g_wifiAggregationTestSuite; ///< the test suite