A Discrete-Event Network Simulator
API
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 
25 namespace ns3
26 {
27 
28 NS_LOG_COMPONENT_DEFINE("NixVector");
29 
30 typedef std::vector<uint32_t> NixBits_t;
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 
54 NixVector&
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 */
79 std::ostream&
80 operator<<(std::ostream& os, const NixVector& nix)
81 {
82  nix.DumpNixVector(os);
83  os << " (" << nix.GetRemainingBits() << " bits left)";
84  return os;
85 }
86 
87 void
88 NixVector::AddNeighborIndex(uint32_t newBits, uint32_t numberOfBits)
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 
143 uint32_t
144 NixVector::ExtractNeighborIndex(uint32_t numberOfBits)
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 
198 uint32_t
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 
212 uint32_t
213 NixVector::Serialize(uint32_t* buffer, uint32_t maxSize) const
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 
238 uint32_t
239 NixVector::Deserialize(const uint32_t* buffer, uint32_t size)
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 
288 void
289 NixVector::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 
322 uint32_t
324 {
325  NS_LOG_FUNCTION(this);
326 
327  return (m_totalBitSize - m_used);
328 }
329 
330 uint32_t
331 NixVector::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 
353 void
354 NixVector::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 
380 void
381 NixVector::SetEpoch(uint32_t epoch)
382 {
383  m_epoch = epoch;
384 }
385 
386 uint32_t
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
#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::vector< uint32_t > NixBits_t
typedef for the nixVector
Definition: nix-vector.cc:28
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:159