21 #include "flow-monitor.h"
22 #include "ns3/simulator.h"
24 #include "ns3/double.h"
28 #define INDENT(level) for (int __xpto = 0; __xpto < level; __xpto++) os << ' ';
30 #define PERIODIC_CHECK_INTERVAL (Seconds (1))
36 NS_OBJECT_ENSURE_REGISTERED (FlowMonitor);
40 FlowMonitor::GetTypeId (
void)
42 static TypeId tid = TypeId (
"ns3::FlowMonitor")
44 .AddConstructor<FlowMonitor> ()
45 .AddAttribute (
"MaxPerHopDelay", (
"The maximum per-hop delay that should be considered. "
46 "Packets still not received after this delay are to be considered lost."),
48 MakeTimeAccessor (&FlowMonitor::m_maxPerHopDelay),
50 .AddAttribute (
"StartTime", (
"The time when the monitoring starts."),
54 .AddAttribute (
"DelayBinWidth", (
"The width used in the delay histogram."),
56 MakeDoubleAccessor (&FlowMonitor::m_delayBinWidth),
57 MakeDoubleChecker <double> ())
58 .AddAttribute (
"JitterBinWidth", (
"The width used in the jitter histogram."),
60 MakeDoubleAccessor (&FlowMonitor::m_jitterBinWidth),
61 MakeDoubleChecker <double> ())
62 .AddAttribute (
"PacketSizeBinWidth", (
"The width used in the packetSize histogram."),
64 MakeDoubleAccessor (&FlowMonitor::m_packetSizeBinWidth),
65 MakeDoubleChecker <double> ())
66 .AddAttribute (
"FlowInterruptionsBinWidth", (
"The width used in the flowInterruptions histogram."),
68 MakeDoubleAccessor (&FlowMonitor::m_flowInterruptionsBinWidth),
69 MakeDoubleChecker <double> ())
70 .AddAttribute (
"FlowInterruptionsMinTime", (
"The minimum inter-arrival time that is considered a flow interruption."),
72 MakeTimeAccessor (&FlowMonitor::m_flowInterruptionsMinTime),
84 FlowMonitor::FlowMonitor ()
94 for (uint32_t i = 0; i < m_flowProbes.size (); i++)
96 m_flowProbes[i]->Dispose ();
103 FlowMonitor::GetStatsForFlow (FlowId flowId)
105 std::map<FlowId, FlowStats>::iterator iter;
106 iter = m_flowStats.find (flowId);
107 if (iter == m_flowStats.end ())
122 ref.flowInterruptionsHistogram.SetDefaultBinWidth (m_flowInterruptionsBinWidth);
140 TrackedPacket &tracked = m_trackedPackets[std::make_pair (flowId, packetId)];
141 tracked.firstSeenTime = now;
142 tracked.lastSeenTime = tracked.firstSeenTime;
143 tracked.timesForwarded = 0;
144 NS_LOG_DEBUG (
"ReportFirstTx: adding tracked packet (flowId=" << flowId <<
", packetId=" << packetId
147 probe->AddPacketStats (flowId, packetSize,
Seconds (0));
149 FlowStats &stats = GetStatsForFlow (flowId);
167 std::pair<FlowId, FlowPacketId> key (flowId, packetId);
168 TrackedPacketMap::iterator tracked = m_trackedPackets.find (key);
169 if (tracked == m_trackedPackets.end ())
171 NS_LOG_WARN (
"Received packet forward report (flowId=" << flowId <<
", packetId=" << packetId
172 <<
") but not known to be transmitted.");
176 tracked->second.timesForwarded++;
180 probe->AddPacketStats (flowId, packetSize, delay);
191 TrackedPacketMap::iterator tracked = m_trackedPackets.find (std::make_pair (flowId, packetId));
192 if (tracked == m_trackedPackets.end ())
194 NS_LOG_WARN (
"Received packet last-tx report (flowId=" << flowId <<
", packetId=" << packetId
195 <<
") but not known to be transmitted.");
200 Time delay = (now - tracked->second.firstSeenTime);
201 probe->AddPacketStats (flowId, packetSize, delay);
203 FlowStats &stats = GetStatsForFlow (flowId);
208 Time jitter = stats.lastDelay - delay;
220 stats.lastDelay = delay;
233 if (interArrivalTime > m_flowInterruptionsMinTime)
235 stats.flowInterruptionsHistogram.AddValue (interArrivalTime.
GetSeconds ());
241 NS_LOG_DEBUG (
"ReportLastTx: removing tracked packet (flowId="
242 << flowId <<
", packetId=" << packetId <<
").");
244 m_trackedPackets.erase (tracked);
256 probe->AddPacketDropStats (flowId, packetSize, reasonCode);
258 FlowStats &stats = GetStatsForFlow (flowId);
269 TrackedPacketMap::iterator tracked = m_trackedPackets.find (std::make_pair (flowId, packetId));
270 if (tracked != m_trackedPackets.end ())
274 NS_LOG_DEBUG (
"ReportDrop: removing tracked packet (flowId="
275 << flowId <<
", packetId=" << packetId <<
").");
276 m_trackedPackets.erase (tracked);
280 std::map<FlowId, FlowMonitor::FlowStats>
292 for (TrackedPacketMap::iterator iter = m_trackedPackets.begin ();
293 iter != m_trackedPackets.end (); )
295 if (now - iter->second.lastSeenTime >= maxDelay)
298 std::map<FlowId, FlowStats>::iterator
299 flow = m_flowStats.find (iter->first.first);
301 flow->second.lostPackets++;
304 m_trackedPackets.erase (iter++);
320 FlowMonitor::PeriodicCheckForLostPackets ()
323 Simulator::Schedule (PERIODIC_CHECK_INTERVAL, &FlowMonitor::PeriodicCheckForLostPackets,
this);
330 Simulator::Schedule (PERIODIC_CHECK_INTERVAL, &FlowMonitor::PeriodicCheckForLostPackets,
this);
336 m_flowProbes.push_back (probe);
339 std::vector< Ptr<FlowProbe> >
394 m_classifier = classifier;
402 INDENT (indent); os <<
"<FlowMonitor>\n";
404 INDENT (indent); os <<
"<FlowStats>\n";
406 for (std::map<FlowId, FlowStats>::const_iterator flowI = m_flowStats.begin ();
407 flowI != m_flowStats.end (); flowI++)
411 #define ATTRIB(name) << " " # name "=\"" << flowI->second.name << "\""
412 os <<
"<Flow flowId=\"" << flowI->first <<
"\""
413 ATTRIB (timeFirstTxPacket)
414 ATTRIB (timeFirstRxPacket)
415 ATTRIB (timeLastTxPacket)
416 ATTRIB (timeLastRxPacket)
425 ATTRIB (timesForwarded)
431 for (uint32_t reasonCode = 0; reasonCode < flowI->second.packetsDropped.size (); reasonCode++)
434 os <<
"<packetsDropped reasonCode=\"" << reasonCode <<
"\""
435 <<
" number=\"" << flowI->second.packetsDropped[reasonCode]
438 for (uint32_t reasonCode = 0; reasonCode < flowI->second.bytesDropped.size (); reasonCode++)
441 os <<
"<bytesDropped reasonCode=\"" << reasonCode <<
"\""
442 <<
" bytes=\"" << flowI->second.bytesDropped[reasonCode]
445 if (enableHistograms)
447 flowI->second.delayHistogram.SerializeToXmlStream (os, indent,
"delayHistogram");
448 flowI->second.jitterHistogram.SerializeToXmlStream (os, indent,
"jitterHistogram");
449 flowI->second.packetSizeHistogram.SerializeToXmlStream (os, indent,
"packetSizeHistogram");
450 flowI->second.flowInterruptionsHistogram.SerializeToXmlStream (os, indent,
"flowInterruptionsHistogram");
454 INDENT (indent); os <<
"</Flow>\n";
457 INDENT (indent); os <<
"</FlowStats>\n";
459 m_classifier->SerializeToXmlStream (os, indent);
463 INDENT (indent); os <<
"<FlowProbes>\n";
465 for (uint32_t i = 0; i < m_flowProbes.size (); i++)
467 m_flowProbes[i]->SerializeToXmlStream (os, indent, i);
470 INDENT (indent); os <<
"</FlowProbes>\n";
474 INDENT (indent); os <<
"</FlowMonitor>\n";
481 std::ostringstream os;
490 std::ofstream os (fileName.c_str (), std::ios::out|std::ios::binary);
491 os <<
"<?xml version=\"1.0\" ?>\n";
smart pointer class similar to boost::intrusive_ptr
void CheckForLostPackets()
Check right now for packets that appear to be lost.
void StartRightNow()
Begin monitoring flows right now
uint32_t rxPackets
Total number of received packets for the flow.
uint32_t txPackets
Total number of transmitted packets for the flow.
#define NS_ASSERT(condition)
#define NS_LOG_COMPONENT_DEFINE(name)
void ReportDrop(Ptr< FlowProbe > probe, FlowId flowId, FlowPacketId packetId, uint32_t packetSize, uint32_t reasonCode)
virtual void DoDispose(void)
static void Cancel(const EventId &id)
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
std::vector< uint64_t > bytesDropped
void ReportFirstTx(Ptr< FlowProbe > probe, FlowId flowId, FlowPacketId packetId, uint32_t packetSize)
void SetFlowClassifier(Ptr< FlowClassifier > classifier)
Set the FlowClassifier to be used by the flow monitor.
std::map< FlowId, FlowStats > GetFlowStats() const
void SerializeToXmlStream(std::ostream &os, int indent, bool enableHistograms, bool enableProbes)
double GetSeconds(void) const
std::string SerializeToXmlString(int indent, bool enableHistograms, bool enableProbes)
virtual void NotifyConstructionCompleted(void)
virtual void NotifyConstructionCompleted()
void Stop(const Time &time)
Set the time, counting from the current time, from which to stop monitoring flows.
void StopRightNow()
End monitoring flows right now
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Histogram delayHistogram
Histogram of the packet delays.
void SerializeToXmlFile(std::string fileName, bool enableHistograms, bool enableProbes)
std::vector< Ptr< FlowProbe > > GetAllProbes() const
Get a list of all FlowProbe's associated with this FlowMonitor.
#define NS_LOG_DEBUG(msg)
virtual void DoDispose(void)
uint64_t txBytes
Total number of transmitted bytes for the flow.
Structure that represents the measured metrics of an individual packet flow.
Histogram jitterHistogram
Histogram of the packet jitters.
void Start(const Time &time)
Set the time, counting from the current time, from which to start monitoring flows.
void ReportForwarding(Ptr< FlowProbe > probe, FlowId flowId, FlowPacketId packetId, uint32_t packetSize)
uint64_t rxBytes
Total number of received bytes for the flow.
void AddProbe(Ptr< FlowProbe > probe)
void ReportLastRx(Ptr< FlowProbe > probe, FlowId flowId, FlowPacketId packetId, uint32_t packetSize)
Histogram packetSizeHistogram
Histogram of the packet sizes.
TypeId GetInstanceTypeId() const
std::vector< uint32_t > packetsDropped