11#include "ns3/config.h" 
   12#include "ns3/eht-configuration.h" 
   13#include "ns3/ht-frame-exchange-manager.h" 
   15#include "ns3/mgt-action-headers.h" 
   16#include "ns3/mgt-headers.h" 
   17#include "ns3/mobility-helper.h" 
   18#include "ns3/multi-link-element.h" 
   19#include "ns3/node-list.h" 
   20#include "ns3/packet-socket-helper.h" 
   21#include "ns3/packet.h" 
   22#include "ns3/pointer.h" 
   23#include "ns3/rng-seed-manager.h" 
   24#include "ns3/rr-multi-user-scheduler.h" 
   25#include "ns3/spectrum-wifi-phy.h" 
   26#include "ns3/string.h" 
   27#include "ns3/vht-configuration.h" 
   28#include "ns3/wifi-acknowledgment.h" 
   29#include "ns3/wifi-assoc-manager.h" 
   30#include "ns3/wifi-mac-header.h" 
   31#include "ns3/wifi-mac-queue.h" 
   32#include "ns3/wifi-net-device.h" 
   33#include "ns3/wifi-protection.h" 
   46    : 
TestCase(
"Check the implementation of WifiAssocManager::GetNextAffiliatedAp()")
 
 
  120                          "Unexpected neighbor ID of the second reported AP");
 
  123                          "Unexpected tbtt ID of the second reported AP");
 
  129                          "Did not expect to find a third suitable reported AP");
 
  136    auto apIt = allAps.begin();
 
  139                          "Unexpected neighbor ID of the first reported AP");
 
  142                          "Unexpected tbtt ID of the first reported AP");
 
  147                          "Unexpected neighbor ID of the second reported AP");
 
  150                          "Unexpected tbtt ID of the second reported AP");
 
 
  158                            .SetGroupName(
"Wifi")
 
 
  164    : 
TestCase(
"Test the WifiMac::SwapLinks() method")
 
 
  171                         const std::map<uint8_t, uint8_t>& links,
 
  172                         const std::map<uint8_t, uint8_t>& expected)
 
  179    std::vector<Ptr<WifiPhy>> phys;
 
  180    std::vector<Ptr<FrameExchangeManager>> feManagers;
 
  181    std::vector<Ptr<WifiRemoteStationManager>> rsManagers;
 
  183    for (std::size_t i = 0; i < nLinks; ++i)
 
  187        phys.emplace_back(phy);
 
  191    mac->SetWifiPhys(phys); 
 
  192    mac->SetFrameExchangeManagers(feManagers);
 
  193    mac->SetWifiRemoteStationManagers(rsManagers);
 
  194    mac->GetTxop()->SetWifiMac(mac);
 
  197    for (std::size_t 
id = 0; 
id < nLinks; ++id)
 
  199        mac->GetTxop()->SetMinCw(
id, 
id);
 
  202    mac->SwapLinks(links);
 
  206    for (
const auto& [linkId, phyId] : expected)
 
  210                              "Link ID " << +linkId << 
" does not exist");
 
  217                              text << 
": Link " << +phyId << 
" has not been moved to link " 
  224            text << 
": Link ID stored by FrameExchangeManager has not been updated");
 
  230            text << 
": Link ID stored by RemoteStationManager has not been updated");
 
  234                              text << 
": Txop Link entity " << +phyId
 
  235                                   << 
