20#include "ns3/ap-wifi-mac.h" 
   21#include "ns3/config.h" 
   22#include "ns3/eht-configuration.h" 
   23#include "ns3/frame-exchange-manager.h" 
   25#include "ns3/mgt-headers.h" 
   26#include "ns3/mobility-helper.h" 
   27#include "ns3/multi-link-element.h" 
   28#include "ns3/multi-model-spectrum-channel.h" 
   29#include "ns3/node-list.h" 
   30#include "ns3/packet-socket-client.h" 
   31#include "ns3/packet-socket-helper.h" 
   32#include "ns3/packet-socket-server.h" 
   33#include "ns3/packet.h" 
   34#include "ns3/pointer.h" 
   35#include "ns3/qos-utils.h" 
   36#include "ns3/rng-seed-manager.h" 
   37#include "ns3/rr-multi-user-scheduler.h" 
   38#include "ns3/spectrum-wifi-helper.h" 
   39#include "ns3/spectrum-wifi-phy.h" 
   40#include "ns3/sta-wifi-mac.h" 
   41#include "ns3/string.h" 
   43#include "ns3/wifi-acknowledgment.h" 
   44#include "ns3/wifi-assoc-manager.h" 
   45#include "ns3/wifi-mac-header.h" 
   46#include "ns3/wifi-mac-queue.h" 
   47#include "ns3/wifi-net-device.h" 
   48#include "ns3/wifi-protection.h" 
   49#include "ns3/wifi-psdu.h" 
   81    void DoRun() 
override;
 
   85    : 
TestCase(
"Check the implementation of WifiAssocManager::GetNextAffiliatedAp()")
 
  159                          "Unexpected neighbor ID of the second reported AP");
 
  162                          "Unexpected tbtt ID of the second reported AP");
 
  168                          "Did not expect to find a third suitable reported AP");
 
  175    auto apIt = allAps.begin();
 
  178                          "Unexpected neighbor ID of the first reported AP");
 
  181                          "Unexpected tbtt ID of the first reported AP");
 
  186                          "Unexpected neighbor ID of the second reported AP");
 
  189                          "Unexpected tbtt ID of the second reported AP");
 
  226    void DoRun() 
override;
 
  239    void RunOne(std::string text,
 
  241                const std::map<uint8_t, uint8_t>& links,
 
  242                const std::map<uint8_t, uint8_t>& expected);
 
  246    : 
TestCase(
"Test the WifiMac::SwapLinks() method")
 
  253                         const std::map<uint8_t, uint8_t>& links,
 
  254                         const std::map<uint8_t, uint8_t>& expected)
 
  258    std::vector<Ptr<WifiPhy>> phys;
 
  259    for (std::size_t i = 0; i < nLinks; i++)
 
  261        phys.emplace_back(CreateObject<SpectrumWifiPhy>());
 
  263    mac.SetWifiPhys(phys); 
 
  265    mac.SwapLinks(links);
 
  269    for (
const auto& [linkId, phyId] : expected)
 
  273                              "Link ID " << +linkId << 
" does not exist");
 
  280                              text << 
": Link " << +phyId << 
" has not been moved to link " 
  288    RunOne(
"No change needed", 3, {{0, 0}, {1, 1}, {2, 2}}, {{0, 0}, {1, 1}, {2, 2}});
 
  289    RunOne(
"Circular swapping", 3, {{0, 2}, {1, 0}, {2, 1}}, {{0, 1}, {1, 2}, {2, 0}});
 
  290    RunOne(
"Swapping two links, one unchanged", 3, {{0, 2}, {2, 0}}, {{0, 2}, {1, 1}, {2, 0}});
 
  291    RunOne(
"Non-circular swapping, autodetect how to close the loop",
 
  294           {{0, 1}, {1, 2}, {2, 0}});
 
  295    RunOne(
"One move only, autodetect how to complete the swapping",
 
  298           {{0, 2}, {1, 1}, {2, 0}});
 
  299    RunOne(
"Create a new link ID (2), remove the unused one (0)",
 
  303    RunOne(
"One move only that creates a new link ID (2)", 2, {{0, 2}}, {{1, 1}, {2, 0}});
 
  304    RunOne(
"Move all links to a new set of IDs", 2, {{0, 2}, {1, 3}}, {{2, 0}, {3, 1}});
 
  325        std::vector<std::string>
 
  327        std::vector<std::string>
 
  383                                           uint8_t priority = 0) 
const;
 
  388    using ChannelMap = std::map<FrequencyRange, Ptr<MultiModelSpectrumChannel>>;
 
  406                        std::optional<Direction> direction = std::nullopt);
 
  441                     const std::vector<std::string>& channels,
 
  465      m_staChannels(baseParams.staChannels),
 
  466      m_apChannels(baseParams.apChannels),
 
  467      m_fixedPhyBands(baseParams.fixedPhyBands),
 
  468      m_staMacs(nStations),
 
  469      m_nStations(nStations),
 
  471      m_rxPkts(nStations + 1)
 
  477                                            std::optional<Direction> direction)
 
  479    std::optional<Mac48Address> apAddr;
 
  480    std::optional<Mac48Address> staAddr;
 
  483    if (psdu->GetHeader(0).IsQosData())
 
  485        direction = (!psdu->GetHeader(0).IsToDs() && psdu->GetHeader(0).IsFromDs()) ? 
DL : 
UL;
 
  491        if (!psdu->GetAddr1().IsGroup())
 
  493            staAddr = psdu->GetAddr1();
 
  495        apAddr = psdu->GetAddr2();
 
  499        if (!psdu->GetAddr1().IsGroup())
 
  501            apAddr = psdu->GetAddr1();
 
  503        staAddr = psdu->GetAddr2();
 
  519                              "Address " << *apAddr << 
" is not an AP device address. " 
  520                                         << 
"PSDU: " << *psdu);
 
  528            for (
const auto& linkId : 
m_staMacs[i]->GetLinkIds())
 
  530                if (
m_staMacs[i]->GetFrameExchangeManager(linkId)->GetAddress() == *staAddr)
 
  543                              "Address " << *staAddr << 
" is not a STA device address. " 
  544                                         << 
"PSDU: " << *psdu);
 
  555    auto linkId = mac->GetLinkForPhy(phyId);
 
  559    for (
const auto& [aid, psdu] : psduMap)
 
  561        std::stringstream ss;
 
  562        ss << std::setprecision(10) << 
"PSDU #" << 
m_txPsdus.size() << 
" Link ID " 
  563           << +linkId.value() << 
" Phy ID " << +phyId << 
" " << psdu->GetHeader(0).GetTypeString()
 
  564           << 
" #MPDUs " << psdu->GetNMpdus() << 
" duration/ID " << psdu->GetHeader(0).GetDuration()
 
  565           << 
