A working engineer's guide

Subnetting, from first principles to fluent.

No memorized tables. By the end you'll look at 172.16.77.200/26 and read off the network, the broadcast, the host range and the host count in under ten seconds — in your head.

network bits host bits borrowed (subnet) bits

00Why subnetting exists

An IPv4 address is just a 32-bit number — about 4.3 billion of them. Early on, addresses were handed out in three rigid sizes (the old "classes"): a Class A block held ~16 million addresses, a Class B held ~65 thousand, a Class C held 254. If you needed 300 machines, a Class C was too small and a Class B wasted 65,000 addresses. That waste, multiplied across the planet, was burning the address space alive.

Subnetting is the act of slicing one block into right-sized pieces by moving the boundary between "which network" and "which host" wherever you want it — not just at the three legacy sizes. The same mechanism also lets routers aggregate many small networks back into one line in a routing table (summarization). Slice down, summarize up: it's the same knob turned in two directions.

Mental modelEvery address is a street + house number. Subnetting decides how many bits name the street vs. the house. More street bits → more streets, fewer houses each. That single trade-off is the whole topic.

01Anatomy of an IPv4 address

32 bits, written as four 8-bit groups (octets) in decimal, separated by dots. Each octet ranges 0–255, because 8 bits can represent 256 values.

1128
064
132
016
18
14
02
01
.
0128
064
032
116
08
04
02
01
.
0128
064
132
016
18
14
02
11
.
0128
064
032
016
08
04
02
11

The grid above is 172.16.45.1. Read each octet by adding the place-values under the 1s: 128+32+8+4 = 172, then 16, then 32+8+4+1 = 45, then 1. The first three octets are coloured as network here, the last as host — but where that colour boundary sits is exactly what the mask decides, which is the rest of this guide.

02The binary you must own

You don't need to convert big numbers in binary all day. You need two small skills cold: the eight place-values of an octet, and the eight "mask values". Burn these in.

The eight bit place-values

bit position12345678
place-value1286432168421
power of 22⁷2⁶2⁵2⁴2⁰

To turn an octet into decimal, add the place-values wherever there's a 1. 11000000 = 128+64 = 192. To go the other way, greedily subtract from 128 down: 200 → 128 (leaves 72) → 64 (leaves 8) → 8 (leaves 0) so 200 = 11001000.

The eight mask values (memorize this row)

A mask octet is always a run of 1s from the left, then 0s — never mixed. So only nine values are legal per octet. These are the only ones you'll ever see:

# of 1-bitsbinarydecimalblock size (256−dec)
0000000000256
110000000128128
21100000019264
31110000022432
41111000024016
5111110002488
6111111002524
7111111102542
8111111112551
The single most useful fact in subnettingBlock size = 256 − mask value. The 192 mask has block size 64. The 224 mask has block size 32. This "block size" (a.k.a. the magic number) is what makes the whole thing doable in your head. We'll use it constantly from §07 on.

03Network vs host: the only split that matters

Take the 32 bits and draw one vertical line through them. Everything left of the line is the network ID — shared by every device on that wire. Everything right of the line is the host ID — unique to each device. Move the line right, you get more host bits (bigger subnet, fewer subnets). Move it left, fewer host bits (smaller subnets, more of them).

·
·
·
·
·
·
·
·
.
·
·
·
·
·
·
·
·
.
·
·
·
·
·
·
·
·
.
·
·
·
·
·
·
·
·

Above the line sits after 18 network bits — a /18. There are 14 host bits left, so this subnet holds 2¹⁴ = 16384 addresses. Two of those are reserved (next section), leaving 16382 usable hosts.

Two addresses are never yours to assignThe all-host-bits-0 address is the network address (the name of the wire). The all-host-bits-1 address is the broadcast (everyone on the wire). That's why usable hosts = 2ⁿ − 2, where n = host bits.

04The subnet mask is just where the line is

The mask is a second 32-bit number whose 1s mark the network portion and 0s mark the host portion. A /24 means 24 ones then 8 zeros:

1
1
1
1
1
1
1
1
.
1
1
1
1
1
1
1
1
.
1
1
1
1
1
1
1
1
.
0
0
0
0
0
0
0
0

Three octets of all-ones (255) and one of all-zeros (0) → 255.255.255.0. The router computes the network ID by a bitwise AND of the address and the mask: wherever the mask is 1 the address bit passes through; wherever the mask is 0 the result is forced to 0. That AND is the only arithmetic a router actually does here — everything in this guide is just doing it faster than the long way.

05CIDR & the master table

CIDR (Classless Inter-Domain Routing) is just the /n shorthand: n = number of network bits. 10.0.0.0/8, 192.168.1.0/24, 172.16.4.0/30. It killed the rigid classes for good. This is the one table worth half-memorizing — but really you only need the pattern, because §07 lets you regenerate any row on demand.