" has not been moved to link " << +linkId);
 
 
  244    RunOne(
"No change needed", 3, {{0, 0}, {1, 1}, {2, 2}}, {{0, 0}, {1, 1}, {2, 2}});
 
  245    RunOne(
"Circular swapping", 3, {{0, 2}, {1, 0}, {2, 1}}, {{0, 1}, {1, 2}, {2, 0}});
 
  246    RunOne(
"Swapping two links, one unchanged", 3, {{0, 2}, {2, 0}}, {{0, 2}, {1, 1}, {2, 0}});
 
  247    RunOne(
"Non-circular swapping, autodetect how to close the loop",
 
  250           {{0, 1}, {1, 2}, {2, 0}});
 
  251    RunOne(
"A different non-circular swapping, same result",
 
  254           {{0, 1}, {1, 2}, {2, 0}});
 
  255    RunOne(
"One move only, autodetect how to complete the swapping",
 
  258           {{0, 2}, {1, 1}, {2, 0}});
 
  259    RunOne(
"Create a new link ID (2), remove the unused one (0)",
 
  263    RunOne(
"One move only that creates a new link ID (2)", 2, {{0, 2}}, {{1, 1}, {2, 0}});
 
  264    RunOne(
"Move all links to a new set of IDs", 2, {{0, 2}, {1, 3}}, {{2, 0}, {3, 1}});
 
 
  269    : 
TestCase(
"Test the assignment of AIDs"),
 
  270      m_linkChannels({
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{2, 0, BAND_2_4GHZ, 0}"}),
 
  272      m_assocType(assocType),
 
 
  282    int64_t streamNumber{1};
 
  285    wifiApNode.Create(1);
 
  290    wifi.SetRemoteStationManager(
"ns3::ConstantRateWifiManager",
 
  310    mac.SetType(
"ns3::ApWifiMac",
 
  316    auto apDevice = wifi.Install(phyHelper, mac, wifiApNode);
 
  325        for (
const auto& 
id : links)
 
  333        mac.SetType(
"ns3::StaWifiMac",
 
  342        auto staDevice = wifi.Install(phyHelper, mac, staNode);
 
  343        wifiStaNodes.Add(staNode);
 
  352    positionAlloc->Add(Vector(0.0, 0.0, 0.0));
 
  354    mobility.SetPositionAllocator(positionAlloc);
 
  355    mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
 
  356    mobility.Install(wifiApNode);
 
  357    mobility.Install(wifiStaNodes);
 
  362        mac->TraceConnectWithoutContext(
 
 
  374    const auto aid = staMac->GetAssociationId();
 
  377    std::stringstream linksStr;
 
  378    const auto setupLinks = staMac->GetSetupLinkIds();
 
  379    std::copy(setupLinks.cbegin(), setupLinks.cend(), std::ostream_iterator<int>(linksStr, 
" "));
 
  381    NS_LOG_INFO(
"STA " << staMac->GetAddress() << 
" associated with AID " << aid << 
" links " 
  388    const auto expectedLinks =
 
  394                          "Unexpected set of setup links " << linksStr.str());
 
 
  416                          "Not all STAs completed association");
 
  421        mac->TraceDisconnectWithoutContext(
 
 
  433      m_staChannels(baseParams.staChannels),
 
  434      m_apChannels(baseParams.apChannels),
 
  435      m_fixedPhyBands(baseParams.fixedPhyBands),
 
  436      m_assocType(baseParams.assocType),
 
  437      m_staMacs(nStations),
 
  438      m_nStations(nStations),
 
  441      m_rxPkts(nStations + 1)
 
 
  447                                            std::optional<Direction> direction)
 
  449    std::optional<Mac48Address> apAddr;
 
  450    std::optional<Mac48Address> staAddr;
 
  453    if (psdu->GetHeader(0).IsQosData())
 
  455        direction = (!psdu->GetHeader(0).IsToDs() && psdu->GetHeader(0).IsFromDs()) ? 
DL : 
UL;
 
  461        if (!psdu->GetAddr1().IsGroup())
 
  463            staAddr = psdu->GetAddr1();
 
  465        apAddr = psdu->GetAddr2();
 
  469        if (!psdu->GetAddr1().IsGroup())
 
  471            apAddr = psdu->GetAddr1();
 
  473        staAddr = psdu->GetAddr2();
 
  479        for (uint8_t linkId = 0; linkId < 
m_apMac->GetNLinks(); linkId++)
 
  481            if (
m_apMac->GetFrameExchangeManager(linkId)->GetAddress() == *apAddr)
 
  489                              "Address " << *apAddr << 
" is not an AP device address. " 
  490                                         << 
"PSDU: " << *psdu);
 
  498            for (
const auto& linkId : 
m_staMacs[i]->GetLinkIds())
 
  500                if (
m_staMacs[i]->GetFrameExchangeManager(linkId)->GetAddress() == *staAddr)
 
  513                              "Address " << *staAddr << 
" is not a STA device address. " 
  514                                         << 
"PSDU: " << *psdu);
 
 
  525    auto linkId = mac->GetLinkForPhy(phyId);
 
  529    for (
const auto& [aid, psdu] : psduMap)
 
  531        std::stringstream ss;
 
  532        ss << std::setprecision(10) << 
"PSDU #" << 
m_txPsdus.size() << 
" Link ID " 
  533           << +linkId.value() << 
" Phy ID " << +phyId << 
" #MPDUs " << psdu->GetNMpdus();
 
  534        for (
auto it = psdu->begin(); it != psdu->end(); ++it)
 
 
  548    auto band = mac->GetDevice()->GetPhy(phyId)->GetPhyBand();
 
  549    bool hasHtCapabilities;
 
  550    bool hasVhtCapabilities;
 
  551    bool hasHeCapabilities;
 
  552    bool hasHe6GhzCapabilities;
 
  553    bool hasEhtCapabilities;
 
  555    auto findCapabilities = [&](
auto&& frame) {
 
  556        hasHtCapabilities = frame.template Get<HtCapabilities>().has_value();
 
  557        hasVhtCapabilities = frame.template Get<VhtCapabilities>().has_value();
 
  558        hasHeCapabilities = frame.template Get<HeCapabilities>().has_value();
 
  559        hasHe6GhzCapabilities = frame.template Get<He6GhzBandCapabilities>().has_value();
 
  560        hasEhtCapabilities = frame.template Get<EhtCapabilities>().has_value();
 
  563    switch (mpdu->GetHeader().GetType())
 
  567        mpdu->GetPacket()->PeekHeader(beacon);
 
  568        findCapabilities(beacon);
 
  574        mpdu->GetPacket()->PeekHeader(probeReq);
 
  575        findCapabilities(probeReq);
 
  581        mpdu->GetPacket()->PeekHeader(probeResp);
 
  582        findCapabilities(probeResp);
 
  588        mpdu->GetPacket()->PeekHeader(assocReq);
 
  589        findCapabilities(assocReq);
 
  595        mpdu->GetPacket()->PeekHeader(assocResp);
 
  596        findCapabilities(assocResp);
 
  607        "HT Capabilities should not be present in a mgt frame sent in 6 GHz band");
 
  611        "VHT Capabilities should only be present in a mgt frame sent in 5 GHz band");
 
  614                          "HE Capabilities should always be present in a mgt frame");
 
  616        hasHe6GhzCapabilities,
 
  618        "HE 6GHz Band Capabilities should only be present in a mgt frame sent in 6 GHz band");
 
  621                          "EHT Capabilities should always be present in a mgt frame");
 
 
  627    NS_LOG_INFO(
"Packet received by NODE " << +nodeId << 
"\n");
 
 
  633                                         const std::vector<std::string>& channels,
 
  641    for (
const auto& str : channels)
 
  648    for (
const auto& [band, channel] : channelMap)
 
 
  659    int64_t streamNumber = 30;
 
  662    wifiApNode.Create(1);
 
  670    wifi.SetRemoteStationManager(
"ns3::ConstantRateWifiManager",
 
  691    mac.SetType(
"ns3::StaWifiMac", 
 
  701    mac.SetType(
"ns3::ApWifiMac",
 
  720    positionAlloc->Add(Vector(0.0, 0.0, 0.0));
 
  721    positionAlloc->Add(Vector(1.0, 0.0, 0.0));
 
  722    mobility.SetPositionAllocator(positionAlloc);
 
  724    mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
 
  725    mobility.Install(wifiApNode);
 
  726    mobility.Install(wifiStaNodes);
 
  736    for (uint8_t phyId = 0; phyId < 
m_apMac->GetDevice()->GetNPhys(); phyId++)
 
  739            "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phys/" + std::to_string(phyId) +
 
  745        for (uint8_t phyId = 0; phyId < 
m_staMacs[i]->GetDevice()->GetNPhys(); phyId++)
 
  748                                              "/DeviceList/*/$ns3::WifiNetDevice/Phys/" +
 
  749                                              std::to_string(phyId) + 
"/PhyTxPsduBegin",
 
  757    packetSocket.
Install(wifiApNode);
 
  758    packetSocket.
Install(wifiStaNodes);
 
  770        server->SetLocal(srvAddr);
 
  771        (*nodeIt)->AddApplication(server);
 
  772        server->SetStartTime(
Seconds(0)); 
 
  779            "/NodeList/" + std::to_string(nodeId) +
 
  780                "/ApplicationList/*/$ns3::PacketSocketServer/Rx",
 
  785    m_apMac->TraceConnectWithoutContext(
"AssociatedSta",
 
 
  797                                            uint8_t priority)
 const 
  804    client->SetRemote(sockAddr);
 
  805    client->SetStartTime(delay);
 
 
  836                                       const std::vector<uint8_t>& setupLinks,
 
  837                                       const std::vector<uint8_t>& staSetupLinks,
 
  839                                       const std::string& dlTidToLinkMapping,
 
  840                                       const std::string& ulTidToLinkMapping,
 
  841                                       bool support160MHzOp)
 
  843      m_setupLinks(setupLinks),
 
  844      m_staSetupLinks(staSetupLinks.empty() ? setupLinks : staSetupLinks),
 
  845      m_scanType(scanType),
 
  847      m_apNegSupport(apNegSupport),
 
  848      m_dlTidLinkMappingStr(dlTidToLinkMapping),
 
  849      m_ulTidLinkMappingStr(ulTidToLinkMapping),
 
  850      m_support160MHzOp(support160MHzOp)
 
  854                          "Number of setup links must be the same for AP and non-AP device");
 
 
  866    auto staEhtConfig = 
m_staMacs[0]->GetEhtConfiguration();
 
  867    staEhtConfig->m_tidLinkMappingSupport = WifiTidToLinkMappingNegSupport::ANY_LINK_SET;
 
  878    if (
m_apNegSupport == WifiTidToLinkMappingNegSupport::NOT_SUPPORTED ||
 
  879        (
m_apNegSupport == WifiTidToLinkMappingNegSupport::SAME_LINK_SET &&
 
  887    using TupleRefs = std::tuple<std::reference_wrapper<const WifiTidLinkMapping>,
 
  888                                 std::reference_wrapper<uint8_t>,
 
  889                                 std::reference_wrapper<std::optional<uint8_t>>,
 
  891    for (
auto& [mappingRef, tid1Ref, tid2Ref, mac] :
 
  896        for (uint8_t tid1 = 0; tid1 < 8; tid1++)
 
  898            if (
auto it1 = mappingRef.get().find(tid1);
 
  899                it1 != mappingRef.get().cend() && it1->second.size() != 
m_setupLinks.size())
 
  902                for (uint8_t tid2 = tid1 + 1; tid2 < 8; tid2++)
 
  904                    if (
auto it2 = mappingRef.get().find(tid2);
 
  905                        it2 != mappingRef.get().cend() && it2->second.size() != 
m_setupLinks.size())
 
  907                        std::list<uint8_t> intersection;
 
  908                        std::set_intersection(it1->second.cbegin(),
 
  910                                              it2->second.cbegin(),
 
  912                                              std::back_inserter(intersection));
 
  913                        if (intersection.empty())
 
  916                            tid2Ref.get() = tid2;
 
  921                tid1Ref.get() = tid1;
 
  926        std::list<uint8_t> tids = {tid1Ref.get()};
 
  929            tids.emplace_back(*tid2Ref.get());
 
  933        for (
auto tid : tids)
 
  935            std::string attrName;
 
  939                attrName = 
"VI_MaxAmpduSize";
 
  942                attrName = 
"VO_MaxAmpduSize";
 
  945                attrName = 
"BE_MaxAmpduSize";
 
  948                attrName = 
"BK_MaxAmpduSize";
 
  965            staMac->GetWifiPhy(linkId++)->SetAttribute(
"ChannelSettings", 
StringValue(str));
 
 
  980        m_apMac->GetDevice()->GetNode()->AddApplication(
 
  984            m_apMac->GetDevice()->GetNode()->AddApplication(
 
  996        m_staMacs[0]->GetDevice()->GetNode()->AddApplication(
 
 1000            m_staMacs[0]->GetDevice()->GetNode()->AddApplication(
 
 
 1017    std::size_t index = 0;
 
 1021        const auto& mpdu = *frameInfo.psduMap.begin()->second->begin();
 
 1022        const auto& linkId = frameInfo.linkId;
 
 1024        switch (mpdu->GetHeader().GetType())
 
 1056    std::size_t expectedProbeResp = 0;
 
 1065                if (staChannel == apChannel)
 
 1067                    expectedProbeResp++;
 
 1079        expectedRxDlPkts *= 2;
 
 1083                          "Unexpected number of DL packets received");
 
 1088        expectedRxUlPkts *= 2;
 
 1092                          "Unexpected number of UL packets received");
 
 
 1105                          mpdu->GetHeader().GetAddr2(),
 
 1106                          "TA of Beacon frame is not the address of the link it is transmitted on");
 
 1108    mpdu->GetPacket()->PeekHeader(beacon);
 
 1112    if (
m_apMac->GetNLinks() == 1)
 
 1116                              "RNR Element in Beacon frame from single link AP");
 
 1119                              "Multi-Link Element in Beacon frame from single link AP");
 
 1127                          static_cast<std::size_t
>(
m_apMac->GetNLinks() - 1),
 
 1128                          "Unexpected number of Neighbor AP Info fields in RNR");
 
 1129    for (std::size_t nbrApInfoId = 0; nbrApInfoId < rnr->GetNNbrApInfoFields(); nbrApInfoId++)
 
 1133                              "MLD Parameters not present");
 
 1136                              "Expected only one TBTT Info subfield per Neighbor AP Info");
 
 1137        uint8_t nbrLinkId = rnr->GetMldParameters(nbrApInfoId, 0).linkId;
 
 1139                              m_apMac->GetFrameExchangeManager(nbrLinkId)->GetAddress(),
 
 1140                              "BSSID advertised in Neighbor AP Info field " 
 1142                                  << 
" does not match the address configured on the link " 
 1143                                     "advertised in the same field");
 
 1149                          "Incorrect MLD address advertised in Multi-Link Element");
 
 1152                          "Incorrect Link ID advertised in Multi-Link Element");
 
 
 1163        m_apMac->GetFrameExchangeManager(linkId)->GetAddress(),
 
 1164        mpdu->GetHeader().GetAddr2(),
 
 1165        "TA of Probe Response is not the address of the link it is transmitted on");
 
 1167    mpdu->GetPacket()->PeekHeader(probeResp);
 
 1171    if (
m_apMac->GetNLinks() == 1)
 
 1175                              "RNR Element in Probe Response frame from single link AP");
 
 1178                              "Multi-Link Element in Probe Response frame from single link AP");
 
 1186                          static_cast<std::size_t
>(
m_apMac->GetNLinks() - 1),
 
 1187                          "Unexpected number of Neighbor AP Info fields in RNR");
 
 1188    for (std::size_t nbrApInfoId = 0; nbrApInfoId < rnr->GetNNbrApInfoFields(); nbrApInfoId++)
 
 1192                              "MLD Parameters not present");
 
 1195                              "Expected only one TBTT Info subfield per Neighbor AP Info");
 
 1196        uint8_t nbrLinkId = rnr->GetMldParameters(nbrApInfoId, 0).linkId;
 
 1198                              m_apMac->GetFrameExchangeManager(nbrLinkId)->GetAddress(),
 
 1199                              "BSSID advertised in Neighbor AP Info field " 
 1201                                  << 
