11#include "ns3/advanced-emlsr-manager.h"
12#include "ns3/boolean.h"
13#include "ns3/config.h"
14#include "ns3/eht-configuration.h"
15#include "ns3/eht-frame-exchange-manager.h"
16#include "ns3/interference-helper.h"
18#include "ns3/mgt-action-headers.h"
19#include "ns3/multi-model-spectrum-channel.h"
20#include "ns3/pointer.h"
21#include "ns3/qos-txop.h"
22#include "ns3/simulator.h"
23#include "ns3/spectrum-wifi-phy.h"
24#include "ns3/string.h"
25#include "ns3/wifi-net-device.h"
26#include "ns3/wifi-spectrum-phy-interface.h"
38 std::string(
"Check EMLSR link switching (switchAuxPhy=") +
39 std::to_string(params.switchAuxPhy) +
", resetCamStateAndInterruptSwitch=" +
40 std::to_string(params.resetCamStateAndInterruptSwitch) +
41 ", auxPhyMaxChWidth=" +
std::to_string(params.auxPhyMaxChWidth) +
"MHz )"),
42 m_switchAuxPhy(params.switchAuxPhy),
43 m_resetCamStateAndInterruptSwitch(params.resetCamStateAndInterruptSwitch),
44 m_auxPhyMaxChWidth(params.auxPhyMaxChWidth),
71 auto psdu = psduMap.begin()->second;
72 auto nodeId = mac->GetDevice()->GetNode()->GetId();
74 switch (psdu->GetHeader(0).GetType())
85 action.protectedEhtAction ==
92 std::set<uint8_t> linksToBlock;
93 for (uint8_t
id = 0;
id <
m_apMac->GetNLinks();
id++)
97 linksToBlock.insert(
id);
100 m_apMac->GetMacQueueScheduler()->BlockQueues(WifiQueueBlockedReason::TID_NOT_MAPPED,
141 for (std::size_t linkId = 0; linkId <
m_apMac->GetNLinks(); ++linkId)
149 mac->GetWifiPhy(0)->SetOperatingChannel(
151 mac->GetWifiPhy(1)->SetOperatingChannel(
153 mac->GetWifiPhy(2)->SetOperatingChannel(
180 m_apMac->GetMacQueueScheduler()->UnblockQueues(WifiQueueBlockedReason::TID_NOT_MAPPED,
188 m_apMac->GetMacQueueScheduler()->BlockQueues(WifiQueueBlockedReason::TID_NOT_MAPPED,
201 m_apMac->GetMacQueueScheduler()->BlockQueues(WifiQueueBlockedReason::TID_NOT_MAPPED,
214 m_apMac->GetMacQueueScheduler()->BlockQueues(WifiQueueBlockedReason::TID_NOT_MAPPED,
222 m_apMac->GetMacQueueScheduler()->UnblockQueues(WifiQueueBlockedReason::TID_NOT_MAPPED,
235 m_staMacs[0]->GetMacQueueScheduler()->BlockQueues(WifiQueueBlockedReason::TID_NOT_MAPPED,
243 m_staMacs[0]->GetMacQueueScheduler()->UnblockQueues(WifiQueueBlockedReason::TID_NOT_MAPPED,
255 m_staMacs[0]->GetMacQueueScheduler()->UnblockQueues(WifiQueueBlockedReason::TID_NOT_MAPPED,
263 m_staMacs[0]->GetMacQueueScheduler()->BlockQueues(WifiQueueBlockedReason::TID_NOT_MAPPED,
391 auto phyRecvIcf =
m_staMacs[0]->GetWifiPhy(linkId);
393 auto currMainPhyLinkId =
m_staMacs[0]->GetLinkForPhy(mainPhy);
396 "Didn't find the link on which the Main PHY is operating");
401 if (phyRecvIcf != mainPhy)
404 phyRecvIcf->GetChannelWidth(),
406 "Aux PHY that received ICF "
407 <<
m_countQoSframes <<
" is operating on a channel whose width exceeds the limit");
416 "Expecting that the ICF was received by the main PHY");
422 "Main PHY is operating on an unexpected link ("
423 << +currMainPhyLinkId.value() <<
", expected " << +
m_mainPhyId
434 "PHY operating on link where ICF was sent is not the main PHY");
439 if (mainPhy != phyRecvIcf)
443 "Aux PHY expected to switch channel");
446 NS_TEST_EXPECT_MSG_EQ(m_staMacs[0]->GetWifiPhy(*currMainPhyLinkId),
448 "The Aux PHY that received the ICF is expected to operate "
449 "on the link where Main PHY was before switching channel");
456 "Aux PHY is not expected to switch channel");
458 mainPhy->GetPhyBand(),
459 "The Aux PHY that received the ICF is expected to operate "
460 "on the same band as the Main PHY");
473 auto psdu = psduMap.begin()->second;
478 m_staMacs[0]->GetFrameExchangeManager(linkId)->GetWifiTxTimer().GetDelayLeft() -
483 auto toCurrSwitchEnd = mainPhy->GetDelayUntilIdle() + TimeStep(1);
488 "Main PHY expected to be in SWITCHING state instead of "
489 << mainPhy->GetState()->GetState());
505 delayLeft += mainPhy->GetChannelSwitchDelay();
508 auto totalSwitchDelay =
509 delayLeft + (mainPhy->GetChannelSwitchDelay() - toCurrSwitchEnd);
520 auto id =
m_staMacs[0]->GetLinkForPhy(mainPhy);
523 "Expected main PHY to operate on a link");
526 "Main PHY is operating on an unexpected link");
527 const auto startMsd =
530 const auto msdIsRunning = msdWasRunning || startMsd;
535 std::string(
"because total switch delay was ") +
536 std::to_string(totalSwitchDelay.GetNanoSeconds()) +
"ns");
543 std::set<uint8_t> links{0, 1, 2};
545 m_staMacs[0]->GetMacQueueScheduler()->BlockQueues(WifiQueueBlockedReason::TID_NOT_MAPPED,
579 const std::size_t nFrameExchNoRts = fe11protected ? 3 : 4;
581 const std::size_t nFrameExchWithRts = fe11protected ? 1 : 0;
586 nFrameExchNoRts * 2 +
587 nFrameExchWithRts * 4 +
589 "Insufficient number of TX PSDUs");
595 auto nextPsdu = [&]() {
600 psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsBeacon());
603 const std::size_t nFrameExchanges =
606 for (std::size_t i = 1; i <= nFrameExchanges; ++i)
608 if (i == 1 || (i >= 3 && i <= 6) || i == 8 || i == 10 || (i == 11 && fe11protected))
612 (i < 9 ? psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsTrigger()
613 : psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsRts())),
615 "Expected a Trigger Frame (ICF)");
622 psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsCts()),
628 if (i == 1 || i == 2 || i == 7 || i == 8)
631 psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsMgt()),
633 "Expected a management frame");
636 psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsAck()),
638 "Expected a Normal Ack");
643 psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsQosData()),
645 "Expected a QoS Data frame");
648 psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsBlockAck()),
650 "Expected a BlockAck");
658 std::to_string(auxPhyMaxChWidth) +
"MHz )"),
659 m_auxPhyMaxChWidth(auxPhyMaxChWidth),
661 m_currMainPhyLinkId(0),
662 m_nextMainPhyLinkId(0)
695 mac->GetWifiPhy(0)->SetOperatingChannel(
697 mac->GetWifiPhy(1)->SetOperatingChannel(
699 mac->GetWifiPhy(2)->SetOperatingChannel(
716 m_staMacs[1]->GetFrameExchangeManager(linkId)->StartTransmission(
718 m_staMacs[1]->GetWifiPhy(linkId)->GetChannelWidth());
728 <<
", other MLD did not start transmitting on link "
739 "Main PHY is not operating on any link");
744 m_staMacs[0]->GetEmlsrManager()->SwitchMainPhy(
795 "Aux PHY is not receiving a PHY header");
800 "Main PHY is receiving a PHY header");
811 "No CCA information for primary20 channel");
815 "ChannelAccessManager on destination link not notified of CCA busy");
819 "ChannelAccessManager on destination link notified of CCA busy until end of transmission");
837 "No CCA information for primary20 channel");
841 "ChannelAccessManager on destination link not notified of CCA busy");
844 "ChannelAccessManager on destination link not notified of CCA busy "
845 "until end of transmission");
862 "No CCA information for primary20 channel");
865 "ChannelAccessManager on source link not notified of CCA busy");
868 "ChannelAccessManager on source link not notified of CCA busy "
869 "until end of transmission");
874 "Check EMLSR single link operation (switchAuxPhy=" +
std::to_string(switchAuxPhy) +
875 ", auxPhyTxCapable=" +
std::to_string(auxPhyTxCapable) +
")"),
876 m_switchAuxPhy(switchAuxPhy),
877 m_auxPhyTxCapable(auxPhyTxCapable)
912 const auto psdu = psduMap.cbegin()->second;
913 const auto& hdr = psdu->GetHeader(0);
916 if (hdr.IsBeacon() || hdr.IsCfEnd())
921 auto linkId = mac->GetLinkForPhy(phyId);
924 "PHY " << +phyId <<
" is not operating on any link");
932 "Unexpected MAC header type for frame #"
950 bool testUnblockedForOtherReasons,
951 const std::string& frameStr) {
954 m_apMac->GetWifiPhy(0)->GetPhyBand());
961 WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY,
963 "Checking that AP MLD blocked transmissions to single link EMLSR "
966 testUnblockedForOtherReasons);
981 m_apMac->GetWifiRemoteStationManager(0)
982 ->GetMldAddress(
m_staMacs[0]->GetAddress())
985 "Expected the EMLSR client address to be seen as an MLD address");
998 "Expected EMLSR mode to be enabled on link 0 of EMLSR client");
1010 checkTransDelay(psdu, txVector,
false,
"DL ADDBA REQUEST");
1018 checkTransDelay(psdu, txVector,
true,
"DL ADDBA RESPONSE");
1028 checkTransDelay(psdu, txVector,
true,
"DL QoS Data");
1038 checkTransDelay(psdu, txVector,
false,
"UL ADDBA REQUEST");
1047 checkTransDelay(psdu, txVector,
true,
"UL ADDBA RESPONSE");
1055 checkTransDelay(psdu, txVector,
true,
"UL QoS Data");
1100 m_staMacs[0]->TraceConnectWithoutContext(
1104 for (uint8_t i = 0; i <
m_staMacs[0]->GetDevice()->GetNPhys(); ++i)
1113 for (
const auto linkId : mac->GetLinkIds())
1117 const auto txPower = phy->GetPower(1) + phy->GetTxGain();
1123 spectrumSignalParams->duration = duration;
1124 spectrumSignalParams->txPhy = phy->GetCurrentInterface();
1125 spectrumSignalParams->txAntenna = phy->GetAntenna();
1126 spectrumSignalParams->psd = psd;
1128 phy->StartRx(spectrumSignalParams, phy->GetCurrentInterface());
1137 for (
const auto& phy :
m_staMacs[0]->GetDevice()->GetPhys())
1140 if (
m_staMacs[0]->GetLinkForPhy(phy) == linkId)
1146 phy->GetAttribute(
"InterferenceHelper", ptr);
1151 for (uint8_t i = 0; i <
m_staMacs[0]->GetNLinks(); ++i)
1153 auto energyDuration =
1160 m_testStr <<
", " << frameTypeStr <<
": Unexpected energy duration for PHY "
1161 << +phy->GetPhyId() <<
" in the band corresponding to link " << +i);
1175 const auto psdu = psduMap.cbegin()->second;
1176 const auto& hdr = psdu->GetHeader(0);
1184 auto linkId = mac->GetLinkForPhy(phyId);
1187 "PHY " << +phyId <<
" is not operating on any link");
1198 m_events.front().func(psdu, txVector, linkId.value());
1236 NS_LOG_DEBUG(
"Main PHY leaving link " << +linkId <<
", switch delay "
1237 << mainPhy->GetChannelSwitchDelay().As(
Time::US)
1245 <<
" PHY connected to link " << +linkId <<
"\n");
1257 const auto useMacHdrInfo = ((
m_testIndex & 0b001) != 0);
1258 const auto interruptSwitch = ((
m_testIndex & 0b010) != 0);
1259 const auto switchToOtherLink = ((
m_testIndex & 0b100) != 0);
1261 const auto keepMainPhyAfterDlTxop = useMacHdrInfo;
1266 advEmlsrMgr->SetAttribute(
"InterruptSwitch",
BooleanValue(interruptSwitch));
1267 advEmlsrMgr->SetAttribute(
"KeepMainPhyAfterDlTxop",
BooleanValue(keepMainPhyAfterDlTxop));
1269 m_testStr =
"SwitchToOtherLink=" + std::to_string(switchToOtherLink) +
1270 ", InterruptSwitch=" + std::to_string(interruptSwitch) +
1271 ", UseMacHdrInfo=" + std::to_string(useMacHdrInfo) +
1272 ", KeepMainPhyAfterDlTxop=" + std::to_string(keepMainPhyAfterDlTxop) +
1273 ", ChannelSwitchDurationIdx=" + std::to_string(
m_csdIndex);
1287 uint8_t prio = (switchToOtherLink ? 3 : 0);
1289 m_staMacs[0]->GetDevice()->GetNode()->AddApplication(
1300 const auto txDuration =
1303 m_apMac->GetWifiPhy(linkId)->GetPhyBand());
1307 Time channelSwitchDelay{0};
1316 channelSwitchDelay = phyHdrDuration - margin;
1319 channelSwitchDelay = phyHdrDuration + margin;
1332 m_testStr <<
": Channel switch delay is not strictly positive ("
1333 << channelSwitchDelay.As(
Time::US) <<
")");
1337 <<
": Channel switch delay is greater than padding delay");
1339 mainPhy->SetAttribute(
"ChannelSwitchDelay",
TimeValue(channelSwitchDelay));
1347 m_testStr <<
": Main PHY did not start switching");
1350 m_testStr <<
": Main PHY did not left the preferred link");
1354 <<
": Main PHY did not start switching at ICF TX start");
1360 auto auxPhy =
m_staMacs[0]->GetWifiPhy(linkId);
1361 auto fem =
m_staMacs[0]->GetFrameExchangeManager(linkId);
1368 m_testStr <<
": Channel switch terminated before padding start");
1375 m_testStr <<
": Channel switch terminated before "
1376 "MAC header info is received");
1382 m_testStr <<
": Channel switch terminated before "
1383 "receiving RXSTART indication");
1388 m_testStr <<
": Expected to be receiving the PHY header");
1394 <<
": Expected to be in preamble detection period");
1396 NS_ABORT_MSG(
"Unexpected channel switch duration index");
1409 <<
": Main PHY not expected to be connected to a link");
1411 if (switchToOtherLink)
1416 m_testStr <<
": Main PHY did not left the link on which TID 3 is mapped");
1431 m_testStr <<
": Main PHY expected to be connected to a link");
1434 m_testStr <<
": Main PHY connected to an unexpected link");
1438 m_testStr <<
": Main PHY was not connected to a link");
1442 <<
": Main PHY was not connected to the expected link");
1445 m_testStr <<
": Main PHY was not connected at ICF TX end");
1455 m_testStr <<
": Main PHY expected to be connected to a link");
1459 <<
": Main PHY expected to be connected to same link as ICF");
1463 m_testStr <<
": Main PHY expected to be transmitting");
1466 const auto txDuration =
1469 m_staMacs[0]->GetWifiPhy(linkId)->GetPhyBand());
1480 const auto txDuration =
1483 m_staMacs[0]->GetWifiPhy(linkId)->GetPhyBand());
1491 auto shouldSwitch = (!keepMainPhyAfterDlTxop || switchToOtherLink);
1495 << (shouldSwitch ?
"" :
"not")
1496 <<
" be switching back after DL TXOP end");
1504 const auto txDuration =
1507 m_staMacs[0]->GetWifiPhy(linkId)->GetPhyBand());
1517 const auto txDuration =
1520 m_staMacs[0]->GetWifiPhy(linkId)->GetPhyBand());
1525 mainPhy->IsStateSwitching(),
1527 m_testStr <<
": Main PHY should be switching back after UL TXOP end");
1571 std::string mapping =
1600 const auto psdu = psduMap.cbegin()->second;
1601 const auto& hdr = psdu->GetHeader(0);
1609 auto linkId = mac->GetLinkForPhy(phyId);
1612 "PHY " << +phyId <<
" is not operating on any link");
1623 m_events.front().func(psdu, txVector, linkId.value());
1672 auto genTid4Frame = [=,
this]() {
1679 m_staMacs[0]->GetDevice()->GetNode()->AddApplication(
1684 DynamicCast<AdvancedEmlsrManager>(m_staMacs[0]->GetEmlsrManager());
1686 NS_TEST_EXPECT_MSG_EQ(advEmlsrMgr->m_mainPhySwitchInfo.disconnected,
1688 "Expected the main PHY to be switching");
1689 NS_TEST_EXPECT_MSG_EQ(
1690 +advEmlsrMgr->m_mainPhySwitchInfo.to,
1691 +(advEmlsrMgr->m_interruptSwitching ? m_linkIdForTid4 : m_mainPhyId),
1692 "Main PHY is switching to wrong link");
1699 info.
GetName() ==
"TxopNotGainedOnAuxPhyLink")
1712 "Unexpected value for the elapsed field");
1715 "earlySwitchReason should hold a value");
1717 WifiExpectedAccessReason::RX_END,
1718 "Unexpected earlySwitchReason value");
1726 "Unexpected value for the elapsed field");
1729 "earlySwitchReason should hold a value");
1731 WifiExpectedAccessReason::BUSY_END,
1732 "Unexpected earlySwitchReason value");
1740 "Unexpected value for the elapsed field");
1743 "earlySwitchReason should hold a value");
1745 WifiExpectedAccessReason::RX_END,
1746 "Unexpected earlySwitchReason value");
1754 "Unexpected value for the elapsed field");
1757 "earlySwitchReason should hold a value");
1759 WifiExpectedAccessReason::BACKOFF_END,
1760 "Unexpected earlySwitchReason value");
1768 "Unexpected value for the elapsed field");
1771 "earlySwitchReason should hold a value");
1773 WifiExpectedAccessReason::BACKOFF_END,
1774 "Unexpected earlySwitchReason value");
1791 "Unexpected TxopEnded reason for switching main PHY back");
1801 std::list<Events> events;
1803 events.emplace_back(
1808 "Unicast frame with TID 4 transmitted on wrong link");
1810 m_apMac->GetFrameExchangeManager(linkId)->GetAddress(),
1811 "Unexpected RA for the unicast frame with TID 4");
1813 m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress(),
1814 "Unexpected TA for the unicast frame with TID 4");
1817 "Expected a unicast frame with TID 4");
1820 if (
auto advEmlsrMgr =
1822 advEmlsrMgr->m_interruptSwitching)
1826 mainPhy->GetChannelSwitchDelay(),
1828 "Expected TX to start at main PHY switch end");
1834 events.emplace_back(
1843 "Did not receive the expected trace infos");
1867 const auto bcastTxVector =
1871 const auto bcastTxDuration =
1888 const auto interruptSwitch =
1891 const auto useMacHeader =
1896 m_staMacs[0]->GetEmlsrManager()->SetAttribute(
"SwitchMainPhyBackDelay",
1921 const auto txDuration =
1924 m_apMac->GetWifiPhy(linkId)->GetPhyBand());
1927 "Expected a broadcast frame");
1930 "Broadcast frame transmitted on wrong link");
1932 m_apMac->GetFrameExchangeManager(linkId)->GetAddress(),
1933 "Unexpected TA for the broadcast frame");
1943 mainPhy->GetState()->GetLastTime({WifiPhyState::SWITCHING}),
1945 "Main PHY is not switching at the end of PHY header reception");
1948 "Main PHY is switching to a wrong link");
1951 "Main PHY switch back timer should be running");
1957 mainPhy->GetState()->GetLastTime({WifiPhyState::SWITCHING}),
1959 "Main PHY is not switching at the end of PHY header reception");
1962 "Main PHY is switching to a wrong link");
1965 "Main PHY switch back timer should have been stopped");
1976 mainPhy->GetState()->GetLastTime({WifiPhyState::SWITCHING}),
1978 "Main PHY is not switching at the end of PHY header reception");
1981 "Main PHY is switching to a wrong link");
1984 "Main PHY switch back timer should be running");
1990 mainPhy->GetState()->GetLastTime({WifiPhyState::SWITCHING}),
1992 "Main PHY is not switching at the end of PHY header reception");
1995 "Main PHY is switching to a wrong link");
1998 "Main PHY switch back timer should have been stopped");
2009 mainPhy->GetState()->GetLastTime({WifiPhyState::SWITCHING}),
2011 "Main PHY is not switching at the end of PHY header reception");
2014 "Main PHY is switching to a wrong link");
2017 "Main PHY switch back timer should have been stopped");
2030 "Main PHY should be waiting to be connected to a link");
2033 "Main PHY is waiting to be connected to a wrong link");
2036 "Main PHY switch back timer should be running");
2046 ->NotifyAckTimeoutResetNow();
2053 mainPhy->GetState()->IsStateSwitching(),
2055 "Main PHY should not be switching at the end of PPDU reception");
2058 "Main PHY should have been connected to a link");
2061 "Main PHY should have been connected to a link");
2064 "Main PHY is connected to a wrong link");
2067 "Main PHY switch back timer should be running");
2079 "Main PHY should be waiting to be connected to a link");
2082 "Main PHY is waiting to be connected to a wrong link");
2085 "Main PHY switch back timer should be running");
2089 "Aux PHY should be in RX state");
2090 auto remTime = auxPhy->GetTimeToMacHdrEnd(
SU_STA_ID);
2093 "No MAC header info available");
2112 mainPhy->GetState()->IsStateSwitching(),
2114 "Main PHY should be switching after receiving the MAC header");
2117 "Main PHY should be switching to the preferred link");
2120 "Main PHY switch back timer should not be running");
2131 "Main PHY should be waiting to be connected to a link");
2134 "Main PHY is waiting to be connected to a wrong link");
2137 "Main PHY switch back timer should be running");
2152 mainPhy->GetState()->IsStateSwitching(),
2154 "Main PHY should be switching at the end of PPDU reception");
2157 "Main PHY should be switching back to preferred link");
2160 "Main PHY switch back timer should be not running");
2176 "Unicast frame transmitted on wrong link");
2178 m_apMac->GetFrameExchangeManager(linkId)->GetAddress(),
2179 "Unexpected RA for the unicast frame");
2181 m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress(),
2182 "Unexpected TA for the unicast frame");
2190 "Main PHY switch back timer should not be running");
2199 const auto txDuration =
2202 m_apMac->GetWifiPhy(linkId)->GetPhyBand());
2215 "Did not receive the expected trace infos");
2257 "{38, 40, BAND_5GHZ, 0}"s,
2258 "{3, 40, BAND_6GHZ, 0}"s};
2272 const auto psdu = psduMap.cbegin()->second;
2273 const auto& hdr = psdu->GetHeader(0);
2281 auto linkId = mac->GetLinkForPhy(phyId);
2284 "PHY " << +phyId <<
" is not operating on any link");
2295 m_events.front().func(psdu, txVector, linkId.value());
2325 const auto useAuxPhyCca = ((
m_testIndex & 0x1) == 1);
2331 const auto slot = auxPhy->GetSlot();
2332 const auto pifs = auxPhy->GetSifs() + slot;
2336 const auto switchDelay =
2338 ? timeToBackoffEnd + slot
2340 : timeToBackoffEnd - pifs - slot));
2343 mainPhy->SetAttribute(
"ChannelSwitchDelay",
TimeValue(switchDelay));
2363 "Expected a broadcast frame");
2366 "Broadcast frame transmitted on wrong link");
2368 m_apMac->GetFrameExchangeManager(linkId)->GetAddress(),
2369 "Unexpected TA for the broadcast frame");
2370 const auto txDuration =
2373 m_apMac->GetWifiPhy(linkId)->GetPhyBand());
2381 m_staMacs[0]->GetDevice()->GetNode()->AddApplication(
2388 const auto aifs = auxPhy->GetSifs() + emlsrBeEdca->GetAifsn(
m_linkIdForTid0) * slot;
2392 "Expected the main PHY to be switching");
2394 switchDelay - TimeStep(1),
2395 "Unexpected end of main PHY channel switch");
2422 ->GetBackoffEndFor(emlsrBeEdca);
2429 ->GetBackoffEndFor(emlsrBeEdca);
2433 NS_ABORT_MSG(
"Unexpected scenario " << +
static_cast<uint8_t
>(scenario));
2443 "Unicast frame transmitted on wrong link");
2445 m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress(),
2446 "Unexpected TA for the unicast frame");
2449 "Unexpected start TX time for unicast frame");
2452 "Unexpected channel width for the unicast frame");
2472 for (
bool switchAuxPhy : {
true,
false})
2474 for (
bool resetCamStateAndInterruptSwitch : {
true,
false})
2479 {switchAuxPhy, resetCamStateAndInterruptSwitch, auxPhyMaxChWidth}),
2480 TestCase::Duration::QUICK);
2492 for (
const auto switchAuxPhy : {
true,
false})
2494 for (
const auto auxPhyTxCapable : {
true,
false})
2497 TestCase::Duration::QUICK);
Test CCA busy notifications on EMLSR clients.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
uint8_t m_nextMainPhyLinkId
the ID of the link the main PHY switches to
uint8_t m_currMainPhyLinkId
the ID of the link the main PHY switches from
void StartTraffic() override
Start the generation of traffic (needs to be overridden)
MHz_u m_auxPhyMaxChWidth
max channel width supported by aux PHYs
void TransmitPacketToAp(uint8_t linkId)
Make the other MLD transmit a packet to the AP on the given link.
void DoRun() override
Implementation to actually run this TestCase.
Time m_channelSwitchDelay
the PHY channel switch delay
void CheckPoint1()
Perform checks after that the preamble of the first PPDU has been received.
void CheckPoint3()
Perform checks after that the aux PHY completed the link switch.
EmlsrCcaBusyTest(MHz_u auxPhyMaxChWidth)
Constructor.
void CheckPoint2()
Perform checks after that the main PHY completed the link switch.
Check NAV and CCA in the last PIFS test.
const uint8_t m_nSlotsLeft
value for the CAM NSlotsLeft attribute
void DoRun() override
Implementation to actually run this TestCase.
void StartTraffic() override
Start the generation of traffic (needs to be overridden)
const uint8_t m_linkIdForTid0
ID of the link on which TID 0 is mapped.
std::size_t m_testIndex
index to iterate over test scenarios
void Transmit(Ptr< WifiMac > mac, uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) override
Callback invoked when a FEM passes PSDUs to the PHY.
TestScenario
Enumeration indicating the tested scenario.
@ LESS_THAN_PIFS_UNTIL_BACKOFF_END
@ MORE_THAN_PIFS_UNTIL_BACKOFF_END
@ BACKOFF_END_BEFORE_SWITCH_END
bool m_setupDone
whether association, BA, ... have been done
void RunOne()
Runs a test case and invokes itself for the next test case.
Time m_expectedTxStart
expected start time for frame transmission
std::list< Events > m_events
list of events for a test run
MHz_u m_expectedWidth
expected channel width for frame transmission
EmlsrCheckNavAndCcaLastPifsTest()
Constructor.
std::size_t m_processedEvents
number of processed events
const MHz_u m_auxPhyWidth
aux PHY channel width
void DoSetup() override
Implementation to do any local setup required for this TestCase.
const MHz_u m_mainPhyWidth
main PHY channel width
Check ICF reception while main PHY is switching.
ChannelSwitchEnd m_csdIndex
index to iterate over channel switch durations
EmlsrIcfSentDuringMainPhySwitchTest()
Constructor.
void CheckInDeviceInterference(const std::string &testStr, uint8_t linkId, Time duration)
Check that the in-device interference generated by a transmission of the given duration on the given ...
const uint8_t m_linkIdForTid3
ID of the link on which TID 3 is mapped.
void RunOne()
Runs a test case and invokes itself for the next test case.
void StartTraffic() override
Start the generation of traffic (needs to be overridden)
bool m_setupDone
whether association, BA, ... have been done
std::array< WifiSpectrumBandInfo, 3 > m_bands
bands of the 3 frequency channels
void DoRun() override
Implementation to actually run this TestCase.
void Transmit(Ptr< WifiMac > mac, uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) override
Callback invoked when a FEM passes PSDUs to the PHY.
uint8_t m_testIndex
index to iterate over test scenarios
void GenerateNoiseOnAllLinks(Ptr< WifiMac > mac, Time duration)
Generate noise on all the links of the given MAC for the given time duration.
void EmlsrLinkSwitchCb(uint8_t linkId, Ptr< WifiPhy > phy, bool connected)
Callback connected to the EmlsrLinkSwitch trace source of the StaWifiMac of the EMLSR client.
std::size_t m_processedEvents
number of processed events
std::optional< MainPhySwitchInfo > m_switchFrom
info for main PHY leaving a link
std::list< Events > m_events
list of events for a test run
ChannelSwitchEnd
Enumeration indicating the duration of a main PHY channel switch compared to the ICF fields.
@ DURING_PREAMBLE_DETECTION
void DoSetup() override
Implementation to do any local setup required for this TestCase.
std::optional< MainPhySwitchInfo > m_switchTo
info for main PHY connected to a link
std::string m_testStr
test scenario description
Test the switching of PHYs on EMLSR clients.
void Transmit(Ptr< WifiMac > mac, uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) override
Callback invoked when a FEM passes PSDUs to the PHY.
bool m_resetCamStateAndInterruptSwitch
whether to reset the state of the ChannelAccessManager associated with the link on which the main PHY...
void DoRun() override
Implementation to actually run this TestCase.
void CheckResults()
Check that the simulation produced the expected results.
void CheckRtsFrame(const WifiConstPsduMap &psduMap, const WifiTxVector &txVector, uint8_t linkId)
Check that appropriate actions are taken by the EMLSR client transmitting a PPDU containing an RTS fr...
void CheckInitialControlFrame(const WifiConstPsduMap &psduMap, const WifiTxVector &txVector, uint8_t linkId)
Check that the Main PHY (and possibly the Aux PHY) correctly switches channel when the reception of a...
void DoSetup() override
Implementation to do any local setup required for this TestCase.
std::size_t m_countRtsFrames
counter for RTS frames
std::size_t m_countIcfFrames
counter for ICF frames
Ptr< ListErrorModel > m_errorModel
error rate model to corrupt packets at AP MLD
std::size_t m_countQoSframes
counter for QoS data frames
std::size_t m_txPsdusPos
position in the vector of TX PSDUs of the first ICF
void CheckQosFrames(const WifiConstPsduMap &psduMap, const WifiTxVector &txVector, uint8_t linkId)
Check that appropriate actions are taken by the AP MLD transmitting a PPDU containing QoS data frames...
EmlsrLinkSwitchTest(const Params ¶ms)
Constructor.
MHz_u m_auxPhyMaxChWidth
max channel width supported by aux PHYs
bool m_switchAuxPhy
whether AUX PHY should switch channel to operate on the link on which the Main PHY was operating befo...
Base class for EMLSR Operations tests.
virtual void MainPhySwitchInfoCallback(std::size_t index, const EmlsrMainPhySwitchTrace &info)
Callback connected to the EMLSR Manager MainPhySwitch trace source.
std::size_t m_nNonEmlsrStations
number of stations to create that do not activate EMLSR
std::vector< uint8_t > m_establishBaDl
the TIDs for which BA needs to be established with the AP as originator
void CheckBlockedLink(Ptr< WifiMac > mac, Mac48Address dest, uint8_t linkId, WifiQueueBlockedReason reason, bool blocked, std::string description, bool testUnblockedForOtherReasons=true)
Check whether QoS data unicast transmissions addressed to the given destination on the given link are...
std::size_t m_nEmlsrStations
number of stations to create that activate EMLSR
std::vector< Time > m_paddingDelay
Padding Delay advertised by the non-AP MLD.
std::set< uint8_t > m_linksToEnableEmlsrOn
IDs of the links on which EMLSR mode has to be enabled.
Ptr< ApWifiMac > m_apMac
AP wifi MAC.
void CheckMsdTimerRunning(Ptr< StaWifiMac > staMac, uint8_t linkId, bool isRunning, const std::string &msg)
Check whether the MediumSyncDelay timer is running on the given link of the given device.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
uint8_t m_mainPhyId
ID of the main PHY.
Time m_duration
simulation duration
Ptr< PacketSocketClient > GetApplication(TrafficDirection dir, std::size_t staId, std::size_t count, std::size_t pktSize, uint8_t priority=0) const
std::vector< FrameInfo > m_txPsdus
transmitted PSDUs
virtual void Transmit(Ptr< WifiMac > mac, uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
Callback invoked when a FEM passes PSDUs to the PHY.
std::vector< Time > m_transitionDelay
Transition Delay advertised by the non-AP MLD.
std::array< std::string, 3 > m_channelsStr
array of strings defining the channels for the MLD links
std::vector< Ptr< StaWifiMac > > m_staMacs
MACs of the non-AP MLDs.
std::size_t m_nPhysPerEmlsrDevice
number of PHYs per EMLSR client
std::vector< uint8_t > m_establishBaUl
the TIDs for which BA needs to be established with the AP as recipient
Switch main PHY back timer test.
void DoRun() override
Implementation to actually run this TestCase.
const uint8_t m_linkIdForTid4
ID of the link on which TID 4 is mapped.
Ptr< WifiMpdu > m_bcastFrame
the broadcast frame sent by the AP MLD
void InsertEventsForQosTid4()
Insert events corresponding to the UL TXOP to transmit the QoS Data frame with TID 4.
std::size_t m_processedEvents
number of processed events
void MainPhySwitchInfoCallback(std::size_t index, const EmlsrMainPhySwitchTrace &info) override
Callback connected to the EMLSR Manager MainPhySwitch trace source.
bool m_dlPktDone
whether the DL packet has been generated
bool m_setupDone
whether association, BA, ... have been done
void DoSetup() override
Implementation to do any local setup required for this TestCase.
std::list< Events > m_events
list of events for a test run
EmlsrSwitchMainPhyBackTest()
Constructor.
Time m_expectedMainPhySwitchBackTime
expected main PHY switch back time
void Transmit(Ptr< WifiMac > mac, uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) override
Callback invoked when a FEM passes PSDUs to the PHY.
uint8_t m_testIndex
index to iterate over test scenarios
void RunOne()
Runs a test case and invokes itself for the next test case.
TestScenario
Enumeration indicating the tested scenario.
@ RXSTART_AFTER_SWITCH_HT_PPDU
@ NON_HT_PPDU_USE_MAC_HDR
@ NON_HT_PPDU_DONT_USE_MAC_HDR
@ RXSTART_WHILE_SWITCH_INTERRUPT
@ LONG_SWITCH_BACK_DELAY_USE_MAC_HDR
@ RXSTART_WHILE_SWITCH_NO_INTERRUPT
@ LONG_SWITCH_BACK_DELAY_DONT_USE_MAC_HDR
Time m_switchMainPhyBackDelay
the switch main PHY back delay
void StartTraffic() override
Start the generation of traffic (needs to be overridden)
const uint8_t m_linkIdForTid0
ID of the link on which TID 0 is mapped.
Test ML setup and data exchange between an AP MLD and a single link EMLSR client.
bool m_auxPhyTxCapable
whether aux PHYs are TX capable
std::list< Events > m_events
list of events for a test run
void Transmit(Ptr< WifiMac > mac, uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) override
Callback invoked when a FEM passes PSDUs to the PHY.
void DoRun() override
Implementation to actually run this TestCase.
bool m_switchAuxPhy
whether aux PHYs switch link
void DoSetup() override
Implementation to do any local setup required for this TestCase.
SingleLinkEmlsrTest(bool switchAuxPhy, bool auxPhyTxCapable)
Constructor.
std::list< Events >::const_iterator m_eventIt
iterator over the list of events
wifi EMLSR suite to test link switch operations
WifiEmlsrLinkSwitchTestSuite()
AttributeValue implementation for Boolean.
static constexpr uint16_t MEDIUM_SYNC_THRESHOLD_USEC
The aMediumSyncThreshold defined by Sec. 35.3.16.18.1 of 802.11be D4.0.
static constexpr bool DONT_REQUEST_ACCESS
do not request channel access when PHY switch ends
static WifiMode GetHtMcs0()
Return MCS 0 from HT MCS values.
handles interference calculations
Time GetEnergyDuration(Watt_u energy, const WifiSpectrumBandInfo &band)
void SetList(const std::list< uint64_t > &packetlist)
static Mac48Address GetBroadcast()
static WifiMode GetOfdmRate6Mbps()
Return a WifiMode for OFDM at 6 Mbps.
AttributeValue implementation for Pointer.
Smart pointer class similar to boost::intrusive_ptr.
Template class for packet Queues.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
static Time Now()
Return the current simulation virtual time.
static void Run()
Run the simulation.
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Hold variables of type string.
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Simulation virtual time values and global simulation resolution.
AttributeValue implementation for Time.
Hold an unsigned integer type.
AttributeValue implementation for WifiMode.
std::tuple< uint8_t, MHz_u, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying a segment of an operating channel.
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode.
MHz_u GetChannelWidth() const
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
void SetDefault(std::string name, const AttributeValue &value)
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
#define NS_TEST_EXPECT_MSG_GT_OR_EQ(actual, limit, msg)
Test that an actual value is greater than or equal to limit and report if not.
#define NS_TEST_ASSERT_MSG_LT(actual, limit, msg)
Test that an actual value is less than a limit and report and abort if not.
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
#define NS_TEST_EXPECT_MSG_LT_OR_EQ(actual, limit, msg)
Test that an actual value is less than or equal to a limit and report if not.
#define NS_TEST_EXPECT_MSG_LT(actual, limit, msg)
Test that an actual value is less than a limit and report if not.
#define NS_TEST_EXPECT_MSG_GT(actual, limit, msg)
Test that an actual value is greater than a limit and report if not.
#define NS_TEST_EXPECT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report if not.
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report and abort if not.
#define NS_TEST_ASSERT_MSG_GT(actual, limit, msg)
Test that an actual value is greater than a limit and report and abort if not.
#define NS_TEST_ASSERT_MSG_GT_OR_EQ(actual, limit, msg)
Test that an actual value is greater than or equal to a limit and report and abort if not.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time Seconds(double value)
Construct a Time in the indicated unit.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
@ WIFI_MAC_MGT_ASSOCIATION_RESPONSE
@ WIFI_MAC_MGT_ASSOCIATION_REQUEST
Watt_u DbmToW(dBm_u val)
Convert from dBm to Watts.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Store information about a main PHY switch.
Parameters for the EMLSR link switching test.
Struct to trace that main PHY switched to start a DL TXOP after that an aux PHY received an ICF.
Base struct for EMLSR Main PHY switch traces.
virtual std::string_view GetName() const =0
Struct to trace that main PHY switched to leave a link on which an aux PHY was expected to gain a TXO...
static WifiEmlsrLinkSwitchTestSuite g_wifiEmlsrLinkSwitchTestSuite
the test suite