CIDRmaskhost bitstotal addrsusable hostsblock size*
/8255.0.0.02416,777,21616,777,2141 (oct 1)
/16255.255.0.01665,53665,5341 (oct 2)
/20255.255.240.0124,0964,09416 (oct 3)
/22255.255.252.0101,0241,0224 (oct 3)
/23255.255.254.095125102 (oct 3)
/24255.255.255.082562541 (oct 4)
/25255.255.255.1287128126128 (oct 4)
/26255.255.255.1926646264 (oct 4)
/27255.255.255.2245323032 (oct 4)
/28255.255.255.2404161416 (oct 4)
/29255.255.255.2483868 (oct 4)
/30255.255.255.2522424 (oct 4)
/31255.255.255.254122†2 (oct 4)
/32255.255.255.255011†1 (oct 4)

* "block size" = how much the network address jumps each step, in the octet where the mask isn't 0 or 255. † /31 and /32 are special-cased — see §12.

Read the pattern, not the rowsEvery drop of one in the prefix doubles the hosts and halves the number of subnets. /26/25 doubles 62→126 usable. That doubling is the entire table.

06The four numbers you compute for any subnet

Given any address with a prefix, you describe its subnet with four facts. Everything else is derived from these.

#namewhat it ishow to get it
1Network addressname of the wire; host bits all 0round the address down to a block-size multiple
2Broadcast addressreaches everyone; host bits all 1next network − 1
3First usable hostfirst assignable IPnetwork + 1
4Last usable hostlast assignable IPbroadcast − 1

Host count = 2^(host bits) − 2. Once you can place the network and broadcast, the two host ends are just ±1 from them. So the real skill is step 1 — and that's what the magic-number method gives you instantly.

07The magic-number method (the expert shortcut)

This is the technique that lets people answer subnet questions out loud. Four steps, no binary.

  • 1. Find the interesting octet. Write the mask. The "interesting" octet is the one that's neither 255 nor 0. (For a /26, mask 255.255.255.192 → 4th octet.)
  • 2. Block size = 256 − that octet's mask value. (256 − 192 = 64.)
  • 3. Network = round the address's interesting-octet down to a multiple of the block size. The multiples are your subnet boundaries: 0, block, 2×block, …
  • 4. Broadcast = network's interesting octet + block size − 1. Host range sits between, ±1.
# Given: 172.16.77.200/26 mask = 255.255.255.192 → interesting octet = 4th block size = 256 − 192 = 64 multiples = 0, 64, 128, 192, (256) 200 lands in → 192 block network = 172.16.77.192 broadcast = 172.16.77.(192+64−1) = 172.16.77.255 host range = 172.16.77.193 → 172.16.77.254 usable hosts = 2^6 − 2 = 62
Say it as one sentence"/26 is block-64 in the last octet; 200 rounds down to 192; so .192 network, .255 broadcast, .193–.254 hosts, 62 of them." That sentence is fluency. Drill it until it's reflex.

08Worked examples (watch the octet move)

Example A — boundary in the 3rd octet

# 10.5.20.0/19 mask = 255.255.224.0 → interesting octet = 3rd block size = 256 − 224 = 32 multiples = 0, 32... ; 20 rounds down to 0 network = 10.5.0.0 broadcast = 10.5.31.255 (0+32−1 = 31 in oct3, then .255) hosts = 10.5.0.1 → 10.5.31.254 (2^13 − 2 = 8190)

When the boundary is in the 3rd octet, the host portion spills across octets 3 and 4. The broadcast's 3rd octet is one below the next block (31), and the 4th octet goes all the way to 255. Everything to the right of the boundary is host space.

Example B — the trap of a non-zero 3rd octet

# 172.16.77.200/19 (same prefix, busier address) block size = 32 (oct 3) multiples = 0,32,64,64... ; 77 rounds down to 64 network = 172.16.64.0 broadcast = 172.16.95.255 (64+32−1 = 95) hosts = 172.16.64.1 → 172.16.95.254

Notice the 4th octet (200) was a distraction: the boundary is in octet 3, so octet 4 is pure host and doesn't affect the network ID at all. Always round in the interesting octet, and zero everything to its right.

Example C — a point-to-point link

# 192.168.1.6/30 block size = 256 − 252 = 4 (oct 4) multiples = 0,4,4,8... ; 6 rounds down to 4 network = 192.168.1.4 broadcast = 192.168.1.7 hosts = .5 and .6 (exactly 2 usable — perfect for a router-to-router link)

09Borrowing bits: turning one network into many

