A Quick And Simple Guide To CIDR IP4 Address Ranges

One of the things you’ll run up against, often, in the DevOps world is CIDR notations, like this:

10.0.0.0/16

It’s difficult for beginners to understand how many IP addresses that creates (65,536) or what the starting and ending address range will be (10.0.0.0 – 10.0.255.255).

I’ve looked around at the top results returned by a Google search for “CIDR notation tutorial” and the like, and all the results I’ve found haven’t been very plain-English or easy to follow. So here is my attempt to try to bring clarity, for the uninitiated, on how to understand CIDR notation.

Background: Octets and binary

The most important thing to understand about CIDR (Classless Inter-Domain Routing) notation for IP4 is that it works in octets, and it works in binary.

Take the example I provided initially:

10.0.0.0/16

That’s four groupings of numbers, each of which is 2^8 when expressed as a binary number. That is, the entire address range for IP4 is 0.0.0.0 to 255.255.255.255.

Thus, each of the four sections of an IP4 address is an octet of ones and zeros.

For example, I can convert 10.0.0.0 to binary, which is:

00001010.00000000.00000000.00000000

There are eight ones or zeros per grouping, or octet.

Knowing this, I can now understand CIDR notation.

Background: Netmasks

Actually, I need to understand one more thing to understand CIDR notation: netmasks.

As its name implies, a netmask is a way to mask — or restrict — the IP addresses that can be assigned to a given network.

The CIDR notation will tell us the netmask being used. More on this in a moment.

A netmask looks just like a normal IP address, except that the values in the netmask tell me how many addresses from each octet I can assign.

If I see a netmask of 0.0.0.0, that means I can assign every value from 0-255 in each octet. If I see a netmask of 255.0.0.0, that means I can use only the specified value for the first octet, but any other octet can be a number from 0 to 255. If I see a netmask of 255.255.128.0, then I know the first two octets cannot be changed, but the third octet can be any of 128 addresses around the starting address, and the fourth octet can be any value from 0 to 255.

For example, suppose I create a network that begins at 10.0.0.0 with a netmask of 255.255.255.0.

The first three octects in that netmask address — 255.255.255 — tell me that I cannot assign to any machine, within this network, an address starting with anything other than 10.0.0. Those first three octets are completely masked.

I can, however, assign any address to the machine from 10.0.0.0 to 10.0.0.255, because the fourth octet of the netmask — 0 — tells me there are no restrictions.

Let’s use that same starting address — 10.0.0.0 — but change the netmask to 255.255.255.128.

I am now being told that, as before, the first three octets of the address range — 10.0.0 — cannot be changed. And I am also being told that the fourth octet will allow me to assign, to a device, any address from 10.0.0.0 to 10.0.0.127.

Let’s change the netmask to 255.255.255.254.

Now I know that I can assign any address from 10.0.0.0 to 10.0.0.1. That’s because the netmask tells me that I can’t change the first three octets of the address, and the fourth octet only has two addresses available.

If I change the netmask to 255.255.255.255, then I can only assign one address to this network: 10.0.0.0

Finally, if I change the netmask to 255.128.0.0, then I know that I can’t change the first octet; the second octet will allow me to assign any address from 0 to 127; and the final two octets can be any address from 0 to 255, meaning my range is 10.0.0.0 to 10.127.255.255.

I hesitate to mention this, for fear of confusing you, but in the interests of accuracy, I must.

When it comes to the fourth octet of an IP4 address, the addresses of 0 and 255 (or the last address in a given range) are automatically assigned as the network and broadcast addresses, respectively. I won’t get into what these are, again because I don’t want to confuse the matter.

Suffice it to say, you don’t actually use an address of 10.0.0.0 or 10.0.0.255, because these addresses are reserved by the network.

Calculating the number of addresses in CIDR notation

Because CIDR works in binary, it is very easy to calculate the total number of addresses in a range.

There are 2^{32} possible addresses in IP4. That’s because there are four groups of eight binary numbers, and 4 x 8 = 32.

The /XX number in CIDR notation tells me the netmask I want to use. So, using our example:

10.0.0.0/16

I can subtract that netmask from the total number of available addresses in IP4, to get the number of addresses specified by the CIDR notation: 2^{32 - 16} = 2^{16} = 65,536

There are 65,536 addresses in 10.0.0.0/16.

Using this CIDR notation:

10.0.0.0/28

I find that 2^{32 - 28} = 2^{4} = 16; there are 16 addresses in that range.

And for this CIDR range:

10.0.0.0/4

There are 2^{32 - 4} = 2^{28} = 268,435,456; or about 268.5 million addresses in that range.

Determining the start and end addresses of a CIDR range

We calculate the start address for a CIDR range by comparing the binary value of the netmask to the binary value of the CIDR address.

Consider this example:

10.50.0.0/14

