A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
nix-vector.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 The Georgia Institute of Technology
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  * Authors: Josh Pelkey <jpelkey@gatech.edu>
19  */
20 
21 #include "ns3/log.h"
22 #include "ns3/fatal-error.h"
23 
24 #include "nix-vector.h"
25 
26 NS_LOG_COMPONENT_DEFINE ("NixVector");
27 
28 namespace ns3 {
29 
30 typedef std::vector<uint32_t> NixBits_t;
31 
32 NixVector::NixVector ()
33  : m_nixVector (0),
34  m_used (0),
35  m_currentVectorBitSize (0),
36  m_totalBitSize (0)
37 {
38  NS_LOG_FUNCTION (this);
39 
40  m_nixVector.push_back (0);
41 }
42 
43 NixVector::~NixVector ()
44 {
45  NS_LOG_FUNCTION (this);
46 }
47 
48 NixVector::NixVector (const NixVector &o)
49  : m_nixVector (o.m_nixVector),
50  m_used (o.m_used),
51  m_currentVectorBitSize (o.m_currentVectorBitSize),
52  m_totalBitSize (o.m_totalBitSize)
53 {
54 }
55 
56 NixVector &
58 {
59  if (this == &o)
60  {
61  return *this;
62  }
63  m_nixVector = o.m_nixVector;
64  m_used = o.m_used;
65  m_currentVectorBitSize = o.m_currentVectorBitSize;
66  m_totalBitSize = o.m_totalBitSize;
67  return *this;
68 }
69 
71 NixVector::Copy (void) const
72 {
73  NS_LOG_FUNCTION (this);
74  // we need to invoke the copy constructor directly
75  // rather than calling Create because the copy constructor
76  // is private.
77  return Ptr<NixVector> (new NixVector (*this), false);
78 }
79 
80 std::ostream & operator << (std::ostream &os, const NixVector &nix)
81 {
82  nix.DumpNixVector (os);
83  return os;
84 }
85 
86 void
87 NixVector::AddNeighborIndex (uint32_t newBits, uint32_t numberOfBits)
88 {
89  NS_LOG_FUNCTION (this << newBits << numberOfBits);
90 
91  if (numberOfBits > 32)
92  {
93  NS_FATAL_ERROR ("Can't add more than 32 bits to a nix-vector at one time");
94  }
95 
96  // Check to see if the number
97  // of new bits forces the creation of
98  // a new entry into the NixVector vector
99  // i.e., we will overflow int o.w.
100  if (m_currentVectorBitSize + numberOfBits > 32)
101  {
102  if (m_currentVectorBitSize == 32)
103  {
104  // can't add any more to this vector, so
105  // start a new one
106  m_nixVector.push_back (newBits);
107 
108  // also reset number of bits in
109  // m_currentVectorBitSize
110  // because we are working with a new
111  // entry in the vector
112  m_currentVectorBitSize = numberOfBits;
113  m_totalBitSize += numberOfBits;
114  }
115  else
116  {
117  // Put what we can in the remaining portion of the
118  // vector entry
119  uint32_t tempBits = newBits;
120  tempBits = newBits << m_currentVectorBitSize;
121  tempBits |= m_nixVector.back ();
122  m_nixVector.back () = tempBits;
123 
124  // Now start a new vector entry
125  // and push the remaining bits
126  // there
127  newBits = newBits >> (32 - m_currentVectorBitSize);
128  m_nixVector.push_back (newBits);
129 
130  // also reset number of bits in
131  // m_currentVectorBitSize
132  // because we are working with a new
133  // entry in the vector
134  m_currentVectorBitSize = (numberOfBits - (32 - m_currentVectorBitSize));
135  m_totalBitSize += numberOfBits;
136  }
137  }
138  else
139  {
140  // Shift over the newbits by the
141  // number of current bits. This allows
142  // us to logically OR with the present
143  // NixVector, resulting in the new
144  // NixVector
145  newBits = newBits << m_currentVectorBitSize;
146  newBits |= m_nixVector.back ();
147 
148  // Now insert the new NixVector and
149  // increment number of bits for
150  // m_currentVectorBitSize and m_totalBitSize
151  // accordingly
152  m_nixVector.back () = newBits;
153  m_currentVectorBitSize += numberOfBits;
154  m_totalBitSize += numberOfBits;
155  }
156 }
157 
158 uint32_t
159 NixVector::ExtractNeighborIndex (uint32_t numberOfBits)
160 {
161  NS_LOG_FUNCTION (this << numberOfBits);
162 
163  if (numberOfBits > 32)
164  {
165  NS_FATAL_ERROR ("Can't extract more than 32 bits to a nix-vector at one time");
166  }
167 
168  uint32_t vectorIndex = 0;
169  uint32_t extractedBits = 0;
170  uint32_t totalRemainingBits = GetRemainingBits ();
171 
172  if (numberOfBits > totalRemainingBits)
173  {
174  NS_FATAL_ERROR ("You've tried to extract too many bits of the Nix-vector, " << this << ". NumberBits: "
175  << numberOfBits << " Remaining: " << totalRemainingBits);
176  }
177 
178  if (numberOfBits <= 0)
179  {
180  NS_FATAL_ERROR ("You've specified a number of bits for Nix-vector <= 0!");
181  }
182 
183  // First determine where in the NixVector
184  // vector we need to extract which depends
185  // on the number of used bits and the total
186  // number of bits
187  vectorIndex = ((totalRemainingBits-1) / 32);
188 
189  // Next, determine if this extraction will
190  // span multiple vector entries
191  if (vectorIndex > 0) // we could span more than one
192  {
193  if ((numberOfBits-1) > ((totalRemainingBits-1) % 32)) // we do span more than one
194  {
195  extractedBits = m_nixVector.at (vectorIndex) << (32 - (totalRemainingBits % 32));
196  extractedBits = extractedBits >> ((32 - (totalRemainingBits % 32))
197  - (numberOfBits - (totalRemainingBits % 32)));
198  extractedBits |= (m_nixVector.at (vectorIndex-1)
199  >> (32 - (numberOfBits - (totalRemainingBits % 32))));
200  m_used += numberOfBits;
201  return extractedBits;
202  }
203  }
204 
205  // we don't span more than one
206  extractedBits = m_nixVector.at (vectorIndex) << (32 - (totalRemainingBits % 32));
207  extractedBits = extractedBits >> (32 - (numberOfBits));
208  m_used += numberOfBits;
209  return extractedBits;
210 }
211 
212 uint32_t
214 {
215  NS_LOG_FUNCTION (this);
216  uint32_t totalSizeInBytes = 0;
217  totalSizeInBytes = sizeof (m_used) + sizeof (m_currentVectorBitSize) +
218  sizeof (m_totalBitSize) + (4 * m_nixVector.size ());
219 
220  return totalSizeInBytes;
221 }
222 
223 uint32_t
224 NixVector::Serialize (uint32_t* buffer, uint32_t maxSize) const
225 {
226  NS_LOG_FUNCTION (this << buffer << maxSize);
227  uint32_t* p = buffer;
228  uint32_t size = 0;
229 
230  if (size + 4 <= maxSize)
231  {
232  size += 4;
233  // grab number of used bits
234  *p++ = m_used;
235  }
236  else
237  {
238  return 0;
239  }
240 
241  if (size + 4 <= maxSize)
242  {
243  size += 4;
244  // grab number of current used bits
245  // for the front vector
246  *p++ = m_currentVectorBitSize;
247  }
248  else
249  {
250  return 0;
251  }
252 
253  if (size + 4 <= maxSize)
254  {
255  size += 4;
256  // grab total bit size
257  *p++ = m_totalBitSize;
258  }
259  else
260  {
261  return 0;
262  }
263  for (uint32_t j = 0; j < m_nixVector.size (); j++)
264  {
265  if (size + 4 <= maxSize)
266  {
267  size += 4;
268  *p++ = m_nixVector.at (j);
269  }
270  else
271  {
272  return 0;
273  }
274  }
275 
276  // Serialized successfully
277  return 1;
278 }
279 
280 uint32_t
281 NixVector::Deserialize (const uint32_t* buffer, uint32_t size)
282 {
283  NS_LOG_FUNCTION (this << buffer << size);
284  const uint32_t* p = buffer;
285  uint32_t sizeCheck = size - 4;
286 
287  NS_ASSERT (sizeCheck >= 4);
288  m_used = *p++;
289  sizeCheck -= 4;
290 
291  NS_ASSERT (sizeCheck >= 4);
292  m_currentVectorBitSize = *p++;
293  sizeCheck -= 4;
294 
295  NS_ASSERT (sizeCheck >= 4);
296  m_totalBitSize = *p++;
297  sizeCheck -= 4;
298 
299  // make sure the nix-vector
300  // is empty
301  m_nixVector.clear ();
302  while (sizeCheck > 0)
303  {
304  NS_ASSERT (sizeCheck >= 4);
305  uint32_t nix = *p++;
306  m_nixVector.push_back (nix);
307  sizeCheck -= 4;
308  }
309 
310  NS_ASSERT (sizeCheck == 0);
311 
312  // return zero if an entire nix-vector was
313  // not deserialized
314  return (sizeCheck != 0) ? 0 : 1;
315 }
316 
317 void
318 NixVector::DumpNixVector (std::ostream &os) const
319 {
320  NS_LOG_FUNCTION (this << &os);
321  uint32_t i = m_nixVector.size ();
322  std::vector<uint32_t>::const_reverse_iterator rIter;
323  for (rIter = m_nixVector.rbegin (); rIter != m_nixVector.rend (); rIter++)
324  {
325  uint32_t numBits = BitCount (*rIter);
326 
327  // all this work just to get the nix
328  // vector to print out neat
329 
330  // if it's not the first entry in the vector,
331  // we may have to add some zeros and fill
332  // out the vector
333  if (m_totalBitSize > ((sizeof (uint32_t)*8) * i))
334  {
335  PrintDec2BinNixFill (*rIter,numBits,os);
336  }
337  else if (m_totalBitSize%32 == 0)
338  {
339  PrintDec2BinNix (*rIter,32,os);
340  }
341  else
342  {
343  PrintDec2BinNix (*rIter,m_totalBitSize%32,os);
344  }
345 
346  i--;
347 
348  if (i > 0)
349  {
350  os << "--";
351  }
352  }
353 }
354 
355 uint32_t
357 {
358  NS_LOG_FUNCTION (this);
359 
360  return (m_totalBitSize - m_used);
361 }
362 
363 uint32_t
364 NixVector::BitCount (uint32_t numberOfNeighbors) const
365 {
366  NS_LOG_FUNCTION (this << numberOfNeighbors);
367 
368  // Given the numberOfNeighbors, return the number
369  // of bits needed (essentially, log2(numberOfNeighbors-1)
370  uint32_t bitCount = 0;
371 
372  if (numberOfNeighbors < 2)
373  {
374  return 1;
375  }
376  else
377  {
378  for (numberOfNeighbors -= 1; numberOfNeighbors != 0; numberOfNeighbors >>= 1)
379  {
380  bitCount++;
381  }
382  return bitCount;
383  }
384 }
385 
386 void
387 NixVector::PrintDec2BinNix (uint32_t decimalNum, uint32_t bitCount, std::ostream &os) const
388 {
389  NS_LOG_FUNCTION (this << decimalNum << bitCount << &os);
390  if(decimalNum == 0)
391  {
392  for (; bitCount > 0; bitCount--)
393  {
394  os << 0;
395  }
396  return;
397  }
398  if(decimalNum == 1)
399  {
400  for (; bitCount > 1; bitCount--)
401  {
402  os << 0;
403  }
404  os << 1;
405  }
406  else
407  {
408  PrintDec2BinNix (decimalNum / 2,bitCount-1, os);
409  os << decimalNum % 2;
410  }
411 }
412 
413 void
414 NixVector::PrintDec2BinNixFill (uint32_t decimalNum, uint32_t bitCount, std::ostream &os) const
415 {
416  NS_LOG_FUNCTION (this << decimalNum << bitCount << &os);
417  if(decimalNum == 0)
418  {
419  os << 0;
420  return;
421  }
422  if(decimalNum == 1)
423  {
424  // check to see if we need to
425  // print out some zeros at the
426  // beginning of the nix vector
427  if ((uint32_t)(sizeof (uint32_t)*8) > bitCount)
428  {
429  for (uint32_t i = ((sizeof (uint32_t)*8)-bitCount); i > 0; i--)
430  {
431  os << 0;
432  }
433  }
434  os << 1;
435  }
436  else
437  {
438  PrintDec2BinNixFill (decimalNum / 2, bitCount, os);
439  os << decimalNum % 2;
440  }
441 }
442 
443 } // namespace ns3
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
Neighbor-index data structure for nix-vector routing.
Definition: nix-vector.h:63
Ptr< NixVector > Copy(void) const
Definition: nix-vector.cc:71
NixVector & operator=(const NixVector &o)
Definition: nix-vector.cc:57
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
uint32_t GetRemainingBits(void)
Definition: nix-vector.cc:356
uint32_t ExtractNeighborIndex(uint32_t numberOfBits)
Definition: nix-vector.cc:159
uint32_t Serialize(uint32_t *buffer, uint32_t maxSize) const
Definition: nix-vector.cc:224
uint32_t GetSerializedSize(void) const
Definition: nix-vector.cc:213
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:43
uint32_t Deserialize(const uint32_t *buffer, uint32_t size)
Definition: nix-vector.cc:281
void AddNeighborIndex(uint32_t newBits, uint32_t numberOfBits)
Definition: nix-vector.cc:87
uint32_t BitCount(uint32_t numberOfNeighbors) const
Definition: nix-vector.cc:364