" does not match the address configured on the link " 
 1202                                     "advertised in the same field");
 
 1208                          "Incorrect MLD address advertised in Multi-Link Element");
 
 1211                          "Incorrect Link ID advertised in Multi-Link Element");
 
 
 1222        m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress(),
 
 1223        mpdu->GetHeader().GetAddr2(),
 
 1224        "TA of Assoc Request frame is not the address of the link it is transmitted on");
 
 1226    mpdu->GetPacket()->PeekHeader(assoc);
 
 1229    if (
m_apMac->GetNLinks() == 1)
 
 1233                              "Multi-Link Element in Assoc Request frame to single link AP");
 
 1235    else if (
m_staMacs[0]->GetAssocType() == WifiAssocType::LEGACY)
 
 1240            "Multi-Link Element in Assoc Request frame from non-AP using legacy association");
 
 1246                              "No Multi-Link Element in Assoc Request frame");
 
 1249                              "Incorrect MLD Address advertised in Multi-Link Element");
 
 1251            mle->GetNPerStaProfileSubelements(),
 
 1253            "Incorrect number of Per-STA Profile subelements in Multi-Link Element");
 
 1254        for (std::size_t i = 0; i < mle->GetNPerStaProfileSubelements(); i++)
 
 1256            auto& perStaProfile = mle->GetPerStaProfile(i);
 
 1259                                  "Per-STA Profile must contain STA MAC address");
 
 1261            auto staLinkId = 
m_staMacs[0]->GetLinkIdByAddress(perStaProfile.GetStaMacAddress());
 
 1263                staLinkId.has_value(),
 
 1265                "No link found with the STA MAC address advertised in Per-STA Profile");
 
 1269                "The STA that sent the Assoc Request should not be included in a Per-STA Profile");
 
 1273                                  "Not expecting to setup STA link ID " << +staLinkId.value());
 
 1276                +perStaProfile.GetLinkId(),
 
 1277                "Not expecting to request association to AP Link ID in Per-STA Profile");
 
 1280                                  "Missing Association Request in Per-STA Profile");
 
 1289    if (
m_apMac->GetNLinks() == 1 || 
m_staMacs[0]->GetAssocType() == WifiAssocType::LEGACY ||
 
 1294                              "Didn't expect a TID-to-Link Mapping IE in Assoc Request frame");
 
 1302                              "Unexpected number of TID-to-Link Mapping IE in Assoc Request");
 
 1307                                  +
static_cast<uint8_t
>(
dir),
 
 1308                                  "Unexpected direction in TID-to-Link Mapping IE " << tlmId);
 
 1309            auto& expectedMapping =
 
 1313                                  expectedMapping.empty(),
 
 1314                                  "Default Link Mapping bit not set correctly");
 
 1316                                  expectedMapping.size(),
 
 1317                                  "Unexpected number of Link Mapping Of TID n fields");
 
 1318            for (uint8_t tid = 0; tid < 8; tid++)
 
 1320                if (
auto it = expectedMapping.find(tid); it != expectedMapping.cend())
 
 1324                                          "Unexpected link mapping for TID " 
 1325                                              << +tid << 
" direction " << 
dir);
 
 1331                                          "Expecting no Link Mapping Of TID n field for TID " 
 1332                                              << +tid << 
" direction " << 
dir);
 
 1337        if (tlm.size() == 1)
 
 1339            checkTlm(0, WifiDirection::BOTH_DIRECTIONS);
 
 1343            std::size_t dlId = (tlm[0].m_control.direction == WifiDirection::DOWNLINK ? 0 : 1);
 
 1344            std::size_t ulId = (dlId == 0 ? 1 : 0);
 
 1346            checkTlm(dlId, WifiDirection::DOWNLINK);
 
 1347            checkTlm(ulId, WifiDirection::UPLINK);
 
 
 1360        m_apMac->GetFrameExchangeManager(linkId)->GetAddress(),
 
 1361        mpdu->GetHeader().GetAddr2(),
 
 1362        "TA of Assoc Response frame is not the address of the link it is transmitted on");
 
 1364    mpdu->GetPacket()->PeekHeader(assoc);
 
 1367    if (
m_apMac->GetNLinks() == 1)
 
 1371                              "Multi-Link Element in Assoc Response frame with single link AP");
 
 1375    if (
m_staMacs[0]->GetAssocType() == WifiAssocType::LEGACY)
 
 1380            "Multi-Link Element in Assoc Response frame with non-AP using legacy association");
 
 1387                          "Incorrect MLD Address advertised in Multi-Link Element");
 
 1390                          "Incorrect number of Per-STA Profile subelements in Multi-Link Element");
 
 1391    for (std::size_t i = 0; i < mle->GetNPerStaProfileSubelements(); i++)
 
 1393        auto& perStaProfile = mle->GetPerStaProfile(i);
 
 1396                              "Per-STA Profile must contain STA MAC address");
 
 1398        auto apLinkId = 
m_apMac->GetLinkIdByAddress(perStaProfile.GetStaMacAddress());
 
 1400            apLinkId.has_value(),
 
 1402            "No link found with the STA MAC address advertised in Per-STA Profile");
 
 1404                              +perStaProfile.GetLinkId(),
 
 1405                              "Link ID and MAC address advertised in Per-STA Profile do not match");
 
 1409            "The AP that sent the Assoc Response should not be included in a Per-STA Profile");
 
 1413                              "Not expecting to setup AP link ID " << +apLinkId.value());
 
 1416                              "Missing Association Response in Per-STA Profile");
 
 1423                          "Didn't expect to find a TID-to-Link Mapping IE in Association Response");
 
 
 1436         ++linkIdIter, ++staLinkIdIter)
 
 1438        auto staLinkId = *staLinkIdIter;
 
 1439        auto apLinkId = *linkIdIter;
 
 1441        auto staAddr = 
m_staMacs[0]->GetFrameExchangeManager(staLinkId)->GetAddress();
 
 1442        auto apAddr = 
m_apMac->GetFrameExchangeManager(apLinkId)->GetAddress();
 
 1444        auto staRemoteMgr = 
m_staMacs[0]->GetWifiRemoteStationManager(staLinkId);
 
 1445        auto apRemoteMgr = 
m_apMac->GetWifiRemoteStationManager(apLinkId);
 
 1450                              "Unexpected BSSID for STA link ID " << +staLinkId);
 
 1455                                  "Incorrect MLD address stored by STA on link ID " << +staLinkId);
 
 1457                (staRemoteMgr->GetAffiliatedStaAddress(
m_apMac->GetAddress()) == apAddr),
 
 1459                "Incorrect affiliated address stored by STA on link ID " << +staLinkId);
 
 1465                              "Expecting STA " << staAddr << 
" to be associated on link " 
 1470                (apRemoteMgr->GetMldAddress(staAddr) == 
m_staMacs[0]->GetAddress()),
 
 1472                "Incorrect MLD address stored by AP on link ID " << +apLinkId);
 
 1474                (apRemoteMgr->GetAffiliatedStaAddress(
m_staMacs[0]->GetAddress()) == staAddr),
 
 1476                "Incorrect affiliated address stored by AP on link ID " << +apLinkId);
 
 1478        auto aid = 
m_apMac->GetAssociationId(staAddr, apLinkId);
 
 1479        const auto& staList = 
m_apMac->GetStaList(apLinkId);
 
 1482                              "STA " << staAddr << 
" not found in list of associated STAs");
 
 1486        const auto& staChannel = 
m_staMacs[0]->GetWifiPhy(staLinkId)->GetOperatingChannel();
 
 1487        const auto& apChannel = 
m_apMac->GetWifiPhy(apLinkId)->GetOperatingChannel();
 
 1489        auto width = apChannel.GetTotalWidth();
 
 1490        auto primary20 = apChannel.GetPrimaryChannelIndex(
MHz_u{20});
 
 1495            primary20 -= apChannel.GetPrimaryChannelIndex(
MHz_u{80}) * 4;
 
 1500                              "Incorrect operating channel number for STA on link " << +staLinkId);
 
 1502                              apChannel.GetPrimaryChannelCenterFrequency(width),
 
 1503                              "Incorrect operating channel frequency for STA on link " 
 1507                              "Incorrect operating channel width for STA on link " << +staLinkId);
 
 1509                              +apChannel.GetPhyBand(),
 
 1510                              "Incorrect operating PHY band for STA on link " << +staLinkId);
 
 1513                              "Incorrect operating primary channel index for STA on link " 
 1518    auto checkStoredMapping =
 
 1522                                  "Link mapping stored by " 
 1523                                      << (mac->GetTypeOfStation() == 
AP ? 
"AP" : 
"non-AP")
 
 1524                                      << 
" MLD for " << 
dir << 
" direction " 
 1525                                      << (present ? 
"expected" : 
"not expected"));
 
 1528                const auto& mapping =
 
 1531                    (mac->GetTidToLinkMapping(dest->GetAddress(), 
dir)->get() == mapping),
 
 1533                    "Incorrect link mapping stored by " 
 1534                        << (mac->GetTypeOfStation() == 
AP ? 
"AP" : 
"non-AP") << 
" MLD for " << 
dir 
 1539                for (uint8_t tid = 0; tid < 8; ++tid)
 
 1541                    const auto& linkSet = mapping.contains(tid) ? mapping.at(tid) : setupLinks;
 
 1543                    for (
const auto linkId : setupLinks)
 
 1546                            mac->TidMappedOnLink(dest->GetAddress(), 
dir, tid, linkId),
 
 1547                            linkSet.contains(linkId),
 
 1548                            "Incorrect return value on " << (mac == 
m_apMac ? 
"AP" : 
"STA")
 
 1549                                                         << 
