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"
25
26namespace ns3 {
27
28NS_LOG_COMPONENT_DEFINE ("Ipv4AddressGenerator");
29
39{
40public:
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);
150private:
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 {
166public:
172 };
173
175
179 class Entry
180 {
181public:
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
197void
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;
229 m_netTable[i].addrMax = ~m_netTable[i].mask;
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
241void
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
305void
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
361bool
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
449bool
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
473bool
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
501void
503{
504 NS_LOG_FUNCTION (this);
505 m_test = true;
506}
507
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
541void
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
571void
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
600void
602{
604
606 ->Reset ();
607}
608
609bool
611{
612 NS_LOG_FUNCTION (addr);
613
615 ->AddAllocated (addr);
616}
617
618bool
620{
621 NS_LOG_FUNCTION (addr);
622
624 ->IsAddressAllocated (addr);
625}
626
627bool
629{
630 NS_LOG_FUNCTION (addr << mask);
631
633 ->IsNetworkAllocated (addr, mask);
634}
635
636void
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.