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
32/**
33 * \ingroup address
34 *
35 * \brief Implementation class of Ipv4AddressGenerator
36 * This generator assigns addresses sequentially from a provided
37 * network address; used in topology code. It also keeps track of all
38 * addresses assigned to perform duplicate detection.
39 */
41{
42 public:
45
46 /**
47 * \brief Initialise the base network, mask and address for the generator
48 *
49 * The first call to NextAddress() or GetAddress() will return the
50 * value passed in.
51 *
52 * \param net The network for the base Ipv4Address
53 * \param mask The network mask of the base Ipv4Address
54 * \param addr The base address used for initialization
55 */
56 void Init(const Ipv4Address net, const Ipv4Mask mask, const Ipv4Address addr);
57
58 /**
59 * \brief Get the current network of the given Ipv4Mask
60 *
61 * Does not change the internal state; this just peeks at the current
62 * network
63 *
64 * \param mask The Ipv4Mask for the current network
65 * \returns the IPv4 address of the current network
66 */
67 Ipv4Address GetNetwork(const Ipv4Mask mask) const;
68
69 /**
70 * \brief Get the next network according to the given Ipv4Mask
71 *
72 * This operation is a pre-increment, meaning that the internal state
73 * is changed before returning the new network address.
74 *
75 * This also resets the address to the base address that was
76 * used for initialization.
77 *
78 * \param mask The Ipv4Mask used to set the next network
79 * \returns the IPv4 address of the next network
80 */
82
83 /**
84 * \brief Set the address for the given mask
85 *
86 * \param addr The address to set for the current mask
87 * \param mask The Ipv4Mask whose address is to be set
88 */
89 void InitAddress(const Ipv4Address addr, const Ipv4Mask mask);
90
91 /**
92 * \brief Allocate the next Ipv4Address for the configured network and mask
93 *
94 * This operation is a post-increment, meaning that the first address
95 * allocated will be the one that was initially configured.
96 *
97 * \param mask The Ipv4Mask for the current network
98 * \returns the IPv4 address
99 */
100 Ipv4Address NextAddress(const Ipv4Mask mask);
101
102 /**
103 * \brief Get the Ipv4Address that will be allocated upon NextAddress ()
104 *
105 * Does not change the internal state; just is used to peek the next
106 * address that will be allocated upon NextAddress ()
107 *
108 * \param mask The Ipv4Mask for the current network
109 * \returns the IPv4 address
110 */
111 Ipv4Address GetAddress(const Ipv4Mask mask) const;
112
113 /**
114 * \brief Reset the networks and Ipv4Address to zero
115 */
116 void Reset();
117
118 /**
119 * \brief Add the Ipv4Address to the list of IPv4 entries
120 *
121 * Typically, this is used by external address allocators that want
122 * to make use of this class's ability to track duplicates. AddAllocated
123 * is always called internally for any address generated by NextAddress ()
124 *
125 * \param addr The Ipv4Address to be added to the list of Ipv4 entries
126 * \returns true on success
127 */
128 bool AddAllocated(const Ipv4Address addr);
129
130 /**
131 * \brief Check the Ipv4Address allocation in the list of IPv4 entries
132 *
133 * \param addr The Ipv4Address to be checked in the list of Ipv4 entries
134 * \returns true if the address is already allocated
135 */
136 bool IsAddressAllocated(const Ipv4Address addr);
137
138 /**
139 * \brief Check if a network has already allocated addresses
140 *
141 * \param addr The Ipv4 network to be checked
142 * \param mask The Ipv4 network mask
143 * \returns true if the network is already allocated
144 */
145 bool IsNetworkAllocated(const Ipv4Address addr, const Ipv4Mask mask);
146
147 /**
148 * \brief Used to turn off fatal errors and assertions, for testing
149 */
150 void TestMode();
151
152 private:
153 static const uint32_t N_BITS = 32; //!< the number of bits in the address
154 static const uint32_t MOST_SIGNIFICANT_BIT = 0x80000000; //!< MSB set to 1
155
156 /**
157 * \brief Create an index number for the network mask
158 * \param mask the mask to index
159 * \returns an index
160 */
161 uint32_t MaskToIndex(Ipv4Mask mask) const;
162
163 /**
164 * \brief This class holds the state for a given network
165 */
167 {
168 public:
169 uint32_t mask; //!< the network mask
170 uint32_t shift; //!< a shift
171 uint32_t network; //!< the network
172 uint32_t addr; //!< the address
173 uint32_t addrMax; //!< the maximum address
174 };
175
176 NetworkState m_netTable[N_BITS]; //!< the available networks
177
178 /**
179 * \brief This class holds the allocated addresses
180 */
181 class Entry
182 {
183 public:
184 uint32_t addrLow; //!< the lowest allocated address
185 uint32_t addrHigh; //!< the highest allocated address
186 };
187
188 std::list<Entry> m_entries; //!< contained of allocated addresses
189 bool m_test; //!< test mode (if true)
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((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 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
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 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
476bool
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 {
496 "Ipv4AddressGeneratorImpl::IsNetworkAllocated(): Network already allocated: "
497 << address << " " << low << "-" << high);
498 return false;
499 }
500 }
501 return true;
502}
503
504void
506{
507 NS_LOG_FUNCTION(this);
508 m_test = true;
509}
510
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
544void
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
566}
567
568void
570{
571 NS_LOG_FUNCTION(addr << mask);
572
574}
575
578{
579 NS_LOG_FUNCTION(mask);
580
582}
583
586{
587 NS_LOG_FUNCTION(mask);
588
589 return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->NextAddress(mask);
590}
591
592void
594{
596
598}
599
600bool
602{
603 NS_LOG_FUNCTION(addr);
604
605 return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->AddAllocated(addr);
606}
607
608bool
610{
611 NS_LOG_FUNCTION(addr);
612
613 return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->IsAddressAllocated(addr);
614}
615
616bool
618{
619 NS_LOG_FUNCTION(addr << mask);
620
621 return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->IsNetworkAllocated(addr, mask);
622}
623
624void
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 ",...
Every class exported by the ns3 library is enclosed in the ns3 namespace.