" direction " << 
dir << 
" TID " << +tid
 
 1550                                                         << 
" linkID " << +linkId);
 
 1556    auto storedMapping = (
m_apMac->GetNLinks() > 1) &&
 
 1557                         (
m_staMacs[0]->GetAssocType() == WifiAssocType::ML_SETUP) &&
 
 1558                         (
m_apNegSupport > WifiTidToLinkMappingNegSupport::NOT_SUPPORTED);
 
 1559    checkStoredMapping(
m_apMac, 
m_staMacs[0], WifiDirection::DOWNLINK, storedMapping);
 
 1560    checkStoredMapping(
m_apMac, 
m_staMacs[0], WifiDirection::UPLINK, storedMapping);
 
 1561    checkStoredMapping(
m_staMacs[0], 
m_apMac, WifiDirection::DOWNLINK, storedMapping);
 
 1562    checkStoredMapping(
m_staMacs[0], 
m_apMac, WifiDirection::UPLINK, storedMapping);
 
 
 1568    const auto legacyAssoc = (
m_assocType == WifiAssocType::LEGACY || 
m_apMac->GetNLinks() == 1);
 
 1574                              "One link is expected to be setup with legacy association");
 
 1577    for (uint8_t linkId = 0; linkId < 
m_apMac->GetNLinks(); ++linkId)
 
 1587        auto mask = 
m_apMac->GetMacQueueScheduler()->GetQueueLinkMask(
AC_BE, queueId, linkId);
 
 1590                              "Unexpected presence/absence of mask on link " << +linkId);
 
 1593    for (
const auto& linkId : 
m_staMacs[0]->GetLinkIds())
 
 1601                                  "Link " << +linkId << 
" has not been setup but is not disabled");
 
 1608                              "Expecting link " << +linkId << 
" to be active");
 
 
 1619    const auto& hdr = mpdu->GetHeader();
 
 1628    if (!hdr.IsToDs() && hdr.IsFromDs())
 
 1630        dir = WifiDirection::DOWNLINK;
 
 1631        width = 
m_apMac->GetWifiPhy(linkId)->GetOperatingChannel().GetTotalWidth();
 
 1633    else if (hdr.IsToDs() && !hdr.IsFromDs())
 
 1635        dir = WifiDirection::UPLINK;
 
 1636        width = 
m_staMacs[0]->GetWifiPhy(linkId)->GetOperatingChannel().GetTotalWidth();
 
 1640        NS_ABORT_MSG(
"Invalid combination for QoS data frame: ToDS(" << hdr.IsToDs() << 
") FromDS(" 
 1641                                                                     << hdr.IsFromDs() << 
")");
 
 1652    uint8_t tid = hdr.GetQosTid();
 
 1655                          (tid2.has_value() && tid == *tid2),
 
 1656                          "QoS frame with unexpected TID " << +tid);
 
 1659    auto findLinkSet = [
this, 
dir](uint8_t tid) -> std::set<uint8_t> {
 
 1664            if (
auto it = mappingOptRef->get().find(tid); it != mappingOptRef->get().cend())
 
 1666                linkSet = it->second;
 
 1667                NS_ASSERT_MSG(!linkSet.empty(), 
"TID " << +tid << 
" mapped to no link");
 
 1673    auto linkSet = findLinkSet(tid);
 
 1680    std::size_t nConcurFrames = std::min(qosFrames.size(), linkSet.size());
 
 1683    for (std::size_t i = 0; i < nConcurFrames; i++)
 
 1685        auto prev = qosFrames[i];
 
 1695        if (qosFrames.size() < linkSet.size())
 
 1700                                  "The " << 
dir << 
" QoS frame number " << qosFrames.size()
 
 1701                                         << 
" was not sent concurrently with others on link " 
 1702                                         << +linkId << 
" which TID " << +tid << 
" is mapped to");
 
 1709                                  "The " << 
dir << 
" QoS frame number " << qosFrames.size()
 
 1710                                         << 
" was sent concurrently with others on a link " 
 1711                                         << +linkId << 
" which TID " << +tid << 
" is mapped to");
 
 1719                              "QoS frame sent on Link ID " 
 1720                                  << +linkId << 
" that does not belong to the link set of TID " 
 1727        auto otherTid = (tid == tid1) ? *tid2 : tid1;
 
 1729        auto otherLinkSet = findLinkSet(otherTid);
 
 1732        std::size_t nOtherConcurFrames = std::min(otherQosFrames.size(), otherLinkSet.size());
 
 1735        for (std::size_t i = 0; i < nOtherConcurFrames; i++)
 
 1737            auto prev = otherQosFrames[i];
 
 1747            if (qosFrames.size() < linkSet.size())
 
 1752                                      "The " << 
dir << 
" QoS frame number " << qosFrames.size()
 
 1753                                             << 
" was not sent concurrently with others with TID " 
 1760    qosFrames.emplace_back(index);
 
 
 1772                                 uint8_t nMaxInflight)
 
 1774          std::string(
"Check data transmission between MLDs ") +
 
 1777                          ? 
"with BA agreement, send BAR after BlockAck timeout" 
 1778                          : 
"with BA agreement, send Data frames after BlockAck timeout")
 
 1779                   : 
"without BA agreement") +
 
 1780              " (Traffic pattern: " + 
std::to_string(static_cast<uint8_t>(trafficPattern)) +
 
 1786      m_trafficPattern(trafficPattern),
 
 1789      m_nMaxInflight(nMaxInflight),
 
 
 1807    auto psdu = psduMap.begin()->second;
 
 1809    switch (psdu->GetHeader(0).GetType())
 
 1814                       psdu->GetHeader(0).GetAddr2() == psdu->GetHeader(0).GetAddr3() ? 
DL : 
UL);
 
 1819            m_uidList.push_front(psdu->GetPacket()->GetUid());
 
 1827        for (
const auto& mpdu : *psdu)
 
 1832                m_sourceMac->GetFrameExchangeManager(linkId)->GetAddress() ==
 
 1833                    mpdu->GetHeader().GetAddr2() &&
 
 1834                !mpdu->GetHeader().GetAddr1().IsGroup())
 
 1836                auto seqNo = mpdu->GetHeader().GetSequenceNumber();
 
 1837                auto [it, success] =
 
 1841                    it->second = std::max(it->second, mpdu->GetInFlightLinkIds().size());
 
 1845        for (std::size_t i = 0; i < psdu->GetNMpdus(); i++)
 
 1851            if (psdu->GetHeader(i).GetSequenceNumber() != 1 ||
 
 1858            auto uid = psdu->GetPayload(i)->GetUid();
 
 1881        if (!
m_sourceMac->GetLinkIdByAddress(psdu->GetHeader(0).GetAddr1()))
 
 1895            m_uidList.push_front(psdu->GetPacket()->GetUid());
 
 1902        if (
m_sourceMac->GetLinkIdByAddress(psdu->GetHeader(0).GetAddr2()))
 
 
 1920                          "No BlockAck expected in AP to broadcast traffic pattern");
 
 1934    auto mpdu = *psdu->begin();
 
 1936    mpdu->GetPacket()->PeekHeader(blockAck);
 
 1945                              "MPDU 0 expected to be successfully received");
 
 1949            "MPDU 1 expected to be received only in STA_TO_STA/STA_TO_BCAST scenarios");
 
 1952        if (
m_staMacs[0]->GetSetupLinkIds().size() > 1)
 
 1957            auto item = queue->PeekByTidAndAddress(0, rcvMac->GetAddress());
 
 1958            std::size_t nQueuedPkt = 0;
 
 1961                                                      rcvMac->GetWifiPhy(linkId)->GetPhyBand()) +
 
 1966                auto seqNo = item->GetHeader().GetSequenceNumber();
 
 1969                                      "MPDU with seqNo=" << seqNo << 
" is not in flight");
 
 1970                auto linkIds = item->GetInFlightLinkIds();
 
 1973                                      "MPDU with seqNo=" << seqNo
 
 1974                                                         << 
" is in flight on multiple links");
 
 1978                auto srcLinkId = 
m_sourceMac->GetLinkIdByAddress(mpdu->GetHeader().GetAddr1());
 
 1981                                      "Addr1 of BlockAck is not an originator's link address");
 
 1984                                      "MPDU with seqNo=" << seqNo
 
 1985                                                         << 
" in flight on unexpected link");
 
 1990                bool isQueued = (seqNo > (isMpdu1corrupted ? 0 : 1));
 
 1994                bool isRetry = isQueued && seqNo <= 1;
 
 2000                                              << item->GetHeader().GetSequenceNumber() << 
" should " 
 2001                                              << (isQueued ? 
"" : 
"not") << 
" be queued");
 
 2003                        item->GetHeader().IsRetry(),
 
 2005                        "Unexpected value for the Retry subfield of the MPDU with seqNo=" 
 2006                            << item->GetHeader().GetSequenceNumber());
 
 2010                item = queue->PeekByTidAndAddress(0, rcvMac->GetAddress(), item);
 
 2021                              "Did not expect to receive a second BlockAck");
 
 2023        std::pair<uint16_t, uint16_t> seqNos;
 
 2028        if (
m_staMacs[0]->GetSetupLinkIds().size() > 1)
 
 2038                              "MPDU " << seqNos.first << 
" expected to be successfully received");
 
 2041                              "MPDU " << seqNos.second << 
