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 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
8
9#include "ns3/abort.h"
10#include "ns3/assert.h"
11#include "ns3/log.h"
12#include "ns3/simulation-singleton.h"
13
14#include <list>
15
16namespace ns3
17{
18
19NS_LOG_COMPONENT_DEFINE("Ipv4AddressGenerator");
20
21/**
22 * @ingroup address
23 *
24 * @brief Implementation class of Ipv4AddressGenerator
25 * This generator assigns addresses sequentially from a provided
26 * network address; used in topology code. It also keeps track of all
27 * addresses assigned to perform duplicate detection.
28 */
30{
31 public:
34
35 /**
36 * @brief Initialise the base network, mask and address for the generator
37 *
38 * The first call to NextAddress() or GetAddress() will return the
39 * value passed in.
40 *
41 * @param net The network for the base Ipv4Address
42 * @param mask The network mask of the base Ipv4Address
43 * @param addr The base address used for initialization
44 */
45 void Init(const Ipv4Address net, const Ipv4Mask mask, const Ipv4Address addr);
46
47 /**
48 * @brief Get the current network of the given Ipv4Mask
49 *
50 * Does not change the internal state; this just peeks at the current
51 * network
52 *
53 * @param mask The Ipv4Mask for the current network
54 * @returns the IPv4 address of the current network
55 */
56 Ipv4Address GetNetwork(const Ipv4Mask mask) const;
57
58 /**
59 * @brief Get the next network according to the given Ipv4Mask
60 *
61 * This operation is a pre-increment, meaning that the internal state
62 * is changed before returning the new network address.
63 *
64 * This also resets the address to the base address that was
65 * used for initialization.
66 *
67 * @param mask The Ipv4Mask used to set the next network
68 * @returns the IPv4 address of the next network
69 */
71
72 /**
73 * @brief Set the address for the given mask
74 *
75 * @param addr The address to set for the current mask
76 * @param mask The Ipv4Mask whose address is to be set
77 */
78 void InitAddress(const Ipv4Address addr, const Ipv4Mask mask);
79
80 /**
81 * @brief Allocate the next Ipv4Address for the configured network and mask
82 *
83 * This operation is a post-increment, meaning that the first address
84 * allocated will be the one that was initially configured.
85 *
86 * @param mask The Ipv4Mask for the current network
87 * @returns the IPv4 address
88 */
90
91 /**
92 * @brief Get the Ipv4Address that will be allocated upon NextAddress ()
93 *
94 * Does not change the internal state; just is used to peek the next
95 * address that will be allocated upon NextAddress ()
96 *
97 * @param mask The Ipv4Mask for the current network
98 * @returns the IPv4 address
99 */
100 Ipv4Address GetAddress(const Ipv4Mask mask) const;
101
102 /**
103 * @brief Reset the networks and Ipv4Address to zero
104 */
105 void Reset();
106
107 /**
108 * @brief Add the Ipv4Address to the list of IPv4 entries
109 *
110 * Typically, this is used by external address allocators that want
111 * to make use of this class's ability to track duplicates. AddAllocated
112 * is always called internally for any address generated by NextAddress ()
113 *
114 * @param addr The Ipv4Address to be added to the list of Ipv4 entries
115 * @returns true on success
116 */
117 bool AddAllocated(const Ipv4Address addr);
118
119 /**
120 * @brief Check the Ipv4Address allocation in the list of IPv4 entries
121 *
122 * @param addr The Ipv4Address to be checked in the list of Ipv4 entries
123 * @returns true if the address is already allocated
124 */
125 bool IsAddressAllocated(const Ipv4Address addr);
126
127 /**
128 * @brief Check if a network has already allocated addresses
129 *
130 * @param addr The Ipv4 network to be checked
131 * @param mask The Ipv4 network mask
132 * @returns true if the network is already allocated
133 */
134 bool IsNetworkAllocated(const Ipv4Address addr, const Ipv4Mask mask);
135
136 /**
137 * @brief Used to turn off fatal errors and assertions, for testing
138 */
139 void TestMode();
140
141 private:
142 static const uint32_t N_BITS = 32; //!< the number of bits in the address
143 static const uint32_t MOST_SIGNIFICANT_BIT = 0x80000000; //!< MSB set to 1
144
145 /**
146 * @brief Create an index number for the network mask
147 * @param mask the mask to index
148 * @returns an index
149 */
150 uint32_t MaskToIndex(Ipv4Mask mask) const;
151
152 /**
153 * @brief This class holds the state for a given network
154 */
156 {
157 public:
158 uint32_t mask; //!< the network mask
159 uint32_t shift; //!< a shift
160 uint32_t network; //!< the network
161 uint32_t addr; //!< the address
162 uint32_t addrMax; //!< the maximum address
163 };
164
165 NetworkState m_netTable[N_BITS]; //!< the available networks
166
167 /**
168 * @brief This class holds the allocated addresses
169 */
170 class Entry
171 {
172 public:
173 uint32_t addrLow; //!< the lowest allocated address
174 uint32_t addrHigh; //!< the highest allocated address
175 };
176
177 std::list<Entry> m_entries; //!< contained of allocated addresses
178 bool m_test; //!< test mode (if true)
179};
180
182 : m_entries(),
183 m_test(false)
184{
185 NS_LOG_FUNCTION(this);
186 Reset();
187}
188
189void
191{
192 NS_LOG_FUNCTION(this);
193
194 uint32_t mask = 0;
195 //
196 // There are 32 possible masks in a 32-bit integer. Two of these are illegal
197 // for a network mask (0x00000000 and 0xffffffff). Valid network masks
198 // correspond to some nonzero number of high order bits set to one followed by
199 // some nonzero number of lower order bits set to zero.
200 //
201 // We look at a network number as an n-bit number where n is defined as the
202 // number of bits in each mask. Allocating a new network number is simply
203 // incrementing this number.
204 //
205 // In order to combine an allocated network number with an IP address, we have
206 // to shift the network into the correct alignment with respect to its mask.
207 // For example, a network mask of 0xff000000 admits the possibility of 256
208 // different network numbers since there are eight bits available. To create
209 // IP addresses, we need to shift the network number counter left by 24 bits
210 // to put it in correct alignment. This leaves 24 bits left for addresses.
211 // We make sure we don't overflow by saving a maximum address number which is
212 // just the inverse of the mask (~mask).
213 //
214 for (uint32_t i = 0; i < N_BITS; ++i)
215 {
216 m_netTable[i].mask = mask;
217 mask >>= 1;
218 mask |= MOST_SIGNIFICANT_BIT;
219 m_netTable[i].network = 1;
220 m_netTable[i].addr = 1;
221 m_netTable[i].addrMax = ~m_netTable[i].mask;
222 m_netTable[i].shift = N_BITS - i;
223 }
224 m_entries.clear();
225 m_test = false;
226}
227
232
233void
235{
236 NS_LOG_FUNCTION(this << net << mask << addr);
237 //
238 // We're going to be playing with the actual bits in the network and mask so
239 // pull them out into ints.
240 //
241 uint32_t maskBits = mask.Get();
242 uint32_t netBits = net.Get();
243 uint32_t addrBits = addr.Get();
244 //
245 // Some quick reasonableness testing.
246 //
247 NS_ABORT_MSG_UNLESS((netBits & ~maskBits) == 0,
248 "Ipv4AddressGeneratorImpl::Init (): Inconsistent network and mask");
249 NS_ABORT_MSG_UNLESS((addrBits & maskBits) == 0,
250 "Ipv4AddressGeneratorImpl::Init (): Inconsistent address and mask");
251
252 //
253 // Convert the network mask into an index into the network number table.
254 // The network number comes in to us properly aligned for the mask and so
255 // needs to be shifted right into the normalized position (lowest bit of the
256 // network number at bit zero of the int that holds it).
257 //
258 uint32_t index = MaskToIndex(mask);
259
260 m_netTable[index].network = netBits >> m_netTable[index].shift;
261
262 NS_ABORT_MSG_UNLESS(addrBits <= m_netTable[index].addrMax,
263 "Ipv4AddressGeneratorImpl::Init(): Address overflow");
264 m_netTable[index].addr = addrBits;
265}
266
269{
270 NS_LOG_FUNCTION(this << mask);
271
272 uint32_t index = MaskToIndex(mask);
273 return Ipv4Address(m_netTable[index].network << m_netTable[index].shift);
274}
275
278{
279 NS_LOG_FUNCTION(this << mask);
280 //
281 // The way this is expected to be used is that an address and network prefix
282 // are initialized, and then NextAddress() is called repeatedly to set the
283 // addresses on a given subnet. The client will expect that the first
284 // addresses will use the network prefix she used to initialize the generator
285 // with. After a subnet is assigned, the client will call NextNetwork to
286 // get the network number of the next subnet. This implies that that this
287 // operation is a pre-increment.
288 //
289 uint32_t index = MaskToIndex(mask);
290 ++m_netTable[index].network;
291 return Ipv4Address(m_netTable[index].network << m_netTable[index].shift);
292}
293
294void
296{
297 NS_LOG_FUNCTION(this << addr << mask);
298
299 uint32_t index = MaskToIndex(mask);
300 uint32_t addrBits = addr.Get();
301
302 NS_ABORT_MSG_UNLESS(addrBits <= m_netTable[index].addrMax,
303 "Ipv4AddressGeneratorImpl::InitAddress(): Address overflow");
304 m_netTable[index].addr = addrBits;
305}
306
309{
310 NS_LOG_FUNCTION(this << mask);
311
312 uint32_t index = MaskToIndex(mask);
313
314 return Ipv4Address((m_netTable[index].network << m_netTable[index].shift) |
315 m_netTable[index].addr);
316}
317
320{
321 NS_LOG_FUNCTION(this << mask);
322 //
323 // The way this is expected to be used is that an address and network prefix
324 // are initialized, and then NextAddress() is called repeatedly to set the
325 // addresses on a given subnet. The client will expect that the first address
326 // she gets back is the one she used to initialize the generator with. This
327 // implies that this operation is a post-increment.
328 //
329 uint32_t index = MaskToIndex(mask);
330
331 NS_ABORT_MSG_UNLESS(m_netTable[index].addr <= m_netTable[index].addrMax,
332 "Ipv4AddressGeneratorImpl::NextAddress(): Address overflow");
333
334 Ipv4Address addr((m_netTable[index].network << m_netTable[index].shift) |
335 m_netTable[index].addr);
336
337 ++m_netTable[index].addr;
338 //
339 // Make a note that we've allocated this address -- used for address collision
340 // detection.
341 //
342 AddAllocated(addr);
343 return addr;
344}
345
346bool
348{
349 NS_LOG_FUNCTION(this << address);
350
351 uint32_t addr = address.Get();
352
354 addr,
355 "Ipv4AddressGeneratorImpl::Add(): Allocating the broadcast address is not a good idea");
356
357 std::list<Entry>::iterator i;
358
359 for (i = m_entries.begin(); i != m_entries.end(); ++i)
360 {
361 NS_LOG_LOGIC("examine entry: " << Ipv4Address((*i).addrLow) << " to "
362 << Ipv4Address((*i).addrHigh));
363 //
364 // First things first. Is there an address collision -- that is, does the
365 // new address fall in a previously allocated block of addresses.
366 //
367 if (addr >= (*i).addrLow && addr <= (*i).addrHigh)
368 {
370 "Ipv4AddressGeneratorImpl::Add(): Address Collision: " << Ipv4Address(addr));
371 if (!m_test)
372 {
374 "Ipv4AddressGeneratorImpl::Add(): Address Collision: " << Ipv4Address(addr));
375 }
376 return false;
377 }
378 //
379 // If the new address is less than the lowest address in the current block,
380 // and can't be merged into to the current block, then insert it as a new
381 // block before the current block.
382 //
383 if (addr < (*i).addrLow - 1)
384 {
385 break;
386 }
387 //
388 // If the new address fits at the end of the block, look ahead to the next
389 // block and make sure it's not a collision there. If we won't overlap, then
390 // just extend the current block by one address. We expect that completely
391 // filled network ranges will be a fairly rare occurrence, so we don't worry
392 // about collapsing address range blocks.
393 //
394 if (addr == (*i).addrHigh + 1)
395 {
396 auto j = i;
397 ++j;
398
399 if (j != m_entries.end())
400 {
401 if (addr == (*j).addrLow)
402 {
403 NS_LOG_LOGIC("Ipv4AddressGeneratorImpl::Add(): "
404 "Address Collision: "
405 << Ipv4Address(addr));
406 if (!m_test)
407 {
408 NS_FATAL_ERROR("Ipv4AddressGeneratorImpl::Add(): Address Collision: "
409 << Ipv4Address(addr));
410 }
411 return false;
412 }
413 }
414
415 NS_LOG_LOGIC("New addrHigh = " << Ipv4Address(addr));
416 (*i).addrHigh = addr;
417 return true;
418 }
419 //
420 // If we get here, we know that the next lower block of addresses couldn't
421 // have been extended to include this new address since the code immediately
422 // above would have been executed and that next lower block extended upward.
423 // So we know it's safe to extend the current block down to include the new
424 // address.
425 //
426 if (addr == (*i).addrLow - 1)
427 {
428 NS_LOG_LOGIC("New addrLow = " << Ipv4Address(addr));
429 (*i).addrLow = addr;
430 return true;
431 }
432 }
433
434 Entry entry;
435 entry.addrLow = entry.addrHigh = addr;
436 m_entries.insert(i, entry);
437 return true;
438}
439
440bool
442{
443 NS_LOG_FUNCTION(this << address);
444
445 uint32_t addr = address.Get();
446
448 addr,
449 "Ipv4AddressGeneratorImpl::IsAddressAllocated(): Don't check for the broadcast address...");
450
451 for (auto i = m_entries.begin(); i != m_entries.end(); ++i)
452 {
453 NS_LOG_LOGIC("examine entry: " << Ipv4Address((*i).addrLow) << " to "
454 << Ipv4Address((*i).addrHigh));
455 if (addr >= (*i).addrLow && addr <= (*i).addrHigh)
456 {
457 NS_LOG_LOGIC("Ipv4AddressGeneratorImpl::IsAddressAllocated(): Address Collision: "
458 << Ipv4Address(addr));
459 return true;
460 }
461 }
462 return false;
463}
464
465bool
467{
468 NS_LOG_FUNCTION(this << address << mask);
469
471 address == address.CombineMask(mask),
472 "Ipv4AddressGeneratorImpl::IsNetworkAllocated(): network address and mask don't match "
473 << address << " " << mask);
474
475 for (auto i = m_entries.begin(); i != m_entries.end(); ++i)
476 {
477 NS_LOG_LOGIC("examine entry: " << Ipv4Address((*i).addrLow) << " to "
478 << Ipv4Address((*i).addrHigh));
479 Ipv4Address low((*i).addrLow);
480 Ipv4Address high((*i).addrHigh);
481
482 if (address == low.CombineMask(mask) || address == high.CombineMask(mask))
483 {
485 "Ipv4AddressGeneratorImpl::IsNetworkAllocated(): Network already allocated: "
486 << address << " " << low << "-" << high);
487 return false;
488 }
489 }
490 return true;
491}
492
493void
499
502{
503 NS_LOG_FUNCTION(this << mask);
504
505 //
506 // We've been given a mask that has a higher order bit set for each bit of the
507 // network number. In order to translate this mask into an index, we just need
508 // to count the number of zero bits in the mask. We do this in a loop in which
509 // we shift the mask right until we find the first nonzero bit. This tells us
510 // the number of zero bits, and from this we infer the number of nonzero bits
511 // which is the number of bits in the mask.
512 //
513 // We use the number of bits in the mask as the number of bits in the network
514 // number and as the index into the network number state table.
515 //
516 uint32_t maskBits = mask.Get();
517
518 for (uint32_t i = 0; i < N_BITS; ++i)
519 {
520 if (maskBits & 1)
521 {
522 uint32_t index = N_BITS - i;
523 NS_ABORT_MSG_UNLESS(index > 0 && index < N_BITS,
524 "Ipv4AddressGenerator::MaskToIndex(): Illegal Mask");
525 return index;
526 }
527 maskBits >>= 1;
528 }
529 NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible");
530 return 0;
531}
532
533void
535{
536 NS_LOG_FUNCTION(net << mask << addr);
537
539}
540
543{
544 NS_LOG_FUNCTION(mask);
545
546 return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->NextNetwork(mask);
547}
548
551{
552 NS_LOG_FUNCTION(mask);
553
555}
556
557void
559{
560 NS_LOG_FUNCTION(addr << mask);
561
563}
564
567{
568 NS_LOG_FUNCTION(mask);
569
571}
572
575{
576 NS_LOG_FUNCTION(mask);
577
578 return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->NextAddress(mask);
579}
580
581void
588
589bool
596
597bool
599{
600 NS_LOG_FUNCTION(addr);
601
602 return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->IsAddressAllocated(addr);
603}
604
605bool
607{
608 NS_LOG_FUNCTION(addr << mask);
609
610 return SimulationSingleton<Ipv4AddressGeneratorImpl>::Get()->IsNetworkAllocated(addr, mask);
611}
612
613void
620
621} // 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.
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
uint32_t Get() const
Get the host-order 32-bit IP mask.
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:75
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition abort.h:133
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#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.