Subnets and CIDR, the way they finally clicked
Once you stop memorising masks and start counting bits, the whole thing collapses into arithmetic you can do on a napkin.
For years I treated subnet masks as incantations. I knew that /24 meant 255.255.255.0 the way I knew a phone number — by rote, with no idea what produced it. Then someone made me write an address out in binary, and the mystery evaporated in about ninety seconds. The thing nobody had told me is that subnetting isn't a topic. It's counting. What follows is the model I wish I'd been handed first.
An address is thirty-two bits
An IPv4 address is a 32-bit number. We write it as four decimal octets separated by dots — 192.168.10.130 — purely because thirty-two ones and zeros are miserable to read aloud. Each octet is eight bits, so each one is a value from 0 to 255. The dots are punctuation, nothing more. Underneath, it is one unbroken run of bits:
192 168 10 130
11000000 . 10101000 . 00001010 . 10000010
└────────────── 32 bits total ──────────────┘
Every address lives somewhere in that flat 32-bit space. Subnetting is the act of drawing a line through the bits and declaring: everything to the left of this line names the network; everything to the right names a host inside it. That line is the only idea here. The prefix length is where you put it, and the mask is how you describe it.
The prefix is the line; the mask is its shadow
The CIDR notation 192.168.10.0/24 reads as plainly as it looks once you know the trick: the /24 says the first 24 bits are the network. That is the whole definition. The remaining 32 − 24 = 8 bits are free to address hosts. Eight host bits give 2⁸ = 256 distinct combinations, which is why a /24 spans 256 addresses.
The dotted-decimal mask is just that same line painted onto an address: set every network bit to 1 and every host bit to 0, then read the result back out in decimal. Twenty-four ones followed by eight zeros is 11111111.11111111.11111111.00000000, which is 255.255.255.0. The mask and the prefix length are two spellings of one fact. The prefix counts the bits; the mask shows you where they fall.
Each extra bit halves the space
Here is where it becomes mechanical, and mechanical is good. Moving the line one bit to the right — from /24 to /25 — borrows a bit from the host side and hands it to the network. You have one fewer host bit, so the address space is cut in half: 256 becomes 128. Do it again for /26 and you halve once more, to 64. Every step right is a division by two.
Run that the other way and it is just as tidy. Each step left doubles the block. So the sequence of block sizes 256, 128, 64, 32, 16, … is nothing but powers of two walking down from the octet boundary. Once you internalise the doubling, you stop looking masks up; you derive them.
| Prefix | Dotted-decimal mask | Usable hosts | Block size |
|---|---|---|---|
/24 | 255.255.255.0 | 254 | 256 |
/25 | 255.255.255.128 | 126 | 128 |
/26 | 255.255.255.192 | 62 | 64 |
/27 | 255.255.255.224 | 30 | 32 |
/28 | 255.255.255.240 | 14 | 16 |
/30 | 255.255.255.252 | 2 | 4 |
The usable count is always two short of the block size, for the network and broadcast addresses reserved above — except in the corners of the table that don't apply here. A /30, with its two usable addresses, is the workhorse of point-to-point links: exactly enough for the device on each end and not one address wasted.
A rule of thumb for the last octet
When the line falls inside the final octet, as it does for everything in that table, there is a shortcut worth committing to memory. It turns the mask and the block size into each other without a single bit written down.
Block size equals 256 minus the mask octet. A mask of
the only subnetting formula I actually memorised.192gives a block of256 − 192 = 64; a mask of.240gives256 − 240 = 16.
That block size is also your step: the spacing between consecutive networks of that size. Subnets of a given prefix begin at multiples of their block size and nowhere else. A /26 has a block of 64, so the valid /26 networks in 192.168.10.0/24 start at .0, .64, .128, and .192 — and never, say, at .40. The arithmetic decides the boundaries; you don't get to pick them.
Worked example: carving a /24 into four /26s
Suppose you have 192.168.10.0/24 and want four equal subnets — one each for trusted hosts, IoT, guests, and management. Four equal pieces of 256 addresses means 64 per piece, and 64 is the block size of a /26. So you are cutting two bits off the host side: /24 plus two bits is /26. Step by the block size of 64 and read off the ranges:
# mask 255.255.255.192 · block 64 · 62 usable each
192.168.10.0/26
network 192.168.10.0
hosts 192.168.10.1 .. 192.168.10.62
broadcast 192.168.10.63
192.168.10.64/26
network 192.168.10.64
hosts 192.168.10.65 .. 192.168.10.126
broadcast 192.168.10.127
192.168.10.128/26
network 192.168.10.128
hosts 192.168.10.129 .. 192.168.10.190
broadcast 192.168.10.191
192.168.10.192/26
network 192.168.10.192
hosts 192.168.10.193 .. 192.168.10.254
broadcast 192.168.10.255
Notice the pattern, because it holds for every subnet you will ever split. The network address is the start of the block. The broadcast is one below the next block's start — the all-ones host. The usable range is everything strictly between them. And the four broadcasts, .63 / .127 / .191 / .255, are each one less than a multiple of 64. The blocks tile the /24 exactly, end to end, with no gap and no overlap, because that is what powers of two do.
What actually clicked
The shift, for me, was giving up on masks as things to recall and treating them as things to derive. The address is bits. The prefix is where the network ends. The mask is the same line in decimal. Each bit you move right halves the hosts and doubles the count of subnets, and inside a single octet the block size is simply 256 minus the mask value. Hold those four facts and you can carve any block on the back of a napkin — which, more often than I'd like to admit, is exactly where the network gets designed.