FlowStatistics.cci
Go to the documentation of this file.
1 //
2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
6 //
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
11 //
12 
13 
14 #include <senf/Utils/senflikely.hh>
15 
16 #define prefix_ inline
17 ///////////////////////////////cci.p///////////////////////////////////////
18 
19 
20 ///////////////////////////////////////////////////////////////////////////
21 // senf::SequenceNumberStatistics
22 
23 prefix_ senf::SequenceNumberStatistics::SequenceNumberStatistics(std::uint8_t bits, std::int32_t maxLate)
24  : DifferenceSigned(bits),
25  maxLate_(maxLate)
26 {
27  reset();
28 }
29 
30 prefix_ void senf::SequenceNumberStatistics::reset()
31 {
32  clear();
33  last_ = 0;
34  goodTotal = 0;
35  goodBytesTotal = 0;
36  firstUpdateAfterReset_ = true;
37 }
38 
39 prefix_ void senf::SequenceNumberStatistics::clear()
40 {
41  goodTotal += good;
42  goodBytesTotal += goodBytes;
43  good = goodBytes = duplicate = late = lost = lostLate = lateMax = 0;
44  resyncs = 0;
45 }
46 
47 prefix_ std::int32_t senf::SequenceNumberStatistics::maxLate()
48  const
49 {
50  return maxLate_;
51 }
52 
53 prefix_ void senf::SequenceNumberStatistics::countGood(std::uint32_t payloadSize)
54 {
55  good++;
56  goodBytes += payloadSize;
57 }
58 
59 prefix_ bool senf::SequenceNumberStatistics::update(std::uint32_t seqNo, std::uint32_t payloadSize)
60 {
61  if (SENF_UNLIKELY(firstUpdateAfterReset_)) {
62  firstUpdateAfterReset_ = false;
63  countGood(payloadSize);
64  last_ = seqNo;
65  return true;
66  }
67 
68  auto diff (difference(seqNo, last_));
69 
70  if (SENF_LIKELY(diff == 1)) {
71  // no loss
72  countGood(payloadSize);
73  last_ = seqNo;
74  return true;
75  }
76  else if (diff == 0) {
77  // duplicate
78  duplicate++;
79  }
80  else if (diff < 0) {
81  // late frame(s) => reordering
82  if (diff <= -maxLate_) {
83  // resync to next expected SeqNo
84  resyncs++;
85  countGood(payloadSize);
86  last_ = seqNo;
87  return true;
88  } else {
89  // we are tolerant to reordering here. So, let's account for it, ...
90  late++;
91  lateMax = std::max(lateMax, std::uint32_t(-diff));
92  if (SENF_LIKELY(lost > 0)) {
93  // we counted this 'late' frame as lost before, so let's reduce the lost count here
94  lost--;
95  // count 'recovered' frames
96  lostLate++;
97  countGood(payloadSize);
98  }
99  // ... but not suggest to drop the frame
100  return true;
101  }
102  } else {
103  // frame loss
104  lost += diff-1;
105  countGood(payloadSize);
106  last_ = seqNo;
107  return true;
108  }
109 
110  // essentially, we only indidate 'duplicates' to be dropped
111  return false;
112 }
113 
114 prefix_ void senf::SequenceNumberStatistics::dump(std::ostream & os, senf::ClockService::clock_type const & period)
115  const
116 {
117  os << "good " << good << ", goodBytes " << goodBytes;
118  if (period) {
119  os << ", good/s " << ((std::uint64_t(good) * 1000) / senf::ClockService::in_milliseconds(period));
120  os << ", goodBytes/s " << ((std::uint64_t(goodBytes) * 1000) / senf::ClockService::in_milliseconds(period));
121  }
122  os << ", duplicate " << duplicate << ", late " << late << ", lost " << lost;
123  os << ", resyncs " << resyncs;
124 }
125 
126 
127 ///////////////////////////////////////////////////////////////////////////
128 // senf::TimestampStatistics
129 
130 prefix_ senf::TimestampStatistics::TimestampStatistics(std::uint8_t bits)
131  : DifferenceSigned(bits)
132 {
133  reset();
134 }
135 
136 prefix_ void senf::TimestampStatistics::reset()
137 {
138  clear();
139  lastPD_ = 0;
140  firstUpdateAfterReset_ = true;
141 }
142 
143 prefix_ void senf::TimestampStatistics::clear()
144 {
145  delay.clear();
146  pdv.clear();
147 }
148 
149 
150 prefix_ void senf::TimestampStatistics::update(std::uint32_t txTStamp, std::uint32_t rxTStamp, bool updateDelay)
151 {
152  auto diff (difference(rxTStamp, txTStamp));
153 
154  // first packet seen => establish the typical delay
155  if (SENF_UNLIKELY(firstUpdateAfterReset_)) {
156  firstUpdateAfterReset_ = false;
157  lastPD_ = diff;
158  }
159 
160  pdv.accumulate(unsigned(abs(diff - lastPD_)));
161  lastPD_ = diff;
162 
163  if (updateDelay) {
164  delay.accumulate(diff);
165  }
166 }
167 
168 
169 ///////////////////////////////cci.e///////////////////////////////////////
170 #undef prefix_