9#include "ns3/boolean.h" 
   10#include "ns3/config.h" 
   11#include "ns3/fatal-error.h" 
   12#include "ns3/frame-exchange-manager.h" 
   14#include "ns3/multi-model-spectrum-channel.h" 
   15#include "ns3/net-device-container.h" 
   16#include "ns3/node-container.h" 
   17#include "ns3/node-list.h" 
   18#include "ns3/pointer.h" 
   19#include "ns3/simulator.h" 
   20#include "ns3/spectrum-wifi-phy.h" 
   21#include "ns3/wifi-mac-header.h" 
   22#include "ns3/wifi-mac-queue.h" 
   23#include "ns3/wifi-mac.h" 
   24#include "ns3/wifi-mode.h" 
   25#include "ns3/wifi-net-device.h" 
   26#include "ns3/wifi-psdu.h" 
   27#include "ns3/wifi-spectrum-signal-parameters.h" 
   28#include "ns3/yans-wifi-phy.h" 
   64    std::set<Ptr<Node>> nodesSeen;
 
   67        auto nodePtr = netDevices.
Get(i)->GetNode();
 
   68        if (nodesSeen.count(nodePtr) == 0)
 
   70            nodesSeen.insert(nodePtr);
 
 
   79                             const std::map<Mac48Address, uint32_t>& macToNodeMap)
 
   84    m_traceSink->SetMapMacAddressToNodeId(macToNodeMap);
 
   87        for (
uint32_t deviceId = 0; deviceId < 
nodes.Get(nodeId)->GetNDevices(); deviceId++)
 
   92                for (uint8_t i = 0; i < wifiDevice->GetNPhys(); i++)
 
   94                    auto phy = wifiDevice->GetPhy(i);
 
   98                    const std::string context =
 
   99                        "/NodeList/" + std::to_string(wifiDevice->GetNode()->GetId()) +
 
  100                        "/DeviceList/" + std::to_string(wifiDevice->GetIfIndex()) + 
"/Phys/" +
 
  102                    auto connected = 
