A Discrete-Event Network Simulator
API
ipv6-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  * Copyright (c) 2011 Atishay Jain
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */
19 
20 #include <list>
21 #include "ns3/abort.h"
22 #include "ns3/assert.h"
23 #include "ns3/log.h"
24 #include "ns3/simulation-singleton.h"
25 #include "ipv6-address-generator.h"
26 
27 namespace ns3 {
28 
29 NS_LOG_COMPONENT_DEFINE ("Ipv6AddressGenerator");
30 
41 {
42 public:
44  virtual ~Ipv6AddressGeneratorImpl ();
45 
56  void Init (const Ipv6Address net, const Ipv6Prefix prefix,
57  const Ipv6Address interfaceId);
58 
71  Ipv6Address NextNetwork (const Ipv6Prefix prefix);
72 
82  Ipv6Address GetNetwork (const Ipv6Prefix prefix) const;
83 
90  void InitAddress (const Ipv6Address interfaceId, const Ipv6Prefix prefix);
91 
101  Ipv6Address GetAddress (const Ipv6Prefix prefix) const;
102 
112  Ipv6Address NextAddress (const Ipv6Prefix prefix);
113 
117  void Reset (void);
118 
129  bool AddAllocated (const Ipv6Address addr);
130 
134  void TestMode (void);
135 
136 private:
137  static const uint32_t N_BITS = 128;
138  static const uint32_t MOST_SIGNIFICANT_BIT = 0x80;
139 
145  uint32_t PrefixToIndex (Ipv6Prefix prefix) const;
146 
151  {
152 public:
153  uint8_t prefix[16];
154  uint32_t shift;
155  uint8_t network[16];
156  uint8_t addr[16];
157  uint8_t addrMax[16];
158  };
159 
161 
165  class Entry
166  {
167 public:
168  uint8_t addrLow[16];
169  uint8_t addrHigh[16];
170  };
171 
172  std::list<Entry> m_entries;
174  bool m_test;
175 };
176 
178  : m_entries (),
179  m_base ("::1"),
180  m_test (false)
181 {
182  NS_LOG_FUNCTION (this);
183  Reset ();
184 }
185 
186 void
188 {
189  NS_LOG_FUNCTION (this);
190 
191  uint8_t prefix[16] = { 0};
192 
193  for (uint32_t i = 0; i < N_BITS; ++i)
194  {
195  for (uint32_t j = 0; j < 16; ++j)
196  {
197  m_netTable[i].prefix[j] = prefix[j];
198  }
199  for (uint32_t j = 0; j < 15; ++j)
200  {
201  prefix[15 - j] >>= 1;
202  prefix[15 - j] |= (prefix[15 - j - 1] & 1);
203  }
204  prefix[0] |= MOST_SIGNIFICANT_BIT;
205  for (uint32_t j = 0; j < 15; ++j)
206  {
207  m_netTable[i].network[j] = 0;
208  }
209  m_netTable[i].network[15] = 1;
210  for (uint32_t j = 0; j < 15; ++j)
211  {
212  m_netTable[i].addr[j] = 0;
213  }
214  m_netTable[i].addr[15] = 1;
215  for (uint32_t j = 0; j < 16; ++j)
216  {
217  m_netTable[i].addrMax[j] = ~prefix[j];
218  }
219  m_netTable[i].shift = N_BITS - i;
220  }
221  m_entries.clear ();
222  m_base = Ipv6Address ("::1");
223  m_test = false;
224 }
225 
227 {
228  NS_LOG_FUNCTION (this);
229 }
230 
231 void
233  const Ipv6Address net,
234  const Ipv6Prefix prefix,
235  const Ipv6Address interfaceId)
236 {
237  NS_LOG_FUNCTION (this << net << prefix << interfaceId);
238 
239  m_base = interfaceId;
240  //
241  // We're going to be playing with the actual bits in the network and prefix so
242  // pull them out into ints.
243  //
244  uint8_t prefixBits[16];
245  prefix.GetBytes (prefixBits);
246  uint8_t netBits[16];
247  net.GetBytes (netBits);
248  uint8_t interfaceIdBits[16];
249  interfaceId.GetBytes (interfaceIdBits);
250  //
251  // Some quick reasonableness testing.
252  //
253  // Convert the network prefix into an index into the network number table.
254  // The network number comes in to us properly aligned for the prefix 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 = PrefixToIndex (prefix);
259  NS_LOG_DEBUG ("Index " << index);
260  uint32_t a = m_netTable[index].shift / 8;
261  uint32_t b = m_netTable[index].shift % 8;
262  for (int32_t j = 15 - a; j >= 0; j--)
263  {
264  m_netTable[index].network[j + a] = netBits[j];
265  }
266  for (uint32_t j = 0; j < a; j++)
267  {
268  m_netTable[index].network[j] = 0;
269  }
270  for (uint32_t j = 15; j >= a; j--)
271  {
272  m_netTable[index].network[j] = m_netTable[index].network[j] >> b;
273  m_netTable[index].network[j] |= m_netTable[index].network[j - 1] << (8 - b);
274  }
275  for (int32_t j = 0; j < 16; j++)
276  {
277  m_netTable[index].addr[j] = interfaceIdBits[j];
278  }
279  return;
280 }
281 
284  const Ipv6Prefix prefix) const
285 {
286  NS_LOG_FUNCTION (this);
287  uint8_t nw[16];
288  uint32_t index = PrefixToIndex (prefix);
289  uint32_t a = m_netTable[index].shift / 8;
290  uint32_t b = m_netTable[index].shift % 8;
291  for (uint32_t j = 0; j < 16 - a; ++j)
292  {
293  nw[j] = m_netTable[index].network[j + a];
294  }
295  for (uint32_t j = 16 - a; j < 16; ++j)
296  {
297  nw[j] = 0;
298  }
299  for (uint32_t j = 0; j < 15; j++)
300  {
301  nw[j] = nw[j] << b;
302  nw[j] |= nw[j + 1] >> (8 - b);
303  }
304  nw[15] = nw[15] << b;
305 
306  return Ipv6Address (nw);
307 }
308 
311  const Ipv6Prefix prefix)
312 {
313  NS_LOG_FUNCTION (this);
314 
315  uint32_t index = PrefixToIndex (prefix);
316  // Reset the base to what was initialized
317  uint8_t interfaceIdBits[16];
318  m_base.GetBytes (interfaceIdBits);
319  for (int32_t j = 0; j < 16; j++)
320  {
321  m_netTable[index].addr[j] = interfaceIdBits[j];
322  }
323 
324  for (int32_t j = 15; j >= 0; j--)
325  {
326  if (m_netTable[index].network[j] < 0xff)
327  {
328  ++m_netTable[index].network[j];
329  break;
330  }
331  else
332  {
333  ++m_netTable[index].network[j];
334  }
335  }
336 
337  uint8_t nw[16];
338  uint32_t a = m_netTable[index].shift / 8;
339  uint32_t b = m_netTable[index].shift % 8;
340  for (uint32_t j = 0; j < 16 - a; ++j)
341  {
342  nw[j] = m_netTable[index].network[j + a];
343  }
344  for (uint32_t j = 16 - a; j < 16; ++j)
345  {
346  nw[j] = 0;
347  }
348  for (uint32_t j = 0; j < 15; j++)
349  {
350  nw[j] = nw[j] << b;
351  nw[j] |= nw[j + 1] >> (8 - b);
352  }
353  nw[15] = nw[15] << b;
354 
355  return Ipv6Address (nw);
356 
357 }
358 
359 void
361  const Ipv6Address interfaceId,
362  const Ipv6Prefix prefix)
363 {
364  NS_LOG_FUNCTION (this);
365 
366  uint32_t index = PrefixToIndex (prefix);
367  uint8_t interfaceIdBits[16];
368  interfaceId.GetBytes (interfaceIdBits);
369 
370  for (uint32_t j = 0; j < 16; ++j)
371  {
372  m_netTable[index].addr[j] = interfaceIdBits[j];
373  }
374 }
375 
378 {
379  NS_LOG_FUNCTION (this);
380 
381  uint32_t index = PrefixToIndex (prefix);
382 
383  uint8_t nw[16];
384  uint32_t a = m_netTable[index].shift / 8;
385  uint32_t b = m_netTable[index].shift % 8;
386  for (uint32_t j = 0; j < 16 - a; ++j)
387  {
388  nw[j] = m_netTable[index].network[j + a];
389  }
390  for (uint32_t j = 16 - a; j < 16; ++j)
391  {
392  nw[j] = 0;
393  }
394  for (uint32_t j = 0; j < 15; j++)
395  {
396  nw[j] = nw[j] << b;
397  nw[j] |= nw[j + 1] >> (8 - b);
398  }
399  nw[15] = nw[15] << b;
400  for (uint32_t j = 0; j < 16; j++)
401  {
402  nw[j] |= m_netTable[index].addr[j];
403  }
404 
405  return Ipv6Address (nw);
406 }
407 
410 {
411  NS_LOG_FUNCTION (this);
412 
413  uint32_t index = PrefixToIndex (prefix);
414 
415  uint8_t ad[16];
416  uint32_t a = m_netTable[index].shift / 8;
417  uint32_t b = m_netTable[index].shift % 8;
418  for (uint32_t j = 0; j < 16 - a; ++j)
419  {
420  ad[j] = m_netTable[index].network[j + a];
421  }
422  for (uint32_t j = 16 - a; j < 16; ++j)
423  {
424  ad[j] = 0;
425  }
426  for (uint32_t j = 0; j < 15; j++)
427  {
428  ad[j] = ad[j] << b;
429  ad[j] |= ad[j + 1] >> (8 - b);
430  }
431  ad[15] = ad[15] << b;
432  for (uint32_t j = 0; j < 16; j++)
433  {
434  ad[j] |= m_netTable[index].addr[j];
435  }
436  Ipv6Address addr = Ipv6Address (ad);
437 
438  for (int32_t j = 15; j >= 0; j--)
439  {
440  if (m_netTable[index].addr[j] < 0xff)
441  {
442  ++m_netTable[index].addr[j];
443  break;
444  }
445  else
446  {
447  ++m_netTable[index].addr[j];
448  }
449  }
450 
451  //
452  // Make a note that we've allocated this address -- used for address collision
453  // detection.
454  //
455  AddAllocated (addr);
456  return addr;
457 }
458 
459 bool
461 {
462  NS_LOG_FUNCTION (this << address);
463 
464  uint8_t addr[16];
465  address.GetBytes (addr);
466 
467  std::list<Entry>::iterator i;
468 
469  for (i = m_entries.begin (); i != m_entries.end (); ++i)
470  {
471  NS_LOG_LOGIC ("examine entry: " << Ipv6Address ((*i).addrLow) <<
472  " to " << Ipv6Address ((*i).addrHigh));
473  //
474  // First things first. Is there an address collision -- that is, does the
475  // new address fall in a previously allocated block of addresses.
476  //
477  if (!(Ipv6Address (addr) < Ipv6Address ((*i).addrLow))
478  && ((Ipv6Address (addr) < Ipv6Address ((*i).addrHigh))
479  || (Ipv6Address (addr) == Ipv6Address ((*i).addrHigh))))
480  {
481  NS_LOG_LOGIC ("Ipv6AddressGeneratorImpl::Add(): Address Collision: " << Ipv6Address (addr));
482  if (!m_test)
483  {
484  NS_FATAL_ERROR ("Ipv6AddressGeneratorImpl::Add(): Address Collision: " << Ipv6Address (addr));
485  }
486  return false;
487  }
488  //
489  // If the new address is less than the lowest address in the current
490  // block and can't be merged into to the current block, then insert it
491  // as a new block before the current block.
492  //
493  uint8_t taddr[16];
494  for (uint32_t j = 0; j < 16; j++)
495  {
496  taddr[j] = (*i).addrLow[j];
497  }
498  taddr[15] -= 1;
499  if (Ipv6Address (addr) < Ipv6Address (taddr))
500  {
501  break;
502  }
503  //
504  // If the new address fits at the end of the block, look ahead to the next
505  // block and make sure it's not a collision there. If we won't overlap,
506  // then just extend the current block by one address. We expect that
507  // completely filled network ranges will be a fairly rare occurrence,
508  // so we don't worry about collapsing address range blocks.
509  //
510  for (uint32_t j = 0; j < 16; j++)
511  {
512  taddr[j] = (*i).addrLow[j];
513  }
514  taddr[15] += 1;
515  if (Ipv6Address (addr) == Ipv6Address (taddr))
516  {
517  std::list<Entry>::iterator j = i;
518  ++j;
519 
520  if (j != m_entries.end ())
521  {
522  if (Ipv6Address (addr) == Ipv6Address ((*j).addrLow))
523  {
524  NS_LOG_LOGIC ("Ipv6AddressGeneratorImpl::Add(): "
525  "Address Collision: " << Ipv6Address (addr));
526  if (!m_test)
527  {
528  NS_FATAL_ERROR ("Ipv6AddressGeneratorImpl::Add(): Address Collision: " << Ipv6Address (addr));
529  }
530  return false;
531  }
532  }
533 
534  NS_LOG_LOGIC ("New addrHigh = " << Ipv6Address (addr));
535  for (uint32_t j = 0; j < 16; j++)
536  {
537  (*i).addrHigh[j] = addr[j];
538  }
539  return true;
540  }
541  //
542  // If we get here, we know that the next lower block of addresses
543  // couldn't have been extended to include this new address since the
544  // code immediately above would have been executed and that next lower
545  // block extended upward. So we know it's safe to extend the current
546  // block down to includ the new address.
547  //
548  for (uint32_t j = 0; j < 16; j++)
549  {
550  taddr[j] = (*i).addrLow[j];
551  }
552  taddr[15] -= 1;
553  if ((Ipv6Address (addr) == Ipv6Address (taddr)))
554  {
555  NS_LOG_LOGIC ("New addrLow = " << Ipv6Address (addr));
556  for (uint32_t j = 0; j < 16; j++)
557  {
558  (*i).addrLow[j] = addr[j];
559  }
560  return true;
561  }
562  }
563 
564  Entry entry;
565  for (uint32_t j = 0; j < 16; j++)
566  {
567  entry.addrLow[j] = entry.addrHigh[j] = addr[j];
568  }
569  m_entries.insert (i, entry);
570  return true;
571 }
572 
573 void
575 {
576  NS_LOG_FUNCTION (this);
577  m_test = true;
578 }
579 
580 uint32_t
582 {
583  //
584  // We've been given a prefix that has a higher order bit set for each bit of
585  // the network number. In order to translate this prefix into an index,
586  // we just need to count the number of zero bits in the prefix. We do this
587  // in a loop in which we shift the prefix right until we find the first
588  // nonzero bit. This tells us the number of zero bits, and from this we
589  // infer the number of nonzero bits which is the number of bits in the prefix.
590  //
591  // We use the number of bits in the prefix as the number of bits in the
592  // network number and as the index into the network number state table.
593  //
594  uint8_t prefixBits[16];
595  prefix.GetBytes (prefixBits);
596 
597  for (int32_t i = 15; i >= 0; --i)
598  {
599  for (uint32_t j = 0; j < 8; ++j)
600  {
601  if (prefixBits[i] & 1)
602  {
603  uint32_t index = N_BITS - (15 - i) * 8 - j;
604  NS_ABORT_MSG_UNLESS (index > 0 && index < N_BITS, "Ip64AddressGenerator::PrefixToIndex(): Illegal Prefix");
605  return index;
606  }
607  prefixBits[i] >>= 1;
608  }
609  }
610  NS_ASSERT_MSG (false, "Ipv6AddressGenerator::PrefixToIndex(): Impossible");
611  return 0;
612 }
613 
614 void
616  const Ipv6Address net,
617  const Ipv6Prefix prefix,
618  const Ipv6Address interfaceId)
619 {
621 
623  ->Init (net, prefix, interfaceId);
624 }
625 
628 {
630 
632  ->NextNetwork (prefix);
633 }
634 
637 {
639 
641  ->GetNetwork (prefix);
642 }
643 
644 void
646  const Ipv6Address interfaceId,
647  const Ipv6Prefix prefix)
648 {
650 
652  ->InitAddress (interfaceId, prefix);
653 }
654 
657 {
659 
661  ->GetAddress (prefix);
662 }
663 
666 {
668 
670  ->NextAddress (prefix);
671 }
672 
673 void
675 {
677 
679  ->Reset ();
680 }
681 
682 bool
684 {
686 
688  ->AddAllocated (addr);
689 }
690 
691 void
693 {
695 
697  ->TestMode ();
698 }
699 
700 } // namespace ns3
701 
Ipv6Address GetNetwork(const Ipv6Prefix prefix) const
Get the current network of the given Ipv6Prefix.
This class holds the state for a given network.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
This class holds the allocated addresses.
uint32_t PrefixToIndex(Ipv6Prefix prefix) const
Create an index number for the prefix.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
static Ipv6Address NextNetwork(const Ipv6Prefix prefix)
Get the next network according to the given Ipv6Prefix.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
static T * Get(void)
Get a pointer to the singleton instance.
void Reset(void)
Reset the networks and Ipv6Address to zero.
static void InitAddress(const Ipv6Address interfaceId, const Ipv6Prefix prefix)
Set the interfaceId for the given Ipv6Prefix.
static void Init(const Ipv6Address net, const Ipv6Prefix prefix, const Ipv6Address interfaceId="::1")
Initialise the base network and interfaceId for the generator.
void InitAddress(const Ipv6Address interfaceId, const Ipv6Prefix prefix)
Set the interfaceId for the given Ipv6Prefix.
void GetBytes(uint8_t buf[16]) const
Get the bytes corresponding to the address.
NetworkState m_netTable[N_BITS]
the available networks
std::list< Entry > m_entries
contained of allocated addresses
static const uint32_t N_BITS
the number of bits in the address
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:252
Ipv6Address GetAddress(const Ipv6Prefix prefix) const
Get the Ipv6Address that will be allocated upon NextAddress ()
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static const uint32_t MOST_SIGNIFICANT_BIT
MSB set to 1.
Implementation class of Ipv6AddressGenerator This generator assigns addresses sequentially from a pro...
static void TestMode(void)
Used to turn off fatal errors and assertions, for testing.
void TestMode(void)
Used to turn off fatal errors and assertions, for testing.
#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:90
Describes an IPv6 address.
Definition: ipv6-address.h:48
static void Reset(void)
Reset the networks and Ipv6Address to zero.
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition: abort.h:144
void GetBytes(uint8_t buf[16]) const
Get the bytes corresponding to the prefix.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:236
Ipv6Address NextNetwork(const Ipv6Prefix prefix)
Get the next network according to the given Ipv6Prefix.
static Ipv6Address GetAddress(const Ipv6Prefix prefix)
Get the Ipv6Address that will be allocated upon NextAddress ()
Describes an IPv6 prefix.
Definition: ipv6-address.h:394
static bool AddAllocated(const Ipv6Address addr)
Add the Ipv6Address to the list of IPv6 entries.
uint8_t addrLow[16]
the lowest allocated address
tuple address
Definition: first.py:37
Ipv6Address NextAddress(const Ipv6Prefix prefix)
Allocate the next Ipv6Address for the configured network and prefix.
void Init(const Ipv6Address net, const Ipv6Prefix prefix, const Ipv6Address interfaceId)
Initialise the base network and interfaceId for the generator.
static Ipv6Address NextAddress(const Ipv6Prefix prefix)
Allocate the next Ipv6Address for the configured network and prefix.
uint8_t addrHigh[16]
the highest allocated address
bool AddAllocated(const Ipv6Address addr)
Add the Ipv6Address to the list of IPv6 entries.
static Ipv6Address GetNetwork(const Ipv6Prefix prefix)
Get the current network of the given Ipv6Prefix.