20 #include "ns3/ap-wifi-mac.h"
21 #include "ns3/config.h"
22 #include "ns3/he-configuration.h"
23 #include "ns3/he-frame-exchange-manager.h"
24 #include "ns3/he-phy.h"
26 #include "ns3/mgt-headers.h"
27 #include "ns3/mobility-helper.h"
28 #include "ns3/multi-link-element.h"
29 #include "ns3/multi-model-spectrum-channel.h"
30 #include "ns3/node-list.h"
31 #include "ns3/packet-socket-client.h"
32 #include "ns3/packet-socket-helper.h"
33 #include "ns3/packet-socket-server.h"
34 #include "ns3/packet.h"
35 #include "ns3/pointer.h"
36 #include "ns3/qos-utils.h"
37 #include "ns3/rng-seed-manager.h"
38 #include "ns3/rr-multi-user-scheduler.h"
39 #include "ns3/spectrum-wifi-helper.h"
40 #include "ns3/spectrum-wifi-phy.h"
41 #include "ns3/sta-wifi-mac.h"
42 #include "ns3/string.h"
44 #include "ns3/wifi-acknowledgment.h"
45 #include "ns3/wifi-assoc-manager.h"
46 #include "ns3/wifi-mac-header.h"
47 #include "ns3/wifi-mac-queue.h"
48 #include "ns3/wifi-net-device.h"
49 #include "ns3/wifi-protection.h"
50 #include "ns3/wifi-psdu.h"
80 void DoRun()
override;
84 :
TestCase(
"Check the implementation of WifiAssocManager::GetNextAffiliatedAp()")
147 auto ret = WifiAssocManager::GetNextAffiliatedAp(rnr, 0);
153 ret = WifiAssocManager::GetNextAffiliatedAp(rnr, ret->m_nbrApInfoId + 1);
158 "Unexpected neighbor ID of the second reported AP");
161 "Unexpected tbtt ID of the second reported AP");
163 ret = WifiAssocManager::GetNextAffiliatedAp(rnr, ret->m_nbrApInfoId + 1);
167 "Did not expect to find a third suitable reported AP");
170 auto allAps = WifiAssocManager::GetAllAffiliatedAps(rnr);
174 auto apIt = allAps.begin();
177 "Unexpected neighbor ID of the first reported AP");
180 "Unexpected tbtt ID of the first reported AP");
185 "Unexpected neighbor ID of the second reported AP");
188 "Unexpected tbtt ID of the second reported AP");
215 std::vector<std::string> staChannels,
216 std::vector<std::string> apChannels,
217 std::vector<uint8_t> fixedPhyBands = {});
230 virtual void Transmit(uint8_t linkId,
254 std::optional<Direction> direction = std::nullopt);
285 const std::vector<std::string>& channels,
307 std::vector<std::string> staChannels,
308 std::vector<std::string> apChannels,
309 std::vector<uint8_t> fixedPhyBands)
311 m_staChannels(staChannels),
312 m_apChannels(apChannels),
313 m_fixedPhyBands(fixedPhyBands),
314 m_staMacs(nStations),
315 m_nStations(nStations),
322 std::optional<Direction> direction)
324 std::optional<Mac48Address> apAddr;
325 std::optional<Mac48Address> staAddr;
364 "Address " << *apAddr <<
" is not an AP device address. "
365 <<
"PSDU: " << *psdu);
373 for (uint8_t linkId = 0; linkId <
m_staMacs[i]->GetNLinks(); linkId++)
375 if (
m_staMacs[i]->GetFrameExchangeManager(linkId)->GetAddress() == *staAddr)
388 "Address " << *staAddr <<
" is not a STA device address. "
389 <<
"PSDU: " << *psdu);
402 for (
const auto& [aid, psdu] : psduMap)
404 std::stringstream ss;
405 ss << std::setprecision(10) <<
"PSDU #" <<
m_txPsdus.size() <<
" Link ID " << +linkId <<
" "
406 << psdu->GetHeader(0).GetTypeString() <<
" #MPDUs " << psdu->GetNMpdus()
407 <<
" duration/ID " << psdu->GetHeader(0).GetDuration() <<
" RA = " << psdu->GetAddr1()
408 <<
" TA = " << psdu->GetAddr2() <<
" ADDR3 = " << psdu->GetHeader(0).GetAddr3()
409 <<
" ToDS = " << psdu->GetHeader(0).IsToDs()
410 <<
" FromDS = " << psdu->GetHeader(0).IsFromDs();
411 if (psdu->GetHeader(0).IsQosData())
416 ss << mpdu->GetHeader().GetSequenceNumber() <<
",";
418 ss <<
"} TID = " << +psdu->GetHeader(0).GetQosTid();
427 const std::vector<std::string>& channels,
434 for (
const auto& str : channels)
445 RngSeedManager::SetSeed(1);
446 RngSeedManager::SetRun(2);
447 int64_t streamNumber = 100;
458 wifi.SetRemoteStationManager(
"ns3::ConstantRateWifiManager",
464 auto channel = CreateObject<MultiModelSpectrumChannel>();
477 mac.SetType(
"ns3::StaWifiMac",
483 mac.SetType(
"ns3::ApWifiMac",
502 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
503 positionAlloc->Add(Vector(1.0, 0.0, 0.0));
504 mobility.SetPositionAllocator(positionAlloc);
506 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
510 m_apMac = DynamicCast<ApWifiMac>(DynamicCast<WifiNetDevice>(
apDevices.Get(0))->GetMac());
514 DynamicCast<StaWifiMac>(DynamicCast<WifiNetDevice>(
staDevices.Get(i))->GetMac());
518 for (uint8_t linkId = 0; linkId < StaticCast<WifiNetDevice>(
apDevices.Get(0))->GetNPhys();
522 std::to_string(linkId) +
"/PhyTxPsduBegin",
527 for (uint8_t linkId = 0; linkId < StaticCast<WifiNetDevice>(
staDevices.Get(i))->GetNPhys();
531 "/NodeList/" + std::to_string(i + 1) +
"/DeviceList/*/$ns3::WifiNetDevice/Phys/" +
532 std::to_string(linkId) +
"/PhyTxPsduBegin",
588 std::vector<std::string> apChannels,
589 std::vector<std::pair<uint8_t, uint8_t>> setupLinks,
590 std::vector<uint8_t> fixedPhyBands = {});
594 void DoRun()
override;
636 std::vector<std::string> apChannels,
637 std::vector<std::pair<uint8_t, uint8_t>> setupLinks,
638 std::vector<uint8_t> fixedPhyBands)
644 m_setupLinks(setupLinks)
661 const auto& mpdu = *frameInfo.psduMap.begin()->second->begin();
662 const auto& linkId = frameInfo.linkId;
664 switch (mpdu->GetHeader().GetType())
685 Simulator::Destroy();
696 mpdu->GetHeader().GetAddr2(),
697 "TA of Beacon frame is not the address of the link it is transmitted on");
699 mpdu->GetPacket()->PeekHeader(beacon);
707 "RNR Element in Beacon frame from single link AP");
710 "Multi-Link Element in Beacon frame from single link AP");
719 "Unexpected number of Neighbor AP Info fields in RNR");
720 for (std::size_t nbrApInfoId = 0; nbrApInfoId < rnr->GetNNbrApInfoFields(); nbrApInfoId++)
724 "MLD Parameters not present");
727 "Expected only one TBTT Info subfield per Neighbor AP Info");
728 uint8_t nbrLinkId = rnr->GetLinkId(nbrApInfoId, 0);
731 "BSSID advertised in Neighbor AP Info field "
733 <<
" does not match the address configured on the link "
734 "advertised in the same field");
740 "Incorrect MLD address advertised in Multi-Link Element");
743 "Incorrect Link ID advertised in Multi-Link Element");
754 m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress(),
755 mpdu->GetHeader().GetAddr2(),
756 "TA of Assoc Request frame is not the address of the link it is transmitted on");
758 mpdu->GetPacket()->PeekHeader(assoc);
765 "Multi-Link Element in Assoc Request frame from single link STA");
772 "Incorrect MLD Address advertised in Multi-Link Element");
775 "Incorrect number of Per-STA Profile subelements in Multi-Link Element");
776 for (std::size_t i = 0; i < mle->GetNPerStaProfileSubelements(); i++)
778 auto& perStaProfile = mle->GetPerStaProfile(i);
781 "Per-STA Profile must contain STA MAC address");
783 auto staLinkId =
m_staMacs[0]->GetLinkIdByAddress(perStaProfile.GetStaMacAddress());
785 staLinkId.has_value(),
787 "No link found with the STA MAC address advertised in Per-STA Profile");
791 "The STA that sent the Assoc Request should not be included in a Per-STA Profile");
793 return pair.first == staLinkId.value();
797 "Not expecting to setup STA link ID " << +staLinkId.value());
800 +perStaProfile.GetLinkId(),
801 "Not expecting to request association to AP Link ID in Per-STA Profile");
804 "Missing Association Request in Per-STA Profile");
817 mpdu->GetHeader().GetAddr2(),
818 "TA of Assoc Response frame is not the address of the link it is transmitted on");
820 mpdu->GetPacket()->PeekHeader(assoc);
828 "Multi-Link Element in Assoc Response frame with single link AP or single link STA");
835 "Incorrect MLD Address advertised in Multi-Link Element");
838 "Incorrect number of Per-STA Profile subelements in Multi-Link Element");
839 for (std::size_t i = 0; i < mle->GetNPerStaProfileSubelements(); i++)
841 auto& perStaProfile = mle->GetPerStaProfile(i);
844 "Per-STA Profile must contain STA MAC address");
848 apLinkId.has_value(),
850 "No link found with the STA MAC address advertised in Per-STA Profile");
852 +perStaProfile.GetLinkId(),
853 "Link ID and MAC address advertised in Per-STA Profile do not match");
857 "The AP that sent the Assoc Response should not be included in a Per-STA Profile");
859 return pair.second == apLinkId.value();
863 "Not expecting to setup AP link ID " << +apLinkId.value());
866 "Missing Association Response in Per-STA Profile");
880 auto staAddr =
m_staMacs[0]->GetFrameExchangeManager(staLinkId)->GetAddress();
883 auto staRemoteMgr =
m_staMacs[0]->GetWifiRemoteStationManager(staLinkId);
889 "Unexpected BSSID for STA link ID " << +staLinkId);
894 "Incorrect MLD address stored by STA on link ID " << +staLinkId);
898 "Incorrect affiliated address stored by STA on link ID " << +staLinkId);
904 "Expecting STA " << staAddr <<
" to be associated on link "
909 (apRemoteMgr->GetMldAddress(staAddr) ==
m_staMacs[0]->GetAddress()),
911 "Incorrect MLD address stored by AP on link ID " << +apLinkId);
913 (apRemoteMgr->GetAffiliatedStaAddress(
m_staMacs[0]->GetAddress()) == staAddr),
915 "Incorrect affiliated address stored by AP on link ID " << +apLinkId);
921 "STA " << staAddr <<
" not found in list of associated STAs");
925 +
m_staMacs[0]->GetWifiPhy(staLinkId)->GetOperatingChannel().GetNumber(),
927 "Incorrect operating channel number for STA on link " << +staLinkId);
929 m_staMacs[0]->GetWifiPhy(staLinkId)->GetOperatingChannel().GetFrequency(),
931 "Incorrect operating channel frequency for STA on link " << +staLinkId);
934 "Incorrect operating channel width for STA on link " << +staLinkId);
936 +
m_staMacs[0]->GetWifiPhy(staLinkId)->GetOperatingChannel().GetPhyBand(),
938 "Incorrect operating PHY band for STA on link " << +staLinkId);
940 +
m_staMacs[0]->GetWifiPhy(staLinkId)->GetOperatingChannel().GetPrimaryChannelIndex(20),
942 "Incorrect operating primary channel index for STA on link " << +staLinkId);
949 for (std::size_t linkId = 0; linkId <
m_staChannels.size(); linkId++)
952 return link.first == linkId;
959 "Link " << +linkId <<
" has not been setup but is not disabled");
966 "Expecting link " << +linkId <<
" to be active");
1046 uint8_t nMaxInflight,
1047 const std::vector<std::string>& staChannels,
1048 const std::vector<std::string>& apChannels,
1049 const std::vector<uint8_t>& fixedPhyBands = {});
1072 std::string context,
1075 double txPowerW)
override;
1077 void DoRun()
override;
1105 uint8_t nMaxInflight,
1106 const std::vector<std::string>& staChannels,
1107 const std::vector<std::string>& apChannels,
1108 const std::vector<uint8_t>& fixedPhyBands)
1110 std::string(
"Check data transmission between MLDs ") +
1113 ?
"with BA agreement, send BAR after BlockAck timeout"
1114 :
"with BA agreement, send Data frames after BlockAck timeout")
1115 :
"without BA agreement") +
1116 " (Traffic pattern: " + std::to_string(static_cast<uint8_t>(trafficPattern)) +
1117 (baEnabled ==
WifiBaEnabled::
YES ?
", nMaxInflight=" + std::to_string(nMaxInflight)
1124 m_trafficPattern(trafficPattern),
1127 m_nMaxInflight(nMaxInflight),
1137 std::string context,
1142 auto psdu = psduMap.begin()->second;
1144 switch (psdu->GetHeader(0).GetType())
1149 psdu->GetHeader(0).GetAddr2() == psdu->GetHeader(0).GetAddr3() ?
DL :
UL);
1154 m_uidList.push_front(psdu->GetPacket()->GetUid());
1162 for (
const auto& mpdu : *psdu)
1166 if (
m_baEnabled && linkId < m_sourceMac->GetNLinks() &&
1168 mpdu->GetHeader().GetAddr2() &&
1169 !mpdu->GetHeader().GetAddr1().IsGroup())
1171 auto seqNo = mpdu->GetHeader().GetSequenceNumber();
1172 auto [it, success] =
1176 it->second =
std::max(it->second, mpdu->GetInFlightLinkIds().size());
1180 for (std::size_t i = 0; i < psdu->GetNMpdus(); i++)
1186 if (psdu->GetHeader(i).GetSequenceNumber() != 1 ||
1193 auto uid = psdu->GetPayload(i)->GetUid();
1230 m_uidList.push_front(psdu->GetPacket()->GetUid());
1257 "No BlockAck expected in AP to broadcast traffic pattern");
1271 auto mpdu = *psdu->
begin();
1273 mpdu->GetPacket()->PeekHeader(blockAck);
1282 "MPDU 0 expected to be successfully received");
1286 "MPDU 1 expected to be received only in STA_TO_STA/STA_TO_BCAST scenarios");
1289 if (
m_staMacs[0]->GetSetupLinkIds().size() > 1)
1294 auto item = queue->PeekByTidAndAddress(0, rcvMac->GetAddress());
1295 std::size_t nQueuedPkt = 0;
1296 auto delay = WifiPhy::CalculateTxDuration(psdu,
1298 rcvMac->GetWifiPhy(linkId)->GetPhyBand()) +
1303 auto seqNo = item->GetHeader().GetSequenceNumber();
1306 "MPDU with seqNo=" << seqNo <<
" is not in flight");
1307 auto linkIds = item->GetInFlightLinkIds();
1310 "MPDU with seqNo=" << seqNo
1311 <<
" is in flight on multiple links");
1318 "Addr1 of BlockAck is not an originator's link address");
1321 "MPDU with seqNo=" << seqNo
1322 <<
" in flight on unexpected link");
1327 bool isQueued = (seqNo > (isMpdu1corrupted ? 0 : 1));
1331 bool isRetry = isQueued && seqNo <= 1;
1333 Simulator::Schedule(delay, [
this, item, isQueued, isRetry]() {
1337 << item->GetHeader().GetSequenceNumber() <<
" should "
1338 << (isQueued ?
"" :
"not") <<
" be queued");
1340 item->GetHeader().IsRetry(),
1342 "Unexpected value for the Retry subfield of the MPDU with seqNo="
1343 << item->GetHeader().GetSequenceNumber());
1347 item = queue->PeekByTidAndAddress(0, rcvMac->GetAddress(), item);
1358 "Did not expect to receive a second BlockAck");
1360 std::pair<uint16_t, uint16_t> seqNos;
1365 if (
m_staMacs[0]->GetSetupLinkIds().size() > 1)
1375 "MPDU " << seqNos.first <<
" expected to be successfully received");
1378 "MPDU " << seqNos.second <<
" expected to be successfully received");
1386 NS_LOG_INFO(
"Packet received by NODE " << +nodeId <<
"\n");
1401 mac->GetQosTxop(
AC_BE)->SetAttribute(
"UseExplicitBarAfterMissedBlockAck",
1410 auto errorModel = CreateObject<ListErrorModel>();
1414 for (std::size_t linkId = 0; linkId <
m_staMacs[0]->GetNLinks(); linkId++)
1416 auto errorModel = CreateObject<ListErrorModel>();
1418 m_staMacs[0]->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel);
1420 errorModel = CreateObject<ListErrorModel>();
1422 m_staMacs[1]->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel);
1436 destAddr =
m_staMacs[1]->GetDevice()->GetAddress();
1444 destAddr =
m_staMacs[1]->GetDevice()->GetAddress();
1448 destAddr = Mac48Address::GetBroadcast();
1452 destAddr = Mac48Address::GetBroadcast();
1467 auto client1 = CreateObject<PacketSocketClient>();
1471 client1->SetRemote(socket);
1473 client1->SetStartTime(
Seconds(0));
1474 client1->SetStopTime(duration);
1479 auto client2 = CreateObject<PacketSocketClient>();
1483 client2->SetRemote(socket);
1487 client2->SetStopTime(duration);
1491 for (
auto nodeIt = NodeList::Begin(); nodeIt != NodeList::End(); nodeIt++)
1494 server->SetLocal(socket);
1495 (*nodeIt)->AddApplication(server);
1496 server->SetStartTime(
Seconds(0));
1497 server->SetStopTime(duration);
1500 for (std::size_t nodeId = 0; nodeId < NodeList::GetNNodes(); nodeId++)
1503 "/ApplicationList/*/$ns3::PacketSocketServer/Rx",
1507 Simulator::Stop(duration);
1516 std::array<std::size_t, 3> expectedRxPkts{};
1545 "Unexpected number of packets received by the AP");
1548 "Unexpected number of packets received by STA 0");
1551 "Unexpected number of packets received by STA 1");
1556 std::size_t expectedBaCount = 0;
1557 std::size_t expectedBarCount = 0;
1564 expectedBaCount = 3;
1571 expectedBaCount = 1;
1577 "Unexpected number of BlockAck frames");
1580 "Unexpected number of BlockAckReq frames");
1591 "Did not collect number of simultaneous transmissions for all data frames");
1594 std::size_t maxCount = 0;
1600 "MPDU with seqNo=" << seqNo
1601 <<
" transmitted simultaneously more times than allowed");
1602 maxCount =
std::max(maxCount, count);
1608 "Expected that at least one data frame was transmitted simultaneously a number of "
1609 "times equal to the NMaxInflights attribute");
1612 Simulator::Destroy();
1665 uint8_t nMaxInflight,
1666 const std::vector<std::string>& staChannels,
1667 const std::vector<std::string>& apChannels,
1668 const std::vector<uint8_t>& fixedPhyBands = {});
1691 std::string context,
1694 double txPowerW)
override;
1696 void DoRun()
override;
1729 uint8_t nMaxInflight,
1730 const std::vector<std::string>& staChannels,
1731 const std::vector<std::string>& apChannels,
1732 const std::vector<uint8_t>& fixedPhyBands)
1734 std::string(
"Check MU data transmission between MLDs ") +
1736 ?
"(send BAR after BlockAck timeout,"
1737 :
"(send Data frames after BlockAck timeout,") +
1738 " MU Traffic pattern: " + std::to_string(static_cast<uint8_t>(muTrafficPattern)) +
1739 ", nMaxInflight=" + std::to_string(nMaxInflight) +
")",
1744 m_muTrafficPattern(muTrafficPattern),
1746 m_nMaxInflight(nMaxInflight),
1747 m_sockets(m_nStations),
1754 std::string context,
1761 for (
const auto& [staId, psdu] : psduMap)
1763 switch (psdu->GetHeader(0).GetType())
1767 if (psdu->GetHeader(0).HasData())
1769 bool isDl = psdu->GetHeader(0).IsFromDs();
1771 isDl ? psdu->GetHeader(0).GetAddr1() : psdu->GetHeader(0).GetAddr2();
1774 for (
const auto& mpdu : *psdu)
1777 auto seqNo = mpdu->GetHeader().GetSequenceNumber();
1779 {{
address, seqNo}, mpdu->GetInFlightLinkIds().size()});
1782 it->second =
std::max(it->second, mpdu->GetInFlightLinkIds().size());
1785 for (std::size_t i = 0; i < psdu->GetNMpdus(); i++)
1788 if (psdu->GetHeader(i).GetSequenceNumber() == 2)
1794 "MPDU " << **std::next(psdu->begin(), i)
1795 <<
" not transmitted in a TB PPDU");
1801 "MPDU " << **std::next(psdu->begin(), i)
1802 <<
" not transmitted in a DL MU PPDU");
1806 if (psdu->GetHeader(i).GetSequenceNumber() != 3)
1810 auto uid = psdu->GetPayload(i)->GetUid();
1847 m_uidList.push_front(psdu->GetPacket()->GetUid());
1853 psdu->GetPayload(0)->PeekHeader(trigger);
1862 Time txDuration = WifiPhy::CalculateTxDuration(psduMap, txVector, band);
1871 m_staMacs[i]->GetDevice()->GetNode()->AddApplication(client);
1872 client->SetStartTime(txDuration);
1873 client->SetStopTime(
Seconds(1.0));
1874 client->Initialize();
1924 auto mpdu = *psdu->
begin();
1926 mpdu->GetPacket()->PeekHeader(blockAck);
1927 bool isMpdu3corrupted;
1942 auto index = indices.front();
1945 "Expected that a QoS data frame was corrupted");
1947 m_staMacs[i]->GetLinkIdByAddress(*m_dataCorruptedSta).has_value();
1950 "MPDU 2 expected to be successfully received");
1953 "Unexpected reception status for MPDU 3");
1963 "MPDU 2 expected to be successfully received");
1966 "Unexpected reception status for MPDU 3");
1970 m_staMacs[0]->GetSetupLinkIds().size() > 1)
1974 if (
m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress() ==
1975 mpdu->GetHeader().GetAddr2())
1979 else if (
m_staMacs[1]->GetFrameExchangeManager(linkId)->GetAddress() ==
1980 mpdu->GetHeader().GetAddr2())
1986 NS_ABORT_MSG(
"BlockAck frame not sent by a station in DL scenario");
1988 auto item = queue->PeekByTidAndAddress(0, rcvMac->
GetAddress());
1989 std::size_t nQueuedPkt = 0;
1990 auto delay = WifiPhy::CalculateTxDuration(psdu,
1997 auto seqNo = item->GetHeader().GetSequenceNumber();
2000 "MPDU with seqNo=" << seqNo <<
" is not in flight");
2001 auto linkIds = item->GetInFlightLinkIds();
2004 "MPDU with seqNo=" << seqNo
2005 <<
" is in flight on multiple links");
2012 "Addr1 of BlockAck is not an originator's link address");
2015 "MPDU with seqNo=" << seqNo
2016 <<
" in flight on unexpected link");
2021 bool isQueued = (seqNo > (isMpdu3corrupted ? 2 : 3));
2025 bool isRetry = isQueued && seqNo <= 3;
2027 Simulator::Schedule(delay, [
this, item, isQueued, isRetry]() {
2031 << item->GetHeader().GetSequenceNumber() <<
" should "
2032 << (isQueued ?
"" :
"not") <<
" be queued");
2034 item->GetHeader().IsRetry(),
2036 "Unexpected value for the Retry subfield of the MPDU with seqNo="
2037 << item->GetHeader().GetSequenceNumber());
2041 item = queue->PeekByTidAndAddress(0, rcvMac->
GetAddress(), item);
2053 NS_LOG_INFO(
"Packet received by NODE " << +nodeId <<
"\n");
2064 EnumValue(WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE));
2068 EnumValue(WifiAcknowledgment::DL_MU_TF_MU_BAR));
2072 EnumValue(WifiAcknowledgment::DL_MU_AGGREGATE_TF));
2083 mac->GetQosTxop(
AC_BE)->SetAttribute(
"UseExplicitBarAfterMissedBlockAck",
2088 mac->GetQosTxop(
AC_VI)->SetAttribute(
"UseExplicitBarAfterMissedBlockAck",
2094 auto muScheduler = CreateObjectWithAttributes<RrMultiUserScheduler>(
2106 auto errorModel = CreateObject<ListErrorModel>();
2110 for (std::size_t linkId = 0; linkId <
m_staMacs[0]->GetNLinks(); linkId++)
2112 auto errorModel = CreateObject<ListErrorModel>();
2114 m_staMacs[0]->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel);
2116 errorModel = CreateObject<ListErrorModel>();
2118 m_staMacs[1]->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel);
2145 auto client1 = CreateObject<PacketSocketClient>();
2149 client1->SetRemote(socket);
2152 client1->SetStopTime(duration);
2156 auto client2 = CreateObject<PacketSocketClient>();
2160 client2->SetRemote(socket);
2164 client2->SetStopTime(duration);
2168 auto client3 = CreateObject<PacketSocketClient>();
2172 client3->SetRemote(socket);
2176 client3->SetStopTime(duration);
2196 m_staMacs[i]->GetDevice()->GetNode()->AddApplication(client1);
2198 client1->SetStopTime(duration);
2210 muScheduler->SetAccessReqInterval(
Seconds(0));
2215 for (
auto nodeIt = NodeList::Begin(); nodeIt != NodeList::End(); nodeIt++)
2218 auto device = DynamicCast<WifiNetDevice>((*nodeIt)->GetDevice(0));
2224 server->SetLocal(srvAddr);
2225 (*nodeIt)->AddApplication(server);
2226 server->SetStartTime(
Seconds(0));
2227 server->SetStopTime(duration);
2228 server->TraceConnectWithoutContext(
2233 Simulator::Stop(duration);
2242 std::array<std::size_t, 3> expectedRxPkts{};
2261 "Unexpected number of packets received by the AP");
2264 "Unexpected number of packets received by STA 0");
2267 "Unexpected number of packets received by STA 1");
2275 "Did not collect number of simultaneous transmissions for all data frames");
2278 std::size_t maxCount = 0;
2284 << txSeqNoPair.second
2285 <<
" transmitted simultaneously more times than allowed");
2286 maxCount =
std::max(maxCount, count);
2292 "Expected that at least one data frame was transmitted simultaneously a number of "
2293 "times equal to the NMaxInflights attribute");
2295 Simulator::Destroy();
2324 void DoRun()
override;
2326 std::string context,
2329 double txPowerW)
override;
2347 "Check sequence numbers after CTS timeout",
2349 {
"{36, 0, BAND_5GHZ, 0}",
"{2, 0, BAND_2_4GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}"},
2350 {
"{36, 0, BAND_5GHZ, 0}",
"{2, 0, BAND_2_4GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}"}),
2351 m_nQosDataFrames(0),
2352 m_errorModel(CreateObject<ListErrorModel>()),
2353 m_rtsCorrupted(
false)
2366 for (std::size_t linkId = 0; linkId <
m_staMacs[0]->GetNLinks(); linkId++)
2377 auto client = CreateObject<PacketSocketClient>();
2382 client->SetStartTime(
Seconds(0));
2383 client->SetStopTime(duration);
2405 for (
auto nodeIt = NodeList::Begin(); nodeIt != NodeList::End(); nodeIt++)
2409 (*nodeIt)->AddApplication(server);
2410 server->SetStartTime(
Seconds(0));
2411 server->SetStopTime(duration);
2417 std::string context,
2422 auto psdu = psduMap.begin()->second;
2431 else if (psdu->GetHeader(0).IsQosData())
2448 Simulator::Stop(
Seconds(1.0));
2453 std::size_t count{};
2457 auto psdu = txPsdu.psduMap.begin()->second;
2459 if (!psdu->GetHeader(0).IsQosData())
2467 uint16_t expectedSeqNo{};
2486 "Unexpected sequence number");
2490 Simulator::Destroy();
2509 std::tuple<std::vector<std::string>,
2510 std::vector<std::string>,
2511 std::vector<std::pair<uint8_t, uint8_t>>,
2513 std::vector<uint8_t>>;
2517 for (
const auto& [staChannels, apChannels, setupLinks, fixedPhyBands] :
2519 ParamsTuple({
"{36, 0, BAND_5GHZ, 0}",
"{2, 0, BAND_2_4GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}"},
2520 {
"{36, 0, BAND_5GHZ, 0}",
"{2, 0, BAND_2_4GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}"},
2521 {{0, 0}, {1, 1}, {2, 2}},
2524 ParamsTuple({
"{108, 0, BAND_5GHZ, 0}",
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}"},
2525 {
"{36, 0, BAND_5GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}",
"{5, 0, BAND_6GHZ, 0}"},
2526 {{1, 0}, {0, 1}, {2, 2}},
2529 ParamsTuple({
"{2, 0, BAND_2_4GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{36, 0, BAND_5GHZ, 0}"},
2530 {
"{36, 0, BAND_5GHZ, 0}",
"{9, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
2531 {{2, 0}, {0, 1}, {1, 2}},
2536 {
"{2, 0, BAND_2_4GHZ, 0}",
"{36, 0, BAND_5GHZ, 0}",
"{8, 20, BAND_2_4GHZ, 0}"},
2537 {
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
2544 {
"{2, 0, BAND_2_4GHZ, 0}",
"{36, 0, BAND_5GHZ, 0}",
"{8, 20, BAND_2_4GHZ, 0}"},
2545 {
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
2553 ParamsTuple({
"{2, 0, BAND_2_4GHZ, 0}",
"{36, 0, BAND_5GHZ, 0}",
"{60, 0, BAND_5GHZ, 0}"},
2554 {
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
2560 ParamsTuple({
"{2, 0, BAND_2_4GHZ, 0}",
"{36, 0, BAND_5GHZ, 0}"},
2561 {
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
2565 ParamsTuple({
"{2, 0, BAND_2_4GHZ, 0}",
"{36, 0, BAND_5GHZ, 0}"},
2566 {
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
2570 ParamsTuple({
"{120, 0, BAND_5GHZ, 0}"},
2571 {
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
2575 ParamsTuple({
"{36, 0, BAND_5GHZ, 0}",
"{1, 0, BAND_6GHZ, 0}",
"{120, 0, BAND_5GHZ, 0}"},
2576 {
"{120, 0, BAND_5GHZ, 0}"},
2598 for (
const auto& useBarAfterMissedBa :
2604 useBarAfterMissedBa,
2613 useBarAfterMissedBa,
2627 for (
const auto& useBarAfterMissedBa :
2632 useBarAfterMissedBa,
2640 useBarAfterMissedBa,
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 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.
MultiLinkMuTxTest(WifiMuTrafficPattern muTrafficPattern, WifiUseBarAfterMissedBa useBarAfterMissedBa, uint8_t nMaxInflight, const std::vector< std::string > &staChannels, const std::vector< std::string > &apChannels, const std::vector< uint8_t > &fixedPhyBands={})
Constructor.
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 L7Receive(uint8_t nodeId, Ptr< const Packet > p, const Address &addr)
Function to trace packets received by the server application.
std::array< std::size_t, 3 > m_rxPkts
number of packets received at application layer by each node (AP, STA 0, STA 1)
std::size_t m_nPackets
number of application packets to generate
void Transmit(uint8_t linkId, std::string context, 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.
std::list< uint64_t > m_uidList
list of UIDs of packets to corrupt
std::unordered_map< Mac48Address, Ptr< ListErrorModel >, WifiAddressHash > RxErrorModelMap
Receiver address-indexed map of list error models.
std::size_t m_blockAckCount
transmitted BlockAck counter
void DoSetup() override
Implementation to do any local setup required for this TestCase.
RxErrorModelMap m_errorModels
error rate models to corrupt packets
std::map< AddrSeqNoPair, std::size_t > m_inflightCount
max number of simultaneous transmissions of each data frame
Ptr< WifiMac > m_sourceMac
MAC of the node sending application packets.
void StartTraffic() override
Start the generation of traffic (needs to be overridden)
bool m_useBarAfterMissedBa
whether to send BAR after missed BlockAck
bool m_waitFirstTf
whether we are waiting for the first Basic Trigger Frame
WifiMuTrafficPattern m_muTrafficPattern
the pattern of traffic to generate
std::size_t m_nMaxInflight
max number of links on which an MPDU can be inflight
Base class for Multi-Link Operations tests.
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.
void SetChannels(SpectrumWifiPhyHelper &helper, const std::vector< std::string > &channels, Ptr< MultiModelSpectrumChannel > channel)
Reset the given PHY helper, use the given strings to set the ChannelSettings attribute of the PHY obj...
virtual void Transmit(uint8_t linkId, std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
Callback invoked when a FEM passes PSDUs to the PHY.
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.
uint8_t m_nStations
number of stations to create
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, std::vector< std::string > staChannels, std::vector< std::string > apChannels, std::vector< uint8_t > fixedPhyBands={})
Constructor.
Multi-Link Discovery & Setup test.
void CheckAssocRequest(Ptr< WifiMpdu > mpdu, uint8_t linkId)
Check correctness of the given Association Request frame.
~MultiLinkSetupTest() override=default
MultiLinkSetupTest(std::vector< std::string > staChannels, std::vector< std::string > apChannels, std::vector< std::pair< uint8_t, uint8_t >> setupLinks, std::vector< uint8_t > fixedPhyBands={})
Constructor.
void CheckMlSetup()
Check correctness of Multi-Link Setup procedure.
void CheckDisabledLinks()
Check that links that are not setup on the non-AP MLD are disabled.
const std::vector< std::pair< uint8_t, uint8_t > > m_setupLinks
expected links to setup (STA link ID, AP link ID)
void DoRun() override
Implementation to actually run this TestCase.
void CheckAssocResponse(Ptr< WifiMpdu > mpdu, uint8_t linkId)
Check correctness of the given Association Response frame.
void CheckBeacon(Ptr< WifiMpdu > mpdu, uint8_t linkId)
Check correctness of the given Beacon frame.
Test data transmission between two MLDs.
void Transmit(uint8_t linkId, std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) override
Callback invoked when a FEM passes PSDUs to the PHY.
~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
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)
void L7Receive(uint8_t nodeId, Ptr< const Packet > p, const Address &addr)
Function to trace packets received by the server application.
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::array< std::size_t, 3 > m_rxPkts
number of packets received at application layer by each node (AP, STA 0, STA 1)
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(WifiTrafficPattern trafficPattern, WifiBaEnabled baEnabled, WifiUseBarAfterMissedBa useBarAfterMissedBa, uint8_t nMaxInflight, const std::vector< std::string > &staChannels, const std::vector< std::string > &apChannels, const std::vector< uint8_t > &fixedPhyBands={})
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()
Ptr< ListErrorModel > m_errorModel
error rate model to corrupt first RTS frame
void Transmit(uint8_t linkId, std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) override
Callback invoked when a FEM passes PSDUs to the PHY.
std::size_t m_nQosDataFrames
counter for transmitted QoS data frames
void StartTraffic() override
Start the generation of traffic (needs to be overridden)
PacketSocketAddress m_socket
packet socket address
Ptr< PacketSocketClient > GetApplication() const
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 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)
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.
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.
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 ...
Make it easy to create and manage PHY objects for the spectrum model.
void SetChannel(Ptr< SpectrumChannel > channel)
The IEEE 802.11 SSID Information Element.
AttributeValue implementation for Ssid.
Hold variables of type string.
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Simulation virtual time values and global simulation resolution.
AttributeValue implementation for Time.
Hold an unsigned integer type.
helps to create WifiNetDevice objects
create MAC layers for a ns3::WifiNetDevice.
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
uint8_t GetNLinks() const
Get the number of links (can be greater than 1 for 11be devices only).
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< 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
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)
void SetPostReceptionErrorModel(const Ptr< ErrorModel > em)
Attach a receive ErrorModel to the WifiPhy.
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).
const WifiMacHeader & GetHeader(std::size_t i) const
Get the header of the i-th MPDU.
std::vector< Ptr< WifiMpdu > >::const_iterator begin() const
Return a const iterator to the first MPDU.
Mac48Address GetAddr2() const
Get the Transmitter Address (TA), which is common to all the MPDUs.
Mac48Address GetAddr1() const
Get the Receiver Address (RA), which is common to all the MPDUs.
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,...
void SetDefault(std::string name, const AttributeValue &value)
void Connect(std::string path, const CallbackBase &cb)
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
#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.
Time Now()
create an ns3::Time instance which contains the current simulation time.
#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_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.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
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...
@ WIFI_MAC_MGT_ASSOCIATION_RESPONSE
@ WIFI_MAC_MGT_ASSOCIATION_REQUEST
U * PeekPointer(const Ptr< U > &p)
Information about transmitted frames.
WifiConstPsduMap psduMap
transmitted PSDU map
WifiTxVector txVector
TXVECTOR.
Time startTx
TX start time.
Function object to compute the hash of a MAC address.
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.