false;
 
  105                        connected = yansPhy->TraceConnect(
 
  110                    else if (spectrumPhy)
 
  112                        connected = spectrumPhy->TraceConnect(
 
  123                    connected = phy->TraceConnect(
 
  124                        "SignalTransmission",
 
  129                    connected = phy->TraceConnect(
 
  135                    connected = phy->GetState()->TraceConnect(
 
  146    if (!macToNodeMap.empty())
 
  148        m_traceSink->SetMapMacAddressToNodeId(macToNodeMap);
 
  156        NS_LOG_DEBUG(
"Connected traces but collection period is not active");
 
 
  169    m_traceSink->PrintStatistics(node->GetId(), deviceId, linkId);
 
 
  175    m_traceSink->PrintStatistics(nodeId, deviceId, linkId);
 
 
  192const std::vector<WifiPpduRxRecord>&
 
  199std::optional<std::reference_wrapper<const std::vector<WifiPpduRxRecord>>>
 
  202    return m_traceSink->GetPpduRecords(nodeId, deviceId, linkId);
 
 
  222    return m_traceSink->GetStatistics(node->GetId(), deviceId, linkId);
 
 
  228    return m_traceSink->GetStatistics(nodeId, deviceId, linkId);
 
 
  231std::map<Mac48Address, uint32_t>
 
  234    std::map<Mac48Address, uint32_t> macAddressToNodeId;
 
  237        for (
uint32_t device = 0; device < 
nodes.Get(i)->GetNDevices(); device++)
 
  241                for (
uint32_t link = 0; link < wdev->GetNPhys(); link++)
 
  244                        wdev->GetMac()->GetFrameExchangeManager(link)->GetAddress())] =
 
  245                        nodes.Get(i)->GetId();
 
  247                                 << 
nodes.Get(i)->GetId() << 
" DeviceID: " << device
 
  248                                 << 
" LinkId: " << link << 
" MAC: " 
  249                                 << wdev->GetMac()->GetFrameExchangeManager(link)->GetAddress());
 
  254    return macAddressToNodeId;
 
 
  264                            .SetGroupName(
"Wifi")
 
 
  276    const std::map<Mac48Address, uint32_t>& MacAddressToNodeIdMap)
 
 
  284    const auto sub = context.substr(10);
 
  285    const auto pos = sub.find(
"/Device");
 
  286    return std::stoi(sub.substr(0, pos));
 
 
  292    const auto pos = context.find(
"/Phys/");
 
  293    const auto sub = context.substr(pos + 6);
 
  294    const auto nextSlashPos = sub.find(
'/');
 
  295    if (nextSlashPos == std::string::npos)
 
  297        return std::stoi(sub);
 
  299    const auto physNumberStr = sub.substr(0, nextSlashPos);
 
  300    return std::stoi(physNumberStr);
 
 
  306    auto pos = context.find(
"/DeviceList/");
 
  308    const auto sub = context.substr(pos);
 
  309    const auto nextSlashPos = sub.find(
'/');
 
  310    const auto deviceIdStr = sub.substr(0, nextSlashPos);
 
  311    return std::stoi(deviceIdStr);
 
 
  335    NS_LOG_DEBUG(
"Generating tag " << tag << 
" from ppdu UID " << ppduUid);
 
 
  348    return !(lhs == rhs);
 
 
  357WifiPhyTraceStatistics
 
  393    return !(lhs == rhs);
 
 
  401        for (
uint32_t device = 0; device < 
nodes.Get(i)->GetNDevices(); device++)
 
  406                for (
uint32_t link = 0; link < wdev->GetNPhys(); link++)
 
  409                                                     [link] = std::make_pair(
 
  410                                                         wdev->GetPhy(link)->GetChannelNumber(),
 
  411                                                         wdev->GetPhy(link)->GetFrequency());
 
  414                                 << 
nodes.Get(i)->GetId() << 
" DeviceID: " << wdev->GetIfIndex()
 
  415                                 << 
" LinkId: " << link
 
  416                                 << 
" freq: " << wdev->GetPhy(link)->GetFrequency()
 
  417                                 << 
" ch#: " << 
int(wdev->GetPhy(link)->GetChannelNumber()));
 
 
  425std::optional<std::pair<uint8_t, uint16_t>>
 
  431        auto& deviceMap = nodeIter->second;
 
  432        auto deviceIter = deviceMap.find(deviceId);
 
  433        if (deviceIter != deviceMap.end())
 
  435            auto& linkMap = deviceIter->second;
 
  436            auto linkIter = linkMap.find(link);
 
  437            if (linkIter != linkMap.end())
 
  439                return std::optional<std::pair<uint8_t, uint16_t>>(linkIter->second);
 
 
  486    NS_LOG_INFO(
"Remove transmit record at " << nodeId << 
":" << deviceId << 
":" 
 
  520        ppduRecord.m_overlappingPpdu.emplace_back(it);
 
  523    NS_LOG_INFO(
"Remove reception record at " << nodeId << 
":" << deviceId << 
":" 
  524                                              << +ppduRecord.m_linkId << 
" UID " << rxTag);
 
  528        .at(ppduRecord.m_linkId)
 
  544        NS_LOG_INFO(
"Adding PPDU record for " << ppduRecord.m_receiverId << 
" " << deviceId << 
" " 
  545                                              << +ppduRecord.m_linkId);
 
  546        m_completedRecords[ppduRecord.m_receiverId][deviceId][ppduRecord.m_linkId].emplace_back(
 
  551        NS_LOG_DEBUG(
"Not adding PPDU record (statistics not started) for " 
  552                     << ppduRecord.m_receiverId << 
" " << deviceId << 
" " << ppduRecord.m_linkId);
 
 
  610                               << 
" insert to active records map for UID " << ppduRecord.
m_rxTag);
 
 
  629    NS_LOG_FUNCTION(context << signal << senderNodeId << rxPower << duration);
 
  631    const auto ppdu = wifiSignal->ppdu;
 
 
  653    bool hasTxTag = 
false;
 
  660                                          << 
" Received on LinkID: " << +linkId
 
  661                                          << 
" Frame Sent on LinkId: " << +txPpduRecord.
m_linkId);
 
  665        NS_LOG_DEBUG(
"Arrival RxNodeID: " << nodeId << 
" Received on LinkID: " << +linkId
 
  666                                          << 
"; no sender info");
 
  674        if (!txInfo.has_value())
 
  677                "Didn't find TX record for transmission; possibly from an untraced sender");
 
  681            if ((
int(txInfo->second) != 
int(rxInfo->second)) ||
 
  682                (
int(txInfo->first) != 
int(rxInfo->first)))
 
  685                    "Received Signal on a different frequency or channel number than what was " 
  686                    "configured for this PHY or link");
 
  696    ppduRecord.
m_rssi = rxPower;
 
  706                          << 
"; insert to active records map for UID " << ppduRecord.
m_rxTag);
 
  711                                  << 
