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 )"),
 
 
   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);
 
 
  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(
 
 
  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};
 
 
  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 )"),
 
 
  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) + 
")"),
 
 
  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());
 
  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 =
 
 1152                interferenceHelper->GetEnergyDuration(
DbmToW(phy->GetCcaEdThreshold()),
 
 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(
 
 1688                                          "Expected the main PHY to be switching");
 
 1690                        +advEmlsrMgr->m_mainPhySwitchInfo.to,
 
 1692                        "Test index " << +
m_testIndex << 
": Main PHY is switching to wrong link");
 
 1699        info.
GetName() == 
"TxopNotGainedOnAuxPhyLink")
 
 1712                                  "Unexpected value for the elapsed field");
 
 1715                                  "earlySwitchReason should hold a value");
 
 1718                                  "Unexpected earlySwitchReason value");
 
 1726                                  "Unexpected value for the elapsed field");
 
 1729                                  "earlySwitchReason should hold a value");
 
 1732                                  "Unexpected earlySwitchReason value");
 
 1740                                  "Unexpected value for the elapsed field");
 
 1743                                  "earlySwitchReason should hold a value");
 
 1746                                  "Unexpected earlySwitchReason value");
 
 1754                                  "Unexpected value for the elapsed field");
 
 1757                                  "earlySwitchReason should hold a value");
 
 1760                                  "Unexpected earlySwitchReason value");
 
 1768                                  "Unexpected value for the elapsed field");
 
 1771                                  "earlySwitchReason should hold a value");
 
 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");
 
 2198            const auto txDuration =
 
 2201                                             m_apMac->GetWifiPhy(linkId)->GetPhyBand());
 
 2214                                          "Did not receive the expected trace infos");
 
 
 2256                     "{38, 40, BAND_5GHZ, 0}"s,
 
 2257                     "{3, 40, BAND_6GHZ, 0}"s};
 
 
 2271    const auto psdu = psduMap.cbegin()->second;
 
 2272    const auto& hdr = psdu->GetHeader(0);
 
 2280    auto linkId = mac->GetLinkForPhy(phyId);
 
 2283                          "PHY " << +phyId << 
" is not operating on any link");
 
 2294            m_events.front().func(psdu, txVector, linkId.value());
 
 
 2324    const auto useAuxPhyCca = ((
m_testIndex & 0x1) == 1);
 
 2330    const auto slot = auxPhy->GetSlot();
 
 2331    const auto pifs = auxPhy->GetSifs() + slot;
 
 2335    const auto switchDelay =
 
 2337             ? timeToBackoffEnd + slot
 
 2339                                                             : timeToBackoffEnd - pifs - slot));
 
 2342    mainPhy->SetAttribute(
"ChannelSwitchDelay", 
TimeValue(switchDelay));
 
 2362                                  "Expected a broadcast frame");
 
 2365                                  "Broadcast frame transmitted on wrong link");
 
 2367                                  m_apMac->GetFrameExchangeManager(linkId)->GetAddress(),
 
 2368                                  "Unexpected TA for the broadcast frame");
 
 2369            const auto txDuration =
 
 2372                                             m_apMac->GetWifiPhy(linkId)->GetPhyBand());
 
 2380                m_staMacs[0]->GetDevice()->GetNode()->AddApplication(
 
 2387            const auto aifs = auxPhy->GetSifs() + emlsrBeEdca->GetAifsn(
m_linkIdForTid0) * slot;
 
 2391                                      "Expected the main PHY to be switching");
 
 2394                                      "Unexpected end of main PHY channel switch");
 
 2421                                                ->GetBackoffEndFor(emlsrBeEdca);
 
 2428                                            ->GetBackoffEndFor(emlsrBeEdca);
 
 2432                    NS_ABORT_MSG(
"Unexpected scenario " << +
static_cast<uint8_t
>(scenario));
 
 2442                                  "Unicast frame transmitted on wrong link");
 
 2444                                  m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress(),
 
 2445                                  "Unexpected TA for the unicast frame");
 
 2448                                  "Unexpected start TX time for unicast frame");
 
 2451                                  "Unexpected channel width for the unicast frame");
 
 
 2471    for (
bool switchAuxPhy : {
true, 
false})
 
 2473        for (
bool resetCamStateAndInterruptSwitch : {
true, 
false})
 
 2478                                {switchAuxPhy, resetCamStateAndInterruptSwitch, auxPhyMaxChWidth}),
 
 2491    for (
const auto switchAuxPhy : {
true, 
false})
 
 2493        for (
const auto auxPhyTxCapable : {
true, 
false})
 
 
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...
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
EmlsrOperationsTestBase(const std::string &name)
Constructor.
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
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.
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.
@ UNIT
This test suite implements a Unit Test.
TestSuite(std::string name, Type type=Type::UNIT)
Construct a new test suite.
Simulation virtual time values and global simulation resolution.
Time TimeStep(uint64_t ts)
Scheduler interface.
AttributeValue implementation for Time.
Hold an unsigned integer type.
AttributeValue implementation for WifiMode.
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
WifiChannelConfig::SegmentWithoutUnits ChannelTuple
kept for backward compatibility, can be deprecated when using strong types
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.
@ WAITING_EMLSR_TRANSITION_DELAY
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...
double MHz_u
MHz weak type.
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.
const Time MEDIUM_SYNC_THRESHOLD
The aMediumSyncThreshold defined by Sec. 35.3.16.18.1 of 802.11be D4.0.
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