" expected to be successfully received");
 
 
 2057            mac->GetQosTxop(
AC_BE)->SetAttribute(
"UseExplicitBarAfterMissedBlockAck",
 
 2064    for (std::size_t linkId = 0; linkId < 
m_apMac->GetNLinks(); linkId++)
 
 2068        m_apMac->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel);
 
 2070    for (std::size_t i : {0, 1})
 
 2072        for (
const auto linkId : 
m_staMacs[i]->GetLinkIds())
 
 2076            m_staMacs[i]->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel);
 
 
 2090        destAddr = 
m_staMacs[1]->GetDevice()->GetAddress();
 
 2094        destAddr = 
m_apMac->GetDevice()->GetAddress();
 
 2098        destAddr = 
m_staMacs[1]->GetDevice()->GetAddress();
 
 2116    m_sourceMac->GetDevice()->GetNode()->AddApplication(
 
 2123        m_sourceMac->GetDevice()->GetNode()->AddApplication(
 
 
 2136    std::array<std::size_t, 3> expectedRxPkts{};
 
 2165                          "Unexpected number of packets received by the AP");
 
 2168                          "Unexpected number of packets received by STA 0");
 
 2171                          "Unexpected number of packets received by STA 1");
 
 2176        std::size_t expectedBaCount = 0;
 
 2177        std::size_t expectedBarCount = 0;
 
 2184            expectedBaCount = 3;
 
 2191            expectedBaCount = 1;
 
 2197                              "Unexpected number of BlockAck frames");
 
 2200                              "Unexpected number of BlockAckReq frames");
 
 2211            "Did not collect number of simultaneous transmissions for all data frames");
 
 2214        std::size_t maxCount = 0;
 
 2220                "MPDU with seqNo=" << seqNo
 
 2221                                   << 
" transmitted simultaneously more times than allowed");
 
 2222            maxCount = std::max(maxCount, count);
 
 2228            "Expected that at least one data frame was transmitted simultaneously a number of " 
 2229            "times equal to the NMaxInflights attribute");
 
 
 2238                                     uint8_t nMaxInflight)
 
 2240          std::string(
"Check MU data transmission between MLDs ") +
 
 2242                   ? 
"(send BAR after BlockAck timeout," 
 2243                   : 
"(send Data frames after BlockAck timeout,") +
 
 2244              " MU Traffic pattern: " + 
std::to_string(static_cast<uint8_t>(muTrafficPattern)) +
 
 2245              ", nMaxInflight=" + 
std::to_string(nMaxInflight) + 
")",
 
 2248      m_muTrafficPattern(muTrafficPattern),
 
 2250      m_nMaxInflight(nMaxInflight),
 
 2251      m_sockets(m_nStations),
 
 
 2268    for (
const auto& [staId, psdu] : psduMap)
 
 2270        switch (psdu->GetHeader(0).GetType())
 
 2274            if (psdu->GetHeader(0).HasData())
 
 2276                bool isDl = psdu->GetHeader(0).IsFromDs();
 
 2278                    isDl ? psdu->GetHeader(0).GetAddr1() : psdu->GetHeader(0).GetAddr2();
 
 2279                auto address = 
m_apMac->GetMldAddress(linkAddress).value_or(linkAddress);
 
 2281                for (
const auto& mpdu : *psdu)
 
 2284                    auto seqNo = mpdu->GetHeader().GetSequenceNumber();
 
 2286                        {{address, seqNo}, mpdu->GetInFlightLinkIds().size()});
 
 2289                        it->second = std::max(it->second, mpdu->GetInFlightLinkIds().size());
 
 2292                for (std::size_t i = 0; i < psdu->GetNMpdus(); i++)
 
 2295                    if (psdu->GetHeader(i).GetSequenceNumber() == 2)
 
 2301                                                  "MPDU " << **std::next(psdu->begin(), i)
 
 2302                                                          << 
" not transmitted in a TB PPDU");
 
 2308                                                  "MPDU " << **std::next(psdu->begin(), i)
 
 2309                                                          << 
" not transmitted in a DL MU PPDU");
 
 2313                    if (psdu->GetHeader(i).GetSequenceNumber() != 3)
 
 2317                    auto uid = psdu->GetPayload(i)->GetUid();
 
 2354                m_uidList.push_front(psdu->GetPacket()->GetUid());
 
 2360            psdu->GetPayload(0)->PeekHeader(trigger);
 
 2369                auto band = mac->GetWifiPhy(linkId)->GetPhyBand();
 
 2373                    m_staMacs[i]->GetDevice()->GetNode()->AddApplication(
 
 2382                muScheduler->SetAttribute(
"EnableUlOfdma", 
BooleanValue(
false));
 
 
 2429    auto mpdu = *psdu->begin();
 
 2431    mpdu->GetPacket()->PeekHeader(blockAck);
 
 2432    bool isMpdu3corrupted;
 
 2447                auto index = indices.front();
 
 2450                                      "Expected that a QoS data frame was corrupted");
 
 2452                    m_staMacs[i]->GetLinkIdByAddress(*m_dataCorruptedSta).has_value();
 
 2455                                      "MPDU 2 expected to be successfully received");
 
 2458                                      "Unexpected reception status for MPDU 3");
 
 2468                              "MPDU 2 expected to be successfully received");
 
 2471                              "Unexpected reception status for MPDU 3");
 
 2475            m_staMacs[0]->GetSetupLinkIds().size() > 1)
 
 2479            if (
m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress() ==
 
 2480                mpdu->GetHeader().GetAddr2())
 
 2484            else if (
m_staMacs[1]->GetFrameExchangeManager(linkId)->GetAddress() ==
 
 2485                     mpdu->GetHeader().GetAddr2())
 
 2491                NS_ABORT_MSG(
"BlockAck frame not sent by a station in DL scenario");
 
 2493            auto item = queue->PeekByTidAndAddress(0, rcvMac->GetAddress());
 
 2494            std::size_t nQueuedPkt = 0;
 
 2497                                                      rcvMac->GetWifiPhy(linkId)->GetPhyBand()) +
 
 2502                auto seqNo = item->GetHeader().GetSequenceNumber();
 
 2505                                      "MPDU with seqNo=" << seqNo << 
" is not in flight");
 
 2506                auto linkIds = item->GetInFlightLinkIds();
 
 2509                                      "MPDU with seqNo=" << seqNo
 
 2510                                                         << 
" is in flight on multiple links");
 
 2514                auto srcLinkId = 
m_apMac->GetLinkIdByAddress(mpdu->GetHeader().GetAddr1());
 
 2517                                      "Addr1 of BlockAck is not an originator's link address");
 
 2520                                      "MPDU with seqNo=" << seqNo
 
 2521                                                         << 
" in flight on unexpected link");
 
 2526                bool isQueued = (seqNo > (isMpdu3corrupted ? 2 : 3));
 
 2530                bool isRetry = isQueued && seqNo <= 3;
 
 2536                                              << item->GetHeader().GetSequenceNumber() << 
" should " 
 2537                                              << (isQueued ? 
"" : 
"not") << 
" be queued");
 
 2539                        item->GetHeader().IsRetry(),
 
 2541                        "Unexpected value for the Retry subfield of the MPDU with seqNo=" 
 2542                            << item->GetHeader().GetSequenceNumber());
 
 2546                item = queue->PeekByTidAndAddress(0, rcvMac->GetAddress(), item);
 
 
 2581        mac->GetQosTxop(
AC_BE)->SetAttribute(
"UseExplicitBarAfterMissedBlockAck",
 
 2586        mac->GetQosTxop(
AC_VI)->SetAttribute(
"UseExplicitBarAfterMissedBlockAck",
 
 2598    m_apMac->AggregateObject(muScheduler);
 
 2601    for (std::size_t linkId = 0; linkId < 
m_apMac->GetNLinks(); linkId++)
 
 2605        m_apMac->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel);
 
 2607    for (std::size_t i : {0, 1})
 
 2609        for (
const auto linkId : 
m_staMacs[i]->GetLinkIds())
 
 2613            m_staMacs[i]->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel);
 
 
 2633            m_apMac->GetDevice()->GetNode()->AddApplication(
 
 2639            m_apMac->GetDevice()->GetNode()->AddApplication(
 
 2645            m_apMac->GetDevice()->GetNode()->AddApplication(
 
 2663            m_staMacs[i]->GetDevice()->GetNode()->AddApplication(
 
 2674            muScheduler->SetAttribute(
"EnableUlOfdma", 
BooleanValue(
true));
 
 2677            muScheduler->SetAccessReqInterval(
Seconds(0));
 
 
 2690    std::array<std::size_t, 3> expectedRxPkts{};
 
 2709                          "Unexpected number of packets received by the AP");
 
 2712                          "Unexpected number of packets received by STA 0");
 
 2715                          "Unexpected number of packets received by STA 1");
 
 2723        "Did not collect number of simultaneous transmissions for all data frames");
 
 2726    std::size_t maxCount = 0;
 
 2732                                        << txSeqNoPair.second
 
 2733                                        << 
