20#include "ns3/ap-wifi-mac.h"
21#include "ns3/attribute-container.h"
22#include "ns3/boolean.h"
23#include "ns3/config.h"
24#include "ns3/ctrl-headers.h"
25#include "ns3/eht-configuration.h"
26#include "ns3/emlsr-manager.h"
27#include "ns3/he-frame-exchange-manager.h"
28#include "ns3/header-serialization-test.h"
30#include "ns3/mgt-headers.h"
31#include "ns3/mobility-helper.h"
32#include "ns3/multi-model-spectrum-channel.h"
33#include "ns3/node-list.h"
34#include "ns3/packet-socket-client.h"
35#include "ns3/packet-socket-helper.h"
36#include "ns3/packet-socket-server.h"
37#include "ns3/qos-txop.h"
38#include "ns3/rng-seed-manager.h"
39#include "ns3/rr-multi-user-scheduler.h"
40#include "ns3/simulator.h"
41#include "ns3/spectrum-wifi-helper.h"
42#include "ns3/spectrum-wifi-phy.h"
43#include "ns3/sta-wifi-mac.h"
44#include "ns3/string.h"
45#include "ns3/wifi-net-device.h"
46#include "ns3/wifi-ppdu.h"
47#include "ns3/wifi-psdu.h"
74 void DoRun()
override;
79 "Check serialization and deserialization of the EML Operating Mode Notification frame")
101 "Unexpected link bitmap");
118 "Unexpected EMLSR Padding Delay");
122 "Unexpected EMLSR Transition Delay");
205 std::string description,
206 bool testUnblockedForOtherReasons =
true);
273 auto linkId = mac->GetLinkForPhy(phyId);
280 for (
const auto& [aid, psdu] : psduMap)
282 std::stringstream ss;
283 ss << std::setprecision(10) <<
"PSDU #" <<
m_txPsdus.size() <<
" Link ID "
284 << +linkId.value() <<
" Phy ID " << +phyId <<
" " << psdu->GetHeader(0).GetTypeString();
285 if (psdu->GetHeader(0).IsAction())
289 psdu->GetPayload(0)->PeekHeader(actionHdr);
292 ss <<
" #MPDUs " << psdu->GetNMpdus() <<
" duration/ID " << psdu->GetHeader(0).GetDuration()
293 <<
" RA = " << psdu->GetAddr1() <<
" TA = " << psdu->GetAddr2()
294 <<
" ADDR3 = " << psdu->GetHeader(0).GetAddr3()
295 <<
" ToDS = " << psdu->GetHeader(0).IsToDs()
296 <<
" FromDS = " << psdu->GetHeader(0).IsFromDs();
297 if (psdu->GetHeader(0).IsQosData())
302 ss << mpdu->GetHeader().GetSequenceNumber() <<
",";
304 ss <<
"} TID = " << +psdu->GetHeader(0).GetQosTid();
308 NS_LOG_INFO(
"TX duration = " << txDuration.As(
Time::MS) <<
" TXVECTOR = " << txVector <<
"\n");
316 int64_t streamNumber = 100;
324 wifi.SetRemoteStationManager(
"ns3::ConstantRateWifiManager",
329 wifi.ConfigEhtOptions(
"EmlsrActivated",
337 phyHelper.
Set(0,
"ChannelSettings",
StringValue(
"{2, 0, BAND_2_4GHZ, 0}"));
338 phyHelper.
Set(1,
"ChannelSettings",
StringValue(
"{36, 0, BAND_5GHZ, 0}"));
339 phyHelper.
Set(2,
"ChannelSettings",
StringValue(
"{1, 0, BAND_6GHZ, 0}"));
346 mac.SetType(
"ns3::ApWifiMac",
354 mac.SetType(
"ns3::StaWifiMac",
359 mac.SetEmlsrManager(
"ns3::DefaultEmlsrManager",
367 m_apMac = DynamicCast<ApWifiMac>(DynamicCast<WifiNetDevice>(apDevice.
Get(0))->GetMac());
369 for (
uint32_t i = 0; i < staDevices.GetN(); i++)
371 auto device = DynamicCast<WifiNetDevice>(staDevices.Get(i));
372 auto staMac = DynamicCast<StaWifiMac>(device->GetMac());
374 staMac->GetEmlsrManager()->SetAttribute(
"EmlsrPaddingDelay",
377 staMac->GetEmlsrManager()->SetAttribute(
"EmlsrTransitionDelay",
384 wifi.ConfigEhtOptions(
"EmlsrActivated",
BooleanValue(
false));
386 staDevices.Add(wifi.Install(phyHelper, mac, otherStaNodes));
387 wifiStaNodes.Add(otherStaNodes);
390 for (
uint32_t i = 0; i < staDevices.GetN(); i++)
392 auto device = DynamicCast<WifiNetDevice>(staDevices.Get(i));
393 m_staMacs.push_back(DynamicCast<StaWifiMac>(device->GetMac()));
400 "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phys/" + std::to_string(phyId) +
406 for (uint8_t phyId = 0; phyId <
m_staMacs[i]->GetDevice()->GetNPhys(); phyId++)
409 "/NodeList/" + std::to_string(i + 1) +
"/DeviceList/*/$ns3::WifiNetDevice/Phys/" +
410 std::to_string(phyId) +
"/PhyTxPsduBegin",
420 streamNumber += wifi.AssignStreams(apDevice, streamNumber);
421 streamNumber += wifi.AssignStreams(staDevices, streamNumber);
429 positionAlloc->Add(Vector(std::min<double>(
id, 1), 0.0, 0.0));
431 mobility.SetPositionAllocator(positionAlloc);
433 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
434 mobility.Install(wifiApNode);
435 mobility.Install(wifiStaNodes);
439 packetSocket.
Install(wifiApNode);
440 packetSocket.
Install(wifiStaNodes);
446 auto device = DynamicCast<WifiNetDevice>((*nodeIt)->GetDevice(0));
451 auto server = CreateObject<PacketSocketServer>();
452 server->SetLocal(srvAddr);
453 (*nodeIt)->AddApplication(server);
454 server->SetStartTime(
Seconds(0));
463 m_dlSockets.back().SetPhysicalAddress(staMac->GetDevice()->GetAddress());
467 m_ulSockets.back().SetSingleDevice(staMac->GetDevice()->GetIfIndex());
484 auto client = CreateObject<PacketSocketClient>();
489 client->SetStartTime(
Seconds(0));
523 m_staMacs[aid - 1]->GetDevice()->GetNode()->AddApplication(
548 std::string description,
549 bool testUnblockedForOtherReasons)
552 auto mask = mac->GetMacQueueScheduler()->GetQueueLinkMask(
AC_BE, queueId, linkId);
555 description <<
": Expected to find a mask for EMLSR link " << +linkId);
560 description <<
": Expected EMLSR link " << +linkId
561 <<
" to be blocked for reason " << reason);
562 if (testUnblockedForOtherReasons)
566 description <<
": Expected EMLSR link " << +linkId
567 <<
" to be blocked for one reason only");
570 else if (testUnblockedForOtherReasons)
574 description <<
": Expected EMLSR link " << +linkId
575 <<
" to be unblocked");
581 description <<
": Expected EMLSR link " << +linkId
582 <<
" to be unblocked for reason " << reason);
622 void DoRun()
override;
627 double txPowerW)
override;
693 Time transitionTimeout)
695 m_checkEmlsrLinksCount(0),
696 m_emlNotificationDroppedCount(0)
716 m_staMacs[0]->TraceConnectWithoutContext(
"AckedMpdu",
718 m_staMacs[0]->TraceConnectWithoutContext(
"DroppedMpdu",
732 auto psdu = psduMap.begin()->second;
734 switch (psdu->GetHeader(0).GetType())
748 action.protectedEhtAction ==
754 m_staMacs[0]->GetLinkIdByAddress(psdu->GetAddr2()) == linkId)
757 m_uidList.push_front(psdu->GetPacket()->GetUid());
773 mpdu->GetPacket()->PeekHeader(frame);
780 "Multi-Link Element in AssocReq must have EML Capabilities");
783 "EML Support subfield of EML Capabilities in AssocReq must be set to 1");
786 "Unexpected Padding Delay in EML Capabilities included in AssocReq");
789 "Unexpected Transition Delay in EML Capabilities included in AssocReq");
797 bool sentToEmlsrClient =
798 (
m_staMacs[0]->GetLinkIdByAddress(mpdu->GetHeader().GetAddr1()) == linkId);
800 if (!sentToEmlsrClient)
807 mpdu->GetPacket()->PeekHeader(frame);
814 "Multi-Link Element in AssocResp must have EML Capabilities");
817 "EML Support subfield of EML Capabilities in AssocResp must be set to 1");
819 mle->GetTransitionTimeout(),
821 "Unexpected Transition Timeout in EML Capabilities included in AssocResp");
830 auto mpdu = *psdu->begin();
831 auto pkt = mpdu->GetPacket()->Copy();
833 pkt->RemoveHeader(frame);
836 bool sentbyNonApMld =
m_staMacs[0]->GetLinkIdByAddress(mpdu->GetHeader().GetAddr2()) == linkId;
840 "EMLSR Mode subfield should be set to 1 (frame sent by non-AP MLD: "
841 << std::boolalpha << sentbyNonApMld <<
")");
845 "EMLMR Mode subfield should be set to 0 (frame sent by non-AP MLD: "
846 << std::boolalpha << sentbyNonApMld <<
")");
850 "Link Bitmap subfield should be present (frame sent by non-AP MLD: "
851 << std::boolalpha << sentbyNonApMld <<
")");
853 auto setupLinks =
m_staMacs[0]->GetSetupLinkIds();
854 std::list<uint8_t> expectedEmlsrLinks;
855 std::set_intersection(setupLinks.begin(),
859 std::back_inserter(expectedEmlsrLinks));
863 "Unexpected Link Bitmap subfield (frame sent by non-AP MLD: "
864 << std::boolalpha << sentbyNonApMld <<
")");
872 "EMLSR Parameter Update Control should be set to 0 in frames sent by the AP MLD");
877 m_staMacs[0]->GetWifiPhy(linkId)->GetPhyBand()) +
884 "EML Notification received on unexpected link (frame sent by non-AP MLD: "
885 << std::boolalpha << sentbyNonApMld <<
")");
891 const auto& hdr = mpdu->GetHeader();
893 if (hdr.IsMgt() && hdr.IsAction())
897 action.protectedEhtAction ==
912 const auto& hdr = mpdu->GetHeader();
914 if (hdr.IsMgt() && hdr.IsAction())
918 action.protectedEhtAction ==
933 auto setupLinks =
m_staMacs[0]->GetSetupLinkIds();
934 std::set<uint8_t> expectedEmlsrLinks;
935 std::set_intersection(setupLinks.begin(),
939 std::inserter(expectedEmlsrLinks, expectedEmlsrLinks.end()));
943 "Unexpected set of EMLSR links)");
954 "Unexpected number of times CheckEmlsrLinks() is called");
958 "Unexpected number of times the EML Notification frame is dropped due to max retry limit");
1030 std::size_t nNonEmlsrStations,
1031 const std::set<uint8_t>& linksToEnableEmlsrOn,
1032 const std::vector<Time>& paddingDelay,
1033 const std::vector<Time>& transitionDelay,
1034 Time transitionTimeout);
1039 void DoRun()
override;
1044 double txPowerW)
override;
1125 std::size_t nNonEmlsrStations,
1126 const std::set<uint8_t>& linksToEnableEmlsrOn,
1127 const std::vector<Time>& paddingDelay,
1128 const std::vector<Time>& transitionDelay,
1129 Time transitionTimeout)
1131 "," +
std::to_string(nNonEmlsrStations) +
")"),
1132 m_emlsrLinks(linksToEnableEmlsrOn),
1133 m_emlsrEnabledTime(0),
1135 m_countQoSframes(0),
1149 "This test requires at least two links to be configured as EMLSR links");
1162 auto psdu = psduMap.begin()->second;
1163 auto nodeId = mac->GetDevice()->GetNode()->GetId();
1165 switch (psdu->GetHeader(0).GetType())
1168 NS_ASSERT_MSG(nodeId > 0,
"APs do not send AssocReq frames");
1175 for (
const auto id :
m_staMacs.at(nodeId - 1)->GetLinkIds())
1179 m_staMacs[nodeId - 1]->SetPowerSaveMode({
true,
id});
1189 action.protectedEhtAction ==
1235 CreateObjectWithAttributes<RrMultiUserScheduler>(
"EnableUlOfdma",
BooleanValue(
false));
1240 "DlMuAckSequenceType",
1283 m_staMacs.at(
id)->GetEmlsrManager()->SetAttribute(
1322 auto jumpToQosDataOrMuRts = [&]() {
1324 !psduIt->psduMap.cbegin()->second->GetHeader(0).IsQosData())
1326 auto psdu = psduIt->psduMap.cbegin()->second;
1327 if (psdu->GetHeader(0).IsTrigger())
1330 psdu->GetPayload(0)->PeekHeader(trigger);
1394 std::set<uint8_t> linkIds;
1396 jumpToQosDataOrMuRts();
1398 psduIt->psduMap.cbegin()->second->GetHeader(0).IsQosData()),
1400 "Expected at least one QoS data frame before enabling EMLSR mode");
1401 linkIds.insert(psduIt->linkId);
1402 const auto firstAmpduTxEnd =
1406 m_staMacs[i]->GetWifiPhy(psduIt->linkId)->GetPhyBand());
1409 jumpToQosDataOrMuRts();
1411 psduIt->psduMap.cbegin()->second->GetHeader(0).IsQosData()),
1413 "Expected at least two QoS data frames before enabling EMLSR mode");
1414 linkIds.insert(psduIt->linkId);
1415 const auto secondAmpduTxStart = psduIt->startTx;
1423 auto setupLinks =
m_staMacs[i]->GetSetupLinkIds();
1425 std::none_of(setupLinks.begin(), setupLinks.end(), [&](
auto&& linkId) {
1426 return linkId != m_mainPhyId && m_emlsrLinks.count(linkId) == 0;
1431 "Expected both A-MPDUs to be sent on the same link");
1435 "A-MPDUs are not sent one after another");
1445 "Expected A-MPDUs to be sent on distinct links");
1448 "A-MPDUs are not sent concurrently");
1514 using FrameExchange = std::list<
decltype(psduIt)>;
1521 jumpToQosDataOrMuRts();
1530 psduIt->psduMap.cbegin()->second->GetPayload(0)->PeekHeader(trigger);
1535 "jumpToQosDataOrMuRts does not return TFs other than MU-RTS");
1536 for (
const auto& userInfo : trigger)
1540 if (
m_staMacs.at(i)->GetAssociationId() == userInfo.GetAid12())
1542 frameExchanges.at(i).emplace_back(FrameExchange{psduIt});
1554 for (
const auto& staIdPsduPair : psduIt->psduMap)
1557 if (!staMac->GetLinkIdByAddress(staIdPsduPair.second->GetAddr1()))
1565 std::size_t
id = staMac->GetDevice()->GetNode()->GetId() - 1;
1566 for (
auto& frameExchange : frameExchanges.at(
id))
1568 if (IsTrigger(frameExchange.front()->psduMap) &&
1569 frameExchange.front()->linkId == psduIt->linkId &&
1570 frameExchange.size() == 1)
1572 auto it = std::next(frameExchange.front());
1573 while (it != m_txPsdus.end())
1576 if (it->linkId == psduIt->linkId &&
1577 !it->psduMap.begin()->second->GetHeader(0).IsCts())
1586 frameExchange.emplace_back(psduIt);
1591 frameExchanges.at(
id).emplace_back(FrameExchange{psduIt});
1603 for (std::size_t i = 0; i < m_nEmlsrStations; i++)
1607 "Expected at least 2 frame exchange sequences "
1608 <<
"involving EMLSR client " << i);
1610 auto firstExchangeIt = frameExchanges.at(i).begin();
1611 auto secondExchangeIt = std::next(firstExchangeIt);
1613 const auto firstAmpduTxEnd =
1614 firstExchangeIt->back()->startTx +
1616 firstExchangeIt->back()->psduMap,
1617 firstExchangeIt->back()->txVector,
1618 m_staMacs[i]->GetWifiPhy(firstExchangeIt->back()->linkId)->GetPhyBand());
1619 const auto secondAmpduTxStart = secondExchangeIt->front()->startTx;
1621 if (m_staMacs[i]->GetNLinks() == m_emlsrLinks.size())
1626 "Expected an MU-RTS TF as ICF of first frame exchange sequence");
1628 firstExchangeIt->back()->psduMap.cbegin()->second->GetHeader(0).IsQosData(),
1630 "Expected a QoS data frame in the first frame exchange sequence");
1634 "Expected an MU-RTS TF as ICF of second frame exchange sequence");
1636 secondExchangeIt->back()->psduMap.cbegin()->second->GetHeader(0).IsQosData(),
1638 "Expected a QoS data frame in the second frame exchange sequence");
1642 "A-MPDUs are not sent one after another");
1646 std::vector<uint8_t> nonEmlsrIds;
1647 auto setupLinks = m_staMacs[i]->GetSetupLinkIds();
1648 std::set_difference(setupLinks.begin(),
1650 m_emlsrLinks.begin(),
1652 std::back_inserter(nonEmlsrIds));
1655 auto nonEmlsrLinkExchangeIt = firstExchangeIt->front()->linkId == nonEmlsrIds[0]
1660 "Did not expect an MU-RTS TF as ICF on non-EMLSR link");
1662 nonEmlsrLinkExchangeIt->front()->psduMap.cbegin()->second->GetHeader(0).IsQosData(),
1664 "Expected a QoS data frame on the non-EMLSR link");
1666 auto emlsrLinkExchangeIt =
1667 nonEmlsrLinkExchangeIt == firstExchangeIt ? secondExchangeIt : firstExchangeIt;
1670 "Expected this exchange not to occur on non-EMLSR link");
1673 "Expected an MU-RTS TF as ICF on the EMLSR link");
1675 emlsrLinkExchangeIt->back()->psduMap.cbegin()->second->GetHeader(0).IsQosData(),
1677 "Expected a QoS data frame on the EMLSR link");
1681 "A-MPDUs are not sent concurrently");
1685 frameExchanges.at(i).erase(firstExchangeIt);
1686 frameExchanges.at(i).erase(secondExchangeIt);
1714 if (m_nEmlsrStations == 2 && m_apMac->GetNLinks() == m_emlsrLinks.size())
1717 for (std::size_t i = 0; i < m_nEmlsrStations; i++)
1721 "Expected at least 2 frame exchange sequences "
1722 <<
"involving EMLSR client " << i);
1724 auto firstExchangeIt = frameExchanges.at(i).begin();
1728 "Expected an MU-RTS TF as ICF of first frame exchange sequence");
1730 firstExchangeIt->back()->psduMap.cbegin()->second->GetHeader(0).IsQosData(),
1732 "Expected a QoS data frame in the first frame exchange sequence");
1736 auto secondExchangeIt = std::next(frameExchanges.at(0).begin())->front()->startTx <
1737 std::next(frameExchanges.at(1).begin())->front()->startTx
1738 ? std::next(frameExchanges.at(0).begin())
1739 :
std::next(frameExchanges.at(1).begin());
1740 decltype(secondExchangeIt) thirdExchangeIt;
1741 std::size_t thirdExchangeStaId;
1743 if (secondExchangeIt == std::next(frameExchanges.at(0).begin()))
1745 thirdExchangeIt = std::next(frameExchanges.at(1).begin());
1746 thirdExchangeStaId = 1;
1750 thirdExchangeIt = std::next(frameExchanges.at(0).begin());
1751 thirdExchangeStaId = 0;
1758 "Expected no ICF for the second frame exchange sequence");
1760 secondExchangeIt->front()->psduMap.cbegin()->second->GetHeader(0).IsQosData(),
1762 "Expected a QoS data frame in the second frame exchange sequence");
1766 +frameExchanges.at(0).begin()->front()->linkId,
1767 "Expected the first two frame exchanges to occur on the same link");
1769 auto bAckRespIt = std::prev(secondExchangeIt->front());
1772 "Expected a BlockAck response before the second frame exchange");
1773 auto bAckRespTxEnd =
1774 bAckRespIt->startTx +
1776 bAckRespIt->txVector,
1777 m_apMac->GetWifiPhy(bAckRespIt->linkId)->GetPhyBand());
1781 bAckRespTxEnd + m_apMac->GetWifiPhy(bAckRespIt->linkId)->GetSifs(),
1782 secondExchangeIt->front()->startTx,
1783 "Expected the second frame exchange to start a SIFS after the first one");
1788 "Expected an MU-RTS as ICF for the third frame exchange sequence");
1790 thirdExchangeIt->back()->psduMap.cbegin()->second->GetHeader(0).IsQosData(),
1792 "Expected a QoS data frame in the third frame exchange sequence");
1795 +secondExchangeIt->front()->linkId,
1796 +thirdExchangeIt->front()->linkId,
1797 "Expected the second and third frame exchanges to occur on distinct links");
1799 auto secondQosIt = secondExchangeIt->front();
1800 auto secondQosTxEnd =
1801 secondQosIt->startTx +
1803 secondQosIt->txVector,
1804 m_apMac->GetWifiPhy(secondQosIt->linkId)->GetPhyBand());
1807 secondQosTxEnd + m_transitionDelay.at(thirdExchangeStaId),
1808 "Transmission started before transition delay");
1814 "Expected a fourth frame exchange");
1815 auto fourthExchangeIt = std::next(thirdExchangeIt);
1820 "Expected an MU-RTS as ICF for the fourth frame exchange sequence");
1822 bAckRespIt = std::prev(fourthExchangeIt->front());
1825 "Expected a BlockAck response before the fourth frame exchange");
1826 auto phy = m_apMac->GetWifiPhy(bAckRespIt->linkId);
1828 bAckRespIt->txVector,
1836 bAckRespTxEnd +
phy->GetSifs(),
1837 "Transmission started less than a SIFS after BlockAck");
1839 bAckRespTxEnd +
phy->GetSifs() +
1841 "Transmission started too much time after BlockAck");
1843 auto bAckReqIt = std::next(fourthExchangeIt->front(), 2);
1846 "Expected a BlockAck request in the fourth frame exchange");
1850 frameExchanges.at(0).pop_front();
1851 frameExchanges.at(0).pop_front();
1852 frameExchanges.at(1).pop_front();
1853 frameExchanges.at(1).pop_front();
1854 frameExchanges.at(thirdExchangeStaId).pop_front();
1915 for (std::size_t i = 0; i < m_nEmlsrStations; i++)
1920 auto exchangeIt = frameExchanges.at(i).cbegin();
1922 auto linkIdOpt = m_staMacs[i]->GetLinkForPhy(m_mainPhyId);
1925 "Didn't find a link on which the main PHY is operating");
1929 "Expected an MU-RTS TF as ICF of first frame exchange sequence");
1932 "ICF was not sent on the expected link");
1935 "Expected no data frame in the first frame exchange sequence");
1937 frameExchanges.at(i).pop_front();
1941 "Expected at least 2 frame exchange sequences "
1942 <<
"involving EMLSR client " << i);
1944 auto firstExchangeIt = frameExchanges.at(i).cbegin();
1945 auto secondExchangeIt = std::next(firstExchangeIt);
1947 const auto firstAmpduTxEnd =
1948 firstExchangeIt->back()->startTx +
1950 firstExchangeIt->back()->psduMap,
1951 firstExchangeIt->back()->txVector,
1952 m_staMacs[i]->GetWifiPhy(firstExchangeIt->back()->linkId)->GetPhyBand());
1953 const auto secondAmpduTxStart = secondExchangeIt->front()->startTx;
1956 firstExchangeIt->front()->psduMap.cbegin()->second->GetHeader(0).IsQosData(),
1958 "Expected a QoS data frame in the first frame exchange sequence");
1961 "Expected one frame only in the first frame exchange sequence");
1964 secondExchangeIt->front()->psduMap.cbegin()->second->GetHeader(0).IsQosData(),
1966 "Expected a QoS data frame in the second frame exchange sequence");
1969 "Expected one frame only in the second frame exchange sequence");
1971 if (m_staMacs[i]->GetNLinks() == m_emlsrLinks.size())
1976 +firstExchangeIt->front()->linkId,
1978 "First frame exchange expected to occur on link used to send EML OMN");
1981 +secondExchangeIt->front()->linkId,
1983 "Second frame exchange expected to occur on link used to send EML OMN");
1987 "A-MPDUs are not sent one after another");
1993 +secondExchangeIt->front()->linkId,
1994 "Frame exchanges expected to occur on distinct links");
1998 "A-MPDUs are not sent concurrently");
2006 std::optional<std::size_t> staId;
2009 if (
m_staMacs.at(
id)->GetLinkIdByAddress(address))
2022 bool psModeExpected =
2024 auto addr =
m_staMacs.at(*staId)->GetAddress();
2028 "EMLSR link " << +linkId <<
" of EMLSR client " << *staId
2029 <<
" not in " << (psModeExpected ?
"PS" :
"active")
2035 WifiQueueBlockedReason::POWER_SAVE_MODE,
2037 "Checking PM mode after association on AP MLD for EMLSR client " +
2038 std::to_string(*staId),
2049 auto pkt = mpdu->GetPacket()->Copy();
2050 const auto& hdr = mpdu->GetHeader();
2053 pkt->RemoveHeader(frame);
2055 std::optional<std::size_t> staId;
2058 if (
m_staMacs.at(
id)->GetFrameExchangeManager(linkId)->GetAddress() == hdr.GetAddr1())
2066 "Not an address of an EMLSR client " << hdr.GetAddr1());
2075 m_staMacs.at(*staId)->GetWifiRemoteStationManager(linkId)->GetAckTxVector(hdr.GetAddr2(),
2082 if (frame.m_emlControl.emlsrMode == 1)
2086 for (const auto linkId : m_emlsrLinks)
2088 auto addr = m_staMacs.at(*staId)->GetAddress();
2089 auto psMode = m_apMac->GetWifiRemoteStationManager(linkId)->IsInPsMode(addr);
2090 NS_TEST_EXPECT_MSG_EQ(psMode,
2092 "EMLSR link " << +linkId <<
" of EMLSR client " << *staId
2093 <<
" not in active mode");
2099 WifiQueueBlockedReason::POWER_SAVE_MODE,
2101 "Checking EMLSR links on AP MLD after EMLSR mode is enabled on EMLSR client " +
2102 std::to_string(*staId),
2111 for (uint8_t id = 0; id < m_apMac->GetNLinks(); id++)
2113 bool psModeExpected = id != linkId && m_emlsrLinks.count(id) == 1;
2114 auto addr = m_staMacs.at(*staId)->GetAddress();
2115 auto psMode = m_apMac->GetWifiRemoteStationManager(id)->IsInPsMode(addr);
2116 NS_TEST_EXPECT_MSG_EQ(psMode,
2119 << +id <<
" of EMLSR client " << *staId <<
" not in "
2120 << (psModeExpected ?
"PS" :
"active") <<
" mode");
2126 WifiQueueBlockedReason::POWER_SAVE_MODE,
2128 "Checking links on AP MLD after EMLSR mode is disabled on EMLSR client " +
2129 std::to_string(*staId),
2142 mpdu->GetPacket()->PeekHeader(trigger);
2150 "Did not expect an ICF before enabling EMLSR mode");
2154 "Unexpected preamble type for the Initial Control frame");
2158 "Unexpected rate for the Initial Control frame: " << rate);
2161 Time maxPaddingDelay{};
2163 for (
const auto& userInfo : trigger)
2168 "AID " << userInfo.GetAid12() <<
" not found");
2176 if (
m_staMacs.at(i)->GetAddress() == *addr)
2194 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2196 "Checking that AP blocked transmissions on all other EMLSR "
2197 "links after sending ICF to client with AID=" +
2198 std::to_string(userInfo.GetAid12()));
2209 if (maxPaddingDelay.IsStrictlyPositive())
2214 auto pkt = Create<Packet>();
2215 pkt->AddHeader(trigger);
2216 auto txDurationWithout =
2222 txDurationWithout + maxPaddingDelay,
2223 "Unexpected TX duration of the MU-RTS TF with padding "
2229 for (
const auto& userInfo : trigger)
2233 if (
m_staMacs[i]->GetAssociationId() != userInfo.GetAid12())
2239 for (uint8_t
id = 0;
id <
m_staMacs[i]->GetNLinks();
id++)
2245 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2246 id != linkId &&
m_staMacs[i]->IsEmlsrLink(
id),
2247 "Checking EMLSR links on EMLSR client " + std::to_string(i) +
2248 " after receiving ICF");
2270 std::size_t firstClientId = 0;
2271 std::size_t secondClientId = 1;
2272 auto addr =
m_staMacs[secondClientId]->GetAddress();
2285 for (std::size_t clientId : {firstClientId, secondClientId})
2288 for (uint8_t
id = 0;
id <
m_staMacs[clientId]->GetNLinks();
id++)
2294 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2296 "Checking EMLSR links on EMLSR client " +
2297 std::to_string(clientId) +
2298 " after receiving the first QoS data frame");
2310 for (std::size_t clientId : {firstClientId, secondClientId})
2312 for (uint8_t
id = 0;
id <
m_staMacs[clientId]->GetNLinks();
id++)
2318 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2320 "Checking EMLSR links on EMLSR client " +
2321 std::to_string(clientId) +
2322 " when starting the reception of the second QoS frame");
2338 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2340 "Checking that links of EMLSR client " +
2341 std::to_string(secondClientId) +
2342 " are blocked on the AP MLD before the end of the PPDU");
2349 for (uint8_t
id = 0;
id <
m_staMacs[secondClientId]->GetNLinks();
id++)
2354 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2356 "Checking that links of EMLSR client " +
2357 std::to_string(secondClientId) +
2358 " are unblocked before the end of the second QoS frame");
2368 WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY,
2370 "Checking links of EMLSR client " +
2371 std::to_string(secondClientId) +
2372 " are all blocked on the AP MLD after the end of the PPDU");
2385 WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY,
2387 "Checking links of EMLSR client " + std::to_string(secondClientId) +
2388 " are all blocked on the AP MLD before the transition delay");
2402 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2404 "Checking EMLSR links on EMLSR client " +
2405 std::to_string(secondClientId) +
2406 " after receiving the third QoS data frame");
2425 auto taddr = psduMap.cbegin()->second->GetAddr2();
2426 std::size_t clientId;
2427 if (
m_staMacs[0]->GetLinkIdByAddress(taddr))
2435 "Unexpected TA for BlockAck: " << taddr);
2440 auto currMainPhyLinkId =
m_staMacs[clientId]->GetLinkForPhy(phyId);
2442 currMainPhyLinkId.has_value(),
2444 "Didn't find the link on which the PHY sending the BlockAck is operating");
2445 auto linkId = *currMainPhyLinkId;
2456 apPhy->GetPhyBand());
2476 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2478 "Checking links on EMLSR client " + std::to_string(clientId) +
2479 " at the end of fourth BlockAck");
2483 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2485 "Checking links of EMLSR client " + std::to_string(clientId) +
2486 " on the AP MLD at the end of fourth BlockAck");
2492 for (uint8_t id = 0; id < m_apMac->GetNLinks(); id++)
2494 CheckBlockedLink(m_staMacs[clientId],
2495 m_apMac->GetAddress(),
2497 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2499 "Checking links on EMLSR client " + std::to_string(clientId) +
2500 " a SIFS after the end of fourth BlockAck");
2501 CheckBlockedLink(m_apMac,
2504 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2506 "Checking links of EMLSR client " + std::to_string(clientId) +
2507 " a SIFS after the end of fourth BlockAck");
2512 auto uid = psduMap.cbegin()->second->GetPacket()->
GetUid();
2525 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2527 "Checking links on EMLSR client " + std::to_string(clientId) +
2528 " at the end of fifth BlockAck");
2532 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2534 "Checking links of EMLSR client " + std::to_string(clientId) +
2535 " on the AP MLD at the end of fifth BlockAck");
2541 txDuration + apPhy->GetSifs() + cfEndTxDuration -
MicroSeconds(1),
2548 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2550 "Checking links on EMLSR client " + std::to_string(clientId) +
2551 " before the end of CF-End frame");
2555 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2557 "Checking links of EMLSR client " + std::to_string(clientId) +
2558 " on the AP MLD before the end of CF-End frame");
2564 txDuration + apPhy->GetSifs() + cfEndTxDuration +
MicroSeconds(1),
2572 WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY,
2574 "Checking links of EMLSR client " + std::to_string(clientId) +
2575 " are all blocked on the AP MLD right after the end of CF-End");
2581 txDuration + apPhy->GetSifs() + cfEndTxDuration +
m_transitionDelay.at(clientId) -
2590 WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY,
2592 "Checking links of EMLSR client " + std::to_string(clientId) +
2593 " are all blocked on the AP MLD before the end of transition delay");
2598 txDuration + apPhy->GetSifs() + cfEndTxDuration +
m_transitionDelay.at(clientId) +
2607 WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY,
2609 "Checking links of EMLSR client " + std::to_string(clientId) +
2610 " are all unblocked on the AP MLD after the transition delay");
2662 void DoRun()
override;
2667 double txPowerW)
override;
2710 uint16_t auxPhyMaxChWidth)
2712 std::to_string(switchAuxPhy) +
2713 ", resetCamState=" +
std::to_string(resetCamState) +
2714 ", auxPhyMaxChWidth=" +
std::to_string(auxPhyMaxChWidth) +
"MHz )"),
2715 m_switchAuxPhy(switchAuxPhy),
2716 m_resetCamState(resetCamState),
2717 m_auxPhyMaxChWidth(auxPhyMaxChWidth),
2718 m_countQoSframes(0),
2739 auto psdu = psduMap.begin()->second;
2740 auto nodeId = mac->GetDevice()->GetNode()->GetId();
2742 switch (psdu->GetHeader(0).GetType())
2745 NS_ASSERT_MSG(nodeId > 0,
"APs do not send AssocReq frames");
2753 action.protectedEhtAction ==
2760 std::set<uint8_t> linksToBlock;
2765 linksToBlock.insert(
id);
2809 mac->GetWifiPhy(0)->SetOperatingChannel(
2811 mac->GetWifiPhy(1)->SetOperatingChannel(
2813 mac->GetWifiPhy(2)->SetOperatingChannel(
2962 auto phyRecvIcf =
m_staMacs[0]->GetWifiPhy(linkId);
2964 auto currMainPhyLinkId =
m_staMacs[0]->GetLinkForPhy(mainPhy);
2967 "Didn't find the link on which the Main PHY is operating");
2969 if (phyRecvIcf && phyRecvIcf != mainPhy)
2972 phyRecvIcf->GetChannelWidth(),
2974 "Aux PHY that received ICF is operating on a channel whose width exceeds the limit "
2990 "PHY operating on link where ICF was sent is not the main PHY");
2998 "PHY that received the ICF is not the main PHY");
3007 NS_TEST_EXPECT_MSG_EQ(m_staMacs[0]->GetWifiPhy(*currMainPhyLinkId),
3009 "PHY operating on link where Main PHY was before switching "
3010 "channel is not the aux PHY that received the ICF");
3019 "No PHY expected to operate on link where Main PHY was "
3020 "before switching channel");
3027 "Expected no PHY to operate on link where ICF is sent");
3041 "Insufficient number of TX PSDUs");
3046 for (std::size_t i = 0; i < nRxOk; i++)
3049 psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsTrigger()),
3051 "Expected a Trigger Frame (ICF)");
3054 (psduIt->psduMap.size() == 1 && psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsCts()),
3059 psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsQosData()),
3061 "Expected a QoS Data frame");
3064 psduIt->psduMap.at(
SU_STA_ID)->GetHeader(0).IsBlockAck()),
3066 "Expected a BlockAck");
3091 for (
const auto& emlsrLinks :
3092 {std::set<uint8_t>{0, 1, 2}, std::set<uint8_t>{1, 2}, std::set<uint8_t>{0, 1}})
3117 for (
bool switchAuxPhy : {
true,
false})
3119 for (
bool resetCamState : {
true,
false})
3121 for (uint16_t auxPhyMaxChWidth : {20, 40, 80, 160})
Test the exchange of EML Operating Mode Notification frames.
void CheckEmlCapabilitiesInAssocResp(Ptr< const WifiMpdu > mpdu, const WifiTxVector &txVector, uint8_t linkId)
Check the content of the EML Capabilities subfield of the Multi-Link Element included in the Associat...
void TxOk(Ptr< const WifiMpdu > mpdu)
Callback invoked when the non-AP MLD receives the acknowledgment for a transmitted MPDU.
std::list< uint64_t > m_uidList
list of UIDs of packets to corrupt
std::size_t m_checkEmlsrLinksCount
counter for the number of times CheckEmlsrLinks is called (should be two: when the transition timeout...
Ptr< ListErrorModel > m_errorModel
error rate model to corrupt packets at AP MLD
void DoSetup() override
Implementation to do any local setup required for this TestCase.
EmlOmnExchangeTest(const std::set< uint8_t > &linksToEnableEmlsrOn, Time transitionTimeout)
Constructor.
std::size_t m_emlNotificationDroppedCount
counter for the number of times the EML Notification frame sent by the non-AP MLD has been dropped du...
void CheckEmlsrLinks()
Check that the EMLSR mode has been enabled on the expected EMLSR links.
void CheckEmlCapabilitiesInAssocReq(Ptr< const WifiMpdu > mpdu, const WifiTxVector &txVector, uint8_t linkId)
Check the content of the EML Capabilities subfield of the Multi-Link Element included in the Associat...
~EmlOmnExchangeTest() override=default
void TxDropped(WifiMacDropReason reason, Ptr< const WifiMpdu > mpdu)
Callback invoked when the non-AP MLD drops the given MPDU for the given reason.
void CheckEmlNotification(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector, uint8_t linkId)
Check the content of a received EML Operating Mode Notification frame.
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 EML Operating Mode Notification frame serialization and deserialization.
EmlOperatingModeNotificationTest()
Constructor.
void DoRun() override
Implementation to actually run this TestCase.
~EmlOperatingModeNotificationTest() override=default
Test the transmission of DL frames to EMLSR clients.
void CheckInitialControlFrame(Ptr< const WifiMpdu > mpdu, const WifiTxVector &txVector, uint8_t linkId)
Check that appropriate actions are taken by the AP MLD transmitting an initial Control frame to an EM...
const Time m_fe2to3delay
time interval between 2nd and 3rd frame exchange sequences after the enablement of EMLSR mode
void CheckResults()
Check that the simulation produced the expected results.
EmlsrDlTxopTest(std::size_t nEmlsrStations, std::size_t nNonEmlsrStations, const std::set< uint8_t > &linksToEnableEmlsrOn, const std::vector< Time > &paddingDelay, const std::vector< Time > &transitionDelay, Time transitionTimeout)
Constructor.
void CheckPmModeAfterAssociation(const Mac48Address &address)
Check that the AP MLD considers the correct Power Management mode for the links setup with the given ...
void StartTraffic() override
Start the generation of traffic (needs to be overridden)
Ptr< ListErrorModel > m_errorModel
error rate model to corrupt BlockAck at AP MLD
std::size_t m_countQoSframes
counter for QoS frames (transition delay test)
~EmlsrDlTxopTest() override=default
Time m_emlsrEnabledTime
when EMLSR mode has been enabled on all EMLSR clients
std::set< uint8_t > m_emlsrLinks
IDs of the links on which EMLSR mode has to be enabled.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void CheckQosFrames(const WifiConstPsduMap &psduMap, const WifiTxVector &txVector, uint8_t linkId)
Check that appropriate actions are taken by the AP MLD transmitting a PPDU containing QoS data frames...
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 EnableEmlsrMode()
Enable EMLSR mode on the next EMLSR client.
void CheckBlockAck(const WifiConstPsduMap &psduMap, const WifiTxVector &txVector, uint8_t phyId)
Check that appropriate actions are taken by the AP MLD receiving a PPDU containing BlockAck frames fr...
void DoRun() override
Implementation to actually run this TestCase.
void CheckEmlNotificationFrame(Ptr< const WifiMpdu > mpdu, const WifiTxVector &txVector, uint8_t linkId)
Check that appropriate actions are taken by the AP MLD transmitting an EML Operating Mode Notificatio...
std::size_t m_countBlockAck
counter for BlockAck frames (transition delay test)
Test the switching of PHYs on EMLSR clients.
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.
bool m_resetCamState
whether to reset the state of the ChannelAccessManager associated with the link on which the main PHY...
void DoRun() override
Implementation to actually run this TestCase.
void CheckResults()
Check that the simulation produced the expected results.
void CheckInitialControlFrame(const WifiConstPsduMap &psduMap, const WifiTxVector &txVector, uint8_t linkId)
Check that the Main PHY (and possibly the Aux PHY) correctly switches channel when the reception of a...
void DoSetup() override
Implementation to do any local setup required for this TestCase.
uint16_t m_auxPhyMaxChWidth
max channel width (MHz) supported by aux PHYs
EmlsrLinkSwitchTest(bool switchAuxPhy, bool resetCamState, uint16_t auxPhyMaxChWidth)
Constructor.
~EmlsrLinkSwitchTest() override=default
std::size_t m_countQoSframes
counter for QoS data frames
std::size_t m_txPsdusPos
a position in the vector of TX PSDUs
void CheckQosFrames(const WifiConstPsduMap &psduMap, const WifiTxVector &txVector, uint8_t linkId)
Check that appropriate actions are taken by the AP MLD transmitting a PPDU containing QoS data frames...
bool m_switchAuxPhy
whether AUX PHY should switch channel to operate on the link on which the Main PHY was operating befo...
Base class for EMLSR Operations tests.
std::size_t m_nNonEmlsrStations
number of stations to create that do not activate EMLSR
void SetSsid(uint16_t aid, Mac48Address)
Set the SSID on the next station that needs to start the association procedure.
bool m_establishBaDl
whether BA needs to be established (for TID 0) with the AP as originator
void CheckBlockedLink(Ptr< WifiMac > mac, Mac48Address dest, uint8_t linkId, WifiQueueBlockedReason reason, bool blocked, std::string description, bool testUnblockedForOtherReasons=true)
Check whether QoS data unicast transmissions addressed to the given destination on the given link are...
std::size_t m_nEmlsrStations
number of stations to create that activate EMLSR
std::vector< PacketSocketAddress > m_dlSockets
packet socket address for DL traffic
std::vector< Time > m_paddingDelay
Padding Delay advertised by the non-AP MLD.
std::set< uint8_t > m_linksToEnableEmlsrOn
IDs of the links on which EMLSR mode has to be enabled.
Ptr< ApWifiMac > m_apMac
AP wifi MAC.
~EmlsrOperationsTestBase() override=default
TrafficDirection
Enumeration for traffic directions.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
uint8_t m_mainPhyId
ID of the main PHY.
Time m_duration
simulation duration
std::vector< FrameInfo > m_txPsdus
transmitted PSDUs
Ptr< PacketSocketClient > GetApplication(TrafficDirection dir, std::size_t staId, std::size_t count, std::size_t pktSize) const
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.
bool m_establishBaUl
whether BA needs to be established (for TID 0) with the AP as recipient
uint16_t m_lastAid
AID of last associated station.
std::vector< Time > m_transitionDelay
Transition Delay advertised by the non-AP MLD.
Time m_transitionTimeout
Transition Timeout advertised by the AP MLD.
std::vector< PacketSocketAddress > m_ulSockets
packet socket address for UL traffic
std::vector< Ptr< StaWifiMac > > m_staMacs
MACs of the non-AP MLDs.
virtual void StartTraffic()
Start the generation of traffic (needs to be overridden)
EmlsrOperationsTestBase(const std::string &name)
Constructor.
std::optional< Mac48Address > GetMldOrLinkAddressByAid(uint16_t aid) const
A container for one type of attribute.
AttributeValue implementation for Boolean.
Hold variables of type enum.
void SetList(const std::list< uint64_t > &packetlist)
static Mac48Address GetBroadcast()
Implement the header for Action frames of type EML Operating Mode Notification.
void SetLinkIdInBitmap(uint8_t linkId)
Set the bit position in the link bitmap corresponding to the given link.
EmlControl m_emlControl
EML Control field.
std::optional< EmlsrParamUpdate > m_emlsrParamUpdate
EMLSR Parameter Update field.
std::list< uint8_t > GetLinkBitmap() const
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
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.
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.
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
an address for a packet socket
void SetProtocol(uint16_t protocol)
Set the protocol.
void SetSingleDevice(uint32_t device)
Set the address to match only a specified NetDevice.
Give ns3::PacketSocket powers to ns3::Node.
void Install(Ptr< Node > node) const
Aggregate an instance of a ns3::PacketSocketFactory onto the provided node.
Smart pointer class similar to boost::intrusive_ptr.
static void SetRun(uint64_t run)
Set the run number of simulation.
static void SetSeed(uint32_t seed)
Set the seed.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
static Time Now()
Return the current simulation virtual time.
static void Run()
Run the simulation.
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Make it easy to create and manage PHY objects for the spectrum model.
void AddChannel(const Ptr< SpectrumChannel > channel, const FrequencyRange &freqRange=WHOLE_WIFI_SPECTRUM)
The IEEE 802.11 SSID Information Element.
AttributeValue implementation for Ssid.
Hold variables of type string.
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Simulation virtual time values and global simulation resolution.
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
bool IsZero() const
Exactly equivalent to t == 0.
AttributeValue implementation for Time.
void SetTxopLimits(const std::vector< Time > &txopLimits)
Set the TXOP limit for each link.
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.
Ptr< WifiMacQueueScheduler > GetMacQueueScheduler() const
Get the wifi MAC queue scheduler.
uint8_t GetNLinks() const
Get the number of links (can be greater than 1 for 11be devices only).
Ptr< WifiPhy > GetWifiPhy(uint8_t linkId=SINGLE_LINK_OP_ID) const
Ptr< WifiNetDevice > GetDevice() const
Return the device this PHY is associated with.
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Mac48Address GetAddress() const
Ptr< QosTxop > GetQosTxop(AcIndex ac) const
Accessor for a specified EDCA object.
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
uint32_t GetIfIndex() const override
Address GetAddress() const override
Ptr< Node > GetNode() const override
void SetPcapDataLinkType(SupportedPcapDataLinkTypes dlt)
Set the data link type of PCAP traces to be used.
void Set(std::string name, const AttributeValue &v)
@ DLT_IEEE802_11_RADIO
Include Radiotap link layer information.
void SetPostReceptionErrorModel(const Ptr< ErrorModel > em)
Attach a receive ErrorModel to the WifiPhy.
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
std::tuple< uint8_t, uint16_t, int, uint8_t > ChannelTuple
Tuple identifying an operating channel.
bool GetEmlsrEnabled(const Mac48Address &address) const
bool IsInPsMode(const Mac48Address &address) const
Return whether the STA is currently in Power Save mode.
std::optional< Mac48Address > GetMldAddress(const Mac48Address &address) const
Get the address of the MLD the given station is affiliated with, if any.
WifiTxVector GetRtsTxVector(Mac48Address address)
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode.
WifiPreamble GetPreambleType() const
#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_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
#define NS_TEST_EXPECT_MSG_GT_OR_EQ(actual, limit, msg)
Test that an actual value is greater than or equal to limit and report 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.
#define NS_TEST_ASSERT_MSG_GT_OR_EQ(actual, limit, msg)
Test that an actual value is greater than or equal to a limit and report and abort if not.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time NanoSeconds(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.
WifiMacDropReason
The reason why an MPDU was dropped.
WifiQueueBlockedReason
Enumeration of the reasons to block container queues.
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
constexpr FrequencyRange WIFI_SPECTRUM_6_GHZ
Identifier for the frequency range covering the wifi spectrum in the 6 GHz band.
U * PeekPointer(const Ptr< U > &p)
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
std::tuple< WifiContainerQueueType, WifiReceiverAddressType, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, receiver address type, Address, TID) identifying a container queue.
bool IsTrigger(const WifiPsduMap &psduMap)
constexpr FrequencyRange WIFI_SPECTRUM_5_GHZ
Identifier for the frequency range covering the wifi spectrum in the 5 GHz band.
@ WIFI_MAC_MGT_ASSOCIATION_RESPONSE
@ WIFI_MAC_MGT_ASSOCIATION_REQUEST
uint32_t GetAckSize()
Return the total Ack size (including FCS trailer).
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
constexpr FrequencyRange WIFI_SPECTRUM_2_4_GHZ
Identifier for the frequency range covering the wifi spectrum in the 2.4 GHz band.
Information about transmitted frames.
WifiConstPsduMap psduMap
transmitted PSDU map
uint8_t phyId
ID of the transmitting PHY.
WifiTxVector txVector
TXVECTOR.
Time startTx
TX start time.
static uint8_t EncodeEmlsrTransitionDelay(Time delay)
static Time DecodeEmlsrTransitionDelay(uint8_t value)
static Time DecodeEmlsrPaddingDelay(uint8_t value)
static uint8_t EncodeEmlsrPaddingDelay(Time delay)
uint8_t emlsrMode
EMLSR Mode.
uint8_t emlsrParamUpdateCtrl
EMLSR Parameter Update Control.
uint8_t emlmrMode
EMLMR Mode.
std::optional< uint16_t > linkBitmap
EMLSR/EMLMR Link Bitmap.
EMLSR Parameter Update field.
uint32_t pktSize
packet size used for the simulation (in bytes)
static WifiEmlsrTestSuite g_wifiEmlsrTestSuite
the test suite