Automating IP subnets allocation using Python

Allocating IP subnets is a simple task for experienced Network Engineers. However, this simple task is prone to human error specially when hundreds of subnets are supposed to be allocated. Most common mistakes are allocating invalid and conflicting subnets. An example of an invalid subnet is 192.168.0.16/27. This subnet is invalid because 192.168.0.16 is not a network address for /27 mask. And an example of conflicting subnets would be 192.168.0.0/27 and 192.168.0.4/30. These are conflicting subnets because there are overlapping IPs between them. In this article, I’ll show you how to write a script in Python to build these checks automatically into your excel sheet. I’ll also show you how to create a script to automate the process of IP allocation altogether. For example, lets say you need to allocate subnets with following masks /28, /28, /27, /27, /29, /29 starting from network address 192.168.0.0, then the expected answer would be, 192.168.0.0/28, 192.168.0.16/28, 192.168.0.32/27, 192.168.0.64/27, 192.168.0.96/29 and 192.168.0.104/29. Without wasting more time, lets get started!

Solving the problem of invalid subnets

First we need to understand why a subnet can be invalid. we know that 192.168.0.16/28 is a valid subnet, whereas, 192.168.0.16/27 is not. To understand why, lets convert both subnets to binary form. 192.168.0.16 in binary form can be written as 11000000101010000000000000010000. Next, we’ll enclose the network bits in square brackets [] and hosts bits in curly brackets {}. So, 192.168.0.16/28 in binary can be written as [1100000010101000000000000001]{0000} and 192.168.0.16/27 as [110000001010100000000000000]{10000}. By definition, binary numbers enclosed in [] bracket is a network address only if all bits inside {} bracket are zeros. Since, the former subnet (192.168.0.16/27) has a bit set to one inside curly bracket {10000}, 192.168.0.16 a not a correct network address for /27 mask. Lets see how we can apply this logic in Python, step by step

successfully verified the sanity of subnets
error occured.10.0.16.16/27 is incorrect subnet
error occured.192.168.0.22/30 is incorrect subnet

Solving the problem of conflicting subnets

Lets recap the problem we are trying to solve here. Consider the two subnets, 192.168.0.0/28 and 192.168.0.8/29 as an example. These two subnets cannot be allocated together because there are overlapping IPs between them. We can verify this by applying following steps. i) Select the smaller mask, in our case since 28 < 29, mask is equal to 28. ii) Convert both IPs into binary form, then enclose first 28 bits in square brackets. We get [1100000010101000000000000000]{0000}’ and ‘[1100000010101000000000000000]{1000} ’. Next, compare the terms inside square brackets, if the terms match, the subnets are conflicting otherwise they are fine. Python implementation for these step are given below

Example of non-conflicting list
No conflict detected
Example of conflicting list
('192.168.10.0/24', '192.168.10.0/28')

Automation Subnets allocation

When subnets are allocated manually, the issues discussed above arises very frequently. The best way to avoid these issues is to automate the process of allocation itself. In this section, we will discuss how this can be done. Lets recap the problem we are trying to solve briefly. Suppose say you were given a task to assign subnets with following masks /28, /28, /27, /27, /29, /29 starting from network address 192.168.0.0 then we want the Python method to return 192.168.0.0/28, 192.168.0.16/28, 192.168.0.32/27, 192.168.0.64/27, 192.168.0.96/29 and 192.168.0.104/29 subnets. The steps we will be following to achieve desired results are as follows

['192.168.12.0/23', '192.168.14.0/24', '192.168.15.0/25', '192.168.15.128/26', '192.168.15.192/27', '192.168.15.224/27']