" RA = " << psdu->GetAddr1() << 
" TA = " << psdu->GetAddr2()
 
  566           << 
" ADDR3 = " << psdu->GetHeader(0).GetAddr3()
 
  567           << 
" ToDS = " << psdu->GetHeader(0).IsToDs()
 
  568           << 
" FromDS = " << psdu->GetHeader(0).IsFromDs();
 
  569        if (psdu->GetHeader(0).IsQosData())
 
  574                ss << mpdu->GetHeader().GetSequenceNumber() << 
",";
 
  576            ss << 
"} TID = " << +psdu->GetHeader(0).GetQosTid();
 
  586    NS_LOG_INFO(
"Packet received by NODE " << +nodeId << 
"\n");
 
  592                                         const std::vector<std::string>& channels,
 
  599    for (
const auto& str : channels)
 
  606    for (
const auto& [band, channel] : channelMap)
 
  617    int64_t streamNumber = 30;
 
  620    wifiApNode.Create(1);
 
  628    wifi.SetRemoteStationManager(
"ns3::ConstantRateWifiManager",
 
  649    mac.SetType(
"ns3::StaWifiMac", 
 
  655    mac.SetType(
"ns3::ApWifiMac",
 
  668    streamNumber += wifi.AssignStreams(apDevices, streamNumber);
 
  669    streamNumber += wifi.AssignStreams(staDevices, streamNumber);
 
  674    positionAlloc->Add(Vector(0.0, 0.0, 0.0));
 
  675    positionAlloc->Add(Vector(1.0, 0.0, 0.0));
 
  676    mobility.SetPositionAllocator(positionAlloc);
 
  678    mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
 
  679    mobility.Install(wifiApNode);
 
  680    mobility.Install(wifiStaNodes);
 
  682    m_apMac = DynamicCast<ApWifiMac>(DynamicCast<WifiNetDevice>(apDevices.Get(0))->GetMac());
 
  686            DynamicCast<StaWifiMac>(DynamicCast<WifiNetDevice>(staDevices.Get(i))->GetMac());
 
  693            "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phys/" + std::to_string(phyId) +
 
  699        for (uint8_t phyId = 0; phyId < 
m_staMacs[i]->GetDevice()->GetNPhys(); phyId++)
 
  702                                              "/DeviceList/*/$ns3::WifiNetDevice/Phys/" +
 
  703                                              std::to_string(phyId) + 
"/PhyTxPsduBegin",
 
  711    packetSocket.
Install(wifiApNode);
 
  712    packetSocket.
Install(wifiStaNodes);
 
  718        auto device = DynamicCast<WifiNetDevice>((*nodeIt)->GetDevice(0));
 
  723        auto server = CreateObject<PacketSocketServer>();
 
  724        server->SetLocal(srvAddr);
 
  725        (*nodeIt)->AddApplication(server);
 
  726        server->SetStartTime(
Seconds(0)); 
 
  733            "/NodeList/" + std::to_string(nodeId) +
 
  734                "/ApplicationList/*/$ns3::PacketSocketServer/Rx",
 
  749                                            uint8_t priority)
 const 
  751    auto client = CreateObject<PacketSocketClient>();
 
  756    client->SetRemote(sockAddr);
 
  757    client->SetStartTime(delay);
 
  829                       const std::vector<uint8_t>& setupLinks,
 
  830                       uint8_t apNegSupport,
 
  831                       const std::string& dlTidToLinkMapping,
 
  832                       const std::string& ulTidToLinkMapping);
 
  837    void DoRun() 
override;
 
  907    std::vector<std::size_t>
 
  909    std::vector<std::size_t>
 
  915                                       const std::vector<uint8_t>& setupLinks,
 
  916                                       uint8_t apNegSupport,
 
  917                                       const std::string& dlTidToLinkMapping,
 
  918                                       const std::string& ulTidToLinkMapping)
 
  920      m_setupLinks(setupLinks),
 
  921      m_scanType(scanType),
 
  923      m_apNegSupport(apNegSupport),
 
  924      m_dlTidLinkMappingStr(dlTidToLinkMapping),
 
  925      m_ulTidLinkMappingStr(ulTidToLinkMapping)
 
  939    auto staEhtConfig = 
m_staMacs[0]->GetEhtConfiguration();
 
  940    staEhtConfig->SetAttribute(
"TidToLinkMappingNegSupport", 
EnumValue(3));
 
  960    using TupleRefs = std::tuple<std::reference_wrapper<const WifiTidLinkMapping>,
 
  961                                 std::reference_wrapper<uint8_t>,
 
  962                                 std::reference_wrapper<std::optional<uint8_t>>,
 
  964    for (
auto& [mappingRef, tid1Ref, tid2Ref, mac] :
 
  969        for (uint8_t tid1 = 0; tid1 < 8; tid1++)
 
  971            if (
auto it1 = mappingRef.get().find(tid1);
 
  972                it1 != mappingRef.get().cend() && it1->second.size() != 
m_setupLinks.size())
 
  975                for (uint8_t tid2 = tid1 + 1; tid2 < 8; tid2++)
 
  977                    if (
auto it2 = mappingRef.get().find(tid2);
 
  978                        it2 != mappingRef.get().cend() && it2->second.size() != 
m_setupLinks.size())
 
  980                        std::list<uint8_t> intersection;
 
  981                        std::set_intersection(it1->second.cbegin(),
 
  983                                              it2->second.cbegin(),
 
  985                                              std::back_inserter(intersection));
 
  986                        if (intersection.empty())
 
  989                            tid2Ref.get() = tid2;
 
  994                tid1Ref.get() = tid1;
 
  999        std::list<uint8_t> tids = {tid1Ref.get()};
 
 1002            tids.emplace_back(*tid2Ref.get());
 
 1006        for (
auto tid : tids)
 
 1008            std::string attrName;
 
 1012                attrName = 
"VI_MaxAmpduSize";
 
 1015                attrName = 
"VO_MaxAmpduSize";
 
 1018                attrName = 
"BE_MaxAmpduSize";
 
 1021                attrName = 
"BK_MaxAmpduSize";
 
 1058        m_staMacs[0]->GetDevice()->GetNode()->AddApplication(
 
 1062            m_staMacs[0]->GetDevice()->GetNode()->AddApplication(
 
 1079    std::size_t index = 0;
 
 1083        const auto& mpdu = *frameInfo.psduMap.begin()->second->begin();
 
 1084        const auto& linkId = frameInfo.linkId;
 
 1086        switch (mpdu->GetHeader().GetType())
 
 1118    std::size_t expectedProbeResp = 0;
 
 1127                if (staChannel == apChannel)
 
 1129                    expectedProbeResp++;
 
 1141        expectedRxDlPkts *= 2;
 
 1145                          "Unexpected number of DL packets received");
 
 1150        expectedRxUlPkts *= 2;
 
 1154                          "Unexpected number of UL packets received");
 
 1167                          mpdu->GetHeader().GetAddr2(),
 
 1168                          "TA of Beacon frame is not the address of the link it is transmitted on");
 
 1170    mpdu->GetPacket()->PeekHeader(beacon);
 
 1178                              "RNR Element in Beacon frame from single link AP");
 
 1181                              "Multi-Link Element in Beacon frame from single link AP");
 
 1190                          "Unexpected number of Neighbor AP Info fields in RNR");
 
 1191    for (std::size_t nbrApInfoId = 0; nbrApInfoId < rnr->GetNNbrApInfoFields(); nbrApInfoId++)
 
 1195                              "MLD Parameters not present");
 
 1198                              "Expected only one TBTT Info subfield per Neighbor AP Info");
 
 1199        uint8_t nbrLinkId = rnr->GetLinkId(nbrApInfoId, 0);
 
 1202                              "BSSID advertised in Neighbor AP Info field " 
 1204                                  << 
