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");
528 const auto msdIsRunning = msdWasRunning || startMsd;
533 std::string(
"because total switch delay was ") +
534 std::to_string(totalSwitchDelay.GetNanoSeconds()) +
"ns");
541 std::set<uint8_t> links{0, 1, 2};
543 m_staMacs[0]->GetMacQueueScheduler()->BlockQueues(WifiQueueBlockedReason::TID_NOT_MAPPED,
577 const std::size_t nFrameExchNoRts = fe11protected ? 3 : 4;
579 const std::size_t nFrameExchWithRts = fe11protected ? 1 : 0;
584 nFrameExchNoRts * 2 +
585 nFrameExchWithRts * 4 +
587 "Insufficient number of TX PSDUs");
593 auto nextPsdu = [&]() {
598 psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsBeacon());
601 const std::size_t nFrameExchanges =
604 for (std::size_t i = 1; i <= nFrameExchanges; ++i)
606 if (i == 1 || (i >= 3 && i <= 6) || i == 8 || i == 10 || (i == 11 && fe11protected))
610 (i < 9 ? psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsTrigger()
611 : psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsRts())),
613 "Expected a Trigger Frame (ICF)");
620 psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsCts()),
626 if (i == 1 || i == 2 || i == 7 || i == 8)
629 psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsMgt()),
631 "Expected a management frame");
634 psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsAck()),
636 "Expected a Normal Ack");
641 psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsQosData()),
643 "Expected a QoS Data frame");
646 psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsBlockAck()),
648 "Expected a BlockAck");
656 std::to_string(auxPhyMaxChWidth) +
"MHz )"),
657 m_auxPhyMaxChWidth(auxPhyMaxChWidth),
659 m_currMainPhyLinkId(0),
660 m_nextMainPhyLinkId(0)
693 mac->GetWifiPhy(0)->SetOperatingChannel(
695 mac->GetWifiPhy(1)->SetOperatingChannel(
697 mac->GetWifiPhy(2)->SetOperatingChannel(
714 m_staMacs[1]->GetFrameExchangeManager(linkId)->StartTransmission(
716 m_staMacs[1]->GetWifiPhy(linkId)->GetChannelWidth());
726 <<
", other MLD did not start transmitting on link "
737 "Main PHY is not operating on any link");
742 m_staMacs[0]->GetEmlsrManager()->SwitchMainPhy(
793 "Aux PHY is not receiving a PHY header");
798 "Main PHY is receiving a PHY header");
809 "No CCA information for primary20 channel");
813 "ChannelAccessManager on destination link not notified of CCA busy");
817 "ChannelAccessManager on destination link notified of CCA busy until end of transmission");
835 "No CCA information for primary20 channel");
839 "ChannelAccessManager on destination link not notified of CCA busy");
842 "ChannelAccessManager on destination link not notified of CCA busy "
843 "until end of transmission");
860 "No CCA information for primary20 channel");
863 "ChannelAccessManager on source link not notified of CCA busy");
866 "ChannelAccessManager on source link not notified of CCA busy "
867 "until end of transmission");
872 "Check EMLSR single link operation (switchAuxPhy=" +
std::to_string(switchAuxPhy) +
873 ", auxPhyTxCapable=" +
std::to_string(auxPhyTxCapable) +
")"),
874 m_switchAuxPhy(switchAuxPhy),
875 m_auxPhyTxCapable(auxPhyTxCapable)
910 const auto psdu = psduMap.cbegin()->second;
911 const auto& hdr = psdu->GetHeader(0);
914 if (hdr.IsBeacon() || hdr.IsCfEnd())
919 auto linkId = mac->GetLinkForPhy(phyId);
922 "PHY " << +phyId <<
" is not operating on any link");
930 "Unexpected MAC header type for frame #"
948 bool testUnblockedForOtherReasons,
949 const std::string& frameStr) {
952 m_apMac->GetWifiPhy(0)->GetPhyBand());
959 WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY,
961 "Checking that AP MLD blocked transmissions to single link EMLSR "
964 testUnblockedForOtherReasons);
979 m_apMac->GetWifiRemoteStationManager(0)
980 ->GetMldAddress(
m_staMacs[0]->GetAddress())
983 "Expected the EMLSR client address to be seen as an MLD address");
996 "Expected EMLSR mode to be enabled on link 0 of EMLSR client");
1008 checkTransDelay(psdu, txVector,
false,
"DL ADDBA REQUEST");
1016 checkTransDelay(psdu, txVector,
true,
"DL ADDBA RESPONSE");
1026 checkTransDelay(psdu, txVector,
true,
"DL QoS Data");
1036 checkTransDelay(psdu, txVector,
false,
"UL ADDBA REQUEST");
1045 checkTransDelay(psdu, txVector,
true,
"UL ADDBA RESPONSE");
1053 checkTransDelay(psdu, txVector,
true,
"UL QoS Data");
1098 m_staMacs[0]->TraceConnectWithoutContext(
1102 for (uint8_t i = 0; i <
m_staMacs[0]->GetDevice()->GetNPhys(); ++i)
1111 for (
const auto linkId : mac->GetLinkIds())
1115 const auto txPower = phy->GetPower(1) + phy->GetTxGain();
1121 spectrumSignalParams->duration = duration;
1122 spectrumSignalParams->txPhy = phy->GetCurrentInterface();
1123 spectrumSignalParams->txAntenna = phy->GetAntenna();
1124 spectrumSignalParams->psd = psd;
1126 phy->StartRx(spectrumSignalParams, phy->GetCurrentInterface());
1135 for (
const auto& phy :
m_staMacs[0]->GetDevice()->GetPhys())
1138 if (
m_staMacs[0]->GetLinkForPhy(phy) == linkId)
1144 phy->GetAttribute(
"InterferenceHelper", ptr);
1149 for (uint8_t i = 0; i <
m_staMacs[0]->GetNLinks(); ++i)
1151 auto energyDuration =
1158 m_testStr <<
", " << frameTypeStr <<
": Unexpected energy duration for PHY "
1159 << +phy->GetPhyId() <<
" in the band corresponding to link " << +i);
1173 const auto psdu = psduMap.cbegin()->second;
1174 const auto& hdr = psdu->GetHeader(0);
1182 auto linkId = mac->GetLinkForPhy(phyId);
1185 "PHY " << +phyId <<
" is not operating on any link");
1196 m_events.front().func(psdu, txVector, linkId.value());
1234 NS_LOG_DEBUG(
"Main PHY leaving link " << +linkId <<
", switch delay "
1235 << mainPhy->GetChannelSwitchDelay().As(
Time::US)
1243 <<
" PHY connected to link " << +linkId <<
"\n");
1255 const auto useMacHdrInfo = ((
m_testIndex & 0b001) != 0);
1256 const auto interruptSwitch = ((
m_testIndex & 0b010) != 0);
1257 const auto switchToOtherLink = ((
m_testIndex & 0b100) != 0);
1259 const auto keepMainPhyAfterDlTxop = useMacHdrInfo;
1264 advEmlsrMgr->SetAttribute(
"InterruptSwitch",
BooleanValue(interruptSwitch));
1265 advEmlsrMgr->SetAttribute(
"KeepMainPhyAfterDlTxop",
BooleanValue(keepMainPhyAfterDlTxop));
1267 m_testStr =
"SwitchToOtherLink=" + std::to_string(switchToOtherLink) +
1268 ", InterruptSwitch=" + std::to_string(interruptSwitch) +
1269 ", UseMacHdrInfo=" + std::to_string(useMacHdrInfo) +
1270 ", KeepMainPhyAfterDlTxop=" + std::to_string(keepMainPhyAfterDlTxop) +
1271 ", ChannelSwitchDurationIdx=" + std::to_string(
m_csdIndex);
1285 uint8_t prio = (switchToOtherLink ? 3 : 0);
1287 m_staMacs[0]->GetDevice()->GetNode()->AddApplication(
1298 const auto txDuration =
1301 m_apMac->GetWifiPhy(linkId)->GetPhyBand());
1305 Time channelSwitchDelay{0};
1314 channelSwitchDelay = phyHdrDuration - margin;
1317 channelSwitchDelay = phyHdrDuration + margin;
1330 m_testStr <<
": Channel switch delay is not strictly positive ("
1331 << channelSwitchDelay.As(
Time::US) <<
")");
1335 <<
": Channel switch delay is greater than padding delay");
1337 mainPhy->SetAttribute(
"ChannelSwitchDelay",
TimeValue(channelSwitchDelay));
1345 m_testStr <<
": Main PHY did not start switching");
1348 m_testStr <<
": Main PHY did not left the preferred link");
1352 <<
": Main PHY did not start switching at ICF TX start");
1358 auto auxPhy =
m_staMacs[0]->GetWifiPhy(linkId);
1359 auto fem =
m_staMacs[0]->GetFrameExchangeManager(linkId);
1366 m_testStr <<
": Channel switch terminated before padding start");
1373 m_testStr <<
": Channel switch terminated before "
1374 "MAC header info is received");
1380 m_testStr <<
": Channel switch terminated before "
1381 "receiving RXSTART indication");
1386 m_testStr <<
": Expected to be receiving the PHY header");
1392 <<
": Expected to be in preamble detection period");
1394 NS_ABORT_MSG(
"Unexpected channel switch duration index");
1407 <<
": Main PHY not expected to be connected to a link");
1409 if (switchToOtherLink)
1414 m_testStr <<
": Main PHY did not left the link on which TID 3 is mapped");
1429 m_testStr <<
": Main PHY expected to be connected to a link");
1432 m_testStr <<
": Main PHY connected to an unexpected link");
1436 m_testStr <<
": Main PHY was not connected to a link");
1440 <<
": Main PHY was not connected to the expected link");
1443 m_testStr <<
": Main PHY was not connected at ICF TX end");
1453 m_testStr <<
": Main PHY expected to be connected to a link");
1457 <<
": Main PHY expected to be connected to same link as ICF");
1461 m_testStr <<
": Main PHY expected to be transmitting");
1464 const auto txDuration =
1467 m_staMacs[0]->GetWifiPhy(linkId)->GetPhyBand());
1478 const auto txDuration =
1481 m_staMacs[0]->GetWifiPhy(linkId)->GetPhyBand());
1489 auto shouldSwitch = (!keepMainPhyAfterDlTxop || switchToOtherLink);
1493 << (shouldSwitch ?
"" :
"not")
1494 <<
" be switching back after DL TXOP end");
1502 const auto txDuration =
1505 m_staMacs[0]->GetWifiPhy(linkId)->GetPhyBand());
1515 const auto txDuration =
1518 m_staMacs[0]->GetWifiPhy(linkId)->GetPhyBand());
1523 mainPhy->IsStateSwitching(),
1525 m_testStr <<
": Main PHY should be switching back after UL TXOP end");
1569 std::string mapping =
1598 const auto psdu = psduMap.cbegin()->second;
1599 const auto& hdr = psdu->GetHeader(0);
1607 auto linkId = mac->GetLinkForPhy(phyId);
1610 "PHY " << +phyId <<
" is not operating on any link");
1621 m_events.front().func(psdu, txVector, linkId.value());
1670 auto genTid4Frame = [=,
this]() {
1677 m_staMacs[0]->GetDevice()->GetNode()->AddApplication(
1682 DynamicCast<AdvancedEmlsrManager>(m_staMacs[0]->GetEmlsrManager());
1684 NS_TEST_EXPECT_MSG_EQ(advEmlsrMgr->m_mainPhySwitchInfo.disconnected,
1686 "Expected the main PHY to be switching");
1687 NS_TEST_EXPECT_MSG_EQ(
1688 +advEmlsrMgr->m_mainPhySwitchInfo.to,
1689 +(advEmlsrMgr->m_interruptSwitching ? m_linkIdForTid4 : m_mainPhyId),
1690 "Main PHY is switching to wrong link");
1697 info.
GetName() ==
"TxopNotGainedOnAuxPhyLink")
1710 "Unexpected value for the elapsed field");
1713 "earlySwitchReason should hold a value");
1715 WifiExpectedAccessReason::RX_END,
1716 "Unexpected earlySwitchReason value");
1724 "Unexpected value for the elapsed field");
1727 "earlySwitchReason should hold a value");
1729 WifiExpectedAccessReason::BUSY_END,
1730 "Unexpected earlySwitchReason value");
1738 "Unexpected value for the elapsed field");
1741 "earlySwitchReason should hold a value");
1743 WifiExpectedAccessReason::RX_END,
1744 "Unexpected earlySwitchReason value");
1752 "Unexpected value for the elapsed field");
1755 "earlySwitchReason should hold a value");
1757 WifiExpectedAccessReason::BACKOFF_END,
1758 "Unexpected earlySwitchReason value");
1766 "Unexpected value for the elapsed field");
1769 "earlySwitchReason should hold a value");
1771 WifiExpectedAccessReason::BACKOFF_END,
1772 "Unexpected earlySwitchReason value");
1789 "Unexpected TxopEnded reason for switching main PHY back");
1799 std::list<Events> events;
1801 events.emplace_back(
1806 "Unicast frame with TID 4 transmitted on wrong link");
1808 m_apMac->GetFrameExchangeManager(linkId)->GetAddress(),
1809 "Unexpected RA for the unicast frame with TID 4");
1811 m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress(),
1812 "Unexpected TA for the unicast frame with TID 4");
1815 "Expected a unicast frame with TID 4");
1818 if (
auto advEmlsrMgr =
1820 advEmlsrMgr->m_interruptSwitching)
1824 mainPhy->GetChannelSwitchDelay(),
1826 "Expected TX to start at main PHY switch end");
1832 events.emplace_back(
1841 "Did not receive the expected trace infos");
1865 const auto bcastTxVector =
1869 const auto bcastTxDuration =
1886 const auto interruptSwitch =
1889 const auto useMacHeader =
1894 m_staMacs[0]->GetEmlsrManager()->SetAttribute(
"SwitchMainPhyBackDelay",
1919 const auto txDuration =
1922 m_apMac->GetWifiPhy(linkId)->GetPhyBand());
1925 "Expected a broadcast frame");
1928 "Broadcast frame transmitted on wrong link");
1930 m_apMac->GetFrameExchangeManager(linkId)->GetAddress(),
1931 "Unexpected TA for the broadcast frame");
1941 mainPhy->GetState()->GetLastTime({WifiPhyState::SWITCHING}),
1943 "Main PHY is not switching at the end of PHY header reception");
1946 "Main PHY is switching to a wrong link");
1949 "Main PHY switch back timer should be running");
1955 mainPhy->GetState()->GetLastTime({WifiPhyState::SWITCHING}),
1957 "Main PHY is not switching at the end of PHY header reception");
1960 "Main PHY is switching to a wrong link");
1963 "Main PHY switch back timer should have been stopped");
1974 mainPhy->GetState()->GetLastTime({WifiPhyState::SWITCHING}),
1976 "Main PHY is not switching at the end of PHY header reception");
1979 "Main PHY is switching to a wrong link");
1982 "Main PHY switch back timer should be running");
1988 mainPhy->GetState()->GetLastTime({WifiPhyState::SWITCHING}),
1990 "Main PHY is not switching at the end of PHY header reception");
1993 "Main PHY is switching to a wrong link");
1996 "Main PHY switch back timer should have been stopped");
2007 mainPhy->GetState()->GetLastTime({WifiPhyState::SWITCHING}),
2009 "Main PHY is not switching at the end of PHY header reception");
2012 "Main PHY is switching to a wrong link");
2015 "Main PHY switch back timer should have been stopped");
2028 "Main PHY should be waiting to be connected to a link");
2031 "Main PHY is waiting to be connected to a wrong link");
2034 "Main PHY switch back timer should be running");
2044 ->NotifyAckTimeoutResetNow();
2051 mainPhy->GetState()->IsStateSwitching(),
2053 "Main PHY should not be switching at the end of PPDU reception");
2056 "Main PHY should have been connected to a link");
2059 "Main PHY should have been connected to a link");
2062 "Main PHY is connected to a wrong link");
2065 "Main PHY switch back timer should be running");
2077 "Main PHY should be waiting to be connected to a link");
2080 "Main PHY is waiting to be connected to a wrong link");
2083 "Main PHY switch back timer should be running");
2087 "Aux PHY should be in RX state");
2088 auto remTime = auxPhy->GetTimeToMacHdrEnd(
SU_STA_ID);
2091 "No MAC header info available");
2110 mainPhy->GetState()->IsStateSwitching(),
2112 "Main PHY should be switching after receiving the MAC header");
2115 "Main PHY should be switching to the preferred link");
2118 "Main PHY switch back timer should not be running");
2129 "Main PHY should be waiting to be connected to a link");
2132 "Main PHY is waiting to be connected to a wrong link");
2135 "Main PHY switch back timer should be running");
2150 mainPhy->GetState()->IsStateSwitching(),
2152 "Main PHY should be switching at the end of PPDU reception");
2155 "Main PHY should be switching back to preferred link");
2158 "Main PHY switch back timer should be not running");
2174 "Unicast frame transmitted on wrong link");
2176 m_apMac->GetFrameExchangeManager(linkId)->GetAddress(),
2177 "Unexpected RA for the unicast frame");
2179 m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress(),
2180 "Unexpected TA for the unicast frame");
2188 "Main PHY switch back timer should not be running");
2197 const auto txDuration =
2200 m_apMac->GetWifiPhy(linkId)->GetPhyBand());
2213 "Did not receive the expected trace infos");
2255 "{38, 40, BAND_5GHZ, 0}"s,
2256 "{3, 40, BAND_6GHZ, 0}"s};
2270 const auto psdu = psduMap.cbegin()->second;
2271 const auto& hdr = psdu->GetHeader(0);
2279 auto linkId = mac->GetLinkForPhy(phyId);
2282 "PHY " << +phyId <<
" is not operating on any link");
2293 m_events.front().func(psdu, txVector, linkId.value());
2323 const auto useAuxPhyCca = ((
m_testIndex & 0x1) == 1);
2329 const auto slot = auxPhy->GetSlot();
2330 const auto pifs = auxPhy->GetSifs() + slot;
2334 const auto switchDelay =
2336 ? timeToBackoffEnd + slot
2338 : timeToBackoffEnd - pifs - slot));
2341 mainPhy->SetAttribute(
"ChannelSwitchDelay",
TimeValue(switchDelay));
2361 "Expected a broadcast frame");
2364 "Broadcast frame transmitted on wrong link");
2366 m_apMac->GetFrameExchangeManager(linkId)->GetAddress(),
2367 "Unexpected TA for the broadcast frame");
2368 const auto txDuration =
2371 m_apMac->GetWifiPhy(linkId)->GetPhyBand());
2379 m_staMacs[0]->GetDevice()->GetNode()->AddApplication(
2386 const auto aifs = auxPhy->GetSifs() + emlsrBeEdca->GetAifsn(
m_linkIdForTid0) * slot;
2390 "Expected the main PHY to be switching");
2392 switchDelay - TimeStep(1),
2393 "Unexpected end of main PHY channel switch");
2420 ->GetBackoffEndFor(emlsrBeEdca);
2427 ->GetBackoffEndFor(emlsrBeEdca);
2431 NS_ABORT_MSG(
"Unexpected scenario " << +
static_cast<uint8_t
>(scenario));
2441 "Unicast frame transmitted on wrong link");
2443 m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress(),
2444 "Unexpected TA for the unicast frame");
2447 "Unexpected start TX time for unicast frame");
2450 "Unexpected channel width for the unicast frame");
2470 for (
bool switchAuxPhy : {
true,
false})
2472 for (
bool resetCamStateAndInterruptSwitch : {
true,
false})
2477 {switchAuxPhy, resetCamStateAndInterruptSwitch, auxPhyMaxChWidth}),
2478 TestCase::Duration::QUICK);
2490 for (
const auto switchAuxPhy : {
true,
false})
2492 for (
const auto auxPhyTxCapable : {
true,
false})
2495 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 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.
const Time MEDIUM_SYNC_THRESHOLD
The aMediumSyncThreshold defined by Sec. 35.3.16.18.1 of 802.11be D4.0.
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