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 <sstream>
17
18#define PERIODIC_CHECK_INTERVAL (Seconds(1))
19
20namespace ns3
21{
22
23NS_LOG_COMPONENT_DEFINE("FlowMonitor");
24
26
27TypeId
29{
30 static TypeId tid =
31 TypeId("ns3::FlowMonitor")
33 .SetGroupName("FlowMonitor")
34 .AddConstructor<FlowMonitor>()
35 .AddAttribute(
36 "MaxPerHopDelay",
37 ("The maximum per-hop delay that should be considered. "
38 "Packets still not received after this delay are to be considered lost."),
39 TimeValue(Seconds(10)),
42 .AddAttribute("StartTime",
43 ("The time when the monitoring starts."),
47 .AddAttribute("DelayBinWidth",
48 ("The width used in the delay histogram."),
49 DoubleValue(0.001),
52 .AddAttribute("JitterBinWidth",
53 ("The width used in the jitter histogram."),
54 DoubleValue(0.001),
57 .AddAttribute("PacketSizeBinWidth",
58 ("The width used in the packetSize histogram."),
59 DoubleValue(20),
62 .AddAttribute("FlowInterruptionsBinWidth",
63 ("The width used in the flowInterruptions histogram."),
64 DoubleValue(0.250),
67 .AddAttribute(
68 "FlowInterruptionsMinTime",
69 ("The minimum inter-arrival time that is considered a flow interruption."),
70 TimeValue(Seconds(0.5)),
73 return tid;
74}
75
77 : m_enabled(false)
78{
79 NS_LOG_FUNCTION(this);
80}
81
82void
84{
85 NS_LOG_FUNCTION(this);
88 for (auto iter = m_classifiers.begin(); iter != m_classifiers.end(); iter++)
89 {
90 *iter = nullptr;
91 }
92 for (uint32_t i = 0; i < m_flowProbes.size(); i++)
93 {
94 m_flowProbes[i]->Dispose();
95 m_flowProbes[i] = nullptr;
96 }
98}
99
102{
103 NS_LOG_FUNCTION(this);
104 auto iter = m_flowStats.find(flowId);
105 if (iter == m_flowStats.end())
106 {
107 FlowMonitor::FlowStats& ref = m_flowStats[flowId];
108 ref.delaySum = Seconds(0);
109 ref.jitterSum = Seconds(0);
110 ref.lastDelay = Seconds(0);
111 ref.maxDelay = Seconds(0);
112 ref.minDelay = Time::Max();
113 ref.txBytes = 0;
114 ref.rxBytes = 0;
115 ref.txPackets = 0;
116 ref.rxPackets = 0;
117 ref.lostPackets = 0;
118 ref.timesForwarded = 0;
123 return ref;
124 }
125 else
126 {
127 return iter->second;
128 }
129}
130
131void
133 uint32_t flowId,
134 uint32_t packetId,
136{
137 NS_LOG_FUNCTION(this << probe << flowId << packetId << packetSize);
138 if (!m_enabled)
139 {
140 NS_LOG_DEBUG("FlowMonitor not enabled; returning");
141 return;
142 }
143 Time now = Simulator::Now();
144 TrackedPacket& tracked = m_trackedPackets[std::make_pair(flowId, packetId)];
145 tracked.firstSeenTime = now;
146 tracked.lastSeenTime = tracked.firstSeenTime;
147 tracked.timesForwarded = 0;
148 NS_LOG_DEBUG("ReportFirstTx: adding tracked packet (flowId=" << flowId << ", packetId="
149 << packetId << ").");
150
151 probe->AddPacketStats(flowId, packetSize, Seconds(0));
152
153 FlowStats& stats = GetStatsForFlow(flowId);
154 stats.txBytes += packetSize;
155 stats.txPackets++;
156 if (stats.txPackets == 1)
157 {
158 stats.timeFirstTxPacket = now;
159 }
160 stats.timeLastTxPacket = now;
161}
162
163void
165 uint32_t flowId,
166 uint32_t packetId,
168{
169 NS_LOG_FUNCTION(this << probe << flowId << packetId << packetSize);
170 if (!m_enabled)
171 {
172 NS_LOG_DEBUG("FlowMonitor not enabled; returning");
173 return;
174 }
175 std::pair<FlowId, FlowPacketId> key(flowId, packetId);
176 auto tracked = m_trackedPackets.find(key);
177 if (tracked == m_trackedPackets.end())
178 {
179 NS_LOG_WARN("Received packet forward report (flowId="
180 << flowId << ", packetId=" << packetId << ") but not known to be transmitted.");
181 return;
182 }
183
184 tracked->second.timesForwarded++;
185 tracked->second.lastSeenTime = Simulator::Now();
186
187 Time delay = (Simulator::Now() - tracked->second.firstSeenTime);
188 probe->AddPacketStats(flowId, packetSize, delay);
189}
190
191void
193 uint32_t flowId,
194 uint32_t packetId,
196{
197 NS_LOG_FUNCTION(this << probe << flowId << packetId << packetSize);
198 if (!m_enabled)
199 {
200 NS_LOG_DEBUG("FlowMonitor not enabled; returning");
201 return;
202 }
203 auto tracked = m_trackedPackets.find(std::make_pair(flowId, packetId));
204 if (tracked == m_trackedPackets.end())
205 {
206 NS_LOG_WARN("Received packet last-tx report (flowId="
207 << flowId << ", packetId=" << packetId << ") but not known to be transmitted.");
208 return;
209 }
210
211 Time now = Simulator::Now();
212 Time delay = (now - tracked->second.firstSeenTime);
213 probe->AddPacketStats(flowId, packetSize, delay);
214
215 FlowStats& stats = GetStatsForFlow(flowId);
216 stats.delaySum += delay;
217 stats.delayHistogram.AddValue(delay.GetSeconds());
218 if (stats.rxPackets > 0)
219 {
220 Time jitter = stats.lastDelay - delay;
221 if (jitter.IsStrictlyPositive())
222 {
223 stats.jitterSum += jitter;
224 stats.jitterHistogram.AddValue(jitter.GetSeconds());
225 }
226 else
227 {
228 stats.jitterSum -= jitter;
229 stats.jitterHistogram.AddValue(-jitter.GetSeconds());
230 }
231 }
232 stats.lastDelay = delay;
233 if (delay > stats.maxDelay)
234 {
235 stats.maxDelay = delay;
236 }
237 if (delay < stats.minDelay)
238 {
239 stats.minDelay = delay;
240 }
241
242 stats.rxBytes += packetSize;
244 stats.rxPackets++;
245 if (stats.rxPackets == 1)
246 {
247 stats.timeFirstRxPacket = now;
248 }
249 else
250 {
251 // measure possible flow interruptions
252 Time interArrivalTime = now - stats.timeLastRxPacket;
253 if (interArrivalTime > m_flowInterruptionsMinTime)
254 {
255 stats.flowInterruptionsHistogram.AddValue(interArrivalTime.GetSeconds());
256 }
257 }
258 stats.timeLastRxPacket = now;
259 stats.timesForwarded += tracked->second.timesForwarded;
260
261 NS_LOG_DEBUG("ReportLastTx: removing tracked packet (flowId=" << flowId << ", packetId="
262 << packetId << ").");
263
264 m_trackedPackets.erase(tracked); // we don't need to track this packet anymore
265}
266
267void
269 uint32_t flowId,
270 uint32_t packetId,
272 uint32_t reasonCode)
273{
274 NS_LOG_FUNCTION(this << probe << flowId << packetId << packetSize << reasonCode);
275 if (!m_enabled)
276 {
277 NS_LOG_DEBUG("FlowMonitor not enabled; returning");
278 return;
279 }
280
281 probe->AddPacketDropStats(flowId, packetSize, reasonCode);
282
283 FlowStats& stats = GetStatsForFlow(flowId);
284 stats.lostPackets++;
285 if (stats.packetsDropped.size() < reasonCode + 1)
286 {
287 stats.packetsDropped.resize(reasonCode + 1, 0);
288 stats.bytesDropped.resize(reasonCode + 1, 0);
289 }
290 ++stats.packetsDropped[reasonCode];
291 stats.bytesDropped[reasonCode] += packetSize;
292 NS_LOG_DEBUG("++stats.packetsDropped["
293 << reasonCode << "]; // becomes: " << stats.packetsDropped[reasonCode]);
294
295 auto tracked = m_trackedPackets.find(std::make_pair(flowId, packetId));
296 if (tracked != m_trackedPackets.end())
297 {
298 // we don't need to track this packet anymore
299 // FIXME: this will not necessarily be true with broadcast/multicast
300 NS_LOG_DEBUG("ReportDrop: removing tracked packet (flowId=" << flowId << ", packetId="
301 << packetId << ").");
302 m_trackedPackets.erase(tracked);
303 }
304}
305
308{
309 return m_flowStats;
310}
311
312void
314{
315 NS_LOG_FUNCTION(this << maxDelay.As(Time::S));
316 Time now = Simulator::Now();
317
318 for (auto iter = m_trackedPackets.begin(); iter != m_trackedPackets.end();)
319 {
320 if (now - iter->second.lastSeenTime >= maxDelay)
321 {
322 // packet is considered lost, add it to the loss statistics
323 auto flow = m_flowStats.find(iter->first.first);
324 NS_ASSERT(flow != m_flowStats.end());
325 flow->second.lostPackets++;
326
327 // we won't track it anymore
328 m_trackedPackets.erase(iter++);
329 }
330 else
331 {
332 iter++;
333 }
334 }
335}
336
337void
342
343void
349
350void
356
357void
359{
360 m_flowProbes.push_back(probe);
361}
362
365{
366 return m_flowProbes;
367}
368
369void
371{
372 NS_LOG_FUNCTION(this << time.As(Time::S));
373 if (m_enabled)
374 {
375 NS_LOG_DEBUG("FlowMonitor already enabled; returning");
376 return;
377 }
379 NS_LOG_DEBUG("Scheduling start at " << time.As(Time::S));
381}
382
383void
385{
386 NS_LOG_FUNCTION(this << time.As(Time::S));
388 NS_LOG_DEBUG("Scheduling stop at " << time.As(Time::S));
390}
391
392void
394{
395 NS_LOG_FUNCTION(this);
396 if (m_enabled)
397 {
398 NS_LOG_DEBUG("FlowMonitor already enabled; returning");
399 return;
400 }
401 m_enabled = true;
402}
403
404void
406{
407 NS_LOG_FUNCTION(this);
408 if (!m_enabled)
409 {
410 NS_LOG_DEBUG("FlowMonitor not enabled; returning");
411 return;
412 }
413 m_enabled = false;
415}
416
417void
419{
420 m_classifiers.push_back(classifier);
421}
422
423void
425 uint16_t indent,
426 bool enableHistograms,
427 bool enableProbes)
428{
429 NS_LOG_FUNCTION(this << indent << enableHistograms << enableProbes);
431
432 os << std::string(indent, ' ') << "<FlowMonitor>\n";
433 indent += 2;
434 os << std::string(indent, ' ') << "<FlowStats>\n";
435 indent += 2;
436 for (const auto& [flowId, flowStats] : m_flowStats)
437 {
438 os << std::string(indent, ' ');
439#define ATTRIB(name) " " #name "=\"" << flowStats.name << "\""
440#define ATTRIB_TIME(name) " " #name "=\"" << flowStats.name.As(Time::NS) << "\""
441 os << "<Flow";
442 os << " flowId=\"" << flowId << "\"";
443 os << ATTRIB_TIME(timeFirstTxPacket);
444 os << ATTRIB_TIME(timeFirstRxPacket);
445 os << ATTRIB_TIME(timeLastTxPacket);
446 os << ATTRIB_TIME(timeLastRxPacket);
447 os << ATTRIB_TIME(delaySum);
448 os << ATTRIB_TIME(jitterSum);
449 os << ATTRIB_TIME(lastDelay);
450 os << ATTRIB_TIME(maxDelay);
451 os << ATTRIB_TIME(minDelay);
452 os << ATTRIB(txBytes);
453 os << ATTRIB(rxBytes);
454 os << ATTRIB(txPackets);
455 os << ATTRIB(rxPackets);
456 os << ATTRIB(lostPackets);
457 os << ATTRIB(timesForwarded);
458 os << ">\n";
459#undef ATTRIB_TIME
460#undef ATTRIB
461
462 indent += 2;
463 for (uint32_t reasonCode = 0; reasonCode < flowStats.packetsDropped.size(); reasonCode++)
464 {
465 os << std::string(indent, ' ');
466 os << "<packetsDropped reasonCode=\"" << reasonCode << "\""
467 << " number=\"" << flowStats.packetsDropped[reasonCode] << "\" />\n";
468 }
469 for (uint32_t reasonCode = 0; reasonCode < flowStats.bytesDropped.size(); reasonCode++)
470 {
471 os << std::string(indent, ' ');
472 os << "<bytesDropped reasonCode=\"" << reasonCode << "\""
473 << " bytes=\"" << flowStats.bytesDropped[reasonCode] << "\" />\n";
474 }
475 if (enableHistograms)
476 {
477 flowStats.delayHistogram.SerializeToXmlStream(os, indent, "delayHistogram");
478 flowStats.jitterHistogram.SerializeToXmlStream(os, indent, "jitterHistogram");
479 flowStats.packetSizeHistogram.SerializeToXmlStream(os, indent, "packetSizeHistogram");
480 flowStats.flowInterruptionsHistogram.SerializeToXmlStream(os,
481 indent,
482 "flowInterruptionsHistogram");
483 }
484 indent -= 2;
485
486 os << std::string(indent, ' ') << "</Flow>\n";
487 }
488 indent -= 2;
489 os << std::string(indent, ' ') << "</FlowStats>\n";
490
491 for (auto iter = m_classifiers.begin(); iter != m_classifiers.end(); iter++)
492 {
493 (*iter)->SerializeToXmlStream(os, indent);
494 }
495
496 if (enableProbes)
497 {
498 os << std::string(indent, ' ') << "<FlowProbes>\n";
499 indent += 2;
500 for (uint32_t i = 0; i < m_flowProbes.size(); i++)
501 {
502 m_flowProbes[i]->SerializeToXmlStream(os, indent, i);
503 }
504 indent -= 2;
505 os << std::string(indent, ' ') << "</FlowProbes>\n";
506 }
507
508 indent -= 2;
509 os << std::string(indent, ' ') << "</FlowMonitor>\n";
510}
511
512std::string
513FlowMonitor::SerializeToXmlString(uint16_t indent, bool enableHistograms, bool enableProbes)
514{
515 NS_LOG_FUNCTION(this << indent << enableHistograms << enableProbes);
516 std::ostringstream os;
517 SerializeToXmlStream(os, indent, enableHistograms, enableProbes);
518 return os.str();
519}
520
521void
522FlowMonitor::SerializeToXmlFile(std::string fileName, bool enableHistograms, bool enableProbes)
523{
524 NS_LOG_FUNCTION(this << fileName << enableHistograms << enableProbes);
525 std::ofstream os(fileName, std::ios::out);
526 os << "<?xml version=\"1.0\" ?>\n";
527 SerializeToXmlStream(os, 0, enableHistograms, enableProbes);
528 os.close();
529}
530
531void
533{
534 NS_LOG_FUNCTION(this);
535
536 for (auto& iter : m_flowStats)
537 {
538 auto& flowStat = iter.second;
539 flowStat.delaySum = Seconds(0);
540 flowStat.jitterSum = Seconds(0);
541 flowStat.lastDelay = Seconds(0);
542 flowStat.maxDelay = Seconds(0);
543 flowStat.minDelay = Time::Max();
544 flowStat.txBytes = 0;
545 flowStat.rxBytes = 0;
546 flowStat.txPackets = 0;
547 flowStat.rxPackets = 0;
548 flowStat.lostPackets = 0;
549 flowStat.timesForwarded = 0;
550 flowStat.bytesDropped.clear();
551 flowStat.packetsDropped.clear();
552
553 flowStat.delayHistogram.Clear();
554 flowStat.jitterHistogram.Clear();
555 flowStat.packetSizeHistogram.Clear();
556 flowStat.flowInterruptionsHistogram.Clear();
557 }
558}
559
560} // namespace ns3
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
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.
Object()
Caller graph was not generated because of its size.
Definition object.cc:93
virtual void DoDispose()
Destructor implementation.
Definition object.cc:430
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:580
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:268
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:191
Simulation virtual time values and global simulation resolution.
Definition nstime.h:96
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:408
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:399
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition nstime.h:342
@ S
second
Definition nstime.h:107
static Time Max()
Maximum representable Time Not to be confused with Max(Time,Time).
Definition nstime.h:288
AttributeValue implementation for Time.
Definition nstime.h:1483
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:999
#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:1484
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1504
uint32_t FlowId
Abstract identifier of a packet flow.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:260
#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:253
#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:1381
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.