" transmitted simultaneously more times than allowed");
 
 2734        maxCount = std::max(maxCount, count);
 
 2740        "Expected that at least one data frame was transmitted simultaneously a number of " 
 2741        "times equal to the NMaxInflights attribute");
 
 
 2748          "Check sequence numbers after CTS timeout",
 
 2750          BaseParams{{
"{36, 0, BAND_5GHZ, 0}", 
"{2, 0, BAND_2_4GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}"},
 
 2751                     {
"{36, 0, BAND_5GHZ, 0}", 
"{2, 0, BAND_2_4GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}"},
 
 2753                     WifiAssocType::ML_SETUP}),
 
 2754      m_nQosDataFrames(0),
 
 2756      m_rtsCorrupted(
false)
 
 
 2769    for (
const auto linkId : 
m_staMacs[0]->GetLinkIds())
 
 
 2795    auto psdu = psduMap.begin()->second;
 
 2804    else if (psdu->GetHeader(0).IsQosData())
 
 
 2824    std::size_t count{};
 
 2828        auto psdu = txPsdu.psduMap.begin()->second;
 
 2830        if (!psdu->GetHeader(0).IsQosData())
 
 2838        uint16_t expectedSeqNo{};
 
 2857                                  "Unexpected sequence number");
 
 
 2866          "Check starting sequence number update after ADDBA Response timeout",
 
 2868          BaseParams{{
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}"},
 
 2869                     {
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}"},
 
 2871                     WifiAssocType::ML_SETUP}),
 
 
 2886    for (
const auto linkId : 
m_staMacs[0]->GetLinkIds())
 
 
 2910    auto psdu = psduMap.begin()->second;
 
 2911    const auto& hdr = psdu->GetHeader(0);
 
 2917        auto prevPsdu = 
m_txPsdus.back().psduMap.begin()->second;
 
 2919        if (prevPsdu->GetHeader(0).IsAction())
 
 2922            (*prevPsdu->begin())->GetPacket()->PeekHeader(actionHdr);
 
 2932                m_staMacs[0]->BlockUnicastTxOnLinks(WifiQueueBlockedReason::TID_NOT_MAPPED,
 
 2945                    ackDuration + 
m_apMac->GetQosTxop(
AC_BE)->GetAddBaResponseTimeout(),
 
 2947                        m_apMac->BlockUnicastTxOnLinks(WifiQueueBlockedReason::TID_NOT_MAPPED,
 
 2948                                                       m_staMacs[0]->GetAddress(),
 
 2951                            WifiQueueBlockedReason::TID_NOT_MAPPED,
 
 2964        (*psdu->begin())->GetPacket()->PeekHeader(actionHdr);
 
 2968            auto band = m_staMacs[0]->GetDevice()->GetPhy(phyId)->GetPhyBand();
 
 2974                auto mpdu = m_apMac->GetTxopQueue(
AC_BE)->Peek();
 
 2978                                      "Expected a QoS data frame");
 
 2982                    "Expected the data frame to be inflight when ADDBA RESP is received");
 
 2987                    m_apMac->GetQosTxop(
AC_BE)->GetBaStartingSequence(m_staMacs[0]->GetAddress(),
 
 2989                    mpdu->GetHeader().GetSequenceNumber(),
 
 2990                    "Unexpected BA Starting Sequence Number");
 
 2994    else if (hdr.IsQosData())
 
 2997        if (m_nQosDataCount++ == 0)
 
 2999            m_staErrorModel->SetList({psdu->GetPacket()->GetUid()});
 
 3003            m_staErrorModel->SetList({});
 
 
 3024                                             {
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}"},
 
 
 3043    for (
const auto linkId : 
m_staMacs[0]->GetLinkIds())
 
 3048    for (
const auto linkId : 
m_apMac->GetLinkIds())
 
 
 3063    const auto psdu = psduMap.cbegin()->second;
 
 3064    const auto& hdr = psdu->GetHeader(0);
 
 3072    auto linkId = mac->GetLinkForPhy(phyId);
 
 3075                          "PHY " << +phyId << 