"; insert to active records map for UID " 
 
  746    if (ppduRecord.
m_ppdu == 
nullptr)
 
  748        NS_LOG_DEBUG(
"Frame being dropped was not observed on SignalArrival trace. Means it was " 
  749                     "received on a wrong link configuration");
 
  754    std::vector<bool> outcome;
 
  755    for (
const auto& mpdu : *
PeekPointer(ppdu->GetPsdu()))
 
  758        outcome.emplace_back(
false);
 
 
  777                                const std::vector<bool>& statusMpdu)
 
  793        NS_LOG_DEBUG(
"Frame to be processed was not observed on SignalArrival trace");
 
 
  811        bool mpduToReceiver = 
false;
 
  812        bool shouldCount = 
true;
 
  817            p = mpdu->GetProtocolDataUnit();
 
  830                mpduToReceiver = 
true;
 
  836        if (mpduToReceiver && shouldCount)
 
  861        bool mpduFail = 
false;
 
  862        bool shouldCount = 
true;
 
  863        bool mpduToReceiver = 
false;
 
  866            p = mpdu->GetProtocolDataUnit();
 
  880                mpduToReceiver = 
true;
 
  888                mpduToReceiver = 
true;
 
  892        if (!mpduFail && shouldCount && mpduToReceiver)
 
  910        else if (shouldCount && mpduToReceiver)
 
 
  936        for (
const auto& deviceMap : nodeMap.second)
 
  938            for (
const auto& linkMap : deviceMap.second)
 
  940                for (
const auto& record : linkMap.second)
 
 
  958        if (mapOfDevices.contains(deviceId))
 
  960            const auto& mapOfLinks = mapOfDevices.at(deviceId);
 
  961            if (mapOfLinks.contains(linkId))
 
  963                auto vectorOfRecords = mapOfLinks.at(linkId);
 
  964                for (
const auto& record : vectorOfRecords)
 
 
  997    std::cout << 
"Total Overlapping PPDUs Received: " << statistics.
m_overlappingPpdus << std::endl;
 
  999    std::cout << 
"\nSuccessful PPDUs: " << statistics.
m_receivedPpdus << std::endl;
 
 1000    std::cout << 
"Failed PPDUs: " << statistics.
m_failedPpdus << std::endl;
 
 1003        std::cout << 
"PPDU Dropped due to " << reason.first << 
": " << reason.second << std::endl;
 
 1007    std::cout << 
"Total Successful MPDUs: " << statistics.
m_receivedMpdus << std::endl;
 
 1008    std::cout << 
"Total Failed MPDUs: " << statistics.
m_failedMpdus << std::endl;
 
 
 1019    std::cout << 
"Total Overlapping PPDUs Received: " << statistics.
m_overlappingPpdus << std::endl;
 
 1021    std::cout << 
"\nSuccessful PPDUs: " << statistics.
m_receivedPpdus << std::endl;
 
 1022    std::cout << 
"Failed PPDUs: " << statistics.
m_failedPpdus << std::endl;
 
 1025        std::cout << 
"PPDU Dropped due to " << reason.first << 
": " << reason.second << std::endl;
 
 1029    std::cout << 
"Total Successful MPDUs: " << statistics.
m_receivedMpdus << std::endl;
 
 1030    std::cout << 