"Subnetting" in the verb sense means: take a block, steal some host bits to act as a subnet number, and split it into equal pieces. Each borrowed bit doubles the count of subnets and halves the hosts each.

  • Subnets created = 2^(bits borrowed)
  • Hosts per subnet = 2^(host bits remaining) − 2

Borrow 3 bits from a /24 (→ /27). The grid: 24 fixed network bits, 3 purple borrowed bits, 5 host bits.

·
·
·
·
·
·
·
·
.
·
·
·
·
·
·
·
·
.
·
·
·
·
·
·
·
·
.
·
·
·
·
·
·
·
·

3 borrowed → 2³ = 8 subnets. 5 host bits → 2⁵ − 2 = 30 hosts each. Block size in the last octet = 256 − 224 = 32, so the eight subnets of 192.168.1.0/24 are:

subnetnetworkfirst hostlast hostbroadcast
0192.168.1.0.1.30.31
1192.168.1.32.33.62.63
2192.168.1.64.65.94.95
3192.168.1.96.97.126.127
4192.168.1.128.129.158.159
5192.168.1.160.161.190.191
6192.168.1.192.193.222.223
7192.168.1.224.225.254.255

See the rhythm: each network jumps by the block size (32), and each broadcast is one below the next network. That's the entire table generated from one number.

10VLSM — sizing each subnet to its real need

Fixed-size subnetting wastes space when your segments differ wildly in size. Variable Length Subnet Masking lets each subnet pick its own prefix. The discipline: allocate largest-first, always carving the next block immediately after the previous one.

Why largest-firstIf you place a small subnet in the middle of the range first, you fragment it and may not be able to fit a large one later. Sort descending by host need, then walk straight up the address space.

Brief: split 192.168.10.0/24 for segments needing 100, 50, 25, and 2 hosts (two point-to-point links).

# round each need UP to a power of two, then add the two reserved need 100 → /25 (126 usable) → 192.168.10.0/25 .0 – .127 need 50 → /26 ( 62 usable) → 192.168.10.128/26 .128 – .191 need 25 → /27 ( 30 usable) → 192.168.10.192/27 .192 – .223 need 2 → /30 ( 2 usable) → 192.168.10.224/30 .224 – .227 need 2 → /30 ( 2 usable) → 192.168.10.228/30 .228 – .231 .232 – .255 still free for growth

Each block starts exactly where the last one ended, and no two overlap. The leftover .232–.255 is real, reclaimable space — the payoff of VLSM over fixed sizing.

11Summarization — the same knob, turned up

Routers don't want 50 routes when one will do. Summarization (supernetting) collapses several adjacent networks into one advertisement by moving the boundary left until a single prefix covers them all. The trick: find the longest prefix where all the networks share identical bits.

Collapse these four:

192.168.4.0/24 → oct3 = 00000100 192.168.5.0/24 → oct3 = 00000101 192.168.6.0/24 → oct3 = 00000110 192.168.7.0/24 → oct3 = 00000111 ^^^^^^‾‾ first 6 bits identical, last 2 vary summary = 192.168.4.0/22 (24 − 2 varying bits = /22)

The four /24s (4,5,6,7) differ only in their lowest two bits, so a /22 covers all of them and nothing extra. One route instead of four. This only works on a properly aligned, contiguous block — 4,5,6,7 summarize cleanly; 5,6,7,8 do not, because they straddle a boundary.

12Private & special-case ranges

RFC 1918 private space (memorize)

rangeCIDRsizetypical use
10.0.0.0 – 10.255.255.25510.0.0.0/8~16.7Mbig cloud VNets, k8s
172.16.0.0 – 172.31.255.255172.16.0.0/12~1Mmid-size estates
192.168.0.0 – 192.168.255.255192.168.0.0/1665Khomes, small labs
Common gotchaThe middle one is 172.16.0.0/12, not /16. It spans 172.16.x.x through 172.31.x.x — sixteen Class-B-sized blocks. People misread this constantly.

