There are very few scenarios that would require a DHCP server to offer over 14.1 million IPs, but if you happen to encounter one, you may find that your ISC DHCP server immediately segfaults at startup or reports a vague error message and fails to start.
Let’s assume that you need to serve a full /8 CIDR block (16.7 million IPs) from your DHCP server. While there are reasons why this is probably not a good idea, such as long daemon start-up times and too flat of a network topology, you would probably try to use a configuration similar to the following scope in your dhcpd.conf file:
If you happen to be running ISC DHCP 4.3.2 or older, the daemon will segfault upon startup and you will find the following error in your logs:
But, if you’re running ISC DHCP 4.3.3 or newer, you’ll receive the following in your logs:
Syntactically, the scope defined above is perfectly valid, but since 304 bytes of RAM is allocated for each IP address in the scope, we need a 5.1GB allocation for this scope. Recalling that 2^32 = 4294967296 (4GB), we can see where the problem lies.
At approximately 14.1 million IPs, the amount of memory necessary to hold the scope exceeds a 32-bit allocation maximum of 4GB.
An important fact to know here is that the memory allocation is scope-based, therefore the memory overflow is also scope-based.
In order to serve a contiguous block of more than 14.1 million IPs, consider breaking up the scope into multiple, overlapping scopes.
For our example where we want to serve 10.0.0.0/8, we can break the single /8 scope into two /9 scopes. The first scope will cover the lower half of the /8 (10.0.0.2-10.127.255.255) and the second scope will cover the upper half of the /8 (10.128.0.0-10.255.255.254):
Dividing the scopes with an additional subnet bit isn’t necessary; it’s just what I choose to do.
The following is equally valid:
If your DHCP server has enough resources, primarily RAM, you could theoretically serve scopes larger than /8, but you will need to break the scope into smaller scopes of no larger than 14.1 million IPs per scope.
You may see the following warning message in your logs:
Since we are purposely creating overlapping subnets because our original subnet is “overly large”, this warning is to be expected.
The same 5.1GB of RAM must be allocated, but we’ve broken into two allocations of just over 2.5GB each.
Breaking up a large scope into smaller scopes within the same subnet may work, and could serve as a temporary fix if you’re up against the wall during an outage, but having this many hosts in a single subnet is usually not a good idea.
In this example, you’d have up to 16.7 million hosts all within the same broadcast domain. Even using switches to break up the collision domain only solves a small part of the problem. Each time one of the devices on the network sends a broadcast packet (such as a DHCP DISCOVER), that packet will be duplicated and forwarded out of every switch port and delivered to every device in the broadcast domain.
Consider breaking up your broadcast domains by routing between disparate portions of your network, using subnets to classify different types of users or devices, and/or assigning devices or network segments to specific VLANs.
For example, if you are serving a very, very large office building, assign a subnet to a router on each floor, break that subnet into smaller subnets for each company or group on the floor and use VLAN-aware switches to deliver these subnets where they are needed. Switches which support untagged VLAN ports can make the conversion from a totally flat network much easier since implementing VLANs can usually be accomplished without any changes on the end-device.
Breaking up your broadcast domains not only improves the efficiency of your network, it also allows you to have greater control (read: security) over your network.