A Discrete-Event Network Simulator
API
ipv4-address-generator.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2008 University of Washington
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 
19 #include <list>
20 #include "ns3/abort.h"
21 #include "ns3/assert.h"
22 #include "ns3/log.h"
23 #include "ns3/simulation-singleton.h"
24 #include "ipv4-address-generator.h"
25 
26 namespace ns3 {
27 
28 NS_LOG_COMPONENT_DEFINE ("Ipv4AddressGenerator");
29 
39 {
40 public:
42  virtual ~Ipv4AddressGeneratorImpl ();
43 
54  void Init (const Ipv4Address net, const Ipv4Mask mask,
55  const Ipv4Address addr);
56 
66  Ipv4Address GetNetwork (const Ipv4Mask mask) const;
67 
80  Ipv4Address NextNetwork (const Ipv4Mask mask);
81 
88  void InitAddress (const Ipv4Address addr, const Ipv4Mask mask);
89 
99  Ipv4Address NextAddress (const Ipv4Mask mask);
100 
110  Ipv4Address GetAddress (const Ipv4Mask mask) const;
111 
115  void Reset (void);
116 
127  bool AddAllocated (const Ipv4Address addr);
128 
135  bool IsAddressAllocated (const Ipv4Address addr);
136 
144  bool IsNetworkAllocated (const Ipv4Address addr, const Ipv4Mask mask);
145 
149  void TestMode (void);
150 private:
151  static const uint32_t N_BITS = 32;
152  static const uint32_t MOST_SIGNIFICANT_BIT = 0x80000000;
153 
159  uint32_t MaskToIndex (Ipv4Mask mask) const;
160 
165  {
166 public:
167  uint32_t mask;
168  uint32_t shift;
169  uint32_t network;
170  uint32_t addr;
171  uint32_t addrMax;
172  };
173 
175 
179  class Entry
180  {
181 public:
182  uint32_t addrLow;
183  uint32_t addrHigh;
184  };
185 
186  std::list<Entry> m_entries;
187  bool m_test;
188 };
189 
191  : m_entries (), m_test (false)
192 {
193  NS_LOG_FUNCTION (this);
194  Reset ();
195 }
196 
197 void
199 {
200  NS_LOG_FUNCTION (this);
201 
202  uint32_t mask = 0;
203 //
204 // There are 32 possible masks in a 32-bit integer. Two of these are illegal
205 // for a network mask (0x00000000 and 0xffffffff). Valid network masks
206 // correspond to some nonzero number of high order bits set to one followed by
207 // some nonzero number of lower order bits set to zero.
208 //
209 // We look at a network number as an n-bit number where n is defined as the
210 // number of bits in each mask. Allocating a new network number is simply
211 // incrementing this number.
212 //
213 // In order to combine an allocated network number with an IP address, we have
214 // to shift the network into the correct alignment with respect to its mask.
215 // For example, a network mask of 0xff000000 admits the possibility of 256
216 // different network numbers since there are eight bits available. To create
217 // IP addresses, we need to shift the network number counter left by 24 bits
218 // to put it in correct alignment. This leaves 24 bits left for addresses.
219 // We make sure we don't overflow by saving a maximum address number which is
220 // just the inverse of the mask (~mask).
221 //
222  for (uint32_t i = 0; i < N_BITS; ++i)
223  {
224  m_netTable[i].mask = mask;
225  mask >>= 1;
226  mask |= MOST_SIGNIFICANT_BIT;
227  m_netTable[i].network = 1;
228  m_netTable[i].addr = 1;
230  m_netTable[i].shift = N_BITS - i;
231  }
232  m_entries.clear ();
233  m_test = false;
234 }
235 
237 {
238  NS_LOG_FUNCTION (this);
239 }
240 
241 void
243  const Ipv4Address net,
244  const Ipv4Mask mask,
245  const Ipv4Address addr)
246 {
247  NS_LOG_FUNCTION (this << net << mask << addr);
248 //
249 // We're going to be playing with the actual bits in the network and mask so
250 // pull them out into ints.
251 //
252  uint32_t maskBits = mask.Get ();
253  uint32_t netBits = net.Get ();
254  uint32_t addrBits = addr.Get ();
255 //
256 // Some quick reasonableness testing.
257 //
258  NS_ABORT_MSG_UNLESS ((netBits & ~maskBits) == 0, "Ipv4AddressGeneratorImpl::Init (): Inconsistent network and mask");
259  NS_ABORT_MSG_UNLESS ((addrBits & maskBits) == 0, "Ipv4AddressGeneratorImpl::Init (): Inconsistent address and mask");
260 
261 //
262 // Convert the network mask into an index into the network number table.
263 // The network number comes in to us properly aligned for the mask and so
264 // needs to be shifted right into the normalized position (lowest bit of the
265 // network number at bit zero of the int that holds it).
266 //
267  uint32_t index = MaskToIndex (mask);
268 
269  m_netTable[index].network = netBits >> m_netTable[index].shift;
270 
271  NS_ABORT_MSG_UNLESS (addrBits <= m_netTable[index].addrMax, "Ipv4AddressGeneratorImpl::Init(): Address overflow");
272  m_netTable[index].addr = addrBits;
273  return;
274 }
275 
278  const Ipv4Mask mask) const
279 {
280  NS_LOG_FUNCTION (this << mask);
281 
282  uint32_t index = MaskToIndex (mask);
283  return Ipv4Address (m_netTable[index].network << m_netTable[index].shift);
284 }
285 
288  const Ipv4Mask mask)
289 {
290  NS_LOG_FUNCTION (this << mask);
291 //
292 // The way this is expected to be used is that an address and network prefix
293 // are initialized, and then NextAddress() is called repeatedly to set the
294 // addresses on a given subnet. The client will expect that the first
295 // addresses will use the network prefix she used to initialize the generator
296 // with. After a subnet is assigned, the client will call NextNetwork to
297 // get the network number of the next subnet. This implies that that this
298 // operation is a pre-increment.
299 //
300  uint32_t index = MaskToIndex (mask);
301  ++m_netTable[index].network;
302  return Ipv4Address (m_netTable[index].network << m_netTable[index].shift);
303 }
304 
305 void
307  const Ipv4Address addr,
308  const Ipv4Mask mask)
309 {
310  NS_LOG_FUNCTION (this << addr << mask);
311 
312  uint32_t index = MaskToIndex (mask);
313  uint32_t addrBits = addr.Get ();
314 
315  NS_ABORT_MSG_UNLESS (addrBits <= m_netTable[index].addrMax, "Ipv4AddressGeneratorImpl::InitAddress(): Address overflow");
316  m_netTable[index].addr = addrBits;
317 }
318 
321  const Ipv4Mask mask) const
322 {
323  NS_LOG_FUNCTION (this << mask);
324 
325  uint32_t index = MaskToIndex (mask);
326 
327  return Ipv4Address (
328  (m_netTable[index].network << m_netTable[index].shift) |
329  m_netTable[index].addr);
330 }
331 
334 {
335  NS_LOG_FUNCTION (this << mask);
336 //
337 // The way this is expected to be used is that an address and network prefix
338 // are initialized, and then NextAddress() is called repeatedly to set the
339 // addresses on a given subnet. The client will expect that the first address
340 // she gets back is the one she used to initialize the generator with. This
341 // implies that this operation is a post-increment.
342 //
343  uint32_t index = MaskToIndex (mask);
344 
345  NS_ABORT_MSG_UNLESS (m_netTable[index].addr <= m_netTable[index].addrMax,
346  "Ipv4AddressGeneratorImpl::NextAddress(): Address overflow");
347 
348  Ipv4Address addr = Ipv4Address (
349  (m_netTable[index].network << m_netTable[index].shift) |
350  m_netTable[index].addr);
351 
352  ++m_netTable[index].addr;
353 //
354 // Make a note that we've allocated this address -- used for address collision
355 // detection.
356 //
357  AddAllocated (addr);
358  return addr;
359 }
360 
361 bool
363 {
364  NS_LOG_FUNCTION (this << address);
365 
366  uint32_t addr = address.Get ();
367 
368  NS_ABORT_MSG_UNLESS (addr, "Ipv4AddressGeneratorImpl::Add(): Allocating the broadcast address is not a good idea");
369 
370  std::list<Entry>::iterator i;
371 
372  for (i = m_entries.begin (); i != m_entries.end (); ++i)
373  {
374  NS_LOG_LOGIC ("examine entry: " << Ipv4Address ((*i).addrLow) <<
375  " to " << Ipv4Address ((*i).addrHigh));
376 //
377 // First things first. Is there an address collision -- that is, does the
378 // new address fall in a previously allocated block of addresses.
379 //
380  if (addr >= (*i).addrLow && addr <= (*i).addrHigh)
381  {
382  NS_LOG_LOGIC ("Ipv4AddressGeneratorImpl::Add(): Address Collision: " << Ipv4Address (addr));
383  if (!m_test)
384  {
385  NS_FATAL_ERROR ("Ipv4AddressGeneratorImpl::Add(): Address Collision: " << Ipv4Address (addr));
386  }
387  return false;
388  }
389 //
390 // If the new address is less than the lowest address in the current block,
391 // and can't be merged into to the current block, then insert it as a new
392 // block before the current block.
393 //
394  if (addr < (*i).addrLow - 1)
395  {
396  break;
397  }
398 //
399 // If the new address fits at the end of the block, look ahead to the next
400 // block and make sure it's not a collision there. If we won't overlap, then
401 // just extend the current block by one address. We expect that completely
402 // filled network ranges will be a fairly rare occurrence, so we don't worry
403 // about collapsing address range blocks.
404 //
405  if (addr == (*i).addrHigh + 1)
406  {
407  std::list<Entry>::iterator j = i;
408  ++j;
409 
410  if (j != m_entries.end ())
411  {
412  if (addr == (*j).addrLow)
413  {
414  NS_LOG_LOGIC ("Ipv4AddressGeneratorImpl::Add(): "
415  "Address Collision: " << Ipv4Address (addr));
416  if (!m_test)
417  {
418  NS_FATAL_ERROR ("Ipv4AddressGeneratorImpl::Add(): Address Collision: " << Ipv4Address (addr));
419  }
420  return false;
421  }
422  }
423 
424  NS_LOG_LOGIC ("New addrHigh = " << Ipv4Address (addr));
425  (*i).addrHigh = addr;
426  return true;
427  }
428 //
429 // If we get here, we know that the next lower block of addresses couldn't
430 // have been extended to include this new address since the code immediately
431 // above would have been executed and that next lower block extended upward.
432 // So we know it's safe to extend the current block down to include the new
433 // address.
434 //
435  if (addr == (*i).addrLow - 1)
436  {
437  NS_LOG_LOGIC ("New addrLow = " << Ipv4Address (addr));
438  (*i).addrLow = addr;
439  return true;
440  }
441  }
442 
443  Entry entry;
444  entry.addrLow = entry.addrHigh = addr;
445  m_entries.insert (i, entry);
446  return true;
447 }
448 
449 bool
451 {
452  NS_LOG_FUNCTION (this << address);
453 
454  uint32_t addr = address.Get ();
455 
456  NS_ABORT_MSG_UNLESS (addr, "Ipv4AddressGeneratorImpl::IsAddressAllocated(): Don't check for the broadcast address...");
457 
458  std::list<Entry>::iterator i;
459 
460  for (i = m_entries.begin (); i != m_entries.end (); ++i)
461  {
462  NS_LOG_LOGIC ("examine entry: " << Ipv4Address ((*i).addrLow) <<
463  " to " << Ipv4Address ((*i).addrHigh));
464  if (addr >= (*i).addrLow && addr <= (*i).addrHigh)
465  {
466  NS_LOG_LOGIC ("Ipv4AddressGeneratorImpl::IsAddressAllocated(): Address Collision: " << Ipv4Address (addr));
467  return false;
468  }
469  }
470  return true;
471 }
472 
473 bool
475 {
476  NS_LOG_FUNCTION (this << address << mask);
477 
478  NS_ABORT_MSG_UNLESS (address == address.CombineMask (mask),
479  "Ipv4AddressGeneratorImpl::IsNetworkAllocated(): network address and mask don't match " << address << " " << mask);
480 
481  std::list<Entry>::iterator i;
482 
483  for (i = m_entries.begin (); i != m_entries.end (); ++i)
484  {
485  NS_LOG_LOGIC ("examine entry: " << Ipv4Address ((*i).addrLow) << " to " << Ipv4Address ((*i).addrHigh));
486  Ipv4Address low = Ipv4Address ((*i).addrLow);
487  Ipv4Address high = Ipv4Address ((*i).addrHigh);
488 
489  if (address == low.CombineMask (mask) || address == high.CombineMask (mask))
490  {
491  NS_LOG_LOGIC ("Ipv4AddressGeneratorImpl::IsNetworkAllocated(): Network already allocated: " <<
492  address << " " << low << "-" << high);
493  return false;
494  }
495 
496  }
497  return true;
498 }
499 
500 
501 void
503 {
504  NS_LOG_FUNCTION (this);
505  m_test = true;
506 }
507 
508 uint32_t
510 {
511 
512  NS_LOG_FUNCTION (this << mask);
513 
514 //
515 // We've been given a mask that has a higher order bit set for each bit of the
516 // network number. In order to translate this mask into an index, we just need
517 // to count the number of zero bits in the mask. We do this in a loop in which
518 // we shift the mask right until we find the first nonzero bit. This tells us
519 // the number of zero bits, and from this we infer the number of nonzero bits
520 // which is the number of bits in the mask.
521 //
522 // We use the number of bits in the mask as the number of bits in the network
523 // number and as the index into the network number state table.
524 //
525  uint32_t maskBits = mask.Get ();
526 
527  for (uint32_t i = 0; i < N_BITS; ++i)
528  {
529  if (maskBits & 1)
530  {
531  uint32_t index = N_BITS - i;
532  NS_ABORT_MSG_UNLESS (index > 0 && index < N_BITS, "Ipv4AddressGenerator::MaskToIndex(): Illegal Mask");
533  return index;
534  }
535  maskBits >>= 1;
536  }
537  NS_ASSERT_MSG (false, "Ipv4AddressGenerator::MaskToIndex(): Impossible");
538  return 0;
539 }
540 
541 void
543  const Ipv4Address net,
544  const Ipv4Mask mask,
545  const Ipv4Address addr)
546 {
547  NS_LOG_FUNCTION (net << mask << addr);
548 
550  ->Init (net, mask, addr);
551 }
552 
555 {
556  NS_LOG_FUNCTION (mask);
557 
559  ->NextNetwork (mask);
560 }
561 
564 {
565  NS_LOG_FUNCTION (mask);
566 
568  ->GetNetwork (mask);
569 }
570 
571 void
573  const Ipv4Address addr,
574  const Ipv4Mask mask)
575 {
576  NS_LOG_FUNCTION (addr << mask);
577 
579  ->InitAddress (addr, mask);
580 }
581 
584 {
585  NS_LOG_FUNCTION (mask);
586 
588  ->GetAddress (mask);
589 }
590 
593 {
594  NS_LOG_FUNCTION (mask);
595 
597  ->NextAddress (mask);
598 }
599 
600 void
602 {
604 
606  ->Reset ();
607 }
608 
609 bool
611 {
612  NS_LOG_FUNCTION (addr);
613 
615  ->AddAllocated (addr);
616 }
617 
618 bool
620 {
621  NS_LOG_FUNCTION (addr);
622 
624  ->IsAddressAllocated (addr);
625 }
626 
627 bool
629 {
630  NS_LOG_FUNCTION (addr << mask);
631 
633  ->IsNetworkAllocated (addr, mask);
634 }
635 
636 void
638 {
640 
642  ->TestMode ();
643 }
644 
645 } // namespace ns3
646 
static Ipv4Address NextAddress(const Ipv4Mask mask)
Allocate the next Ipv4Address for the configured network and mask.
static void InitAddress(const Ipv4Address addr, const Ipv4Mask mask)
Set the address for the given mask.
static void TestMode(void)
Used to turn off fatal errors and assertions, for testing.
static Ipv4Address NextNetwork(const Ipv4Mask mask)
Get the next network according to the given Ipv4Mask.
static bool AddAllocated(const Ipv4Address addr)
Add the Ipv4Address to the list of IPv4 entries.
static bool IsAddressAllocated(const Ipv4Address addr)
Check the Ipv4Address allocation in the list of IPv4 entries.
static void Reset(void)
Reset the networks and Ipv4Address to zero.
static Ipv4Address GetNetwork(const Ipv4Mask mask)
Get the current network of the given Ipv4Mask.
static void Init(const Ipv4Address net, const Ipv4Mask mask, const Ipv4Address addr="0.0.0.1")
Initialise the base network, mask and address for the generator.
static bool IsNetworkAllocated(const Ipv4Address addr, const Ipv4Mask mask)
Check if a network has already allocated addresses.
static Ipv4Address GetAddress(const Ipv4Mask mask)
Get the Ipv4Address that will be allocated upon NextAddress ()
This class holds the allocated addresses.
uint32_t addrHigh
the highest allocated address
uint32_t addrLow
the lowest allocated address
This class holds the state for a given network.
Implementation class of Ipv4AddressGenerator This generator assigns addresses sequentially from a pro...
void TestMode(void)
Used to turn off fatal errors and assertions, for testing.
uint32_t MaskToIndex(Ipv4Mask mask) const
Create an index number for the network mask.
Ipv4Address GetNetwork(const Ipv4Mask mask) const
Get the current network of the given Ipv4Mask.
Ipv4Address GetAddress(const Ipv4Mask mask) const
Get the Ipv4Address that will be allocated upon NextAddress ()
void Init(const Ipv4Address net, const Ipv4Mask mask, const Ipv4Address addr)
Initialise the base network, mask and address for the generator.
bool IsNetworkAllocated(const Ipv4Address addr, const Ipv4Mask mask)
Check if a network has already allocated addresses.
bool AddAllocated(const Ipv4Address addr)
Add the Ipv4Address to the list of IPv4 entries.
static const uint32_t N_BITS
the number of bits in the address
void InitAddress(const Ipv4Address addr, const Ipv4Mask mask)
Set the address for the given mask.
void Reset(void)
Reset the networks and Ipv4Address to zero.
NetworkState m_netTable[N_BITS]
the available networks
std::list< Entry > m_entries
contained of allocated addresses
static const uint32_t MOST_SIGNIFICANT_BIT
MSB set to 1.
bool IsAddressAllocated(const Ipv4Address addr)
Check the Ipv4Address allocation in the list of IPv4 entries.
Ipv4Address NextAddress(const Ipv4Mask mask)
Allocate the next Ipv4Address for the configured network and mask.
Ipv4Address NextNetwork(const Ipv4Mask mask)
Get the next network according to the given Ipv4Mask.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
uint32_t Get(void) const
Get the host-order 32-bit IP address.
Ipv4Address CombineMask(Ipv4Mask const &mask) const
Combine this address with a network mask.
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:256
uint32_t Get(void) const
Get the host-order 32-bit IP mask.
static T * Get(void)
Get a pointer to the singleton instance.
#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_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition: abort.h:144
#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_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
address
Definition: first.py:44
Every class exported by the ns3 library is enclosed in the ns3 namespace.