11#include "ns3/advanced-ap-emlsr-manager.h"
12#include "ns3/advanced-emlsr-manager.h"
13#include "ns3/attribute-container.h"
14#include "ns3/boolean.h"
15#include "ns3/config.h"
16#include "ns3/ctrl-headers.h"
17#include "ns3/eht-configuration.h"
18#include "ns3/eht-frame-exchange-manager.h"
19#include "ns3/interference-helper.h"
21#include "ns3/mgt-action-headers.h"
22#include "ns3/mobility-helper.h"
23#include "ns3/multi-model-spectrum-channel.h"
24#include "ns3/node-list.h"
25#include "ns3/packet-socket-helper.h"
26#include "ns3/packet-socket-server.h"
27#include "ns3/pointer.h"
28#include "ns3/qos-txop.h"
29#include "ns3/rng-seed-manager.h"
30#include "ns3/rr-multi-user-scheduler.h"
31#include "ns3/simulator.h"
32#include "ns3/spectrum-wifi-helper.h"
33#include "ns3/spectrum-wifi-phy.h"
34#include "ns3/string.h"
35#include "ns3/wifi-net-device.h"
36#include "ns3/wifi-spectrum-phy-interface.h"
58 auto linkId = mac->GetLinkForPhy(phyId);
65 for (
const auto& [aid, psdu] : psduMap)
68 ss << std::setprecision(10) <<
"PSDU #" <<
m_txPsdus.size() <<
" Link ID "
69 << +linkId.value() <<
" Phy ID " << +phyId <<
" " << psdu->GetHeader(0).GetTypeString();
70 if (psdu->GetHeader(0).IsAction())
74 psdu->GetPayload(0)->PeekHeader(actionHdr);
77 ss <<
" #MPDUs " << psdu->GetNMpdus() <<
" duration/ID " << psdu->GetHeader(0).GetDuration()
78 <<
" RA = " << psdu->GetAddr1() <<
" TA = " << psdu->GetAddr2()
79 <<
" ADDR3 = " << psdu->GetHeader(0).GetAddr3()
80 <<
" ToDS = " << psdu->GetHeader(0).IsToDs()
81 <<
" FromDS = " << psdu->GetHeader(0).IsFromDs();
82 if (psdu->GetHeader(0).IsQosData())
87 ss << mpdu->GetHeader().GetSequenceNumber() <<
",";
89 ss <<
"} TID = " << +psdu->GetHeader(0).GetQosTid();
97 staMac && staMac->IsEmlsrLink(*linkId) &&
98 staMac->GetEmlsrManager()->GetMediumSyncDuration().IsStrictlyPositive())
100 const auto mustStartMsd =
101 staMac->GetEmlsrManager()->GetInDeviceInterference() &&
104 for (
auto id : staMac->GetLinkIds())
108 if (!staMac->IsEmlsrLink(
id) ||
id == *linkId || staMac->GetWifiPhy(
id) ==
nullptr)
113 txDuration - TimeStep(1),
114 [=, hdrType = psdu->GetHeader(0).GetTypeString(),
this]() {
117 const auto msdTimer =
118 staMac->GetEmlsrManager()->GetElapsedMediumSyncDelayTimer(id);
119 const auto msdDuration =
120 staMac->GetEhtConfiguration()->m_mediumSyncDuration;
121 const auto msdWasRunning =
122 (msdTimer.has_value() && (msdDuration - *msdTimer > TimeStep(2)));
123 if (auto phy = staMac->GetWifiPhy(id);
124 !msdWasRunning && !mustStartMsd && phy && phy->IsStateSleep())
136 (msdWasRunning || mustStartMsd),
137 std::string(
"after transmitting ") + hdrType +
138 " on link " + std::to_string(*linkId));
144 NS_LOG_INFO(
"TX duration = " << txDuration.As(
Time::MS) <<
" TXVECTOR = " << txVector <<
"\n");
151 const std::string& msg)
153 auto time = staMac->GetEmlsrManager()->GetElapsedMediumSyncDelayTimer(linkId);
157 <<
" Unexpected status for MediumSyncDelay timer on link " << +linkId
159 if (
auto phy = staMac->GetWifiPhy(linkId))
161 auto currThreshold = phy->GetCcaEdThreshold();
163 staMac->GetEmlsrManager()->GetMediumSyncOfdmEdThreshold()),
166 <<
" Unexpected value (" << currThreshold
167 <<
") for CCA ED threshold on link " << +linkId <<
" " << msg);
180 for (
const auto& phy : staMac->GetDevice()->GetPhys())
187 auto linkId = staMac->GetLinkForPhy(phy);
189 if (linkId.has_value() && !staMac->IsEmlsrLink(*linkId))
199 <<
" PHY " << +phy->GetPhyId() <<
" is in unexpected state "
200 << phy->GetState()->GetState());
206 (phy->IsStateTx() || phy->IsStateSwitching()) ? phy->GetDelayUntilIdle() :
Time{0};
211 "PHY " << +phy->GetPhyId() <<
" is in unexpected state "
212 << phy->GetState()->GetState());
226 std::string_view reason,
227 const std::optional<uint8_t>& fromLinkId,
229 bool checkFromLinkId,
235 "Expected stored trace info: " << reason);
236 const auto& traceInfo = traceInfoIt->second;
243 fromLinkId.has_value(),
244 "Unexpected stored from_link ID");
245 if (fromLinkId.has_value())
249 "Unexpected from_link ID");
278 wifi.SetRemoteStationManager(
"ns3::ConstantRateWifiManager",
283 wifi.ConfigEhtOptions(
"EmlsrActivated",
300 mac.SetType(
"ns3::ApWifiMac",
305 mac.SetApEmlsrManager(
"ns3::AdvancedApEmlsrManager",
306 "WaitTransDelayOnPsduRxError",
312 mac.SetType(
"ns3::StaWifiMac",
319 mac.SetEmlsrManager(
"ns3::AdvancedEmlsrManager",
338 "Channel " << +
id <<
" is not a spectrum channel");
345 for (
uint32_t i = 0; i < staDevices.GetN(); i++)
349 auto emlsrManager = staMac->GetEmlsrManager();
354 emlsrManager->TraceConnectWithoutContext(
362 wifi.ConfigEhtOptions(
"EmlsrActivated",
BooleanValue(
false));
364 staDevices.Add(wifi.Install(phyHelper, mac, otherStaNodes));
365 wifiStaNodes.Add(otherStaNodes);
368 for (
uint32_t i = 0; i < staDevices.GetN(); i++)
375 for (uint8_t phyId = 0; phyId <
m_apMac->GetDevice()->GetNPhys(); phyId++)
378 "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phys/" + std::to_string(phyId) +
384 for (uint8_t phyId = 0; phyId <
m_staMacs[i]->GetDevice()->GetNPhys(); phyId++)
387 "/NodeList/" + std::to_string(i + 1) +
"/DeviceList/*/$ns3::WifiNetDevice/Phys/" +
388 std::to_string(phyId) +
"/PhyTxPsduBegin",
407 positionAlloc->Add(Vector(std::min<double>(
id, 1), 0.0, 0.0));
409 mobility.SetPositionAllocator(positionAlloc);
411 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
412 mobility.Install(wifiApNode);
413 mobility.Install(wifiStaNodes);
417 packetSocket.
Install(wifiApNode);
418 packetSocket.
Install(wifiStaNodes);
430 server->SetLocal(srvAddr);
431 (*nodeIt)->AddApplication(server);
432 server->SetStartTime(
Seconds(0));
441 m_dlSockets.back().SetPhysicalAddress(staMac->GetDevice()->GetAddress());
445 m_ulSockets.back().SetSingleDevice(staMac->GetDevice()->GetIfIndex());
453 m_apMac->TraceConnectWithoutContext(
458 m_apMac->GetQosTxop(aci)->TraceConnectWithoutContext(
463 m_staMacs[id]->GetQosTxop(aci)->TraceConnectWithoutContext(
476 uint8_t priority)
const
484 client->SetStartTime(
Seconds(0));
507 m_apMac->GetDevice()->GetNode()->AddApplication(
528 std::optional<Mac48Address> )
533 auto linkId =
m_apMac->IsAssociated(recipient);
535 auto aid =
m_apMac->GetWifiRemoteStationManager(*linkId)->GetAssociationId(recipient);
542 m_apMac->GetDevice()->GetNode()->AddApplication(
564 std::optional<Mac48Address> )
574 m_staMacs[index]->GetDevice()->GetNode()->AddApplication(
604 m_apMac->TraceDisconnectWithoutContext(
609 m_apMac->GetQosTxop(aci)->TraceDisconnectWithoutContext(
614 m_staMacs[id]->GetQosTxop(aci)->TraceDisconnectWithoutContext(
627 std::string description,
628 bool testUnblockedForOtherReasons)
631 auto mask = mac->GetMacQueueScheduler()->GetQueueLinkMask(
AC_BE, queueId, linkId);
634 description <<
": Expected to find a mask for EMLSR link " << +linkId);
639 description <<
": Expected EMLSR link " << +linkId
640 <<
" to be blocked for reason " << reason);
641 if (testUnblockedForOtherReasons)
645 description <<
": Expected EMLSR link " << +linkId
646 <<
" to be blocked for one reason only");
649 else if (testUnblockedForOtherReasons)
653 description <<
": Expected EMLSR link " << +linkId
654 <<
" to be unblocked");
660 description <<
": Expected EMLSR link " << +linkId
661 <<
" to be unblocked for reason " << reason);
void BaEstablishedDl(Mac48Address recipient, uint8_t tid, std::optional< Mac48Address >)
Callback connected to the QosTxop's BaEstablished trace source of the AP's BE AC.
virtual void MainPhySwitchInfoCallback(std::size_t index, const EmlsrMainPhySwitchTrace &info)
Callback connected to the EMLSR Manager MainPhySwitch trace source.
std::size_t m_nNonEmlsrStations
number of stations to create that do not activate EMLSR
std::vector< uint8_t > m_establishBaDl
the TIDs for which BA needs to be established 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.
bool m_putAuxPhyToSleep
whether aux PHYs are put to sleep during DL/UL TXOPs
void BaEstablishedUl(std::size_t index, Mac48Address recipient, uint8_t tid, std::optional< Mac48Address >)
Callback connected to the QosTxop's BaEstablished trace source of a STA's BE AC.
TrafficDirection
Enumeration for traffic directions.
void CheckMsdTimerRunning(Ptr< StaWifiMac > staMac, uint8_t linkId, bool isRunning, const std::string &msg)
Check whether the MediumSyncDelay timer is running on the given link of the given device.
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
Ptr< PacketSocketClient > GetApplication(TrafficDirection dir, std::size_t staId, std::size_t count, std::size_t pktSize, uint8_t priority=0) const
std::vector< FrameInfo > m_txPsdus
transmitted PSDUs
uint32_t m_rngSeed
RNG seed value.
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.
uint16_t m_lastAid
AID of last associated station.
std::vector< Time > m_transitionDelay
Transition Delay advertised by the non-AP MLD.
void CheckMainPhyTraceInfo(std::size_t index, std::string_view reason, const std::optional< uint8_t > &fromLinkId, uint8_t toLinkId, bool checkFromLinkId=true, bool checkToLinkId=true)
Check information provided by the EMLSR Manager MainPhySwitch trace.
uint16_t m_startAid
first AID to allocate to stations
std::array< std::string, 3 > m_channelsStr
array of strings defining the channels for the MLD links
std::map< std::size_t, std::shared_ptr< EmlsrMainPhySwitchTrace > > m_traceInfo
EMLSR client ID-indexed map of trace info from last main PHY switch.
Time m_transitionTimeout
Transition Timeout advertised by the AP MLD.
const std::array< FrequencyRange, 3 > m_freqRanges
array of frequency ranges for MLD links
void SetSsid(std::size_t count)
Set the SSID on the next station that needs to start the association procedure, or start traffic if n...
std::vector< PacketSocketAddress > m_ulSockets
packet socket address for UL traffic
void StaAssociated(uint16_t aid, Mac48Address)
Callback connected to the ApWifiMac's AssociatedSta trace source.
void CheckAuxPhysSleepMode(Ptr< StaWifiMac > staMac, bool sleep)
Check whether aux PHYs of the given device are in sleep mode/awake.
std::vector< Ptr< StaWifiMac > > m_staMacs
MACs of the non-AP MLDs.
std::size_t m_nPhysPerEmlsrDevice
number of PHYs per EMLSR client
virtual void StartTraffic()
Start the generation of traffic (needs to be overridden)
int64_t m_streamNo
RNG stream number.
uint64_t m_rngRun
RNG run value.
std::vector< uint8_t > m_establishBaUl
the TIDs for which BA needs to be established with the AP as recipient
EmlsrOperationsTestBase(const std::string &name)
Constructor.
A container for one type of attribute.
AttributeValue implementation for Boolean.
static constexpr uint16_t MEDIUM_SYNC_THRESHOLD_USEC
The aMediumSyncThreshold defined by Sec. 35.3.16.18.1 of 802.11be D4.0.
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.
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 Time Now()
Return the current simulation virtual time.
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.
Simulation virtual time values and global simulation resolution.
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
int64_t GetTimeStep() const
Get the raw time value, in the current resolution unit.
AttributeValue implementation for Time.
Hold an unsigned integer type.
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.
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...
#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_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.
#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_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.
WifiQueueBlockedReason
Enumeration of the reasons to block container queues.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
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...
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
const std::map< AcIndex, WifiAc > wifiAcList
Map containing the four ACs in increasing order of priority (according to Table 10-1 "UP-to-AC Mappin...
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Base struct for EMLSR Main PHY switch traces.
virtual std::shared_ptr< EmlsrMainPhySwitchTrace > Clone() const =0
uint32_t pktSize
packet size used for the simulation (in bytes)