" does not match the address configured on the link " 
 1205                                     "advertised in the same field");
 
 1211                          "Incorrect MLD address advertised in Multi-Link Element");
 
 1214                          "Incorrect Link ID advertised in Multi-Link Element");
 
 1226        mpdu->GetHeader().GetAddr2(),
 
 1227        "TA of Probe Response is not the address of the link it is transmitted on");
 
 1229    mpdu->GetPacket()->PeekHeader(probeResp);
 
 1237                              "RNR Element in Probe Response frame from single link AP");
 
 1240                              "Multi-Link Element in Probe Response frame from single link AP");
 
 1249                          "Unexpected number of Neighbor AP Info fields in RNR");
 
 1250    for (std::size_t nbrApInfoId = 0; nbrApInfoId < rnr->GetNNbrApInfoFields(); nbrApInfoId++)
 
 1254                              "MLD Parameters not present");
 
 1257                              "Expected only one TBTT Info subfield per Neighbor AP Info");
 
 1258        uint8_t nbrLinkId = rnr->GetLinkId(nbrApInfoId, 0);
 
 1261                              "BSSID advertised in Neighbor AP Info field " 
 1263                                  << 
" does not match the address configured on the link " 
 1264                                     "advertised in the same field");
 
 1270                          "Incorrect MLD address advertised in Multi-Link Element");
 
 1273                          "Incorrect Link ID advertised in Multi-Link Element");
 
 1284        m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress(),
 
 1285        mpdu->GetHeader().GetAddr2(),
 
 1286        "TA of Assoc Request frame is not the address of the link it is transmitted on");
 
 1288    mpdu->GetPacket()->PeekHeader(assoc);
 
 1295                              "Multi-Link Element in Assoc Request frame from single link STA");
 
 1301                              "No Multi-Link Element in Assoc Request frame");
 
 1304                              "Incorrect MLD Address advertised in Multi-Link Element");
 
 1306            mle->GetNPerStaProfileSubelements(),
 
 1308            "Incorrect number of Per-STA Profile subelements in Multi-Link Element");
 
 1309        for (std::size_t i = 0; i < mle->GetNPerStaProfileSubelements(); i++)
 
 1311            auto& perStaProfile = mle->GetPerStaProfile(i);
 
 1314                                  "Per-STA Profile must contain STA MAC address");
 
 1316            auto staLinkId = 
m_staMacs[0]->GetLinkIdByAddress(perStaProfile.GetStaMacAddress());
 
 1318                staLinkId.has_value(),
 
 1320                "No link found with the STA MAC address advertised in Per-STA Profile");
 
 1324                "The STA that sent the Assoc Request should not be included in a Per-STA Profile");
 
 1328                                  "Not expecting to setup STA link ID " << +staLinkId.value());
 
 1331                +perStaProfile.GetLinkId(),
 
 1332                "Not expecting to request association to AP Link ID in Per-STA Profile");
 
 1335                                  "Missing Association Request in Per-STA Profile");
 
 1348                              "Didn't expect a TID-to-Link Mapping IE in Assoc Request frame");
 
 1356                              "Unexpected number of TID-to-Link Mapping IE in Assoc Request");
 
 1361                                  +
static_cast<uint8_t
>(
dir),
 
 1362                                  "Unexpected direction in TID-to-Link Mapping IE " << tlmId);
 
 1363            auto& expectedMapping =
 
 1367                                  expectedMapping.empty(),
 
 1368                                  "Default Link Mapping bit not set correctly");
 
 1370                                  expectedMapping.size(),
 
 1371                                  "Unexpected number of Link Mapping Of TID n fields");
 
 1372            for (uint8_t tid = 0; tid < 8; tid++)
 
 1374                if (
auto it = expectedMapping.find(tid); it != expectedMapping.cend())
 
 1378                                          "Unexpected link mapping for TID " 
 1379                                              << +tid << 
" direction " << 
dir);
 
 1385                                          "Expecting no Link Mapping Of TID n field for TID " 
 1386                                              << +tid << 
" direction " << 
dir);
 
 1391        if (tlm.size() == 1)
 
 1393            checkTlm(0, WifiDirection::BOTH_DIRECTIONS);
 
 1397            std::size_t dlId = (tlm[0].m_control.direction == WifiDirection::DOWNLINK ? 0 : 1);
 
 1398            std::size_t ulId = (dlId == 0 ? 1 : 0);
 
 1400            checkTlm(dlId, WifiDirection::DOWNLINK);
 
 1401            checkTlm(ulId, WifiDirection::UPLINK);
 
 1415        mpdu->GetHeader().GetAddr2(),
 
 1416        "TA of Assoc Response frame is not the address of the link it is transmitted on");
 
 1418    mpdu->GetPacket()->PeekHeader(assoc);
 
 1426            "Multi-Link Element in Assoc Response frame with single link AP or single link STA");
 
 1433                          "Incorrect MLD Address advertised in Multi-Link Element");
 
 1436                          "Incorrect number of Per-STA Profile subelements in Multi-Link Element");
 
 1437    for (std::size_t i = 0; i < mle->GetNPerStaProfileSubelements(); i++)
 
 1439        auto& perStaProfile = mle->GetPerStaProfile(i);
 
 1442                              "Per-STA Profile must contain STA MAC address");
 
 1446            apLinkId.has_value(),
 
 1448            "No link found with the STA MAC address advertised in Per-STA Profile");
 
 1450                              +perStaProfile.GetLinkId(),
 
 1451                              "Link ID and MAC address advertised in Per-STA Profile do not match");
 
 1455            "The AP that sent the Assoc Response should not be included in a Per-STA Profile");
 
 1459                              "Not expecting to setup AP link ID " << +apLinkId.value());
 
 1462                              "Missing Association Response in Per-STA Profile");
 
 1469                          "Didn't expect to find a TID-to-Link Mapping IE in Association Response");
 
 1485        auto staAddr = 
