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");
231 void DoRun()
override;
244 void RunOne(std::string text,
246 const std::map<uint8_t, uint8_t>& links,
247 const std::map<uint8_t, uint8_t>& expected);
251 :
TestCase(
"Test the WifiMac::SwapLinks() method")
258 const std::map<uint8_t, uint8_t>& links,
259 const std::map<uint8_t, uint8_t>& expected)
263 std::vector<Ptr<WifiPhy>> phys;
264 for (std::size_t i = 0; i < nLinks; i++)
266 phys.emplace_back(CreateObject<SpectrumWifiPhy>());
268 mac.SetWifiPhys(phys);
270 mac.SwapLinks(links);
274 for (
const auto& [linkId, phyId] : expected)
278 "Link ID " << +linkId <<
" does not exist");
285 text <<
": Link " << +phyId <<
" has not been moved to link "
293 RunOne(
"No change needed", 3, {{0, 0}, {1, 1}, {2, 2}}, {{0, 0}, {1, 1}, {2, 2}});
294 RunOne(
"Circular swapping", 3, {{0, 2}, {1, 0}, {2, 1}}, {{0, 1}, {1, 2}, {2, 0}});
295 RunOne(
"Swapping two links, one unchanged", 3, {{0, 2}, {2, 0}}, {{0, 2}, {1, 1}, {2, 0}});
296 RunOne(
"Non-circular swapping, autodetect how to close the loop",
299 {{0, 1}, {1, 2}, {2, 0}});
300 RunOne(
"One move only, autodetect how to complete the swapping",
303 {{0, 2}, {1, 1}, {2, 0}});
304 RunOne(
"Create a new link ID (2), remove the unused one (0)",
308 RunOne(
"One move only that creates a new link ID (2)", 2, {{0, 2}}, {{1, 1}, {2, 0}});
309 RunOne(
"Move all links to a new set of IDs", 2, {{0, 2}, {1, 3}}, {{2, 0}, {3, 1}});
330 std::vector<std::string>
332 std::vector<std::string>
398 uint8_t priority = 0)
const;
403 using ChannelMap = std::map<FrequencyRange, Ptr<MultiModelSpectrumChannel>>;
421 std::optional<Direction> direction = std::nullopt);
456 const std::vector<std::string>& channels,
480 m_staChannels(baseParams.staChannels),
481 m_apChannels(baseParams.apChannels),
482 m_fixedPhyBands(baseParams.fixedPhyBands),
483 m_staMacs(nStations),
484 m_nStations(nStations),
486 m_rxPkts(nStations + 1)
492 std::optional<Direction> direction)
494 std::optional<Mac48Address> apAddr;
495 std::optional<Mac48Address> staAddr;
498 if (psdu->GetHeader(0).IsQosData())
500 direction = (!psdu->GetHeader(0).IsToDs() && psdu->GetHeader(0).IsFromDs()) ?
DL :
UL;
506 if (!psdu->GetAddr1().IsGroup())
508 staAddr = psdu->GetAddr1();
510 apAddr = psdu->GetAddr2();
514 if (!psdu->GetAddr1().IsGroup())
516 apAddr = psdu->GetAddr1();
518 staAddr = psdu->GetAddr2();
534 "Address " << *apAddr <<
" is not an AP device address. "
535 <<
"PSDU: " << *psdu);
543 for (
const auto& linkId :
m_staMacs[i]->GetLinkIds())
545 if (
m_staMacs[i]->GetFrameExchangeManager(linkId)->GetAddress() == *staAddr)
558 "Address " << *staAddr <<
" is not a STA device address. "
559 <<
"PSDU: " << *psdu);
570 auto linkId = mac->GetLinkForPhy(phyId);
574 for (
const auto& [aid, psdu] : psduMap)
576 std::stringstream ss;
577 ss << std::setprecision(10) <<
"PSDU #" <<
m_txPsdus.size() <<
" Link ID "
578 << +linkId.value() <<
" Phy ID " << +phyId <<
" " << psdu->GetHeader(0).GetTypeString()
579 <<
" #MPDUs " << psdu->GetNMpdus() <<
" duration/ID " << psdu->GetHeader(0).GetDuration()
580 <<
" RA = " << psdu->GetAddr1() <<
" TA = " << psdu->GetAddr2()
581 <<
" ADDR3 = " << psdu->GetHeader(0).GetAddr3()
582 <<
" ToDS = " << psdu->GetHeader(0).IsToDs()
583 <<
" FromDS = " << psdu->GetHeader(0).IsFromDs();
584 if (psdu->GetHeader(0).IsQosData())
589 ss << mpdu->GetHeader().GetSequenceNumber() <<
",";
591 ss <<
"} TID = " << +psdu->GetHeader(0).GetQosTid();
603 auto band = mac->GetDevice()->GetPhy(phyId)->GetPhyBand();
604 bool hasHtCapabilities;
605 bool hasVhtCapabilities;
606 bool hasHeCapabilities;
607 bool hasHe6GhzCapabilities;
608 bool hasEhtCapabilities;
610 auto findCapabilities = [&](
auto&& frame) {
611 hasHtCapabilities = frame.template Get<HtCapabilities>().has_value();
612 hasVhtCapabilities = frame.template Get<VhtCapabilities>().has_value();
613 hasHeCapabilities = frame.template Get<HeCapabilities>().has_value();
614 hasHe6GhzCapabilities = frame.template Get<He6GhzBandCapabilities>().has_value();
615 hasEhtCapabilities = frame.template Get<EhtCapabilities>().has_value();
618 switch (mpdu->GetHeader().GetType())
622 mpdu->GetPacket()->PeekHeader(beacon);
623 findCapabilities(beacon);
629 mpdu->GetPacket()->PeekHeader(probeReq);
630 findCapabilities(probeReq);
636 mpdu->GetPacket()->PeekHeader(probeResp);
637 findCapabilities(probeResp);
643 mpdu->GetPacket()->PeekHeader(assocReq);
644 findCapabilities(assocReq);
650 mpdu->GetPacket()->PeekHeader(assocResp);
651 findCapabilities(assocResp);
662 "HT Capabilities should not be present in a mgt frame sent in 6 GHz band");
666 "VHT Capabilities should only be present in a mgt frame sent in 5 GHz band");
669 "HE Capabilities should always be present in a mgt frame");
671 hasHe6GhzCapabilities,
673 "HE 6GHz Band Capabilities should only be present in a mgt frame sent in 6 GHz band");
676 "EHT Capabilities should always be present in a mgt frame");
682 NS_LOG_INFO(
"Packet received by NODE " << +nodeId <<
"\n");
688 const std::vector<std::string>& channels,
695 for (
const auto& str : channels)
702 for (
const auto& [band, channel] : channelMap)
713 int64_t streamNumber = 30;
716 wifiApNode.Create(1);
724 wifi.SetRemoteStationManager(
"ns3::ConstantRateWifiManager",
745 mac.SetType(
"ns3::StaWifiMac",
751 mac.SetType(
"ns3::ApWifiMac",
764 streamNumber += wifi.AssignStreams(apDevices, streamNumber);
765 streamNumber += wifi.AssignStreams(staDevices, streamNumber);
770 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
771 positionAlloc->Add(Vector(1.0, 0.0, 0.0));
772 mobility.SetPositionAllocator(positionAlloc);
774 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
775 mobility.Install(wifiApNode);
776 mobility.Install(wifiStaNodes);
778 m_apMac = DynamicCast<ApWifiMac>(DynamicCast<WifiNetDevice>(apDevices.Get(0))->GetMac());
782 DynamicCast<StaWifiMac>(DynamicCast<WifiNetDevice>(staDevices.Get(i))->GetMac());
789 "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phys/" + std::to_string(phyId) +
795 for (uint8_t phyId = 0; phyId <
m_staMacs[i]->GetDevice()->GetNPhys(); phyId++)
798 "/DeviceList/*/$ns3::WifiNetDevice/Phys/" +
799 std::to_string(phyId) +
"/PhyTxPsduBegin",
807 packetSocket.
Install(wifiApNode);
808 packetSocket.
Install(wifiStaNodes);
814 auto device = DynamicCast<WifiNetDevice>((*nodeIt)->GetDevice(0));
819 auto server = CreateObject<PacketSocketServer>();
820 server->SetLocal(srvAddr);
821 (*nodeIt)->AddApplication(server);
822 server->SetStartTime(
Seconds(0));
829 "/NodeList/" + std::to_string(nodeId) +
830 "/ApplicationList/*/$ns3::PacketSocketServer/Rx",
845 uint8_t priority)
const
847 auto client = CreateObject<PacketSocketClient>();
852 client->SetRemote(sockAddr);
853 client->SetStartTime(delay);
925 const std::vector<uint8_t>& setupLinks,
927 const std::string& dlTidToLinkMapping,
928 const std::string& ulTidToLinkMapping);
933 void DoRun()
override;
1006 std::vector<std::size_t>
1008 std::vector<std::size_t>
1014 const std::vector<uint8_t>& setupLinks,
1016 const std::string& dlTidToLinkMapping,
1017 const std::string& ulTidToLinkMapping)
1019 m_setupLinks(setupLinks),
1020 m_scanType(scanType),
1022 m_apNegSupport(apNegSupport),
1023 m_dlTidLinkMappingStr(dlTidToLinkMapping),
1024 m_ulTidLinkMappingStr(ulTidToLinkMapping)
1038 auto staEhtConfig =
m_staMacs[0]->GetEhtConfiguration();
1039 staEhtConfig->SetAttribute(
"TidToLinkMappingNegSupport",
1040 EnumValue(WifiTidToLinkMappingNegSupport::ANY_LINK_SET));
1051 if (
m_apNegSupport == WifiTidToLinkMappingNegSupport::NOT_SUPPORTED ||
1052 (
m_apNegSupport == WifiTidToLinkMappingNegSupport::SAME_LINK_SET &&
1060 using TupleRefs = std::tuple<std::reference_wrapper<const WifiTidLinkMapping>,
1061 std::reference_wrapper<uint8_t>,
1062 std::reference_wrapper<std::optional<uint8_t>>,
1064 for (
auto& [mappingRef, tid1Ref, tid2Ref, mac] :
1069 for (uint8_t tid1 = 0; tid1 < 8; tid1++)
1071 if (
auto it1 = mappingRef.get().find(tid1);
1072 it1 != mappingRef.get().cend() && it1->second.size() !=
m_setupLinks.size())
1075 for (uint8_t tid2 = tid1 + 1; tid2 < 8; tid2++)
1077 if (
auto it2 = mappingRef.get().find(tid2);
1078 it2 != mappingRef.get().cend() && it2->second.size() !=
m_setupLinks.size())
1080 std::list<uint8_t> intersection;
1081 std::set_intersection(it1->second.cbegin(),
1083 it2->second.cbegin(),
1085 std::back_inserter(intersection));
1086 if (intersection.empty())
1089 tid2Ref.get() = tid2;
1094 tid1Ref.get() = tid1;
1099 std::list<uint8_t> tids = {tid1Ref.get()};
1102 tids.emplace_back(*tid2Ref.get());
1106 for (
auto tid : tids)
1108 std::string attrName;
1112 attrName =
"VI_MaxAmpduSize";
1115 attrName =
"VO_MaxAmpduSize";
1118 attrName =
"BE_MaxAmpduSize";
1121 attrName =
"BK_MaxAmpduSize";
1158 m_staMacs[0]->GetDevice()->GetNode()->AddApplication(
1162 m_staMacs[0]->GetDevice()->GetNode()->AddApplication(
1179 std::size_t index = 0;
1183 const auto& mpdu = *frameInfo.psduMap.begin()->second->begin();
1184 const auto& linkId = frameInfo.linkId;
1186 switch (mpdu->GetHeader().GetType())
1218 std::size_t expectedProbeResp = 0;
1227 if (staChannel == apChannel)
1229 expectedProbeResp++;
1241 expectedRxDlPkts *= 2;
1245 "Unexpected number of DL packets received");
1250 expectedRxUlPkts *= 2;
1254 "Unexpected number of UL packets received");
1267 mpdu->GetHeader().GetAddr2(),
1268 "TA of Beacon frame is not the address of the link it is transmitted on");
1270 mpdu->GetPacket()->PeekHeader(beacon);
1278 "RNR Element in Beacon frame from single link AP");
1281 "Multi-Link Element in Beacon frame from single link AP");
1290 "Unexpected number of Neighbor AP Info fields in RNR");
1291 for (std::size_t nbrApInfoId = 0; nbrApInfoId < rnr->GetNNbrApInfoFields(); nbrApInfoId++)
1295 "MLD Parameters not present");
1298 "Expected only one TBTT Info subfield per Neighbor AP Info");
1299 uint8_t nbrLinkId = rnr->GetLinkId(nbrApInfoId, 0);
1302 "BSSID advertised in Neighbor AP Info field "
1304 <<
" does not match the address configured on the link "
1305 "advertised in the same field");
1311 "Incorrect MLD address advertised in Multi-Link Element");
1314 "Incorrect Link ID advertised in Multi-Link Element");
1326 mpdu->GetHeader().GetAddr2(),
1327 "TA of Probe Response is not the address of the link it is transmitted on");
1329 mpdu->GetPacket()->PeekHeader(probeResp);
1337 "RNR Element in Probe Response frame from single link AP");
1340 "Multi-Link Element in Probe Response frame from single link AP");
1349 "Unexpected number of Neighbor AP Info fields in RNR");
1350 for (std::size_t nbrApInfoId = 0; nbrApInfoId < rnr->GetNNbrApInfoFields(); nbrApInfoId++)
1354 "MLD Parameters not present");
1357 "Expected only one TBTT Info subfield per Neighbor AP Info");
1358 uint8_t nbrLinkId = rnr->GetLinkId(nbrApInfoId, 0);
1361 "BSSID advertised in Neighbor AP Info field "
1363 <<
" does not match the address configured on the link "
1364 "advertised in the same field");
1370 "Incorrect MLD address advertised in Multi-Link Element");
1373 "Incorrect Link ID advertised in Multi-Link Element");
1384 m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress(),
1385 mpdu->GetHeader().GetAddr2(),
1386 "TA of Assoc Request frame is not the address of the link it is transmitted on");
1388 mpdu->GetPacket()->PeekHeader(assoc);
1395 "Multi-Link Element in Assoc Request frame from single link STA");
1401 "No Multi-Link Element in Assoc Request frame");
1404 "Incorrect MLD Address advertised in Multi-Link Element");
1406 mle->GetNPerStaProfileSubelements(),
1408 "Incorrect number of Per-STA Profile subelements in Multi-Link Element");
1409 for (std::size_t i = 0; i < mle->GetNPerStaProfileSubelements(); i++)
1411 auto& perStaProfile = mle->GetPerStaProfile(i);
1414 "Per-STA Profile must contain STA MAC address");
1416 auto staLinkId =
m_staMacs[0]->GetLinkIdByAddress(perStaProfile.GetStaMacAddress());
1418 staLinkId.has_value(),
1420 "No link found with the STA MAC address advertised in Per-STA Profile");
1424 "The STA that sent the Assoc Request should not be included in a Per-STA Profile");
1428 "Not expecting to setup STA link ID " << +staLinkId.value());
1431 +perStaProfile.GetLinkId(),
1432 "Not expecting to request association to AP Link ID in Per-STA Profile");
1435 "Missing Association Request in Per-STA Profile");
1449 "Didn't expect a TID-to-Link Mapping IE in Assoc Request frame");
1457 "Unexpected number of TID-to-Link Mapping IE in Assoc Request");
1462 +
static_cast<uint8_t
>(
dir),
1463 "Unexpected direction in TID-to-Link Mapping IE " << tlmId);
1464 auto& expectedMapping =
1468 expectedMapping.empty(),
1469 "Default Link Mapping bit not set correctly");
1471 expectedMapping.size(),
1472 "Unexpected number of Link Mapping Of TID n fields");
1473 for (uint8_t tid = 0; tid < 8; tid++)
1475 if (
auto it = expectedMapping.find(tid); it != expectedMapping.cend())
1479 "Unexpected link mapping for TID "
1480 << +tid <<
" direction " <<
dir);
1486 "Expecting no Link Mapping Of TID n field for TID "
1487 << +tid <<
" direction " <<
dir);
1492 if (tlm.size() == 1)
1494 checkTlm(0, WifiDirection::BOTH_DIRECTIONS);
1498 std::size_t dlId = (tlm[0].m_control.direction == WifiDirection::DOWNLINK ? 0 : 1);
1499 std::size_t ulId = (dlId == 0 ? 1 : 0);
1501 checkTlm(dlId, WifiDirection::DOWNLINK);
1502 checkTlm(ulId, WifiDirection::UPLINK);
1516 mpdu->GetHeader().GetAddr2(),
1517 "TA of Assoc Response frame is not the address of the link it is transmitted on");
1519 mpdu->GetPacket()->PeekHeader(assoc);
1527 "Multi-Link Element in Assoc Response frame with single link AP or single link STA");
1534 "Incorrect MLD Address advertised in Multi-Link Element");
1537 "Incorrect number of Per-STA Profile subelements in Multi-Link Element");
1538 for (std::size_t i = 0; i < mle->GetNPerStaProfileSubelements(); i++)
1540 auto& perStaProfile = mle->GetPerStaProfile(i);
1543 "Per-STA Profile must contain STA MAC address");
1547 apLinkId.has_value(),
1549 "No link found with the STA MAC address advertised in Per-STA Profile");
1551 +perStaProfile.GetLinkId(),
1552 "Link ID and MAC address advertised in Per-STA Profile do not match");
1556 "The AP that sent the Assoc Response should not be included in a Per-STA Profile");
1560 "Not expecting to setup AP link ID " << +apLinkId.value());
1563 "Missing Association Response in Per-STA Profile");
1570 "Didn't expect to find a TID-to-Link Mapping IE in Association Response");
1586 auto staAddr =
m_staMacs[0]->GetFrameExchangeManager(staLinkId)->GetAddress();
1589 auto staRemoteMgr =
m_staMacs[0]->GetWifiRemoteStationManager(staLinkId);
1595 "Unexpected BSSID for STA link ID " << +staLinkId);
1600 "Incorrect MLD address stored by STA on link ID " << +staLinkId);
1604 "Incorrect affiliated address stored by STA on link ID " << +staLinkId);
1610 "Expecting STA " << staAddr <<
" to be associated on link "
1615 (apRemoteMgr->GetMldAddress(staAddr) ==
m_staMacs[0]->GetAddress()),
1617 "Incorrect MLD address stored by AP on link ID " << +apLinkId);
1619 (apRemoteMgr->GetAffiliatedStaAddress(
m_staMacs[0]->GetAddress()) == staAddr),
1621 "Incorrect affiliated address stored by AP on link ID " << +apLinkId);
1627 "STA " << staAddr <<
" not found in list of associated STAs");
1631 +
m_staMacs[0]->GetWifiPhy(staLinkId)->GetOperatingChannel().GetNumber(),
1633 "Incorrect operating channel number for STA on link " << +staLinkId);
1635 m_staMacs[0]->GetWifiPhy(staLinkId)->GetOperatingChannel().GetFrequency(),
1637 "Incorrect operating channel frequency for STA on link " << +staLinkId);
1640 "Incorrect operating channel width for STA on link " << +staLinkId);
1642 +
m_staMacs[0]->GetWifiPhy(staLinkId)->GetOperatingChannel().GetPhyBand(),
1644 "Incorrect operating PHY band for STA on link " << +staLinkId);
1646 +
m_staMacs[0]->GetWifiPhy(staLinkId)->GetOperatingChannel().GetPrimaryChannelIndex(20),
1648 "Incorrect operating primary channel index for STA on link " << +staLinkId);
1652 auto checkStoredMapping =
1656 "Link mapping stored by "
1657 << (mac->GetTypeOfStation() ==
AP ?
"AP" :
"non-AP")
1658 <<
" MLD for " <<
dir <<
" direction "
1659 << (present ?
"expected" :
"not expected"));
1662 const auto& mapping =
1665 (mac->GetTidToLinkMapping(dest->GetAddress(),
dir)->get() == mapping),
1667 "Incorrect link mapping stored by "
1668 << (mac->GetTypeOfStation() ==
AP ?
"AP" :
"non-AP") <<
" MLD for " <<
dir
1675 checkStoredMapping(
m_apMac,
m_staMacs[0], WifiDirection::DOWNLINK, storedMapping);
1676 checkStoredMapping(
m_apMac,
m_staMacs[0], WifiDirection::UPLINK, storedMapping);
1677 checkStoredMapping(
m_staMacs[0],
m_apMac, WifiDirection::DOWNLINK, storedMapping);
1678 checkStoredMapping(
m_staMacs[0],
m_apMac, WifiDirection::UPLINK, storedMapping);
1699 "Unexpected presence/absence of mask on link " << +linkId);
1709 for (
const auto& linkId :
m_staMacs[0]->GetLinkIds())
1717 "Link " << +linkId <<
" has not been setup but is not disabled");
1724 "Expecting link " << +linkId <<
" to be active");
1732 const auto& hdr = mpdu->GetHeader();
1736 if (!hdr.IsToDs() && hdr.IsFromDs())
1738 dir = WifiDirection::DOWNLINK;
1740 else if (hdr.IsToDs() && !hdr.IsFromDs())
1742 dir = WifiDirection::UPLINK;
1746 NS_ABORT_MSG(
"Invalid combination for QoS data frame: ToDS(" << hdr.IsToDs() <<
") FromDS("
1747 << hdr.IsFromDs() <<
")");
1752 uint8_t tid = hdr.GetQosTid();
1755 (tid2.has_value() && tid == *tid2),
1756 "QoS frame with unexpected TID " << +tid);
1759 auto findLinkSet = [
this,
dir](uint8_t tid) -> std::set<uint8_t> {
1764 if (
auto it = mappingOptRef->get().find(tid); it != mappingOptRef->get().cend())
1766 linkSet = it->second;
1767 NS_ASSERT_MSG(!linkSet.empty(),
"TID " << +tid <<
" mapped to no link");
1773 auto linkSet = findLinkSet(tid);
1780 std::size_t nConcurFrames = std::min(qosFrames.size(), linkSet.size());
1783 for (std::size_t i = 0; i < nConcurFrames; i++)
1785 auto prev = qosFrames[i];
1795 if (qosFrames.size() < linkSet.size())
1800 "The " <<
dir <<
" QoS frame number " << qosFrames.size()
1801 <<
" was not sent concurrently with others on link "
1802 << +linkId <<
" which TID " << +tid <<
" is mapped to");
1809 "The " <<
dir <<
" QoS frame number " << qosFrames.size()
1810 <<
" was sent concurrently with others on a link "
1811 << +linkId <<
" which TID " << +tid <<
" is mapped to");
1819 "QoS frame sent on Link ID "
1820 << +linkId <<
" that does not belong to the link set of TID "
1827 auto otherTid = (tid == tid1) ? *tid2 : tid1;
1829 auto otherLinkSet = findLinkSet(otherTid);
1832 std::size_t nOtherConcurFrames = std::min(otherQosFrames.size(), otherLinkSet.size());
1835 for (std::size_t i = 0; i < nOtherConcurFrames; i++)
1837 auto prev = otherQosFrames[i];
1847 if (qosFrames.size() < linkSet.size())
1852 "The " <<
dir <<
" QoS frame number " << qosFrames.size()
1853 <<
" was not sent concurrently with others with TID "
1860 qosFrames.emplace_back(index);
1943 uint8_t nMaxInflight);
1961 double txPowerW)
override;
1963 void DoRun()
override;
1990 uint8_t nMaxInflight)
1992 std::string(
"Check data transmission between MLDs ") +
1995 ?
"with BA agreement, send BAR after BlockAck timeout"
1996 :
"with BA agreement, send Data frames after BlockAck timeout")
1997 :
"without BA agreement") +
1998 " (Traffic pattern: " +
std::to_string(static_cast<uint8_t>(trafficPattern)) +
2004 m_trafficPattern(trafficPattern),
2007 m_nMaxInflight(nMaxInflight),
2025 auto psdu = psduMap.begin()->second;
2027 switch (psdu->GetHeader(0).GetType())
2032 psdu->GetHeader(0).GetAddr2() == psdu->GetHeader(0).GetAddr3() ?
DL :
UL);
2037 m_uidList.push_front(psdu->GetPacket()->GetUid());
2045 for (
const auto& mpdu : *psdu)
2051 mpdu->GetHeader().GetAddr2() &&
2052 !mpdu->GetHeader().GetAddr1().IsGroup())
2054 auto seqNo = mpdu->GetHeader().GetSequenceNumber();
2055 auto [it, success] =
2059 it->second = std::max(it->second, mpdu->GetInFlightLinkIds().size());
2063 for (std::size_t i = 0; i < psdu->GetNMpdus(); i++)
2069 if (psdu->GetHeader(i).GetSequenceNumber() != 1 ||
2076 auto uid = psdu->GetPayload(i)->GetUid();
2113 m_uidList.push_front(psdu->GetPacket()->GetUid());
2138 "No BlockAck expected in AP to broadcast traffic pattern");
2152 auto mpdu = *psdu->begin();
2154 mpdu->GetPacket()->PeekHeader(blockAck);
2155 bool isMpdu1corrupted = (
m_trafficPattern == WifiTrafficPattern::STA_TO_AP ||
2163 "MPDU 0 expected to be successfully received");
2167 "MPDU 1 expected to be received only in STA_TO_STA/STA_TO_BCAST scenarios");
2170 if (
m_staMacs[0]->GetSetupLinkIds().size() > 1)
2175 auto item = queue->PeekByTidAndAddress(0, rcvMac->GetAddress());
2176 std::size_t nQueuedPkt = 0;
2179 rcvMac->GetWifiPhy(linkId)->GetPhyBand()) +
2184 auto seqNo = item->GetHeader().GetSequenceNumber();
2187 "MPDU with seqNo=" << seqNo <<
" is not in flight");
2188 auto linkIds = item->GetInFlightLinkIds();
2191 "MPDU with seqNo=" << seqNo
2192 <<
" is in flight on multiple links");
2199 "Addr1 of BlockAck is not an originator's link address");
2202 "MPDU with seqNo=" << seqNo
2203 <<
" in flight on unexpected link");
2208 bool isQueued = (seqNo > (isMpdu1corrupted ? 0 : 1));
2212 bool isRetry = isQueued && seqNo <= 1;
2218 << item->GetHeader().GetSequenceNumber() <<
" should "
2219 << (isQueued ?
"" :
"not") <<
" be queued");
2221 item->GetHeader().IsRetry(),
2223 "Unexpected value for the Retry subfield of the MPDU with seqNo="
2224 << item->GetHeader().GetSequenceNumber());
2228 item = queue->PeekByTidAndAddress(0, rcvMac->GetAddress(), item);
2239 "Did not expect to receive a second BlockAck");
2241 std::pair<uint16_t, uint16_t> seqNos;
2246 if (
m_staMacs[0]->GetSetupLinkIds().size() > 1)
2256 "MPDU " << seqNos.first <<
" expected to be successfully received");
2259 "MPDU " << seqNos.second <<
" expected to be successfully received");
2275 mac->GetQosTxop(
AC_BE)->SetAttribute(
"UseExplicitBarAfterMissedBlockAck",
2284 auto errorModel = CreateObject<ListErrorModel>();
2288 for (std::size_t i : {0, 1})
2290 for (
const auto linkId :
m_staMacs[i]->GetLinkIds())
2292 auto errorModel = CreateObject<ListErrorModel>();
2294 m_staMacs[i]->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel);
2306 case WifiTrafficPattern::STA_TO_STA:
2308 destAddr =
m_staMacs[1]->GetDevice()->GetAddress();
2310 case WifiTrafficPattern::STA_TO_AP:
2314 case WifiTrafficPattern::AP_TO_STA:
2316 destAddr =
m_staMacs[1]->GetDevice()->GetAddress();
2318 case WifiTrafficPattern::AP_TO_BCAST:
2322 case WifiTrafficPattern::STA_TO_BCAST:
2354 std::array<std::size_t, 3> expectedRxPkts{};
2358 case WifiTrafficPattern::STA_TO_STA:
2359 case WifiTrafficPattern::AP_TO_STA:
2363 case WifiTrafficPattern::STA_TO_AP:
2367 case WifiTrafficPattern::AP_TO_BCAST:
2373 case WifiTrafficPattern::STA_TO_BCAST:
2383 "Unexpected number of packets received by the AP");
2386 "Unexpected number of packets received by STA 0");
2389 "Unexpected number of packets received by STA 1");
2394 std::size_t expectedBaCount = 0;
2395 std::size_t expectedBarCount = 0;
2399 case WifiTrafficPattern::STA_TO_AP:
2400 case WifiTrafficPattern::AP_TO_STA:
2402 expectedBaCount = 3;
2406 case WifiTrafficPattern::STA_TO_STA:
2407 case WifiTrafficPattern::STA_TO_BCAST:
2409 expectedBaCount = 1;
2415 "Unexpected number of BlockAck frames");
2418 "Unexpected number of BlockAckReq frames");
2429 "Did not collect number of simultaneous transmissions for all data frames");
2432 std::size_t maxCount = 0;
2438 "MPDU with seqNo=" << seqNo
2439 <<
" transmitted simultaneously more times than allowed");
2440 maxCount = std::max(maxCount, count);
2446 "Expected that at least one data frame was transmitted simultaneously a number of "
2447 "times equal to the NMaxInflights attribute");
2502 uint8_t nMaxInflight);
2520 double txPowerW)
override;
2522 void DoRun()
override;
2555 uint8_t nMaxInflight)
2557 std::string(
"Check MU data transmission between MLDs ") +
2559 ?
"(send BAR after BlockAck timeout,"
2560 :
"(send Data frames after BlockAck timeout,") +
2561 " MU Traffic pattern: " +
std::to_string(static_cast<uint8_t>(muTrafficPattern)) +
2562 ", nMaxInflight=" +
std::to_string(nMaxInflight) +
")",
2565 m_muTrafficPattern(muTrafficPattern),
2567 m_nMaxInflight(nMaxInflight),
2568 m_sockets(m_nStations),
2585 for (
const auto& [staId, psdu] : psduMap)
2587 switch (psdu->GetHeader(0).GetType())
2591 if (psdu->GetHeader(0).HasData())
2593 bool isDl = psdu->GetHeader(0).IsFromDs();
2595 isDl ? psdu->GetHeader(0).GetAddr1() : psdu->GetHeader(0).GetAddr2();
2598 for (
const auto& mpdu : *psdu)
2601 auto seqNo = mpdu->GetHeader().GetSequenceNumber();
2603 {{address, seqNo}, mpdu->GetInFlightLinkIds().size()});
2606 it->second = std::max(it->second, mpdu->GetInFlightLinkIds().size());
2609 for (std::size_t i = 0; i < psdu->GetNMpdus(); i++)
2612 if (psdu->GetHeader(i).GetSequenceNumber() == 2)
2618 "MPDU " << **std::next(psdu->begin(), i)
2619 <<
" not transmitted in a TB PPDU");
2625 "MPDU " << **std::next(psdu->begin(), i)
2626 <<
" not transmitted in a DL MU PPDU");
2630 if (psdu->GetHeader(i).GetSequenceNumber() != 3)
2634 auto uid = psdu->GetPayload(i)->GetUid();
2671 m_uidList.push_front(psdu->GetPacket()->GetUid());
2677 psdu->GetPayload(0)->PeekHeader(trigger);
2686 auto band = mac->GetWifiPhy(linkId)->GetPhyBand();
2690 m_staMacs[i]->GetDevice()->GetNode()->AddApplication(
2699 muScheduler->SetAttribute(
"EnableUlOfdma",
BooleanValue(
false));
2746 auto mpdu = *psdu->begin();
2748 mpdu->GetPacket()->PeekHeader(blockAck);
2749 bool isMpdu3corrupted;
2764 auto index = indices.front();
2767 "Expected that a QoS data frame was corrupted");
2769 m_staMacs[i]->GetLinkIdByAddress(*m_dataCorruptedSta).has_value();
2772 "MPDU 2 expected to be successfully received");
2775 "Unexpected reception status for MPDU 3");
2785 "MPDU 2 expected to be successfully received");
2788 "Unexpected reception status for MPDU 3");
2792 m_staMacs[0]->GetSetupLinkIds().size() > 1)
2796 if (
m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress() ==
2797 mpdu->GetHeader().GetAddr2())
2801 else if (
m_staMacs[1]->GetFrameExchangeManager(linkId)->GetAddress() ==
2802 mpdu->GetHeader().GetAddr2())
2808 NS_ABORT_MSG(
"BlockAck frame not sent by a station in DL scenario");
2810 auto item = queue->PeekByTidAndAddress(0, rcvMac->GetAddress());
2811 std::size_t nQueuedPkt = 0;
2814 rcvMac->GetWifiPhy(linkId)->GetPhyBand()) +
2819 auto seqNo = item->GetHeader().GetSequenceNumber();
2822 "MPDU with seqNo=" << seqNo <<
" is not in flight");
2823 auto linkIds = item->GetInFlightLinkIds();
2826 "MPDU with seqNo=" << seqNo
2827 <<
" is in flight on multiple links");
2834 "Addr1 of BlockAck is not an originator's link address");
2837 "MPDU with seqNo=" << seqNo
2838 <<
" in flight on unexpected link");
2843 bool isQueued = (seqNo > (isMpdu3corrupted ? 2 : 3));
2847 bool isRetry = isQueued && seqNo <= 3;
2853 << item->GetHeader().GetSequenceNumber() <<
" should "
2854 << (isQueued ?
"" :
"not") <<
" be queued");
2856 item->GetHeader().IsRetry(),
2858 "Unexpected value for the Retry subfield of the MPDU with seqNo="
2859 << item->GetHeader().GetSequenceNumber());
2863 item = queue->PeekByTidAndAddress(0, rcvMac->GetAddress(), item);
2877 case WifiMuTrafficPattern::DL_MU_BAR_BA_SEQUENCE:
2881 case WifiMuTrafficPattern::DL_MU_MU_BAR:
2885 case WifiMuTrafficPattern::DL_MU_AGGR_MU_BAR:
2898 mac->GetQosTxop(
AC_BE)->SetAttribute(
"UseExplicitBarAfterMissedBlockAck",
2903 mac->GetQosTxop(
AC_VI)->SetAttribute(
"UseExplicitBarAfterMissedBlockAck",
2909 auto muScheduler = CreateObjectWithAttributes<RrMultiUserScheduler>(
"EnableUlOfdma",
2920 auto errorModel = CreateObject<ListErrorModel>();
2924 for (std::size_t i : {0, 1})
2926 for (
const auto linkId :
m_staMacs[i]->GetLinkIds())
2928 auto errorModel = CreateObject<ListErrorModel>();
2930 m_staMacs[i]->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel);
2980 m_staMacs[i]->GetDevice()->GetNode()->AddApplication(
2991 muScheduler->SetAttribute(
"EnableUlOfdma",
BooleanValue(
true));
2994 muScheduler->SetAccessReqInterval(
Seconds(0));
3007 std::array<std::size_t, 3> expectedRxPkts{};
3011 case WifiMuTrafficPattern::DL_MU_BAR_BA_SEQUENCE:
3012 case WifiMuTrafficPattern::DL_MU_MU_BAR:
3013 case WifiMuTrafficPattern::DL_MU_AGGR_MU_BAR:
3018 case WifiMuTrafficPattern::UL_MU:
3026 "Unexpected number of packets received by the AP");
3029 "Unexpected number of packets received by STA 0");
3032 "Unexpected number of packets received by STA 1");
3040 "Did not collect number of simultaneous transmissions for all data frames");
3043 std::size_t maxCount = 0;
3049 << txSeqNoPair.second
3050 <<
" transmitted simultaneously more times than allowed");
3051 maxCount = std::max(maxCount, count);
3057 "Expected that at least one data frame was transmitted simultaneously a number of "
3058 "times equal to the NMaxInflights attribute");
3089 void DoRun()
override;
3094 double txPowerW)
override;
3107 "Check sequence numbers after CTS timeout",
3109 BaseParams{{
"{36, 0, BAND_5GHZ, 0}",
"{2, 0, BAND_2_4GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}"},
3110 {
"{36, 0, BAND_5GHZ, 0}",
"{2, 0, BAND_2_4GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}"},
3112 m_nQosDataFrames(0),
3113 m_errorModel(CreateObject<ListErrorModel>()),
3114 m_rtsCorrupted(
false)
3127 for (
const auto linkId :
m_staMacs[0]->GetLinkIds())
3153 auto psdu = psduMap.begin()->second;
3162 else if (psdu->GetHeader(0).IsQosData())
3182 std::size_t count{};
3186 auto psdu = txPsdu.psduMap.begin()->second;
3188 if (!psdu->GetHeader(0).IsQosData())
3196 uint16_t expectedSeqNo{};
3215 "Unexpected sequence number");
3238 std::vector<uint8_t>,
3246 for (
const auto& [baseParams,
3253 {{
"{36, 0, BAND_5GHZ, 0}",
"{2, 0, BAND_2_4GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}"},
3254 {
"{36, 0, BAND_5GHZ, 0}",
"{2, 0, BAND_2_4GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}"},
3257 WifiTidToLinkMappingNegSupport::NOT_SUPPORTED,
3259 "0,1,2,3 0,1,2; 4,5 0,1",
3260 "0,1,2,3 1,2; 6,7 0,1"
3263 ParamsTuple({{
"{108, 0, BAND_5GHZ, 0}",
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}"},
3264 {
"{36, 0, BAND_5GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}",
"{5, 0, BAND_6GHZ, 0}"},
3267 WifiTidToLinkMappingNegSupport::SAME_LINK_SET,
3269 "0,1,2,3 0,1,2; 4,5 0,1",
3272 ParamsTuple({{
"{2, 0, BAND_2_4GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{36, 0, BAND_5GHZ, 0}"},
3273 {
"{36, 0, BAND_5GHZ, 0}",
"{9, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
3276 WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
3277 "0,1,2,3 0; 4,5,6,7 1,2",
3278 "0,2,3 1,2; 1,4,5,6,7 0"
3283 {{
"{2, 0, BAND_2_4GHZ, 0}",
"{36, 0, BAND_5GHZ, 0}",
"{8, 20, BAND_2_4GHZ, 0}"},
3284 {
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
3287 WifiTidToLinkMappingNegSupport::SAME_LINK_SET,
3289 "0,1,2,3,4,5,6,7 0",
3290 "0,1,2,3,4,5,6,7 0"),
3295 {{
"{2, 0, BAND_2_4GHZ, 0}",
"{36, 0, BAND_5GHZ, 0}",
"{8, 20, BAND_2_4GHZ, 0}"},
3296 {
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
3299 WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
3307 ParamsTuple({{
"{2, 0, BAND_2_4GHZ, 0}",
"{36, 0, BAND_5GHZ, 0}",
"{60, 0, BAND_5GHZ, 0}"},
3308 {
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
3311 WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
3317 ParamsTuple({{
"{2, 0, BAND_2_4GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
3318 {
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
3321 WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
3325 ParamsTuple({{
"{2, 0, BAND_2_4GHZ, 0}",
"{36, 0, BAND_5GHZ, 0}"},
3326 {
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
3329 WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
3333 ParamsTuple({{
"{120, 0, BAND_5GHZ, 0}"},
3334 {
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
3337 WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
3341 ParamsTuple({{
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
3342 {
"{120, 0, BAND_5GHZ, 0}"},
3345 WifiTidToLinkMappingNegSupport::NOT_SUPPORTED,
3346 "0,1,2,3 0,1; 4,5,6,7 0,1",
3350 WifiScanType::PASSIVE,
3355 TestCase::Duration::QUICK);
3357 WifiScanType::ACTIVE,
3362 TestCase::Duration::QUICK);
3364 for (
const auto& trafficPattern : {WifiTrafficPattern::STA_TO_STA,
3365 WifiTrafficPattern::STA_TO_AP,
3366 WifiTrafficPattern::AP_TO_STA,
3367 WifiTrafficPattern::AP_TO_BCAST,
3368 WifiTrafficPattern::STA_TO_BCAST})
3374 WifiUseBarAfterMissedBa::NO,
3376 TestCase::Duration::QUICK);
3377 for (
const auto& useBarAfterMissedBa :
3378 {WifiUseBarAfterMissedBa::YES, WifiUseBarAfterMissedBa::NO})
3384 useBarAfterMissedBa,
3386 TestCase::Duration::QUICK);
3391 useBarAfterMissedBa,
3393 TestCase::Duration::QUICK);
3397 for (
const auto& muTrafficPattern : {WifiMuTrafficPattern::DL_MU_BAR_BA_SEQUENCE,
3398 WifiMuTrafficPattern::DL_MU_MU_BAR,
3399 WifiMuTrafficPattern::DL_MU_AGGR_MU_BAR,
3400 WifiMuTrafficPattern::UL_MU})
3402 for (
const auto& useBarAfterMissedBa :
3403 {WifiUseBarAfterMissedBa::YES, WifiUseBarAfterMissedBa::NO})
3408 TestCase::Duration::QUICK);
3412 TestCase::Duration::QUICK);
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
void DoCompleteConfig() override
Allow subclasses to complete the configuration of the MAC layer components.
~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_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
~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 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
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
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.
MultiLinkSetupTest(const BaseParams &baseParams, WifiScanType scanType, const std::vector< uint8_t > &setupLinks, WifiTidToLinkMappingNegSupport apNegSupport, const std::string &dlTidToLinkMapping, const std::string &ulTidToLinkMapping)
Constructor.
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 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.
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, 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.
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
Ptr< WifiMacQueueScheduler > GetMacQueueScheduler() const
Get the wifi MAC queue scheduler.
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.
@ 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::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...
WifiTidToLinkMappingNegSupport
TID-to-Link Mapping Negotiation Support.
std::tuple< WifiContainerQueueType, WifiReceiverAddressType, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, receiver address type, Address, TID) identifying a container queue.
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.
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.