The Art of IPv4 Subnetting

There are plenty of calculators out there to help you figure out IP ranges, important values, etc. However, when I took an introductory Cisco networking class I built a subnetting calculator in excel. It might be worth copying that calculator to follow along with the article. The calculator could probably be more accurately described as a base-two calculator. It worked by limiting certain values to 0 or 1 - on or off - in a row of cells and assigning a value between 1 to 27 to the cell below, and adding up all the actual values. I'm no mathematician, but the math is pretty easy.

However, before I go into all that I want to address the concept of subnetting. Subnetting is a way of systematically segregating large networks into smaller bitesized portions. Think of it like a university, where each school houses classes and faculties who specialize in fields specific to a certain group of majors or school of thought. While there may be some overlap, it is generally segregated. The end result is generally a more streamlined and higher quality product, whether that product is network design or a degree. With that in mind, let's see how we can computationally describe segments of a network using math and Python.

To really dig into the computational side of things it's probably worth explaining logic and binary anding. Programmers and philosophers use a similar technique for determining the true or false value of an argument. The way it works is that every argument can be broken down into statements and symbols that join those statements, with a value of true or false (or 1 or 0) to each statement. Then whether or not the combination of those statements are true is dependent on how they're combined. Philosophically it can get a lot deeper here, but programmers also do not worry about implicature so I'm going to leave that for another person. The following tables, however, will show how the 'and' and 'or' operators evaluate given true/false values. Let true = 1, false = 0 in the example.
And Evaluation
Value 1 Operator Value 2 Result
1 and 1 1
1 and 0 0
0 and 1 0
0 and 0 0

The table above illustrates that an argument that relies on 'and' will only evaluate to true when both sides of and evaluate to true. In the context of math, each side of the and must be '1' in order for the result to be '1', otherwise it is '0'. Keep this point in mind because it will be important for evaluating IPs and analyzing networks computationally. However, just for reference I'd like to throw in a table for 'or'. In the following example let True = 1, False = 0.
Or Evaluation
Value 1 Operator Value 2 Result
1 or 1 1
1 or 0 1
0 or 1 1
0 or 0 0

The above tables show a contrast between 'and' and 'or', in that only one value must evaluate to true for 'or' to evaluate to true, whereas both values must evaluate to true for 'and' to evaluate to true. However, if you ever need 'or' to evaluate to true whenever exactly one value is true, you can just use 'exclusive or'. Here's what that looks like below:
Xor/Exclusive Or Evaluation
Value 1 Operator Value 2 Result
1 xor 1 0
1 xor 0 1
0 xor 1 1
0 xor 0 0

Anywho, all of this is important because you use binary operators to find the important addresses in a subnetwork, which are the network address and broadcast address. First though, you need the subnet mask. They are commonly denoted in "slash" notation, which is a '/' followed by a number between 0-32, because an IPV4 address has 4 octets separated by periods. The number tells us how many bits are 'on', and an octet is just a value between 0-255. First let's get a look at the anatomy of an octet before we explore slash notation:
A single octet
27 26 25 24 23 22 21 20
1 0 1 0 0 0 0 0

The above octet's value is 160. This is because only the first and third bit are on (or set to 1). Now when you do that four times over you get a full IP. Every bit can either be 0 or 1, and you just add up the values. There is no special math or anything aside from the fact a bit can be either 0 or 1. So now, keeping in mind that a subnet mask follows the same rules as normal IPs there are going to be a total of 32 bits that can be 'turned on'. When you keep this in mind, and that the highest value an octet can have is 255 figuring out subnets can be very easy. Here is a pattern:
/8 = 255.0.0.0
/16 = 255.255.0.0
/24 = 255.255.255.0
/32 = 255.255.255.255

The amount of times 8 goes into a number (without a remainder) will tell you how many full octets are on. Keeping this trick in mind makes weird values like /27 easy to figure out too. Let's do it real quick. We know that 27 % 24 = 3, so 8 goes into 27 cleanly 3 times. As a result, our subnet mask will at least look like:
255.255.255.

Now, what about the final value? Well we know that 3 out of the 8 bits are on for that last value. I did not mention it previously, but we work backwards when doing the addition. That means we start at the 27 position and work towards 20. Therefore, the math for the final octet becomes: 27 + 26 + 25, which gives us 224. Therefore, the subnet mask is:
255.255.255.224/27

In the table below each individual octet is represented by a row. The first octet is the highest row, and the final octet is the lowest row. This is meant to help visualize how the subnet mask looks in terms of bits.
255.255.255.224/27
27 26 25 24 23 22 21 20
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 0 0 0 0 0

From here, we can figure out quite a few things. For example, since the highest possible value a slash subnetmask can have is 32, and ours is 27, we can work out how many computers can exist on this subnet. That equation was: 2n - 2, where n in this case will be (32 - 27). So let's work through the math real quick:
2(32 - 27) - 2
25 - 2
32 - 2
30

There can be 30 devices on this network, because two addresses are always reserved on any subnetwork for broadcasting messages to every device on the subnetwork, and for identification of the subnetwork. This information is also useful because it tells us what the reverse subnetmask will be.
If our subnet mask is: 11111111.11111111.11111111.111 00000
Then our reverse subnetmask will be: 00000000.00000000.00000000.000 11111

When you've got the 'n' in this equation, you can work backwards through the subnetmask setting the bits to 1 until you've hit n-bits. You don't even need the original subnet mask, I only used it to make a point. Onto the fun part, let's figure out the broadcast address for the following IP on a /27 subnetmask:
192.168.32.16

The first step is to figure out what this translates to in binary. This step is probably easier to just use the binary calculator, or on a piece of scratch paper. I have the answer below though just in case.
11000000.10101000.00100000.00010000

Now that we've done that, we can start to work on the math. BUT, before we do that, let's eyeball things real quick because there's a nice shortcut. Using the rule of 'or', we know that an equation will be true IFF at least one side is true. Likewise, it is false IFF both sides are false. This means, whenever we have a one we will keep that one, and whenever both sides are zero it will be unchanged. In other words, the first three octets of our IP will remain the same, because the reverse subnetmask is entirely zeroed out for those octets. So the only time we really need to work is on the final octet.
192.168.32.x

Now we have to find x, but that's easy!