A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
nix-vector.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009 The Georgia Institute of Technology
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Authors: Josh Pelkey <jpelkey@gatech.edu>
18 */
19
20#include "nix-vector.h"
21
22#include "ns3/fatal-error.h"
23#include "ns3/log.h"
24
25namespace ns3
26{
27
28NS_LOG_COMPONENT_DEFINE("NixVector");
29
30typedef std::vector<uint32_t> NixBits_t; //!< typedef for the nixVector
31
33 : m_nixVector(0),
34 m_used(0),
35 m_totalBitSize(0),
36 m_epoch(0)
37{
38 NS_LOG_FUNCTION(this);
39}
40
42{
43 NS_LOG_FUNCTION(this);
44}
45
47 : m_nixVector(o.m_nixVector),
48 m_used(o.m_used),
49 m_totalBitSize(o.m_totalBitSize),
50 m_epoch(o.m_epoch)
51{
52}
53
56{
57 if (this == &o)
58 {
59 return *this;
60 }
62 m_used = o.m_used;
64 m_epoch = o.m_epoch;
65 return *this;
66}
67
70{
71 NS_LOG_FUNCTION(this);
72 // we need to invoke the copy constructor directly
73 // rather than calling Create because the copy constructor
74 // is private.
75 return Ptr<NixVector>(new NixVector(*this), false);
76}
77
78/* For printing the nix vector */
79std::ostream&
80operator<<(std::ostream& os, const NixVector& nix)
81{
82 nix.DumpNixVector(os);
83 os << " (" << nix.GetRemainingBits() << " bits left)";
84 return os;
85}
86
87void
89{
90 NS_LOG_FUNCTION(this << newBits << numberOfBits);
91
92 if (numberOfBits > 32)
93 {
94 NS_FATAL_ERROR("Can't add more than 32 bits to a nix-vector at one time");
95 }
96
97 // This can be in the range [0,31]
98 uint32_t currentVectorBitSize = m_totalBitSize % 32;
99
100 if (currentVectorBitSize == 0)
101 {
102 m_nixVector.push_back(0);
103 }
104
105 // Check to see if the number
106 // of new bits forces the creation of
107 // a new entry into the NixVector vector
108 // i.e., we will overflow int o.w.
109 if (currentVectorBitSize + numberOfBits > 32)
110 {
111 // Put what we can in the remaining portion of the
112 // vector entry
113 uint32_t tempBits = newBits;
114 tempBits = newBits << currentVectorBitSize;
115 tempBits |= m_nixVector.back();
116 m_nixVector.back() = tempBits;
117
118 // Now start a new vector entry
119 // and push the remaining bits
120 // there
121 newBits = newBits >> (32 - currentVectorBitSize);
122 m_nixVector.push_back(newBits);
123 }
124 else
125 {
126 // Shift over the newbits by the
127 // number of current bits. This allows
128 // us to logically OR with the present
129 // NixVector, resulting in the new
130 // NixVector
131 newBits = newBits << currentVectorBitSize;
132 newBits |= m_nixVector.back();
133
134 // Now insert the new NixVector and
135 // increment number of bits for
136 // currentVectorBitSize and m_totalBitSize
137 // accordingly
138 m_nixVector.back() = newBits;
139 }
140 m_totalBitSize += numberOfBits;
141}
142
145{
146 NS_LOG_FUNCTION(this << numberOfBits);
147
148 if (numberOfBits > 32)
149 {
150 NS_FATAL_ERROR("Can't extract more than 32 bits to a nix-vector at one time");
151 }
152
153 uint32_t vectorIndex = 0;
154 uint32_t extractedBits = 0;
155 uint32_t totalRemainingBits = GetRemainingBits();
156
157 if (numberOfBits > totalRemainingBits)
158 {
159 NS_FATAL_ERROR("You've tried to extract too many bits of the Nix-vector, "
160 << this << ". NumberBits: " << numberOfBits
161 << " Remaining: " << totalRemainingBits);
162 }
163
164 if (numberOfBits <= 0)
165 {
166 NS_FATAL_ERROR("You've specified a number of bits for Nix-vector <= 0!");
167 }
168
169 // First determine where in the NixVector
170 // vector we need to extract which depends
171 // on the number of used bits and the total
172 // number of bits
173 vectorIndex = ((totalRemainingBits - 1) / 32);
174
175 // Next, determine if this extraction will
176 // span multiple vector entries
177 if (vectorIndex > 0) // we could span more than one
178 {
179 if ((numberOfBits - 1) > ((totalRemainingBits - 1) % 32)) // we do span more than one
180 {
181 extractedBits = m_nixVector.at(vectorIndex) << (32 - (totalRemainingBits % 32));
182 extractedBits = extractedBits >> ((32 - (totalRemainingBits % 32)) -
183 (numberOfBits - (totalRemainingBits % 32)));
184 extractedBits |= (m_nixVector.at(vectorIndex - 1) >>
185 (32 - (numberOfBits - (totalRemainingBits % 32))));
186 m_used += numberOfBits;
187 return extractedBits;
188 }
189 }
190
191 // we don't span more than one
192 extractedBits = m_nixVector.at(vectorIndex) << (32 - (totalRemainingBits % 32));
193 extractedBits = extractedBits >> (32 - (numberOfBits));
194 m_used += numberOfBits;
195 return extractedBits;
196}
197
200{
201 NS_LOG_FUNCTION(this);
202
203 if (m_totalBitSize == 0)
204 {
205 return sizeof(m_totalBitSize);
206 }
207
208 return sizeof(m_used) + sizeof(m_totalBitSize) + (sizeof(uint32_t) * m_nixVector.size()) +
209 sizeof(m_epoch);
210}
211
214{
215 NS_LOG_FUNCTION(this << buffer << maxSize);
216 uint32_t* p = buffer;
217
218 if (maxSize < GetSerializedSize())
219 {
220 return 0;
221 }
222
223 *p++ = m_totalBitSize;
224
225 if (m_totalBitSize)
226 {
227 *p++ = m_used;
228 for (uint32_t j = 0; j < m_nixVector.size(); j++)
229 {
230 *p++ = m_nixVector.at(j);
231 }
232 *p++ = m_epoch;
233 }
234
235 return 1;
236}
237
240{
241 NS_LOG_FUNCTION(this << buffer << size);
242 const uint32_t* p = buffer;
243
244 NS_ASSERT_MSG(size >= sizeof(m_totalBitSize),
245 "NixVector minimum serialized length is " << sizeof(m_totalBitSize) << " bytes");
246 if (size < sizeof(m_totalBitSize))
247 {
248 // return zero if an entire nix-vector was
249 // not deserialized
250 return 0;
251 }
252
253 m_totalBitSize = *p++;
254
255 if (m_totalBitSize)
256 {
257 m_used = *p++;
258
259 // NixVector is packed in 32-bit unsigned ints.
260 uint32_t nixVectorLength = m_totalBitSize / 32;
261 nixVectorLength += (m_totalBitSize % 32) ? 1 : 0;
262
263 NS_ASSERT_MSG(size >= 16 + nixVectorLength,
264 "NixVector serialized length should have been " << 16 + nixVectorLength
265 << " but buffer is shorter");
266 if (size < 16 + nixVectorLength * 4)
267 {
268 // return zero if an entire nix-vector was
269 // not deserialized
270 return 0;
271 }
272
273 // make sure the nix-vector
274 // is empty
275 m_nixVector.clear();
276 for (uint32_t j = 0; j < nixVectorLength; j++)
277 {
278 uint32_t nix = *p++;
279 m_nixVector.push_back(nix);
280 }
281
282 m_epoch = *p++;
283 }
284
285 return GetSerializedSize();
286}
287
288void
289NixVector::DumpNixVector(std::ostream& os) const
290{
291 NS_LOG_FUNCTION(this << &os);
292
293 if (m_nixVector.empty())
294 {
295 os << "0";
296 return;
297 }
298
299 std::vector<uint32_t>::const_reverse_iterator rIter;
300 bool first = true;
301
302 for (rIter = m_nixVector.rbegin(); rIter != m_nixVector.rend();)
303 {
304 if (m_totalBitSize % 32 != 0 && first)
305 {
306 PrintDec2BinNix(*rIter, m_totalBitSize % 32, os);
307 }
308 else
309 {
310 PrintDec2BinNix(*rIter, 32, os);
311 }
312 first = false;
313
314 rIter++;
315 if (rIter != m_nixVector.rend())
316 {
317 os << "--";
318 }
319 }
320}
321
324{
325 NS_LOG_FUNCTION(this);
326
327 return (m_totalBitSize - m_used);
328}
329
331NixVector::BitCount(uint32_t numberOfNeighbors) const
332{
333 NS_LOG_FUNCTION(this << numberOfNeighbors);
334
335 // Given the numberOfNeighbors, return the number
336 // of bits needed (essentially, log2(numberOfNeighbors-1)
337 uint32_t bitCount = 0;
338
339 if (numberOfNeighbors < 2)
340 {
341 return 1;
342 }
343 else
344 {
345 for (numberOfNeighbors -= 1; numberOfNeighbors != 0; numberOfNeighbors >>= 1)
346 {
347 bitCount++;
348 }
349 return bitCount;
350 }
351}
352
353void
354NixVector::PrintDec2BinNix(uint32_t decimalNum, uint32_t bitCount, std::ostream& os) const
355{
356 NS_LOG_FUNCTION(this << decimalNum << bitCount << &os);
357 if (decimalNum == 0)
358 {
359 for (; bitCount > 0; bitCount--)
360 {
361 os << 0;
362 }
363 return;
364 }
365 if (decimalNum == 1)
366 {
367 for (; bitCount > 1; bitCount--)
368 {
369 os << 0;
370 }
371 os << 1;
372 }
373 else
374 {
375 PrintDec2BinNix(decimalNum / 2, bitCount - 1, os);
376 os << decimalNum % 2;
377 }
378}
379
380void
382{
383 m_epoch = epoch;
384}
385
388{
389 return m_epoch;
390}
391
392} // namespace ns3
Neighbor-index data structure for nix-vector routing.
Definition: nix-vector.h:65
void AddNeighborIndex(uint32_t newBits, uint32_t numberOfBits)
Definition: nix-vector.cc:88
uint32_t m_used
For tracking where we are in the nix-vector.
Definition: nix-vector.h:189
uint32_t GetSerializedSize() const
Definition: nix-vector.cc:199
uint32_t m_epoch
Epoch of the Nix-vector creation.
Definition: nix-vector.h:197
uint32_t GetRemainingBits() const
Definition: nix-vector.cc:323
NixVector & operator=(const NixVector &o)
Definition: nix-vector.cc:55
uint32_t m_totalBitSize
A counter of how total bits are in the nix-vector.
Definition: nix-vector.h:195
uint32_t Serialize(uint32_t *buffer, uint32_t maxSize) const
Definition: nix-vector.cc:213
uint32_t ExtractNeighborIndex(uint32_t numberOfBits)
Definition: nix-vector.cc:144
NixBits_t m_nixVector
the actual nix-vector
Definition: nix-vector.h:188
void SetEpoch(uint32_t epoch)
Set the NixVector Epoch.
Definition: nix-vector.cc:381
void DumpNixVector(std::ostream &os) const
Print the NixVector.
Definition: nix-vector.cc:289
uint32_t Deserialize(const uint32_t *buffer, uint32_t size)
Definition: nix-vector.cc:239
Ptr< NixVector > Copy() const
Definition: nix-vector.cc:69
uint32_t BitCount(uint32_t numberOfNeighbors) const
Definition: nix-vector.cc:331
void PrintDec2BinNix(uint32_t decimalNum, uint32_t bitCount, std::ostream &os) const
Internal for pretty printing of nix-vector (no fill)
Definition: nix-vector.cc:354
uint32_t GetEpoch() const
Get the NixVector Epoch.
Definition: nix-vector.cc:387
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Definition: first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:159
std::vector< uint32_t > NixBits_t
typedef for the nixVector
Definition: nix-vector.cc:30