11#include "ns3/config.h"
12#include "ns3/eht-configuration.h"
13#include "ns3/ht-frame-exchange-manager.h"
15#include "ns3/mgt-action-headers.h"
16#include "ns3/mgt-headers.h"
17#include "ns3/mobility-helper.h"
18#include "ns3/multi-link-element.h"
19#include "ns3/node-list.h"
20#include "ns3/packet-socket-helper.h"
21#include "ns3/packet.h"
22#include "ns3/pointer.h"
23#include "ns3/rng-seed-manager.h"
24#include "ns3/rr-multi-user-scheduler.h"
25#include "ns3/spectrum-wifi-phy.h"
26#include "ns3/string.h"
27#include "ns3/vht-configuration.h"
28#include "ns3/wifi-acknowledgment.h"
29#include "ns3/wifi-assoc-manager.h"
30#include "ns3/wifi-mac-header.h"
31#include "ns3/wifi-mac-queue.h"
32#include "ns3/wifi-net-device.h"
33#include "ns3/wifi-protection.h"
46 :
TestCase(
"Check the implementation of WifiAssocManager::GetNextAffiliatedAp()")
120 "Unexpected neighbor ID of the second reported AP");
123 "Unexpected tbtt ID of the second reported AP");
129 "Did not expect to find a third suitable reported AP");
136 auto apIt = allAps.begin();
139 "Unexpected neighbor ID of the first reported AP");
142 "Unexpected tbtt ID of the first reported AP");
147 "Unexpected neighbor ID of the second reported AP");
150 "Unexpected tbtt ID of the second reported AP");
158 .SetGroupName(
"Wifi")
164 :
TestCase(
"Test the WifiMac::SwapLinks() method")
171 const std::map<uint8_t, uint8_t>& links,
172 const std::map<uint8_t, uint8_t>& expected)
179 std::vector<Ptr<WifiPhy>> phys;
180 std::vector<Ptr<FrameExchangeManager>> feManagers;
182 for (std::size_t i = 0; i < nLinks; ++i)
186 phys.emplace_back(phy);
189 mac->SetWifiPhys(phys);
190 mac->SetFrameExchangeManagers(feManagers);
191 mac->GetTxop()->SetWifiMac(mac);
194 for (std::size_t
id = 0;
id < nLinks; ++id)
196 mac->GetTxop()->SetMinCw(
id,
id);
199 mac->SwapLinks(links);
203 for (
const auto& [linkId, phyId] : expected)
207 "Link ID " << +linkId <<
" does not exist");
214 text <<
": Link " << +phyId <<
" has not been moved to link "
221 text <<
": Link ID stored by FrameExchangeManager has not been updated");
225 text <<
": Txop Link entity " << +phyId
226 <<
" has not been moved to link " << +linkId);
235 RunOne(
"No change needed", 3, {{0, 0}, {1, 1}, {2, 2}}, {{0, 0}, {1, 1}, {2, 2}});
236 RunOne(
"Circular swapping", 3, {{0, 2}, {1, 0}, {2, 1}}, {{0, 1}, {1, 2}, {2, 0}});
237 RunOne(
"Swapping two links, one unchanged", 3, {{0, 2}, {2, 0}}, {{0, 2}, {1, 1}, {2, 0}});
238 RunOne(
"Non-circular swapping, autodetect how to close the loop",
241 {{0, 1}, {1, 2}, {2, 0}});
242 RunOne(
"A different non-circular swapping, same result",
245 {{0, 1}, {1, 2}, {2, 0}});
246 RunOne(
"One move only, autodetect how to complete the swapping",
249 {{0, 2}, {1, 1}, {2, 0}});
250 RunOne(
"Create a new link ID (2), remove the unused one (0)",
254 RunOne(
"One move only that creates a new link ID (2)", 2, {{0, 2}}, {{1, 1}, {2, 0}});
255 RunOne(
"Move all links to a new set of IDs", 2, {{0, 2}, {1, 3}}, {{2, 0}, {3, 1}});
259 :
TestCase(
"Test the assignment of AIDs"),
260 m_linkChannels({
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{2, 0, BAND_2_4GHZ, 0}"}),
271 int64_t streamNumber{1};
274 wifiApNode.Create(1);
279 wifi.SetRemoteStationManager(
"ns3::ConstantRateWifiManager",
299 mac.SetType(
"ns3::ApWifiMac",
305 auto apDevice = wifi.Install(phyHelper, mac, wifiApNode);
314 for (
const auto&
id : links)
322 mac.SetType(
"ns3::StaWifiMac",
329 auto staDevice = wifi.Install(phyHelper, mac, staNode);
330 wifiStaNodes.Add(staNode);
339 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
341 mobility.SetPositionAllocator(positionAlloc);
342 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
343 mobility.Install(wifiApNode);
344 mobility.Install(wifiStaNodes);
349 mac->TraceConnectWithoutContext(
358 const auto aid = staMac->GetAssociationId();
360 std::stringstream linksStr;
361 const auto setupLinks = staMac->GetSetupLinkIds();
362 std::copy(setupLinks.cbegin(), setupLinks.cend(), std::ostream_iterator<int>(linksStr,
" "));
364 NS_LOG_INFO(
"STA " << staMac->GetAddress() <<
" associated with AID " << aid <<
" links "
374 "Unexpected set of setup links " << linksStr.str());
382 ->SetSsid(
Ssid(
"ns-3-ssid"));
402 mac->TraceDisconnectWithoutContext(
414 m_staChannels(baseParams.staChannels),
415 m_apChannels(baseParams.apChannels),
416 m_fixedPhyBands(baseParams.fixedPhyBands),
417 m_staMacs(nStations),
418 m_nStations(nStations),
420 m_rxPkts(nStations + 1)
426 std::optional<Direction> direction)
428 std::optional<Mac48Address> apAddr;
429 std::optional<Mac48Address> staAddr;
432 if (psdu->GetHeader(0).IsQosData())
434 direction = (!psdu->GetHeader(0).IsToDs() && psdu->GetHeader(0).IsFromDs()) ?
DL :
UL;
440 if (!psdu->GetAddr1().IsGroup())
442 staAddr = psdu->GetAddr1();
444 apAddr = psdu->GetAddr2();
448 if (!psdu->GetAddr1().IsGroup())
450 apAddr = psdu->GetAddr1();
452 staAddr = psdu->GetAddr2();
458 for (uint8_t linkId = 0; linkId <
m_apMac->GetNLinks(); linkId++)
460 if (
m_apMac->GetFrameExchangeManager(linkId)->GetAddress() == *apAddr)
468 "Address " << *apAddr <<
" is not an AP device address. "
469 <<
"PSDU: " << *psdu);
477 for (
const auto& linkId :
m_staMacs[i]->GetLinkIds())
479 if (
m_staMacs[i]->GetFrameExchangeManager(linkId)->GetAddress() == *staAddr)
492 "Address " << *staAddr <<
" is not a STA device address. "
493 <<
"PSDU: " << *psdu);
504 auto linkId = mac->GetLinkForPhy(phyId);
508 for (
const auto& [aid, psdu] : psduMap)
510 std::stringstream ss;
511 ss << std::setprecision(10) <<
"PSDU #" <<
m_txPsdus.size() <<
" Link ID "
512 << +linkId.value() <<
" Phy ID " << +phyId <<
" #MPDUs " << psdu->GetNMpdus();
513 for (
auto it = psdu->begin(); it != psdu->end(); ++it)
527 auto band = mac->GetDevice()->GetPhy(phyId)->GetPhyBand();
528 bool hasHtCapabilities;
529 bool hasVhtCapabilities;
530 bool hasHeCapabilities;
531 bool hasHe6GhzCapabilities;
532 bool hasEhtCapabilities;
534 auto findCapabilities = [&](
auto&& frame) {
535 hasHtCapabilities = frame.template Get<HtCapabilities>().has_value();
536 hasVhtCapabilities = frame.template Get<VhtCapabilities>().has_value();
537 hasHeCapabilities = frame.template Get<HeCapabilities>().has_value();
538 hasHe6GhzCapabilities = frame.template Get<He6GhzBandCapabilities>().has_value();
539 hasEhtCapabilities = frame.template Get<EhtCapabilities>().has_value();
542 switch (mpdu->GetHeader().GetType())
546 mpdu->GetPacket()->PeekHeader(beacon);
547 findCapabilities(beacon);
553 mpdu->GetPacket()->PeekHeader(probeReq);
554 findCapabilities(probeReq);
560 mpdu->GetPacket()->PeekHeader(probeResp);
561 findCapabilities(probeResp);
567 mpdu->GetPacket()->PeekHeader(assocReq);
568 findCapabilities(assocReq);
574 mpdu->GetPacket()->PeekHeader(assocResp);
575 findCapabilities(assocResp);
586 "HT Capabilities should not be present in a mgt frame sent in 6 GHz band");
590 "VHT Capabilities should only be present in a mgt frame sent in 5 GHz band");
593 "HE Capabilities should always be present in a mgt frame");
595 hasHe6GhzCapabilities,
597 "HE 6GHz Band Capabilities should only be present in a mgt frame sent in 6 GHz band");
600 "EHT Capabilities should always be present in a mgt frame");
606 NS_LOG_INFO(
"Packet received by NODE " << +nodeId <<
"\n");
612 const std::vector<std::string>& channels,
620 for (
const auto& str : channels)
627 for (
const auto& [band, channel] : channelMap)
638 int64_t streamNumber = 30;
641 wifiApNode.Create(1);
649 wifi.SetRemoteStationManager(
"ns3::ConstantRateWifiManager",
670 mac.SetType(
"ns3::StaWifiMac",
676 mac.SetType(
"ns3::ApWifiMac",
695 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
696 positionAlloc->Add(Vector(1.0, 0.0, 0.0));
697 mobility.SetPositionAllocator(positionAlloc);
699 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
700 mobility.Install(wifiApNode);
701 mobility.Install(wifiStaNodes);
711 for (uint8_t phyId = 0; phyId <
m_apMac->GetDevice()->GetNPhys(); phyId++)
714 "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phys/" + std::to_string(phyId) +
720 for (uint8_t phyId = 0; phyId <
m_staMacs[i]->GetDevice()->GetNPhys(); phyId++)
723 "/DeviceList/*/$ns3::WifiNetDevice/Phys/" +
724 std::to_string(phyId) +
"/PhyTxPsduBegin",
732 packetSocket.
Install(wifiApNode);
733 packetSocket.
Install(wifiStaNodes);
745 server->SetLocal(srvAddr);
746 (*nodeIt)->AddApplication(server);
747 server->SetStartTime(
Seconds(0));
754 "/NodeList/" + std::to_string(nodeId) +
755 "/ApplicationList/*/$ns3::PacketSocketServer/Rx",
760 m_apMac->TraceConnectWithoutContext(
"AssociatedSta",
770 uint8_t priority)
const
777 client->SetRemote(sockAddr);
778 client->SetStartTime(delay);
806 const std::vector<uint8_t>& setupLinks,
808 const std::string& dlTidToLinkMapping,
809 const std::string& ulTidToLinkMapping,
810 bool support160MHzOp)
812 m_setupLinks(setupLinks),
813 m_scanType(scanType),
815 m_apNegSupport(apNegSupport),
816 m_dlTidLinkMappingStr(dlTidToLinkMapping),
817 m_ulTidLinkMappingStr(ulTidToLinkMapping),
818 m_support160MHzOp(support160MHzOp)
828 m_apMac->GetEhtConfiguration()->SetAttribute(
"TidToLinkMappingNegSupport",
832 auto staEhtConfig =
m_staMacs[0]->GetEhtConfiguration();
833 staEhtConfig->SetAttribute(
"TidToLinkMappingNegSupport",
834 EnumValue(WifiTidToLinkMappingNegSupport::ANY_LINK_SET));
845 if (
m_apNegSupport == WifiTidToLinkMappingNegSupport::NOT_SUPPORTED ||
846 (
m_apNegSupport == WifiTidToLinkMappingNegSupport::SAME_LINK_SET &&
854 using TupleRefs = std::tuple<std::reference_wrapper<const WifiTidLinkMapping>,
855 std::reference_wrapper<uint8_t>,
856 std::reference_wrapper<std::optional<uint8_t>>,
858 for (
auto& [mappingRef, tid1Ref, tid2Ref, mac] :
863 for (uint8_t tid1 = 0; tid1 < 8; tid1++)
865 if (
auto it1 = mappingRef.get().find(tid1);
866 it1 != mappingRef.get().cend() && it1->second.size() !=
m_setupLinks.size())
869 for (uint8_t tid2 = tid1 + 1; tid2 < 8; tid2++)
871 if (
auto it2 = mappingRef.get().find(tid2);
872 it2 != mappingRef.get().cend() && it2->second.size() !=
m_setupLinks.size())
874 std::list<uint8_t> intersection;
875 std::set_intersection(it1->second.cbegin(),
877 it2->second.cbegin(),
879 std::back_inserter(intersection));
880 if (intersection.empty())
883 tid2Ref.get() = tid2;
888 tid1Ref.get() = tid1;
893 std::list<uint8_t> tids = {tid1Ref.get()};
896 tids.emplace_back(*tid2Ref.get());
900 for (
auto tid : tids)
902 std::string attrName;
906 attrName =
"VI_MaxAmpduSize";
909 attrName =
"VO_MaxAmpduSize";
912 attrName =
"BE_MaxAmpduSize";
915 attrName =
"BK_MaxAmpduSize";
929 staMac->GetVhtConfiguration()->SetAttribute(
"Support160MHzOperation",
934 staMac->GetWifiPhy(linkId++)->SetAttribute(
"ChannelSettings",
StringValue(str));
949 m_apMac->GetDevice()->GetNode()->AddApplication(
953 m_apMac->GetDevice()->GetNode()->AddApplication(
965 m_staMacs[0]->GetDevice()->GetNode()->AddApplication(
969 m_staMacs[0]->GetDevice()->GetNode()->AddApplication(
986 std::size_t index = 0;
990 const auto& mpdu = *frameInfo.psduMap.begin()->second->begin();
991 const auto& linkId = frameInfo.linkId;
993 switch (mpdu->GetHeader().GetType())
1025 std::size_t expectedProbeResp = 0;
1034 if (staChannel == apChannel)
1036 expectedProbeResp++;
1048 expectedRxDlPkts *= 2;
1052 "Unexpected number of DL packets received");
1057 expectedRxUlPkts *= 2;
1061 "Unexpected number of UL packets received");
1074 mpdu->GetHeader().GetAddr2(),
1075 "TA of Beacon frame is not the address of the link it is transmitted on");
1077 mpdu->GetPacket()->PeekHeader(beacon);
1081 if (
m_apMac->GetNLinks() == 1)
1085 "RNR Element in Beacon frame from single link AP");
1088 "Multi-Link Element in Beacon frame from single link AP");
1096 static_cast<std::size_t
>(
m_apMac->GetNLinks() - 1),
1097 "Unexpected number of Neighbor AP Info fields in RNR");
1098 for (std::size_t nbrApInfoId = 0; nbrApInfoId < rnr->GetNNbrApInfoFields(); nbrApInfoId++)
1102 "MLD Parameters not present");
1105 "Expected only one TBTT Info subfield per Neighbor AP Info");
1106 uint8_t nbrLinkId = rnr->GetLinkId(nbrApInfoId, 0);
1108 m_apMac->GetFrameExchangeManager(nbrLinkId)->GetAddress(),
1109 "BSSID advertised in Neighbor AP Info field "
1111 <<
" does not match the address configured on the link "
1112 "advertised in the same field");
1118 "Incorrect MLD address advertised in Multi-Link Element");
1121 "Incorrect Link ID advertised in Multi-Link Element");
1132 m_apMac->GetFrameExchangeManager(linkId)->GetAddress(),
1133 mpdu->GetHeader().GetAddr2(),
1134 "TA of Probe Response is not the address of the link it is transmitted on");
1136 mpdu->GetPacket()->PeekHeader(probeResp);
1140 if (
m_apMac->GetNLinks() == 1)
1144 "RNR Element in Probe Response frame from single link AP");
1147 "Multi-Link Element in Probe Response frame from single link AP");
1155 static_cast<std::size_t
>(
m_apMac->GetNLinks() - 1),
1156 "Unexpected number of Neighbor AP Info fields in RNR");
1157 for (std::size_t nbrApInfoId = 0; nbrApInfoId < rnr->GetNNbrApInfoFields(); nbrApInfoId++)
1161 "MLD Parameters not present");
1164 "Expected only one TBTT Info subfield per Neighbor AP Info");
1165 uint8_t nbrLinkId = rnr->GetLinkId(nbrApInfoId, 0);
1167 m_apMac->GetFrameExchangeManager(nbrLinkId)->GetAddress(),
1168 "BSSID advertised in Neighbor AP Info field "
1170 <<
" does not match the address configured on the link "
1171 "advertised in the same field");
1177 "Incorrect MLD address advertised in Multi-Link Element");
1180 "Incorrect Link ID advertised in Multi-Link Element");
1191 m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress(),
1192 mpdu->GetHeader().GetAddr2(),
1193 "TA of Assoc Request frame is not the address of the link it is transmitted on");
1195 mpdu->GetPacket()->PeekHeader(assoc);
1202 "Multi-Link Element in Assoc Request frame from single link STA");
1208 "No Multi-Link Element in Assoc Request frame");
1211 "Incorrect MLD Address advertised in Multi-Link Element");
1213 mle->GetNPerStaProfileSubelements(),
1215 "Incorrect number of Per-STA Profile subelements in Multi-Link Element");
1216 for (std::size_t i = 0; i < mle->GetNPerStaProfileSubelements(); i++)
1218 auto& perStaProfile = mle->GetPerStaProfile(i);
1221 "Per-STA Profile must contain STA MAC address");
1223 auto staLinkId =
m_staMacs[0]->GetLinkIdByAddress(perStaProfile.GetStaMacAddress());
1225 staLinkId.has_value(),
1227 "No link found with the STA MAC address advertised in Per-STA Profile");
1231 "The STA that sent the Assoc Request should not be included in a Per-STA Profile");
1235 "Not expecting to setup STA link ID " << +staLinkId.value());
1238 +perStaProfile.GetLinkId(),
1239 "Not expecting to request association to AP Link ID in Per-STA Profile");
1242 "Missing Association Request in Per-STA Profile");
1256 "Didn't expect a TID-to-Link Mapping IE in Assoc Request frame");
1264 "Unexpected number of TID-to-Link Mapping IE in Assoc Request");
1269 +
static_cast<uint8_t
>(
dir),
1270 "Unexpected direction in TID-to-Link Mapping IE " << tlmId);
1271 auto& expectedMapping =
1275 expectedMapping.empty(),
1276 "Default Link Mapping bit not set correctly");
1278 expectedMapping.size(),
1279 "Unexpected number of Link Mapping Of TID n fields");
1280 for (uint8_t tid = 0; tid < 8; tid++)
1282 if (
auto it = expectedMapping.find(tid); it != expectedMapping.cend())
1286 "Unexpected link mapping for TID "
1287 << +tid <<
" direction " <<
dir);
1293 "Expecting no Link Mapping Of TID n field for TID "
1294 << +tid <<
" direction " <<
dir);
1299 if (tlm.size() == 1)
1301 checkTlm(0, WifiDirection::BOTH_DIRECTIONS);
1305 std::size_t dlId = (tlm[0].m_control.direction == WifiDirection::DOWNLINK ? 0 : 1);
1306 std::size_t ulId = (dlId == 0 ? 1 : 0);
1308 checkTlm(dlId, WifiDirection::DOWNLINK);
1309 checkTlm(ulId, WifiDirection::UPLINK);
1322 m_apMac->GetFrameExchangeManager(linkId)->GetAddress(),
1323 mpdu->GetHeader().GetAddr2(),
1324 "TA of Assoc Response frame is not the address of the link it is transmitted on");
1326 mpdu->GetPacket()->PeekHeader(assoc);
1334 "Multi-Link Element in Assoc Response frame with single link AP or single link STA");
1341 "Incorrect MLD Address advertised in Multi-Link Element");
1344 "Incorrect number of Per-STA Profile subelements in Multi-Link Element");
1345 for (std::size_t i = 0; i < mle->GetNPerStaProfileSubelements(); i++)
1347 auto& perStaProfile = mle->GetPerStaProfile(i);
1350 "Per-STA Profile must contain STA MAC address");
1352 auto apLinkId =
m_apMac->GetLinkIdByAddress(perStaProfile.GetStaMacAddress());
1354 apLinkId.has_value(),
1356 "No link found with the STA MAC address advertised in Per-STA Profile");
1358 +perStaProfile.GetLinkId(),
1359 "Link ID and MAC address advertised in Per-STA Profile do not match");
1363 "The AP that sent the Assoc Response should not be included in a Per-STA Profile");
1367 "Not expecting to setup AP link ID " << +apLinkId.value());
1370 "Missing Association Response in Per-STA Profile");
1377 "Didn't expect to find a TID-to-Link Mapping IE in Association Response");
1393 auto staAddr =
m_staMacs[0]->GetFrameExchangeManager(staLinkId)->GetAddress();
1394 auto apAddr =
m_apMac->GetFrameExchangeManager(apLinkId)->GetAddress();
1396 auto staRemoteMgr =
m_staMacs[0]->GetWifiRemoteStationManager(staLinkId);
1397 auto apRemoteMgr =
m_apMac->GetWifiRemoteStationManager(apLinkId);
1402 "Unexpected BSSID for STA link ID " << +staLinkId);
1407 "Incorrect MLD address stored by STA on link ID " << +staLinkId);
1409 (staRemoteMgr->GetAffiliatedStaAddress(
m_apMac->GetAddress()) == apAddr),
1411 "Incorrect affiliated address stored by STA on link ID " << +staLinkId);
1417 "Expecting STA " << staAddr <<
" to be associated on link "
1422 (apRemoteMgr->GetMldAddress(staAddr) ==
m_staMacs[0]->GetAddress()),
1424 "Incorrect MLD address stored by AP on link ID " << +apLinkId);
1426 (apRemoteMgr->GetAffiliatedStaAddress(
m_staMacs[0]->GetAddress()) == staAddr),
1428 "Incorrect affiliated address stored by AP on link ID " << +apLinkId);
1430 auto aid =
m_apMac->GetAssociationId(staAddr, apLinkId);
1431 const auto& staList =
m_apMac->GetStaList(apLinkId);
1434 "STA " << staAddr <<
" not found in list of associated STAs");
1438 const auto& staChannel =
m_staMacs[0]->GetWifiPhy(staLinkId)->GetOperatingChannel();
1439 const auto& apChannel =
m_apMac->GetWifiPhy(apLinkId)->GetOperatingChannel();
1441 auto width = apChannel.GetTotalWidth();
1442 auto primary20 = apChannel.GetPrimaryChannelIndex(20);
1447 primary20 -= apChannel.GetPrimaryChannelIndex(80) * 4;
1452 "Incorrect operating channel number for STA on link " << +staLinkId);
1454 apChannel.GetPrimaryChannelCenterFrequency(width),
1455 "Incorrect operating channel frequency for STA on link "
1459 "Incorrect operating channel width for STA on link " << +staLinkId);
1461 +apChannel.GetPhyBand(),
1462 "Incorrect operating PHY band for STA on link " << +staLinkId);
1465 "Incorrect operating primary channel index for STA on link "
1470 auto checkStoredMapping =
1474 "Link mapping stored by "
1475 << (mac->GetTypeOfStation() ==
AP ?
"AP" :
"non-AP")
1476 <<
" MLD for " <<
dir <<
" direction "
1477 << (present ?
"expected" :
"not expected"));
1480 const auto& mapping =
1483 (mac->GetTidToLinkMapping(dest->GetAddress(),
dir)->get() == mapping),
1485 "Incorrect link mapping stored by "
1486 << (mac->GetTypeOfStation() ==
AP ?
"AP" :
"non-AP") <<
" MLD for " <<
dir
1491 for (uint8_t tid = 0; tid < 8; ++tid)
1493 const auto& linkSet = mapping.contains(tid) ? mapping.at(tid) : setupLinks;
1495 for (
const auto linkId : setupLinks)
1498 mac->TidMappedOnLink(dest->GetAddress(),
dir, tid, linkId),
1499 linkSet.contains(linkId),
1500 "Incorrect return value on " << (mac ==
m_apMac ?
"AP" :
"STA")
1501 <<
" direction " <<
dir <<
" TID " << +tid
1502 <<
" linkID " << +linkId);
1508 auto storedMapping =
m_apMac->GetNLinks() > 1 &&
m_staMacs[0]->GetNLinks() > 1 &&
1510 checkStoredMapping(
m_apMac,
m_staMacs[0], WifiDirection::DOWNLINK, storedMapping);
1511 checkStoredMapping(
m_apMac,
m_staMacs[0], WifiDirection::UPLINK, storedMapping);
1512 checkStoredMapping(
m_staMacs[0],
m_apMac, WifiDirection::DOWNLINK, storedMapping);
1513 checkStoredMapping(
m_staMacs[0],
m_apMac, WifiDirection::UPLINK, storedMapping);
1526 for (uint8_t linkId = 0; linkId <
m_apMac->GetNLinks(); ++linkId)
1531 auto mask =
m_apMac->GetMacQueueScheduler()->GetQueueLinkMask(
AC_BE, queueId, linkId);
1534 "Unexpected presence/absence of mask on link " << +linkId);
1544 for (
const auto& linkId :
m_staMacs[0]->GetLinkIds())
1552 "Link " << +linkId <<
" has not been setup but is not disabled");
1559 "Expecting link " << +linkId <<
" to be active");
1570 const auto& hdr = mpdu->GetHeader();
1579 if (!hdr.IsToDs() && hdr.IsFromDs())
1581 dir = WifiDirection::DOWNLINK;
1582 width =
m_apMac->GetWifiPhy(linkId)->GetOperatingChannel().GetTotalWidth();
1584 else if (hdr.IsToDs() && !hdr.IsFromDs())
1586 dir = WifiDirection::UPLINK;
1587 width =
m_staMacs[0]->GetWifiPhy(linkId)->GetOperatingChannel().GetTotalWidth();
1591 NS_ABORT_MSG(
"Invalid combination for QoS data frame: ToDS(" << hdr.IsToDs() <<
") FromDS("
1592 << hdr.IsFromDs() <<
")");
1603 uint8_t tid = hdr.GetQosTid();
1606 (tid2.has_value() && tid == *tid2),
1607 "QoS frame with unexpected TID " << +tid);
1610 auto findLinkSet = [
this,
dir](uint8_t tid) -> std::set<uint8_t> {
1615 if (
auto it = mappingOptRef->get().find(tid); it != mappingOptRef->get().cend())
1617 linkSet = it->second;
1618 NS_ASSERT_MSG(!linkSet.empty(),
"TID " << +tid <<
" mapped to no link");
1624 auto linkSet = findLinkSet(tid);
1631 std::size_t nConcurFrames = std::min(qosFrames.size(), linkSet.size());
1634 for (std::size_t i = 0; i < nConcurFrames; i++)
1636 auto prev = qosFrames[i];
1646 if (qosFrames.size() < linkSet.size())
1651 "The " <<
dir <<
" QoS frame number " << qosFrames.size()
1652 <<
" was not sent concurrently with others on link "
1653 << +linkId <<
" which TID " << +tid <<
" is mapped to");
1660 "The " <<
dir <<
" QoS frame number " << qosFrames.size()
1661 <<
" was sent concurrently with others on a link "
1662 << +linkId <<
" which TID " << +tid <<
" is mapped to");
1670 "QoS frame sent on Link ID "
1671 << +linkId <<
" that does not belong to the link set of TID "
1678 auto otherTid = (tid == tid1) ? *tid2 : tid1;
1680 auto otherLinkSet = findLinkSet(otherTid);
1683 std::size_t nOtherConcurFrames = std::min(otherQosFrames.size(), otherLinkSet.size());
1686 for (std::size_t i = 0; i < nOtherConcurFrames; i++)
1688 auto prev = otherQosFrames[i];
1698 if (qosFrames.size() < linkSet.size())
1703 "The " <<
dir <<
" QoS frame number " << qosFrames.size()
1704 <<
" was not sent concurrently with others with TID "
1711 qosFrames.emplace_back(index);
1723 uint8_t nMaxInflight)
1725 std::string(
"Check data transmission between MLDs ") +
1728 ?
"with BA agreement, send BAR after BlockAck timeout"
1729 :
"with BA agreement, send Data frames after BlockAck timeout")
1730 :
"without BA agreement") +
1731 " (Traffic pattern: " +
std::to_string(static_cast<uint8_t>(trafficPattern)) +
1737 m_trafficPattern(trafficPattern),
1740 m_nMaxInflight(nMaxInflight),
1758 auto psdu = psduMap.begin()->second;
1760 switch (psdu->GetHeader(0).GetType())
1765 psdu->GetHeader(0).GetAddr2() == psdu->GetHeader(0).GetAddr3() ?
DL :
UL);
1770 m_uidList.push_front(psdu->GetPacket()->GetUid());
1778 for (
const auto& mpdu : *psdu)
1783 m_sourceMac->GetFrameExchangeManager(linkId)->GetAddress() ==
1784 mpdu->GetHeader().GetAddr2() &&
1785 !mpdu->GetHeader().GetAddr1().IsGroup())
1787 auto seqNo = mpdu->GetHeader().GetSequenceNumber();
1788 auto [it, success] =
1792 it->second = std::max(it->second, mpdu->GetInFlightLinkIds().size());
1796 for (std::size_t i = 0; i < psdu->GetNMpdus(); i++)
1802 if (psdu->GetHeader(i).GetSequenceNumber() != 1 ||
1809 auto uid = psdu->GetPayload(i)->GetUid();
1832 if (!
m_sourceMac->GetLinkIdByAddress(psdu->GetHeader(0).GetAddr1()))
1846 m_uidList.push_front(psdu->GetPacket()->GetUid());
1853 if (
m_sourceMac->GetLinkIdByAddress(psdu->GetHeader(0).GetAddr2()))
1871 "No BlockAck expected in AP to broadcast traffic pattern");
1885 auto mpdu = *psdu->begin();
1887 mpdu->GetPacket()->PeekHeader(blockAck);
1896 "MPDU 0 expected to be successfully received");
1900 "MPDU 1 expected to be received only in STA_TO_STA/STA_TO_BCAST scenarios");
1903 if (
m_staMacs[0]->GetSetupLinkIds().size() > 1)
1908 auto item = queue->PeekByTidAndAddress(0, rcvMac->GetAddress());
1909 std::size_t nQueuedPkt = 0;
1912 rcvMac->GetWifiPhy(linkId)->GetPhyBand()) +
1917 auto seqNo = item->GetHeader().GetSequenceNumber();
1920 "MPDU with seqNo=" << seqNo <<
" is not in flight");
1921 auto linkIds = item->GetInFlightLinkIds();
1924 "MPDU with seqNo=" << seqNo
1925 <<
" is in flight on multiple links");
1929 auto srcLinkId =
m_sourceMac->GetLinkIdByAddress(mpdu->GetHeader().GetAddr1());
1932 "Addr1 of BlockAck is not an originator's link address");
1935 "MPDU with seqNo=" << seqNo
1936 <<
" in flight on unexpected link");
1941 bool isQueued = (seqNo > (isMpdu1corrupted ? 0 : 1));
1945 bool isRetry = isQueued && seqNo <= 1;
1951 << item->GetHeader().GetSequenceNumber() <<
" should "
1952 << (isQueued ?
"" :
"not") <<
" be queued");
1954 item->GetHeader().IsRetry(),
1956 "Unexpected value for the Retry subfield of the MPDU with seqNo="
1957 << item->GetHeader().GetSequenceNumber());
1961 item = queue->PeekByTidAndAddress(0, rcvMac->GetAddress(), item);
1972 "Did not expect to receive a second BlockAck");
1974 std::pair<uint16_t, uint16_t> seqNos;
1979 if (
m_staMacs[0]->GetSetupLinkIds().size() > 1)
1989 "MPDU " << seqNos.first <<
" expected to be successfully received");
1992 "MPDU " << seqNos.second <<
" expected to be successfully received");
2008 mac->GetQosTxop(
AC_BE)->SetAttribute(
"UseExplicitBarAfterMissedBlockAck",
2015 for (std::size_t linkId = 0; linkId <
m_apMac->GetNLinks(); linkId++)
2019 m_apMac->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel);
2021 for (std::size_t i : {0, 1})
2023 for (
const auto linkId :
m_staMacs[i]->GetLinkIds())
2027 m_staMacs[i]->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel);
2041 destAddr =
m_staMacs[1]->GetDevice()->GetAddress();
2045 destAddr =
m_apMac->GetDevice()->GetAddress();
2049 destAddr =
m_staMacs[1]->GetDevice()->GetAddress();
2067 m_sourceMac->GetDevice()->GetNode()->AddApplication(
2074 m_sourceMac->GetDevice()->GetNode()->AddApplication(
2087 std::array<std::size_t, 3> expectedRxPkts{};
2116 "Unexpected number of packets received by the AP");
2119 "Unexpected number of packets received by STA 0");
2122 "Unexpected number of packets received by STA 1");
2127 std::size_t expectedBaCount = 0;
2128 std::size_t expectedBarCount = 0;
2135 expectedBaCount = 3;
2142 expectedBaCount = 1;
2148 "Unexpected number of BlockAck frames");
2151 "Unexpected number of BlockAckReq frames");
2162 "Did not collect number of simultaneous transmissions for all data frames");
2165 std::size_t maxCount = 0;
2171 "MPDU with seqNo=" << seqNo
2172 <<
" transmitted simultaneously more times than allowed");
2173 maxCount = std::max(maxCount, count);
2179 "Expected that at least one data frame was transmitted simultaneously a number of "
2180 "times equal to the NMaxInflights attribute");
2189 uint8_t nMaxInflight)
2191 std::string(
"Check MU data transmission between MLDs ") +
2193 ?
"(send BAR after BlockAck timeout,"
2194 :
"(send Data frames after BlockAck timeout,") +
2195 " MU Traffic pattern: " +
std::to_string(static_cast<uint8_t>(muTrafficPattern)) +
2196 ", nMaxInflight=" +
std::to_string(nMaxInflight) +
")",
2199 m_muTrafficPattern(muTrafficPattern),
2201 m_nMaxInflight(nMaxInflight),
2202 m_sockets(m_nStations),
2219 for (
const auto& [staId, psdu] : psduMap)
2221 switch (psdu->GetHeader(0).GetType())
2225 if (psdu->GetHeader(0).HasData())
2227 bool isDl = psdu->GetHeader(0).IsFromDs();
2229 isDl ? psdu->GetHeader(0).GetAddr1() : psdu->GetHeader(0).GetAddr2();
2230 auto address =
m_apMac->GetMldAddress(linkAddress).value_or(linkAddress);
2232 for (
const auto& mpdu : *psdu)
2235 auto seqNo = mpdu->GetHeader().GetSequenceNumber();
2237 {{address, seqNo}, mpdu->GetInFlightLinkIds().size()});
2240 it->second = std::max(it->second, mpdu->GetInFlightLinkIds().size());
2243 for (std::size_t i = 0; i < psdu->GetNMpdus(); i++)
2246 if (psdu->GetHeader(i).GetSequenceNumber() == 2)
2252 "MPDU " << **std::next(psdu->begin(), i)
2253 <<
" not transmitted in a TB PPDU");
2259 "MPDU " << **std::next(psdu->begin(), i)
2260 <<
" not transmitted in a DL MU PPDU");
2264 if (psdu->GetHeader(i).GetSequenceNumber() != 3)
2268 auto uid = psdu->GetPayload(i)->GetUid();
2305 m_uidList.push_front(psdu->GetPacket()->GetUid());
2311 psdu->GetPayload(0)->PeekHeader(trigger);
2320 auto band = mac->GetWifiPhy(linkId)->GetPhyBand();
2324 m_staMacs[i]->GetDevice()->GetNode()->AddApplication(
2333 muScheduler->SetAttribute(
"EnableUlOfdma",
BooleanValue(
false));
2380 auto mpdu = *psdu->begin();
2382 mpdu->GetPacket()->PeekHeader(blockAck);
2383 bool isMpdu3corrupted;
2398 auto index = indices.front();
2401 "Expected that a QoS data frame was corrupted");
2403 m_staMacs[i]->GetLinkIdByAddress(*m_dataCorruptedSta).has_value();
2406 "MPDU 2 expected to be successfully received");
2409 "Unexpected reception status for MPDU 3");
2419 "MPDU 2 expected to be successfully received");
2422 "Unexpected reception status for MPDU 3");
2426 m_staMacs[0]->GetSetupLinkIds().size() > 1)
2430 if (
m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress() ==
2431 mpdu->GetHeader().GetAddr2())
2435 else if (
m_staMacs[1]->GetFrameExchangeManager(linkId)->GetAddress() ==
2436 mpdu->GetHeader().GetAddr2())
2442 NS_ABORT_MSG(
"BlockAck frame not sent by a station in DL scenario");
2444 auto item = queue->PeekByTidAndAddress(0, rcvMac->GetAddress());
2445 std::size_t nQueuedPkt = 0;
2448 rcvMac->GetWifiPhy(linkId)->GetPhyBand()) +
2453 auto seqNo = item->GetHeader().GetSequenceNumber();
2456 "MPDU with seqNo=" << seqNo <<
" is not in flight");
2457 auto linkIds = item->GetInFlightLinkIds();
2460 "MPDU with seqNo=" << seqNo
2461 <<
" is in flight on multiple links");
2465 auto srcLinkId =
m_apMac->GetLinkIdByAddress(mpdu->GetHeader().GetAddr1());
2468 "Addr1 of BlockAck is not an originator's link address");
2471 "MPDU with seqNo=" << seqNo
2472 <<
" in flight on unexpected link");
2477 bool isQueued = (seqNo > (isMpdu3corrupted ? 2 : 3));
2481 bool isRetry = isQueued && seqNo <= 3;
2487 << item->GetHeader().GetSequenceNumber() <<
" should "
2488 << (isQueued ?
"" :
"not") <<
" be queued");
2490 item->GetHeader().IsRetry(),
2492 "Unexpected value for the Retry subfield of the MPDU with seqNo="
2493 << item->GetHeader().GetSequenceNumber());
2497 item = queue->PeekByTidAndAddress(0, rcvMac->GetAddress(), item);
2532 mac->GetQosTxop(
AC_BE)->SetAttribute(
"UseExplicitBarAfterMissedBlockAck",
2537 mac->GetQosTxop(
AC_VI)->SetAttribute(
"UseExplicitBarAfterMissedBlockAck",
2549 m_apMac->AggregateObject(muScheduler);
2552 for (std::size_t linkId = 0; linkId <
m_apMac->GetNLinks(); linkId++)
2556 m_apMac->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel);
2558 for (std::size_t i : {0, 1})
2560 for (
const auto linkId :
m_staMacs[i]->GetLinkIds())
2564 m_staMacs[i]->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel);
2584 m_apMac->GetDevice()->GetNode()->AddApplication(
2590 m_apMac->GetDevice()->GetNode()->AddApplication(
2596 m_apMac->GetDevice()->GetNode()->AddApplication(
2614 m_staMacs[i]->GetDevice()->GetNode()->AddApplication(
2625 muScheduler->SetAttribute(
"EnableUlOfdma",
BooleanValue(
true));
2628 muScheduler->SetAccessReqInterval(
Seconds(0));
2641 std::array<std::size_t, 3> expectedRxPkts{};
2660 "Unexpected number of packets received by the AP");
2663 "Unexpected number of packets received by STA 0");
2666 "Unexpected number of packets received by STA 1");
2674 "Did not collect number of simultaneous transmissions for all data frames");
2677 std::size_t maxCount = 0;
2683 << txSeqNoPair.second
2684 <<
" transmitted simultaneously more times than allowed");
2685 maxCount = std::max(maxCount, count);
2691 "Expected that at least one data frame was transmitted simultaneously a number of "
2692 "times equal to the NMaxInflights attribute");
2699 "Check sequence numbers after CTS timeout",
2701 BaseParams{{
"{36, 0, BAND_5GHZ, 0}",
"{2, 0, BAND_2_4GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}"},
2702 {
"{36, 0, BAND_5GHZ, 0}",
"{2, 0, BAND_2_4GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}"},
2704 m_nQosDataFrames(0),
2706 m_rtsCorrupted(
false)
2719 for (
const auto linkId :
m_staMacs[0]->GetLinkIds())
2745 auto psdu = psduMap.begin()->second;
2754 else if (psdu->GetHeader(0).IsQosData())
2774 std::size_t count{};
2778 auto psdu = txPsdu.psduMap.begin()->second;
2780 if (!psdu->GetHeader(0).IsQosData())
2788 uint16_t expectedSeqNo{};
2807 "Unexpected sequence number");
2816 "Check starting sequence number update after ADDBA Response timeout",
2818 BaseParams{{
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}"},
2819 {
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}"},
2835 for (
const auto linkId :
m_staMacs[0]->GetLinkIds())
2859 auto psdu = psduMap.begin()->second;
2860 const auto& hdr = psdu->GetHeader(0);
2866 auto prevPsdu =
m_txPsdus.back().psduMap.begin()->second;
2868 if (prevPsdu->GetHeader(0).IsAction())
2871 (*prevPsdu->begin())->GetPacket()->PeekHeader(actionHdr);
2881 m_staMacs[0]->BlockUnicastTxOnLinks(WifiQueueBlockedReason::TID_NOT_MAPPED,
2894 ackDuration +
m_apMac->GetQosTxop(
AC_BE)->GetAddBaResponseTimeout(),
2896 m_apMac->BlockUnicastTxOnLinks(WifiQueueBlockedReason::TID_NOT_MAPPED,
2897 m_staMacs[0]->GetAddress(),
2900 WifiQueueBlockedReason::TID_NOT_MAPPED,
2913 (*psdu->begin())->GetPacket()->PeekHeader(actionHdr);
2917 auto band = m_staMacs[0]->GetDevice()->GetPhy(phyId)->GetPhyBand();
2923 auto mpdu = m_apMac->GetTxopQueue(
AC_BE)->Peek();
2927 "Expected a QoS data frame");
2931 "Expected the data frame to be inflight when ADDBA RESP is received");
2936 m_apMac->GetQosTxop(
AC_BE)->GetBaStartingSequence(m_staMacs[0]->GetAddress(),
2938 mpdu->GetHeader().GetSequenceNumber(),
2939 "Unexpected BA Starting Sequence Number");
2943 else if (hdr.IsQosData())
2946 if (m_nQosDataCount++ == 0)
2948 m_staErrorModel->SetList({psdu->GetPacket()->GetUid()});
2952 m_staErrorModel->SetList({});
2973 std::vector<uint8_t>,
2982 std::vector<std::set<uint8_t>>{{0, 1, 2}, {1, 2}, {0, 1}, {0, 2}, {0}, {1}, {2}}),
2983 TestCase::Duration::QUICK);
2990 {
"{42, 80, BAND_5GHZ, 2}",
"{5, 40, BAND_2_4GHZ, 0}",
"{7, 80, BAND_6GHZ, 0}"},
2991 {
"{3, 40, BAND_2_4GHZ, 0}",
"{15, 160, BAND_6GHZ, 7}",
"{50, 160, BAND_5GHZ, 2}"},
2993 WifiScanType::PASSIVE,
2995 WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
2999 TestCase::Duration::QUICK);
3001 for (
const auto& [baseParams,
3008 {{
"{36, 0, BAND_5GHZ, 0}",
"{2, 0, BAND_2_4GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}"},
3009 {
"{36, 0, BAND_5GHZ, 0}",
"{2, 0, BAND_2_4GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}"},
3012 WifiTidToLinkMappingNegSupport::NOT_SUPPORTED,
3014 "0,1,2,3 0,1,2; 4,5 0,1",
3015 "0,1,2,3 1,2; 6,7 0,1"
3018 ParamsTuple({{
"{108, 0, BAND_5GHZ, 0}",
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}"},
3019 {
"{36, 0, BAND_5GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}",
"{5, 0, BAND_6GHZ, 0}"},
3022 WifiTidToLinkMappingNegSupport::SAME_LINK_SET,
3024 "0,1,2,3 0,1,2; 4,5 0,1",
3027 ParamsTuple({{
"{2, 0, BAND_2_4GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{36, 0, BAND_5GHZ, 0}"},
3028 {
"{36, 0, BAND_5GHZ, 0}",
"{9, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
3031 WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
3032 "0,1,2,3 0; 4,5,6,7 1,2",
3033 "0,2,3 1,2; 1,4,5,6,7 0"
3038 {{
"{2, 0, BAND_2_4GHZ, 0}",
"{36, 0, BAND_5GHZ, 0}",
"{8, 20, BAND_2_4GHZ, 0}"},
3039 {
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
3042 WifiTidToLinkMappingNegSupport::SAME_LINK_SET,
3044 "0,1,2,3,4,5,6,7 0",
3045 "0,1,2,3,4,5,6,7 0"),
3050 {{
"{2, 0, BAND_2_4GHZ, 0}",
"{36, 0, BAND_5GHZ, 0}",
"{8, 20, BAND_2_4GHZ, 0}"},
3051 {
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
3054 WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
3062 ParamsTuple({{
"{2, 0, BAND_2_4GHZ, 0}",
"{36, 0, BAND_5GHZ, 0}",
"{60, 0, BAND_5GHZ, 0}"},
3063 {
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
3066 WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
3072 ParamsTuple({{
"{2, 0, BAND_2_4GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
3073 {
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
3076 WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
3080 ParamsTuple({{
"{2, 0, BAND_2_4GHZ, 0}",
"{36, 0, BAND_5GHZ, 0}"},
3081 {
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
3084 WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
3088 ParamsTuple({{
"{120, 0, BAND_5GHZ, 0}"},
3089 {
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
3092 WifiTidToLinkMappingNegSupport::ANY_LINK_SET,
3096 ParamsTuple({{
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
3097 {
"{120, 0, BAND_5GHZ, 0}"},
3100 WifiTidToLinkMappingNegSupport::NOT_SUPPORTED,
3101 "0,1,2,3 0,1; 4,5,6,7 0,1",
3105 WifiScanType::PASSIVE,
3110 TestCase::Duration::QUICK);
3112 WifiScanType::ACTIVE,
3117 TestCase::Duration::QUICK);
3131 TestCase::Duration::QUICK);
3132 for (
const auto& useBarAfterMissedBa :
3139 useBarAfterMissedBa,
3141 TestCase::Duration::QUICK);
3146 useBarAfterMissedBa,
3148 TestCase::Duration::QUICK);
3157 for (
const auto& useBarAfterMissedBa :
3163 TestCase::Duration::QUICK);
3167 TestCase::Duration::QUICK);
Test that the AIDs that an AP MLD assigns to SLDs and MLDs are all unique.
AidAssignmentTest(const std::vector< std::set< uint8_t > > &linkIds)
Constructor.
const std::vector< std::set< uint8_t > > m_linkIds
link IDs for all non-AP STAs/MLDs
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void SetSsid(Ptr< StaWifiMac > staMac, Mac48Address)
Set the SSID on the next station that needs to start the association procedure.
void DoRun() override
Implementation to actually run this TestCase.
uint16_t m_expectedAid
expected AID for current non-AP STA/MLD
const std::vector< std::string > m_linkChannels
channels for all AP links
NetDeviceContainer m_staDevices
non-AP STAs/MLDs devices
Test the implementation of WifiAssocManager::GetNextAffiliatedAp(), which searches a given RNR elemen...
GetRnrLinkInfoTest()
Constructor.
void DoRun() override
Implementation to actually run this TestCase.
Test WifiMac subclass used to access the SwapLinks method.
static TypeId GetTypeId()
Test the WifiMac::SwapLinks() method.
void DoRun() override
Implementation to actually run this TestCase.
void RunOne(std::string text, std::size_t nLinks, const std::map< uint8_t, uint8_t > &links, const std::map< uint8_t, uint8_t > &expected)
Run a single test case.
Test data transmission between MLDs using OFDMA MU transmissions.
std::optional< Mac48Address > m_dataCorruptedSta
MAC address of the station that received MPDU with SeqNo=2 corrupted.
void CheckBlockAck(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector, uint8_t linkId)
Check the content of a received BlockAck frame when the max number of links on which an MPDU can be i...
std::vector< PacketSocketAddress > m_sockets
packet socket addresses for STAs
void Transmit(Ptr< WifiMac > mac, uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) override
Callback invoked when a FEM passes PSDUs to the PHY.
std::size_t m_nPackets
number of application packets to generate
void DoRun() override
Implementation to actually run this TestCase.
MultiLinkMuTxTest(const BaseParams &baseParams, WifiMuTrafficPattern muTrafficPattern, WifiUseBarAfterMissedBa useBarAfterMissedBa, uint8_t nMaxInflight)
Constructor.
std::list< uint64_t > m_uidList
list of UIDs of packets to corrupt
std::size_t m_blockAckCount
transmitted BlockAck counter
void DoSetup() override
Implementation to do any local setup required for this TestCase.
RxErrorModelMap m_errorModels
error rate models to corrupt packets
std::map< AddrSeqNoPair, std::size_t > m_inflightCount
max number of simultaneous transmissions of each data frame
void StartTraffic() override
Start the generation of traffic (needs to be overridden)
bool m_useBarAfterMissedBa
whether to send BAR after missed BlockAck
bool m_waitFirstTf
whether we are waiting for the first Basic Trigger Frame
WifiMuTrafficPattern m_muTrafficPattern
the pattern of traffic to generate
std::size_t m_tfCount
transmitted Trigger Frame counter
std::size_t m_nMaxInflight
max number of links on which an MPDU can be inflight
Base class for Multi-Link Operations tests.
virtual void Transmit(Ptr< WifiMac > mac, uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
Callback invoked when a FEM passes PSDUs to the PHY.
void SetSsid(uint16_t aid, Mac48Address)
Set the SSID on the next station that needs to start the association procedure.
virtual void StartTraffic()
Start the generation of traffic (needs to be overridden)
std::vector< Ptr< StaWifiMac > > m_staMacs
STA wifi MACs.
const std::vector< std::string > m_staChannels
strings specifying channels for STA
void CheckAddresses(Ptr< const WifiPsdu > psdu, std::optional< Direction > direction=std::nullopt)
Check that the Address 1 and Address 2 fields of the given PSDU contain device MAC addresses.
virtual void L7Receive(uint8_t nodeId, Ptr< const Packet > p, const Address &addr)
Function to trace packets received by the server application.
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.
std::map< FrequencyRange, Ptr< MultiModelSpectrumChannel > > ChannelMap
PHY band-indexed map of spectrum channels.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
std::vector< std::size_t > m_rxPkts
number of packets received at application layer by each node (index is node ID)
uint8_t m_nStations
number of stations to create
Time m_duration
simulation duration
const std::vector< uint8_t > m_fixedPhyBands
links on non-AP MLD with fixed PHY band
std::vector< FrameInfo > m_txPsdus
transmitted PSDUs
Ptr< ApWifiMac > m_apMac
AP wifi MAC.
MultiLinkOperationsTestBase(const std::string &name, uint8_t nStations, const BaseParams &baseParams)
Constructor.
Multi-Link Discovery & Setup test.
MultiLinkSetupTest(const BaseParams &baseParams, WifiScanType scanType, const std::vector< uint8_t > &setupLinks, WifiTidToLinkMappingNegSupport apNegSupport, const std::string &dlTidToLinkMapping, const std::string &ulTidToLinkMapping, bool support160MHzOp=true)
Constructor.
uint8_t m_dlTid1
the TID of the first set of DL QoS data frames
void CheckAssocRequest(Ptr< WifiMpdu > mpdu, uint8_t linkId)
Check correctness of the given Association Request frame.
void CheckProbeResponse(Ptr< WifiMpdu > mpdu, uint8_t linkId)
Check correctness of the given Probe Response frame.
std::optional< uint8_t > m_ulTid2
the TID of the optional set of UL QoS data frames
WifiScanType m_scanType
the scan type (active or passive)
void CheckMlSetup()
Check correctness of Multi-Link Setup procedure.
std::vector< std::size_t > m_qosFrames1
indices of QoS frames of the first set in the vector of TX PSDUs
void CheckDisabledLinks()
Check that links that are not setup on the non-AP MLD are disabled.
std::size_t m_nProbeResp
number of Probe Responses received by the non-AP MLD
std::string m_dlTidLinkMappingStr
DL TID-to-Link Mapping for non-AP MLD EHT configuration.
bool m_support160MHzOp
whether non-AP MLDs support 160 MHz operations
uint8_t m_ulTid1
the TID of the first set of UL QoS data frames
WifiTidLinkMapping m_ulTidLinkMapping
expected UL TID-to-Link Mapping requested by non-AP MLD and accepted by AP MLD
void StartTraffic() override
Start the generation of traffic (needs to be overridden)
void DoRun() override
Implementation to actually run this TestCase.
WifiTidToLinkMappingNegSupport m_apNegSupport
TID-to-Link Mapping negotiation supported by the AP MLD.
std::optional< uint8_t > m_dlTid2
the TID of the optional set of DL QoS data frames
WifiTidLinkMapping m_dlTidLinkMapping
expected DL TID-to-Link Mapping requested by non-AP MLD and accepted by AP MLD
void CheckAssocResponse(Ptr< WifiMpdu > mpdu, uint8_t linkId)
Check correctness of the given Association Response frame.
void CheckQosData(Ptr< WifiMpdu > mpdu, const WifiTxVector &txvector, uint8_t linkId, std::size_t index)
Check that QoS data frames are sent on links their TID is mapped to and with the correct TX width.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
std::string m_ulTidLinkMappingStr
UL TID-to-Link Mapping for non-AP MLD EHT configuration.
void CheckBeacon(Ptr< WifiMpdu > mpdu, uint8_t linkId)
Check correctness of the given Beacon frame.
std::vector< std::size_t > m_qosFrames2
indices of QoS frames of the optional set in the vector of TX PSDUs
const std::vector< uint8_t > m_setupLinks
IDs of the expected links to setup.
Test data transmission between two MLDs.
bool m_dataCorrupted
whether second data frame has been already corrupted
RxErrorModelMap m_errorModels
error rate models to corrupt packets
void Transmit(Ptr< WifiMac > mac, uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) override
Callback invoked when a FEM passes PSDUs to the PHY.
std::list< uint64_t > m_uidList
list of UIDs of packets to corrupt
void DoRun() override
Implementation to actually run this TestCase.
std::size_t m_nPackets
number of application packets to generate
std::size_t m_nMaxInflight
max number of links on which an MPDU can be inflight
bool m_baEnabled
whether BA agreement is enabled or disabled
void StartTraffic() override
Start the generation of traffic (needs to be overridden)
bool m_useBarAfterMissedBa
whether to send BAR after missed BlockAck
std::size_t m_blockAckCount
transmitted BlockAck counter
WifiTrafficPattern m_trafficPattern
the pattern of traffic to generate
std::size_t m_blockAckReqCount
transmitted BlockAckReq counter
std::map< uint16_t, std::size_t > m_inflightCount
seqNo-indexed max number of simultaneous transmissions of a data frame
void DoSetup() override
Implementation to do any local setup required for this TestCase.
Ptr< WifiMac > m_sourceMac
MAC of the node sending application packets.
MultiLinkTxTest(const BaseParams &baseParams, WifiTrafficPattern trafficPattern, WifiBaEnabled baEnabled, WifiUseBarAfterMissedBa useBarAfterMissedBa, uint8_t nMaxInflight)
Constructor.
void CheckBlockAck(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector, uint8_t linkId)
Check the content of a received BlockAck frame when the max number of links on which an MPDU can be i...
Test release of sequence numbers upon CTS timeout in multi-link operations.
ReleaseSeqNoAfterCtsTimeoutTest()
PacketSocketAddress m_sockAddr
packet socket address
Ptr< ListErrorModel > m_errorModel
error rate model to corrupt first RTS frame
std::size_t m_nQosDataFrames
counter for transmitted QoS data frames
void StartTraffic() override
Start the generation of traffic (needs to be overridden)
bool m_rtsCorrupted
whether the first RTS frame has been corrupted
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void Transmit(Ptr< WifiMac > mac, uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) override
Callback invoked when a FEM passes PSDUs to the PHY.
void DoRun() override
Implementation to actually run this TestCase.
Test update of BA starting sequence number after ADDBA Response timeout in multi-link operations.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
PacketSocketAddress m_sockAddr
packet socket address
std::size_t m_nQosDataCount
counter for transmitted QoS data frames
void StartTraffic() override
Start the generation of traffic (needs to be overridden)
StartSeqNoUpdateAfterAddBaTimeoutTest()
void Transmit(Ptr< WifiMac > mac, uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) override
Callback invoked when a FEM passes PSDUs to the PHY.
Ptr< ListErrorModel > m_staErrorModel
error rate model to corrupt frames at the non-AP MLD
WifiMultiLinkOperationsTestSuite()
a polymophic address class
Hold variables of type enum.
void SetList(const std::list< uint64_t > &packetlist)
static Mac48Address GetBroadcast()
Helper class used to assign positions and mobility models to nodes.
MultiUserScheduler is an abstract base class defining the API that APs supporting at least VHT can us...
holds a vector of ns3::NetDevice pointers
uint32_t GetN() const
Get the number of Ptr<NetDevice> stored in this container.
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
static uint32_t GetNNodes()
an address for a packet socket
void SetProtocol(uint16_t protocol)
Set the protocol.
void SetPhysicalAddress(const Address address)
Set the destination address.
void SetSingleDevice(uint32_t device)
Set the address to match only a specified NetDevice.
Give ns3::PacketSocket powers to ns3::Node.
void Install(Ptr< Node > node) const
Aggregate an instance of a ns3::PacketSocketFactory onto the provided node.
AttributeValue implementation for Pointer.
Smart pointer class similar to boost::intrusive_ptr.
The Reduced Neighbor Report element.
std::size_t GetNNbrApInfoFields() const
Get the number of Neighbor AP Information fields.
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)
void SetChannel(const Ptr< SpectrumChannel > channel)
The IEEE 802.11 SSID Information Element.
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.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Hold an unsigned integer type.
static std::optional< WifiAssocManager::RnrLinkInfo > GetNextAffiliatedAp(const ReducedNeighborReport &rnr, std::size_t nbrApInfoId)
Search the given RNR element for APs affiliated to the same AP MLD as the reporting AP.
static std::list< WifiAssocManager::RnrLinkInfo > GetAllAffiliatedAps(const ReducedNeighborReport &rnr)
Find all the APs affiliated to the same AP MLD as the reporting AP that sent the given RNR element.
helps to create WifiNetDevice objects
static int64_t AssignStreams(NetDeviceContainer c, int64_t stream)
Assign a fixed random variable stream number to the random variables used by the PHY and MAC aspects ...
create MAC layers for a ns3::WifiNetDevice.
base class for all MAC-level wifi objects.
void SetPcapCaptureType(PcapCaptureType type)
Set the PCAP capture type to be used.
void SetPcapDataLinkType(SupportedPcapDataLinkTypes dlt)
Set the data link type of PCAP traces to be used.
void Set(std::string name, const AttributeValue &v)
@ DLT_IEEE802_11_RADIO
Include Radiotap link layer information.
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
const HeMuUserInfoMap & GetHeMuUserInfoMap() const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
MHz_u GetChannelWidth() const
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
void SetDefault(std::string name, const AttributeValue &value)
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Ptr< T > CreateObjectWithAttributes(Args... args)
Allocate an Object on the heap and initialize with a set of attributes.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
#define NS_TEST_ASSERT_MSG_LT(actual, limit, msg)
Test that an actual value is less than a limit and report and abort if not.
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
#define NS_TEST_EXPECT_MSG_LT_OR_EQ(actual, limit, msg)
Test that an actual value is less than or equal to a limit and report if not.
#define NS_TEST_EXPECT_MSG_LT(actual, limit, msg)
Test that an actual value is less than a limit and report if not.
#define NS_TEST_EXPECT_MSG_GT(actual, limit, msg)
Test that an actual value is greater than a limit and report if not.
#define NS_TEST_EXPECT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report if not.
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report and abort if not.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time Seconds(double value)
Construct a Time in the indicated unit.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
WifiScanType
Scan type (active or passive)
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Maps TID (Traffic ID) to Access classes.
@ 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.
std:: tuple< WifiContainerQueueType, WifiReceiverAddressType, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, receiver address type, Address, TID) identifying a container queue.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
WifiTidToLinkMappingNegSupport
TID-to-Link Mapping Negotiation Support.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
static constexpr uint8_t SINGLE_LINK_OP_ID
Link ID for single link operations (helps tracking places where correct link ID is to be used to supp...
constexpr FrequencyRange WIFI_SPECTRUM_5_GHZ
Identifier for the frequency range covering the wifi spectrum in the 5 GHz band.
@ WIFI_MAC_MGT_PROBE_REQUEST
@ WIFI_MAC_MGT_ASSOCIATION_RESPONSE
@ WIFI_MAC_MGT_ASSOCIATION_REQUEST
@ WIFI_MAC_MGT_PROBE_RESPONSE
WifiDirection
Wifi direction.
bool TidToLinkMappingValidForNegType1(const WifiTidLinkMapping &dlLinkMapping, const WifiTidLinkMapping &ulLinkMapping)
Check if the given TID-to-Link Mappings are valid for a negotiation type of 1.
Ptr< T1 > StaticCast(const Ptr< T2 > &p)
Cast a Ptr.
constexpr FrequencyRange WIFI_SPECTRUM_2_4_GHZ
Identifier for the frequency range covering the wifi spectrum in the 2.4 GHz band.
Configuration parameters common to all subclasses.
uint32_t pktSize
packet size used for the simulation (in bytes)
static WifiMultiLinkOperationsTestSuite g_wifiMultiLinkOperationsTestSuite
the test suite
WifiMuTrafficPattern
Tested MU traffic patterns.
WifiTrafficPattern
Tested traffic patterns.
WifiUseBarAfterMissedBa
Whether to send a BlockAckReq after a missed BlockAck.
WifiBaEnabled
Block Ack agreement enabled/disabled.