The netmask for that range, in binary, is:

11111111.11111100.00000000.00000000

Now, I want to convert my CIDR address of 10.50.0.0 to binary:

00001010.00110010.00000000.00000000

Let’s line those up, so that the netmask is atop the CIDR address:

11111111.11111100.00000000.00000000
00001010.00110010.00000000.00000000

Again, the netmask is the top line, the specified CIDR address is the second line.

Now, I compare the ones and zeros in the netmask to the ones and zeros in the CIDR address. To find the starting address of my IP range, anyplace where I have a 0 in the netmask, I want to make that a 0 in the CIDR address. Like this:

11111111.11111100.00000000.00000000
00001010.00110000.00000000.00000000

Note that the CIDR address went from 00001010.00110010.00000000.00000000 to 00001010.00110000.00000000.00000000. When I convert that back to a decimal, I get:

10.48.0.0

Therefore, I know that this range will begin at 10.48.0.0.

I also know that there will be 262,144 addresses in this range; 2^{32 - 14} = 2^{18} = 262,144.

If I divide that number by 65,536 — which is the number of addresses available in the third and fourth octets — I get 4 (262,144 / (256 * 256) = 4).

So, if I start from 10.48.0.0, I need to go through all the addresses in the third and fourth octets four times, in order to get all 262,144 addresses in. Or, in other words, my range is 10.48.0.0 to 10.51.255.255.

Complex CIDR ranges

OK, let’s look at a more complicated range:

10.1.16.6/28

I know that the netmask in this case is going to be, in binary:

11111111.11111111.11111111.11110000

That is, only the last four digits will be subject to change.

To get the starting address, I compare the binary netmask against the binary CIDR address:

11111111.11111111.11111111.11110000
00001010.00000001.00010000.00000110

Anyplace where the netmask has a zero, I change the CIDR address value to 0:

11111111.11111111.11111111.11110000
00001010.00000001.00010000.00000000

And then I convert that CIDR address back to decimal, to get my starting IP address:

10.1.16.0

And since I know there are 16 addresses in this range, I know my full range for this netblock will be 10.1.16.0 – 10.1.16.15.

Overrunning the specified starting address

What ultimately matters in a CIDR range is the netmask; or the /XX number. This can easily override the value you specify in your CIDR address.

Consider this:

10.220.200.20/10

That’s going to result in about 4.2 million addresses: 2^{32 - 10} = 2^{22} = 4,194,304.

When I convert /10 to a binary netmask, I get:

11111111.11000000.00000000.00000000

I compare the netmask against the CIDR address:

11111111.11000000.00000000.00000000
00001010.11011100.11001000.00010100

and change all the ones in the CIDR address to 0, wherever there’s a zero in the netmask:

11111111.11000000.00000000.00000000
00001010.11000000.00000000.00000000

When I convert that altered CIDR address back to decimal, I get:

10.192.0.0

Which is my starting address; my ending address will be 10.255.255.255, to fit all 4.2 million addresses in.

Note that this is an earlier starting address than 10.220.200.20, which we passed in as the CIDR address.

Because what matters is the /10, which assigns too many addresses to start at 10.220.200.20, a CIDR-compliant system will start the address range at 10.192.0.0, overriding our CIDR address.

Conclusion

So, to recap:

  • CIDR notation is interpreted as binary numbers.
  • In an IP4 address, there are four octets, which represent a range of addresses from 0.0.0.0 to 255.255.255.255. This is  2^{32} addresses, total.
  • I can subtract the /XX number from 2^{32} to get the number of IP addresses in the range, e.g., 10.0.0.0/16 is 2^{32 - 16} = 2^{16} = 65,536 addresses.
  • I can find the netmask by typing out a 32-bit number, where the /XX of the CIDR notation is the leading number of ones in that number; e.g., 10.0.0.0/16 = 11111111.11111111.00000000.00000000 = 255.255.0.0.
  • I can find the starting IP address for a CIDR range by comparing the binary value of the netmask to the binary value of the CIDR address. Any position in the netmask where there is a 0, I want to change the corresponding position of the CIDR address to 0. When I convert that transformed CIDR address back to decimal, I will have the starting address for the range.

A couple of shoutouts. I made extensive use of two websites when writing this post: The CIDR Utility Tool at ipaddressguide.com, and the network calculators at subnetmask.info. Many thanks to their creators and maintainers for making me look a lot better at math than I actually am.

That’s it for this post. Comments, questions, etc. are welcome; use the form below.

Feature photo by geralt via pixabay, in the public domain.

Leave a Reply

  • Check out the Commenting Guidelines before commenting, please!
  • Want to share code? Please put it into a GitHub Gist, CodePen or pastebin and link to that in your comment.
  • Just have a line or two of markup? Wrap them in an appropriate SyntaxHighlighter Evolved shortcode for your programming language, please!