How cidrsubnet works in Terraform

Nadeen Nilanka
6 min readNov 13, 2019

As you might already know by using cidrsubnet you can calculate a subnet by given network address prefix in Terraform.

However if you are like me who is not that much a geek about network subnets/netmasks/CIDRs ..etc, you might feel a little bit magical when you use this function. How the hell that subnet got generated 🤔 There is an almost-good example in the documentation but I couldn’t grasp fully. Specially the netnum part. So I spent little time to understand how this actually works and how these parameters relate to each other. If you have the same magical feeling may be this article helps you to understand how this function works.

cidrsubnet(prefix, newbits, netnum)

How it’s in the documentation.

  • prefix = must be given in CIDR notation, as defined in RFC 4632 section 3.1.
  • newbits = is the number of additional bits with which to extend the prefix. For example, if given a prefix ending in /16 and a newbits value of 4, the resulting subnet address will have length /20.
  • netnum = is a whole number that can be represented as a binary integer with no more than newbits binary digits, which will be used to populate the additional bits added to the prefix.

First and second params are self-explanatory and easy to understand. However the third, yeah it went over my head too. Don’t worry little later we will go through few examples then you will understand the logic behind the netnum and relation to prefix and newbits. Before that we need to know the structure of CIDR notation. Let’s have a look that first!

Understanding Network and Host portion

Take 10.1.0.0/24 as the example.

CIDR notation has 2 parts: network portion and the host portion. Let’s get the 10.1.0.0 and write it in binary and find out these 2 parts there.
Note: Counting binary is starting from right.

Our current suffix is 24 which means 24 bits out of 32 is allocated for the network portion and remaining 8 bits are for the host portion.

Understanding relation of params

cidrsubnet(“10.1.0.0/24”, 4, 10)

As in the function suffix needs to be extended with another 4bits(newbits) so current network portion(/24) + newbits(4) = /28 which means we add 4 more bits to the network portion.

Before extend

After extended with 4 bits of newbits

Definition: is a whole number that can be represented as a binary integer with no more than newbits binary digits, which will be used to populate the additional bits added to the prefix.

Would be easy to think as: an integer could represent from newbits.

Let’s grab these newbits and find little bit more about netnum We have 4 newbits, ignore current position in the octals of the CIDR, as you see below with 4 bits possible maximum decimal value is 15 and minimum is 0.

Hmm so? It means with given parameters maximum value that you can use as netnum is 15 and minimum is 0. Ok if i put 16 i should get error ha? Let’s try in terraform console and check.

Ok seems legit!

As you see: you can have 16 subnets(by using netnum 0–15) with /28 suffix. You can verify with ipcalc command ipcalc 10.1.0.0/24 /28 it will show how many subnets are available. Let’s go through examples and understand how exactly these subnets get return with given parameters.

Example number one:

cidrsubnet(“10.1.0.0/24”, 4, 10)

Step 1: Binary representation with newbits. Little explanation about below 0s and 1s.

  1. Current network portion (24bits before the newbits)
  2. Then newbits (orange color bits)
  3. Final Host portion (after orange color bits)

Step 2: Reset those newbits to 0s, if there are any 1s, since here no 1s nothing to change.
for ex:

Step 3: Let’s represent 10(netnum) in newbits yes ignore current position in the octal.

Step 4: Now get the result as octals and convert to decimal(counting binary is starting from right).

Here you go, your subnet is 10.1.0.160/28

Example number two:

cidrsubnet(“10.1.0.0/24”, 4, 13)

Step 1: Binary representation with newbits.

Step 2: Let’s reset those newbits if there are any 1s, since here no 1s nothing to change. Cool let’s move on!

Step 3: Now represent 13(netnum) in newbits Note: Ignore current position in the octal. We just need bits!

Step 4: Now get the binary representation as octals and convert to decimal(counting binary is starting from right).

is it true? yes it is!

ok! this is boring give me a harder one 🤓 how about newbits spread among 2 octals.

Example number three:

cidrsubnet(“10.121.0.0/20”, 5, 11)

Step 1: Binary representation with newbits.
Note: newbits spreading between 2 octals.

Step 2: Let’s reset those newbits if there are any 1s, nope nothing to change.

Step 3: Now represent 11(netnum) in newbits Note: Ignore current position in the octal. We just need bits!

Cool we are getting better with this!

Last step result time: Now get the binary representation as octals and convert to decimal(counting binary is starting from right).

ok next please!

Last one:

cidrsubnet(“10.121.20.0/21”, 8, 14)

Step 1: Binary representation with newbits this one is cool: spread among 2 octals and we have 1s.

Step 2: Let’s reset those newbits if there are already 1s, yep we have a 1 here!

Step 3: Now represent 14(netnum) in newbits Note: Ignore current position in the octal. We just need bits!

Now: convert octals to decimal(counting binary is starting from right).

Cool it seems you got the logic!

So result is 10.121.16.112/29 great 👏🏻

Yep that was it, job done! Now hopefully you don’t feel anymore magical when you use cidrsubnet and hope this helps to clear your confusion. Please let me know if i missed anything or i got something wrong. Thank you very much for come this far fellow human beings ✌️ Happy Terraforming!

--

--