'Calculating remaining CIDR ranges with Python

I need assistance in calculating in Python the remaining CIDR ranges after i use a subnet.

Example: I want to use a wide range of 10.0.0.0/15 and from it to calculate what available ranges i have left if i substract 10.0.0.0/16 ( the answer should be 10.1.0.0/16 )

But this gets trickier if i want to substract /24 or other actions.

Is there something that can help with this inside Python?

thank you



Solution 1:[1]

This is very easy to do with netaddr module.

from netaddr import *
subnet1= IPSet(IPNetwork("10.0.0.0/15"))
subnet2 = IPSet(IPNetwork("10.0.0.0/16"))
# symmetric difference
result = subnet1 ^ subnet2
print(result)

result: IPSet(['10.1.0.0/16'])

if you want to subtract /24

from netaddr import *
subnet1= IPSet(IPNetwork("10.0.0.0/15"))
subnet2 = IPSet(IPNetwork("10.0.0.0/24"))
# symmetric difference
result = subnet1 ^ subnet2
print(result)

result:

IPSet(['10.0.1.0/24', '10.0.2.0/23', '10.0.4.0/22', '10.0.8.0/21', '10.0.16.0/20', '10.0.32.0/19', '10.0.64.0/18', '10.0.128.0/17', '10.1.0.0/16'])

Solution 2:[2]

Consider your example: you assigned a /16 subnet of your /15 net, so you split your total host address space in two, i.e. the one you assigned, which has a 0 value for the 16th bit, and the one which is still free, and has a 1 for the 16th bit.

Now suppose you had a /14 net. Assigning a /16 subnet would leave you with 3 free /16 subnets, i.e. the ones with respectively 01, 10, 11 in positions 15-16. Of course since two of them have 1 in position 15 we may also say you have one /15 subnet (10.2.0.0/15) and one /16 subnet (`10.1.0.0/16).

And so on.

So when you assign a /24 subnet from your original /15 net you are creating 2**9 (512) /24 subnets: the one you assigned and 511 more. Or you may say you are left with one /16, one /17, ..., one /24 free subnet.

I don't know of any libraries for that, but as you see the calculations are simple enough. On the other hand, developing a system to keep track of many subsequent assignments is far from trivial...

If you want a list of all the subnets, this will do:

def ip2int(dec_ip):
    t = 0
    for e,k in enumerate(reversed(dec_ip)):
        t += k*16**(e*2)
    return t

def int2ip(int_ip):
    ip = []
    for e in range(4):
        ip.append(int_ip % 256)
        int_ip //= 256
    return list(reversed(ip))

def subtract_ip(mask, width, sub_width):
    subnets = []
    int_mask = ip2int(mask)
    delta = int(2 ** (sub_width - width))
    for d in range(1, delta):
        subnets.append(int2ip(int_mask + d*2**(32-width)))
    return subnets

subtract_ip([10,0,0,0], 14, 16)
[[10, 0, 1, 0], [10, 0, 2, 0], [10, 0, 3, 0]]

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 marksoe
Solution 2