" is not operating on any link");
 
 3081                              std::string(hdr.GetTypeString()),
 
 3086            m_events.front().func(psdu, txVector, linkId.value());
 
 
 3113        std::list<uint64_t> uids;
 
 3116            uids.push_back(mpdu->GetPacket()->GetUid());
 
 3131                                  m_apMac->GetFrameExchangeManager(linkId)->GetAddress(),
 
 3132                                  "Unexpected TA for the data frame sent by the AP");
 
 3144                                  m_apMac->GetFrameExchangeManager(linkId)->GetAddress(),
 
 3145                                  "Unexpected TA for the BlockAckReq sent by the AP");
 
 3148                                  "Unexpected RA for the BlockAckReq sent by the AP");
 
 3156                                  "Unexpected TA for the BlockAck sent by the non-AP STA");
 
 3159                                  "Unexpected RA for the BlockAck sent by the non-AP STA");
 
 3169                m_staMacs[0]->GetDevice()->GetNode()->AddApplication(
 
 3184                                  m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress(),
 
 3185                                  "Unexpected TA for the data frame sent by the non-AP STA");
 
 3198                                  "Unexpected TA for the BlockAckReq sent by the non-AP STA");
 
 3201                                  "Unexpected RA for the BlockAckReq sent by the non-AP STA");
 
 3208                                  m_apMac->GetFrameExchangeManager(linkId)->GetAddress(),
 
 3209                                  "Unexpected TA for the BlockAck sent by the AP");
 
 3212                                  "Unexpected RA for the BlockAck sent by the AP");
 
 
 3232                   std::vector<uint8_t>, 
 
 3233                   std::vector<uint8_t>, 
 
 3242            std::vector<std::set<uint8_t>>{{0, 1, 2}, {1, 2}, {0, 1}, {0, 2}, {0}, {1}, {2}},
 
 3243            WifiAssocType::ML_SETUP),
 
 3244        TestCase::Duration::QUICK);
 
 3247            std::vector<std::set<uint8_t>>{{0, 1, 2}, {1, 2}, {0, 1}, {0, 2}, {0}, {1}, {2}},
 
 3248            WifiAssocType::LEGACY),
 
 3249        TestCase::Duration::QUICK);
 
 3256                {
"{42, 80, BAND_5GHZ, 2}", 
"{5, 40, BAND_2_4GHZ, 0}", 
"{7, 80, BAND_6GHZ, 0}"},
 
 3257                {
"{3, 40, BAND_2_4GHZ, 0}", 
"{15, 160, BAND_6GHZ, 7}", 
"{50, 160, BAND_5GHZ, 2}"},
 
 3259                WifiAssocType::ML_SETUP},
 
 3260            WifiScanType::PASSIVE,
 
 3263            WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
 
 3267        TestCase::Duration::QUICK);
 
 3269    for (
const auto& [baseParams,
 
 3277              {{
"{36, 0, BAND_5GHZ, 0}", 
"{2, 0, BAND_2_4GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}"},
 
 3278               {
"{36, 0, BAND_5GHZ, 0}", 
"{2, 0, BAND_2_4GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}"},
 
 3280               WifiAssocType::ML_SETUP},
 
 3283              WifiTidToLinkMappingNegSupport::NOT_SUPPORTED, 
 
 3285              "0,1,2,3  0,1,2;  4,5  0,1",                   
 
 3286              "0,1,2,3  1,2;    6,7  0,1"                     
 3289          ParamsTuple({{
"{108, 0, BAND_5GHZ, 0}", 
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}"},
 
 3290                       {
"{36, 0, BAND_5GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}", 
"{5, 0, BAND_6GHZ, 0}"},
 
 3292                       WifiAssocType::ML_SETUP},
 
 3295                      WifiTidToLinkMappingNegSupport::SAME_LINK_SET, 
 
 3297                      "0,1,2,3  0,1,2;  4,5  0,1",                   
 
 3300          ParamsTuple({{
"{2, 0, BAND_2_4GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{36, 0, BAND_5GHZ, 0}"},
 
 3301                       {
"{36, 0, BAND_5GHZ, 0}", 
"{9, 0, BAND_6GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3303                       WifiAssocType::ML_SETUP},
 
 3306                      WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
 
 3307                      "0,1,2,3  0;  4,5,6,7  1,2", 
 
 3308                      "0,2,3  1,2;  1,4,5,6,7  0"   
 3313              {{
"{2, 0, BAND_2_4GHZ, 0}", 
"{36, 0, BAND_5GHZ, 0}", 
"{8, 20, BAND_2_4GHZ, 0}"},
 
 3314               {
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3316               WifiAssocType::ML_SETUP},
 
 3319              WifiTidToLinkMappingNegSupport::SAME_LINK_SET, 
 
 3321              "0,1,2,3,4,5,6,7  0",
 
 3322              "0,1,2,3,4,5,6,7  0"),
 
 3327              {{
"{2, 0, BAND_2_4GHZ, 0}", 
"{36, 0, BAND_5GHZ, 0}", 
"{8, 20, BAND_2_4GHZ, 0}"},
 
 3328               {
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3330               WifiAssocType::ML_SETUP},
 
 3333              WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
 
 3341          ParamsTuple({{
"{2, 0, BAND_2_4GHZ, 0}", 
"{36, 0, BAND_5GHZ, 0}", 
"{60, 0, BAND_5GHZ, 0}"},
 
 3342                       {
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3344                       WifiAssocType::ML_SETUP},
 
 3347                      WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
 
 3353          ParamsTuple({{
"{2, 0, BAND_2_4GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3354                       {
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3356                       WifiAssocType::ML_SETUP},
 
 3359                      WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
 
 3363          ParamsTuple({{
"{2, 0, BAND_2_4GHZ, 0}", 
"{36, 0, BAND_5GHZ, 0}"},
 
 3364                       {
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3366                       WifiAssocType::ML_SETUP},
 
 3369                      WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
 
 3373          ParamsTuple({{
"{2, 0, BAND_2_4GHZ, 0}", 
"{36, 0, BAND_5GHZ, 0}", 
"{60, 0, BAND_5GHZ, 0}"},
 
 3374                       {
"{120, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{36, 0, BAND_5GHZ, 0}"},
 
 3376                       WifiAssocType::LEGACY},
 
 3379                      WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
 
 3383          ParamsTuple({{
"{120, 0, BAND_5GHZ, 0}"},
 
 3384                       {
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3386                       WifiAssocType::LEGACY},
 
 3389                      WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
 
 3393          ParamsTuple({{
"{120, 0, BAND_5GHZ, 0}"},
 
 3394                       {
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3396                       WifiAssocType::ML_SETUP},
 
 3399                      WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
 
 3403          ParamsTuple({{
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3404                       {
"{120, 0, BAND_5GHZ, 0}"},
 
 3406                       WifiAssocType::LEGACY},
 
 3409                      WifiTidToLinkMappingNegSupport::NOT_SUPPORTED,
 
 3410                      "0,1,2,3  0,1;  4,5,6,7  0,1", 
 
 3413          ParamsTuple({{
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3414                       {
"{120, 0, BAND_5GHZ, 0}"},
 
 3416                       WifiAssocType::ML_SETUP},
 
 3419                      WifiTidToLinkMappingNegSupport::NOT_SUPPORTED,
 
 3420                      "0,1,2,3  0,1;  4,5,6,7  0,1", 
 
 3424                                           WifiScanType::PASSIVE,
 
 3430                    TestCase::Duration::QUICK);
 
 3432                                           WifiScanType::ACTIVE,
 
 3438                    TestCase::Duration::QUICK);
 
 3452                        TestCase::Duration::QUICK);
 
 3453            for (
const auto& useBarAfterMissedBa :
 
 3460                                                useBarAfterMissedBa,
 
 3462                            TestCase::Duration::QUICK);
 
 3467                                                useBarAfterMissedBa,
 
 3469                            TestCase::Duration::QUICK);
 
 3478            for (
const auto& useBarAfterMissedBa :
 
 3484                    TestCase::Duration::QUICK);
 
 3488                    TestCase::Duration::QUICK);
 
 
Test that the AIDs that an AP MLD assigns to SLDs and MLDs are all unique.
WifiAssocType m_assocType
association type
AidAssignmentTest(const std::vector< std::set< uint8_t > > &linkIds, WifiAssocType assocType)
Constructor.
const std::vector< std::set< uint8_t > > m_linkIds
link IDs for all non-AP STAs/MLDs
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void SetSsid(Ptr< StaWifiMac > staMac, Mac48Address)
Set the SSID on the next station that needs to start the association procedure.
uint16_t m_startAid
first AID to allocate to stations
void DoRun() override
Implementation to actually run this TestCase.
uint16_t m_expectedAid
expected AID for current non-AP STA/MLD
const std::vector< std::string > m_linkChannels
channels for all AP links
NetDeviceContainer m_staDevices
non-AP STAs/MLDs devices
Test BlockAckReq frame sent by a Block Ack originator after dropping QoS data frames.
Ptr< ListErrorModel > m_apErrorModel
error rate model to corrupt frames at the AP MLD
void InsertEvents()
Insert elements in the list of expected events (transmitted frames)
void DoSetup() override
Implementation to do any local setup required for this TestCase.
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.
std::list< Events > m_events
list of events for a test run
bool m_setupDone
whether association has been completed
void StartTraffic() override
Start the generation of traffic (needs to be overridden)
std::size_t m_processedEvents
number of processed events
Ptr< ListErrorModel > m_staErrorModel
error rate model to corrupt frames at the non-AP STA
BarAfterDroppedMpduTest(WifiAssocType assocType)
Constructor.
Test the implementation of WifiAssocManager::GetNextAffiliatedAp(), which searches a given RNR elemen...
GetRnrLinkInfoTest()
Constructor.
void DoRun() override
Implementation to actually run this TestCase.
Test WifiMac subclass used to access the SwapLinks method.
static TypeId GetTypeId()
Test the WifiMac::SwapLinks() method.
void DoRun() override
Implementation to actually run this TestCase.
void RunOne(std::string text, std::size_t nLinks, const std::map< uint8_t, uint8_t > &links, const std::map< uint8_t, uint8_t > &expected)
Run a single test case.
Test data transmission between MLDs using OFDMA MU transmissions.
std::optional< Mac48Address > m_dataCorruptedSta
MAC address of the station that received MPDU with SeqNo=2 corrupted.
void CheckBlockAck(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector, uint8_t linkId)
Check the content of a received BlockAck frame when the max number of links on which an MPDU can be i...
std::vector< PacketSocketAddress > m_sockets
packet socket addresses for STAs
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.
std::size_t m_nPackets
number of application packets to generate
void DoRun() override
Implementation to actually run this TestCase.
MultiLinkMuTxTest(const BaseParams &baseParams, WifiMuTrafficPattern muTrafficPattern, WifiUseBarAfterMissedBa useBarAfterMissedBa, uint8_t nMaxInflight)
Constructor.
std::list< uint64_t > m_uidList
list of UIDs of packets to corrupt
std::size_t m_blockAckCount
transmitted BlockAck counter
void DoSetup() override
Implementation to do any local setup required for this TestCase.
RxErrorModelMap m_errorModels
error rate models to corrupt packets
std::map< AddrSeqNoPair, std::size_t > m_inflightCount
max number of simultaneous transmissions of each data frame
void StartTraffic() override
Start the generation of traffic (needs to be overridden)
bool m_useBarAfterMissedBa
whether to send BAR after missed BlockAck
bool m_waitFirstTf
whether we are waiting for the first Basic Trigger Frame
WifiMuTrafficPattern m_muTrafficPattern
the pattern of traffic to generate
std::size_t m_tfCount
transmitted Trigger Frame counter
std::size_t m_nMaxInflight
max number of links on which an MPDU can be inflight
Base class for Multi-Link Operations tests.
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.
void SetSsid(uint16_t aid, Mac48Address)
Set the SSID on the next station that needs to start the association procedure.
virtual void StartTraffic()
Start the generation of traffic (needs to be overridden)
std::vector< Ptr< StaWifiMac > > m_staMacs
STA wifi MACs.
const std::vector< std::string > m_staChannels
strings specifying channels for STA
void CheckAddresses(Ptr< const WifiPsdu > psdu, std::optional< Direction > direction=std::nullopt)
Check that the Address 1 and Address 2 fields of the given PSDU contain device MAC addresses.
virtual void L7Receive(uint8_t nodeId, Ptr< const Packet > p, const Address &addr)
Function to trace packets received by the server application.
uint16_t m_startAid
first AID to allocate to stations
Ptr< PacketSocketClient > GetApplication(const PacketSocketAddress &sockAddr, std::size_t count, std::size_t pktSize, Time delay=Seconds(0), uint8_t priority=0) const
void CheckCapabilities(Ptr< WifiMpdu > mpdu, Ptr< WifiMac > mac, uint8_t phyId)
Check that the expected Capabilities information elements are present in the given management frame b...
void SetChannels(SpectrumWifiPhyHelper &helper, const std::vector< std::string > &channels, const ChannelMap &channelMap)
Reset the given PHY helper, use the given strings to set the ChannelSettings attribute of the PHY obj...
const std::vector< std::string > m_apChannels
strings specifying channels for AP
WifiAssocType m_assocType
type of the association procedure used by non-AP devices
uint16_t m_lastAid
AID of last associated station.
std::map< FrequencyRange, Ptr< MultiModelSpectrumChannel > > ChannelMap
PHY band-indexed map of spectrum channels.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
std::vector< std::size_t > m_rxPkts
number of packets received at application layer by each node (index is node ID)
uint8_t m_nStations
number of stations to create
Time m_duration
simulation duration
const std::vector< uint8_t > m_fixedPhyBands
links on non-AP MLD with fixed PHY band
std::vector< FrameInfo > m_txPsdus
transmitted PSDUs
Ptr< ApWifiMac > m_apMac
AP wifi MAC.
MultiLinkOperationsTestBase(const std::string &name, uint8_t nStations, const BaseParams &baseParams)
Constructor.
Multi-Link Discovery & Setup test.
const std::vector< uint8_t > m_staSetupLinks
IDs (as seen by the non-AP device) of the expected links to setup.
uint8_t m_dlTid1
the TID of the first set of DL QoS data frames
void CheckAssocRequest(Ptr< WifiMpdu > mpdu, uint8_t linkId)
Check correctness of the given Association Request frame.
void CheckProbeResponse(Ptr< WifiMpdu > mpdu, uint8_t linkId)
Check correctness of the given Probe Response frame.
std::optional< uint8_t > m_ulTid2
the TID of the optional set of UL QoS data frames
WifiScanType m_scanType
the scan type (active or passive)
void CheckMlSetup()
Check correctness of Multi-Link Setup procedure.
std::vector< std::size_t > m_qosFrames1
indices of QoS frames of the first set in the vector of TX PSDUs
void CheckDisabledLinks()
Check that links that are not setup on the non-AP MLD are disabled.
std::size_t m_nProbeResp
number of Probe Responses received by the non-AP MLD
std::string m_dlTidLinkMappingStr
DL TID-to-Link Mapping for non-AP MLD EHT configuration.
bool m_support160MHzOp
whether non-AP MLDs support 160 MHz operations
uint8_t m_ulTid1
the TID of the first set of UL QoS data frames
WifiTidLinkMapping m_ulTidLinkMapping
expected UL TID-to-Link Mapping requested by non-AP MLD and accepted by AP MLD
void StartTraffic() override
Start the generation of traffic (needs to be overridden)
void DoRun() override
Implementation to actually run this TestCase.
WifiTidToLinkMappingNegSupport m_apNegSupport
TID-to-Link Mapping negotiation supported by the AP MLD.
std::optional< uint8_t > m_dlTid2
the TID of the optional set of DL QoS data frames
WifiTidLinkMapping m_dlTidLinkMapping
expected DL TID-to-Link Mapping requested by non-AP MLD and accepted by AP MLD
void CheckAssocResponse(Ptr< WifiMpdu > mpdu, uint8_t linkId)
Check correctness of the given Association Response frame.
void CheckQosData(Ptr< WifiMpdu > mpdu, const WifiTxVector &txvector, uint8_t linkId, std::size_t index)
Check that QoS data frames are sent on links their TID is mapped to and with the correct TX width.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
std::string m_ulTidLinkMappingStr
UL TID-to-Link Mapping for non-AP MLD EHT configuration.
MultiLinkSetupTest(const BaseParams &baseParams, WifiScanType scanType, const std::vector< uint8_t > &setupLinks, const std::vector< uint8_t > &staSetupLinks, WifiTidToLinkMappingNegSupport apNegSupport, const std::string &dlTidToLinkMapping, const std::string &ulTidToLinkMapping, bool support160MHzOp=true)
Constructor.
void CheckBeacon(Ptr< WifiMpdu > mpdu, uint8_t linkId)
Check correctness of the given Beacon frame.
std::vector< std::size_t > m_qosFrames2
indices of QoS frames of the optional set in the vector of TX PSDUs
const std::vector< uint8_t > m_setupLinks
IDs (as seen by the AP device) of the expected links to setup.
Test data transmission between two MLDs.
bool m_dataCorrupted
whether second data frame has been already corrupted
RxErrorModelMap m_errorModels
error rate models to corrupt packets
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.
std::list< uint64_t > m_uidList
list of UIDs of packets to corrupt
void DoRun() override
Implementation to actually run this TestCase.
std::size_t m_nPackets
number of application packets to generate
std::size_t m_nMaxInflight
max number of links on which an MPDU can be inflight
bool m_baEnabled
whether BA agreement is enabled or disabled
void StartTraffic() override
Start the generation of traffic (needs to be overridden)
bool m_useBarAfterMissedBa
whether to send BAR after missed BlockAck
std::size_t m_blockAckCount
transmitted BlockAck counter
WifiTrafficPattern m_trafficPattern
the pattern of traffic to generate
std::size_t m_blockAckReqCount
transmitted BlockAckReq counter
std::map< uint16_t, std::size_t > m_inflightCount
seqNo-indexed max number of simultaneous transmissions of a data frame
void DoSetup() override
Implementation to do any local setup required for this TestCase.
Ptr< WifiMac > m_sourceMac
MAC of the node sending application packets.
MultiLinkTxTest(const BaseParams &baseParams, WifiTrafficPattern trafficPattern, WifiBaEnabled baEnabled, WifiUseBarAfterMissedBa useBarAfterMissedBa, uint8_t nMaxInflight)
Constructor.
void CheckBlockAck(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector, uint8_t linkId)
Check the content of a received BlockAck frame when the max number of links on which an MPDU can be i...
Test release of sequence numbers upon CTS timeout in multi-link operations.
ReleaseSeqNoAfterCtsTimeoutTest()
PacketSocketAddress m_sockAddr
packet socket address
Ptr< ListErrorModel > m_errorModel
error rate model to corrupt first RTS frame
std::size_t m_nQosDataFrames
counter for transmitted QoS data frames
void StartTraffic() override
Start the generation of traffic (needs to be overridden)
bool m_rtsCorrupted
whether the first RTS frame has been corrupted
void DoSetup() override
Implementation to do any local setup required for 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.
void DoRun() override
Implementation to actually run this TestCase.
Test update of BA starting sequence number after ADDBA Response timeout in multi-link operations.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
PacketSocketAddress m_sockAddr
packet socket address
std::size_t m_nQosDataCount
counter for transmitted QoS data frames
void StartTraffic() override
Start the generation of traffic (needs to be overridden)
StartSeqNoUpdateAfterAddBaTimeoutTest()
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.
Ptr< ListErrorModel > m_staErrorModel
error rate model to corrupt frames at the non-AP MLD
WifiMultiLinkOperationsTestSuite()
a polymophic address class
AttributeValue implementation for Boolean.
Hold variables of type enum.
void SetList(const std::list< uint64_t > &packetlist)
static Mac48Address GetBroadcast()
Helper class used to assign positions and mobility models to nodes.
MultiUserScheduler is an abstract base class defining the API that APs supporting at least VHT can us...
holds a vector of ns3::NetDevice pointers
uint32_t GetN() const
Get the number of Ptr<NetDevice> stored in this container.
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
static uint32_t GetNNodes()
an address for a packet socket
void SetProtocol(uint16_t protocol)
Set the protocol.
void SetPhysicalAddress(const Address address)
Set the destination address.
void SetSingleDevice(uint32_t device)
Set the address to match only a specified NetDevice.
Give ns3::PacketSocket powers to ns3::Node.
void Install(Ptr< Node > node) const
Aggregate an instance of a ns3::PacketSocketFactory onto the provided node.
AttributeValue implementation for Pointer.
Smart pointer class similar to boost::intrusive_ptr.
The Reduced Neighbor Report element.
std::size_t GetNNbrApInfoFields() const
Get the number of Neighbor AP Information fields.
std::size_t GetNTbttInformationFields(std::size_t nbrApInfoId) const
Get the number of TBTT Information fields included in the TBTT Information Set field of the given Nei...
void AddNbrApInfoField()
Add a Neighbor AP Information field.
void SetMldParameters(std::size_t nbrApInfoId, std::size_t index, const MldParameters &mldParams)
Set the MLD Parameters subfield of the i-th TBTT Information field of the given Neighbor AP Informati...
void AddTbttInformationField(std::size_t nbrApInfoId)
Add a TBTT Information fields to the TBTT Information Set field of the given Neighbor AP Information ...
static void SetRun(uint64_t run)
Set the run number of simulation.
static void SetSeed(uint32_t seed)
Set the seed.
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 void Stop()
Tell the Simulator the calling event should be the last one executed.
Make it easy to create and manage PHY objects for the spectrum model.
void AddChannel(const Ptr< SpectrumChannel > channel, const FrequencyRange &freqRange=WHOLE_WIFI_SPECTRUM)
void SetChannel(const Ptr< SpectrumChannel > channel)
The IEEE 802.11 SSID Information Element.
AttributeValue implementation for Ssid.
Hold variables of type string.
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
TID-to-Link Mapping Information Element.
Simulation virtual time values and global simulation resolution.
AttributeValue implementation for Time.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Hold an unsigned integer type.
static std::optional< WifiAssocManager::RnrLinkInfo > GetNextAffiliatedAp(const ReducedNeighborReport &rnr, std::size_t nbrApInfoId)
Search the given RNR element for APs affiliated to the same AP MLD as the reporting AP.
static std::list< WifiAssocManager::RnrLinkInfo > GetAllAffiliatedAps(const ReducedNeighborReport &rnr)
Find all the APs affiliated to the same AP MLD as the reporting AP that sent the given RNR element.
helps to create WifiNetDevice objects
static int64_t AssignStreams(NetDeviceContainer c, int64_t stream)
Assign a fixed random variable stream number to the random variables used by the PHY and MAC aspects ...
create MAC layers for a ns3::WifiNetDevice.
base class for all MAC-level wifi objects.
void SetPcapCaptureType(PcapCaptureType type)
Set the PCAP capture type to be used.
void SetPcapDataLinkType(SupportedPcapDataLinkTypes dlt)
Set the data link type of PCAP traces to be used.
void Set(std::string name, const AttributeValue &v)
@ DLT_IEEE802_11_RADIO
Include Radiotap link layer information.
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
const HeMuUserInfoMap & GetHeMuUserInfoMap() const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
MHz_u GetChannelWidth() const
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#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)
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#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 > CreateObjectWithAttributes(Args... args)
Allocate an Object on the heap and initialize with a set of attributes.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
#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.
Time MicroSeconds(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.
WifiScanType
Scan type (active or passive)
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Maps TID (Traffic ID) to Access classes.
WifiAssocType
Type of association performed by this device (provided that it is supported by the standard configure...
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
constexpr FrequencyRange WIFI_SPECTRUM_6_GHZ
Identifier for the frequency range covering the wifi spectrum in the 6 GHz band.
U * PeekPointer(const Ptr< U > &p)
std:: tuple< WifiContainerQueueType, WifiReceiverAddressType, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, receiver address type, Address, TID) identifying a container queue.
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...
WifiTidToLinkMappingNegSupport
TID-to-Link Mapping Negotiation Support.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
static constexpr uint8_t SINGLE_LINK_OP_ID
Link ID for single link operations (helps tracking places where correct link ID is to be used to supp...
constexpr FrequencyRange WIFI_SPECTRUM_5_GHZ
Identifier for the frequency range covering the wifi spectrum in the 5 GHz band.
@ WIFI_MAC_MGT_PROBE_REQUEST
@ WIFI_MAC_MGT_ASSOCIATION_RESPONSE
@ WIFI_MAC_MGT_ASSOCIATION_REQUEST
@ WIFI_MAC_MGT_PROBE_RESPONSE
WifiDirection
Wifi direction.
bool TidToLinkMappingValidForNegType1(const WifiTidLinkMapping &dlLinkMapping, const WifiTidLinkMapping &ulLinkMapping)
Check if the given TID-to-Link Mappings are valid for a negotiation type of 1.
Ptr< T1 > StaticCast(const Ptr< T2 > &p)
Cast a Ptr.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
constexpr FrequencyRange WIFI_SPECTRUM_2_4_GHZ
Identifier for the frequency range covering the wifi spectrum in the 2.4 GHz band.
Configuration parameters common to all subclasses.
uint32_t pktSize
packet size used for the simulation (in bytes)
static WifiMultiLinkOperationsTestSuite g_wifiMultiLinkOperationsTestSuite
the test suite
WifiMuTrafficPattern
Tested MU traffic patterns.
WifiTrafficPattern
Tested traffic patterns.
WifiUseBarAfterMissedBa
Whether to send a BlockAckReq after a missed BlockAck.
WifiBaEnabled
Block Ack agreement enabled/disabled.