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
26namespace ns3 {
27
28NS_LOG_COMPONENT_DEFINE ("NixVector");
29
30typedef 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
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
69NixVector::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 */
79std::ostream & operator << (std::ostream &os, const NixVector &nix)
80{
81 nix.DumpNixVector (os);
82 os << " (" << nix.GetRemainingBits () << " bits left)";
83 return os;
84}
85
86void
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
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
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
211NixVector::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
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
286void
287NixVector::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
322{
323 NS_LOG_FUNCTION (this);
324
325 return (m_totalBitSize - m_used);
326}
327
329NixVector::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
351void
352NixVector::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
378void
380{
381 m_epoch = epoch;
382}
383
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::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:139
std::vector< uint32_t > NixBits_t
typedef for the nixVector
Definition: nix-vector.cc:28