20#include "ns3/boolean.h"
21#include "ns3/config.h"
22#include "ns3/fatal-error.h"
23#include "ns3/frame-exchange-manager.h"
25#include "ns3/multi-model-spectrum-channel.h"
26#include "ns3/net-device-container.h"
27#include "ns3/node-container.h"
28#include "ns3/node-list.h"
29#include "ns3/pointer.h"
30#include "ns3/simulator.h"
31#include "ns3/spectrum-wifi-phy.h"
32#include "ns3/wifi-mac-header.h"
33#include "ns3/wifi-mac-queue.h"
34#include "ns3/wifi-mac.h"
35#include "ns3/wifi-mode.h"
36#include "ns3/wifi-net-device.h"
37#include "ns3/wifi-psdu.h"
38#include "ns3/wifi-spectrum-signal-parameters.h"
39#include "ns3/yans-wifi-phy.h"
75 std::set<Ptr<Node>> nodesSeen;
78 auto nodePtr = netDevices.
Get(i)->GetNode();
79 if (nodesSeen.count(nodePtr) == 0)
81 nodesSeen.insert(nodePtr);
90 const std::map<Mac48Address, uint32_t>& macToNodeMap)
95 m_traceSink->SetMapMacAddressToNodeId(macToNodeMap);
98 for (
uint32_t deviceId = 0; deviceId <
nodes.Get(nodeId)->GetNDevices(); deviceId++)
100 auto wifiDevice = DynamicCast<WifiNetDevice>(
nodes.Get(nodeId)->GetDevice(deviceId));
103 for (uint8_t i = 0; i < wifiDevice->GetNPhys(); i++)
105 auto phy = wifiDevice->GetPhy(i);
106 auto yansPhy = DynamicCast<YansWifiPhy>(phy);
107 auto spectrumPhy = DynamicCast<SpectrumWifiPhy>(phy);
109 const std::string context =
110 "/NodeList/" + std::to_string(wifiDevice->GetNode()->GetId()) +
111 "/DeviceList/" + std::to_string(wifiDevice->GetIfIndex()) +
"/Phys/" +
113 auto connected =
false;
116 connected = yansPhy->TraceConnect(
121 else if (spectrumPhy)
123 connected = spectrumPhy->TraceConnect(
134 connected = phy->TraceConnect(
135 "SignalTransmission",
140 connected = phy->TraceConnect(
146 connected = phy->GetState()->TraceConnect(
157 if (!macToNodeMap.empty())
159 m_traceSink->SetMapMacAddressToNodeId(macToNodeMap);
167 NS_LOG_DEBUG(
"Connected traces but collection period is not active");
180 m_traceSink->PrintStatistics(node->GetId(), deviceId, linkId);
186 m_traceSink->PrintStatistics(nodeId, deviceId, linkId);
203const std::vector<WifiPpduRxRecord>&
210std::optional<std::reference_wrapper<const std::vector<WifiPpduRxRecord>>>
213 return m_traceSink->GetPpduRecords(nodeId, deviceId, linkId);
233 return m_traceSink->GetStatistics(node->GetId(), deviceId, linkId);
239 return m_traceSink->GetStatistics(nodeId, deviceId, linkId);
242std::map<Mac48Address, uint32_t>
245 std::map<Mac48Address, uint32_t> macAddressToNodeId;
248 for (
uint32_t device = 0; device <
nodes.Get(i)->GetNDevices(); device++)
250 if (
auto wdev = DynamicCast<WifiNetDevice>(
nodes.Get(i)->GetDevice(device)))
252 for (
uint32_t link = 0; link < wdev->GetNPhys(); link++)
255 wdev->GetMac()->GetFrameExchangeManager(link)->GetAddress())] =
256 nodes.Get(i)->GetId();
258 <<
nodes.Get(i)->GetId() <<
" DeviceID: " << device
259 <<
" LinkId: " << link <<
" MAC: "
260 << wdev->GetMac()->GetFrameExchangeManager(link)->GetAddress());
265 return macAddressToNodeId;
275 .SetGroupName(
"Wifi")
287 const std::map<Mac48Address, uint32_t>& MacAddressToNodeIdMap)
295 const auto sub = context.substr(10);
296 const auto pos = sub.find(
"/Device");
297 return std::stoi(sub.substr(0, pos));
303 const auto pos = context.find(
"/Phys/");
304 const auto sub = context.substr(pos + 6);
305 const auto nextSlashPos = sub.find(
'/');
306 if (nextSlashPos == std::string::npos)
308 return std::stoi(sub);
310 const auto physNumberStr = sub.substr(0, nextSlashPos);
311 return std::stoi(physNumberStr);
317 auto pos = context.find(
"/DeviceList/");
319 const auto sub = context.substr(pos);
320 const auto nextSlashPos = sub.find(
'/');
321 const auto deviceIdStr = sub.substr(0, nextSlashPos);
322 return std::stoi(deviceIdStr);
346 NS_LOG_DEBUG(
"Generating tag " << tag <<
" from ppdu UID " << ppduUid);
359 return !(lhs == rhs);
368WifiPhyTraceStatistics
404 return !(lhs == rhs);
412 for (
uint32_t device = 0; device <
nodes.Get(i)->GetNDevices(); device++)
414 auto wdev = DynamicCast<WifiNetDevice>(
nodes.Get(i)->GetDevice(device));
417 for (
uint32_t link = 0; link < wdev->GetNPhys(); link++)
420 [link] = std::make_pair(
421 wdev->GetPhy(link)->GetChannelNumber(),
422 wdev->GetPhy(link)->GetFrequency());
425 <<
nodes.Get(i)->GetId() <<
" DeviceID: " << wdev->GetIfIndex()
426 <<
" LinkId: " << link
427 <<
" freq: " << wdev->GetPhy(link)->GetFrequency()
428 <<
" ch#: " <<
int(wdev->GetPhy(link)->GetChannelNumber()));
436std::optional<std::pair<uint8_t, uint16_t>>
442 auto& deviceMap = nodeIter->second;
443 auto deviceIter = deviceMap.find(deviceId);
444 if (deviceIter != deviceMap.end())
446 auto& linkMap = deviceIter->second;
447 auto linkIter = linkMap.find(link);
448 if (linkIter != linkMap.end())
450 return std::optional<std::pair<uint8_t, uint16_t>>(linkIter->second);
497 NS_LOG_INFO(
"Remove transmit record at " << nodeId <<
":" << deviceId <<
":"
531 ppduRecord.m_overlappingPpdu.emplace_back(it);
534 NS_LOG_INFO(
"Remove reception record at " << nodeId <<
":" << deviceId <<
":"
535 << +ppduRecord.m_linkId <<
" UID " << rxTag);
539 .at(ppduRecord.m_linkId)
555 NS_LOG_INFO(
"Adding PPDU record for " << ppduRecord.m_receiverId <<
" " << deviceId <<
" "
556 << +ppduRecord.m_linkId);
557 m_completedRecords[ppduRecord.m_receiverId][deviceId][ppduRecord.m_linkId].emplace_back(
562 NS_LOG_DEBUG(
"Not adding PPDU record (statistics not started) for "
563 << ppduRecord.m_receiverId <<
" " << deviceId <<
" " << ppduRecord.m_linkId);
621 <<
" insert to active records map for UID " << ppduRecord.
m_rxTag);
640 NS_LOG_FUNCTION(context << signal << senderNodeId << rxPower << duration);
641 const auto wifiSignal = DynamicCast<const WifiSpectrumSignalParameters>(signal);
642 const auto ppdu = wifiSignal->ppdu;
664 bool hasTxTag =
false;
671 <<
" Received on LinkID: " << +linkId
672 <<
" Frame Sent on LinkId: " << +txPpduRecord.
m_linkId);
676 NS_LOG_DEBUG(
"Arrival RxNodeID: " << nodeId <<
" Received on LinkID: " << +linkId
677 <<
"; no sender info");
685 if (!txInfo.has_value())
688 "Didn't find TX record for transmission; possibly from an untraced sender");
692 if ((
int(txInfo->second) !=
int(rxInfo->second)) ||
693 (
int(txInfo->first) !=
int(rxInfo->first)))
696 "Received Signal on a different frequency or channel number than what was "
697 "configured for this PHY or link");
707 ppduRecord.
m_rssi = rxPower;
717 <<
"; insert to active records map for UID " << ppduRecord.
m_rxTag);
722 <<
"; insert to active records map for UID "
757 if (ppduRecord.
m_ppdu ==
nullptr)
759 NS_LOG_DEBUG(
"Frame being dropped was not observed on SignalArrival trace. Means it was "
760 "received on a wrong link configuration");
765 std::vector<bool> outcome;
766 for (
const auto& mpdu : *
PeekPointer(ppdu->GetPsdu()))
769 outcome.emplace_back(
false);
788 const std::vector<bool>& statusMpdu)
804 NS_LOG_DEBUG(
"Frame to be processed was not observed on SignalArrival trace");
822 bool mpduToReceiver =
false;
823 bool shouldCount =
true;
828 p = mpdu->GetProtocolDataUnit();
841 mpduToReceiver =
true;
847 if (mpduToReceiver && shouldCount)
872 bool mpduFail =
false;
873 bool shouldCount =
true;
874 bool mpduToReceiver =
false;
877 p = mpdu->GetProtocolDataUnit();
891 mpduToReceiver =
true;
899 mpduToReceiver =
true;
903 if (!mpduFail && shouldCount && mpduToReceiver)
921 else if (shouldCount && mpduToReceiver)
947 for (
const auto& deviceMap : nodeMap.second)
949 for (
const auto& linkMap : deviceMap.second)
951 for (
const auto& record : linkMap.second)
969 if (mapOfDevices.contains(deviceId))
971 auto mapOfLinks = mapOfDevices.at(deviceId);
972 if (mapOfLinks.contains(linkId))
974 auto vectorOfRecords = mapOfLinks.at(linkId);
975 for (
const auto& record : vectorOfRecords)
1008 std::cout <<
"Total Overlapping PPDUs Received: " << statistics.
m_overlappingPpdus << std::endl;
1010 std::cout <<
"\nSuccessful PPDUs: " << statistics.
m_receivedPpdus << std::endl;
1011 std::cout <<
"Failed PPDUs: " << statistics.
m_failedPpdus << std::endl;
1014 std::cout <<
"PPDU Dropped due to " << reason.first <<
": " << reason.second << std::endl;
1018 std::cout <<
"Total Successful MPDUs: " << statistics.
m_receivedMpdus << std::endl;
1019 std::cout <<
"Total Failed MPDUs: " << statistics.
m_failedMpdus << std::endl;
1030 std::cout <<
"Total Overlapping PPDUs Received: " << statistics.
m_overlappingPpdus << std::endl;
1032 std::cout <<
"\nSuccessful PPDUs: " << statistics.
m_receivedPpdus << std::endl;
1033 std::cout <<
"Failed PPDUs: " << statistics.
m_failedPpdus << std::endl;
1036 std::cout <<
"PPDU Dropped due to " << reason.first <<
": " << reason.second << std::endl;
1040 std::cout <<
"Total Successful MPDUs: " << statistics.
m_receivedMpdus << std::endl;
1041 std::cout <<
"Total Failed MPDUs: " << statistics.
m_failedMpdus << std::endl;
1058 for (
const auto& deviceMap : nodeMap.second)
1060 for (
const auto& linkMap : deviceMap.second)
1062 for (
const auto& wifiRecord : linkMap.second)
1071const std::vector<WifiPpduRxRecord>&
1077std::optional<std::reference_wrapper<const std::vector<WifiPpduRxRecord>>>
1086 return std::optional<std::reference_wrapper<const std::vector<WifiPpduRxRecord>>>(
1091 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.
#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)
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.