"Total Failed MPDUs: " << statistics.
m_failedMpdus << std::endl;
 
 
 1047        for (
const auto& deviceMap : nodeMap.second)
 
 1049            for (
const auto& linkMap : deviceMap.second)
 
 1051                for (
const auto& wifiRecord : linkMap.second)
 
 
 1060const std::vector<WifiPpduRxRecord>&
 
 1066std::optional<std::reference_wrapper<const std::vector<WifiPpduRxRecord>>>
 
 1075                return std::optional<std::reference_wrapper<const std::vector<WifiPpduRxRecord>>>(
 
 1080    return std::nullopt;
 
 
static Mac48Address ConvertFrom(const Address &address)
holds a vector of ns3::NetDevice pointers
uint32_t GetN() const
Get the number of Ptr<NetDevice> stored in this container.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
A base class which provides memory management and object aggregation.
Smart pointer class similar to boost::intrusive_ptr.
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.
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.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
const std::vector< WifiPpduRxRecord > & GetPpduRecords() const
Accesses a vector of saved and completed PPDU reception records.
WifiPhyRxTraceHelper()
Constructor.
void PrintStatistics() const
Print statistics for all nodes, devices, and links during the collection period.
void Reset()
Resets the current statistics, clearing all counts and PPDU records.
Ptr< WifiPhyRxTraceSink > m_traceSink
Pointer to the current trace sink object.
void Stop(Time stopTime)
Stops the collection of statistics at a specified time.
WifiPhyTraceStatistics GetStatistics() const
Retrieves current statistics of successful and failed data PPDUs and MPDUs receptions,...
void Enable(NodeContainer nodes)
Enables trace collection for all nodes and WifiNetDevices in the specified NodeContainer.
std::map< Mac48Address, uint32_t > MapMacAddressesToNodeIds(NodeContainer nodes) const
Populates the mapping of MAC addresses to node IDs for a given set of nodes.
void Start(Time startTime)
Starts the collection of statistics from a specified start time.
std::set< uint64_t > usedTags
Set of already used tags.
uint64_t GenerateUniqueTag(uint64_t ppduUid)
Generates a unique tag for a WifiPpdu.
uint64_t counter
Counter to help generate unique tags.
Sink class for capturing and analyzing PHY layer reception events in Wi-Fi networks.
std::map< uint64_t, std::map< uint64_t, std::map< uint64_t, std::map< uint64_t, uint64_t > > > > m_nodeDeviceLinkPidToRxId
Aids in correlating PHY reception drops and outcomes with specific reception tags.
void Reset()
Resets the statistics collection, clearing all counts and discarding all fully completed PPDU records...
std::map< uint32_t, std::map< uint32_t, std::map< uint8_t, std::vector< WifiPpduRxRecord > > > > m_completedRecords
Stores records of PPDUs that have completed reception, organized by node, device, and link.
void CreateVectorFromRecords()
Creates a vector with all completed WiFi reception records to be returned by the GetPpduRecords().
void SpectrumPhySignalArrival(std::string context, Ptr< const SpectrumSignalParameters > signal, uint32_t senderNodeId, double rxPower, Time duration)
Handles the event of a PHY signal arrival from a SpectrumChannel.
const std::vector< WifiPpduRxRecord > & GetPpduRecords() const
Provides access to all saved and completed PPDU reception records across all nodes,...
bool m_statisticsCollectionPeriodStarted
Flag indicating whether to keep a record of certain statistics or events for analysis.
void Stop()
Stops the statistics collection period at a specified time.
WifiPhyTraceStatistics CountStatistics() const
Counts and aggregates PHY layer statistics including receptions, transmissions, and performance metri...
void PhyRxEnd(uint32_t nodeId, uint32_t deviceId, uint64_t rxTag, uint64_t ppduUid)
Handles the end of a PHY reception event, logging the conclusion of a reception and its associated de...
bool IsCollectionPeriodActive() const
Returns whether the collection period is active.
WifiPhyRxTraceSink()
Constructor.
std::map< uint64_t, WifiPpduRxRecord > m_rxTagToPpduRecord
Maps a reception tag to the corresponding WifiPpduRxRecord.
std::map< Mac48Address, uint32_t > m_macAddressToNodeId
Maps MAC addresses to node IDs.
void PhyPpduDrop(std::string context, Ptr< const WifiPpdu > ppdu, WifiPhyRxfailureReason reason)
Logs the drop of a PPDU at the PHY layer, detailing the context and reason for the drop.
std::optional< std::pair< uint8_t, uint16_t > > GetChannelInfo(uint32_t node, uint32_t deviceId, int link) const
Retrieves the frequency and channel number used by a specific link.
std::vector< WifiPpduRxRecord > m_records
Stores a flat vector of all records of PPDUs that have completed reception.
void PhySignalTransmission(std::string context, Ptr< const WifiPpdu > ppdu, const WifiTxVector &txVector)
Handles the event of a PHY signal transmission.
void PrintStatistics() const
Prints a summary of the statistics collected, offering a concise overview of PHY layer performance an...
WifiPhyTraceStatistics GetStatistics() const
Returns statistics on the count of successful and failed PPDUs with unicast data, and their MPDUs,...
std::map< uint64_t, std::vector< WifiPpduRxRecord > > m_rxTagToListOfOverlappingPpduRecords
Maps each reception tag to a list of overlapping WifiPpduRxRecords.
std::string ContextToTuple(std::string context) const
Translate a context string to a colon-delimited tuple "0:0:0" where the first element is a node ID,...
void Start()
Starts the statistics collection period from a specified start time.
void PpduOutcome(std::string context, Ptr< const WifiPpdu > ppdu, RxSignalInfo signal, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Records the outcome of a PPDU transmission, including the signal info, and the success or failure sta...
std::map< uint32_t, std::map< uint32_t, std::map< uint32_t, std::vector< WifiPpduRxRecord > > > > m_nodeDeviceLinkRxRecords
Tracks ongoing frames being transmitted or received per node, device, and link.
void EndTx(uint32_t nodeId, uint32_t deviceId, WifiPpduRxRecord ppduRecord)
Handles the conclusion of a transmission event, facilitating the logging of transmission outcomes.
int ContextToDeviceId(std::string context) const
Translates a context string to a device ID, enabling the identification of devices involved in recept...
void CountStatisticsForRecord(WifiPhyTraceStatistics &statistics, const WifiPpduRxRecord &record) const
Update the passed-in statistics object with statistics from the passed-in record.
void PhySignalArrival(std::string context, Ptr< const WifiPpdu > ppdu, double rxPower, Time duration)
Handles the event of a Wi-Fi PPDU arrival.
UniqueTagGenerator m_tagGenerator
Instance of UniqueTagGenerator used for generating unique reception tags.
void SetMapMacAddressToNodeId(const std::map< Mac48Address, uint32_t > &MacAddressToNodeIdMap)
Provides a custom mapping of MAC addresses to intended receiver node IDs.
void UpdateCurrentlyReceivedSignal(uint32_t nodeId, uint32_t deviceId, uint8_t linkId)
Updates the information for signals currently being received by a node.
uint32_t ContextToNodeId(std::string context) const
Translates a context string to a node ID.
int ContextToLinkId(std::string context) const
Translates a context string to a link ID, facilitating the association of events with specific links ...
void MapNodeToLinkToChannel(NodeContainer nodes)
Maps nodes to links and channels, creating a structured association between network elements and thei...
std::map< uint32_t, std::map< uint32_t, std::map< int, std::pair< uint8_t, uint16_t > > > > m_nodeToDeviceToLinkToChannelInfo
Maps node IDs to device IDs and further to link IDs, associating each with a pair consisting of the c...
std::map< uint64_t, uint64_t > m_ppduUidToTxTag
Maps WifiPpdu UIDs to WifiPpduRxRecord tags stored by transmitter.
static TypeId GetTypeId()
Retrieves the TypeId of the class.
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...
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
int64x64_t operator+(const int64x64_t &lhs, const int64x64_t &rhs)
Addition operator.
#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_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#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_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
bool operator!=(Callback< R, Args... > a, Callback< R, Args... > b)
Inequality test.
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...
bool operator==(const EventId &a, const EventId &b)
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
bool operator<(const EventId &a, const EventId &b)
const uint32_t SHIFT
Number of places to shift WifiPpdu UID values, when generating unique IDs.
RxSignalInfo structure containing info on the received signal.
Keeps track of PHY layer trace statistics.
std::map< WifiPhyRxfailureReason, uint64_t > m_ppduDropReasons
Counts of the drop reasons.
uint64_t m_failedMpdus
Number of failed unicast data MPDU receptions.
uint64_t m_failedPpdus
Number of failed PPDU receptions (with unicast data).
uint64_t m_receivedPpdus
Number of successfully received PPDUs (with unicast data).
uint64_t m_receivedMpdus
Number of successfully received unicast data MPDUs.
uint64_t m_overlappingPpdus
Number of PPDUs that overlapped in time with at least one other PPDU.
uint64_t m_nonOverlappingPpdus
Number of PPDUs that did not overlap in time with any other PPDU.
Structure recording a received PPDU (Physical Protocol Data Unit) in a Wi-Fi network.
Ptr< const WifiPpdu > m_ppdu
Pointer to the received PPDU.
double m_rssi
Received Signal Strength Indicator (RSSI) in dBm.
Time m_endTime
End time of the PPDU reception.
Time m_startTime
Start time of the PPDU reception.
uint8_t m_linkId
The link ID belonging to this record.
WifiPhyRxfailureReason m_reason
Reason for reception failure, if any.
uint32_t m_senderDeviceId
Device ID of Sender.
uint32_t m_senderId
Node ID of the sender.
std::vector< bool > m_statusPerMpdu
Reception status for each MPDU within the PPDU.
std::vector< WifiPpduRxRecord > m_overlappingPpdu
List of PPDUs that overlapped in time with this reception.
uint32_t m_receiverId
Node ID of the receiver.
uint64_t m_rxTag
Unique tag for the reception of this PPDU.