From 8f3053fcf244acf4a1e41da8a301e8d3363a3c4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deronne?= Date: Mon, 26 Feb 2024 17:54:30 +0100 Subject: [PATCH] wifi: Extend multiple PHY interfaces test with an EMLSR use case --- src/wifi/test/spectrum-wifi-phy-test.cc | 206 +++++++++++++++++++++--- 1 file changed, 187 insertions(+), 19 deletions(-) diff --git a/src/wifi/test/spectrum-wifi-phy-test.cc b/src/wifi/test/spectrum-wifi-phy-test.cc index 9091572e1..8be77b451 100644 --- a/src/wifi/test/spectrum-wifi-phy-test.cc +++ b/src/wifi/test/spectrum-wifi-phy-test.cc @@ -820,8 +820,9 @@ class SpectrumWifiPhyMultipleInterfacesTest : public TestCase * \param phy the PHY to transmit the signal * \param txPowerDbm the power in dBm to transmit the signal (this is also the received power * since we do not have propagation loss to simplify) + * \param payloadSize the payload size in bytes */ - void SendPpdu(Ptr phy, double txPowerDbm); + void SendPpdu(Ptr phy, double txPowerDbm, uint32_t payloadSize); /** * Callback triggered when a packet is received by a PHY @@ -833,6 +834,27 @@ class SpectrumWifiPhyMultipleInterfacesTest : public TestCase Ptr packet, RxPowerWattPerChannelBand rxPowersW); + /** + * Receive success function + * \param index index of the RX STA + * \param psdu the PSDU + * \param rxSignalInfo the info on the received signal (\see RxSignalInfo) + * \param txVector the transmit vector + * \param statusPerMpdu reception status per MPDU + */ + void RxSuccess(std::size_t index, + Ptr psdu, + RxSignalInfo rxSignalInfo, + WifiTxVector txVector, + std::vector statusPerMpdu); + + /** + * Receive failure function + * \param index index of the RX STA + * \param psdu the PSDU + */ + void RxFailure(std::size_t index, Ptr psdu); + /** * Schedule now to check the interferences * \param phy the PHY for which the check has to be executed @@ -860,6 +882,8 @@ class SpectrumWifiPhyMultipleInterfacesTest : public TestCase * * \param index the index to identify the RX PHY to check * \param expectedNumRx the expected number of RX events for that PHY + * \param expectedNumRxSuccess the expected amount of successfully received packets + * \param expectedRxBytes the expected amount of received bytes * \param expectedFrequencyRangeActiveRfInterface the expected frequency range (in MHz) of the * active RF interface * \param expectedConnectedPhysPerChannel the expected @@ -867,6 +891,8 @@ class SpectrumWifiPhyMultipleInterfacesTest : public TestCase */ void CheckResults(std::size_t index, uint32_t expectedNumRx, + uint32_t expectedNumRxSuccess, + uint32_t expectedRxBytes, FrequencyRange expectedFrequencyRangeActiveRfInterface, const std::vector& expectedConnectedPhysPerChannel); @@ -894,7 +920,12 @@ class SpectrumWifiPhyMultipleInterfacesTest : public TestCase std::vector> m_rxPhys{}; //!< RX PHYs std::vector> m_listeners{}; //!< listeners - std::vector m_counts{0}; //!< count number of packets received by PHYs + std::vector m_counts; //!< count number of packets received by PHYs + std::vector + m_countRxSuccess; //!< count number of packets successfully received by PHYs + std::vector + m_countRxFailure; //!< count number of packets unsuccessfully received by PHYs + std::vector m_rxBytes; //!< count number of received bytes Time m_lastTxStart{0}; //!< hold the time at which the last transmission started Time m_lastTxEnd{0}; //!< hold the time at which the last transmission ended @@ -923,14 +954,16 @@ SpectrumWifiPhyMultipleInterfacesTest::SwitchChannel(std::size_t index, } void -SpectrumWifiPhyMultipleInterfacesTest::SendPpdu(Ptr phy, double txPowerDbm) +SpectrumWifiPhyMultipleInterfacesTest::SendPpdu(Ptr phy, + double txPowerDbm, + uint32_t payloadSize) { - NS_LOG_FUNCTION(this << phy << txPowerDbm << phy->GetCurrentFrequencyRange() + NS_LOG_FUNCTION(this << phy << txPowerDbm << payloadSize << phy->GetCurrentFrequencyRange() << phy->GetChannelWidth() << phy->GetChannelNumber()); WifiTxVector txVector = - WifiTxVector(HePhy::GetHeMcs0(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, false, false); - Ptr pkt = Create(1000); + WifiTxVector(HePhy::GetHeMcs11(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, false, false); + Ptr pkt = Create(payloadSize); WifiMacHeader hdr; hdr.SetType(WIFI_MAC_QOSDATA); hdr.SetQosTid(0); @@ -949,13 +982,33 @@ SpectrumWifiPhyMultipleInterfacesTest::SendPpdu(Ptr phy, double void SpectrumWifiPhyMultipleInterfacesTest::RxCallback(std::size_t index, - Ptr /*packet*/, + Ptr packet, RxPowerWattPerChannelBand /*rxPowersW*/) { auto phy = m_rxPhys.at(index); - NS_LOG_FUNCTION(this << index << phy->GetCurrentFrequencyRange() << phy->GetChannelWidth() - << phy->GetChannelNumber()); + const auto payloadBytes = packet->GetSize() - 30; + NS_LOG_FUNCTION(this << index << payloadBytes << phy->GetCurrentFrequencyRange() + << phy->GetChannelWidth() << phy->GetChannelNumber()); m_counts.at(index)++; + m_rxBytes.at(index) += payloadBytes; +} + +void +SpectrumWifiPhyMultipleInterfacesTest::RxSuccess(std::size_t index, + Ptr psdu, + RxSignalInfo rxSignalInfo, + WifiTxVector txVector, + std::vector /*statusPerMpdu*/) +{ + NS_LOG_FUNCTION(this << index << *psdu << rxSignalInfo << txVector); + m_countRxSuccess.at(index)++; +} + +void +SpectrumWifiPhyMultipleInterfacesTest::RxFailure(std::size_t index, Ptr psdu) +{ + NS_LOG_FUNCTION(this << index << *psdu); + m_countRxFailure.at(index)++; } void @@ -998,10 +1051,13 @@ void SpectrumWifiPhyMultipleInterfacesTest::CheckResults( std::size_t index, uint32_t expectedNumRx, + uint32_t expectedNumRxSuccess, + uint32_t expectedRxBytes, FrequencyRange expectedFrequencyRangeActiveRfInterface, const std::vector& expectedConnectedPhysPerChannel) { - NS_LOG_FUNCTION(this << index << expectedNumRx << expectedFrequencyRangeActiveRfInterface); + NS_LOG_FUNCTION(this << index << expectedNumRx << expectedNumRxSuccess << expectedRxBytes + << expectedFrequencyRangeActiveRfInterface); const auto phy = m_rxPhys.at(index); std::size_t numActiveInterfaces = 0; for (const auto& [freqRange, interface] : phy->GetSpectrumPhyInterfaces()) @@ -1022,12 +1078,16 @@ SpectrumWifiPhyMultipleInterfacesTest::CheckResults( expectedConnectedPhysPerChannel.at(i), "Incorrect number of PHYs attached to the spectrum channel"); } - NS_TEST_ASSERT_MSG_EQ(m_counts.at(index), - expectedNumRx, - "Didn't receive right number of packets"); + NS_TEST_ASSERT_MSG_EQ(m_counts.at(index), expectedNumRx, "Unexpected amount of RX events"); + NS_TEST_ASSERT_MSG_EQ(m_countRxSuccess.at(index), + expectedNumRxSuccess, + "Unexpected amount of successfully received packets"); + NS_TEST_ASSERT_MSG_EQ(m_countRxFailure.at(index), + 0, + "Unexpected amount of unsuccessfully received packets"); NS_TEST_ASSERT_MSG_EQ(m_listeners.at(index)->m_notifyRxStart, - expectedNumRx, - "Didn't receive NotifyRxStart"); + expectedNumRxSuccess, + "Unexpected amount of RX payload start indication"); } void @@ -1072,6 +1132,19 @@ SpectrumWifiPhyMultipleInterfacesTest::Reset() txPhy->GetChannelNumber(), txPhy->GetChannelWidth()); } + // reset counters + for (auto& countRxSuccess : m_countRxSuccess) + { + countRxSuccess = 0; + } + for (auto& countRxFailure : m_countRxFailure) + { + countRxFailure = 0; + } + for (auto& rxBytes : m_rxBytes) + { + rxBytes = 0; + } } void @@ -1155,12 +1228,20 @@ SpectrumWifiPhyMultipleInterfacesTest::DoSetup() "PhyRxBegin", MakeCallback(&SpectrumWifiPhyMultipleInterfacesTest::RxCallback, this).Bind(index)); + rxPhy->SetReceiveOkCallback( + MakeCallback(&SpectrumWifiPhyMultipleInterfacesTest::RxSuccess, this).Bind(index)); + rxPhy->SetReceiveErrorCallback( + MakeCallback(&SpectrumWifiPhyMultipleInterfacesTest::RxFailure, this).Bind(index)); + auto listener = std::make_shared(); rxPhy->RegisterListener(listener); m_listeners.push_back(std::move(listener)); m_rxPhys.push_back(rxPhy); m_counts.push_back(0); + m_countRxSuccess.push_back(0); + m_countRxFailure.push_back(0); + m_rxBytes.push_back(0); } } @@ -1207,6 +1288,7 @@ SpectrumWifiPhyMultipleInterfacesTest::DoRun() // interferences on inactive interfaces std::vector{2, 2, 2, 2}; // default channels active for all PHYs: each PHY // only receives from its associated TX + for (std::size_t i = 0; i < 4; ++i) { auto txPpduPhy = m_txPhys.at(i); @@ -1215,7 +1297,8 @@ SpectrumWifiPhyMultipleInterfacesTest::DoRun() &SpectrumWifiPhyMultipleInterfacesTest::SendPpdu, this, txPpduPhy, - 0); + 0, + 1000); for (std::size_t j = 0; j < 4; ++j) { auto txPhy = m_txPhys.at(j); @@ -1233,6 +1316,8 @@ SpectrumWifiPhyMultipleInterfacesTest::DoRun() this, j, (i == j) ? 1 : 0, + (i == j) ? 1 : 0, + (i == j) ? 1000 : 0, expectedFreqRange, expectedConnectedPhysPerChannel); } @@ -1250,7 +1335,8 @@ SpectrumWifiPhyMultipleInterfacesTest::DoRun() &SpectrumWifiPhyMultipleInterfacesTest::SendPpdu, this, txPpduPhy, - 0); + 0, + 1000); const auto& expectedFreqRange = txPpduPhy->GetCurrentFrequencyRange(); for (std::size_t j = 0; j < 4; ++j) { @@ -1281,6 +1367,8 @@ SpectrumWifiPhyMultipleInterfacesTest::DoRun() this, j, 1, + 1, + 1000, expectedFreqRange, expectedConnectedPhysPerChannel); } @@ -1302,7 +1390,8 @@ SpectrumWifiPhyMultipleInterfacesTest::DoRun() &SpectrumWifiPhyMultipleInterfacesTest::SendPpdu, this, txPpduPhy, - 0); + 0, + 1000); for (std::size_t j = 0; j < 4; ++j) { if (!m_trackSignalsInactiveInterfaces) @@ -1325,6 +1414,8 @@ SpectrumWifiPhyMultipleInterfacesTest::DoRun() this, j, (i == secondSpectrumChannelIndex) ? 1 : 0, + (i == secondSpectrumChannelIndex) ? 1 : 0, + (i == secondSpectrumChannelIndex) ? 1000 : 0, expectedFreqRange, expectedConnectedPhysPerChannel); } @@ -1361,7 +1452,8 @@ SpectrumWifiPhyMultipleInterfacesTest::DoRun() &SpectrumWifiPhyMultipleInterfacesTest::SendPpdu, this, txPpduPhy, - txPowerDbm); + txPowerDbm, + 1000); Simulator::Schedule(delay + txOngoingAfterTxStartedDelay, &SpectrumWifiPhyMultipleInterfacesTest::SwitchChannel, this, @@ -1396,6 +1488,82 @@ SpectrumWifiPhyMultipleInterfacesTest::DoRun() } } + /* Reproduce an EMLSR scenario where a PHY is on an initial band and receives a packet. + * Then, the PHY switches to another band where it starts receiving another packet. + * During reception of the PHY header, the PHY switches back to the initial band and starts + * receiving yet another packet. In this case, first and last packets should be successfully + * received (no interference), the second packet reception has been interrupted (before the + * payload reception does start, hence it does not reach the RX state). */ + if (m_trackSignalsInactiveInterfaces) + { + // first TX on initial band + auto txPpduPhy = m_txPhys.at(0); + delay += Seconds(1); + Simulator::Schedule(delay, + &SpectrumWifiPhyMultipleInterfacesTest::SendPpdu, + this, + txPpduPhy, + 20, + 500); + + // switch channel to other band + delay += Seconds(1); + txPpduPhy = m_txPhys.at(1); + Simulator::Schedule(delay, + &SpectrumWifiPhyMultipleInterfacesTest::SwitchChannel, + this, + 0, + txPpduPhy->GetPhyBand(), + txPpduPhy->GetChannelNumber(), + txPpduPhy->GetChannelWidth()); + + // TX on other band with high power + delay += Seconds(1); + Simulator::Schedule(delay, + &SpectrumWifiPhyMultipleInterfacesTest::SendPpdu, + this, + txPpduPhy, + 0, + 1000); + + // switch back to initial band during PHY header reception + txPpduPhy = m_txPhys.at(0); + delay += MicroSeconds(20); // right after legacy PHY header reception + Simulator::Schedule(delay, + &SpectrumWifiPhyMultipleInterfacesTest::SwitchChannel, + this, + 0, + txPpduPhy->GetPhyBand(), + txPpduPhy->GetChannelNumber(), + txPpduPhy->GetChannelWidth()); + + // TX once more on the initial band + delay += Seconds(1); + Simulator::Schedule(delay, + &SpectrumWifiPhyMultipleInterfacesTest::SendPpdu, + this, + txPpduPhy, + 0, + 1500); + + // check results + Simulator::Schedule(delay + checkResultsDelay, + &SpectrumWifiPhyMultipleInterfacesTest::CheckResults, + this, + 0, + 3, // 3 RX events + 2, // 2 packets should have been successfully received, 1 packet should + // have been interrupted (switch during PHY header reception) + 2000, // 500 bytes (firstpacket) and 1500 bytes (third packet) + txPpduPhy->GetCurrentFrequencyRange(), + expectedConnectedPhysPerChannel); + + // reset + Simulator::Schedule(delay + flushResultsDelay, + &SpectrumWifiPhyMultipleInterfacesTest::Reset, + this); + } + delay += Seconds(1); Simulator::Stop(delay); Simulator::Run();