A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
flow-monitor.cc
Go to the documentation of this file.
1//
2// Copyright (c) 2009 INESC Porto
3//
4// SPDX-License-Identifier: GPL-2.0-only
5//
6// Author: Gustavo J. A. M. Carneiro <gjc@inescporto.pt> <gjcarneiro@gmail.com>
7//
8
9#include "flow-monitor.h"
10
11#include "ns3/double.h"
12#include "ns3/log.h"
13#include "ns3/simulator.h"
14
15#include <fstream>
16#include <limits>
17#include <sstream>
18
19#define PERIODIC_CHECK_INTERVAL (Seconds(1))
20
21namespace ns3
22{
23
24NS_LOG_COMPONENT_DEFINE("FlowMonitor");
25
27
28TypeId
30{
31 static TypeId tid =
32 TypeId("ns3::FlowMonitor")
34 .SetGroupName("FlowMonitor")
35 .AddConstructor<FlowMonitor>()
36 .AddAttribute(
37 "MaxPerHopDelay",
38 ("The maximum per-hop delay that should be considered. "
39 "Packets still not received after this delay are to be considered lost."),
40 TimeValue(Seconds(10)),
43 .AddAttribute("StartTime",
44 ("The time when the monitoring starts."),
48 .AddAttribute("DelayBinWidth",
49 ("The width used in the delay histogram."),
50 DoubleValue(0.001),
53 .AddAttribute("JitterBinWidth",
54 ("The width used in the jitter histogram."),
55 DoubleValue(0.001),
58 .AddAttribute("PacketSizeBinWidth",
59 ("The width used in the packetSize histogram."),
60 DoubleValue(20),
63 .AddAttribute("FlowInterruptionsBinWidth",
64 ("The width used in the flowInterruptions histogram."),
65 DoubleValue(0.250),
68 .AddAttribute(
69 "FlowInterruptionsMinTime",
70 ("The minimum inter-arrival time that is considered a flow interruption."),
71 TimeValue(Seconds(0.5)),
74 return tid;
75}
76
78 : m_enabled(false)
79{
80 NS_LOG_FUNCTION(this);
81}
82
83void
85{
86 NS_LOG_FUNCTION(this);
89 for (auto iter = m_classifiers.begin(); iter != m_classifiers.end(); iter++)
90 {
91 *iter = nullptr;
92 }
93 for (uint32_t i = 0; i < m_flowProbes.size(); i++)
94 {
95 m_flowProbes[i]->Dispose();
96 m_flowProbes[i] = nullptr;
97 }
99}
100
103{
104 NS_LOG_FUNCTION(this);
105 auto iter = m_flowStats.find(flowId);
106 if (iter == m_flowStats.end())
107 {
108 FlowMonitor::FlowStats& ref = m_flowStats[flowId];
109 ref.delaySum = Seconds(0);
110 ref.jitterSum = Seconds(0);
111 ref.lastDelay = Seconds(0);
112 ref.maxDelay = Seconds(0);
113 ref.minDelay = Time::Max();
114 ref.txBytes = 0;
115 ref.rxBytes = 0;
116 ref.txPackets = 0;
117 ref.rxPackets = 0;
118 ref.lostPackets = 0;
119 ref.timesForwarded = 0;
124 return ref;
125 }
126 else
127 {
128 return iter->second;
129 }
130}
131
132void
134 uint32_t flowId,
135 uint32_t packetId,
137{
138 NS_LOG_FUNCTION(this << probe << flowId << packetId << packetSize);
139 if (!m_enabled)
140 {
141 NS_LOG_DEBUG("FlowMonitor not enabled; returning");
142 return;
143 }
144 Time now = Simulator::Now();
145 TrackedPacket& tracked = m_trackedPackets[std::make_pair(flowId, packetId)];
146 tracked.firstSeenTime = now;
147 tracked.lastSeenTime = tracked.firstSeenTime;
148 tracked.timesForwarded = 0;
149 NS_LOG_DEBUG("ReportFirstTx: adding tracked packet (flowId=" << flowId << ", packetId="
150 << packetId << ").");
151
152 probe->AddPacketStats(flowId, packetSize, Seconds(0));
153
154 FlowStats& stats = GetStatsForFlow(flowId);
155 stats.txBytes += packetSize;
156 stats.txPackets++;
157 if (stats.txPackets == 1)
158 {
159 stats.timeFirstTxPacket = now;
160 }
161 stats.timeLastTxPacket = now;
162}
163
164void
166 uint32_t flowId,
167 uint32_t packetId,
169{
170 NS_LOG_FUNCTION(this << probe << flowId << packetId << packetSize);
171 if (!m_enabled)
172 {
173 NS_LOG_DEBUG("FlowMonitor not enabled; returning");
174 return;
175 }
176 std::pair<FlowId, FlowPacketId> key(flowId, packetId);
177 auto tracked = m_trackedPackets.find(key);
178 if (tracked == m_trackedPackets.end())
179 {
180 NS_LOG_WARN("Received packet forward report (flowId="
181 << flowId << ", packetId=" << packetId << ") but not known to be transmitted.");
182 return;
183 }
184
185 tracked->second.timesForwarded++;
186 tracked->second.lastSeenTime = Simulator::Now();
187
188 Time delay = (Simulator::Now() - tracked->second.firstSeenTime);
189 probe->AddPacketStats(flowId, packetSize, delay);
190}
191
192void
194 uint32_t flowId,
195 uint32_t packetId,
197{
198 NS_LOG_FUNCTION(this << probe << flowId << packetId << packetSize);
199 if (!m_enabled)
200 {
201 NS_LOG_DEBUG("FlowMonitor not enabled; returning");
202 return;
203 }
204 auto tracked = m_trackedPackets.find(std::make_pair(flowId, packetId));
205 if (tracked == m_trackedPackets.end())
206 {
207 NS_LOG_WARN("Received packet last-tx report (flowId="
208 << flowId << ", packetId=" << packetId << ") but not known to be transmitted.");
209 return;
210 }
211
212 Time now = Simulator::Now();
213 Time delay = (now - tracked->second.firstSeenTime);
214 probe->AddPacketStats(flowId, packetSize, delay);
215
216 FlowStats& stats = GetStatsForFlow(flowId);
217 stats.delaySum += delay;
218 stats.delayHistogram.AddValue(delay.GetSeconds());
219 if (stats.rxPackets > 0)
220 {
221 Time jitter = stats.lastDelay - delay;
222 if (jitter.IsStrictlyPositive())
223 {
224 stats.jitterSum += jitter;
225 stats.jitterHistogram.AddValue(jitter.GetSeconds());
226 }
227 else
228 {
229 stats.jitterSum -= jitter;
230 stats.jitterHistogram.AddValue(-jitter.GetSeconds());
231 }
232 }
233 stats.lastDelay = delay;
234 if (delay > stats.maxDelay)
235 {
236 stats.maxDelay = delay;
237 }
238 if (delay < stats.minDelay)
239 {
240 stats.minDelay = delay;
241 }
242
243 stats.rxBytes += packetSize;
245 stats.rxPackets++;
246 if (stats.rxPackets == 1)
247 {
248 stats.timeFirstRxPacket = now;
249 }
250 else
251 {
252 // measure possible flow interruptions
253 Time interArrivalTime = now - stats.timeLastRxPacket;
254 if (interArrivalTime > m_flowInterruptionsMinTime)
255 {
256 stats.flowInterruptionsHistogram.AddValue(interArrivalTime.GetSeconds());
257 }
258 }
259 stats.timeLastRxPacket = now;
260 stats.timesForwarded += tracked->second.timesForwarded;
261
262 NS_LOG_DEBUG("ReportLastTx: removing tracked packet (flowId=" << flowId << ", packetId="
263 << packetId << ").");
264
265 m_trackedPackets.erase(tracked); // we don't need to track this packet anymore
266}
267
268void
270 uint32_t flowId,
271 uint32_t packetId,
273 uint32_t reasonCode)
274{
275 NS_LOG_FUNCTION(this << probe << flowId << packetId << packetSize << reasonCode);
276 if (!m_enabled)
277 {
278 NS_LOG_DEBUG("FlowMonitor not enabled; returning");
279 return;
280 }
281
282 probe->AddPacketDropStats(flowId, packetSize, reasonCode);
283
284 FlowStats& stats = GetStatsForFlow(flowId);
285 stats.lostPackets++;
286 if (stats.packetsDropped.size() < reasonCode + 1)
287 {
288 stats.packetsDropped.resize(reasonCode + 1, 0);
289 stats.bytesDropped.resize(reasonCode + 1, 0);
290 }
291 ++stats.packetsDropped[reasonCode];
292 stats.bytesDropped[reasonCode] += packetSize;
293 NS_LOG_DEBUG("++stats.packetsDropped["
294 << reasonCode << "]; // becomes: " << stats.packetsDropped[reasonCode]);
295
296 auto tracked = m_trackedPackets.find(std::make_pair(flowId, packetId));
297 if (tracked != m_trackedPackets.end())
298 {
299 // we don't need to track this packet anymore
300 // FIXME: this will not necessarily be true with broadcast/multicast
301 NS_LOG_DEBUG("ReportDrop: removing tracked packet (flowId=" << flowId << ", packetId="
302 << packetId << ").");
303 m_trackedPackets.erase(tracked);
304 }
305}
306
309{
310 return m_flowStats;
311}
312
313void
315{
316 NS_LOG_FUNCTION(this << maxDelay.As(Time::S));
317 Time now = Simulator::Now();
318
319 for (auto iter = m_trackedPackets.begin(); iter != m_trackedPackets.end();)
320 {
321 if (now - iter->second.lastSeenTime >= maxDelay)
322 {
323 // packet is considered lost, add it to the loss statistics
324 auto flow = m_flowStats.find(iter->first.first);
325 NS_ASSERT(flow != m_flowStats.end());
326 flow->second.lostPackets++;
327
328 // we won't track it anymore
329 m_trackedPackets.erase(iter++);
330 }
331 else
332 {
333 iter++;
334 }
335 }
336}
337
338void
343
344void
350
351void
357
358void
360{
361 m_flowProbes.push_back(probe);
362}
363
366{
367 return m_flowProbes;
368}
369
370void
372{
373 NS_LOG_FUNCTION(this << time.As(Time::S));
374 if (m_enabled)
375 {
376 NS_LOG_DEBUG("FlowMonitor already enabled; returning");
377 return;
378 }
380 NS_LOG_DEBUG("Scheduling start at " << time.As(Time::S));
382}
383
384void
386{
387 NS_LOG_FUNCTION(this << time.As(Time::S));
389 NS_LOG_DEBUG("Scheduling stop at " << time.As(Time::S));
391}
392
393void
395{
396 NS_LOG_FUNCTION(this);
397 if (m_enabled)
398 {
399 NS_LOG_DEBUG("FlowMonitor already enabled; returning");
400 return;
401 }
402 m_enabled = true;
403}
404
405void
407{
408 NS_LOG_FUNCTION(this);
409 if (!m_enabled)
410 {
411 NS_LOG_DEBUG("FlowMonitor not enabled; returning");
412 return;
413 }
414 m_enabled = false;
416}
417
418void
420{
421 m_classifiers.push_back(classifier);
422}
423
424void
426 uint16_t indent,
427 bool enableHistograms,
428 bool enableProbes)
429{
430 NS_LOG_FUNCTION(this << indent << enableHistograms << enableProbes);
432
433 os << std::string(indent, ' ') << "<FlowMonitor>\n";
434 indent += 2;
435 os << std::string(indent, ' ') << "<FlowStats>\n";
436 indent += 2;
437 for (const auto& [flowId, flowStats] : m_flowStats)
438 {
439 os << std::string(indent, ' ');
440#define ATTRIB(name) " " #name "=\"" << flowStats.name << "\""
441#define ATTRIB_TIME(name) " " #name "=\"" << flowStats.name.As(Time::NS) << "\""
442 os << "<Flow";
443 os << " flowId=\"" << flowId << "\"";
444 os << ATTRIB_TIME(timeFirstTxPacket);
445 os << ATTRIB_TIME(timeFirstRxPacket);
446 os << ATTRIB_TIME(timeLastTxPacket);
447 os << ATTRIB_TIME(timeLastRxPacket);
448 os << ATTRIB_TIME(delaySum);
449 os << ATTRIB_TIME(jitterSum);
450 os << ATTRIB_TIME(lastDelay);
451 os << ATTRIB_TIME(maxDelay);
452 os << ATTRIB_TIME(minDelay);
453 os << ATTRIB(txBytes);
454 os << ATTRIB(rxBytes);
455 os << ATTRIB(txPackets);
456 os << ATTRIB(rxPackets);
457 os << ATTRIB(lostPackets);
458 os << ATTRIB(timesForwarded);
459 os << ">\n";
460#undef ATTRIB_TIME
461#undef ATTRIB
462
463 indent += 2;
464 for (uint32_t reasonCode = 0; reasonCode < flowStats.packetsDropped.size(); reasonCode++)
465 {
466 os << std::string(indent, ' ');
467 os << "<packetsDropped reasonCode=\"" << reasonCode << "\""
468 << " number=\"" << flowStats.packetsDropped[reasonCode] << "\" />\n";
469 }
470 for (uint32_t reasonCode = 0; reasonCode < flowStats.bytesDropped.size(); reasonCode++)
471 {
472 os << std::string(indent, ' ');
473 os << "<bytesDropped reasonCode=\"" << reasonCode << "\""
474 << " bytes=\"" << flowStats.bytesDropped[reasonCode] << "\" />\n";
475 }
476 if (enableHistograms)
477 {
478 flowStats.delayHistogram.SerializeToXmlStream(os, indent, "delayHistogram");
479 flowStats.jitterHistogram.SerializeToXmlStream(os, indent, "jitterHistogram");
480 flowStats.packetSizeHistogram.SerializeToXmlStream(os, indent, "packetSizeHistogram");
481 flowStats.flowInterruptionsHistogram.SerializeToXmlStream(os,
482 indent,
483 "flowInterruptionsHistogram");
484 }
485 indent -= 2;
486
487 os << std::string(indent, ' ') << "</Flow>\n";
488 }
489 indent -= 2;
490 os << std::string(indent, ' ') << "</FlowStats>\n";
491
492 for (auto iter = m_classifiers.begin(); iter != m_classifiers.end(); iter++)
493 {
494 (*iter)->SerializeToXmlStream(os, indent);
495 }
496
497 if (enableProbes)
498 {
499 os << std::string(indent, ' ') << "<FlowProbes>\n";
500 indent += 2;
501 for (uint32_t i = 0; i < m_flowProbes.size(); i++)
502 {
503 m_flowProbes[i]->SerializeToXmlStream(os, indent, i);
504 }
505 indent -= 2;
506 os << std::string(indent, ' ') << "</FlowProbes>\n";
507 }
508
509 indent -= 2;
510 os << std::string(indent, ' ') << "</FlowMonitor>\n";
511}
512
513std::string
514FlowMonitor::SerializeToXmlString(uint16_t indent, bool enableHistograms, bool enableProbes)
515{
516 NS_LOG_FUNCTION(this << indent << enableHistograms << enableProbes);
517 std::ostringstream os;
518 SerializeToXmlStream(os, indent, enableHistograms, enableProbes);
519 return os.str();
520}
521
522void
523FlowMonitor::SerializeToXmlFile(std::string fileName, bool enableHistograms, bool enableProbes)
524{
525 NS_LOG_FUNCTION(this << fileName << enableHistograms << enableProbes);
526 std::ofstream os(fileName, std::ios::out);
527 os << "<?xml version=\"1.0\" ?>\n";
528 SerializeToXmlStream(os, 0, enableHistograms, enableProbes);
529 os.close();
530}
531
532void
534{
535 NS_LOG_FUNCTION(this);
536
537 for (auto& iter : m_flowStats)
538 {
539 auto& flowStat = iter.second;
540 flowStat.delaySum = Seconds(0);
541 flowStat.jitterSum = Seconds(0);
542 flowStat.lastDelay = Seconds(0);
543 flowStat.maxDelay = Seconds(0);
544 flowStat.minDelay = Seconds(std::numeric_limits<double>::max());
545 flowStat.txBytes = 0;
546 flowStat.rxBytes = 0;
547 flowStat.txPackets = 0;
548 flowStat.rxPackets = 0;
549 flowStat.lostPackets = 0;
550 flowStat.timesForwarded = 0;
551 flowStat.bytesDropped.clear();
552 flowStat.packetsDropped.clear();
553
554 flowStat.delayHistogram.Clear();
555 flowStat.jitterHistogram.Clear();
556 flowStat.packetSizeHistogram.Clear();
557 flowStat.flowInterruptionsHistogram.Clear();
558 }
559}
560
561} // namespace ns3
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
An object that monitors and reports back packet flows observed during a simulation.
FlowStats & GetStatsForFlow(FlowId flowId)
Get the stats for a given flow.
FlowProbeContainer m_flowProbes
all the FlowProbes
void StopRightNow()
End monitoring flows right now
void ResetAllStats()
Reset all the statistics.
const FlowProbeContainer & GetAllProbes() const
Get a list of all FlowProbe's associated with this FlowMonitor.
std::vector< Ptr< FlowProbe > > FlowProbeContainer
Container: FlowProbe.
FlowStatsContainer m_flowStats
FlowId --> FlowStats.
bool m_enabled
FlowMon is enabled.
void CheckForLostPackets()
Check right now for packets that appear to be lost.
void Start(const Time &time)
Set the time, counting from the current time, from which to start monitoring flows.
double m_flowInterruptionsBinWidth
Flow interruptions bin width (for histograms)
void SerializeToXmlFile(std::string fileName, bool enableHistograms, bool enableProbes)
Same as SerializeToXmlStream, but writes to a file instead.
void AddFlowClassifier(Ptr< FlowClassifier > classifier)
Add a FlowClassifier to be used by the flow monitor.
void ReportLastRx(Ptr< FlowProbe > probe, FlowId flowId, FlowPacketId packetId, uint32_t packetSize)
FlowProbe implementations are supposed to call this method to report that a known packet is being rec...
EventId m_startEvent
Start event.
std::list< Ptr< FlowClassifier > > m_classifiers
the FlowClassifiers
void AddProbe(Ptr< FlowProbe > probe)
Register a new FlowProbe that will begin monitoring and report events to this monitor.
void ReportForwarding(Ptr< FlowProbe > probe, FlowId flowId, FlowPacketId packetId, uint32_t packetSize)
FlowProbe implementations are supposed to call this method to report that a known packet is being for...
Time m_flowInterruptionsMinTime
Flow interruptions minimum time.
std::map< FlowId, FlowStats > FlowStatsContainer
Container: FlowId, FlowStats.
double m_jitterBinWidth
Jitter bin width (for histograms)
std::string SerializeToXmlString(uint16_t indent, bool enableHistograms, bool enableProbes)
Same as SerializeToXmlStream, but returns the output as a std::string.
void Stop(const Time &time)
Set the time, counting from the current time, from which to stop monitoring flows.
void PeriodicCheckForLostPackets()
Periodic function to check for lost packets and prune statistics.
double m_packetSizeBinWidth
packet size bin width (for histograms)
Time m_maxPerHopDelay
Minimum per-hop delay.
void DoDispose() override
Destructor implementation.
void NotifyConstructionCompleted() override
Notifier called once the ObjectBase is fully constructed.
const FlowStatsContainer & GetFlowStats() const
Retrieve all collected the flow statistics.
TrackedPacketMap m_trackedPackets
Tracked packets.
double m_delayBinWidth
Delay bin width (for histograms)
void StartRightNow()
Begin monitoring flows right now
void ReportFirstTx(Ptr< FlowProbe > probe, FlowId flowId, FlowPacketId packetId, uint32_t packetSize)
FlowProbe implementations are supposed to call this method to report that a new packet was transmitte...
void SerializeToXmlStream(std::ostream &os, uint16_t indent, bool enableHistograms, bool enableProbes)
Serializes the results to an std::ostream in XML format.
EventId m_stopEvent
Stop event.
static TypeId GetTypeId()
Get the type ID.
void ReportDrop(Ptr< FlowProbe > probe, FlowId flowId, FlowPacketId packetId, uint32_t packetSize, uint32_t reasonCode)
FlowProbe implementations are supposed to call this method to report that a known packet is being dro...
void SetDefaultBinWidth(double binWidth)
Set the bin width.
Definition histogram.cc:56
void AddValue(double value)
Add a value to the histogram.
Definition histogram.cc:70
virtual void NotifyConstructionCompleted()
Notifier called once the ObjectBase is fully constructed.
A base class which provides memory management and object aggregation.
Definition object.h:78
virtual void DoDispose()
Destructor implementation.
Definition object.cc:433
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.
Definition simulator.h:561
static void Cancel(const EventId &id)
Set the cancel bit on this event: the event's associated function will not be invoked when it expires...
Definition simulator.cc:274
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:403
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:392
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition nstime.h:340
@ S
second
Definition nstime.h:105
static Time Max()
Maximum representable Time Not to be confused with Max(Time,Time).
Definition nstime.h:286
AttributeValue implementation for Time.
Definition nstime.h:1432
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
#define ATTRIB(name)
#define PERIODIC_CHECK_INTERVAL
#define ATTRIB_TIME(name)
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
Ptr< const AttributeChecker > MakeDoubleChecker()
Definition double.h:82
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition double.h:32
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition nstime.h:1433
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1453
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition log.h:250
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1345
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Structure that represents the measured metrics of an individual packet flow.
uint32_t rxPackets
Total number of received packets for the flow.
Histogram packetSizeHistogram
Histogram of the packet sizes.
Time timeLastTxPacket
Contains the absolute time when the last packet in the flow was transmitted, i.e.
uint32_t lostPackets
Total number of packets that are assumed to be lost, i.e.
Histogram jitterHistogram
Histogram of the packet jitters.
Time lastDelay
Contains the last measured delay of a packet It is stored to measure the packet's Jitter.
Time timeLastRxPacket
Contains the absolute time when the last packet in the flow was received, i.e.
Histogram flowInterruptionsHistogram
histogram of durations of flow interruptions
uint64_t rxBytes
Total number of received bytes for the flow.
Time maxDelay
Contains the largest measured delay of a received packet.
Time minDelay
Contains the smallest measured delay of a received packet.
Time delaySum
Contains the sum of all end-to-end delays for all received packets of the flow.
Time timeFirstRxPacket
Contains the absolute time when the first packet in the flow was received by an end node,...
uint32_t timesForwarded
Contains the number of times a packet has been reportedly forwarded, summed for all received packets ...
uint32_t txPackets
Total number of transmitted packets for the flow.
uint64_t txBytes
Total number of transmitted bytes for the flow.
Histogram delayHistogram
Histogram of the packet delays.
Time jitterSum
Contains the sum of all end-to-end delay jitter (delay variation) values for all received packets of ...
std::vector< uint64_t > bytesDropped
This attribute also tracks the number of lost bytes.
Time timeFirstTxPacket
Contains the absolute time when the first packet in the flow was transmitted, i.e.
std::vector< uint32_t > packetsDropped
This attribute also tracks the number of lost packets and bytes, but discriminates the losses by a re...
Structure to represent a single tracked packet data.
Time lastSeenTime
absolute time when the packet was last seen by a probe
Time firstSeenTime
absolute time when the packet was first seen by a probe
uint32_t timesForwarded
number of times the packet was reportedly forwarded
static const uint32_t packetSize
Packet size generated at the AP.