A Discrete-Event Network Simulator
API
nix-vector.cc
Go to the documentation of this file.
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 namespace ns3 {
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 
69 NixVector::Copy (void) const
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 & operator << (std::ostream &os, const NixVector &nix)
80 {
81  nix.DumpNixVector (os);
82  os << " (" << nix.GetRemainingBits () << " bits left)";
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  // This can be in the range [0,31]
97  uint32_t currentVectorBitSize = m_totalBitSize % 32;
98 
99  if (currentVectorBitSize == 0)
100  {
101  m_nixVector.push_back (0);
102  }
103 
104  // Check to see if the number
105  // of new bits forces the creation of
106  // a new entry into the NixVector vector
107  // i.e., we will overflow int o.w.
108  if (currentVectorBitSize + numberOfBits > 32)
109  {
110  // Put what we can in the remaining portion of the
111  // vector entry
112  uint32_t tempBits = newBits;
113  tempBits = newBits << currentVectorBitSize;
114  tempBits |= m_nixVector.back ();
115  m_nixVector.back () = tempBits;
116 
117  // Now start a new vector entry
118  // and push the remaining bits
119  // there
120  newBits = newBits >> (32 - currentVectorBitSize);
121  m_nixVector.push_back (newBits);
122  }
123  else
124  {
125  // Shift over the newbits by the
126  // number of current bits. This allows
127  // us to logically OR with the present
128  // NixVector, resulting in the new
129  // NixVector
130  newBits = newBits << currentVectorBitSize;
131  newBits |= m_nixVector.back ();
132 
133  // Now insert the new NixVector and
134  // increment number of bits for
135  // currentVectorBitSize and m_totalBitSize
136  // accordingly
137  m_nixVector.back () = newBits;
138  }
139  m_totalBitSize += numberOfBits;
140 }
141 
142 uint32_t
143 NixVector::ExtractNeighborIndex (uint32_t numberOfBits)
144 {
145  NS_LOG_FUNCTION (this << numberOfBits);
146 
147  if (numberOfBits > 32)
148  {
149  NS_FATAL_ERROR ("Can't extract more than 32 bits to a nix-vector at one time");
150  }
151 
152  uint32_t vectorIndex = 0;
153  uint32_t extractedBits = 0;
154  uint32_t totalRemainingBits = GetRemainingBits ();
155 
156  if (numberOfBits > totalRemainingBits)
157  {
158  NS_FATAL_ERROR ("You've tried to extract too many bits of the Nix-vector, " << this << ". NumberBits: "
159  << numberOfBits << " Remaining: " << totalRemainingBits);
160  }
161 
162  if (numberOfBits <= 0)
163  {
164  NS_FATAL_ERROR ("You've specified a number of bits for Nix-vector <= 0!");
165  }
166 
167  // First determine where in the NixVector
168  // vector we need to extract which depends
169  // on the number of used bits and the total
170  // number of bits
171  vectorIndex = ((totalRemainingBits-1) / 32);
172 
173  // Next, determine if this extraction will
174  // span multiple vector entries
175  if (vectorIndex > 0) // we could span more than one
176  {
177  if ((numberOfBits-1) > ((totalRemainingBits-1) % 32)) // we do span more than one
178  {
179  extractedBits = m_nixVector.at (vectorIndex) << (32 - (totalRemainingBits % 32));
180  extractedBits = extractedBits >> ((32 - (totalRemainingBits % 32))
181  - (numberOfBits - (totalRemainingBits % 32)));
182  extractedBits |= (m_nixVector.at (vectorIndex-1)
183  >> (32 - (numberOfBits - (totalRemainingBits % 32))));
184  m_used += numberOfBits;
185  return extractedBits;
186  }
187  }
188 
189  // we don't span more than one
190  extractedBits = m_nixVector.at (vectorIndex) << (32 - (totalRemainingBits % 32));
191  extractedBits = extractedBits >> (32 - (numberOfBits));
192  m_used += numberOfBits;
193  return extractedBits;
194 }
195 
196 uint32_t
198 {
199  NS_LOG_FUNCTION (this);
200 
201  if (m_totalBitSize == 0)
202  {
203  return sizeof (m_totalBitSize);
204  }
205 
206  return sizeof (m_used) + sizeof (m_totalBitSize) + (sizeof (uint32_t) * m_nixVector.size ()) +
207  sizeof (m_epoch);
208 }
209 
210 uint32_t
211 NixVector::Serialize (uint32_t* buffer, uint32_t maxSize) const
212 {
213  NS_LOG_FUNCTION (this << buffer << maxSize);
214  uint32_t* p = buffer;
215 
216  if (maxSize < GetSerializedSize ())
217  {
218  return 0;
219  }
220 
221  *p++ = m_totalBitSize;
222 
223  if (m_totalBitSize)
224  {
225  *p++ = m_used;
226  for (uint32_t j = 0; j < m_nixVector.size (); j++)
227  {
228  *p++ = m_nixVector.at (j);
229  }
230  *p++ = m_epoch;
231  }
232 
233  return 1;
234 }
235 
236 uint32_t
237 NixVector::Deserialize (const uint32_t* buffer, uint32_t size)
238 {
239  NS_LOG_FUNCTION (this << buffer << size);
240  const uint32_t* p = buffer;
241 
242  NS_ASSERT_MSG (size >= sizeof (m_totalBitSize),
243  "NixVector minimum serialized length is " << sizeof (m_totalBitSize) << " bytes");
244  if (size < sizeof (m_totalBitSize))
245  {
246  // return zero if an entire nix-vector was
247  // not deserialized
248  return 0;
249  }
250 
251  m_totalBitSize = *p++;
252 
253  if (m_totalBitSize)
254  {
255  m_used = *p++;
256 
257  // NixVector is packed in 32-bit unsigned ints.
258  uint32_t nixVectorLenth = m_totalBitSize / 32;
259  nixVectorLenth += (m_totalBitSize % 32) ? 1 : 0;
260 
261  NS_ASSERT_MSG (size >= 16 + nixVectorLenth, "NixVector serialized length should have been "
262  << 16 + nixVectorLenth
263  << " but buffer is shorter");
264  if (size < 16 + nixVectorLenth * 4)
265  {
266  // return zero if an entire nix-vector was
267  // not deserialized
268  return 0;
269  }
270 
271  // make sure the nix-vector
272  // is empty
273  m_nixVector.clear ();
274  for (uint32_t j = 0; j < nixVectorLenth; j++)
275  {
276  uint32_t nix = *p++;
277  m_nixVector.push_back (nix);
278  }
279 
280  m_epoch = *p++;
281  }
282 
283  return (GetSerializedSize ());
284 }
285 
286 void
287 NixVector::DumpNixVector (std::ostream &os) const
288 {
289  NS_LOG_FUNCTION (this << &os);
290 
291  if (m_nixVector.empty ())
292  {
293  os << "0";
294  return;
295  }
296 
297  std::vector<uint32_t>::const_reverse_iterator rIter;
298  bool first = true;
299 
300  for (rIter = m_nixVector.rbegin (); rIter != m_nixVector.rend (); )
301  {
302  if (m_totalBitSize % 32 != 0 && first)
303  {
304  PrintDec2BinNix (*rIter, m_totalBitSize % 32, os);
305  }
306  else
307  {
308  PrintDec2BinNix (*rIter, 32, os);
309  }
310  first = false;
311 
312  rIter++;
313  if (rIter != m_nixVector.rend ())
314  {
315  os << "--";
316  }
317  }
318 }
319 
320 uint32_t
322 {
323  NS_LOG_FUNCTION (this);
324 
325  return (m_totalBitSize - m_used);
326 }
327 
328 uint32_t
329 NixVector::BitCount (uint32_t numberOfNeighbors) const
330 {
331  NS_LOG_FUNCTION (this << numberOfNeighbors);
332 
333  // Given the numberOfNeighbors, return the number
334  // of bits needed (essentially, log2(numberOfNeighbors-1)
335  uint32_t bitCount = 0;
336 
337  if (numberOfNeighbors < 2)
338  {
339  return 1;
340  }
341  else
342  {
343  for (numberOfNeighbors -= 1; numberOfNeighbors != 0; numberOfNeighbors >>= 1)
344  {
345  bitCount++;
346  }
347  return bitCount;
348  }
349 }
350 
351 void
352 NixVector::PrintDec2BinNix (uint32_t decimalNum, uint32_t bitCount, std::ostream &os) const
353 {
354  NS_LOG_FUNCTION (this << decimalNum << bitCount << &os);
355  if(decimalNum == 0)
356  {
357  for (; bitCount > 0; bitCount--)
358  {
359  os << 0;
360  }
361  return;
362  }
363  if(decimalNum == 1)
364  {
365  for (; bitCount > 1; bitCount--)
366  {
367  os << 0;
368  }
369  os << 1;
370  }
371  else
372  {
373  PrintDec2BinNix (decimalNum / 2,bitCount-1, os);
374  os << decimalNum % 2;
375  }
376 }
377 
378 void
379 NixVector::SetEpoch (uint32_t epoch)
380 {
381  m_epoch = epoch;
382 }
383 
384 uint32_t
386 {
387  return m_epoch;
388 }
389 
390 } // namespace ns3
Neighbor-index data structure for nix-vector routing.
Definition: nix-vector.h:64
void AddNeighborIndex(uint32_t newBits, uint32_t numberOfBits)
Definition: nix-vector.cc:87
Ptr< NixVector > Copy(void) const
Definition: nix-vector.cc:69
uint32_t m_used
For tracking where we are in the nix-vector.
Definition: nix-vector.h:188
uint32_t m_epoch
Epoch of the Nix-vector creation.
Definition: nix-vector.h:196
uint32_t GetRemainingBits(void) const
Definition: nix-vector.cc:321
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:194
uint32_t GetSerializedSize(void) const
Definition: nix-vector.cc:197
uint32_t Serialize(uint32_t *buffer, uint32_t maxSize) const
Definition: nix-vector.cc:211
uint32_t ExtractNeighborIndex(uint32_t numberOfBits)
Definition: nix-vector.cc:143
NixBits_t m_nixVector
the actual nix-vector
Definition: nix-vector.h:187
void SetEpoch(uint32_t epoch)
Set the NixVector Epoch.
Definition: nix-vector.cc:379
void DumpNixVector(std::ostream &os) const
Print the NixVector.
Definition: nix-vector.cc:287
uint32_t Deserialize(const uint32_t *buffer, uint32_t size)
Definition: nix-vector.cc:237
uint32_t BitCount(uint32_t numberOfNeighbors) const
Definition: nix-vector.cc:329
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:352
uint32_t GetEpoch() const
Get the NixVector Epoch.
Definition: nix-vector.cc:385
#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:88
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#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:139