Techies
Techies

Reputation: 3

How to get all possible subnet ID of a network in python?

Trying to create a function that returns a list of all possible subnet ID given a network ID, Subnet Mask, the default mask, an octet of interest, and the magic number. Inside the function, I feel like the classful subnet mask must be also used but can seem to write a useful procedure.

def getAllSubnet(networkID, SubnetMask, classfulSubnetMask, octetInterest, magicNumber):
    classfulSubnetMask = classfulSubnetMask.split('.')
    SubnetMask = SubnetMask.split('.')
    allSubnet = []
    for _ in range(0, int(SubnetMask[octetInterest-1]), magicNumber):
        networkID = networkID.split('.')
        networkID[octetInterest-1] = str(int(networkID[octetInterest-1])+magicNumber)
        networkID = '.'.join(networkID)
        allSubnet.append(networkID)
    return allSubnet

networkID = '16.0.0.0'
subnetRequested = '500'
classfulSubnetMask = '255.0.0.0'
subnetMask = '255.255.128.0'
octetInterest = 3
magicNumber = 128

print(getAllSubnet(networkID, subnetMask, classfulSubnetMask, octetInterest, magicNumber))

Upvotes: 0

Views: 2655

Answers (1)

TheWriter
TheWriter

Reputation: 256

Explanation of Network and Host IDs

There are generally two types of IPv4 addressing methodologies, classful and classless. Since your example includes information about classful subnetting I will assume you want to calculate out the possible number of subnets given an IPv4 class and a subnet mask. I can edit the answer as needed if you were looking for something else.

There are 5 classes when dealing with IPv4 addresses (A, B, C, D, E). Each class is determined in the first octet (first 8 bits) of the IP address.

You can read more about determining IPv4 class here: https://www.tutorialspoint.com/ipv4/ipv4_address_classes.htm

It should be noted that classful IP addressing is not used anymore in real-world scenarios.

With that said, here is how you would break this information down given the example you provided.

First is the “Classful Subnet Mask” which would be used to determine how many bits of your IP address make up the class. Any bits that are used for the class cannot be used for your subnet or your host IDs (the host IDs being the actual individual nodes on your network).

Then you have your “Subnet Mask” which is telling you which bits make up your Subnet IDs versus your Host IDs.

Finally you have your “Network ID” which is showing us the actual prefix that will be used for all Subnet and Host IDs. So as follows:

Classful Subnet Mask: 255.0.0.0 (Binary Rep: 11111111.00000000.00000000.00000000)

Subnet Mask: 255.255.128.0 (Binary Rep: 11111111.11111111.10000000.00000000)

Network ID: 16.0.0.0 (Binary Rep: 00010000.00000000.00000000.00000000)

We know that the bits set by the classful subnet mask is reserved for your network ID (i.e. cannot be used by subnets), we also know that the bits NOT set by the subnet mask are reserved for hosts (those last 15 0s at the end of the subnet mask).

This means we want to calculate out how many of those 1s in the subnet mask are unique to the subnet mask and not included in your classful mask. In our example the decimal representation would be ‘0.255.128.0’ and the binary representation would be ‘00000000.11111111.10000000.00000000’.

Thus we have 9 bits of subnet addressing space, which If we take 2^9, we get 512 possible subnet IDs. We then know, based on our network ID of 16.0.0.0 that our subnet ID’s range from 16.0.0.0 to 16.255.128.0. We also know that each subnet can have 32,768 hosts. For instance, if your network id and subnet id equate to 16.0.0.0, we can have hosts in the range of 16.0.0.1 to 16.0.127.255.

Implementing a Solution Using Python "ipaddress" Library

Using the ‘ipaddress’ library in python we can solve the issue of finding all possible subnets very easily. I will post the example code and then explain below.

import ipaddress

# Here I've left your variables exactly as they were in case this format is a requirement.
networkID = '16.0.0.0'
subnetRequested = '500'
classfulSubnetMask = '255.0.0.0'
subnetMask = '255.255.128.0'
octetInterest = 3
magicNumber = 128

# Calculate how many 1's are set in the binary forms of both net masks
subnetMaskBits = bin(int(ipaddress.IPv4Address(subnetMask))).count("1")
classfulMaskBits = bin(int(ipaddress.IPv4Address(classfulSubnetMask))).count("1")

# Create an ip_network object using our network address and in CIDR notation
fullAddress = ipaddress.ip_network(networkID + "/" + str(classfulMaskBits))

# Print out all possible subnets against our fulladdress with subnet mask
output = list(fullAddress.subnets(prefixlen_diff=(subnetMaskBits-classfulMaskBits)))

# Print the addresses (note there are going to be a LOT of them)
print (output)

The code is relatively straight forward, but there are a few things that might need explaining. First we calculate the number of 1’s in both of the net masks binary forms. Then we create an ip_network object (part of the python ipaddress library) and initialize it using CIDR notation.

CIDR stands for Classless Interdomain Routing and is used instead of classful (what we are using in your example) in the real world. Here we are using it only because it will allow us to easily calculate out our subnet IDs.

CIDR notation looks like this (16.0.0.0/8) where the “/8” represents the number of 1’s in the mask. Therefore for the full address we pass in the number of 1’s from the classful subnet mask which is 8.

This python library has a function called “subnets” which will do exactly what your question is asking. The only thing you need to know here is the “prefixlen_diff” argument. This argument is basically saying how many bits are reserved for our subnet IDs. This is going to be equal to the number of 1’s in our classful mask subtracted from our subnet mask (as explained above).

To summarize this a bit more clearly:

Network IP Address: 16.0.0.0

Classful Mask: 255.0.0.0 (11111111.00000000.00000000.00000000)

Classful Mask 1's: 8

Network IP CIDR Notation: 16.0.0.0/8

Then for the subnet:

Subnet Mask: 255.255.128.0 (11111111.11111111.10000000.00000000)

1's in Subnet Mask: 17

1's Unique to Subnet Mask: 9 (00000000.11111111.10000000.00000000)

All applies to this line of code:

output = list(fullAddress.subnets(prefixlen_diff=(subnetMaskBits-classfulMaskBits)))

Where fullAddress is "16.0.0.0/8" and prefixlen_diff is 9 (17 - 8).

We call the subnets method with list to iterate out all of the possible Subnet IDs. We actually don't need the octetInterest or magicNumber variables at all.

Hopefully I answered the question that you were trying to ask, but I can edit this as needed if you were looking for a different kind of output.

Upvotes: 1

Related Questions