Subnetting: Splitting an Address Space
10.0.0.0/24 is 256 addresses with 254 usable; move the mask one bit right and it becomes two /25s of 128 — subnetting is prefix arithmetic, and it exists to bound broadcast domains, draw security boundaries and let routers aggregate many networks into one route.
The problem
10.0.0.0/24 and three teams that must not share a broadcast domain, plus a router that wants one route for all of them. How do you cut one block of addresses into several networks, and what do you lose at every cut?Anatomy of one subnet
10.0.0.0/24 says: the first 24 bits are fixed (10.0.0), the last 8 vary. 2^8 = 256 addresses, from 10.0.0.0 to 10.0.0.255. Two are reserved — all host bits zero is the network address 10.0.0.0, all host bits one is the broadcast address 10.0.0.255 — leaving 254 usable host addresses, 10.0.0.1 through 10.0.0.254. By convention the router takes .1 (or .254); nothing enforces it.
The general formulas: a /n has 2^(32−n) addresses and 2^(32−n) − 2 usable hosts. The mask in dotted form is n ones followed by zeros: /24 = 255.255.255.0, /25 = 255.255.255.128, /26 = 255.255.255.192, /27 = 255.255.255.224, /28 = 255.255.255.240, /30 = 255.255.255.252 (4 addresses, 2 usable — a point-to-point link), /31 (2 addresses, both usable on point-to-point links per RFC 3021), /32 (one host). Network address = addr AND mask; broadcast = addr OR NOT mask. Everything else in subnetting is this arithmetic.
10 .0 .0 .x
/24 mask 11111111 .11111111 .11111111 .00000000 256 addrs, 254 usable
network 00001010 .00000000 .00000000 .00000000 10.0.0.0
broadcast 00001010 .00000000 .00000000 .11111111 10.0.0.255
split: borrow one host bit → two /25s
/25 mask 11111111 .11111111 .11111111 .10000000 128 addrs each, 126 usable
subnet A 00001010 .00000000 .00000000 .0xxxxxxx 10.0.0.0/25 hosts .1–.126, bcast .127
subnet B 00001010 .00000000 .00000000 .1xxxxxxx 10.0.0.128/25 hosts .129–.254, bcast .255
split again: /26 → four subnets of 64 (62 usable)
10.0.0.0/26 .0–.63 10.0.0.64/26 .64–.127
10.0.0.128/26 .128–.191 10.0.0.192/26 .192–.255Splitting: borrow a bit, double the count, halve the size
To split 10.0.0.0/24 into two, extend the mask by one bit: the 25th bit becomes part of the network, and its two values name two subnets — 10.0.0.0/25 (bit is 0, addresses .0–.127) and 10.0.0.128/25 (bit is 1, addresses .128–.255). Each has 128 addresses and 126 usable, because each now pays its own network and broadcast address. Split again to /26 and you have four subnets of 64 (62 usable) at .0, .64, .128, .192. Every bit borrowed doubles the number of subnets, halves their size, and costs two more reserved addresses in total.
The intuition that makes this fast in an interview: the size of a /n subnet in the last octet is 256 ÷ 2^(n−24), and subnets start at multiples of that size. /26 → 64, so boundaries are .0, .64, .128, .192. /27 → 32, boundaries every 32. /28 → 16. To find which /26 contains 10.0.0.150: 150 ÷ 64 = 2 remainder 22, so it is in the third block, 10.0.0.128/26, with broadcast .191. No binary needed once the block size is known.
| Prefix | Mask (last octet) | Addresses | Usable hosts | Block size / boundaries |
|---|---|---|---|---|
| /24 | 255.255.255.0 | 256 | 254 | 256 — one block |
| /25 | 255.255.255.128 | 128 | 126 | .0, .128 |
| /26 | 255.255.255.192 | 64 | 62 | .0, .64, .128, .192 |
| /27 | 255.255.255.224 | 32 | 30 | every 32 |
| /28 | 255.255.255.240 | 16 | 14 | every 16 |
| /29 | 255.255.255.248 | 8 | 6 | every 8 |
| /30 | 255.255.255.252 | 4 | 2 | point-to-point links |
| /31 | 255.255.255.254 | 2 | 2 (RFC 3021) | point-to-point, no broadcast |
| /32 | 255.255.255.255 | 1 | 1 | a single host route |
| /16 | 255.255.0.0 | 65,536 | 65,534 | a whole second octet |
| /8 | 255.0.0.0 | 16,777,216 | 16,777,214 | 10.0.0.0/8 |
VLSM: subnets of different sizes
Nothing says the pieces must be equal. Variable-length subnet masking lets you carve 10.0.0.0/24 into one /25 for 100 workstations (.0–.127), one /26 for 50 servers (.128–.191), one /27 for 20 printers (.192–.223), and a handful of /30s for router links (.224–.227, .228–.231, …), leaving the rest free. The rule is only that each subnet starts on a multiple of its own size and none overlap. Allocate the largest first, from the bottom, so that the leftover is contiguous and can itself be aggregated later.
Cloud VPCs are VLSM in practice: a /16 VPC (10.0.0.0/16) split into /20 or /24 subnets per availability zone and tier. Kubernetes does the same one level down — a pod CIDR of 10.244.0.0/16 from which each node takes a /24 — which is why a cluster’s maximum size is set by prefix arithmetic (256 nodes × 254 pods) before anything else runs out. The reverse operation, aggregation (supernetting), is what routers do: 10.0.0.0/25 and 10.0.0.128/25 are advertised upstream as one 10.0.0.0/24, and the whole of a company’s 10.0.0.0/8 is one line in someone else’s table.
Why subnets exist at all
The first reason is the broadcast domain. Every ARP request, DHCP discover and mDNS announcement reaches every host in a subnet; at a few hundred hosts the background chatter is measurable, at a few thousand it is a problem, and a single misbehaving NIC can take the whole segment with it. Subnets bound the blast radius. The second is security and policy: a router or firewall between subnets is a place to say "the guest network may reach the internet and nothing else", "only the bastion may reach the database subnet". Without a subnet boundary there is no place to put the rule — hosts on one segment talk to each other directly, past any firewall. The third is route aggregation: a subnet is one line in a routing table, and a hierarchy of subnets is one line per level, which is the only reason the internet’s core table (~1 million IPv4 prefixes) is not four billion entries.
The cost is address waste — every subnet burns two addresses and rounds up to a power of two — and the operational friction of moving a host between subnets (new address, new gateway, firewall rules). IPv6 removes the first cost entirely by giving every subnet a /64 with 2^64 addresses: subnetting there is purely about topology and policy, never about running out.
Key points
- A
/nhas 2^(32−n) addresses and two fewer usable: network (host bits 0) and broadcast (host bits 1)./24→ 256 / 254. - Borrow one host bit to split in two:
/24→10.0.0.0/25and10.0.0.128/25, 126 usable each. Every borrowed bit doubles the count and halves the size. - Block size in the last octet = 256 ÷ 2^(n−24):
/26→ 64, boundaries at .0, .64, .128, .192. Find a host’s subnet by integer division. - VLSM: unequal pieces, each aligned to its own size and non-overlapping; largest first.
- Subnets exist to bound broadcast domains, to give firewalls a boundary, and to let routes aggregate.
- Network =
addr & mask; broadcast =addr | ~mask; on-link test =(dst & mask) == network.
Why does this exist?
Mechanisms are answers to constraints. Open each question before reading the answer.
▸Why are two addresses per subnet unusable?
The all-zeros host part names the subnet in routing tables and configuration; the all-ones host part is the directed broadcast every host must receive. Both are conventions old enough that stacks and tools assume them; /31 on point-to-point links is the one sanctioned exception.
▸Why powers of two?
Because the boundary between network and host is a bit position, and a bit position can only halve. It is the price of making the on-link test a single AND and the routing lookup a prefix match.
▸Why not one huge flat network?
Broadcast traffic, one failure domain, no place for a firewall, and no way to summarise routes. Every one of those becomes visible somewhere between 500 and 5,000 hosts.
Subnet calculator
addr 00001010.00000000.00000000.00000000
mask 11111111.11111111.11111111.00000000
net 00001010.00000000.00000000.00000000 ← addr AND mask
^^^^^^^^^^^^^^^^^^^^^^^^^^ 24 network bits, 8 host bits00001010.00000000.00000000.10000010 10.0.0.130 11111111.11111111.11111111.00000000 AND mask 00001010.00000000.00000000.00000000 = 10.0.0.0 == network ✓
/24 255.255.255.0 256 addrs 254 usable /25 255.255.255.128 128 addrs 126 usable /26 255.255.255.192 64 addrs 62 usable /27 255.255.255.224 32 addrs 30 usable /28 255.255.255.240 16 addrs 14 usable /29 255.255.255.248 8 addrs 6 usable /30 255.255.255.252 4 addrs 2 usable /31 255.255.255.254 2 addrs point-to-point (RFC 3021) /32 255.255.255.255 1 addr a single host route
How it fails
What the failure looks like from inside real software.
- Overlapping subnets:
10.0.0.0/24on one VLAN and10.0.0.128/25on another; hosts in the overlap are reachable from one side only, depending on which route is more specific. - Off-by-one on the boundary: assigning
10.0.0.128as a host in10.0.0.0/25— it is the broadcast address of that subnet and the network address of the next. - A
/30for a link that later needs a third device (an HA pair plus a monitor): renumber, or use a/29from the start. - Pod CIDR exhaustion: a Kubernetes cluster with a
/16pod range and/24per node cannot exceed 256 nodes, whatever the compute budget says. - Peering two VPCs that both chose
10.0.0.0/16: routes conflict; the only fixes are NAT or renumbering one side.