m_staMacs[0]->GetFrameExchangeManager(staLinkId)->GetAddress();
 
 1488        auto staRemoteMgr = 
m_staMacs[0]->GetWifiRemoteStationManager(staLinkId);
 
 1494                              "Unexpected BSSID for STA link ID " << +staLinkId);
 
 1499                                  "Incorrect MLD address stored by STA on link ID " << +staLinkId);
 
 1503                "Incorrect affiliated address stored by STA on link ID " << +staLinkId);
 
 1509                              "Expecting STA " << staAddr << 
" to be associated on link " 
 1514                (apRemoteMgr->GetMldAddress(staAddr) == 
m_staMacs[0]->GetAddress()),
 
 1516                "Incorrect MLD address stored by AP on link ID " << +apLinkId);
 
 1518                (apRemoteMgr->GetAffiliatedStaAddress(
m_staMacs[0]->GetAddress()) == staAddr),
 
 1520                "Incorrect affiliated address stored by AP on link ID " << +apLinkId);
 
 1526                              "STA " << staAddr << 
" not found in list of associated STAs");
 
 1530            +
m_staMacs[0]->GetWifiPhy(staLinkId)->GetOperatingChannel().GetNumber(),
 
 1532            "Incorrect operating channel number for STA on link " << +staLinkId);
 
 1534            m_staMacs[0]->GetWifiPhy(staLinkId)->GetOperatingChannel().GetFrequency(),
 
 1536            "Incorrect operating channel frequency for STA on link " << +staLinkId);
 
 1539                              "Incorrect operating channel width for STA on link " << +staLinkId);
 
 1541            +
m_staMacs[0]->GetWifiPhy(staLinkId)->GetOperatingChannel().GetPhyBand(),
 
 1543            "Incorrect operating PHY band for STA on link " << +staLinkId);
 
 1545            +
m_staMacs[0]->GetWifiPhy(staLinkId)->GetOperatingChannel().GetPrimaryChannelIndex(20),
 
 1547            "Incorrect operating primary channel index for STA on link " << +staLinkId);
 
 1551    auto checkStoredMapping =
 
 1555                                  "Link mapping stored by " 
 1556                                      << (mac->GetTypeOfStation() == 
AP ? 
"AP" : 
"non-AP")
 
 1557                                      << 
" MLD for " << 
dir << 
" direction " 
 1558                                      << (present ? 
"expected" : 
"not expected"));
 
 1561                const auto& mapping =
 
 1564                    (mac->GetTidToLinkMapping(dest->GetAddress(), 
dir)->get() == mapping),
 
 1566                    "Incorrect link mapping stored by " 
 1567                        << (mac->GetTypeOfStation() == 
AP ? 
"AP" : 
"non-AP") << 
" MLD for " << 
dir 
 1572    auto storedMapping =
 
 1574    checkStoredMapping(
m_apMac, 
m_staMacs[0], WifiDirection::DOWNLINK, storedMapping);
 
 1575    checkStoredMapping(
m_apMac, 
m_staMacs[0], WifiDirection::UPLINK, storedMapping);
 
 1576    checkStoredMapping(
m_staMacs[0], 
m_apMac, WifiDirection::DOWNLINK, storedMapping);
 
 1577    checkStoredMapping(
m_staMacs[0], 
m_apMac, WifiDirection::UPLINK, storedMapping);
 
 1589    for (
const auto& linkId : 
m_staMacs[0]->GetLinkIds())
 
 1597                                  "Link " << +linkId << 
" has not been setup but is not disabled");
 
 1604                              "Expecting link " << +linkId << 
" to be active");
 
 1612    const auto& hdr = mpdu->GetHeader();
 
 1616    if (!hdr.IsToDs() && hdr.IsFromDs())
 
 1618        dir = WifiDirection::DOWNLINK;
 
 1620    else if (hdr.IsToDs() && !hdr.IsFromDs())
 
 1622        dir = WifiDirection::UPLINK;
 
 1626        NS_ABORT_MSG(
"Invalid combination for QoS data frame: ToDS(" << hdr.IsToDs() << 
") FromDS(" 
 1627                                                                     << hdr.IsFromDs() << 
")");
 
 1632    uint8_t tid = hdr.GetQosTid();
 
 1635                          (tid2.has_value() && tid == *tid2),
 
 1636                          "QoS frame with unexpected TID " << +tid);
 
 1639    auto findLinkSet = [
this, 
dir](uint8_t tid) -> std::set<uint8_t> {
 
 1644            if (
auto it = mappingOptRef->get().find(tid); it != mappingOptRef->get().cend())
 
 1646                linkSet = it->second;
 
 1647                NS_ASSERT_MSG(!linkSet.empty(), 
"TID " << +tid << 
" mapped to no link");
 
 1653    auto linkSet = findLinkSet(tid);
 
 1660    std::size_t nConcurFrames = std::min(qosFrames.size(), linkSet.size());
 
 1663    for (std::size_t i = 0; i < nConcurFrames; i++)
 
 1665        auto prev = qosFrames[i];
 
 1675        if (qosFrames.size() < linkSet.size())
 
 1680                                  "The " << 
dir << 
" QoS frame number " << qosFrames.size()
 
 1681                                         << 
" was not sent concurrently with others on link " 
 1682                                         << +linkId << 
" which TID " << +tid << 
" is mapped to");
 
 1689                                  "The " << 
dir << 
" QoS frame number " << qosFrames.size()
 
 1690                                         << 
" was sent concurrently with others on a link " 
 1691                                         << +linkId << 
" which TID " << +tid << 
" is mapped to");
 
 1699                              "QoS frame sent on Link ID " 
 1700                                  << +linkId << 
" that does not belong to the link set of TID " 
 1707        auto otherTid = (tid == tid1) ? *tid2 : tid1;
 
 1709        auto otherLinkSet = findLinkSet(otherTid);
 
 1712        std::size_t nOtherConcurFrames = std::min(otherQosFrames.size(), otherLinkSet.size());
 
 1715        for (std::size_t i = 0; i < nOtherConcurFrames; i++)
 
 1717            auto prev = otherQosFrames[i];
 
 1727            if (qosFrames.size() < linkSet.size())
 
 1732                                      "The " << 
dir << 
" QoS frame number " << qosFrames.size()
 
 1733                                             << 
" was not sent concurrently with others with TID " 
 1740    qosFrames.emplace_back(index);
 
 1823                    uint8_t nMaxInflight);
 
 1841                  double txPowerW) 
override;
 
 1843    void DoRun() 
override;
 
 1870                                 uint8_t nMaxInflight)
 
 1872          std::string(
"Check data transmission between MLDs ") +
 
 1875                          ? 
"with BA agreement, send BAR after BlockAck timeout" 
 1876                          : 
"with BA agreement, send Data frames after BlockAck timeout")
 
 1877                   : 
