Specifying Address Ranges in IPv6



How do I specify an address range for IPv6?


The instruction range6 provides two ways to define a block of addresses that the server can use for allocations.  While either method will work, the server will allocate addresses more efficiently if they are configured in CIDR blocks.

First Method

One way to specify an address range for IPv6 is to provide the beginning and ending addresses of the block:

range6 2001:DB8::64 2001:DB8::C8

# This is the address range 100-200 in decimal

Second Method

The second way to specify an address range for IPV6 is to use CIDR notation to specify a block of addresses. For example:

range6 2001:DB8::0/120

The server will convert the ranges into a set of internal structures that each are a single CIDR block and then link them together to form the range.  In the first case this results in a number of smaller blocks (in the server's internal data structures) while in the second there is one single larger block.

Internal data structure resulting from the First Method: six CIDR blocks comprising a pool of 101

2001:DB8::64 / 126  (100-103, 4 addresses)

2001:DB8::68 / 125  (104-111, 8 addresses)

2001:DB8::70 / 124  (112-127, 16 addresses)

2001:DB8::80 / 122  (128-191, 64 addresses)

2001:DB8::C0 / 125  (192-199, 8 addresses)

2001:DB8::C8 / 128  (200, only 1 address)


Internal data structure resulting from the Second Method: one CIDR block, one pool of 256

2001:DB8::00 / 120  (256 addresses)

When the server attempts to find an address for a client it first finds the list of pools for the given region.  In this example, it would find the 6 internal pools that make up the range above.  The server then works its way through the list of pools trying to find an address, halting the search when it finds an acceptable address.  To find an address it performs a hash function (on the DUID for a non temporary address or on internal information for a temporary address) and masks the result to fit into the given block.  If the address is already in use it performs another round of hashing on the previous result and tries the new result.  If it is unable to find an available address after a number of such iterations it moves to the next pool and repeats the process.  

There are two items to note about this process:

1) The server is unlikely to be able to use the entire block of addresses you provide.  As the pools fill the probability of collision will increase and you will be unlikely to be able to use the last addresses.

2) Using ranges that convert to large numbers of small CIDR blocks is inefficient as the server will need to walk through the list of pools to try and find an address, and it will use the address space inefficiently.

It is significantly preferable to configure an IPv6 address pool using a CIDR block (Second Method above) instead of an address range (First Method above). Considering the size (and purpose) of IPv6 address space, generally you should err on the side of a larger address pool.  If for some reason you must use an address range, the server will operate more efficiently if you can specify a range that the server can store in as few CIDR blocks as possible. For example:

range6 2001:DB8::60 2001:DB8::BF

# This is the address range 96-191 in decimal

Internal data structure for this range6: two CIDR blocks comprising a pool of 96

2001:DB8::60 / 123  (96-127, 32 addresses)

2001:DB8::80 / 122  (128-191, 64 addresses)

The "trick" is to use CIDR boundaries on the top and bottom addresses in the range6 statement.  In the example we see 60 (decimal 96) as the base and BF (decimal 191) as the top.

Is your DHCP server using a lot more memory than you expect it to?

Strategic use of range6 statements can signficantly alter dhcpd's memory consumption.  For more information see DHCP uses too much memory: reducing dhcp memory consumption by careful use of range6 statements