A Discrete-Event Network Simulator
API
lollipop-counter.h
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2020 Universita' di Firenze, Italy
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
19 */
20
21
22#ifndef LOLLIPOP_COUNTER_H
23#define LOLLIPOP_COUNTER_H
24
25#include <limits>
26#include "ns3/abort.h"
27
28namespace ns3 {
29
63template <class T>
65{
66public:
74 {
75 NS_ABORT_MSG_UNLESS (std::is_unsigned<T>::value, "Lollipop counters must be defined on unsigned integer types");
76
77 uint16_t numberofDigits = std::numeric_limits<T>::digits;
78 m_sequenceWindow = 1 << (numberofDigits / 2);
79
81 }
82
92 {
93 uint16_t numberofDigits = std::numeric_limits<T>::digits;
94 m_sequenceWindow = 1 << (numberofDigits / 2);
95
96 m_value = val;
97 }
98
106 {
107 m_value = o.m_value;
108 return *this;
109 }
110
114 void Reset ()
115 {
117 }
118
128 void SetSequenceWindowSize (uint16_t numberOfBits)
129 {
130 uint16_t numberofDigits = std::numeric_limits<T>::digits;
131
132 NS_ABORT_MSG_IF (numberOfBits >= numberofDigits, "The size of the Sequence Window should be less than the counter size (which is " << +m_maxValue << ")");
133
134 m_sequenceWindow = 1 << numberOfBits;
135
137 }
138
153 bool IsComparable (const LollipopCounter &val) const
154 {
155 NS_ABORT_MSG_IF (m_sequenceWindow != val.m_sequenceWindow, "Can not compare two Lollipop Counters with different sequence windows");
156
159 {
160 // They are desynchronized - comparison is impossible.
161 T absDiff = AbsoluteMagnitudeOfDifference (val);
162 if (absDiff > m_sequenceWindow)
163 {
164 return false;
165 }
166 }
167 return true;
168 }
169
175 bool IsInit () const
176 {
178 {
179 return true;
180 }
181 return false;
182 }
183
190 friend bool operator == (const LollipopCounter & lhs, const LollipopCounter & rhs)
191 {
192
193 NS_ABORT_MSG_IF (lhs.m_sequenceWindow != rhs.m_sequenceWindow, "Can not compare two Lollipop Counters with different sequence windows");
194
195 if (lhs.m_value == rhs.m_value)
196 {
197 return true;
198 }
199 return false;
200 }
201
208 friend bool operator > (const LollipopCounter & lhs, const LollipopCounter & rhs)
209 {
210 NS_ABORT_MSG_IF (lhs.m_sequenceWindow != rhs.m_sequenceWindow, "Can not compare two Lollipop Counters with different sequence windows");
211
212 if (lhs.m_value == rhs.m_value)
213 {
214 return false;
215 }
216
217 if ((lhs.m_value <= m_circularRegion && rhs.m_value <= m_circularRegion)
219 {
220 // both counters are in the same region
221
222 T absDiff = lhs.AbsoluteMagnitudeOfDifference (rhs);
223 if (absDiff > lhs.m_sequenceWindow)
224 {
225 // They are desynchronized - comparison is impossible.
226 // return false because we can not return anything else.
227 return false;
228 }
229
230 // They are synchronized - comparison according to RFC1982.
231 T serialRegion = ((m_circularRegion >> 1) + 1);
232 return (((lhs.m_value < rhs.m_value) && ((rhs.m_value - lhs.m_value) > serialRegion))
233 || ((lhs.m_value > rhs.m_value) && ((lhs.m_value - rhs.m_value) < serialRegion)) );
234 }
235
236 // One counter is in the "high" region and the other is in the in the "lower" region
237 bool lhsIsHigher;
238 T difference;
239
241 {
242 lhsIsHigher = true;
243 // this is guaranteed to be positive and between [1...m_lollipopMaxValue].
244 difference = lhs.m_value - rhs.m_value;
245 }
246 else
247 {
248 lhsIsHigher = false;
249 // this is guaranteed to be positive and between [1...m_lollipopMaxValue].
250 difference = rhs.m_value - lhs.m_value;
251 }
252
253 T distance = (m_maxValue - difference) + 1; // this is guaranteed to be positive and between [1...m_lollipopMaxValue].
254 if (distance > lhs.m_sequenceWindow)
255 {
256 if (lhsIsHigher)
257 {
258 return true;
259 }
260 else
261 {
262 return false;
263 }
264 }
265 else
266 {
267 if (lhsIsHigher)
268 {
269 return false;
270 }
271 else
272 {
273 return true;
274 }
275 }
276
277 // this should never be reached.
278 return false;
279 }
280
287 friend bool operator < (const LollipopCounter & lhs, const LollipopCounter & rhs)
288 {
289 if (!lhs.IsComparable (rhs))
290 {
291 return false;
292 }
293
294 if (lhs > rhs)
295 {
296 return false;
297 }
298 else if (lhs == rhs)
299 {
300 return false;
301 }
302
303 return true;
304 }
305
312 {
313 val.m_value++;
314
315 if ( val.m_value == val.m_circularRegion + 1 )
316 {
317 val.m_value = 0;
318 }
319
320 return val;
321 }
322
329 friend LollipopCounter operator++ (LollipopCounter& val, int noop) // postfix ++
330 {
331 LollipopCounter ans = val;
332 ++(val); // or just call operator++()
333 return ans;
334 }
335
341 T GetValue () const
342 {
343 return m_value;
344 }
345
353 friend std::ostream &
354 operator<< (std::ostream & os, LollipopCounter const & counter)
355 {
356 os << +counter.m_value;
357 return os;
358 }
359
360private:
361
374 {
375 // useless because it is computed always on counters on their respective regions.
376 // Left (commented) for debugging purposes in case there is a code change.
377 // NS_ASSERT_MSG ((m_value <= m_circularRegion && val.m_value <= m_circularRegion) ||
378 // (m_value > m_circularRegion && val.m_value > m_circularRegion),
379 // "Absolute Magnitude Of Difference can be computed only on two values in the circular region " << +m_value << " - " << +val.m_value);
380
381 T absDiffDirect = std::max (m_value, val.m_value) - std::min (m_value, val.m_value);
382 T absDiffWrapped = (std::min (m_value, val.m_value) + m_circularRegion + 1) - std::max (m_value, val.m_value);
383 T absDiff = std::min (absDiffDirect, absDiffWrapped);
384 return absDiff;
385 }
386
389 static constexpr T m_maxValue = std::numeric_limits<T>::max ();
390 static constexpr T m_circularRegion = m_maxValue >> 1;
391};
392
403
404} /* namespace ns3 */
405
406#endif /* LOLLIPOP_COUNTER_H */
#define min(a, b)
Definition: 80211b.c:42
#define max(a, b)
Definition: 80211b.c:43
Template class implementing a Lollipop counter as defined in RFC 8505, RFC 6550, and [Perlman83].
friend std::ostream & operator<<(std::ostream &os, LollipopCounter const &counter)
Output streamer for LollipopCounter.
static constexpr T m_maxValue
Maximum value of the counter.
T m_value
Value of the Lollipop Counter.
LollipopCounter()
Builds a Lollipop counter with a default initial value.
friend LollipopCounter operator++(LollipopCounter &val)
Prefix increment operator.
T GetValue() const
Get the counter value.
T m_sequenceWindow
Sequence window used for comparing two counters.
friend bool operator<(const LollipopCounter &lhs, const LollipopCounter &rhs)
Arithmetic operator less-than.
bool IsInit() const
Checks if a counter is in its starting region.
T AbsoluteMagnitudeOfDifference(LollipopCounter const &val) const
Compute the Absolute Magnitude Of Difference between two counters.
static constexpr T m_circularRegion
Circular region of the counter.
LollipopCounter(T val)
Builds a Lollipop counter with a specific initial value.
LollipopCounter & operator=(const LollipopCounter &o)
Assignment.
friend bool operator==(const LollipopCounter &lhs, const LollipopCounter &rhs)
Arithmetic operator equal-to.
void SetSequenceWindowSize(uint16_t numberOfBits)
Set the Sequence Window Size and resets the counter.
bool IsComparable(const LollipopCounter &val) const
Checks if the counter is comparable with another counter (i.e., not desynchronized).
friend bool operator>(const LollipopCounter &lhs, const LollipopCounter &rhs)
Arithmetic operator greater-than.
void Reset()
Resets the counter to its initial value.
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition: abort.h:144
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
LollipopCounter< uint8_t > LollipopCounter8
8 bit Lollipop Counter.
LollipopCounter< uint16_t > LollipopCounter16
16 bit Lollipop Counter.
Every class exported by the ns3 library is enclosed in the ns3 namespace.