"without BA agreement") +
 
 1878              " (Traffic pattern: " + 
std::to_string(static_cast<uint8_t>(trafficPattern)) +
 
 1884      m_trafficPattern(trafficPattern),
 
 1887      m_nMaxInflight(nMaxInflight),
 
 1905    auto psdu = psduMap.begin()->second;
 
 1907    switch (psdu->GetHeader(0).GetType())
 
 1912                       psdu->GetHeader(0).GetAddr2() == psdu->GetHeader(0).GetAddr3() ? 
DL : 
UL);
 
 1917            m_uidList.push_front(psdu->GetPacket()->GetUid());
 
 1925        for (
const auto& mpdu : *psdu)
 
 1931                    mpdu->GetHeader().GetAddr2() &&
 
 1932                !mpdu->GetHeader().GetAddr1().IsGroup())
 
 1934                auto seqNo = mpdu->GetHeader().GetSequenceNumber();
 
 1935                auto [it, success] =
 
 1939                    it->second = std::max(it->second, mpdu->GetInFlightLinkIds().size());
 
 1943        for (std::size_t i = 0; i < psdu->GetNMpdus(); i++)
 
 1949            if (psdu->GetHeader(i).GetSequenceNumber() != 1 ||
 
 1956            auto uid = psdu->GetPayload(i)->GetUid();
 
 1993            m_uidList.push_front(psdu->GetPacket()->GetUid());
 
 2018                          "No BlockAck expected in AP to broadcast traffic pattern");
 
 2032    auto mpdu = *psdu->begin();
 
 2034    mpdu->GetPacket()->PeekHeader(blockAck);
 
 2035    bool isMpdu1corrupted = (
m_trafficPattern == WifiTrafficPattern::STA_TO_AP ||
 
 2043                              "MPDU 0 expected to be successfully received");
 
 2047            "MPDU 1 expected to be received only in STA_TO_STA/STA_TO_BCAST scenarios");
 
 2050        if (
m_staMacs[0]->GetSetupLinkIds().size() > 1)
 
 2055            auto item = queue->PeekByTidAndAddress(0, rcvMac->GetAddress());
 
 2056            std::size_t nQueuedPkt = 0;
 
 2059                                                      rcvMac->GetWifiPhy(linkId)->GetPhyBand()) +
 
 2064                auto seqNo = item->GetHeader().GetSequenceNumber();
 
 2067                                      "MPDU with seqNo=" << seqNo << 
" is not in flight");
 
 2068                auto linkIds = item->GetInFlightLinkIds();
 
 2071                                      "MPDU with seqNo=" << seqNo
 
 2072                                                         << 
" is in flight on multiple links");
 
 2079                                      "Addr1 of BlockAck is not an originator's link address");
 
 2082                                      "MPDU with seqNo=" << seqNo
 
 2083                                                         << 
" in flight on unexpected link");
 
 2088                bool isQueued = (seqNo > (isMpdu1corrupted ? 0 : 1));
 
 2092                bool isRetry = isQueued && seqNo <= 1;
 
 2098                                              << item->GetHeader().GetSequenceNumber() << 
" should " 
 2099                                              << (isQueued ? 
"" : 
"not") << 
" be queued");
 
 2101                        item->GetHeader().IsRetry(),
 
 2103                        "Unexpected value for the Retry subfield of the MPDU with seqNo=" 
 2104                            << item->GetHeader().GetSequenceNumber());
 
 2108                item = queue->PeekByTidAndAddress(0, rcvMac->GetAddress(), item);
 
 2119                              "Did not expect to receive a second BlockAck");
 
 2121        std::pair<uint16_t, uint16_t> seqNos;
 
 2126        if (
m_staMacs[0]->GetSetupLinkIds().size() > 1)
 
 2136                              "MPDU " << seqNos.first << 
" expected to be successfully received");
 
 2139                              "MPDU " << seqNos.second << 
" expected to be successfully received");
 
 2155            mac->GetQosTxop(
AC_BE)->SetAttribute(
"UseExplicitBarAfterMissedBlockAck",
 
 2164        auto errorModel = CreateObject<ListErrorModel>();
 
 2168    for (std::size_t i : {0, 1})
 
 2170        for (
const auto linkId : 
m_staMacs[i]->GetLinkIds())
 
 2172            auto errorModel = CreateObject<ListErrorModel>();
 
 2174            m_staMacs[i]->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel);
 
 2186    case WifiTrafficPattern::STA_TO_STA:
 
 2188        destAddr = 
m_staMacs[1]->GetDevice()->GetAddress();
 
 2190    case WifiTrafficPattern::STA_TO_AP:
 
 2194    case WifiTrafficPattern::AP_TO_STA:
 
 2196        destAddr = 
m_staMacs[1]->GetDevice()->GetAddress();
 
 2198    case WifiTrafficPattern::AP_TO_BCAST:
 
 2202    case WifiTrafficPattern::STA_TO_BCAST:
 
 2234    std::array<std::size_t, 3> expectedRxPkts{};
 
 2238    case WifiTrafficPattern::STA_TO_STA:
 
 2239    case WifiTrafficPattern::AP_TO_STA:
 
 2243    case WifiTrafficPattern::STA_TO_AP:
 
 2247    case WifiTrafficPattern::AP_TO_BCAST:
 
 2253    case WifiTrafficPattern::STA_TO_BCAST:
 
 2263                          "Unexpected number of packets received by the AP");
 
 2266                          "Unexpected number of packets received by STA 0");
 
 2269                          "Unexpected number of packets received by STA 1");
 
 2274        std::size_t expectedBaCount = 0;
 
 2275        std::size_t expectedBarCount = 0;
 
 2279        case WifiTrafficPattern::STA_TO_AP:
 
 2280        case WifiTrafficPattern::AP_TO_STA:
 
 2282            expectedBaCount = 3;
 
 2286        case WifiTrafficPattern::STA_TO_STA:
 
 2287        case WifiTrafficPattern::STA_TO_BCAST:
 
 2289            expectedBaCount = 1;
 
 2295                              "Unexpected number of BlockAck frames");
 
 2298                              "Unexpected number of BlockAckReq frames");
 
 2309            "Did not collect number of simultaneous transmissions for all data frames");
 
 2312        std::size_t maxCount = 0;
 
 2318                "MPDU with seqNo=" << seqNo
 
 2319                                   << 
" transmitted simultaneously more times than allowed");
 
 2320            maxCount = std::max(maxCount, count);
 
 2326            "Expected that at least one data frame was transmitted simultaneously a number of " 
 2327            "times equal to the NMaxInflights attribute");
 
 2382                      uint8_t nMaxInflight);
 
 2400                  double txPowerW) 
override;
 
 2402    void DoRun() 
override;
 
 2434                                     uint8_t nMaxInflight)
 
 2436          std::string(
"Check MU data transmission between MLDs ") +
 
 2438                   ? 
