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 = staMac->GetEmlsrManager()->GetInDeviceInterference() &&
103 for (
auto id : staMac->GetLinkIds())
107 if (!staMac->IsEmlsrLink(
id) ||
id == *linkId || staMac->GetWifiPhy(
id) ==
nullptr)
112 txDuration - TimeStep(1),
113 [=, hdrType = psdu->GetHeader(0).GetTypeString(),
this]() {
116 const auto msdTimer =
117 staMac->GetEmlsrManager()->GetElapsedMediumSyncDelayTimer(id);
118 const auto msdDuration =
119 staMac->GetEhtConfiguration()->m_mediumSyncDuration;
120 const auto msdWasRunning =
121 (msdTimer.has_value() && (msdDuration - *msdTimer > TimeStep(2)));
122 if (auto phy = staMac->GetWifiPhy(id);
123 !msdWasRunning && !mustStartMsd && phy && phy->IsStateSleep())
135 (msdWasRunning || mustStartMsd),
136 std::string(
"after transmitting ") + hdrType +
137 " on link " + std::to_string(*linkId));
143 NS_LOG_INFO(
"TX duration = " << txDuration.As(
Time::MS) <<
" TXVECTOR = " << txVector <<
"\n");
150 const std::string& msg)
152 auto time = staMac->GetEmlsrManager()->GetElapsedMediumSyncDelayTimer(linkId);
156 <<
" Unexpected status for MediumSyncDelay timer on link " << +linkId
158 if (
auto phy = staMac->GetWifiPhy(linkId))
160 auto currThreshold = phy->GetCcaEdThreshold();
162 staMac->GetEmlsrManager()->GetMediumSyncOfdmEdThreshold()),
165 <<
" Unexpected value (" << currThreshold
166 <<
") for CCA ED threshold on link " << +linkId <<
" " << msg);
179 for (
const auto& phy : staMac->GetDevice()->GetPhys())
186 auto linkId = staMac->GetLinkForPhy(phy);
188 if (linkId.has_value() && !staMac->IsEmlsrLink(*linkId))
198 <<
" PHY " << +phy->GetPhyId() <<
" is in unexpected state "
199 << phy->GetState()->GetState());
205 (phy->IsStateTx() || phy->IsStateSwitching()) ? phy->GetDelayUntilIdle() :
Time{0};
210 "PHY " << +phy->GetPhyId() <<
" is in unexpected state "
211 << phy->GetState()->GetState());
225 std::string_view reason,
226 const std::optional<uint8_t>& fromLinkId,
228 bool checkFromLinkId,
234 "Expected stored trace info: " << reason);
235 const auto& traceInfo = traceInfoIt->second;
242 fromLinkId.has_value(),
243 "Unexpected stored from_link ID");
244 if (fromLinkId.has_value())
248 "Unexpected from_link ID");
277 wifi.SetRemoteStationManager(
"ns3::ConstantRateWifiManager",
282 wifi.ConfigEhtOptions(
"EmlsrActivated",
299 mac.SetType(
"ns3::ApWifiMac",
304 mac.SetApEmlsrManager(
"ns3::AdvancedApEmlsrManager",
305 "WaitTransDelayOnPsduRxError",
311 mac.SetType(
"ns3::StaWifiMac",
318 mac.SetEmlsrManager(
"ns3::AdvancedEmlsrManager",
337 "Channel " << +
id <<
" is not a spectrum channel");
344 for (
uint32_t i = 0; i < staDevices.GetN(); i++)
348 auto emlsrManager = staMac->GetEmlsrManager();
353 emlsrManager->TraceConnectWithoutContext(
361 wifi.ConfigEhtOptions(
"EmlsrActivated",
BooleanValue(
false));
363 staDevices.Add(wifi.Install(phyHelper, mac, otherStaNodes));
364 wifiStaNodes.Add(otherStaNodes);
367 for (
uint32_t i = 0; i < staDevices.GetN(); i++)
374 for (uint8_t phyId = 0; phyId <
m_apMac->GetDevice()->GetNPhys(); phyId++)
377 "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phys/" + std::to_string(phyId) +
383 for (uint8_t phyId = 0; phyId <
m_staMacs[i]->GetDevice()->GetNPhys(); phyId++)
386 "/NodeList/" + std::to_string(i + 1) +
"/DeviceList/*/$ns3::WifiNetDevice/Phys/" +
387 std::to_string(phyId) +
"/PhyTxPsduBegin",
406 positionAlloc->Add(Vector(std::min<double>(
id, 1), 0.0, 0.0));
408 mobility.SetPositionAllocator(positionAlloc);
410 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
411 mobility.Install(wifiApNode);
412 mobility.Install(wifiStaNodes);
416 packetSocket.
Install(wifiApNode);
417 packetSocket.
Install(wifiStaNodes);
429 server->SetLocal(srvAddr);
430 (*nodeIt)->AddApplication(server);
431 server->SetStartTime(
Seconds(0));
440 m_dlSockets.back().SetPhysicalAddress(staMac->GetDevice()->GetAddress());
444 m_ulSockets.back().SetSingleDevice(staMac->GetDevice()->GetIfIndex());
452 m_apMac->TraceConnectWithoutContext(
457 m_apMac->GetQosTxop(aci)->TraceConnectWithoutContext(
462 m_staMacs[id]->GetQosTxop(aci)->TraceConnectWithoutContext(
475 uint8_t priority)
const
483 client->SetStartTime(
Seconds(0));
506 m_apMac->GetDevice()->GetNode()->AddApplication(
527 std::optional<Mac48Address> )
532 auto linkId =
m_apMac->IsAssociated(recipient);
534 auto aid =
m_apMac->GetWifiRemoteStationManager(*linkId)->GetAssociationId(recipient);
541 m_apMac->GetDevice()->GetNode()->AddApplication(
563 std::optional<Mac48Address> )
573 m_staMacs[index]->GetDevice()->GetNode()->AddApplication(
603 m_apMac->TraceDisconnectWithoutContext(
608 m_apMac->GetQosTxop(aci)->TraceDisconnectWithoutContext(
613 m_staMacs[id]->GetQosTxop(aci)->TraceDisconnectWithoutContext(
626 std::string description,
627 bool testUnblockedForOtherReasons)
630 auto mask = mac->GetMacQueueScheduler()->GetQueueLinkMask(
AC_BE, queueId, linkId);
633 description <<
": Expected to find a mask for EMLSR link " << +linkId);
638 description <<
": Expected EMLSR link " << +linkId
639 <<
" to be blocked for reason " << reason);
640 if (testUnblockedForOtherReasons)
644 description <<
": Expected EMLSR link " << +linkId
645 <<
" to be blocked for one reason only");
648 else if (testUnblockedForOtherReasons)
652 description <<
": Expected EMLSR link " << +linkId
653 <<
" to be unblocked");
659 description <<
": Expected EMLSR link " << +linkId
660 <<
" 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.
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)
const Time MEDIUM_SYNC_THRESHOLD
The aMediumSyncThreshold defined by Sec. 35.3.16.18.1 of 802.11be D4.0.
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)