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
62template <class T>
64{
65public:
73 {
74 NS_ABORT_MSG_UNLESS (std::is_unsigned<T>::value, "Lollipop counters must be defined on unsigned integer types");
75
76 uint16_t numberofDigits = std::numeric_limits<T>::digits;
77 m_sequenceWindow = 1 << (numberofDigits / 2);
78
80 }
81
91 {
92 uint16_t numberofDigits = std::numeric_limits<T>::digits;
93 m_sequenceWindow = 1 << (numberofDigits / 2);
94
95 m_value = val;
96 }
97
105 {
106 m_value = o.m_value;
107 return *this;
108 }
109
113 void Reset ()
114 {
116 }
117
127 void SetSequenceWindowSize (uint16_t numberOfBits)
128 {
129 uint16_t numberofDigits = std::numeric_limits<T>::digits;
130
131 NS_ABORT_MSG_IF (numberOfBits >= numberofDigits, "The size of the Sequence Window should be less than the counter size (which is " << +m_maxValue << ")");
132
133 m_sequenceWindow = 1 << numberOfBits;
134
136 }
137
152 bool IsComparable (const LollipopCounter &val) const
153 {
154 NS_ABORT_MSG_IF (m_sequenceWindow != val.m_sequenceWindow, "Can not compare two Lollipop Counters with different sequence windows");
155
158 {
159 // They are desynchronized - comparison is impossible.
160 T absDiff = AbsoluteMagnitudeOfDifference (val);
161 if (absDiff > m_sequenceWindow)
162 {
163 return false;
164 }
165 }
166 return true;
167 }
168
174 bool IsInit () const
175 {
177 {
178 return true;
179 }
180 return false;
181 }
182
189 friend bool operator == (const LollipopCounter & lhs, const LollipopCounter & rhs)
190 {
191
192 NS_ABORT_MSG_IF (lhs.m_sequenceWindow != rhs.m_sequenceWindow, "Can not compare two Lollipop Counters with different sequence windows");
193
194 if (lhs.m_value == rhs.m_value)
195 {
196 return true;
197 }
198 return false;
199 }
200
207 friend bool operator > (const LollipopCounter & lhs, const LollipopCounter & rhs)
208 {
209 NS_ABORT_MSG_IF (lhs.m_sequenceWindow != rhs.m_sequenceWindow, "Can not compare two Lollipop Counters with different sequence windows");
210
211 if (lhs.m_value == rhs.m_value)
212 {
213 return false;
214 }
215
216 if ((lhs.m_value <= m_circularRegion && rhs.m_value <= m_circularRegion)
218 {
219 // both counters are in the same region
220
221 T absDiff = lhs.AbsoluteMagnitudeOfDifference (rhs);
222 if (absDiff > lhs.m_sequenceWindow)
223 {
224 // They are desynchronized - comparison is impossible.
225 // return false because we can not return anything else.
226 return false;
227 }
228
229 // They are synchronized - comparison according to RFC1982.
230 T serialRegion = ((m_circularRegion >> 1) + 1);
231 return (((lhs.m_value < rhs.m_value) && ((rhs.m_value - lhs.m_value) > serialRegion))
232 || ((lhs.m_value > rhs.m_value) && ((lhs.m_value - rhs.m_value) < serialRegion)) );
233 }
234
235 // One counter is in the "high" region and the other is in the in the "lower" region
236 bool lhsIsHigher;
237 T difference;
238
240 {
241 lhsIsHigher = true;
242 // this is guaranteed to be positive and between [1...m_lollipopMaxValue].
243 difference = lhs.m_value - rhs.m_value;
244 }
245 else
246 {
247 lhsIsHigher = false;
248 // this is guaranteed to be positive and between [1...m_lollipopMaxValue].
249 difference = rhs.m_value - lhs.m_value;
250 }
251
252 T distance = (m_maxValue - difference) + 1; // this is guaranteed to be positive and between [1...m_lollipopMaxValue].
253 if (distance > lhs.m_sequenceWindow)
254 {
255 if (lhsIsHigher)
256 {
257 return true;
258 }
259 else
260 {
261 return false;
262 }
263 }
264 else
265 {
266 if (lhsIsHigher)
267 {
268 return false;
269 }
270 else
271 {
272 return true;
273 }
274 }
275
276 // this should never be reached.
277 return false;
278 }
279
286 friend bool operator < (const LollipopCounter & lhs, const LollipopCounter & rhs)
287 {
288 if (!lhs.IsComparable (rhs))
289 {
290 return false;
291 }
292
293 if (lhs > rhs)
294 {
295 return false;
296 }
297 else if (lhs == rhs)
298 {
299 return false;
300 }
301
302 return true;
303 }
304
311 {
312 val.m_value++;
313
314 if ( val.m_value == val.m_circularRegion + 1 )
315 {
316 val.m_value = 0;
317 }
318
319 return val;
320 }
321
328 friend LollipopCounter operator++ (LollipopCounter& val, int noop) // postfix ++
329 {
330 LollipopCounter ans = val;
331 ++(val); // or just call operator++()
332 return ans;
333 }
334
340 T GetValue () const
341 {
342 return m_value;
343 }
344
352 friend std::ostream &
353 operator<< (std::ostream & os, LollipopCounter const & counter)
354 {
355 os << +counter.m_value;
356 return os;
357 }
358
359private:
360
373 {
374 // useless because it is computed always on counters on their respective regions.
375 // Left (commented) for debugging purposes in case there is a code change.
376 // NS_ASSERT_MSG ((m_value <= m_circularRegion && val.m_value <= m_circularRegion) ||
377 // (m_value > m_circularRegion && val.m_value > m_circularRegion),
378 // "Absolute Magnitude Of Difference can be computed only on two values in the circular region " << +m_value << " - " << +val.m_value);
379
380 T absDiffDirect = std::max (m_value, val.m_value) - std::min (m_value, val.m_value);
381 T absDiffWrapped = (std::min (m_value, val.m_value) + m_circularRegion + 1) - std::max (m_value, val.m_value);
382 T absDiff = std::min (absDiffDirect, absDiffWrapped);
383 return absDiff;
384 }
385
388 static constexpr T m_maxValue = std::numeric_limits<T>::max ();
389 static constexpr T m_circularRegion = m_maxValue >> 1;
390};
391
402
403} /* namespace ns3 */
404
405#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.