"(send BAR after BlockAck timeout," 
 2439                   : 
"(send Data frames after BlockAck timeout,") +
 
 2440              " MU Traffic pattern: " + 
std::to_string(static_cast<uint8_t>(muTrafficPattern)) +
 
 2441              ", nMaxInflight=" + 
std::to_string(nMaxInflight) + 
")",
 
 2444      m_muTrafficPattern(muTrafficPattern),
 
 2446      m_nMaxInflight(nMaxInflight),
 
 2447      m_sockets(m_nStations),
 
 2464    for (
const auto& [staId, psdu] : psduMap)
 
 2466        switch (psdu->GetHeader(0).GetType())
 
 2470            if (psdu->GetHeader(0).HasData())
 
 2472                bool isDl = psdu->GetHeader(0).IsFromDs();
 
 2474                    isDl ? psdu->GetHeader(0).GetAddr1() : psdu->GetHeader(0).GetAddr2();
 
 2477                for (
const auto& mpdu : *psdu)
 
 2480                    auto seqNo = mpdu->GetHeader().GetSequenceNumber();
 
 2482                        {{address, seqNo}, mpdu->GetInFlightLinkIds().size()});
 
 2485                        it->second = std::max(it->second, mpdu->GetInFlightLinkIds().size());
 
 2488                for (std::size_t i = 0; i < psdu->GetNMpdus(); i++)
 
 2491                    if (psdu->GetHeader(i).GetSequenceNumber() == 2)
 
 2497                                                  "MPDU " << **std::next(psdu->begin(), i)
 
 2498                                                          << 
" not transmitted in a TB PPDU");
 
 2504                                                  "MPDU " << **std::next(psdu->begin(), i)
 
 2505                                                          << 
" not transmitted in a DL MU PPDU");
 
 2509                    if (psdu->GetHeader(i).GetSequenceNumber() != 3)
 
 2513                    auto uid = psdu->GetPayload(i)->GetUid();
 
 2550                m_uidList.push_front(psdu->GetPacket()->GetUid());
 
 2556            psdu->GetPayload(0)->PeekHeader(trigger);
 
 2565                auto band = mac->GetWifiPhy(linkId)->GetPhyBand();
 
 2569                    m_staMacs[i]->GetDevice()->GetNode()->AddApplication(
 
 2618    auto mpdu = *psdu->begin();
 
 2620    mpdu->GetPacket()->PeekHeader(blockAck);
 
 2621    bool isMpdu3corrupted;
 
 2636                auto index = indices.front();
 
 2639                                      "Expected that a QoS data frame was corrupted");
 
 2641                    m_staMacs[i]->GetLinkIdByAddress(*m_dataCorruptedSta).has_value();
 
 2644                                      "MPDU 2 expected to be successfully received");
 
 2647                                      "Unexpected reception status for MPDU 3");
 
 2657                              "MPDU 2 expected to be successfully received");
 
 2660                              "Unexpected reception status for MPDU 3");
 
 2664            m_staMacs[0]->GetSetupLinkIds().size() > 1)
 
 2668            if (
m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress() ==
 
 2669                mpdu->GetHeader().GetAddr2())
 
 2673            else if (
m_staMacs[1]->GetFrameExchangeManager(linkId)->GetAddress() ==
 
 2674                     mpdu->GetHeader().GetAddr2())
 
 2680                NS_ABORT_MSG(
"BlockAck frame not sent by a station in DL scenario");
 
 2682            auto item = queue->PeekByTidAndAddress(0, rcvMac->GetAddress());
 
 2683            std::size_t nQueuedPkt = 0;
 
 2686                                                      rcvMac->GetWifiPhy(linkId)->GetPhyBand()) +
 
 2691                auto seqNo = item->GetHeader().GetSequenceNumber();
 
 2694                                      "MPDU with seqNo=" << seqNo << 
" is not in flight");
 
 2695                auto linkIds = item->GetInFlightLinkIds();
 
 2698                                      "MPDU with seqNo=" << seqNo
 
 2699                                                         << 
" is in flight on multiple links");
 
 2706                                      "Addr1 of BlockAck is not an originator's link address");
 
 2709                                      "MPDU with seqNo=" << seqNo
 
 2710                                                         << 
" in flight on unexpected link");
 
 2715                bool isQueued = (seqNo > (isMpdu3corrupted ? 2 : 3));
 
 2719                bool isRetry = isQueued && seqNo <= 3;
 
 2725                                              << item->GetHeader().GetSequenceNumber() << 
" should " 
 2726                                              << (isQueued ? 
"" : 
"not") << 
" be queued");
 
 2728                        item->GetHeader().IsRetry(),
 
 2730                        "Unexpected value for the Retry subfield of the MPDU with seqNo=" 
 2731                            << item->GetHeader().GetSequenceNumber());
 
 2735                item = queue->PeekByTidAndAddress(0, rcvMac->GetAddress(), item);
 
 2749    case WifiMuTrafficPattern::DL_MU_BAR_BA_SEQUENCE:
 
 2753    case WifiMuTrafficPattern::DL_MU_MU_BAR:
 
 2757    case WifiMuTrafficPattern::DL_MU_AGGR_MU_BAR:
 
 2770        mac->GetQosTxop(
AC_BE)->SetAttribute(
"UseExplicitBarAfterMissedBlockAck",
 
 2775        mac->GetQosTxop(
AC_VI)->SetAttribute(
"UseExplicitBarAfterMissedBlockAck",
 
 2781    auto muScheduler = CreateObjectWithAttributes<RrMultiUserScheduler>(
 
 2793        auto errorModel = CreateObject<ListErrorModel>();
 
 2797    for (std::size_t i : {0, 1})
 
 2799        for (
const auto linkId : 
m_staMacs[i]->GetLinkIds())
 
 2801            auto errorModel = CreateObject<ListErrorModel>();
 
 2803            m_staMacs[i]->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel);
 
 2853            m_staMacs[i]->GetDevice()->GetNode()->AddApplication(
 
 2866            muScheduler->SetAccessReqInterval(
Seconds(0));
 
 2879    std::array<std::size_t, 3> expectedRxPkts{};
 
 2883    case WifiMuTrafficPattern::DL_MU_BAR_BA_SEQUENCE:
 
 2884    case WifiMuTrafficPattern::DL_MU_MU_BAR:
 
 2885    case WifiMuTrafficPattern::DL_MU_AGGR_MU_BAR:
 
 2890    case WifiMuTrafficPattern::UL_MU:
 
 2898                          "Unexpected number of packets received by the AP");
 
 2901                          "Unexpected number of packets received by STA 0");
 
 2904                          "Unexpected number of packets received by STA 1");
 
 2912        "Did not collect number of simultaneous transmissions for all data frames");
 
 2915    std::size_t maxCount = 0;
 
 2921                                        << txSeqNoPair.second
 
 2922                                        << 