Other ranges worth knowing

  • 127.0.0.0/8 — loopback (127.0.0.1 = localhost).
  • 169.254.0.0/16 — link-local / APIPA. If a host shows this, DHCP failed.
  • 100.64.0.0/10 — carrier-grade NAT (and Tailscale's default range).
  • 224.0.0.0/4 — multicast.

The /31 and /32 exceptions

By the 2ⁿ−2 rule a /31 would have zero usable hosts. RFC 3021 special-cases it: on a point-to-point link a /31 gives you both addresses as usable hosts (no network/broadcast waste). A /32 is a single host — used for loopbacks, host routes, and matching one exact IP in a firewall or route table.

13Where this actually bites you in prod

This isn't an exam topic for you — it's the thing behind half your incidents. A few translations into your world:

  • VNet / subnet sizing. A VNet is just a CIDR (say 10.20.0.0/16); each subnet carves a slice. Size a subnet too tight and you run out of IPs mid-scale-out — the node pool can't get addresses and pods go Pending.
  • AKS / pod CIDRs. In Azure CNI every pod consumes a real subnet IP, so a /24 node subnet (254 usable) can be exhausted by a couple of busy nodes. The "careful IP planning" you did during the AGIC pod-IP-update incident is exactly §10 VLSM thinking — carving non-overlapping subnets sized to real pod density.
  • App Gateway subnets. AGIC wants headroom in its dedicated subnet; an undersized one is why pod-IP updates stall. Knowing block size at a glance tells you instantly whether a /27 can survive a scale event.
  • Route tables & NSGs. A rule scoped to 10.20.0.0/22 covers four /24s — that's §11 summarization. Get the prefix wrong and you either leak access or black-hole traffic.
  • Peering overlap. Two VNets that both use 10.0.0.0/16 can't peer. Disciplined allocation from one parent block is what prevents the collision.

14Graded drills

Do these on paper, out loud, then reveal. The goal isn't the answer — it's the sentence you say to get there. If you can't narrate the block-size step, you're not fluent yet.

EASYFor 192.168.4.77/26: network, broadcast, host range, usable count?

Mask …255.192 → block 64 in oct 4. Multiples 0/64/128/192; 77 rounds down to 64.

Broadcast = 64 + 64 − 1 = 127.

net 192.168.4.64 · bcast 192.168.4.127 · hosts .65–.126 · 62 usable
EASYHow many usable hosts in a /29? And what's its mask?

32 − 29 = 3 host bits → 2³ − 2 = 6. Mask: 5 ones in the last octet = 248.

6 usable · mask 255.255.255.248 · block size 8
MEDIUMFor 10.34.150.200/21: network & broadcast?

Mask 255.255.248.0 → interesting octet 3, block 256 − 248 = 8. Multiples in oct 3: 0,8,…,144,152; 150 rounds down to 144 (next is 152).

Broadcast oct 3 = 144 + 8 − 1 = 151, oct 4 = 255.

net 10.34.144.0 · bcast 10.34.151.255 · hosts 10.34.144.1 – 10.34.151.254
MEDIUMIs 172.16.93.40/26 in the same subnet as 172.16.93.70/26?

Block 64 in oct 4. 40 rounds to 0 (range .0–.63). 70 rounds to 64 (range .64–.127). Different blocks.

No — .40 is in subnet .0/26, .70 is in subnet .64/26
HARDVLSM: carve 10.10.0.0/24 for needs of 60, 30, 12, and 2 hosts.

Round each up: 60→/26 (62), 30→/27 (30), 12→/28 (14), 2→/30 (2). Allocate largest-first, contiguously:

60 → 10.10.0.0/26 .0 – .63 30 → 10.10.0.64/27 .64 – .95 12 → 10.10.0.96/28 .96 – .111 2 → 10.10.0.112/30 .112 – .115 .116 – .255 free
No overlaps; 140 addresses still free for growth
HARDSummarize 10.8.16.0/24, 10.8.17.0/24, 10.8.18.0/24, 10.8.19.0/24 into one route.

Octet 3 values 16–19 in binary: 00010000 / 00010001 / 00010010 / 00010011. First 6 bits identical, last 2 vary → drop 2 bits from /24.

10.8.16.0/22 (covers .16 through .19, nothing extra)
HARDTrap check: can you summarize 10.8.17.0/24 … 10.8.20.0/24 (17,18,19,20) into one clean route?

No. 17–20 straddle the /22 boundary: 16–19 form one aligned /22, but 20 starts the next. A single prefix that covers 17–20 (a /21 = 16–23) would also pull in 16, 21, 22, 23 — addresses you didn't intend. Summarization needs a power-of-two-aligned, contiguous set.

Not summarizable into one exact route — alignment fails

15Live calculator — check your own work

Use this after you've worked a problem by hand, never before. The point is to verify the sentence in your head, not replace it.

16Cheat sheet — the whole thing on one card

you want…do this
usable hosts2^(32 − prefix) − 2
host bits32 − prefix
block size (magic number)256 − (mask value of interesting octet)
network addressround interesting octet DOWN to a block multiple; zero everything right
broadcastnetwork's interesting octet + block − 1; 255 everything right
first / last hostnetwork + 1 / broadcast − 1
# subnets when borrowing b bits2^b
VLSM rulesort needs descending, round up to powers of 2, allocate contiguously
summarizationfind longest prefix where all networks share identical bits
mask octet values128·192·224·240·248·252·254·255
If you remember one thingblock size = 256 − mask, and the network address is the multiple of the block size at or below your octet. Everything else falls out of that.

Now go drill §14 until the sentences come without effort, then test yourself against §15. That's the path from "I can derive it slowly" to "I just know."