CIDR Cheatsheet - Subnet Mask & IP Address Reference

The trouble with CIDR arithmetic is that mistakes do not raise errors. A /23 written as /24 in a firewall rule lets the service start normally while quietly exposing extra addresses; shrinking a /8 to /16 stays hidden until capacity runs out a quarter later. So this sheet exists to make the mental arithmetic explicit: host bits equal 32 minus the prefix, usable addresses are two to the host-bit count minus two for the network and broadcast addresses, and /31 is the exception with no broadcast address so all four are usable. It is grouped into a subnet mask table, common subnet sizes, private ranges, special-purpose addresses, and calculation tools with worked examples. Reach for it when allocating a VPC range, reconciling NAT and security group allow-lists, deciding between /24 and /16, or reading an unfamiliar range and needing to know instantly whether it is private. The special ranges double as diagnostics: a 169.254 address means DHCP or the cloud metadata service is unreachable, while 127 in a config means loopback was written into an externally visible field.

Reference·34 commands·Last updated 2026-07-21
cidrNetworkingipSubnets

CIDR Notation Basics 5

192.168.1.0/24
Standard CIDR notation: IP address / prefix length
IP/prefix
The prefix is the number of network bits (0-32)
/24
The first 24 bits are network bits, the last 8 are host bits
host bits = 32 - prefix
Host bits = 32 - prefix, the basis for counting total addresses
subnet mask
Derived from the prefix by setting every network bit to 1

Subnet Mask Reference 6

/32 = 255.255.255.255 = 1 IP
A single host, the host route
/24 = 255.255.255.0 = 256 IPs
Standard Class C subnet
/23 = 255.255.254.0 = 512 IPs
Supernet formed by merging two /24s
/16 = 255.255.0.0 = 65,536 IPs
Standard Class B subnet
/8 = 255.0.0.0 = 16,777,216 IPs
Standard Class A subnet
/0 = 0.0.0.0 = all IPs
Default route, the entire address space

Common Subnet Sizes 7

/30 = 4 IPs (2 usable)
Point-to-point link, the most address-efficient
/29 = 8 IPs (6 usable)
Small subnet
/28 = 16 IPs (14 usable)
Common size for VLANs
/27 = 32 IPs (30 usable)
Medium subnet
/26 = 64 IPs (62 usable)
A fairly large subnet
/25 = 128 IPs (126 usable)
Large subnet
/24 = 256 IPs (254 usable)
The most common LAN size

Private IP Ranges 5

10.0.0.0/8
Private Class A range, 10.0.0.0 through 10.255.255.255
172.16.0.0/12
Private Class B range, 172.16.0.0 through 172.31.255.255
192.168.0.0/16
Private Class C range, 192.168.0.0 through 192.168.255.255
100.64.0.0/10
Reserved for carrier-grade NAT (CGN)
169.254.0.0/16
Link-local addresses, self-assigned via APIPA

Special-purpose Addresses 5

0.0.0.0/0
Default route, matches every IP address
127.0.0.0/8
Loopback addresses on the local host
224.0.0.0/4
Multicast addresses
240.0.0.0/4
Reserved Class E addresses, unassigned
255.255.255.255
Limited broadcast address, every host on this segment

Calculation Tools & Examples 6

ipcalc 192.168.1.0/24
Shows subnet details on Linux
sipcalc 10.0.0.0/16
A more verbose CIDR calculator
ipaddress.ip_network("192.168.1.0/28")
Python standard library ipaddress module for CIDR maths
network address = IP & subnet mask
Network address = IP AND subnet mask, a bitwise AND
broadcast address = network address | ~mask
Broadcast address = network address OR NOT mask, all host bits set to 1
usable IPs = 2^(32-prefix) - 2
Usable IPs = 2^(32-prefix) - 2, minus the network and broadcast addresses

Command Examples

Compute mask, network, broadcast and usable count in one pass