" transmitted simultaneously more times than allowed");
 
 2923        maxCount = std::max(maxCount, count);
 
 2929        "Expected that at least one data frame was transmitted simultaneously a number of " 
 2930        "times equal to the NMaxInflights attribute");
 
 2961    void DoRun() 
override;
 
 2966                  double txPowerW) 
override;
 
 2979          "Check sequence numbers after CTS timeout",
 
 2981          BaseParams{{
"{36, 0, BAND_5GHZ, 0}", 
"{2, 0, BAND_2_4GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}"},
 
 2982                     {
"{36, 0, BAND_5GHZ, 0}", 
"{2, 0, BAND_2_4GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}"},
 
 2984      m_nQosDataFrames(0),
 
 2985      m_errorModel(CreateObject<ListErrorModel>()),
 
 2986      m_rtsCorrupted(
false)
 
 2999    for (
const auto linkId : 
m_staMacs[0]->GetLinkIds())
 
 3025    auto psdu = psduMap.begin()->second;
 
 3034    else if (psdu->GetHeader(0).IsQosData())
 
 3054    std::size_t count{};
 
 3058        auto psdu = txPsdu.psduMap.begin()->second;
 
 3060        if (!psdu->GetHeader(0).IsQosData())
 
 3068        uint16_t expectedSeqNo{};
 
 3087                                  "Unexpected sequence number");
 
 3110                                   std::vector<uint8_t>, 
 
 3118    for (
const auto& [baseParams,
 
 3124          ParamsTuple({{
"{36, 0, BAND_5GHZ, 0}", 
"{2, 0, BAND_2_4GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}"},
 
 3125                       {
"{36, 0, BAND_5GHZ, 0}", 
"{2, 0, BAND_2_4GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}"},
 
 3129                      "0,1,2,3  0,1,2;  4,5  0,1", 
 
 3130                      "0,1,2,3  1,2;    6,7  0,1"   
 3133          ParamsTuple({{
"{108, 0, BAND_5GHZ, 0}", 
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}"},
 
 3134                       {
"{36, 0, BAND_5GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}", 
"{5, 0, BAND_6GHZ, 0}"},
 
 3138                      "0,1,2,3  0,1,2;  4,5  0,1", 
 
 3141          ParamsTuple({{
"{2, 0, BAND_2_4GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{36, 0, BAND_5GHZ, 0}"},
 
 3142                       {
"{36, 0, BAND_5GHZ, 0}", 
"{9, 0, BAND_6GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3146                      "0,1,2,3  0;  4,5,6,7  1,2", 
 
 3147                      "0,2,3  1,2;  1,4,5,6,7  0"   
 3152              {{
"{2, 0, BAND_2_4GHZ, 0}", 
"{36, 0, BAND_5GHZ, 0}", 
"{8, 20, BAND_2_4GHZ, 0}"},
 
 3153               {
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3157              "0,1,2,3,4,5,6,7  0",
 
 3158              "0,1,2,3,4,5,6,7  0"),
 
 3163              {{
"{2, 0, BAND_2_4GHZ, 0}", 
"{36, 0, BAND_5GHZ, 0}", 
"{8, 20, BAND_2_4GHZ, 0}"},
 
 3164               {
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3175          ParamsTuple({{
"{2, 0, BAND_2_4GHZ, 0}", 
"{36, 0, BAND_5GHZ, 0}", 
"{60, 0, BAND_5GHZ, 0}"},
 
 3176                       {
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3185          ParamsTuple({{
"{2, 0, BAND_2_4GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3186                       {
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3193          ParamsTuple({{
"{2, 0, BAND_2_4GHZ, 0}", 
"{36, 0, BAND_5GHZ, 0}"},
 
 3194                       {
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3201          ParamsTuple({{
"{120, 0, BAND_5GHZ, 0}"},
 
 3202                       {
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3209          ParamsTuple({{
"{36, 0, BAND_5GHZ, 0}", 
"{1, 0, BAND_6GHZ, 0}", 
"{120, 0, BAND_5GHZ, 0}"},
 
 3210                       {
"{120, 0, BAND_5GHZ, 0}"},
 
 3214                      "0,1,2,3  0,1;  4,5,6,7  0,1", 
 
 3218                                           WifiScanType::PASSIVE,
 
 3225                                           WifiScanType::ACTIVE,
 
 3232        for (
const auto& trafficPattern : {WifiTrafficPattern::STA_TO_STA,
 
 3233                                           WifiTrafficPattern::STA_TO_AP,
 
 3234                                           WifiTrafficPattern::AP_TO_STA,
 
 3235                                           WifiTrafficPattern::AP_TO_BCAST,
 
 3236                                           WifiTrafficPattern::STA_TO_BCAST})
 
 3242                                            WifiUseBarAfterMissedBa::NO,
 
 3245            for (
const auto& useBarAfterMissedBa :
 
 3246                 {WifiUseBarAfterMissedBa::YES, WifiUseBarAfterMissedBa::NO})
 
 3252                                                useBarAfterMissedBa,
 
 3259                                                useBarAfterMissedBa,
 
 3265        for (
const auto& muTrafficPattern : {WifiMuTrafficPattern::DL_MU_BAR_BA_SEQUENCE,
 
 3266                                             WifiMuTrafficPattern::DL_MU_MU_BAR,
 
 3267                                             WifiMuTrafficPattern::DL_MU_AGGR_MU_BAR,
 
 3268                                             WifiMuTrafficPattern::UL_MU})
 
 3270            for (
const auto& useBarAfterMissedBa :
 
 3271                 {WifiUseBarAfterMissedBa::YES, WifiUseBarAfterMissedBa::NO})
 
Test the implementation of WifiAssocManager::GetNextAffiliatedAp(), which searches a given RNR elemen...
 
GetRnrLinkInfoTest()
Constructor.
 
~GetRnrLinkInfoTest() override=default
 
void DoRun() override
Implementation to actually run this TestCase.
 
Test WifiMac subclass used to access the SwapLinks method.
 
void Enqueue(Ptr< Packet > packet, Mac48Address to) override
 
~TestWifiMac() override=default
 
bool CanForwardPacketsTo(Mac48Address to) const override
Return true if packets can be forwarded to the given destination, false otherwise.
 
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.
 
~MldSwapLinksTest() override=default
 
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.
 
std::pair< Mac48Address, uint16_t > AddrSeqNoPair
A pair of a MAC address (the address of the receiver for DL frames and the address of the sender for ...
 
~MultiLinkMuTxTest() override=default
 
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::unordered_map< Mac48Address, Ptr< ListErrorModel >, WifiAddressHash > RxErrorModelMap
Receiver address-indexed map of list error models.
 
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
 
Ptr< WifiMac > m_sourceMac
MAC of the node sending application packets.
 
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_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
 
~MultiLinkOperationsTestBase() override=default
 
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.
 
Ptr< PacketSocketClient > GetApplication(const PacketSocketAddress &sockAddr, std::size_t count, std::size_t pktSize, Time delay=Seconds(0), uint8_t priority=0) const
 
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
 
uint16_t m_lastAid
AID of last associated station.
 
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
 
Direction
Uplink or Downlink direction.
 
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.
 
std::map< FrequencyRange, Ptr< MultiModelSpectrumChannel > > ChannelMap
PHY band-indexed map of spectrum channels.
 
Multi-Link Discovery & Setup test.
 
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.
 
~MultiLinkSetupTest() override=default
 
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
 
uint8_t m_apNegSupport
TID-to-Link Mapping negotiation supported by the AP MLD.
 
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.
 
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.
 
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 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.
 
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
 
void CheckQosData(Ptr< WifiMpdu > mpdu, uint8_t linkId, std::size_t index)
Check that QoS data frames are sent on links their TID is mapped to.
 
const std::vector< uint8_t > m_setupLinks
IDs of the expected links to setup.
 
MultiLinkSetupTest(const BaseParams &baseParams, WifiScanType scanType, const std::vector< uint8_t > &setupLinks, uint8_t apNegSupport, const std::string &dlTidToLinkMapping, const std::string &ulTidToLinkMapping)
Constructor.
 
Test data transmission between two MLDs.
 
~MultiLinkTxTest() override=default
 
std::unordered_map< Mac48Address, Ptr< ListErrorModel >, WifiAddressHash > RxErrorModelMap
Receiver address-indexed map of list error models.
 
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.
 
~ReleaseSeqNoAfterCtsTimeoutTest() override=default
 
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.
 
WifiMultiLinkOperationsTestSuite()
 
a polymophic address class
 
uint16_t GetAssociationId(Mac48Address addr, uint8_t linkId) const
 
const std::map< uint16_t, Mac48Address > & GetStaList(uint8_t linkId) const
Get a const reference to the map of associated stations on the given link.
 
Ptr< WifiMacQueue > GetTxopQueue(AcIndex ac) const override
Get the wifi MAC queue of the (Qos)Txop associated with the given AC, if such (Qos)Txop is installed,...
 
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
 
keep track of a set of node pointers.
 
uint32_t AddApplication(Ptr< Application > application)
Associate an Application to this Node.
 
static uint32_t GetNNodes()
 
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
 
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
 
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
 
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.
 
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.
 
void SetMldParameters(std::size_t nbrApInfoId, std::size_t index, uint8_t mldId, uint8_t linkId, uint8_t changeSequence)
Set the MLD Parameters subfield of the i-th TBTT Information field of the given Neighbor AP Informati...
 
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 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)
 
The IEEE 802.11 SSID Information Element.
 
AttributeValue implementation for Ssid.
 
Hold variables of type string.
 
void AddTestCase(TestCase *testCase, TestDuration 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.
 
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
 
create MAC layers for a ns3::WifiNetDevice.
 
base class for all MAC-level wifi objects.
 
Ptr< FrameExchangeManager > GetFrameExchangeManager(uint8_t linkId=SINGLE_LINK_OP_ID) const
Get the Frame Exchange Manager associated with the given link.
 
std::optional< Mac48Address > GetMldAddress(const Mac48Address &remoteAddr) const
 
const std::map< uint8_t, std::unique_ptr< LinkEntity > > & GetLinks() const
 
uint8_t GetNLinks() const
Get the number of links (can be greater than 1 for 11be devices only).
 
void SwapLinks(std::map< uint8_t, uint8_t > links)
Swap the links based on the information included in the given map.
 
Ptr< WifiPhy > GetWifiPhy(uint8_t linkId=SINGLE_LINK_OP_ID) const
 
virtual std::optional< uint8_t > GetLinkIdByAddress(const Mac48Address &address) const
Get the ID of the link having the given MAC address, if any.
 
Ptr< EhtConfiguration > GetEhtConfiguration() const
 
std::optional< std::reference_wrapper< const WifiTidLinkMapping > > GetTidToLinkMapping(Mac48Address mldAddr, WifiDirection dir) const
Get the TID-to-Link Mapping negotiated with the given MLD (if any) for the given direction.
 
Ptr< WifiNetDevice > GetDevice() const
Return the device this PHY is associated with.
 
virtual Ptr< WifiMacQueue > GetTxopQueue(AcIndex ac) const
Get the wifi MAC queue of the (Qos)Txop associated with the given AC, if such (Qos)Txop is installed,...
 
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
 
const std::set< uint8_t > & GetLinkIds() const
 
Mac48Address GetAddress() const
 
uint32_t GetIfIndex() const override
 
Address GetAddress() const override
 
Ptr< Node > GetNode() const override
 
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.
 
void SetPostReceptionErrorModel(const Ptr< ErrorModel > em)
Attach a receive ErrorModel to the WifiPhy.
 
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
 
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
 
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
 
uint8_t GetPrimaryChannelIndex(uint16_t primaryChannelWidth) const
If the operating channel width is a multiple of 20 MHz, return the index of the primary channel of th...
 
uint16_t GetWidth() const
Return the width of the whole operating channel (in MHz).
 
WifiPhyBand GetPhyBand() const
Return the PHY band of the operating channel.
 
uint8_t GetNumber() const
Return the channel number identifying the whole operating channel.
 
uint16_t GetFrequency() const
Return the center frequency of the operating channel (in MHz).
 
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.
 
#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.
 
#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.
 
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::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
 
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...
 
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_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.
 
std::map< uint8_t, std::set< uint8_t > > WifiTidLinkMapping
TID-indexed map of the link set to which the TID is mapped.
 
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.
 
std::vector< std::string > staChannels
the strings specifying the operating channels for the non-AP MLD
 
std::vector< uint8_t > fixedPhyBands
list of IDs of non-AP MLD PHYs that cannot switch band
 
std::vector< std::string > apChannels
the strings specifying the operating channels for the AP MLD
 
Information about transmitted frames.
 
uint8_t phyId
ID of the transmitting PHY.
 
WifiConstPsduMap psduMap
transmitted PSDU map
 
WifiTxVector txVector
TXVECTOR.
 
Time startTx
TX start time.
 
Function object to compute the hash of a MAC address.
 
uint32_t pktSize
packet size used for the simulation (in bytes)
 
WifiMuTrafficPattern
Tested MU traffic patterns.
 
WifiTrafficPattern
Tested traffic patterns.
 
WifiUseBarAfterMissedBa
Whether to send a BlockAckReq after a missed BlockAck.
 
static WifiMultiLinkOperationsTestSuite g_wifiMultiLinkOperationsTestSuite
the test suite
 
WifiBaEnabled
Block Ack agreement enabled/disabled.