A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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
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
27namespace ns3
28{
29
30NS_LOG_COMPONENT_DEFINE("Ipv4AddressGenerator");
31
41{
42 public:
45
56 void Init(const Ipv4Address net, const Ipv4Mask mask, const Ipv4Address addr);
57
67 Ipv4Address GetNetwork(const Ipv4Mask mask) const;
68
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:
174 };
175
177
181 class Entry
182 {
183 public:
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
200void
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;
232 m_netTable[i].addrMax = ~m_netTable[i].mask;
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
244void
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
305void
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 = Ipv4Address((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
357bool
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 {
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 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: "
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
451bool
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 std::list<Entry>::iterator i;
463
464 for (i = m_entries.begin(); i != m_entries.end(); ++i)
465 {
466 NS_LOG_LOGIC("examine entry: " << Ipv4Address((*i).addrLow) << " to "
467 << Ipv4Address((*i).addrHigh));
468 if (addr >= (*i).addrLow && addr <= (*i).addrHigh)
469 {
470 NS_LOG_LOGIC("Ipv4AddressGeneratorImpl::IsAddressAllocated(): Address Collision: "
471 << Ipv4Address(addr));
472 return false;
473 }
474 }
475 return true;
476}
477
478bool
480{
481 NS_LOG_FUNCTION(this << address << mask);
482
484 address == address.CombineMask(mask),
485 "Ipv4AddressGeneratorImpl::IsNetworkAllocated(): network address and mask don't match "
486 << address << " " << mask);
487
488 std::list<Entry>::iterator i;
489
490 for (i = m_entries.begin(); i != m_entries.end(); ++i)
491 {
492 NS_LOG_LOGIC("examine entry: " << Ipv4Address((*i).addrLow) << " to "
493 << Ipv4Address((*i).addrHigh));
494 Ipv4Address low = Ipv4Address((*i).addrLow);
495 Ipv4Address high = Ipv4Address((*i).addrHigh);
496
497 if (address == low.CombineMask(mask) || address == high.CombineMask(mask))
498 {
500 "Ipv4AddressGeneratorImpl::IsNetworkAllocated(): Network already allocated: "
501 << address << " " << low << "-" << high);
502 return false;
503 }
504 }
505 return true;
506}
507
508void
510{
511 NS_LOG_FUNCTION(this);
512 m_test = true;
513}
514
517{
518 NS_LOG_FUNCTION(this << mask);
519
520 //
521 // We've been given a mask that has a higher order bit set for each bit of the
522 // network number. In order to translate this mask into an index, we just need
523 // to count the number of zero bits in the mask. We do this in a loop in which
524 // we shift the mask right until we find the first nonzero bit. This tells us
525 // the number of zero bits, and from this we infer the number of nonzero bits
526 // which is the number of bits in the mask.
527 //
528 // We use the number of bits in the mask as the number of bits in the network
529 // number and as the index into the network number state table.
530 //
531 uint32_t maskBits = mask.Get();
532
533 for (uint32_t i = 0; i < N_BITS; ++i)
534 {
535 if (maskBits & 1)
536 {
537 uint32_t index = N_BITS - i;
538 NS_ABORT_MSG_UNLESS(index > 0 && index < N_BITS,
539 "Ipv4AddressGenerator::MaskToIndex(): Illegal Mask");
540 return index;
541 }
542 maskBits >>= 1;
543 }
544 NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible");
545 return 0;
546}
547
548void
550{
551 NS_LOG_FUNCTION(net << mask << addr);
552
554}
555
558{
559 NS_LOG_FUNCTION(mask);
560
561 return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->NextNetwork(mask);
562}
563
566{
567 NS_LOG_FUNCTION(mask);
568
570}
571
572void
574{
575 NS_LOG_FUNCTION(addr << mask);
576
578}
579
582{
583 NS_LOG_FUNCTION(mask);
584
586}
587
590{
591 NS_LOG_FUNCTION(mask);
592
593 return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->NextAddress(mask);
594}
595
596void
598{
600
602}
603
604bool
606{
607 NS_LOG_FUNCTION(addr);
608
609 return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->AddAllocated(addr);
610}
611
612bool
614{
615 NS_LOG_FUNCTION(addr);
616
617 return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->IsAddressAllocated(addr);
618}
619
620bool
622{
623 NS_LOG_FUNCTION(addr << mask);
624
625 return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->IsNetworkAllocated(addr, mask);
626}
627
628void
630{
632
634}
635
636} // 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 ",...
Every class exported by the ns3 library is enclosed in the ns3 namespace.