12#include "ns3/net-device-container.h"
13#include "ns3/node-container.h"
14#include "ns3/node-list.h"
16#include "ns3/pointer.h"
17#include "ns3/wifi-mac.h"
18#include "ns3/wifi-net-device.h"
19#include "ns3/wifi-phy-state-helper.h"
20#include "ns3/wifi-phy.h"
41 "Invalid Start: " << startTime <<
" and Stop: " <<
stopTime <<
" Time");
52 "Invalid Start: " << start <<
" and Stop: " <<
m_stopTime <<
" Time");
54 "Invalid Start: " << start <<
" less than Now(): " <<
Simulator::Now());
63 "Invalid Start: " <<
m_startTime <<
" and Stop: " << stop <<
" Time");
65 "Invalid Stop: " << stop <<
" less than Now(): " <<
Simulator::Now());
77 record.m_linkStateDurations.clear();
90 netDevices.
Add(
nodes.Get(i)->GetDevice(j));
101 for (
uint32_t j = 0; j < devices.GetN(); ++j)
106 NS_LOG_INFO(
"Ignoring deviceId: " << devices.Get(j)->GetIfIndex() <<
" on nodeId: "
107 << devices.Get(j)->GetNode()->GetId()
108 <<
" because it is not of type WifiNetDevice");
114 for (
uint32_t k = 0; k < device->GetNPhys(); ++k)
116 auto wifiPhyStateHelper = device->GetPhy(k)->GetState();
119 wifiPhyStateHelper->TraceConnectWithoutContext(
"State", linkCallback);
134 if (nodeName.empty())
138 if (deviceName.empty())
145 auto& statistics =
m_deviceRecords[i].m_linkStateDurations.begin()->second;
147 <<
"---- COT for " << nodeName <<
":" << deviceName <<
" ----"
151 else if (numLinks > 1)
153 os <<
"\nDevice \"" << nodeName <<
":" << deviceName
154 <<
"\" has statistics for multiple links: "
159 <<
"---- COT for " << nodeName <<
":" << deviceName <<
"#Link"
160 << std::to_string(linkStates.first) <<
" ---"
167 os <<
"\nDevice \"" << nodeName <<
":" << deviceName <<
"\" has no statistics."
176 const std::map<WifiPhyState, Time>& linkStates,
180 os <<
"Showing duration by states: "
184 const auto showPercents = !percents.empty();
186 std::vector<std::string> stateColumn{};
187 std::vector<std::string> durationColumn{};
188 std::vector<std::string> percentColumn{};
190 for (
const auto& it : linkStates)
192 std::stringstream stateStream;
193 stateStream << it.first <<
": ";
194 stateColumn.emplace_back(stateStream.str());
196 std::stringstream durationStream;
197 durationStream << std::showpoint << std::fixed << std::setprecision(2)
198 << it.second.As(unit);
199 durationColumn.emplace_back(durationStream.str());
203 std::stringstream percentStream;
204 percentStream << std::showpoint << std::fixed << std::setprecision(2) <<
" ("
205 << percents.at(it.first) <<
"%)";
206 percentColumn.emplace_back(percentStream.str());
218 for (
size_t i = 0; i < stateColumn.size(); ++i)
220 os << stateColumn.at(i) << durationColumn.at(i);
223 os << percentColumn.at(i);
237 for (
auto& s : column)
239 size_t pos = s.find_first_of(decimal);
246 for (
auto& s : column)
248 auto padding = std::string(maxPos - s.find_first_of(decimal),
' ');
258 for (
auto& s : column)
260 size_t width = s.length();
261 if (width > maxWidth)
267 for (
auto& s : column)
269 auto padding = std::string(maxWidth - s.length(),
' ');
274std::map<WifiPhyState, double>
279 for (
const auto& it : linkStates)
289 std::map<WifiPhyState, double> percents;
290 for (
const auto& it : linkStates)
292 percents[it.first] = it.second.GetDouble() * 100.0 / total.
GetDouble();
298const std::vector<WifiCoTraceHelper::DeviceRecord>&
316 const auto overlappingDuration =
319 if (!overlappingDuration.IsZero())
325 NS_ASSERT_MSG(wifiDevice,
"Error, Device type is not WifiNetDevice.");
327 auto linkId = wifiDevice->GetMac()->GetLinkForPhy(phyId);
329 if (linkId.has_value())
333 <<
m_deviceRecords[idx].m_ifIndex <<
" linkId " << *linkId <<
" duration "
334 << overlappingDuration.As(
Time::US) <<
" state " << state);
335 m_deviceRecords[idx].AddLinkMeasurement(*linkId, start, overlappingDuration, state);
349 NS_ASSERT_MSG(start1 >= Zero && stop1 >= Zero && start1 <= stop1,
350 "Interval: [" << start1 <<
"," << stop1 <<
"] is invalid.");
351 NS_ASSERT_MSG(start2 >= Zero && stop2 >= Zero && start2 <= stop2,
352 "Interval: [" << start2 <<
"," << stop2 <<
"] is invalid.");
354 const auto maxStart =
Max(start1, start2);
355 const auto minStop =
Min(stop1, stop2);
356 const auto duration = minStop - maxStart;
358 return duration > Zero ? duration : Zero;
362 : m_nodeId(device->GetNode()->GetId()),
363 m_ifIndex(device->GetIfIndex())
383 auto& stateDurations = m_linkStateDurations[linkId];
384 stateDurations[state] += duration;
static std::string FindName(Ptr< Object > object)
Given a pointer to an object, look to see if that object has a name associated with it and,...
holds a vector of ns3::NetDevice pointers
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
keep track of a set of node pointers.
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
static Ptr< Node > GetNode(uint32_t n)
Smart pointer class similar to boost::intrusive_ptr.
static Time Now()
Return the current simulation virtual time.
Simulation virtual time values and global simulation resolution.
bool IsPositive() const
Exactly equivalent to t >= 0.
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Unit
The unit to use to interpret a number representing time.
double GetDouble() const
Get the raw time value, in the current resolution unit.
bool IsZero() const
Exactly equivalent to t == 0.
std::map< WifiPhyState, double > ComputePercentage(const std::map< WifiPhyState, Time > &linkStates) const
A helper function used by PrintStatistics method.
void AlignWidth(std::vector< std::string > &column) const
A helper function used by PrintLinkStates method to format the output.
Time ComputeOverlappingDuration(Time start1, Time stop1, Time start2, Time stop2)
Compute overlapping time-duration between two intervals.
void Stop(Time stopTime)
Stops the collection of statistics at a specified time.
void Enable(NodeContainer nodes)
Enables trace collection for all nodes and WifiNetDevices in the specified NodeContainer.
void PrintStatistics(std::ostream &os, Time::Unit unit=Time::Unit::AUTO) const
Print measurement results on an output stream.
Time m_stopTime
Instant at which statistics collection should stop.
void Start(Time startTime)
Starts the collection of statistics from a specified start time.
Time m_startTime
Instant at which statistics collection should start.
std::ostream & PrintLinkStates(std::ostream &os, const std::map< WifiPhyState, Time > &linkStates, Time::Unit unit) const
A helper function used by PrintStatistics method.
void NotifyWifiPhyState(std::size_t idx, std::size_t phyId, Time start, Time duration, WifiPhyState state)
A callback used to update statistics.
std::vector< DeviceRecord > m_deviceRecords
Stores the collected statistics.
const std::vector< DeviceRecord > & GetDeviceRecords() const
Returns measurement results on each installed device.
void AlignDecimal(std::vector< std::string > &column) const
A helper function used by PrintLinkStates method to format the output.
uint32_t m_numDevices
Count the number of devices traced by this helper.
void Reset()
Resets the current statistics, clearing all links and their durations.
WifiCoTraceHelper()
Default Constructor.
#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_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.
Time Seconds(double value)
Construct a Time in the indicated unit.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
WifiPhyState
The state of the PHY layer.
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.
void AddLinkMeasurement(size_t linkId, Time start, Time duration, WifiPhyState state)
Update the duration statistics for the provided linkId and state.
std::string m_deviceName
Device name. It's empty if the name isn't configured.
DeviceRecord(Ptr< WifiNetDevice > device)
Constructor.
std::string m_nodeName
Name of Node on which the WifiNetDevice is installed.