Networking
Subnetting and CIDR
Slicing 32 bits into networks and hosts — at any bit boundary
Subnetting divides a 32-bit IPv4 address space into smaller networks by moving the boundary between the leading network bits and the trailing host bits. CIDR — Classless Inter-Domain Routing, standardized in RFC 1519 in 1993 — writes that boundary as a prefix length: 10.0.0.0/24 means the first 24 bits identify the network, leaving 8 host bits for 256 addresses (254 usable). The same arithmetic run backward (a shorter prefix) aggregates many routes into one. CIDR replaced the rigid classful A/B/C scheme and is the reason the global routing table did not collapse under its own weight in the 1990s.
- Address width32 bits (IPv4)
- Prefix range/0 to /32
- Usable hosts2^(32 − prefix) − 2
- /24 mask255.255.255.0 · 254 hosts
- StandardRFC 1519 (1993), updated RFC 4632
- Longest-prefix matchO(W) or O(log W), W = 32
Interactive visualization
Press play, or step through manually. The visualization is yours to drive — try it before reading on.
Watch the 60-second explainer
A condensed visual walkthrough — narrated, captioned, under a minute.
Network bits versus host bits
Every IPv4 address is a single unsigned 32-bit integer, written for humans as four dotted decimal octets — 192.168.10.130 is really the number 0xC0A80A82. CIDR draws one vertical line through those 32 bits. Everything to the left is the network prefix (shared by every host on the link); everything to the right is the host part (unique per host). The prefix length after the slash says exactly where the line falls.
The subnet mask is that same line expressed as a bitmask: a contiguous run of 1s for the network bits followed by 0s for the host bits. A /24 is 11111111.11111111.11111111.00000000 = 255.255.255.0. Because the 1s must be contiguous, only 33 masks are legal (/0 through /32), which is why the fourth octet of a mask is always one of the eight "magic numbers": 128, 192, 224, 240, 248, 252, 254, 255.
Given an address and a prefix, three addresses are mechanically determined:
- Network address — address
ANDmask (all host bits cleared). It names the subnet and is never assigned to a host. - Broadcast address — the network with all host bits set. A packet here reaches every host on the link; also not assignable.
- Usable range — everything strictly between them. That is why usable hosts =
2^(32 − prefix) − 2.
Why CIDR matters: two crises it defused
Before 1993, addresses were classful. The first few bits of an address fixed its class and therefore its prefix: Class A was /8 (16.7M hosts), Class B was /16 (65,534 hosts), Class C was /24 (254 hosts). This created two simultaneous emergencies:
- Address exhaustion. An organization with 500 machines was too big for a Class C (254) and had to take a whole Class B (65,534), wasting ~99% of it. Class B space was running out fast in the early 1990s.
- Routing table explosion. Handing out thousands of tiny Class Cs instead meant thousands of separate routes flooding the backbone. The BGP table growth curve threatened to outrun router memory.
CIDR fixed both by letting the prefix fall on any bit. The 500-host org gets a right-sized /23 (510 usable). And an ISP that owns 203.0.16.0/24 through 203.0.19.0/24 advertises a single aggregate 203.0.16.0/22 to the rest of the world — one route instead of four. This is prefix aggregation, and it is the reason the global table grew linearly instead of exponentially.
Working an example by hand: 192.168.10.130 /26
A /26 means 26 network bits and 6 host bits. Only the fourth octet is interesting — the first three are fully inside the network prefix. The mask's fourth octet is 11000000 = 192, so the mask is 255.255.255.192. The "magic number" (block size) is 256 − 192 = 64: subnets start at .0, .64, .128, .192.
- Which block? 130 falls in the
128–191block. Network address =192.168.10.128(from130 AND 192 = 128). - Broadcast: set all 6 host bits →
192.168.10.191. - Usable range:
192.168.10.129to192.168.10.190— that is2^6 − 2 = 62hosts.
Splitting the parent 192.168.10.0/24 into /26s yields exactly four equal subnets (.0/26, .64/26, .128/26, .192/26), each 64 addresses, each 62 usable. That equal split is the simple case; the interesting one is VLSM.
VLSM: unequal subnets in one block
Real networks are lumpy — a big user LAN, a couple of small server segments, and several two-address router links. Splitting a /24 into equal pieces wastes addresses on the tiny links. Variable-Length Subnet Masking (VLSM) lets each subnet pick its own prefix. The discipline is: allocate largest-first, and keep every subnet aligned to a multiple of its own size. Carving 192.168.10.0/24 for one 100-host LAN, one 50-host LAN, and two point-to-point links:
| Requirement | Prefix | Block size | Network | Usable range | Broadcast |
|---|---|---|---|---|---|
| LAN A (100 hosts) | /25 | 128 | .0 | .1 – .126 | .127 |
| LAN B (50 hosts) | /26 | 64 | .128 | .129 – .190 | .191 |
| Servers (14 hosts) | /28 | 16 | .192 | .193 – .206 | .207 |
| Link 1 (2 hosts) | /30 | 4 | .208 | .209 – .210 | .211 |
| Link 2 (2 hosts) | /30 | 4 | .212 | .213 – .214 | .215 |
Largest-first prevents the classic VLSM bug — placing a small subnet first so that no aligned slot remains for a larger one later. Note each network number is a multiple of its block size (128, 64, 16, 4), which is what keeps the ranges from overlapping.
Classful versus classless (CIDR)
| Classful (A/B/C) | CIDR (classless) | |
|---|---|---|
| Boundary | Fixed at /8, /16, /24 by address class | Any bit, /0 – /32 |
| Mask carried in routing? | No — inferred from class | Yes — prefix travels with the route |
| Allocation granularity | 256 / 65,536 / 16.7M | Right-sized to a power of two |
| Aggregation | Impossible | Contiguous prefixes merge (supernetting) |
| Routing-table impact | Explosive growth | Aggregated, near-linear |
| Standard | RFC 791 (1981) | RFC 1519 (1993) / RFC 4632 (2006) |
Supernetting and longest-prefix match
Supernetting is subnetting in reverse: shorten the prefix to swallow adjacent blocks. Four contiguous /24s whose base is aligned to a /22 boundary (e.g. .16, .17, .18, .19) collapse into one 203.0.16.0/22. Aggregation only works when the blocks are numerically contiguous and the combined block is aligned — you cannot merge .17 and .18 alone into a valid CIDR block.
Because a router can now hold both a broad aggregate and a more specific carve-out, forwarding uses longest-prefix match (LPM): among all routes that contain the destination, pick the one with the most network bits. A packet to 203.0.17.5 matching both 203.0.16.0/22 and 203.0.17.0/24 follows the /24 — the more specific route wins. A naive linear scan is O(N) over N routes; production routers use a binary trie / PATRICIA structure for O(W) with W = 32 bits, or a multibit / Lulea-compressed trie for even fewer memory accesses.
Implementation: CIDR math in Python
def parse_ip(s):
a, b, c, d = (int(x) for x in s.split('.'))
return (a << 24) | (b << 16) | (c << 8) | d # 32-bit int
def ip_str(n):
return '.'.join(str((n >> sh) & 0xFF) for sh in (24, 16, 8, 0))
def subnet_info(cidr):
addr_s, prefix_s = cidr.split('/')
addr, prefix = parse_ip(addr_s), int(prefix_s)
# mask: `prefix` leading 1s in a 32-bit word
mask = (0xFFFFFFFF << (32 - prefix)) & 0xFFFFFFFF if prefix else 0
network = addr & mask # host bits cleared
broadcast = network | (~mask & 0xFFFFFFFF) # host bits set
total = 1 << (32 - prefix)
usable = max(total - 2, 0) if prefix <= 30 else total # RFC 3021 for /31
return {
'network': ip_str(network),
'broadcast': ip_str(broadcast),
'mask': ip_str(mask),
'first': ip_str(network + 1) if prefix <= 30 else ip_str(network),
'last': ip_str(broadcast - 1) if prefix <= 30 else ip_str(broadcast),
'usable': usable,
}
# Longest-prefix match over a routing table of (cidr, next_hop)
def lpm(dest_ip, table):
d = parse_ip(dest_ip)
best, best_len = None, -1
for cidr, hop in table:
net_s, pfx = cidr.split('/'); pfx = int(pfx)
mask = (0xFFFFFFFF << (32 - pfx)) & 0xFFFFFFFF if pfx else 0
if (d & mask) == (parse_ip(net_s) & mask) and pfx > best_len:
best, best_len = hop, pfx # most-specific match wins
return best
print(subnet_info('192.168.10.130/26'))
# {'network': '192.168.10.128', 'broadcast': '192.168.10.191',
# 'mask': '255.255.255.192', 'first': '192.168.10.129',
# 'last': '192.168.10.190', 'usable': 62}
The whole subject is bitwise AND/OR against a mask that is nothing more than prefix leading 1s. Everything else — network, broadcast, host count, aggregation — falls out of that one operation.
Common misconceptions and pitfalls
- Assuming a mask can have non-contiguous 1s. Legal masks are always contiguous 1s then 0s.
255.255.0.255is not a valid subnet mask (though such "wildcard" patterns exist in ACLs, which use an inverted mask). - Forgetting the two reserved addresses. A
/29is 8 addresses but only 6 hosts. Sizing a link for exactly a power of two and then losing the network and broadcast is the most common off-by-two. - Misaligning subnets in VLSM. A subnet must start on a multiple of its block size. Placing a
/26at.32is illegal — 32 is not a multiple of 64. Allocate largest-first to avoid painting yourself into a corner. - Trying to aggregate non-contiguous or unaligned blocks.
10.0.1.0/24and10.0.3.0/24cannot merge — they are not adjacent and the pair is not/23-aligned. - Confusing /31 handling. On modern gear a
/31point-to-point link (RFC 3021) has two usable addresses and no broadcast; older stacks reject it and force a/30.
Frequently asked questions
How many usable hosts are in a /24 subnet?
A /24 has 8 host bits, so 2^8 = 256 total addresses. Two are reserved: the all-zeros host is the network address (e.g. 192.168.1.0) and the all-ones host is the directed broadcast (192.168.1.255). That leaves 254 usable host addresses. The general formula is 2^(32 − prefix) − 2 usable hosts, valid for prefixes of /30 or shorter.
What is the subnet mask for a /26?
A /26 sets the first 26 bits to 1. In dotted-decimal that is 255.255.255.192, because the fourth octet is 11000000 = 192. A /26 splits a /24 into four subnets of 64 addresses each (62 usable). The value 192 is one of the eight 'magic numbers' derived from the boundary bit: 128, 192, 224, 240, 248, 252, 254, 255.
What is the difference between subnetting and supernetting?
Subnetting lengthens the prefix (borrows host bits) to carve one block into smaller networks — a /24 becomes four /26 subnets. Supernetting, also called route aggregation, shortens the prefix (borrows network bits) to combine several adjacent, numerically contiguous blocks into one advertisement — four /24s that share a /22-aligned base become a single /22. Both are the same CIDR arithmetic run in opposite directions.
Why did CIDR replace classful A/B/C addressing?
Classful addressing fixed the network boundary at /8 (Class A), /16 (Class B), or /24 (Class C). An organization needing 500 hosts had to take a full Class B of 65,534 addresses, wasting ~99%, while Class B exhaustion loomed and the routing table exploded. CIDR (RFC 1519, 1993) let the prefix fall on any bit boundary, so that organization gets a right-sized /23 (510 usable), and providers aggregate customer routes into single entries — directly slowing IPv4 exhaustion and BGP table growth.
What is VLSM and why does it matter?
VLSM (Variable-Length Subnet Masking) means using different prefix lengths within one parent block instead of splitting it into equal pieces. A /24 can hold a /25 for 126 hosts, two /27s for 30 hosts each, and several /30 point-to-point links (2 usable) all at once. The rule: allocate largest-first and keep each subnet aligned to its own size boundary so ranges never overlap.
How do I find the network address from an IP and a mask?
Bitwise-AND the 32-bit address with the 32-bit mask. For 192.168.10.130 with mask /26 (255.255.255.192), only the last octet matters: 130 AND 192 = 128, so the network address is 192.168.10.128. The broadcast address is the network with all host bits set: 192.168.10.191. The usable range is 192.168.10.129 through 192.168.10.190.
Why does a point-to-point link use a /31 or /30?
A /30 gives 4 addresses — network, broadcast, and exactly 2 usable hosts — a perfect fit for the two ends of a router-to-router link. To save the two reserved addresses, RFC 3021 defines /31 links: with 1 host bit there is no distinct network or broadcast address, and both addresses are treated as usable endpoints. A /32 is a single-host route, common for loopbacks and host-specific entries.