A Discrete-Event Network Simulator
API
ipv4-address-generator.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008 University of Washington
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 
18 #include "ipv4-address-generator.h"
19 
20 #include "ns3/abort.h"
21 #include "ns3/assert.h"
22 #include "ns3/log.h"
23 #include "ns3/simulation-singleton.h"
24 
25 #include <list>
26 
27 namespace ns3
28 {
29 
30 NS_LOG_COMPONENT_DEFINE("Ipv4AddressGenerator");
31 
41 {
42  public:
44  virtual ~Ipv4AddressGeneratorImpl();
45 
56  void Init(const Ipv4Address net, const Ipv4Mask mask, const Ipv4Address addr);
57 
67  Ipv4Address GetNetwork(const Ipv4Mask mask) const;
68 
81  Ipv4Address NextNetwork(const Ipv4Mask mask);
82 
89  void InitAddress(const Ipv4Address addr, const Ipv4Mask mask);
90 
100  Ipv4Address NextAddress(const Ipv4Mask mask);
101 
111  Ipv4Address GetAddress(const Ipv4Mask mask) const;
112 
116  void Reset();
117 
128  bool AddAllocated(const Ipv4Address addr);
129 
136  bool IsAddressAllocated(const Ipv4Address addr);
137 
145  bool IsNetworkAllocated(const Ipv4Address addr, const Ipv4Mask mask);
146 
150  void TestMode();
151 
152  private:
153  static const uint32_t N_BITS = 32;
154  static const uint32_t MOST_SIGNIFICANT_BIT = 0x80000000;
155 
161  uint32_t MaskToIndex(Ipv4Mask mask) const;
162 
167  {
168  public:
169  uint32_t mask;
170  uint32_t shift;
171  uint32_t network;
172  uint32_t addr;
173  uint32_t addrMax;
174  };
175 
177 
181  class Entry
182  {
183  public:
184  uint32_t addrLow;
185  uint32_t addrHigh;
186  };
187 
188  std::list<Entry> m_entries;
189  bool m_test;
190 };
191 
193  : m_entries(),
194  m_test(false)
195 {
196  NS_LOG_FUNCTION(this);
197  Reset();
198 }
199 
200 void
202 {
203  NS_LOG_FUNCTION(this);
204 
205  uint32_t mask = 0;
206  //
207  // There are 32 possible masks in a 32-bit integer. Two of these are illegal
208  // for a network mask (0x00000000 and 0xffffffff). Valid network masks
209  // correspond to some nonzero number of high order bits set to one followed by
210  // some nonzero number of lower order bits set to zero.
211  //
212  // We look at a network number as an n-bit number where n is defined as the
213  // number of bits in each mask. Allocating a new network number is simply
214  // incrementing this number.
215  //
216  // In order to combine an allocated network number with an IP address, we have
217  // to shift the network into the correct alignment with respect to its mask.
218  // For example, a network mask of 0xff000000 admits the possibility of 256
219  // different network numbers since there are eight bits available. To create
220  // IP addresses, we need to shift the network number counter left by 24 bits
221  // to put it in correct alignment. This leaves 24 bits left for addresses.
222  // We make sure we don't overflow by saving a maximum address number which is
223  // just the inverse of the mask (~mask).
224  //
225  for (uint32_t i = 0; i < N_BITS; ++i)
226  {
227  m_netTable[i].mask = mask;
228  mask >>= 1;
229  mask |= MOST_SIGNIFICANT_BIT;
230  m_netTable[i].network = 1;
231  m_netTable[i].addr = 1;
233  m_netTable[i].shift = N_BITS - i;
234  }
235  m_entries.clear();
236  m_test = false;
237 }
238 
240 {
241  NS_LOG_FUNCTION(this);
242 }
243 
244 void
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,
259  "Ipv4AddressGeneratorImpl::Init (): Inconsistent network and mask");
260  NS_ABORT_MSG_UNLESS((addrBits & maskBits) == 0,
261  "Ipv4AddressGeneratorImpl::Init (): Inconsistent address and mask");
262 
263  //
264  // Convert the network mask into an index into the network number table.
265  // The network number comes in to us properly aligned for the mask and so
266  // needs to be shifted right into the normalized position (lowest bit of the
267  // network number at bit zero of the int that holds it).
268  //
269  uint32_t index = MaskToIndex(mask);
270 
271  m_netTable[index].network = netBits >> m_netTable[index].shift;
272 
273  NS_ABORT_MSG_UNLESS(addrBits <= m_netTable[index].addrMax,
274  "Ipv4AddressGeneratorImpl::Init(): Address overflow");
275  m_netTable[index].addr = addrBits;
276 }
277 
280 {
281  NS_LOG_FUNCTION(this << mask);
282 
283  uint32_t index = MaskToIndex(mask);
284  return Ipv4Address(m_netTable[index].network << m_netTable[index].shift);
285 }
286 
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 {
308  NS_LOG_FUNCTION(this << addr << mask);
309 
310  uint32_t index = MaskToIndex(mask);
311  uint32_t addrBits = addr.Get();
312 
313  NS_ABORT_MSG_UNLESS(addrBits <= m_netTable[index].addrMax,
314  "Ipv4AddressGeneratorImpl::InitAddress(): Address overflow");
315  m_netTable[index].addr = addrBits;
316 }
317 
320 {
321  NS_LOG_FUNCTION(this << mask);
322 
323  uint32_t index = MaskToIndex(mask);
324 
325  return Ipv4Address((m_netTable[index].network << m_netTable[index].shift) |
326  m_netTable[index].addr);
327 }
328 
331 {
332  NS_LOG_FUNCTION(this << mask);
333  //
334  // The way this is expected to be used is that an address and network prefix
335  // are initialized, and then NextAddress() is called repeatedly to set the
336  // addresses on a given subnet. The client will expect that the first address
337  // she gets back is the one she used to initialize the generator with. This
338  // implies that this operation is a post-increment.
339  //
340  uint32_t index = MaskToIndex(mask);
341 
342  NS_ABORT_MSG_UNLESS(m_netTable[index].addr <= m_netTable[index].addrMax,
343  "Ipv4AddressGeneratorImpl::NextAddress(): Address overflow");
344 
345  Ipv4Address addr((m_netTable[index].network << m_netTable[index].shift) |
346  m_netTable[index].addr);
347 
348  ++m_netTable[index].addr;
349  //
350  // Make a note that we've allocated this address -- used for address collision
351  // detection.
352  //
353  AddAllocated(addr);
354  return addr;
355 }
356 
357 bool
359 {
360  NS_LOG_FUNCTION(this << address);
361 
362  uint32_t addr = address.Get();
363 
365  addr,
366  "Ipv4AddressGeneratorImpl::Add(): Allocating the broadcast address is not a good idea");
367 
368  std::list<Entry>::iterator i;
369 
370  for (i = m_entries.begin(); i != m_entries.end(); ++i)
371  {
372  NS_LOG_LOGIC("examine entry: " << Ipv4Address((*i).addrLow) << " to "
373  << Ipv4Address((*i).addrHigh));
374  //
375  // First things first. Is there an address collision -- that is, does the
376  // new address fall in a previously allocated block of addresses.
377  //
378  if (addr >= (*i).addrLow && addr <= (*i).addrHigh)
379  {
380  NS_LOG_LOGIC(
381  "Ipv4AddressGeneratorImpl::Add(): Address Collision: " << Ipv4Address(addr));
382  if (!m_test)
383  {
385  "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  auto 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: "
416  << Ipv4Address(addr));
417  if (!m_test)
418  {
419  NS_FATAL_ERROR("Ipv4AddressGeneratorImpl::Add(): Address Collision: "
420  << Ipv4Address(addr));
421  }
422  return false;
423  }
424  }
425 
426  NS_LOG_LOGIC("New addrHigh = " << Ipv4Address(addr));
427  (*i).addrHigh = addr;
428  return true;
429  }
430  //
431  // If we get here, we know that the next lower block of addresses couldn't
432  // have been extended to include this new address since the code immediately
433  // above would have been executed and that next lower block extended upward.
434  // So we know it's safe to extend the current block down to include the new
435  // address.
436  //
437  if (addr == (*i).addrLow - 1)
438  {
439  NS_LOG_LOGIC("New addrLow = " << Ipv4Address(addr));
440  (*i).addrLow = addr;
441  return true;
442  }
443  }
444 
445  Entry entry;
446  entry.addrLow = entry.addrHigh = addr;
447  m_entries.insert(i, entry);
448  return true;
449 }
450 
451 bool
453 {
454  NS_LOG_FUNCTION(this << address);
455 
456  uint32_t addr = address.Get();
457 
459  addr,
460  "Ipv4AddressGeneratorImpl::IsAddressAllocated(): Don't check for the broadcast address...");
461 
462  for (auto i = m_entries.begin(); i != m_entries.end(); ++i)
463  {
464  NS_LOG_LOGIC("examine entry: " << Ipv4Address((*i).addrLow) << " to "
465  << Ipv4Address((*i).addrHigh));
466  if (addr >= (*i).addrLow && addr <= (*i).addrHigh)
467  {
468  NS_LOG_LOGIC("Ipv4AddressGeneratorImpl::IsAddressAllocated(): Address Collision: "
469  << Ipv4Address(addr));
470  return true;
471  }
472  }
473  return false;
474 }
475 
476 bool
478 {
479  NS_LOG_FUNCTION(this << address << mask);
480 
482  address == address.CombineMask(mask),
483  "Ipv4AddressGeneratorImpl::IsNetworkAllocated(): network address and mask don't match "
484  << address << " " << mask);
485 
486  for (auto i = m_entries.begin(); i != m_entries.end(); ++i)
487  {
488  NS_LOG_LOGIC("examine entry: " << Ipv4Address((*i).addrLow) << " to "
489  << Ipv4Address((*i).addrHigh));
490  Ipv4Address low((*i).addrLow);
491  Ipv4Address high((*i).addrHigh);
492 
493  if (address == low.CombineMask(mask) || address == high.CombineMask(mask))
494  {
495  NS_LOG_LOGIC(
496  "Ipv4AddressGeneratorImpl::IsNetworkAllocated(): Network already allocated: "
497  << address << " " << low << "-" << high);
498  return false;
499  }
500  }
501  return true;
502 }
503 
504 void
506 {
507  NS_LOG_FUNCTION(this);
508  m_test = true;
509 }
510 
511 uint32_t
513 {
514  NS_LOG_FUNCTION(this << mask);
515 
516  //
517  // We've been given a mask that has a higher order bit set for each bit of the
518  // network number. In order to translate this mask into an index, we just need
519  // to count the number of zero bits in the mask. We do this in a loop in which
520  // we shift the mask right until we find the first nonzero bit. This tells us
521  // the number of zero bits, and from this we infer the number of nonzero bits
522  // which is the number of bits in the mask.
523  //
524  // We use the number of bits in the mask as the number of bits in the network
525  // number and as the index into the network number state table.
526  //
527  uint32_t maskBits = mask.Get();
528 
529  for (uint32_t i = 0; i < N_BITS; ++i)
530  {
531  if (maskBits & 1)
532  {
533  uint32_t index = N_BITS - i;
534  NS_ABORT_MSG_UNLESS(index > 0 && index < N_BITS,
535  "Ipv4AddressGenerator::MaskToIndex(): Illegal Mask");
536  return index;
537  }
538  maskBits >>= 1;
539  }
540  NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible");
541  return 0;
542 }
543 
544 void
545 Ipv4AddressGenerator::Init(const Ipv4Address net, const Ipv4Mask mask, const Ipv4Address addr)
546 {
547  NS_LOG_FUNCTION(net << mask << addr);
548 
550 }
551 
554 {
555  NS_LOG_FUNCTION(mask);
556 
557  return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->NextNetwork(mask);
558 }
559 
562 {
563  NS_LOG_FUNCTION(mask);
564 
565  return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->GetNetwork(mask);
566 }
567 
568 void
570 {
571  NS_LOG_FUNCTION(addr << mask);
572 
573  SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->InitAddress(addr, mask);
574 }
575 
578 {
579  NS_LOG_FUNCTION(mask);
580 
581  return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->GetAddress(mask);
582 }
583 
586 {
587  NS_LOG_FUNCTION(mask);
588 
589  return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->NextAddress(mask);
590 }
591 
592 void
594 {
596 
598 }
599 
600 bool
602 {
603  NS_LOG_FUNCTION(addr);
604 
605  return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->AddAllocated(addr);
606 }
607 
608 bool
610 {
611  NS_LOG_FUNCTION(addr);
612 
613  return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->IsAddressAllocated(addr);
614 }
615 
616 bool
618 {
619  NS_LOG_FUNCTION(addr << mask);
620 
621  return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->IsNetworkAllocated(addr, mask);
622 }
623 
624 void
626 {
628 
630 }
631 
632 } // namespace ns3
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()
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 void Reset()
Reset the networks and Ipv4Address to zero.
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 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...
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.
NetworkState m_netTable[N_BITS]
the available networks
std::list< Entry > m_entries
contained of allocated addresses
void TestMode()
Used to turn off fatal errors and assertions, for testing.
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.
void Reset()
Reset the networks and Ipv4Address to zero.
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:42
Ipv4Address CombineMask(const Ipv4Mask &mask) const
Combine this address with a network mask.
uint32_t Get() const
Get the host-order 32-bit IP address.
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:257
uint32_t Get() const
Get the host-order 32-bit IP mask.
Definition: ipv4-address.cc:84
static T * Get()
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:86
#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:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#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:47
Every class exported by the ns3 library is enclosed in the ns3 namespace.