node -e " function calc(cidr) { const [ip, p] = cidr.split('/') const bits = p | 0 const ipn = ip.split('.').map(Number).reduce((a, b) => ((a << 8) + b) >>> 0, 0) const m = (0xFFFFFFFF << (32 - bits)) >>> 0 const net = ipn & m const bc = (net | (~m >>> 0)) >>> 0 const size = 2 ** (32 - bits) const f = (n) => [24, 16, 8, 0].map((s) => (n >>> s) & 255).join('.') console.log(cidr, 'mask', f(m), 'net', f(net), 'bcast', f(bc), 'total', size, 'usable', bits >= 31 ? size : size - 2) } ;['10.0.0.0/8', '172.16.0.0/12', '100.64.0.0/10', '0.0.0.0/0'].forEach(calc) "

The script encodes the two formulas on the sheet directly: the mask is all 1s left-shifted, the network address is a bitwise AND of IP and mask, the broadcast address is network OR the inverted mask, and the usable count is 2^hostbits minus 2, with a special case at /31 and above so nothing is subtracted. The /0 row shows total 4294967296 and a mask printed as 255.255.255.255, which is just what the bitwise inversion yields — not a typo.

Output

10.0.0.0/8 mask 255.0.0.0 net 10.0.0.0 bcast 10.255.255.255 total 16777216 usable 16777214
172.16.0.0/12 mask 255.240.0.0 net 172.16.0.0 bcast 172.31.255.255 total 1048576 usable 1048574
100.64.0.0/10 mask 255.192.0.0 net 100.64.0.0 bcast 100.127.255.255 total 4194304 usable 4194302
0.0.0.0/0 mask 255.255.255.255 net 0.0.0.0 bcast 0.0.0.0 total 4294967296 usable 4294967294

Read the network, mask, broadcast and usable count of a /28 from the standard library

python -c " from ipaddress import ip_network n = ip_network('192.168.1.0/28') print(n.network_address, n.netmask, n.broadcast_address, n.num_addresses, n.num_addresses - 2) "

This sheet marks /28 as the common VLAN size: 16 addresses, 14 usable. In a validation script, ip_network replaces hand arithmetic and returns all three values at once — the network address to skip during assignment, the broadcast address never to hand to a host, and the usable count — so nobody hands out all 16. Passing strict=False also tolerates being given a host address inside the network rather than the network address itself.

Output

192.168.1.0 255.255.255.240 192.168.1.15 16 14

Compare hosts() for /31 and /30 to see the point-to-point exception

python -c " from ipaddress import ip_network print(list(ip_network('10.0.0.0/31').hosts())) print(list(ip_network('10.0.0.0/30').hosts())) "

Both addresses of the /31 show up as hosts because a point-to-point link has no broadcast address at all, while the /30 drops the network and broadcast addresses and keeps only the middle two. When reviewing a submitted network plan, misapplying the minus-2 rule to a /31 and concluding it has zero usable addresses is the most common review error, and this side-by-side makes it obvious at a glance.

Output

[IPv4Address('10.0.0.0'), IPv4Address('10.0.0.1')]
[IPv4Address('10.0.0.1'), IPv4Address('10.0.0.2')]

Decide which of a batch of addresses fall inside private ranges

python -c " from ipaddress import ip_address for s in ['10.1.2.3', '172.32.0.1', '192.168.5.5', '100.64.0.1', '169.254.1.1', '127.0.0.1']: a = ip_address(s) print(s, a.is_private) "

The two False values deserve attention: 172.32.0.1 sits just above the 172.16.0.0/12 boundary and 100.64.0.1 belongs to the carrier-grade NAT range 100.64.0.0/10. The standard library counts neither as an RFC1918 private address, yet cloud networks usually still route them internally, so reachability needs a separate judgement. 169.254 and 127 come back True because they genuinely do not come from the public internet, but seeing those two True in an outward-facing config is still a mistake.

Output

10.1.2.3 True
172.32.0.1 False
192.168.5.5 True
100.64.0.1 False
169.254.1.1 True
127.0.0.1 True

