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 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.