Common Pitfalls

  • A wrong CIDR does not raise an error. Entering /23 where /24 was meant in a firewall rule leaves the service starting normally while the extra addresses silently stay reachable inside the network; only a per-rule review of prefix and address count catches it.
  • The upper bound of 172.16.0.0/12 is 172.31.255.255, and 172.32.0.0 is already outside it. Allowing traffic on the assumption that anything starting with 172 is internal exposes a public address.
  • 100.64.0.0/10 is the carrier-grade NAT range. The standard library does not class it as private, yet cloud networks often route it internally, so pointing a public service straight at that range usually fails.
  • Usable = 2^(32-prefix) - 2 only holds for ordinary sizes such as /30 down to /24. A /31 has no broadcast address, and applying the minus 2 there yields zero usable addresses.
  • 240.0.0.0/4 is reserved Class E, 0.0.0.0/0 is the default route, 127.0.0.0/8 is loopback and 169.254.0.0/16 is link-local. Seeing any of them in an outward-facing address or a security-group allow-list is a misconfiguration, not a special case to wave through.

Tips

  • Usable IPs = 2^(32-prefix) - 2 (minus network and broadcast addresses).
  • Docker's default bridge is 172.17.0.0/16; Kubernetes Pod CIDR is often 10.244.0.0/16.
  • /24 is the most common subnet, good for small LANs.
  • ipcalc or sipcalc quickly compute CIDR info from the CLI.
  • /31 (2 IPs) is for point-to-point links (RFC 3021) and needs no broadcast address.

FAQ

Given 192.168.1.0/24, how do I get the usable host count immediately?

Two steps: host bits = 32 - 24 = 8, total addresses = 2^8 = 256. Subtract the network address 192.168.1.0 and the broadcast address 192.168.1.255 and you get 254 usable. Do not do this arithmetic by hand in a script: use the standard library with ipaddress.ip_network("192.168.1.0/24"), read num_addresses for the total and num_addresses - 2 for the usable count. Printing both keeps you from handing out the network address by mistake.

Why does a /31 have usable addresses instead of zero?

A /31 is the dedicated point-to-point size. A full-length prefix yields two addresses, and the traditional rule would spend one on the network address and one on the broadcast address, leaving none usable. RFC 3021 removes the broadcast address from /31, so both addresses are usable. That is why "usable = 2^(32-prefix) - 2" needs a special case at /31: ip_network("10.0.0.0/31").hosts() in Python lists both 10.0.0.0 and 10.0.0.1. Compare a /30, which follows the ordinary shape: four addresses, two usable.

How do I tell quickly whether an unfamiliar network is private?

Check the three private ranges on this sheet: 10.0.0.0/8 spans 10.0.0.0 to 10.255.255.255; 172.16.0.0/12 spans 172.16.0.0 to 172.31.255.255, note it ends at 172.31 so 172.32 is already outside; 192.168.0.0/16 covers all of 192.168.x.x. There are also 100.64.0.0/10, the carrier-grade NAT range, and 169.254.0.0/16, link-local. Neither is an RFC1918 private range, yet both are usually treated as internal on cloud networks. Do not judge by eye: use ip_address(s).is_private or a bitwise comparison against the network address.

Why can the 1s and 0s in a subnet mask not be arranged freely?

A subnet mask is all 1s for the network bits followed by all 0s for the host bits, network portion first, and that order is fixed by the convention linking CIDR to the integer form of an IP address. Prefix 16 yields 255.255.0.0, prefix 12 yields 255.240.0.0: bits fill from the most significant end and stop at the prefix length, so the third byte of a /12 is 11110000, that is 240. A mask written as 0.0.255.255 has the same numeric value but every bitwise tool and routing protocol reads the opposite network address, so the configuration is certainly wrong.

What does it usually mean when 169.254 or 127 appears in a configuration?

Both point back at the machine, but for different reasons. 169.254.0.0/16 is link-local, typically a self-assigned fallback after DHCP got no answer or a cloud metadata service (commonly 169.254.169.254) is unreachable; it should never be the destination written in a config. 127.0.0.0/8 is loopback, meaning a loopback address was mistaken for an external one and put into a whitelist or a listen address, so outbound calls bounce straight back. Neither is a legitimate special case here: fix the DHCP config or the address field.

Official References

Each command links to its official documentation below, so you can verify the latest usage and read deeper.

Maintained by LaoHand

Publicly updated on Jul 21, 2026, continuously proofread against official docs.

Contact Us

Wrong command or description? Send us corrections, business inquiries or product feedback by email.

Contact Us